Check out Sunborn's two newly announced games (official English titles pending): Girls' Frontline: Blue Butterfly Contract and Reverse Collapse: F !
You don't need an account to join in. Learn how to contribute, browse Bounties and join our Discord server.

MediaWiki:Gadget-md5hasher.js: Difference between revisions

Welcome to IOP Wiki. This website is maintained by the Girls' Frontline community and is free to edit by anyone.
Jump to navigation Jump to search
Adding StatsGraph to utilities. Does 'this' even work in this scope?
m Parameterize StatsGraph for target container
 
Line 272: Line 272:
},
},
buildGraph: function(dataComplete) {
buildGraph: function(dataComplete, container) {
  var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  var svgNS = svg.namespaceURI;
  var svgNS = svg.namespaceURI;
Line 368: Line 368:
   
   
  svg.appendChild(gDrawing);
  svg.appendChild(gDrawing);
 
  var container = document.currentScript.parentNode;
  container.appendChild(svg);
  container.appendChild(svg);
}
}
};
};

Latest revision as of 19:20, 19 July 2025

window.gfUtils = window.gfUtils || {};

(function(globSpace){'use strict';function safe_add(x,y){var lsw=(x&0xFFFF)+(y&0xFFFF),msw=(x>>16)+(y>>16)+(lsw>>16);return(msw<<16)|(lsw&0xFFFF)}
function bit_rol(num,cnt){return(num<<cnt)|(num>>>(32-cnt))}
function md5_cmn(q,a,b,x,s,t){return safe_add(bit_rol(safe_add(safe_add(a,q),safe_add(x,t)),s),b)}
function md5_ff(a,b,c,d,x,s,t){return md5_cmn((b&c)|((~b)&d),a,b,x,s,t)}
function md5_gg(a,b,c,d,x,s,t){return md5_cmn((b&d)|(c&(~d)),a,b,x,s,t)}
function md5_hh(a,b,c,d,x,s,t){return md5_cmn(b^c^d,a,b,x,s,t)}
function md5_ii(a,b,c,d,x,s,t){return md5_cmn(c^(b|(~d)),a,b,x,s,t)}
function binl_md5(x,len){x[len>>5]|=0x80<<((len)%32);x[(((len+64)>>>9)<<4)+14]=len;var i,olda,oldb,oldc,oldd,a=1732584193,b=-271733879,c=-1732584194,d=271733878;for(i=0;i<x.length;i+=16){olda=a;oldb=b;oldc=c;oldd=d;a=md5_ff(a,b,c,d,x[i],7,-680876936);d=md5_ff(d,a,b,c,x[i+1],12,-389564586);c=md5_ff(c,d,a,b,x[i+2],17,606105819);b=md5_ff(b,c,d,a,x[i+3],22,-1044525330);a=md5_ff(a,b,c,d,x[i+4],7,-176418897);d=md5_ff(d,a,b,c,x[i+5],12,1200080426);c=md5_ff(c,d,a,b,x[i+6],17,-1473231341);b=md5_ff(b,c,d,a,x[i+7],22,-45705983);a=md5_ff(a,b,c,d,x[i+8],7,1770035416);d=md5_ff(d,a,b,c,x[i+9],12,-1958414417);c=md5_ff(c,d,a,b,x[i+10],17,-42063);b=md5_ff(b,c,d,a,x[i+11],22,-1990404162);a=md5_ff(a,b,c,d,x[i+12],7,1804603682);d=md5_ff(d,a,b,c,x[i+13],12,-40341101);c=md5_ff(c,d,a,b,x[i+14],17,-1502002290);b=md5_ff(b,c,d,a,x[i+15],22,1236535329);a=md5_gg(a,b,c,d,x[i+1],5,-165796510);d=md5_gg(d,a,b,c,x[i+6],9,-1069501632);c=md5_gg(c,d,a,b,x[i+11],14,643717713);b=md5_gg(b,c,d,a,x[i],20,-373897302);a=md5_gg(a,b,c,d,x[i+5],5,-701558691);d=md5_gg(d,a,b,c,x[i+10],9,38016083);c=md5_gg(c,d,a,b,x[i+15],14,-660478335);b=md5_gg(b,c,d,a,x[i+4],20,-405537848);a=md5_gg(a,b,c,d,x[i+9],5,568446438);d=md5_gg(d,a,b,c,x[i+14],9,-1019803690);c=md5_gg(c,d,a,b,x[i+3],14,-187363961);b=md5_gg(b,c,d,a,x[i+8],20,1163531501);a=md5_gg(a,b,c,d,x[i+13],5,-1444681467);d=md5_gg(d,a,b,c,x[i+2],9,-51403784);c=md5_gg(c,d,a,b,x[i+7],14,1735328473);b=md5_gg(b,c,d,a,x[i+12],20,-1926607734);a=md5_hh(a,b,c,d,x[i+5],4,-378558);d=md5_hh(d,a,b,c,x[i+8],11,-2022574463);c=md5_hh(c,d,a,b,x[i+11],16,1839030562);b=md5_hh(b,c,d,a,x[i+14],23,-35309556);a=md5_hh(a,b,c,d,x[i+1],4,-1530992060);d=md5_hh(d,a,b,c,x[i+4],11,1272893353);c=md5_hh(c,d,a,b,x[i+7],16,-155497632);b=md5_hh(b,c,d,a,x[i+10],23,-1094730640);a=md5_hh(a,b,c,d,x[i+13],4,681279174);d=md5_hh(d,a,b,c,x[i],11,-358537222);c=md5_hh(c,d,a,b,x[i+3],16,-722521979);b=md5_hh(b,c,d,a,x[i+6],23,76029189);a=md5_hh(a,b,c,d,x[i+9],4,-640364487);d=md5_hh(d,a,b,c,x[i+12],11,-421815835);c=md5_hh(c,d,a,b,x[i+15],16,530742520);b=md5_hh(b,c,d,a,x[i+2],23,-995338651);a=md5_ii(a,b,c,d,x[i],6,-198630844);d=md5_ii(d,a,b,c,x[i+7],10,1126891415);c=md5_ii(c,d,a,b,x[i+14],15,-1416354905);b=md5_ii(b,c,d,a,x[i+5],21,-57434055);a=md5_ii(a,b,c,d,x[i+12],6,1700485571);d=md5_ii(d,a,b,c,x[i+3],10,-1894986606);c=md5_ii(c,d,a,b,x[i+10],15,-1051523);b=md5_ii(b,c,d,a,x[i+1],21,-2054922799);a=md5_ii(a,b,c,d,x[i+8],6,1873313359);d=md5_ii(d,a,b,c,x[i+15],10,-30611744);c=md5_ii(c,d,a,b,x[i+6],15,-1560198380);b=md5_ii(b,c,d,a,x[i+13],21,1309151649);a=md5_ii(a,b,c,d,x[i+4],6,-145523070);d=md5_ii(d,a,b,c,x[i+11],10,-1120210379);c=md5_ii(c,d,a,b,x[i+2],15,718787259);b=md5_ii(b,c,d,a,x[i+9],21,-343485551);a=safe_add(a,olda);b=safe_add(b,oldb);c=safe_add(c,oldc);d=safe_add(d,oldd)}
return[a,b,c,d]}
function binl2rstr(input){var i,output='';for(i=0;i<input.length*32;i+=8){output+=String.fromCharCode((input[i>>5]>>>(i%32))&0xFF)}
return output}
function rstr2binl(input){var i,output=[];output[(input.length>>2)-1]=undefined;for(i=0;i<output.length;i+=1){output[i]=0}
for(i=0;i<input.length*8;i+=8){output[i>>5]|=(input.charCodeAt(i/8)&0xFF)<<(i%32)}
return output}
function rstr_md5(s){return binl2rstr(binl_md5(rstr2binl(s),s.length*8))}
function rstr_hmac_md5(key,data){var i,bkey=rstr2binl(key),ipad=[],opad=[],hash;ipad[15]=opad[15]=undefined;if(bkey.length>16){bkey=binl_md5(bkey,key.length*8)}
for(i=0;i<16;i+=1){ipad[i]=bkey[i]^0x36363636;opad[i]=bkey[i]^0x5C5C5C5C}
hash=binl_md5(ipad.concat(rstr2binl(data)),512+data.length*8);return binl2rstr(binl_md5(opad.concat(hash),512+128))}
function rstr2hex(input){var hex_tab='0123456789abcdef',output='',x,i;for(i=0;i<input.length;i+=1){x=input.charCodeAt(i);output+=hex_tab.charAt((x>>>4)&0x0F)+hex_tab.charAt(x&0x0F)}
return output}
function str2rstr_utf8(input){return unescape(encodeURIComponent(input))}
function raw_md5(s){return rstr_md5(str2rstr_utf8(s))}
function hex_md5(s){return rstr2hex(raw_md5(s))}
function raw_hmac_md5(k,d){return rstr_hmac_md5(str2rstr_utf8(k),str2rstr_utf8(d))}
function hex_hmac_md5(k,d){return rstr2hex(raw_hmac_md5(k,d))}
globSpace.md5=function(string,key,raw){if(!key){if(!raw){return hex_md5(string)}else{return raw_md5(string)}}
if(!raw){return hex_hmac_md5(key,string)}else{return raw_hmac_md5(key,string)}}}(window.gfUtils))

window.gfUtils.createWikiPathPart = function createPathPart(filename) {
  var hash = window.gfUtils.md5(decodeURIComponent(filename));
  return hash[0] + "/" + hash[0] + hash[1] + "/";
};

var createSliderButtonCounter = 0;
window.gfUtils.createSliderButton = function createSliderButton(iconUrl, eventHandler) {


  var idForThisButton = "dormSliderIdent" + createSliderButtonCounter;
  createSliderButtonCounter = createSliderButtonCounter + 1;

  var dormInput = $('<input></input>');
  dormInput.attr('type', "checkbox");
  dormInput.attr('value', "None");
  dormInput.attr('name', "check");
  dormInput.attr('id', idForThisButton);
  dormInput.change(eventHandler);
                
  var dormSpanOn = $('<span></span >');
  dormSpanOn.addClass('texton');
  dormSpanOn.text('ON');
                
  var dormLabel = $('<label></label>');
  dormLabel.attr('for', idForThisButton);
                
  var dormSpanOff = $('<span></span >');
  dormSpanOff.addClass('textoff');
  dormSpanOff.text('OFF');
                
  var dormSlidebutton = $('<div></div>');
  dormSlidebutton.addClass('slideButton');
  dormSlidebutton.append(dormSpanOn);
  dormSlidebutton.append(dormLabel);
  dormSlidebutton.append(dormSpanOff);
                
  var dormSwitcher = $('<div></div>');
  dormSwitcher.addClass('chibiDormSwitcher');
  dormSwitcher.append(dormInput);
  dormSwitcher.append(dormSlidebutton);
  
  return dormSwitcher;
};

window.gfUtils.base64ArrayBuffer = function base64ArrayBuffer(arrayBuffer) {
  var base64    = '';
  var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';

  var bytes         = new Uint8Array(arrayBuffer);
  var byteLength    = bytes.byteLength;
  var byteRemainder = byteLength % 3;
  var mainLength    = byteLength - byteRemainder;

  var a, b, c, d;
  var chunk;

  var i;
  // Main loop deals with bytes in chunks of 3
  for (i = 0; i < mainLength; i = i + 3) {
    // Combine the three bytes into a single integer
    chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];

    // Use bitmasks to extract 6-bit segments from the triplet
    a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18;
    b = (chunk & 258048)   >> 12; // 258048   = (2^6 - 1) << 12;
    c = (chunk & 4032)     >>  6; // 4032     = (2^6 - 1) << 6;
    d = chunk & 63              ; // 63       = 2^6 - 1;

    // Convert the raw binary segments to the appropriate ASCII encoding
    base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
  }

  // Deal with the remaining bytes and padding
  if (byteRemainder == 1) {
    chunk = bytes[mainLength];

    a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2;

    // Set the 4 least significant bits to zero
    b = (chunk & 3)   << 4; // 3   = 2^2 - 1;

    base64 += encodings[a] + encodings[b] + '==';
  } else if (byteRemainder == 2) {
    chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];

    a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10;
    b = (chunk & 1008)  >>  4; // 1008  = (2^6 - 1) << 4;

    // Set the 2 least significant bits to zero
    c = (chunk & 15)    <<  2; // 15    = 2^4 - 1;

    base64 += encodings[a] + encodings[b] + encodings[c] + '=';
  }

  return base64;
};

/* =========== Widget functions */
window.iopwidgets = window.iopwidgets || {};

/* ----------- ICSGenerator*/
window.iopwidgets.ICSGenerator = {
	/* Hashing as seen on https://stackoverflow.com/a/52171480 */
	cyrb53: function(str, seedRaw) {
	    var seed = seedRaw || 0;
	    var h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed;
	    for (var i = 0, ch; i < str.length; i++) {
	        ch = str.charCodeAt(i);
	        h1 = Math.imul(h1 ^ ch, 2654435761);
	        h2 = Math.imul(h2 ^ ch, 1597334677);
	    }
	    h1 = Math.imul(h1 ^ (h1>>>16), 2246822507) ^ Math.imul(h2 ^ (h2>>>13), 3266489909);
	    h2 = Math.imul(h2 ^ (h2>>>16), 2246822507) ^ Math.imul(h1 ^ (h1>>>13), 3266489909);
	    return 4294967296 * (2097151 & h2) + (h1>>>0);
	},

	buildIcsLink: function(name, start, end, destContainer) {
		var d= new Date();
		var currentDateString = d.getFullYear() + ("0"+(d.getMonth()+1)).slice(-2) + ("0" + d.getDate()).slice(-2) + "T"
		 + ("0" + d.getHours()).slice(-2) + ("0" + d.getMinutes()).slice(-2) + ("0" + d.getSeconds()).slice(-2);
	
		var hash = window.iopwidgets.ICSGenerator.cyrb53("" + name + start + end);
	
		var icsContent = "BEGIN:VCALENDAR\r\n";
		icsContent += "VERSION:2.0\r\n";
		icsContent += "PRODID:-//iopwiki.com//ICS Widget\r\n";
		icsContent += "CALSCALE:GREGORIAN\r\n";
		icsContent += "BEGIN:VEVENT\r\n";
		icsContent += "DTSTAMP:" + currentDateString + "\r\n";
		icsContent += "UID:" + hash + "\r\n";
		icsContent += "DTSTART;TZID=Etc/UTC:" + start + "\r\n";
		icsContent += "DTEND;TZID=Etc/UTC:" + end + "\r\n";
		icsContent += "SUMMARY:" + name + "\r\n";
		icsContent += "END:VEVENT\r\n";
		icsContent += "END:VCALENDAR\r\n";
		
		var icsLink = document.createElement("a");
		icsLink.classList.add('ics-link');
		icsLink.setAttribute("href", "javascript:void(0);");
		icsLink.setAttribute("target", "_blank");
		icsLink.setAttribute("rel", "noopener");
		icsLink.setAttribute("tooltip", "Download iCal file");
		icsLink.setAttribute("download", "event.ics");
		icsLink.addEventListener('click', function(e) {
			var uriContent = "data:text/calendar," + encodeURIComponent(icsContent);
			e.target.href = uriContent;
		});
		
		var visibleText = document.createTextNode("Download iCal file");
		icsLink.appendChild(visibleText);
		
		destContainer.appendChild(icsLink);
	}
};

/* ---------- NavboxPopulizer*/
window.iopwidgets.NavboxPopulizer = {
	handlePopulize: function(e, targetList, server) {
      e.preventDefault();
      
      var element = $(e.target);
      var table = element.closest('table');
      
      var addresstocall = "/api.php?action=parse&page=Template:Navbox/" + targetList + "&format=json";
      // for old navbox calls
      if (server != "") {
        addresstocall = "/api.php?action=parse&page=Template:" + targetList + "/list/" + server + "&format=json";
      }
      
      $.getJSON(addresstocall)
        .done(function( json ) {
          table.find(".navboxlist").remove();

          var dataToInsert = json.parse.text["*"];
          
          var cell = $("<td></td>");
          cell.append(dataToInsert);
          
          var row = $("<tr></tr>");
          row.addClass('navboxlist');
          row.append(cell);
          
          table.find("tbody").append(row);
          table.removeClass("loading");
        })
        .fail(function( jqxhr, textStatus, error ) {
          table.removeClass("loading");
          console.log("Request Failed", textStatus, error);
        });
    }	
};

/* ---------- StatTable*/
window.iopwidgets.StatTable = {
	swap_costume: function() {
        costumeSelection = document.getElementById("costumeSelection").value;

        $("#fullart a").attr("href", costumeSelection);
        $("#fullart a img").attr("src", costumeSelection);
        $("#fullart a img").attr("alt", costumeSelection);
        //$("#fullart a img").attr("srcset", "/wiki/Special:Redirect/file/Springfield" + costumeSelection + ".png 1.5x, /wiki/Special:Redirect/file/Springfield" + costumeSelection + ".png 2x");
        $(".tdoll_chibi").attr("src", "/wiki/Special:Redirect/file/Springfield" + costumeSelection + "_S.png");
        
        // As we change the link, we have to update the Thumb-Cache of the Media Viewer
        // Clear up the thumbs cache
        if (mv && mv.mmv && mv.mmv.bootstrap && mv.mmv.bootstrap.viewer) {
          mw.mmv.bootstrap.thumbs = [];
          // Search for all thumbs
          mw.mmv.bootstrap.processThumbs($("#content"));
          // Re-Init the viewer with the new thumbs
          mw.mmv.bootstrap.viewer.initWithThumbs(mw.mmv.bootstrap.thumbs);
        }
	}
};

/* ---------- StatsGraph*/
window.iopwidgets.StatsGraph = {
	calcCoordinate: function(degree, min, max, val) {
	  var oldX = 0;
	  var oldY = (max-min) == 0 ? 0 : -(300 / (max-min)) * (val - min);
	  
	  if (degree == 0) {
	    return [oldX, Math.floor(oldY)];
	  }
	  
	  var rotate = (-degree * Math.PI) / 180;
	  
	  var newX = oldX*Math.cos(rotate)+oldY*Math.sin(rotate);
	  var newY = oldY*Math.cos(rotate)+oldX*Math.sin(rotate);
	  return [Math.floor(newX), Math.round(newY)];
	},
	
	buildPolygonString: function(data) {
	  var ret = "";
	  var degreeSpacing = 360 / data.length;
	  for (var i=0;i<data.length;i++) {
	    var coord = this.calcCoordinate(degreeSpacing*i, data[i].min, data[i].max, data[i].value);
	    ret += coord[0] + "," + coord[1] + " ";
	  }
	  ret = ret.trim();
	  return ret;
	},
	
	buildGraph: function(dataComplete, container) {
	  var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
	  var svgNS = svg.namespaceURI;
	  var svgLinkNS = "http://www.w3.org/1999/xlink";
	  svg.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", svgLinkNS);
	  svg.setAttribute('viewBox', "0 0 800 800");
	  svg.setAttribute('preserveAspectRatio', "xMidyMid meet");
	  svg.setAttribute('width', "300px");
	  svg.setAttribute('height', "auto");
	  svg.setAttribute('version', "1.1");
	  
	  /* This pretty much defines the base net lines */
	  var defs = document.createElementNS(svgNS, 'defs');
	  
	  /* Wedge id has to be unique */
	  var wedgeId = "wedge-" + 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
	    var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
	    return v.toString(16);
	  });
	  
	  var wedge = document.createElementNS(svgNS, 'g');
	  wedge.setAttribute('id', wedgeId);
	  
	  var directionCount = dataComplete[0].data.length;
	  var degreeSpacing = 360 / directionCount;
	  
	  var radialLine = document.createElementNS(svgNS, 'line');
	  radialLine.setAttribute('class', 'radial');
	  radialLine.setAttribute('y2', -325);
	  wedge.appendChild(radialLine);
	  
	  for (var lineIdx=1;lineIdx<5;lineIdx++) {
	    var orientationLine = document.createElementNS(svgNS, 'line');
	    var lineDistance = lineIdx * -75;
	    var rotate = (degreeSpacing * Math.PI) / 180;
	    orientationLine.setAttribute('y1', lineDistance);
	    orientationLine.setAttribute('x2', lineDistance*Math.sin(rotate));
	    orientationLine.setAttribute('y2', lineDistance*Math.cos(rotate));
	    if (lineIdx % 2 == 0) {
	      orientationLine.setAttribute('class', 'emphased');
	    }
	    wedge.appendChild(orientationLine);
	  }
	  defs.appendChild(wedge);
	  svg.appendChild(defs);
	  
	  // Now start drawing
	  var gDrawing = document.createElementNS(svgNS, 'g');
	  gDrawing.setAttribute('transform', 'translate(400 400)');
	  
	  for (var dataIdx=0; dataIdx<directionCount; dataIdx++) {
	    var propertyLine = document.createElementNS(svgNS, 'use');
	    propertyLine.setAttributeNS(svgLinkNS, "href", "#" + wedgeId);
	    propertyLine.setAttribute('transform', "rotate(" + (degreeSpacing * dataIdx) + ")");
	    gDrawing.appendChild(propertyLine );
	  }
	  
	  for (var dataIdx=0; dataIdx<dataComplete.length; dataIdx++) {
	    var polygonParams = dataComplete[dataIdx];
	    var datapresentation = document.createElementNS(svgNS, 'polygon');
	    
	    if ('title' in polygonParams) {
	      var title = document.createElementNS(svgNS, 'title');
	      title.appendChild(document.createTextNode(polygonParams.title));
	      datapresentation.appendChild(title);
	    }
	    
	    if (('fill' in polygonParams) || ('stroke' in polygonParams)) {
	      if ('fill' in polygonParams) datapresentation.setAttribute('fill', polygonParams.fill);
	      if ('stroke' in polygonParams) datapresentation.setAttribute('stroke', polygonParams.stroke);
	    } else {
	      datapresentation.setAttribute('class', polygonParams.class ? polygonParams.class : "graph-orange");
	    }
	    datapresentation.setAttribute('points', this.buildPolygonString(polygonParams.data));
	    gDrawing.appendChild(datapresentation);
	    
	    for (var labelIdx=0; labelIdx<polygonParams.data.length; labelIdx++) {
	      var polygonCornerData = polygonParams.data[labelIdx];
	      var rotate = (-degreeSpacing * labelIdx * Math.PI) / 180;
	      
	      var label = document.createElementNS(svgNS, 'text');
	      label.setAttribute('x', -340*Math.sin(rotate));
	      label.setAttribute('y', -340*Math.cos(rotate));
	      label.setAttribute('title', titleText);
	      label.appendChild(document.createTextNode(polygonCornerData.label));
	
	      var titleText = "" + polygonCornerData.min + " <= " + polygonCornerData.value + " <= " + polygonCornerData.max;
	      var title = document.createElementNS(svgNS, 'title');
	      title.appendChild(document.createTextNode(titleText));
	      label.appendChild(title);
	      
	      gDrawing.appendChild(label);
	    }
	  }
	  
	  svg.appendChild(gDrawing);

	  container.appendChild(svg);
	}
};