diff --git a/src/General/Config.coffee b/src/General/Config.coffee index e99b0d75b..e0ece6756 100755 --- a/src/General/Config.coffee +++ b/src/General/Config.coffee @@ -456,11 +456,6 @@ Config = 'Show notifications on successful post creation or file uploading.' 1 ] - 'Use Recaptcha v1': [ - false - 'Use the old text version of Recaptcha.' - 1 - ] 'Force Noscript Captcha': [ false 'Use the non-Javascript fallback captcha in the QR even if Javascript is enabled.' @@ -485,6 +480,10 @@ Config = true 'Make captcha easier to use, especially with the keyboard.' ] + 'Use Recaptcha v1': [ + false + 'Use the old text version of Recaptcha.' + ] 'Use Recaptcha v2 in Reports': [ false 'Use the image selection captcha in the report window.' diff --git a/src/General/Main.coffee b/src/General/Main.coffee index c68ab3bf9..5d1c068f1 100755 --- a/src/General/Main.coffee +++ b/src/General/Main.coffee @@ -15,14 +15,6 @@ Main = $.ready -> Captcha.fixes.init() return - if location.hostname is 'www.4chan.org' - $.onExists d.documentElement, 'body', false, -> $.addStyle Main.cssWWW - Conf = {'captchaLanguage': Config.captchaLanguage} - $.get Conf, (items) -> - $.extend Conf, items - Captcha.language.fixPage() - return - g.threads = new SimpleDict() g.posts = new SimpleDict() @@ -71,10 +63,13 @@ Main = $.onExists doc, 'body', false, Main.initStyle initFeatures: -> - if location.hostname in ['boards.4chan.org', 'sys.4chan.org'] + if location.hostname in ['boards.4chan.org', 'sys.4chan.org', 'www.4chan.org'] $.globalEval 'document.documentElement.classList.add("js-enabled");' switch location.hostname + when 'www.4chan.org' + Captcha.replace.init() + return when 'a.4cdn.org' return when 'sys.4chan.org' @@ -123,7 +118,10 @@ Main = $.ready Main.initReady initStyle: -> + $.addStyle Main.cssWWW if location.hostname is 'www.4chan.org' + return if !Main.isThisPageLegit() or $.hasClass doc, 'fourchan-x' + # disable the mobile layout $('link[href*=mobile]', d.head)?.disabled = true $.addClass doc, 'fourchan-x', 'seaweedchan' @@ -313,7 +311,7 @@ Main = features: [ ['Polyfill', Polyfill] - ['Captcha Language', Captcha.language] + ['Captcha Replacement', Captcha.replace] ['Redirect', Redirect] ['Header', Header] ['Catalog Links', CatalogLinks] diff --git a/src/Miscellaneous/Report.coffee b/src/Miscellaneous/Report.coffee index 4f1ec3d3c..7ced583f5 100755 --- a/src/Miscellaneous/Report.coffee +++ b/src/Miscellaneous/Report.coffee @@ -3,15 +3,13 @@ Report = init: -> return unless /\bmode=report\b/.test(location.search) and match = location.search.match /\bno=(\d+)/ - Captcha.language.fixPage() + Captcha.replace.init() @postID = +match[1] $.ready @ready ready: -> $.addStyle Report.css Report.archive() if Conf['Archive Report'] - if Conf['Use Recaptcha v2 in Reports'] - Report.captchaV2() if Conf['Use Recaptcha v2 in Reports'] and $.hasClass doc, 'js-enabled' new MutationObserver(-> Report.fit '.gc-bubbleDefault').observe d.body, childList: true @@ -20,19 +18,6 @@ Report = else Report.fit 'body' - captchaV2: -> - return unless old = $.id 'captchaContainerAlt' - container = $.el 'div', - className: 'g-recaptcha' - container.dataset.sitekey = '<%= meta.recaptchaKey %>' - $.replace old, container - url = 'https://www.google.com/recaptcha/api.js' - if lang = Conf['captchaLanguage'].trim() - url += "?hl=#{encodeURIComponent lang}" - script = $.el 'script', - src: url - $.add d.head, script - fit: (selector) -> return unless el = $ selector, doc dy = el.getBoundingClientRect().bottom - doc.clientHeight + 8 diff --git a/src/Posting/Captcha.language.coffee b/src/Posting/Captcha.language.coffee deleted file mode 100644 index bd63efb72..000000000 --- a/src/Posting/Captcha.language.coffee +++ /dev/null @@ -1,17 +0,0 @@ -Captcha.language = - init: -> - return unless Conf['captchaLanguage'].trim() and d.cookie.indexOf('pass_enabled=1') < 0 and !Conf['Hide Original Post Form'] - $.onExists doc, '#captchaFormPart', true, (node) -> - $.onExists node, 'iframe', true, Captcha.language.fixIframe - - fixPage: -> - return unless Conf['captchaLanguage'].trim() and d.cookie.indexOf('pass_enabled=1') < 0 - $.onExists doc, 'iframe', true, Captcha.language.fixIframe - - fixIframe: (el) -> - return unless lang = Conf['captchaLanguage'].trim() - src = if /[?&]hl=/.test el.src - el.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent lang) - else - el.src + "&hl=#{encodeURIComponent lang}" - el.src = src unless el.src is src diff --git a/src/Posting/Captcha.noscript.coffee b/src/Posting/Captcha.noscript.coffee index 6edd8d378..70cef6409 100644 --- a/src/Posting/Captcha.noscript.coffee +++ b/src/Posting/Captcha.noscript.coffee @@ -3,7 +3,7 @@ Captcha.noscript = init: -> return if d.cookie.indexOf('pass_enabled=1') >= 0 - return unless @isEnabled = !!$.id 'g-recaptcha' + return unless @isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt' container = $.el 'div', className: 'captcha-img' diff --git a/src/Posting/Captcha.replace.coffee b/src/Posting/Captcha.replace.coffee new file mode 100644 index 000000000..e118edded --- /dev/null +++ b/src/Posting/Captcha.replace.coffee @@ -0,0 +1,59 @@ +Captcha.replace = + init: -> + return unless d.cookie.indexOf('pass_enabled=1') < 0 + return if location.hostname is 'boards.4chan.org' and Conf['Hide Original Post Form'] + + jsEnabled = $.hasClass doc, 'js-enabled' + + if location.hostname is 'sys.4chan.org' and Conf['Use Recaptcha v2 in Reports'] and jsEnabled + $.ready Captcha.replace.v2 + return + + if Conf['Use Recaptcha v1'] and jsEnabled and location.hostname isnt 'www.4chan.org' + $.ready Captcha.replace.v1 + return + + if Conf['captchaLanguage'].trim() + if location.hostname is 'boards.4chan.org' + $.onExists doc, '#captchaFormPart', true, (node) -> $.onExists node, 'iframe', true, Captcha.replace.iframe + else + $.onExists doc, 'iframe', true, Captcha.replace.iframe + + v1: -> + return unless $.id 'g-recaptcha' + Captcha.v1.replace() + if link = $.id 'form-link' + $.on link, 'click', -> Captcha.v1.create() + else if location.hostname is 'boards.4chan.org' + form = $.id 'postForm' + form.addEventListener 'focus', (-> Captcha.v1.create()), true + form.addEventListener 'blur', -> + $.queueTask -> + unless form.contains(document.activeElement) or $.id('qr')?.contains(document.activeElement) + Captcha.v1.destroy() + , true + else + Captcha.v1.create() + + v2: -> + return unless old = $.id 'captchaContainerAlt' + container = $.el 'div', + className: 'g-recaptcha' + $.extend container.dataset, + sitekey: '<%= meta.recaptchaKey %>' + tabindex: 3 + $.replace old, container + url = 'https://www.google.com/recaptcha/api.js' + if lang = Conf['captchaLanguage'].trim() + url += "?hl=#{encodeURIComponent lang}" + script = $.el 'script', + src: url + $.add d.head, script + + iframe: (el) -> + return unless lang = Conf['captchaLanguage'].trim() + src = if /[?&]hl=/.test el.src + el.src.replace(/([?&]hl=)[^&]*/, '$1' + encodeURIComponent lang) + else + el.src + "&hl=#{encodeURIComponent lang}" + el.src = src unless el.src is src diff --git a/src/Posting/Captcha.v1.coffee b/src/Posting/Captcha.v1.coffee index 2c6752726..a9d488b9a 100644 --- a/src/Posting/Captcha.v1.coffee +++ b/src/Posting/Captcha.v1.coffee @@ -1,15 +1,7 @@ Captcha.v1 = init: -> return if d.cookie.indexOf('pass_enabled=1') >= 0 - return unless @isEnabled = !!$.id 'g-recaptcha' - - script = $.el 'script', - src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' - $.add d.head, script - captchaContainer = $.el 'div', - id: 'captchaContainer' - hidden: true - $.add d.body, captchaContainer + return unless @isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt' imgContainer = $.el 'div', className: 'captcha-img' @@ -38,10 +30,39 @@ Captcha.v1 = QR.captcha.clear() $.sync 'captchas', @sync - new MutationObserver(@afterSetup).observe $.id('captchaContainer'), childList: true - @beforeSetup() @setup() if Conf['Auto-load captcha'] + new MutationObserver(@afterSetup).observe $.id('captchaContainerAlt'), childList: true + @afterSetup() # reCAPTCHA might have loaded before the QR. + + replace: -> + return if @script + unless @script = $ 'script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]', d.head + @script = $.el 'script', + src: '//www.google.com/recaptcha/api/js/recaptcha_ajax.js' + $.add d.head, @script + if old = $.id 'g-recaptcha' + container = $.el 'div', + id: 'captchaContainerAlt' + $.replace old, container + + create: -> + @replace() + $.globalEval ''' + (function() { + var container = document.getElementById("captchaContainerAlt"); + if (container.firstChild) return; + var options = {theme: "clean"}; + if (window.Recaptcha) { + window.Recaptcha.create("<%= meta.recaptchaKey %>", container, options); + } else { + var script = document.head.querySelector('script[src="//www.google.com/recaptcha/api/js/recaptcha_ajax.js"]'); + script.addEventListener('load', function() { + window.Recaptcha.create("<%= meta.recaptchaKey %>", container, options); + }, false); + } + })(); + ''' cb: focus: -> QR.captcha.setup false, true @@ -67,20 +88,7 @@ Captcha.v1 = setup: (focus, force) -> return unless @isEnabled and (@needed() or force) - $.globalEval ''' - (function() { - var captchaContainer = document.getElementById("captchaContainer"); - if (captchaContainer.firstChild) return; - function setup() { - if (window.Recaptcha) { - Recaptcha.create(recaptchaKey, captchaContainer, {theme: "clean"}); - } else { - setTimeout(setup, 25); - } - } - setup(); - })() - ''' + @create() @nodes.input.focus() if focus afterSetup: -> @@ -110,9 +118,9 @@ Captcha.v1 = QR.nodes.el.style.bottom = '0px' destroy: -> - return unless @isEnabled + return unless @script $.globalEval 'Recaptcha.destroy()' - @beforeSetup() + @beforeSetup() if @nodes sync: (captchas=[]) -> QR.captcha.captchas = captchas diff --git a/src/Posting/Captcha.v2.coffee b/src/Posting/Captcha.v2.coffee index c0d819472..10161b56e 100644 --- a/src/Posting/Captcha.v2.coffee +++ b/src/Posting/Captcha.v2.coffee @@ -3,7 +3,7 @@ Captcha.v2 = init: -> return if d.cookie.indexOf('pass_enabled=1') >= 0 - return unless @isEnabled = !!$.id 'g-recaptcha' + return unless @isEnabled = !!$ '#g-recaptcha, #captchaContainerAlt' if @noscript = Conf['Force Noscript Captcha'] or not $.hasClass doc, 'js-enabled' @conn = new Connection null, "#{location.protocol}//www.google.com", @@ -136,7 +136,7 @@ Captcha.v2 = return setupIFrame: (iframe) -> - Captcha.language.fixIframe iframe + Captcha.replace.iframe iframe $.addClass QR.nodes.el, 'captcha-open' if QR.nodes.el.getBoundingClientRect().bottom > doc.clientHeight QR.nodes.el.style.top = null