/* Special:Contributions Wildcard/CIDR lookup, version
Originally from: http://en.wikipedia.orghttps://dictious.com/en/User:Splarka/contribsrange.js
Notes:
* Uses the API (Requires http://svn.wikimedia.org/viewvc/mediawiki?view=rev&revision=31312), which is faster than most CIDR contrib tools.
* Currently uses a GET json via <script src=""> to avoid ajax problems.
* Only currently works if submitted (or called by URL parameter, eg Special:Contributions/User).
** Checks namespace and date options in form.
* Uses: Submit any IP CIDR range /16 or from /24 to /32. Submit any string (at least 3 characters) with a suffixed asterisk.
** eg: or or .
** NOTE: Currently seems broken with spaces in the search string. Possibly a fault of the API. %20,+,_ don't work
To do:
* Sortable by address? (not useful until pagination is available).
* More like normal Special:Recentchanges (hist)(diff) blah blah blah (except talk page existence for red/blue link) with BiDi characters?
* Option to refresh on page? (not really needed, but might be more handy than onload action only).
* Respect limit in user prefs? frm.limit.value ?
*/
if(wgCanonicalSpecialPageName == 'Contributions') {
addOnloadHook(prefixContribsInit);
var prefixlimit = 500;
var frm = ''; //global
}
function prefixContribsInit() {
var show = (document.getElementById('contentSub')) ? document.getElementById('contentSub') : document.getElementById('topbar')
show.appendChild(document.createTextNode(' \u2022 Javascript-enhanced contributions lookup enabled. You may enter a CIDR range or append an asterisk to do a prefix search.'))
frm = document.getElementsByTagName('form');
if(!frm.target) return;
//general optionlets independant of type of search.
var opt_ns = (parseInt(frm.namespace.value) > -1) ? '&ucnamespace=' + frm.namespace.value : '';
var opt_ts = '';
if(queryString('ucstart')) {
opt_ts = '&ucstart=' + queryString('ucstart');
} else {
var m = '' + frm.month.selectedIndex;
var y = frm.year.value;
if(m.length == 1) m = '0' + m
if(y > 2000 && y < 2100) opt_ts = '&ucstart=' + y + '-' + m + '-01T00:00:00Z'
}
var options = opt_ns + opt_ts;
var patternCIDR = /(25|2|??)\.(25|2|??)\.(25|2|??)\.(25|2|??)\/(2|3|16)/i ;
var patternWild = /^.{3,}\*$/i ;
if(frm.target.value.search(patternCIDR) == 0) {
prefixContribsStartbox(frm.parentNode);
var cidr = frm.target.value.match(patternCIDR);
var range = cidr.match(/\d{1,2}$/i);
if(range == 24 || range == 16) {
//prefixable CIDR, lets do-er
if(range == 24) {
cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./);
} else {
cidr = cidr.match(/\d{1,3}\.\d{1,3}\./);
}
var url = wgScriptPath + '/api.php?action=query&format=json&rawcontinue=&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuserprefix=' + cidr;
prefixContribsCall(url);
} else {
//complex CIDR, lets figure it out
var oct3 = cidr.match(/\.\d{1,3}\//i).replace(/(\.|\/)/g,'');
cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./);
var num = Math.pow(2,32 - range);
var start = oct3 - oct3 % num;
var url = wgScriptPath + '/api.php?action=query&format=json&rawcontinue=&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuser=';
for(var i=start;i<=start + num;i++) {
url += '' + cidr + i;
if(i != start + num) url += '|'
}
prefixContribsCall(url);
}
} else if(frm.target.value.search(patternWild) == 0) {
//very simple wildcard, lets do-er
prefixContribsStartbox(frm.parentNode);
var prefix = frm.target.value.replace(/\*$/,'');
prefix = prefix.substr(0,1).toUpperCase() + prefix.substr(1);
var url = wgScriptPath + '/api.php?action=query&format=json&rawcontinue=&callback=prefixContribs&list=usercontribs' + options + '&uclimit=' + parseInt(prefixlimit) + '&ucuserprefix=' + prefix;
prefixContribsCall(url);
}
}
function prefixContribsStartbox(parent) {
var res = document.createElement('div');
res.setAttribute('id','results-from-CIDR');
res.style.border = '1px solid black';
res.style.padding = '.5em';
var prog = document.createElement('img');
prog.setAttribute('id','prefixcontribs-prog');
prog.setAttribute('src',stylepath + '/common/images/spinner.gif');
res.appendChild(prog);
parent.appendChild(res);
}
function prefixContribsCall(url) {
var scriptElem = document.createElement('script');
scriptElem.setAttribute('src',url);
scriptElem.setAttribute('type','text/javascript');
document.getElementsByTagName('head').appendChild(scriptElem);
}
function prefixContribs(obj) {
if(!obj || !obj) return
var prog = document.getElementById('prefixcontribs-prog');
if(prog) prog.parentNode.removeChild(prog)
cidr = obj;
var res = document.getElementById('results-from-CIDR');
res.appendChild(document.createElement('hr'));
if(cidr.length == 0) {
res.appendChild(document.createTextNode('No changes were found for this wildcard/CIDR range.'));
res.appendChild(document.createElement('hr'));
return;
}
res.appendChild(document.createTextNode(cidr.length + ' matches in the wildcard/CIDR range specified (chronologically): '));
if(cidr.length == parseInt(prefixlimit)) {
res.appendChild(document.createElement('br'));
res.appendChild(document.createTextNode('Click '));
var ns = (parseInt(frm.namespace.value) > -1) ? '&namespace=' + frm.namespace.value : '';
var ts = (obj) ? obj.usercontribs.ucstart : cidr.timestamp;
addlinkchild(res, wgScript + '?title=Special:Contributions&target=' + encodeURIComponent(frm.target.value) + ns + '&ucstart=' + ts, 'here');
res.appendChild(document.createTextNode(' to see the next ' + prefixlimit + ' results.'));
}
res.appendChild(document.createElement('hr'));
for(var i=0;i<cidr.length;i++) {
res.appendChild(document.createTextNode('\u2022 ' + cidr.timestamp.replace(/T*Z/,' ')));
addlinkchild(res, wgScript + '?title=Special:Contributions/' + cidr.user, cidr.user);
res.appendChild(document.createTextNode(' edited ('));
addlinkchild(res, wgScript + '?title=-&curid=' + cidr.pageid + '&diff=' + cidr.revid , 'diff');
res.appendChild(document.createTextNode(') '));
addlinkchild(res, wgScript + '?title=-&curid=' + cidr.pageid, cidr.title);
if(cidr.comment) res.appendChild(document.createTextNode(' (' + cidr.comment + ')'));
res.appendChild(document.createElement('br'));
}
}
function addlinkchild(obj,href,text,id,classes) {
if(!obj || !href || !text) return false;
var a = document.createElement('a');
a.setAttribute('href',href);
a.appendChild(document.createTextNode(text));
if(id) a.setAttribute('id',id);
if(classes) a.setAttribute('class',classes);
obj.appendChild(a);
}
function queryString(p) {
var re = RegExp('' + p + '=(*)');
var matches;
if (matches = re.exec(document.location)) {
try {
return decodeURI(matches);
} catch (e) {
}
}
return null;
}