diff --git a/CHANGELOG.md b/CHANGELOG.md index 913581ea7..94afff081 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +### v1.7.25 +*2014-05-01* + **ccd0** - For single files, file errors are reported but no longer stop you from attempting to post. Files with errors are still removed when posting multiple files. - Fix small bugs in file checking, uploading from URLs. diff --git a/LICENSE b/LICENSE index d5ee36f05..939f12b8c 100755 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ /* -* 4chan X - Version 1.7.24 - 2014-04-30 +* 4chan X - Version 1.7.25 - 2014-05-01 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE diff --git a/builds/4chan-X.meta.js b/builds/4chan-X.meta.js index 6f08f02bb..c9d3d7ad2 100755 --- a/builds/4chan-X.meta.js +++ b/builds/4chan-X.meta.js @@ -1,6 +1,6 @@ // ==UserScript== // @name 4chan X -// @version 1.7.24 +// @version 1.7.25 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X diff --git a/builds/4chan-X.user.js b/builds/4chan-X.user.js index d27634168..4358cebb7 100644 --- a/builds/4chan-X.user.js +++ b/builds/4chan-X.user.js @@ -1,7 +1,7 @@ // Generated by CoffeeScript // ==UserScript== // @name 4chan X -// @version 1.7.24 +// @version 1.7.25 // @minGMVer 1.14 // @minFFVer 26 // @namespace 4chan-X @@ -24,7 +24,7 @@ // ==/UserScript== /* -* 4chan X - Version 1.7.24 - 2014-04-30 +* 4chan X - Version 1.7.25 - 2014-05-01 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -372,7 +372,7 @@ doc = d.documentElement; g = { - VERSION: '1.7.24', + VERSION: '1.7.25', NAMESPACE: '4chan X.', boards: {} }; @@ -5647,7 +5647,7 @@ }; QR = { - mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/x-shockwave-flash', 'video/webm', ''], + mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], init: function() { var sc; if (!Conf['Quick Reply']) { @@ -5990,32 +5990,18 @@ QR.handleFiles(files); return $.addClass(QR.nodes.el, 'dump'); }, - handleBlob: function(urlBlob, header, url) { - var blob, end, endnl, endsc, mime, name, name_end, name_start, start, _ref; - name = url.substr(url.lastIndexOf('/') + 1, url.length); - start = header.indexOf("Content-Type: ") + 14; - endsc = header.substr(start, header.length).indexOf(";"); - endnl = header.substr(start, header.length).indexOf("\n") - 1; - end = endnl; - if (endsc !== -1 && endsc < endnl) { - end = endsc; + handleBlob: function(urlBlob, contentType, contentDisposition, url) { + var blob, match, mime, name, _ref, _ref1, _ref2; + name = (_ref = url.match(/([^\/]+)\/*$/)) != null ? _ref[1] : void 0; + mime = (contentType != null ? contentType.match(/[^;]*/)[0] : void 0) || 'application/octet-stream'; + match = (contentDisposition != null ? (_ref1 = contentDisposition.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)) != null ? _ref1[1] : void 0 : void 0) || (contentType != null ? (_ref2 = contentType.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)) != null ? _ref2[1] : void 0 : void 0); + if (match) { + name = match.replace(/\\"/g, '"'); } - mime = header.substr(start, end); blob = new Blob([urlBlob], { type: mime }); - blob.name = url.substr(url.lastIndexOf('/') + 1, url.length); - name_start = header.indexOf('name="') + 6; - if (name_start - 6 !== -1) { - name_end = header.substr(name_start, header.length).indexOf('"'); - blob.name = header.substr(name_start, name_end); - } - if (blob.type === null) { - return QR.error("Unsupported file type."); - } - if (_ref = blob.type, __indexOf.call(QR.mimeTypes, _ref) < 0) { - return QR.error("Unsupported file type."); - } + blob.name = name; return QR.handleFiles([blob]); }, handleUrl: function() { @@ -6024,12 +6010,12 @@ if (url === null) { return; } - GM_xmlhttpRequest({ + return GM_xmlhttpRequest({ method: "GET", url: url, overrideMimeType: "text/plain; charset=x-user-defined", onload: function(xhr) { - var data, i, r; + var contentDisposition, contentType, data, i, r, _ref, _ref1; r = xhr.responseText; data = new Uint8Array(r.length); i = 0; @@ -6037,13 +6023,12 @@ data[i] = r.charCodeAt(i); i++; } - QR.handleBlob(data, xhr.responseHeaders, url); - return; - return { - onerror: function(xhr) { - return QR.error("Can't load image."); - } - }; + contentType = (_ref = xhr.responseHeaders.match(/Content-Type:\s*(.*)/i)) != null ? _ref[1] : void 0; + contentDisposition = (_ref1 = xhr.responseHeaders.match(/Content-Disposition:\s*(.*)/i)) != null ? _ref1[1] : void 0; + return QR.handleBlob(data, contentType, contentDisposition, url); + }, + onerror: function(xhr) { + return QR.error("Can't load image."); } }); }, @@ -6067,38 +6052,45 @@ }, handleFile: function(file, index, nfiles) { var isNewPost, max, post, _ref; - if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { - max = QR.nodes.fileInput.max; - if (/^video\//.test(file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (file.size > max) { - return QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); - } - isNewPost = false; - if (nfiles === 1) { - post = QR.selected; - } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { - isNewPost = true; - post = new QR.post(); - } - return QR.checkDimensions(file, function(pass) { - if (pass) { - return post.setFile(file); - } else if (isNewPost) { - return post.rm(); - } - }); - } else if (/^text/.test(file.type)) { + if (/^text\//.test(file.type)) { if (nfiles === 1) { post = QR.selected; } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { post = new QR.post(); } - return post.pasteText(file); - } else { - return QR.error("" + file.name + ": Unsupported file type."); + post.pasteText(file); + return; } + if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) < 0) { + QR.error("" + file.name + ": Unsupported file type."); + if (nfiles !== 1) { + return; + } + } + max = QR.nodes.fileInput.max; + if (/^video\//.test(file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (file.size > max) { + QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); + if (nfiles !== 1) { + return; + } + } + isNewPost = false; + if (nfiles === 1) { + post = QR.selected; + } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { + isNewPost = true; + post = new QR.post(); + } + return QR.checkDimensions(file, function(pass) { + if (pass || nfiles === 1) { + return post.setFile(file); + } else if (isNewPost) { + return post.rm(); + } + }); }, checkDimensions: function(file, cb) { var img, video; @@ -6106,17 +6098,18 @@ img = new Image(); img.onload = (function(_this) { return function() { - var height, width; + var height, pass, width; height = img.height, width = img.width; + pass = true; if (height > QR.max_height || width > QR.max_width) { QR.error("" + file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - return cb(false); - } else if (height < QR.min_height || width < QR.min_width) { - QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - return cb(false); - } else { - return cb(true); + pass = false; } + if (height < QR.min_height || width < QR.min_width) { + QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + pass = false; + } + return cb(pass); }; })(this); return img.src = URL.createObjectURL(file); @@ -6124,37 +6117,47 @@ video = $.el('video'); $.on(video, 'loadedmetadata', (function(_this) { return function() { - var duration, max_height, max_width, videoHeight, videoWidth; + var duration, max_height, max_width, pass, videoHeight, videoWidth; if (cb == null) { return; } videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration; max_height = Math.min(QR.max_height, QR.max_height_video); max_width = Math.min(QR.max_width, QR.max_width_video); + pass = true; if (videoHeight > max_height || videoWidth > max_width) { QR.error("" + file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - cb(false); - } else if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - cb(false); - } else if (!isFinite(video.duration)) { - QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); - cb(false); - } else if (duration > QR.max_duration_video) { - QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - cb(false); - } else { - cb(true); + pass = false; } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + pass = false; + } + if (!isFinite(video.duration)) { + QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); + pass = false; + } + if (duration > QR.max_duration_video) { + QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + pass = false; + } + if (video.mozHasAudio) { + QR.error("" + file.name + ": Audio not allowed"); + pass = false; + } + cb(pass); return cb = null; }; })(this)); $.on(video, 'error', (function(_this) { return function() { + var _ref; if (cb == null) { return; } - QR.error("" + file.name + ": Video appears corrupt"); + if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { + QR.error("" + file.name + ": Video appears corrupt"); + } cb(false); return cb = null; }; @@ -6244,7 +6247,7 @@ } rules = $('ul.rules').textContent.trim(); QR.min_width = QR.min_height = 1; - QR.max_width = QR.max_height = 5000; + QR.max_width = QR.max_height = 10000; try { _ref1 = rules.match(/.+smaller than (\d+)x(\d+).+/), _ = _ref1[0], QR.min_width = _ref1[1], QR.min_height = _ref1[2]; _ref2 = rules.match(/.+greater than (\d+)x(\d+).+/), _ = _ref2[0], QR.max_width = _ref2[1], QR.max_height = _ref2[2]; diff --git a/builds/crx.crx b/builds/crx.crx index 36e7e8a2e..76995c488 100644 Binary files a/builds/crx.crx and b/builds/crx.crx differ diff --git a/builds/crx/manifest.json b/builds/crx/manifest.json index 57213eab9..b79876390 100755 --- a/builds/crx/manifest.json +++ b/builds/crx/manifest.json @@ -1,6 +1,6 @@ { "name": "4chan X", - "version": "1.7.24", + "version": "1.7.25", "manifest_version": 2, "description": "Cross-browser userscript for maximum lurking on 4chan.", "icons": { diff --git a/builds/crx/script.js b/builds/crx/script.js index 1f1feafe0..a7589e09a 100644 --- a/builds/crx/script.js +++ b/builds/crx/script.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript /* -* 4chan X - Version 1.7.24 - 2014-04-30 +* 4chan X - Version 1.7.25 - 2014-05-01 * * Licensed under the MIT license. * https://github.com/ccd0/4chan-x/blob/master/LICENSE @@ -348,7 +348,7 @@ doc = d.documentElement; g = { - VERSION: '1.7.24', + VERSION: '1.7.25', NAMESPACE: '4chan X.', boards: {} }; @@ -5681,7 +5681,7 @@ }; QR = { - mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/x-shockwave-flash', 'video/webm', ''], + mimeTypes: ['image/jpeg', 'image/png', 'image/gif', 'application/pdf', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash', 'video/webm'], init: function() { var sc; if (!Conf['Quick Reply']) { @@ -6034,32 +6034,18 @@ QR.handleFiles(files); return $.addClass(QR.nodes.el, 'dump'); }, - handleBlob: function(urlBlob, header, url) { - var blob, end, endnl, endsc, mime, name, name_end, name_start, start, _ref; - name = url.substr(url.lastIndexOf('/') + 1, url.length); - start = header.indexOf("Content-Type: ") + 14; - endsc = header.substr(start, header.length).indexOf(";"); - endnl = header.substr(start, header.length).indexOf("\n") - 1; - end = endnl; - if (endsc !== -1 && endsc < endnl) { - end = endsc; + handleBlob: function(urlBlob, contentType, contentDisposition, url) { + var blob, match, mime, name, _ref, _ref1, _ref2; + name = (_ref = url.match(/([^\/]+)\/*$/)) != null ? _ref[1] : void 0; + mime = (contentType != null ? contentType.match(/[^;]*/)[0] : void 0) || 'application/octet-stream'; + match = (contentDisposition != null ? (_ref1 = contentDisposition.match(/\bfilename\s*=\s*"((\\"|[^"])+)"/i)) != null ? _ref1[1] : void 0 : void 0) || (contentType != null ? (_ref2 = contentType.match(/\bname\s*=\s*"((\\"|[^"])+)"/i)) != null ? _ref2[1] : void 0 : void 0); + if (match) { + name = match.replace(/\\"/g, '"'); } - mime = header.substr(start, end); blob = new Blob([urlBlob], { type: mime }); - blob.name = url.substr(url.lastIndexOf('/') + 1, url.length); - name_start = header.indexOf('name="') + 6; - if (name_start - 6 !== -1) { - name_end = header.substr(name_start, header.length).indexOf('"'); - blob.name = header.substr(name_start, name_end); - } - if (blob.type === null) { - return QR.error("Unsupported file type."); - } - if (_ref = blob.type, __indexOf.call(QR.mimeTypes, _ref) < 0) { - return QR.error("Unsupported file type."); - } + blob.name = name; return QR.handleFiles([blob]); }, handleUrl: function() { @@ -6072,16 +6058,19 @@ xhr.open('GET', url, true); xhr.responseType = 'blob'; xhr.onload = function(e) { + var contentDisposition, contentType; if (this.readyState === this.DONE && xhr.status === 200) { - QR.handleBlob(this.response, this.getResponseHeader('Content-Type'), url); + contentType = this.getResponseHeader('Content-Type'); + contentDisposition = this.getResponseHeader('Content-Disposition'); + return QR.handleBlob(this.response, contentType, contentDisposition, url); } else { - QR.error("Can't load image."); + return QR.error("Can't load image."); } }; xhr.onerror = function(e) { - QR.error("Can't load image."); + return QR.error("Can't load image."); }; - xhr.send(); + return xhr.send(); }, handleFiles: function(files) { var file, i, _i, _len; @@ -6103,38 +6092,45 @@ }, handleFile: function(file, index, nfiles) { var isNewPost, max, post, _ref; - if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { - max = QR.nodes.fileInput.max; - if (/^video\//.test(file.type)) { - max = Math.min(max, QR.max_size_video); - } - if (file.size > max) { - return QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); - } - isNewPost = false; - if (nfiles === 1) { - post = QR.selected; - } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { - isNewPost = true; - post = new QR.post(); - } - return QR.checkDimensions(file, function(pass) { - if (pass) { - return post.setFile(file); - } else if (isNewPost) { - return post.rm(); - } - }); - } else if (/^text/.test(file.type)) { + if (/^text\//.test(file.type)) { if (nfiles === 1) { post = QR.selected; } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).com) { post = new QR.post(); } - return post.pasteText(file); - } else { - return QR.error("" + file.name + ": Unsupported file type."); + post.pasteText(file); + return; } + if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) < 0) { + QR.error("" + file.name + ": Unsupported file type."); + if (nfiles !== 1) { + return; + } + } + max = QR.nodes.fileInput.max; + if (/^video\//.test(file.type)) { + max = Math.min(max, QR.max_size_video); + } + if (file.size > max) { + QR.error("" + file.name + ": File too large (file: " + ($.bytesToString(file.size)) + ", max: " + ($.bytesToString(max)) + ")."); + if (nfiles !== 1) { + return; + } + } + isNewPost = false; + if (nfiles === 1) { + post = QR.selected; + } else if (index !== 0 || (post = QR.posts[QR.posts.length - 1]).file) { + isNewPost = true; + post = new QR.post(); + } + return QR.checkDimensions(file, function(pass) { + if (pass || nfiles === 1) { + return post.setFile(file); + } else if (isNewPost) { + return post.rm(); + } + }); }, checkDimensions: function(file, cb) { var img, video; @@ -6142,17 +6138,18 @@ img = new Image(); img.onload = (function(_this) { return function() { - var height, width; + var height, pass, width; height = img.height, width = img.width; + pass = true; if (height > QR.max_height || width > QR.max_width) { QR.error("" + file.name + ": Image too large (image: " + height + "x" + width + "px, max: " + QR.max_height + "x" + QR.max_width + "px)"); - return cb(false); - } else if (height < QR.min_height || width < QR.min_width) { - QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - return cb(false); - } else { - return cb(true); + pass = false; } + if (height < QR.min_height || width < QR.min_width) { + QR.error("" + file.name + ": Image too small (image: " + height + "x" + width + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + pass = false; + } + return cb(pass); }; })(this); return img.src = URL.createObjectURL(file); @@ -6160,37 +6157,43 @@ video = $.el('video'); $.on(video, 'loadedmetadata', (function(_this) { return function() { - var duration, max_height, max_width, videoHeight, videoWidth; + var duration, max_height, max_width, pass, videoHeight, videoWidth; if (cb == null) { return; } videoHeight = video.videoHeight, videoWidth = video.videoWidth, duration = video.duration; max_height = Math.min(QR.max_height, QR.max_height_video); max_width = Math.min(QR.max_width, QR.max_width_video); + pass = true; if (videoHeight > max_height || videoWidth > max_width) { QR.error("" + file.name + ": Video too large (video: " + videoHeight + "x" + videoWidth + "px, max: " + max_height + "x" + max_width + "px)"); - cb(false); - } else if (videoHeight < QR.min_height || videoWidth < QR.min_width) { - QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); - cb(false); - } else if (!isFinite(video.duration)) { - QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); - cb(false); - } else if (duration > QR.max_duration_video) { - QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); - cb(false); - } else { - cb(true); + pass = false; } + if (videoHeight < QR.min_height || videoWidth < QR.min_width) { + QR.error("" + file.name + ": Video too small (video: " + videoHeight + "x" + videoWidth + "px, min: " + QR.min_height + "x" + QR.min_width + "px)"); + pass = false; + } + if (!isFinite(video.duration)) { + QR.error("" + file.name + ": Video lacks duration metadata (try remuxing)"); + pass = false; + } + if (duration > QR.max_duration_video) { + QR.error("" + file.name + ": Video too long (video: " + duration + "s, max: " + QR.max_duration_video + "s)"); + pass = false; + } + cb(pass); return cb = null; }; })(this)); $.on(video, 'error', (function(_this) { return function() { + var _ref; if (cb == null) { return; } - QR.error("" + file.name + ": Video appears corrupt"); + if (_ref = file.type, __indexOf.call(QR.mimeTypes, _ref) >= 0) { + QR.error("" + file.name + ": Video appears corrupt"); + } cb(false); return cb = null; }; @@ -6280,7 +6283,7 @@ } rules = $('ul.rules').textContent.trim(); QR.min_width = QR.min_height = 1; - QR.max_width = QR.max_height = 5000; + QR.max_width = QR.max_height = 10000; try { _ref1 = rules.match(/.+smaller than (\d+)x(\d+).+/), _ = _ref1[0], QR.min_width = _ref1[1], QR.min_height = _ref1[2]; _ref2 = rules.match(/.+greater than (\d+)x(\d+).+/), _ = _ref2[0], QR.max_width = _ref2[1], QR.max_height = _ref2[2]; diff --git a/builds/updates.xml b/builds/updates.xml index d6680a96f..50314e1e8 100644 --- a/builds/updates.xml +++ b/builds/updates.xml @@ -1,7 +1,7 @@ - + diff --git a/package.json b/package.json index 7bb1ba6c0..fda27f974 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "4chan-X", - "version": "1.7.24", + "version": "1.7.25", "description": "Cross-browser userscript for maximum lurking on 4chan.", "meta": { "name": "4chan X",