MediaWiki:Gadget-contribsrange.js

/* Special:Contributions Wildcard/CIDR lookup, version [0.1.4] Originally from: http://en.wikipedia.org/wiki/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 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: [123.123.123.0/24 ] or [123.123.123.* ] or [Willy* ].
 * 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')[0]; if(!frm.target) return;

//general optionlets independant of type of search. var opt_ns = (parseInt(frm.namespace[frm.namespace.selectedIndex].value) > -1) ? '&ucnamespace=' + frm.namespace[frm.namespace.selectedIndex].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[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/(2[4-9]|3[0-2]|16)/i ; var patternWild = /^.{3,}\*$/i ; if(frm.target.value.search(patternCIDR) == 0) { prefixContribsStartbox(frm.parentNode); var cidr = frm.target.value.match(patternCIDR)[0]; var range = cidr.match(/[^\/]\d{1,2}$/i)[0]; 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}\./)[0]; } else { cidr = cidr.match(/\d{1,3}\.\d{1,3}\./)[0]; }     var url = wgScriptPath + '/api.php?action=query&format=json&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)[0].replace(/(\.|\/)/g,''); cidr = cidr.match(/\d{1,3}\.\d{1,3}\.\d{1,3}\./)[0]; var num = Math.pow(2,32 - range); var start = oct3 - oct3 % num; var url = wgScriptPath + '/api.php?action=query&format=json&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&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')[0].appendChild(scriptElem); }

function prefixContribs(obj) { if(!obj['query'] || !obj['query']['usercontribs']) return var prog = document.getElementById('prefixcontribs-prog'); if(prog) prog.parentNode.removeChild(prog) cidr = obj['query']['usercontribs']; 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[frm.namespace.selectedIndex].value) > -1) ? '&namespace=' + frm.namespace[frm.namespace.selectedIndex].value : ''; var ts = (obj['query-continue']) ? obj['query-continue'].usercontribs.ucstart : cidr[cidr.length-1].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[i].timestamp.replace(/T[\d:]*Z/,' '))); addlinkchild(res, wgScript + '?title=Special:Contributions/' + cidr[i].user, cidr[i].user); res.appendChild(document.createTextNode(' edited ('));   addlinkchild(res, wgScript + '?title=-&curid=' + cidr[i].pageid + '&diff=' + cidr[i].revid, 'diff');    res.appendChild(document.createTextNode(') ')); addlinkchild(res, wgScript + '?title=-&curid=' + cidr[i].pageid, cidr[i].title); if(cidr[i].comment) res.appendChild(document.createTextNode(' (' + cidr[i].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[1]); } catch (e) { } }  return null; }