diff --git a/4chan_x.user.js b/4chan_x.user.js
index d34578e03..dbe75ca8b 100644
--- a/4chan_x.user.js
+++ b/4chan_x.user.js
@@ -9,7 +9,6 @@
// @include http*://boards.4chan.org/*
// @include http*://images.4chan.org/*
// @include http*://sys.4chan.org/*
-// @include http*://www.4chan.org/*
// @run-at document-start
// @updateURL https://raw.github.com/MayhemYDG/4chan-x/stable/4chan_x.user.js
// @icon http://mayhemydg.github.com/4chan-x/favicon.gif
@@ -1226,46 +1225,17 @@
return setTimeout(this.asyncInit);
},
asyncInit: function() {
- var form, iframe, link, loadChecking, script, src;
- form = $('form[name=post]');
+ var link, script;
if (Conf['Hide Original Post Form']) {
link = $.el('h1', {
innerHTML: "" + (g.REPLY ? 'Quick Reply' : 'New Thread') + ""
});
- $.on($('a', link), 'click', function() {
+ $.on(link.firstChild, 'click', function() {
QR.open();
if (!g.REPLY) $('select', QR.el).value = 'new';
return $('textarea', QR.el).focus();
});
- $.before(form, link);
- }
- if (/chrome/i.test(navigator.userAgent)) {
- QR.status({
- ready: true
- });
- } else {
- src = "http" + (/^https/.test(form.action) ? 's' : '') + "://sys.4chan.org/robots.txt";
- iframe = $.el('iframe', {
- id: 'iframe',
- src: src
- });
- $.on(iframe, 'error', function() {
- return this.src = this.src;
- });
- loadChecking = function(iframe) {
- if (!QR.status.ready) {
- iframe.src = 'about:blank';
- return setTimeout((function() {
- return iframe.src = src;
- }), 100);
- }
- };
- $.on(iframe, 'load', function() {
- if (this.src !== 'about:blank') {
- return setTimeout(loadChecking, 500, this);
- }
- });
- $.add(d.head, iframe);
+ $.before($('form[name=post]'), link);
}
script = $.el('script', {
textContent: 'Recaptcha.focus_response_field=function(){}'
@@ -1294,9 +1264,7 @@
close: function() {
var i, spoiler, _i, _len, _ref;
QR.el.hidden = true;
- QR.message.send({
- req: 'abort'
- });
+ QR.abort();
d.activeElement.blur();
$.removeClass(QR.el, 'dump');
_ref = QR.replies;
@@ -1341,23 +1309,12 @@
status: function(data) {
var disabled, input, value;
if (data == null) data = {};
- if (data.ready) {
- QR.status.ready = true;
- QR.status.banned = data.banned;
- } else if (!QR.status.ready) {
- value = 'Loading';
- disabled = true;
- }
if (g.dead) {
value = 404;
disabled = true;
QR.cooldown.auto = false;
- } else if (QR.status.banned) {
- value = 'Banned';
- disabled = true;
- } else {
- value = QR.cooldown.seconds || data.progress || value;
}
+ value = QR.cooldown.seconds || data.progress || value;
if (!QR.el) return;
input = QR.status.input;
input.value = QR.cooldown.auto && Conf['Cooldown'] ? value ? "Auto " + value : 'Auto' : value || 'Submit';
@@ -1823,16 +1780,14 @@
return QR.el.dispatchEvent(e);
},
submit: function(e) {
- var captcha, captchas, challenge, err, file, m, post, reader, reply, response, threadID;
+ var callbacks, captcha, captchas, challenge, err, form, m, name, opts, post, reply, response, threadID, val;
if (e != null) e.preventDefault();
if (QR.cooldown.seconds) {
QR.cooldown.auto = !QR.cooldown.auto;
QR.status();
return;
}
- QR.message.send({
- req: 'abort'
- });
+ QR.abort();
reply = QR.replies[0];
if (!(reply.com || reply.file)) {
err = 'No file selected.';
@@ -1865,8 +1820,10 @@
if (Conf['Thread Watcher'] && Conf['Auto Watch Reply'] && threadID !== 'new') {
Watcher.watch(threadID);
}
+ QR.status({
+ progress: '...'
+ });
post = {
- postURL: $('form[name=post]').action,
resto: threadID,
name: reply.name,
email: reply.email,
@@ -1879,37 +1836,51 @@
recaptcha_challenge_field: challenge,
recaptcha_response_field: response + ' '
};
- QR.status({
- progress: '...'
- });
- if ($.engine === 'gecko' && reply.file) {
- file = {};
- reader = new FileReader();
- reader.onload = function() {
- file.buffer = this.result;
- file.name = reply.file.name;
- file.type = reply.file.type;
- post.upfile = file;
- return QR.message.send(post);
- };
- reader.readAsBinaryString(reply.file);
- return;
+ form = new FormData();
+ for (name in post) {
+ val = post[name];
+ if (val) form.append(name, val);
}
- if (/chrome/i.test(navigator.userAgent)) {
- QR.message.post(post);
- return;
- }
- return QR.message.send(post);
+ callbacks = {
+ onload: function() {
+ return QR.response(this.response);
+ },
+ onerror: function() {
+ return QR.error('_', $.el('a', {
+ href: '//www.4chan.org/banned',
+ target: '_blank',
+ textContent: 'Connection error, or you are banned.'
+ }));
+ }
+ };
+ opts = {
+ form: form,
+ type: 'POST',
+ upCallbacks: {
+ onload: function() {
+ return QR.status({
+ progress: '...'
+ });
+ },
+ onprogress: function(e) {
+ return QR.status({
+ progress: "" + (Math.round(e.loaded / e.total * 100)) + "%"
+ });
+ }
+ }
+ };
+ return QR.ajax = $.ajax($('form[name=post]').action, callbacks, opts);
},
response: function(html) {
var b, doc, err, node, persona, postNumber, reply, thread, _, _ref;
- doc = $.el('a', {
- innerHTML: html
- });
- if ($('title', doc).textContent === '4chan - Banned') {
- QR.message.receive({
- req: 'banned'
- });
+ doc = d.implementation.createHTMLDocument(null);
+ doc.documentElement.innerHTML = html;
+ if (doc.title === '4chan - Banned') {
+ QR.error('_', $.el('a', {
+ href: '//www.4chan.org/banned',
+ target: '_blank',
+ textContent: 'You are banned.'
+ }));
return;
}
if (!(b = $('td b', doc))) {
@@ -1967,146 +1938,10 @@
QR.status();
return QR.resetFileInput();
},
- message: {
- send: function(data) {
- var host, window;
- if (/chrome/i.test(navigator.userAgent)) {
- QR.message.receive(data);
- return;
- }
- data.QR = true;
- host = location.hostname;
- window = host === 'boards.4chan.org' ? $.id('iframe').contentWindow : parent;
- return window.postMessage(data, '*');
- },
- receive: function(data) {
- var req, _ref;
- req = data.req;
- delete data.req;
- delete data.QR;
- switch (req) {
- case 'abort':
- if ((_ref = QR.ajax) != null) _ref.abort();
- return QR.message.send({
- req: 'status'
- });
- case 'response':
- return QR.response(data.html);
- case 'status':
- return QR.status(data);
- case 'connection error':
- return QR.error('_', $.el('a', {
- href: '//www.4chan.org/banned',
- target: '_blank',
- textContent: 'Connection error, or you are banned.'
- }));
- case 'banned':
- QR.error('_', $.el('a', {
- href: '//www.4chan.org/banned',
- target: '_blank',
- textContent: 'You are banned.'
- }));
- return QR.status({
- ready: true,
- banned: true
- });
- default:
- return QR.message.post(data);
- }
- },
- post: function(data) {
- var boundary, callbacks, form, i, name, opts, parts, toBin, url, val;
- url = data.postURL;
- delete data.postURL;
- if ($.engine === 'gecko' && data.upfile) {
- if (!data.binary) {
- toBin = function(data, name, val) {
- var bb, r;
- bb = new MozBlobBuilder();
- bb.append(val);
- r = new FileReader();
- r.onload = function() {
- data[name] = r.result;
- if (!--i) return QR.message.post(data);
- };
- return r.readAsBinaryString(bb.getBlob('text/plain'));
- };
- i = Object.keys(data).length;
- for (name in data) {
- val = data[name];
- if (typeof val === 'object') {
- toBin(data.upfile, 'name', data.upfile.name);
- } else if (typeof val === 'boolean') {
- if (val) {
- toBin(data, name, String(val));
- } else {
- i--;
- }
- } else {
- toBin(data, name, val);
- }
- }
- data.postURL = url;
- data.binary = true;
- return;
- }
- delete data.binary;
- boundary = '-------------SMCD' + Date.now();
- parts = [];
- parts.push('Content-Disposition: form-data; name="upfile"; filename="' + data.upfile.name + '"\r\n' + 'Content-Type: ' + data.upfile.type + '\r\n\r\n' + data.upfile.buffer + '\r\n');
- delete data.upfile;
- for (name in data) {
- val = data[name];
- if (val) {
- parts.push('Content-Disposition: form-data; name="' + name + '"\r\n\r\n' + val + '\r\n');
- }
- }
- form = '--' + boundary + '\r\n' + parts.join('--' + boundary + '\r\n') + '--' + boundary + '--\r\n';
- } else {
- form = new FormData();
- for (name in data) {
- val = data[name];
- if (val) form.append(name, val);
- }
- }
- callbacks = {
- onload: function() {
- return QR.message.send({
- req: 'response',
- html: this.response
- });
- },
- onerror: function() {
- return QR.message.send({
- req: 'connection error'
- });
- }
- };
- opts = {
- form: form,
- type: 'post',
- upCallbacks: {
- onload: function() {
- return QR.message.send({
- req: 'status',
- progress: '...'
- });
- },
- onprogress: function(e) {
- return QR.message.send({
- req: 'status',
- progress: "" + (Math.round(e.loaded / e.total * 100)) + "%"
- });
- }
- }
- };
- if (boundary) {
- opts.headers = {
- 'Content-Type': 'multipart/form-data;boundary=' + boundary
- };
- }
- return QR.ajax = $.ajax(url, callbacks, opts);
- }
+ abort: function() {
+ var _ref;
+ if ((_ref = QR.ajax) != null) _ref.abort();
+ return QR.status();
}
};
@@ -2566,10 +2401,7 @@
d.title = d.title.match(/^.+-/)[0] + ' 404';
}
Unread.update(true);
- QR.message.send({
- req: 'abort'
- });
- QR.status();
+ QR.abort();
return;
}
Updater.retryCoef = 10;
@@ -3811,12 +3643,7 @@
$.on(window, 'message', Main.message);
switch (location.hostname) {
case 'sys.4chan.org':
- if (path === '/robots.txt') {
- QR.message.send({
- req: 'status',
- ready: true
- });
- } else if (/report/.test(location.search)) {
+ if (/report/.test(location.search)) {
$.ready(function() {
return $.on($.id('recaptcha_response_field'), 'keydown', function(e) {
if (e.keyCode === 8 && !e.target.value) {
@@ -3826,13 +3653,6 @@
});
}
return;
- case 'www.4chan.org':
- if (path === '/banned') {
- QR.message.send({
- req: 'banned'
- });
- }
- return;
case 'images.4chan.org':
$.ready(function() {
if (d.title === '4chan - 404') return Redirect.init();
@@ -3993,13 +3813,8 @@
}
},
message: function(e) {
- var data, version;
- data = e.data;
- if (data.QR) {
- QR.message.receive(data);
- return;
- }
- version = data.version;
+ var version;
+ version = e.data.version;
if (version && version !== Main.version && confirm('An updated version of 4chan X is available, would you like to install it now?')) {
return window.location = "https://raw.github.com/mayhemydg/4chan-x/" + version + "/4chan_x.user.js";
}
diff --git a/Cakefile b/Cakefile
index 8fb5a2a42..139742e0c 100644
--- a/Cakefile
+++ b/Cakefile
@@ -16,7 +16,6 @@ HEADER = """
// @include http*://boards.4chan.org/*
// @include http*://images.4chan.org/*
// @include http*://sys.4chan.org/*
-// @include http*://www.4chan.org/*
// @run-at document-start
// @updateURL https://raw.github.com/MayhemYDG/4chan-x/stable/4chan_x.user.js
// @icon http://mayhemydg.github.com/4chan-x/favicon.gif
diff --git a/changelog b/changelog
index a6f7f9e6a..2fd72e603 100644
--- a/changelog
+++ b/changelog
@@ -1,4 +1,6 @@
master
+- Mayhem
+ Update posting method.
2.29.2
- Mayhem
diff --git a/script.coffee b/script.coffee
index fd50fadd0..e10dc9695 100644
--- a/script.coffee
+++ b/script.coffee
@@ -1010,34 +1010,17 @@ QR =
setTimeout @asyncInit
asyncInit: ->
- form = $ 'form[name=post]'
if Conf['Hide Original Post Form']
link = $.el 'h1', innerHTML: "#{if g.REPLY then 'Quick Reply' else 'New Thread'}"
- $.on $('a', link), 'click', ->
+ $.on link.firstChild, 'click', ->
QR.open()
$('select', QR.el).value = 'new' unless g.REPLY
$('textarea', QR.el).focus()
- $.before form, link
-
- # CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox.
- if /chrome/i.test navigator.userAgent
- QR.status ready: true
- else
- src = "http#{if /^https/.test form.action then 's' else ''}://sys.4chan.org/robots.txt"
- iframe = $.el 'iframe',
- id: 'iframe'
- src: src
- $.on iframe, 'error', -> @src = @src
- # Greasemonkey ghetto fix
- loadChecking = (iframe) ->
- unless QR.status.ready
- iframe.src = 'about:blank'
- setTimeout (-> iframe.src = src), 100
- $.on iframe, 'load', -> if @src isnt 'about:blank' then setTimeout loadChecking, 500, @
- $.add d.head, iframe
+ $.before $('form[name=post]'), link
# Prevent original captcha input from being focused on reload.
- script = $.el 'script', textContent: 'Recaptcha.focus_response_field=function(){}'
+ script = $.el 'script',
+ textContent: 'Recaptcha.focus_response_field=function(){}'
$.add d.head, script
$.rm script
@@ -1059,7 +1042,7 @@ QR =
QR.dialog()
close: ->
QR.el.hidden = true
- QR.message.send req: 'abort'
+ QR.abort()
d.activeElement.blur()
$.removeClass QR.el, 'dump'
for i in QR.replies
@@ -1093,22 +1076,11 @@ QR =
$('.warning', QR.el).textContent = null
status: (data={}) ->
- if data.ready
- QR.status.ready = true
- QR.status.banned = data.banned
- else unless QR.status.ready
- value = 'Loading'
- disabled = true
if g.dead
value = 404
disabled = true
QR.cooldown.auto = false
- else if QR.status.banned
- value = 'Banned'
- disabled = true
- else
- # do not cancel `value = 'Loading'` once the cooldown is over
- value = QR.cooldown.seconds or data.progress or value
+ value = QR.cooldown.seconds or data.progress or value
return unless QR.el
{input} = QR.status
input.value =
@@ -1509,7 +1481,7 @@ QR =
QR.cooldown.auto = !QR.cooldown.auto
QR.status()
return
- QR.message.send req: 'abort'
+ QR.abort()
reply = QR.replies[0]
# prevent errors
@@ -1549,8 +1521,11 @@ QR =
if Conf['Thread Watcher'] and Conf['Auto Watch Reply'] and threadID isnt 'new'
Watcher.watch threadID
+ # Starting to upload might take some time.
+ # Provide some feedback that we're starting to submit.
+ QR.status progress: '...'
+
post =
- postURL: $('form[name=post]').action
resto: threadID
name: reply.name
email: reply.email
@@ -1563,36 +1538,42 @@ QR =
recaptcha_challenge_field: challenge
recaptcha_response_field: response + ' '
- # Starting to upload might take some time.
- # Provide some feedback that we're starting to submit.
- QR.status progress: '...'
+ form = new FormData()
+ for name, val of post
+ form.append name, val if val
- if $.engine is 'gecko' and reply.file
- # https://bugzilla.mozilla.org/show_bug.cgi?id=673742
- # We plan to allow postMessaging Files and FileLists across origins,
- # that just needs a more in depth security review.
- file = {}
- reader = new FileReader()
- reader.onload = ->
- file.buffer = @result
- file.name = reply.file.name
- file.type = reply.file.type
- post.upfile = file
- QR.message.send post
- reader.readAsBinaryString reply.file
- return
+ callbacks =
+ onload: ->
+ QR.response @response
+ onerror: ->
+ # Connection error, or
+ # CORS disabled error on www.4chan.org/banned
+ QR.error '_', $.el 'a',
+ href: '//www.4chan.org/banned'
+ target: '_blank'
+ textContent: 'Connection error, or you are banned.'
+ opts =
+ form: form
+ type: 'POST'
+ upCallbacks:
+ onload: ->
+ # Upload done, waiting for response.
+ QR.status progress: '...'
+ onprogress: (e) ->
+ # Uploading...
+ QR.status progress: "#{Math.round e.loaded / e.total * 100}%"
- # CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox.
- if /chrome/i.test navigator.userAgent
- QR.message.post post
- return
- QR.message.send post
+ QR.ajax = $.ajax $('form[name=post]').action, callbacks, opts
response: (html) ->
- doc = $.el 'a', innerHTML: html
+ doc = d.implementation.createHTMLDocument null
+ doc.documentElement.innerHTML = html
# Check for ban.
- if $('title', doc).textContent is '4chan - Banned'
- QR.message.receive req: 'banned'
+ if doc.title is '4chan - Banned'
+ QR.error '_', $.el 'a',
+ href: '//www.4chan.org/banned'
+ target: '_blank'
+ textContent: 'You are banned.'
return
unless b = $ 'td b', doc
err = 'Connection error with sys.4chan.org.'
@@ -1650,123 +1631,9 @@ QR =
QR.status()
QR.resetFileInput()
- message:
- send: (data) ->
- # CORS is ignored for content script on Chrome, but not Safari/Oprah/Firefox.
- if /chrome/i.test navigator.userAgent
- QR.message.receive data
- return
- data.QR = true
- host = location.hostname
- window =
- if host is 'boards.4chan.org'
- $.id('iframe').contentWindow
- else
- parent
- window.postMessage data, '*'
- receive: (data) ->
- req = data.req
- delete data.req
- delete data.QR
- switch req
- when 'abort'
- QR.ajax?.abort()
- QR.message.send req: 'status'
- when 'response' # xhr response
- QR.response data.html
- when 'status'
- QR.status data
- when 'connection error'
- QR.error '_', $.el 'a',
- href: '//www.4chan.org/banned'
- target: '_blank'
- textContent: 'Connection error, or you are banned.'
- when 'banned'
- QR.error '_', $.el 'a',
- href: '//www.4chan.org/banned'
- target: '_blank'
- textContent: 'You are banned.'
- # Disable iframe reloading
- QR.status ready: true, banned: true
- else
- QR.message.post data # Reply object: we're posting
-
- post: (data) ->
-
- url = data.postURL
- # Do not append these values to the form.
- delete data.postURL
-
- # File with filename upload fix from desuwa
- if $.engine is 'gecko' and data.upfile
- # All of this is fucking retarded.
- unless data.binary
- toBin = (data, name, val) ->
- bb = new MozBlobBuilder()
- bb.append val
- r = new FileReader()
- r.onload = ->
- data[name] = r.result
- unless --i
- QR.message.post data
- r.readAsBinaryString bb.getBlob 'text/plain'
- i = Object.keys(data).length
- for name, val of data
- if typeof val is 'object' # File. toBin the filename.
- toBin data.upfile, 'name', data.upfile.name
- else if typeof val is 'boolean'
- if val
- toBin data, name, String val
- else
- i--
- else
- toBin data, name, val
- data.postURL = url
- data.binary = true
- return
-
- delete data.binary
-
- boundary = '-------------SMCD' + Date.now();
- parts = []
- parts.push 'Content-Disposition: form-data; name="upfile"; filename="' + data.upfile.name + '"\r\n' + 'Content-Type: ' + data.upfile.type + '\r\n\r\n' + data.upfile.buffer + '\r\n'
- delete data.upfile
-
- for name, val of data
- parts.push 'Content-Disposition: form-data; name="' + name + '"\r\n\r\n' + val + '\r\n' if val
- form = '--' + boundary + '\r\n' + parts.join('--' + boundary + '\r\n') + '--' + boundary + '--\r\n'
-
- else
- form = new FormData()
- for name, val of data
- form.append name, val if val
-
- callbacks =
- onload: ->
- QR.message.send
- req: 'response'
- html: @response
- onerror: ->
- # Connection error, or
- # CORS disabled error: redirecting to banned page ;_;
- QR.message.send req: 'connection error'
- opts =
- form: form
- type: 'post'
- upCallbacks:
- onload: ->
- QR.message.send
- req: 'status'
- progress: '...'
- onprogress: (e) ->
- QR.message.send
- req: 'status'
- progress: "#{Math.round e.loaded / e.total * 100}%"
- if boundary
- opts.headers =
- 'Content-Type': 'multipart/form-data;boundary=' + boundary
-
- QR.ajax = $.ajax url, callbacks, opts
+ abort: ->
+ QR.ajax?.abort()
+ QR.status()
Options =
init: ->
@@ -2179,8 +2046,7 @@ Updater =
else
d.title = d.title.match(/^.+-/)[0] + ' 404'
Unread.update true
- QR.message.send req: 'abort'
- QR.status()
+ QR.abort()
return
Updater.retryCoef = 10
@@ -3178,17 +3044,11 @@ Main =
switch location.hostname
when 'sys.4chan.org'
- if path is '/robots.txt'
- QR.message.send req: 'status', ready: true
- else if /report/.test location.search
+ if /report/.test location.search
$.ready ->
$.on $.id('recaptcha_response_field'), 'keydown', (e) ->
window.location = 'javascript:Recaptcha.reload()' if e.keyCode is 8 and not e.target.value
return
- when 'www.4chan.org'
- if path is '/banned'
- QR.message.send req: 'banned'
- return
when 'images.4chan.org'
$.ready -> Redirect.init() if d.title is '4chan - 404'
return
@@ -3365,11 +3225,7 @@ Main =
$.on d, 'DOMNodeInserted', Main.addStyle
message: (e) ->
- {data} = e
- if data.QR
- QR.message.receive data
- return
- {version} = data
+ {version} = e.data
if version and version isnt Main.version and confirm 'An updated version of 4chan X is available, would you like to install it now?'
window.location = "https://raw.github.com/mayhemydg/4chan-x/#{version}/4chan_x.user.js"