// ===============================================
// User script to add a dropdown box to the admin
// block form, offering CDIR range block codes
// when blocking IPs
// ===============================================
var patternIP = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
function isIP(txt) {
var found = patternIP.exec(txt);
if (found) {
for (var i = 0; i < 4; i++) {
if (found[i] > 255) return false;
}
return true;
} else return false;
}
// =============================================
// create the dropdown box if not done already,
// and (re-)populate it with CDIR ranges based
// on the one currently in the user input box
// =============================================
function makeOptions() {
var frm = getBlockForm();
if (frm) {
var userBox = document.getElementsByName('wpTarget')[0];
if (userBox) {
var user = userBox.value;
// check if our added div already exists
var div = document.getElementById('rangeBlockSelectionDiv');
// only proceed if the current user is an IP
if (isIP(user)) {
var select = document.getElementById('rangeBlockSelector');
if (div) {
// if div has already been created: reset the
// dropdown box before repopulating it
select.innerHTML = "";
}
else {
// create the selection dropdown, inside a new
// div
div = document.createElement('div');
div.id = "rangeBlockSelectionDiv";
div.appendChild(document.createTextNode("Range block? "));
select = document.createElement('select');
// install onchange event handler on dropdown box:
select.onchange = resetUser;
select.id = "rangeBlockSelector";
div.appendChild(select);
var parent = frm.parentNode;
var sibling = frm.nextSibling;
if (sibling) {
parent.insertBefore(div, sibling)
}
else {
parent.appendChild(div);
}
}
// default value in dropdown box is single IP
var opt = document.createElement('option');
opt.value = user;
opt.innerHTML = "single IP (" + user + ")";
select.appendChild(opt);
// offer range blocks from /26 to /16
var maxMask = 26;
var minMask = 16;
for (var i = maxMask; i >= minMask; i--) {
opt = makeOption(user, i);
select.appendChild(opt);
}
// make div visible
div.style.display = null;
}
else {
// make div invisible if it exists
if (div) div.style.display = "none";
}
}
}
}
function makeOption(ip, mask) {
var parts = patternIP.exec(ip);
// turn IP string into a single 32-bit integer:
var ipVal = (parts[1] * 0x1000000) |
(parts[2] * 0x10000) |
(parts[3] * 0x100) |
parts[4];
// get the binary mask
var maskVal = Math.pow(2, (32-mask)) - 1;
var rgVal = ipVal & maskVal;
// make sure the result is treated as an unsigned integer:
if (rgVal < 0) rgVal += 0x100000000;
rgVal = (ipVal - rgVal);
// translate back into four-byte representation:
parts = [0,0,0,0];
for (i = 3; i>=0; i--) {
parts[i] = rgVal % 0x100;
rgVal -= parts[i];
rgVal = rgVal >>> 8;
}
var cdir = parts[0] + "." +
parts[1] + "." +
parts[2] + "." +
parts[3] + "/" + mask;
var size = Math.pow(2, (32-mask));
var desc = cdir + " (" + size + " IPs )";
var opt = document.createElement('option');
opt.value = cdir;
opt.innerHTML = desc;
return opt;
}
function getBlockForm() {
// the standard block form has no id, so we need to identify it
// by its action attribute
for (var i = document.forms.length - 1; i >= 0; i--) {
var frm = document.forms[i];
if (frm.action.search(/\bSpecial:Block\b/) >= 0) {
if (! frm.id) frm.id = "_myBlockForm";
document.forms._myBlockForm = frm;
return frm;
}
}
return null;
}
function resetUser() {
// Onchange event handler of the dropdown box.
// Copy selected value back into user input field.
var val = this.value;
var userBox = document.getElementsByName('wpTarget')[0];
userBox.value = val;
var act = document.forms._myBlockForm.action;
act = act.replace(/Special:Block\/.+/, "Special:Block/" + val);
document.forms._myBlockForm.action = act;
}
// install this script as an onload hook
$(function() {
// only proceed if we are on the Special:Block page
if (document.title.match(/^Block user - Wikipedia, the free encyclopedia$/)) {
var userBox = document.getElementsByName('wpTarget')[0];
if (userBox) {
// call the update function both now, and
// on later onchange events
makeOptions();
userBox.onchange = makeOptions;
}
}
});