Jump to content

User:Future Perfect at Sunrise/rangeblock.js

From Wikipedia, the free encyclopedia
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// ===============================================
// 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;  
      }
   }
});