diff --git a/files/assets/css/main.css b/files/assets/css/main.css index 098b4ccd1..324d6a32a 100644 --- a/files/assets/css/main.css +++ b/files/assets/css/main.css @@ -4901,7 +4901,6 @@ video { color: var(--primary); display: inline-block; cursor: pointer; - height: 100%; width: 10px; content: "\f056"; position: static; @@ -5022,7 +5021,7 @@ code { .noshadow { box-shadow: none !important; } -[role="button"], :not(textarea)[onclick], th { +[role="button"], :not(textarea)[onclick], :not(textarea)[data-onclick], th { cursor: pointer !important; } diff --git a/files/assets/event/css/blizzard.css b/files/assets/event/css/blizzard.css index 9584995aa..78690a5af 100644 --- a/files/assets/event/css/blizzard.css +++ b/files/assets/event/css/blizzard.css @@ -247,7 +247,7 @@ body { background-color: #235E6F; } - #snow { + #snow:not([data-nonce]) { height: 100%; color: #FFF; display: block; diff --git a/files/assets/js/award_modal.js b/files/assets/js/award_modal.js index daf63f8d1..a45f5b27f 100644 --- a/files/assets/js/award_modal.js +++ b/files/assets/js/award_modal.js @@ -165,3 +165,11 @@ function giveaward(t) { } ); } + +const data_url = document.querySelectorAll('[data-url]'); +for (const element of data_url) { + if (element.dataset.nonce != nonce) continue + element.onclick = () => { + document.getElementById('giveaward').dataset.action = element.dataset.url + }; +} diff --git a/files/assets/js/bottom.js b/files/assets/js/bottom.js new file mode 100644 index 000000000..cccca24aa --- /dev/null +++ b/files/assets/js/bottom.js @@ -0,0 +1,105 @@ +function execute(element, attr) { + if (element.dataset.nonce != nonce) return + const funcs = element.getAttribute(`data-${attr}`).split(';') + for (const func of funcs) { + if (func) { + const split = func.split('(') + const name = split[0] + const args = split[1].replace(/[' )]/g, "").split(',') + if (args[0] == 'this') args[0] = element + try { + window[name](...args); + } + catch (e) { + console.log(name) + } + } + } +} + +document.addEventListener("click", function(e){ + const element = e.target + if (element instanceof HTMLImageElement && element.alt.startsWith('![](')) + expandImage() + else if (element.tagName == "TH") + sort_table(element) + else if (element.classList.contains('giphy')) + insertGIF(e.target.src); + else if (element.classList.contains('gif-cat-overlay')) + searchGifs(e.target.firstElementChild.innerHTML); + else if (element.dataset.onclick) + execute(element, 'onclick'); + else if (element.dataset.href) + location.href = element.dataset.href; + + if (element.dataset.toggleelement) { + document.getElementById(element.dataset.toggleelement).classList.toggle(element.dataset.toggleattr) + } +}); + +const oninput = document.querySelectorAll('[data-oninput]'); +for (const element of oninput) { + element.oninput = ()=>{execute(element, 'oninput')}; +} + +const onmouseover = document.querySelectorAll('[data-onmouseover]'); +for (const element of onmouseover) { + element.onmouseover = ()=>{execute(element, 'onmouseover')}; +} + +const onchange = document.querySelectorAll('[data-onchange]'); +for (const element of onchange) { + element.onchange = ()=>{execute(element, 'onchange')}; +} + +const onsubmit = document.querySelectorAll('[data-onsubmit]'); +for (const element of onsubmit) { + element.onsubmit = ()=>{execute(element, 'onsubmit')}; +} + +const onfocus = document.querySelectorAll('[data-onfocus]'); +for (const element of onfocus) { + element.onfocus = ()=>{execute(element, 'onfocus')}; +} + +const click_submit = document.querySelectorAll('[click_submit]'); +for (const element of click_submit) { + if (element.dataset.nonce != nonce) continue + element.onclick = () => {element.form.submit()}; +} + +const change_submit = document.querySelectorAll('[change_submit]'); +for (const element of change_submit) { + if (element.dataset.nonce != nonce) continue + element.onchange = () => {element.form.submit()}; +} + +const undisableelement = document.querySelectorAll('[undisableelement]'); +for (const element of undisableelement) { + if (element.dataset.nonce != nonce) continue + element.oninput = () => { + document.getElementById(element.dataset.undisableelement).disabled = false; + }; +} + +// data-on[^"]*?="[^"]+?\.(?![%a-z._ ]+?\}) + +const setting_switchs = document.getElementsByClassName('setting_switch'); +for (const element of setting_switchs) { + if (element.dataset.nonce != nonce) continue + element.onchange = () => { + postToastSwitch(this,`/settings/${element.name}?poor=${element.checked}`); + }; +} + +const setting_reloads = document.getElementsByClassName('setting_reload'); +for (const element of setting_reloads) { + if (element.dataset.nonce != nonce) continue + element.onchange = () => { + postToastReload(this,`/settings/${element.name}?poor=${element.checked}`); + }; +} + +const reload_page = document.getElementById('reload-page') +if (reload_page) + reload_page.onclick = ()=>{location.reload()}; diff --git a/files/assets/js/comments.js b/files/assets/js/comments.js index 8472ab60c..e5018b8a7 100644 --- a/files/assets/js/comments.js +++ b/files/assets/js/comments.js @@ -17,7 +17,8 @@ function expandMarkdown(id,type) { } }; -function collapse_comment(id, element) { +function collapse_comment(id) { + const element = document.getElementById(`comment-${id}`) const closed = element.classList.toggle("collapsed") const top = element.getBoundingClientRect().y @@ -38,4 +39,4 @@ function collapse_comment(id, element) { const ta = document.getElementById('markdown-'+id); if (!ta.classList.contains('d-none')) expandMarkdown(id,'c') -}; \ No newline at end of file +}; diff --git a/files/assets/js/core.js b/files/assets/js/core.js index 79c861bf3..13d31a4b7 100644 --- a/files/assets/js/core.js +++ b/files/assets/js/core.js @@ -334,7 +334,7 @@ function areyousure(t) { else t.innerHTML = t.innerHTML.replace(t.textContent, 'Are you sure?') - t.setAttribute("onclick", t.dataset.click); + t.setAttribute("data-onclick", t.dataset.areyousure); if (t.dataset.dismiss) t.setAttribute("data-bs-dismiss", t.dataset.dismiss); @@ -436,19 +436,6 @@ function sort_table(t) { } } - -document.addEventListener("click", function(e){ - const element = e.target - if (element instanceof HTMLImageElement && element.alt.startsWith('![](')) - expandImage() - else if (element.tagName == "TH") - sort_table(element) - else if (element.classList.contains('giphy')) - insertGIF(e.target.src); - else if (element.classList.contains('gif-cat-overlay')) - searchGifs(e.target.firstElementChild.innerHTML); -}); - if (window.matchMedia('(display-mode: minimal-ui)')['matches']) { const links = document.querySelectorAll('a[data-target="t"]'); for (const link of links) { diff --git a/files/assets/js/emoji_modal.js b/files/assets/js/emoji_modal.js index 359361a6c..e5a01ee51 100644 --- a/files/assets/js/emoji_modal.js +++ b/files/assets/js/emoji_modal.js @@ -15,6 +15,7 @@ Copyright (C) 2022 Dr Steven Transmisia, anti-evil engineer, */ // Status +let favs = null; let emojiEngineStarted = false; // DOM stuff @@ -280,9 +281,11 @@ function switchEmojiTab(e) for(const emojiDOM of Object.values(emojiDOMs)) emojiDOM.hidden = true; - for (const emoji of favs) - if(emojiDOMs[emoji] instanceof HTMLElement) - emojiDOMs[emoji].hidden = false; + if (favs) { + for (const emoji of favs) + if(emojiDOMs[emoji] instanceof HTMLElement) + emojiDOMs[emoji].hidden = false; + } return; } @@ -291,6 +294,10 @@ function switchEmojiTab(e) emojiDOM.hidden = emojiDOM.dataset.className !== className; } +for (const emojitab of document.getElementsByClassName('emojitab')) { + emojitab.addEventListener('click', (e)=>{switchEmojiTab(e)}) +} + async function start_search() { emojiSearcher.addQuery(emojiSearchBarDOM.value.trim()); diff --git a/files/assets/js/settings_security.js b/files/assets/js/settings_security.js index 58bff296e..831c846f1 100644 --- a/files/assets/js/settings_security.js +++ b/files/assets/js/settings_security.js @@ -41,3 +41,5 @@ function unblock_user(t, url) { } ); } + +document.getElementById('2faToggle').onchange = () => {twoStepModal.show()} diff --git a/files/assets/js/signup.js b/files/assets/js/signup.js index 72bd14fc6..b6a40088e 100644 --- a/files/assets/js/signup.js +++ b/files/assets/js/signup.js @@ -39,3 +39,8 @@ document.getElementById('username-register').addEventListener('input', function } } }); + + +document.getElementById('email-register').onfocus () => { + if (this.hasAttribute('readonly')) {this.removeAttribute('readonly');this.blur();this.focus()} +} diff --git a/files/assets/js/top.js b/files/assets/js/top.js new file mode 100644 index 000000000..1e5864cbe --- /dev/null +++ b/files/assets/js/top.js @@ -0,0 +1 @@ +const nonce = document.getElementById('gnonce').value diff --git a/files/classes/submission.py b/files/classes/submission.py index 3b5724f31..9915c3007 100644 --- a/files/classes/submission.py +++ b/files/classes/submission.py @@ -297,7 +297,7 @@ class Submission(Base): body += " - WINNER!" if not winner and v and v.admin_level >= PERMS['POST_BETS_DISTRIBUTE']: - body += f'''''' + body += f'''''' body += "" else: input_type = 'radio' if o.exclusive else 'checkbox' diff --git a/files/routes/allroutes.py b/files/routes/allroutes.py index 8c1b3ba12..77d032468 100644 --- a/files/routes/allroutes.py +++ b/files/routes/allroutes.py @@ -56,6 +56,8 @@ def before_request(): limiter.check() g.db = db_session() + g.nonce = secrets.token_urlsafe(31) + CSP = { @@ -75,11 +77,12 @@ CSP = { "style-src": "'self' 'unsafe-inline'", "script-src-elem": "'self' challenges.cloudflare.com", - "script-src-attr": "'unsafe-inline'", - "script-src": "'self' 'unsafe-inline' challenges.cloudflare.com", + "script-src-attr": "'none'", + "script-src": "'self' challenges.cloudflare.com", "media-src": "https:", "img-src": "https: data:", + "frame-src": "challenges.cloudflare.com www.youtube-nocookie.com platform.twitter.com", "connect-src": "'self' tls-use1.fpapi.io api.fpjs.io", @@ -90,6 +93,7 @@ CSP = { if IS_LOCALHOST: CSP["style-src-elem"] += " rdrama.net" CSP["script-src-elem"] += " rdrama.net" + CSP["media-src"] += " http:" CSP["img-src"] += " http:" CSP_str = '' diff --git a/files/templates/admin/admin_home.html b/files/templates/admin/admin_home.html index f12f1810c..1c9c2b24b 100644 --- a/files/templates/admin/admin_home.html +++ b/files/templates/admin/admin_home.html @@ -111,13 +111,13 @@ {% if v.admin_level >= PERMS['SITE_SETTINGS'] %} {% for setting in site_settings.keys() %}
Two accounts controlled by different people should have most uniqueness percentages at or above 70-80%
A sockpuppet account will have its uniqueness percentages significantly lower.
- + {% endif %} {% endif %} {% endif %} diff --git a/files/templates/admin/alts.html b/files/templates/admin/alts.html index 32da5d425..6f0fe17c4 100644 --- a/files/templates/admin/alts.html +++ b/files/templates/admin/alts.html @@ -10,7 +10,7 @@ {% if u %} @@ -40,8 +40,8 @@