Temporarily revert "Take messaging between iframes out of the qr code, get ready for ajaxing with

images.4chan.org"

This reverts commit dea285d389cdb33b30a92d6057434120ee4b0928.
This commit is contained in:
Nicolas Stepien 2012-02-15 13:29:32 +01:00
parent 227ad8fefb
commit 53405d085f
2 changed files with 313 additions and 355 deletions

View File

@ -71,7 +71,7 @@
*/
(function() {
var $, $$, DAY, Favicon, HOUR, MINUTE, Main, NAMESPACE, SECOND, Time, VERSION, anonymize, conf, config, d, engine, expandComment, expandThread, filter, flatten, g, getTitle, imgExpand, imgGif, imgHover, key, keybinds, log, message, nav, options, qr, quoteBacklink, quoteDR, quoteInline, quoteOP, quotePreview, redirect, replyHiding, reportButton, revealSpoilers, sauce, strikethroughQuotes, threadHiding, threadStats, threading, titlePost, ui, unread, updater, val, watcher, _base,
var $, $$, DAY, Favicon, HOUR, MINUTE, Main, NAMESPACE, SECOND, Time, VERSION, anonymize, conf, config, d, engine, expandComment, expandThread, filter, flatten, g, getTitle, imgExpand, imgGif, imgHover, key, keybinds, log, nav, options, qr, quoteBacklink, quoteDR, quoteInline, quoteOP, quotePreview, redirect, replyHiding, reportButton, revealSpoilers, sauce, strikethroughQuotes, threadHiding, threadStats, threading, titlePost, ui, unread, updater, val, watcher, _base,
__slice = Array.prototype.slice;
config = {
@ -1191,7 +1191,7 @@
qr = {
init: function() {
var form, link;
var form, iframe, link, loadChecking;
if (!$.id('recaptcha_challenge_field_holder')) return;
if (conf['Hide Original Post Form']) {
link = $.el('h1', {
@ -1205,6 +1205,26 @@
$.before(form, link);
}
g.callbacks.push(this.node);
iframe = $.el('iframe', {
id: 'iframe',
hidden: true,
src: 'http://sys.4chan.org/robots.txt'
});
$.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 = 'http://sys.4chan.org/robots.txt';
}), 250);
}
};
$.on(iframe, 'load', function() {
if (this.src !== 'about:blank') return setTimeout(loadChecking, 500, this);
});
$.add(d.body, iframe);
if (conf['Persistent QR']) {
qr.dialog();
if (conf['Auto Hide QR']) qr.hide();
@ -1229,9 +1249,9 @@
close: function() {
var i, spoiler, _i, _len, _ref;
qr.el.hidden = true;
message.send({
qr.message.send({
req: 'abort'
}, 'sys');
});
d.activeElement.blur();
$.removeClass(qr.el, 'dump');
_ref = qr.replies;
@ -1701,6 +1721,7 @@
qr.status();
qr.cooldown.init();
qr.captcha.init();
qr.message.init();
$.add(d.body, qr.el);
e = d.createEvent('CustomEvent');
e.initEvent('QRDialogCreation', true, false);
@ -1714,9 +1735,9 @@
qr.status();
return;
}
message.send({
qr.message.send({
req: 'abort'
}, 'sys');
});
reply = qr.replies[0];
if (!(reply.com || reply.file)) {
err = 'No file selected.';
@ -1774,12 +1795,12 @@
file.name = reply.file.name;
file.type = reply.file.type;
post.upfile = file;
return message.send(post, 'sys');
return qr.message.send(post);
};
reader.readAsBinaryString(reply.file);
return;
}
return message.send(post, 'sys');
return qr.message.send(post);
},
response: function(html) {
var b, err, node, persona, postNumber, reply, thread, _, _ref;
@ -1831,93 +1852,150 @@
qr.status();
return qr.resetFileInput();
},
post: function(data) {
var boundary, callbacks, form, i, name, opts, parts, toBin, url, val;
url = "http://sys.4chan.org/" + data.board + "/post";
delete data.board;
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.post(data);
message: {
init: function() {
var code, ready, script;
code = function(e) {
var data, host;
data = e.data;
if (!data.changeContext) return;
delete data.changeContext;
host = location.hostname;
if (host === 'boards.4chan.org') {
return document.getElementById('iframe').contentWindow.postMessage(data, '*');
} else if (host === 'sys.4chan.org') {
return parent.postMessage(data, '*');
}
};
script = $.el('script', {
textContent: "window.addEventListener('message'," + code + ",false)"
});
ready = function() {
$.add(d.documentElement, script);
if (location.hostname === 'sys.4chan.org') {
qr.message.send({
req: 'status',
ready: true
});
}
return $.rm(script);
};
if (d.documentElement) {
return ready();
} else {
return $.ready(ready);
}
},
send: function(data) {
data.changeContext = true;
data.qr = true;
return postMessage(data, '*');
},
receive: function(data) {
var _ref;
switch (data.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);
default:
return qr.message.post(data);
}
},
post: function(data) {
var boundary, callbacks, form, i, name, opts, parts, toBin, url, val;
url = "http://sys.4chan.org/" + data.board + "/post";
delete data.board;
delete data.qr;
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'));
};
return r.readAsBinaryString(bb.getBlob('text/plain'));
};
i = Object.keys(data).length;
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.board = url.split('/')[3];
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 (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);
if (val) {
parts.push('Content-Disposition: form-data; name="' + name + '"\r\n\r\n' + val + '\r\n');
}
}
data.board = url.split('/')[3];
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);
}
}
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 message.send({
req: 'response',
html: this.response
});
}
};
opts = {
form: form,
type: 'post',
upCallbacks: {
callbacks = {
onload: function() {
return message.send({
req: 'status',
progress: '...'
});
},
onprogress: function(e) {
return message.send({
req: 'status',
progress: "" + (Math.round(e.loaded / e.total * 100)) + "%"
return qr.message.send({
req: 'response',
html: this.response
});
}
}
};
if (boundary) {
opts.headers = {
'Content-Type': 'multipart/form-data;boundary=' + boundary
};
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);
}
return qr.ajax = $.ajax(url, callbacks, opts);
}
};
@ -2352,9 +2430,9 @@
d.title = d.title.match(/^.+-/)[0] + ' 404';
}
unread.update(true);
message.send({
qr.message.send({
req: 'abort'
}, 'sys');
});
qr.status();
Favicon.update();
return;
@ -3410,113 +3488,6 @@
}
};
message = {
init: function() {
var code, script;
$.on(window, 'message', message.receive);
$.ready(function() {
var domain, domains, iframe, _i, _len, _results;
if (location.hostname !== 'boards.4chan.org') return;
domains = [];
if (conf['Quick Reply']) domains.push('sys');
if (conf['Image Expansion'] || conf['Sauce']) domains.push('images');
_results = [];
for (_i = 0, _len = domains.length; _i < _len; _i++) {
domain = domains[_i];
iframe = $.el('iframe', {
id: domain,
hidden: true,
src: "http://" + domain + ".4chan.org/robots.txt"
});
$.on(iframe, 'error', message.loadControl);
$.on(iframe, 'load', message.loadControl);
_results.push($.add(d.body, iframe));
}
return _results;
});
code = function(e) {
var data;
data = e.data;
if (!data.changeContext) return;
delete data.changeContext;
if (location.hostname === 'boards.4chan.org') {
return document.getElementById(data.iframe).contentWindow.postMessage(data, '*');
} else {
return parent.postMessage(data, '*');
}
};
script = $.el('script', {
textContent: "window.addEventListener('message'," + code + ",false)"
});
return $.ready(function() {
var host;
$.add(d.documentElement, script);
host = location.hostname;
if (host === 'sys.4chan.org') {
message.send({
req: 'status',
ready: true
});
}
if (host !== 'boards.4chan.org') {
message.send({
req: 'iframeLoad',
id: location.hostname.split('.')[0]
});
}
return $.rm(script);
});
},
loadControl: function() {
var _this = this;
return setTimeout((function() {
if (_this.src === 'about:blank' || message[_this.id] === 'ready') return;
_this.src = 'about:blank';
return setTimeout((function() {
return _this.src = "http://" + _this.id + ".4chan.org/robots.txt";
}), 250);
}), 1000);
},
receive: function(e) {
var data, version;
data = e.data;
if (data.iframe) {
if (!data.changeContext) message.handle(data);
return;
}
version = data.version;
if (version && version !== 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";
}
},
send: function(data, iframe) {
data.changeContext = true;
data.iframe = iframe || 'boards';
return postMessage(data, '*');
},
handle: function(data) {
var req, _ref;
req = data.req;
delete data.req;
delete data.iframe;
switch (req) {
case 'iframeLoad':
return message[data.id] = 'ready';
case 'abort':
if ((_ref = qr.ajax) != null) _ref.abort();
return message.send({
req: 'status'
});
case 'response':
return qr.response(data.html);
case 'status':
return qr.status(data);
default:
return qr.post(data);
}
}
};
Main = {
init: function() {
var cutoff, hiddenThreads, id, now, pathname, temp, timestamp, _ref;
@ -3528,9 +3499,11 @@
} else {
g.PAGENUM = parseInt(temp) || 0;
}
message.init();
$.on(window, 'message', Main.message);
if (location.hostname === 'sys.4chan.org') {
if (/report/.test(location.search)) {
if (location.pathname === '/robots.txt') {
qr.message.init();
} else if (/report/.test(location.search)) {
$.ready(function() {
return $.on($('#recaptcha_response_field'), 'keydown', function(e) {
if (e.keyCode === 8 && !e.target.value) {
@ -3646,6 +3619,16 @@
return $.on(d, 'DOMNodeInserted', Main.addStyle);
}
},
message: function(e) {
var data, version;
data = e.data;
version = data.version;
if (data.qr && !data.changeContext) {
return qr.message.receive(data);
} else if (version && version !== 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";
}
},
node: function(e) {
var callback, target, _i, _len, _ref, _results;
target = e.target;

View File

@ -880,6 +880,19 @@ qr =
$.before form, link
g.callbacks.push @node
iframe = $.el 'iframe',
id: 'iframe'
hidden: true
src: 'http://sys.4chan.org/robots.txt'
$.on iframe, 'error', -> @src = @src
# Greasemonkey ghetto fix
loadChecking = (iframe) ->
unless qr.status.ready
iframe.src = 'about:blank'
setTimeout (-> iframe.src = 'http://sys.4chan.org/robots.txt'), 250
$.on iframe, 'load', -> unless @src is 'about:blank' then setTimeout loadChecking, 500, @
$.add d.body, iframe
if conf['Persistent QR']
qr.dialog()
qr.hide() if conf['Auto Hide QR']
@ -901,7 +914,7 @@ qr =
qr.dialog()
close: ->
qr.el.hidden = true
message.send req: 'abort', 'sys'
qr.message.send req: 'abort'
d.activeElement.blur()
$.removeClass qr.el, 'dump'
for i in qr.replies
@ -1274,6 +1287,7 @@ qr =
qr.status()
qr.cooldown.init()
qr.captcha.init()
qr.message.init()
$.add d.body, qr.el
# Create a custom event when the QR dialog is first initialized.
@ -1288,7 +1302,7 @@ qr =
qr.cooldown.auto = !qr.cooldown.auto
qr.status()
return
message.send req: 'abort', 'sys'
qr.message.send req: 'abort'
reply = qr.replies[0]
# prevent errors
@ -1357,11 +1371,11 @@ qr =
file.name = reply.file.name
file.type = reply.file.type
post.upfile = file
message.send post, 'sys'
qr.message.send post
reader.readAsBinaryString reply.file
return
message.send post, 'sys'
qr.message.send post
response: (html) ->
unless b = $ 'td b', $.el('a', innerHTML: html)
@ -1413,78 +1427,121 @@ qr =
qr.status()
qr.resetFileInput()
post: (data) ->
message:
init: ->
# http://code.google.com/p/chromium/issues/detail?id=20773
# Let content scripts see other frames (instead of them being undefined)
# To access the parent, we have to break out of the sandbox and evaluate
# in the global context.
code = (e) ->
{data} = e
return unless data.changeContext
delete data.changeContext
host = location.hostname
if host is 'boards.4chan.org'
document.getElementById('iframe').contentWindow.postMessage data, '*'
else if host is 'sys.4chan.org'
parent.postMessage data, '*'
script = $.el 'script', textContent: "window.addEventListener('message',#{code},false)"
ready = ->
$.add d.documentElement, script
if location.hostname is 'sys.4chan.org'
qr.message.send req: 'status', ready: true
$.rm script
# Chrome can access the documentElement on document-start
if d.documentElement
ready()
# other browsers will have to wait
else $.ready ready
send: (data) ->
data.changeContext = true
data.qr = true
postMessage data, '*'
receive: (data) ->
switch data.req
when 'abort'
qr.ajax?.abort()
qr.message.send req: 'status'
when 'response' # xhr response
qr.response data.html
when 'status'
qr.status data
else
qr.message.post data # Reply object: we're posting
url = "http://sys.4chan.org/#{data.board}/post"
# Do not append that value to the form.
delete data.board
post: (data) ->
# 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.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
url = "http://sys.4chan.org/#{data.board}/post"
# Do not append these values to the form.
delete data.board
delete data.qr
# 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
i--
else
toBin data, name, val
data.board = url.split('/')[3]
data.binary = true
return
toBin data, name, val
data.board = url.split('/')[3]
data.binary = true
return
delete data.binary
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
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'
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
else
form = new FormData()
for name, val of data
form.append name, val if val
callbacks =
onload: ->
message.send
req: 'response'
html: @response
opts =
form: form
type: 'post'
upCallbacks:
callbacks =
onload: ->
message.send
req: 'status'
progress: '...'
onprogress: (e) ->
message.send
req: 'status'
progress: "#{Math.round e.loaded / e.total * 100}%"
if boundary
opts.headers =
'Content-Type': 'multipart/form-data;boundary=' + boundary
qr.message.send
req: 'response'
html: @response
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
qr.ajax = $.ajax url, callbacks, opts
options =
init: ->
@ -1864,7 +1921,7 @@ updater =
else
d.title = d.title.match(/^.+-/)[0] + ' 404'
unread.update true
message.send req: 'abort', 'sys'
qr.message.send req: 'abort'
qr.status()
Favicon.update()
return
@ -2656,98 +2713,6 @@ imgExpand =
resize: ->
imgExpand.style.innerHTML = ".fitheight img[md5] + img {max-height:#{d.body.clientHeight}px;}"
message =
init: ->
$.on window, 'message', message.receive
$.ready ->
return if location.hostname isnt 'boards.4chan.org'
domains = []
if conf['Quick Reply']
domains.push 'sys'
if conf['Image Expansion'] or conf['Sauce']
domains.push 'images'
for domain in domains
iframe = $.el 'iframe',
id: domain
hidden: true
src: "http://#{domain}.4chan.org/robots.txt"
$.on iframe, 'error', message.loadControl
$.on iframe, 'load', message.loadControl
$.add d.body, iframe
# http://code.google.com/p/chromium/issues/detail?id=20773
# Let content scripts see other frames (instead of them being undefined)
# To access the parent, we have to break out of the sandbox and evaluate
# in the global context.
code = (e) ->
{data} = e
return unless data.changeContext
delete data.changeContext
if location.hostname is 'boards.4chan.org'
document.getElementById(data.iframe).contentWindow.postMessage data, '*'
else
parent.postMessage data, '*'
script = $.el 'script',
textContent: "window.addEventListener('message',#{code},false)"
$.ready ->
$.add d.documentElement, script
host = location.hostname
if host is 'sys.4chan.org'
message.send req: 'status', ready: true
if host isnt 'boards.4chan.org'
message.send req: 'iframeLoad', id: location.hostname.split('.')[0]
$.rm script
loadControl: ->
# Make sure the iframe has loaded correctly.
# This is necessary for Greasemonkey users.
setTimeout (=>
return if @src is 'about:blank' or message[@id] is 'ready'
@src = 'about:blank'
setTimeout (=>
@src = "http://#{@id}.4chan.org/robots.txt"
), 250
), 1000
receive: (e) ->
{data} = e
if data.iframe
unless data.changeContext
message.handle data
return
{version} = data
if version and version isnt 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"
send: (data, iframe) ->
data.changeContext = true
data.iframe = iframe or 'boards'
postMessage data, '*'
handle: (data) ->
{req} = data
delete data.req
delete data.iframe
switch req
when 'iframeLoad'
message[data.id] = 'ready'
when 'abort'
qr.ajax?.abort()
message.send req: 'status'
when 'response' # xhr response
qr.response data.html
when 'status'
qr.status data
else
# Reply object: we're posting
qr.post data
Main =
init: ->
pathname = location.pathname[1..].split('/')
@ -2758,10 +2723,12 @@ Main =
else
g.PAGENUM = parseInt(temp) or 0
message.init()
$.on window, 'message', Main.message
if location.hostname is 'sys.4chan.org'
if /report/.test location.search
if location.pathname is '/robots.txt'
qr.message.init()
else if /report/.test location.search
$.ready ->
$.on $('#recaptcha_response_field'), 'keydown', (e) ->
window.location = 'javascript:Recaptcha.reload()' if e.keyCode is 8 and not e.target.value
@ -2920,6 +2887,14 @@ Main =
else # XXX fox
$.on d, 'DOMNodeInserted', Main.addStyle
message: (e) ->
{data} = e
{version} = data
if data.qr and not data.changeContext
qr.message.receive data
else if version and version isnt 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"
node: (e) ->
{target} = e
return unless target.nodeName is 'TABLE'