User:Rillke/fastTransfer.js
Jump to navigation
Jump to search
Note: After saving, you have to bypass your browser's cache to see the changes. Internet Explorer: press Ctrl-F5, Mozilla: hold down Shift while clicking Reload (or press Ctrl-Shift-R), Opera/Konqueror: press F5, Safari: hold down Shift + Alt while clicking Reload, Chrome: hold down Shift while clicking Reload.
Documentation for this user script can be added at User:Rillke/fastTransfer. |
/** Please always jshint validate.
* Script allows transferring of files from other wikis without having them to save somewhere on your hard drive
* Only works in Mozilla Firefox (because it makes use of sendAsBinary) and possibly Chrome (using FormData)
**/
var targetFileName = 'File:TestRillkeXwd2.jpg',
sourceFileURL = '',
sourceFile = 'File:Calypte Anna DSC 0038.jpg',
text = "",
comment = '',
lastUploader;
var APIURL = mw.util.wikiScript('api'),
MPB = '----------rillkesuploadscript' + Math.random();
function firstItem(o) {
for (var i in o) {
if (o.hasOwnProperty(i)) {
return o[i];
}
}
}
function firstItemName(o) {
for (var i in o) {
if (o.hasOwnProperty(i)) {
return i;
}
}
}
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
// Firefox does not allow setting file titles for "blob" data. That's why we have to send it as binary.
var clnt = $.client.profile();
if ("firefox" === clnt.name && clnt.versionNumber < 22) {
var MultipartMessage = function() {
this.msg = '';
};
MultipartMessage.fn = MultipartMessage.prototype;
$.extend(MultipartMessage.fn, {
createPart: function(param, data, ContentType, ContentTransferEncoding, ContentDisposition) {
var p = '--' + MPB + '\n';
if (!ContentDisposition) {
p += 'Content-Disposition: form-data; name=\"' + param + '\"\n';
} else {
p += 'Content-Disposition: ' + ContentDisposition + '\n';
}
p += 'Content-Type: ' + ContentType + '\n';
p += 'Content-Transfer-Encoding: ' + ContentTransferEncoding + '\n';
return [p, '\n', data, '\n'].join('');
},
appendPart: function(param, data, ContentType, ContentTransferEncoding, ContentDisposition) {
if (!ContentType) data = encode_utf8(data);
this.msg += this.createPart(param, data, (ContentType || "text/plain; charset=UTF-8"), (ContentTransferEncoding || "8bit"), ContentDisposition);
},
send: function() {
var msg = [this.msg, '--', MPB, '--', '\n'].join('');
var req = new XMLHttpRequest();
req.onreadystatechange = function(r) {
if (4 !== req.readyState) return;
console.log(req.responseText);
};
req.open('POST', APIURL);
req.setRequestHeader('Content-Type', 'multipart/form-data; charset=UTF-8; boundary=' + MPB);
req.sendAsBinary(msg);
}
});
} else {
// We can use FormData in Chrome and Safari
var MultipartMessage = function() {
this.fd = new FormData();
};
MultipartMessage.fn = MultipartMessage.prototype;
$.extend(MultipartMessage.fn, {
appendPart: function(param, data, ContentType, ContentTransferEncoding, ContentDisposition) {
if (ContentDisposition) {
var bl = new Blob([data], { type: ContentType });
this.fd.append(param, bl, ContentDisposition.match(/filename\=\"([^"]+)\"/)[1]);
} else {
this.fd.append(param, data);
}
},
send: function() {
var req = new XMLHttpRequest();
req.open('POST', APIURL);
req.send(this.fd);
req.onreadystatechange = function(r) {
if (4 !== req.readyState) return;
console.log(req.responseText);
};
}
});
}
var _gotToken = function(t, f) {
targetFileName = targetFileName.replace(/^(?:File|Image):/, '');
if (!t) console.log('Error. Unable to get token.');
var mpm = new MultipartMessage();
mpm.appendPart('format', 'json');
mpm.appendPart('action', 'upload');
mpm.appendPart('filename', targetFileName);
mpm.appendPart('comment', comment);
mpm.appendPart('text', text);
mpm.appendPart('file', f, 'application/octet-stream', 'binary', 'attachment; name=\"file\"; filename=\"' + targetFileName + '\"');
//mpm.appendPart('url', u );
mpm.appendPart('ignorewarnings', 1);
mpm.appendPart('token', t);
mpm.send();
};
var _gotURL = function() {
comment = comment || ('Copying from ' + (sourceFile ? '[[' + sourceFile + ']]' : sourceFileURL) + (lastUploader ? ' (uploaded by [[User:' + lastUploader + ']])' : '') + ' using [[User:Rillke/Down\'NUp|Down\'NUp]].');
var _gotFile = function(f) {
if (!f) return console.log('Error. Unable to get file.');
$.get(APIURL, {
format: 'json',
action: 'tokens'
}, function(r) {
_gotToken(r.tokens.edittoken, f);
});
};
$.ajax({
url: sourceFileURL,
beforeSend: function (xhr) {
xhr.overrideMimeType("text/plain; charset=x-user-defined");
}
}).done(function (d) {
// Some more sophisticated stuff avoiding killing performance with memory allocations and thousands of function invocations
var f = '',
len = d.length,
buff = 1018, // You can't apply huge arrays to functions!
arrCC = Array(Math.min(buff, len)),
arrF = Array(Math.ceil(len/buff));
// Remove junk-high-order-bytes
for (var i = 0, j = 0, z = 0; i < len; i++) {
arrCC[j] = (d.charCodeAt(i) & 0xff);
j++;
if (0 === (j % buff)) {
// Convert char codes to chars
arrF[z] = String.fromCharCode.apply(null, arrCC);
// Empty the char code array
arrCC = Array(Math.min(buff, len - i - 1));
z++;
j = 0;
}
}
if (j !== 0) arrF[z + 1] = String.fromCharCode.apply(null, arrCC);
f = arrF.join('');
_gotFile(f);
});
};
if (sourceFile) {
sourceFile = 'File:' + sourceFile.replace(/^(?:File|Image):/, '');
mw.loader.using('ext.gadget.libAPI', function() {
mw.libs.commons.api.query({
action: 'query',
titles: sourceFile,
prop: 'revisions|imageinfo',
iiprop: 'url|user',
rvprop: 'content'
}, {
url: APIURL,
method: 'POST',
cb: function(r) {
var pg = firstItem(r.query.pages);
text = text || pg.revisions[0]['*'];
sourceFileURL = sourceFileURL || pg.imageinfo[0].url;
lastUploader = pg.imageinfo[0].user;
_gotURL();
},
// r-result, query, text
errCb: function(t, r, q) {
}
});
});
} else if (sourceFileURL) {
_gotURL();
}