User:Ilmari Karonen/licensemigration.js

From Wikimedia Commons, the free media repository
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.
// do nothing unless this is an image page
if (mw.config.get('wgNamespaceNumber') == 6) {
    importScript('MediaWiki:MD5.js');

    var lmactions = {
        'relicense' : "eligible for relicensing",
        'not-eligible' : "not eligible for relicensing",
        'redundant' : "already multilicensed with CC-BY-SA 3.0",
        'needs-review' : "needing further license migration review",
        'opt-out' : "excluded from license migration by author's request"
    }; 

    // create a reasonably random 64-bit token and store it as a cookie to make creating malicious edit links harder
    var getLicenseMigrationRandomCookie = function () {
        var match = /(^|; ?)licenseMigrationRandomCookie=([0-9a-f]{16})$/.exec(document.cookie);
        if (match && match[2]) return match[2];
        var hash = hex_md5(wgUserName +"|"+ wgPageName +"|"+ window.wgTrackingToken +"|"+ (new Date ()).getTime() +"|"+ Math.random());
        hash = hash.substring(0,16).toLowerCase();  // we don't need the full hash, 64 bits should be enough
        document.cookie = "licenseMigrationRandomCookie="+hash+"; path=/";
        return hash;
    };

    if (wgAction == "edit" && /&migration=/.test(location.search)) {

        addOnloadHook(function () {
            var match = /&timestamp=([0-9]+)&migration=([^&]+)&md5=([0-9a-f]+)/.exec(location.search);
            if (!match || match.length <= 3) return alert("licensemigration.js: URL match failed.");

            var age = (new Date ()).getTime() - match[1];
            if (age > 3600000 || age < -60000) return alert("licensemigration.js: URL too old ("+age+" ms).");

            var action = decodeURIComponent(match[2]);
            if (typeof (lmactions[action]) !== 'string') return alert("licensemigration.js: Invalid action \""+action+"\".");

            var testURL = mw.config.get('wgServer') + mw.config.get('wgScriptPath') + "/index.php?title=" + encodeURIComponent(mw.config.get('wgPageName')) +
                          "&action=edit" +
                          "&timestamp=" + match[1] +
                          "&migration=" + action +
                          "&cookie=" + getLicenseMigrationRandomCookie();
            if (match[3] != hex_md5(testURL)) return alert("licensemigration.js: MD5 mismatch!");

            var editbox = document.getElementById('wpTextbox1');
            if (!editbox) return alert("licensemigration.js: Can't find edit form!");

            var summary = document.getElementById('wpSummary');
            if (summary) summary.value = "Marking file as "+lmactions[action]+".";
            var minor = document.getElementById('wpMinoredit');
            if (minor) minor.checked = true;

            var parts = editbox.value.split(/(<nowiki>.*?<\/nowiki>)/);
            if (parts.join("") != editbox.value) return alert("Your browser does not implement String.split() correctly! Aborting to avoid page corruption.\nWARNING: Any edits you've made with this script before this check was added may have caused unintended loss of text in <nowiki> tags.\nPlease check your edit history.");

            for (var i = 0; i < parts.length; i += 2) {
                parts[i] = parts[i].replace(/\{\{\s*[Ll]icense[ _]+migration\b[^{}]*\}\}\n?/g, "");  // these should never be used directly on image pages, but CommonsHelper doesn't (yet) know that
                parts[i] = parts[i].replace(/\{\{(\s*(?:self|GFDL(?:-[-a-z0-9]+)?)\s*(?:\|[^{|}]*)*)\|\s*migration\s*=[^{|}]*((?:\|[^{|}]*)*)\}\}/ig, "{"+"{$1$2}}");
            }
            var stripped = parts.join("");

            for (var i = 0; i < parts.length; i += 2)
                parts[i] = parts[i].replace(/\{\{(\s*(?:self|GFDL(?:-[-a-z0-9]+)?)\s*(?:\|[^{|}]*)*)\}\}/ig, "{"+"{$1|migration="+action+"}}");
            var edited = parts.join("");

            if (edited == stripped) return alert("Could not locate the right place to add the \"migration="+action+"\" parameter. Please add it manually.");
            if (edited == editbox.value) return;  // added successfully, but result is the same as original => probably an accidental reload or something
            editbox.value = edited;

            var submit = document.getElementById('wpSave');
            if (submit) submit.click();
        });
    }
    else {
        addOnloadHook(function () {
            var spans = document.querySelectorAll('span.license-migration-announcement-fixme');
            if (!spans || !spans.length) return;

            var baseURL = wgScriptPath + "/index.php?title=" + encodeURIComponent(mw.config.get('wgPageName')) +
                          "&action=edit" +
                          "&timestamp=" + (new Date ()).getTime() +
                          "&migration=";
            var cookie = getLicenseMigrationRandomCookie();

            var container = document.createElement('span');
            for (var action in lmactions) {
                if (spans[0].className.indexOf(action) >= 0) continue;

                var md5 = hex_md5(wgServer + baseURL + action + "&cookie=" + cookie);
                var link = document.createElement('a');
                link.href = baseURL + action + "&md5=" + md5;
                link.title = "Mark this file as "+lmactions[action]+".";
                link.appendChild(document.createTextNode(action));

                container.appendChild(document.createTextNode('['));
                container.appendChild(link);
                container.appendChild(document.createTextNode('] '));
            }
            spans[0].appendChild(document.createElement('br'));
            spans[0].appendChild(container);
        });
    }
}