860 lines
26 KiB
JavaScript
860 lines
26 KiB
JavaScript
/* jQuery functions */
|
|
|
|
(function($) {
|
|
$.fn.getCursorPosition = function() {
|
|
var input = this.get(0);
|
|
if (!input) return; // No (input) element found
|
|
if ('selectionStart' in input) {
|
|
// Standard-compliant browsers
|
|
return input.selectionStart;
|
|
} else if (document.selection) {
|
|
// IE
|
|
input.focus();
|
|
var sel = document.selection.createRange();
|
|
var selLen = document.selection.createRange().text.length;
|
|
sel.moveStart('character', -input.value.length);
|
|
return sel.text.length - selLen;
|
|
}
|
|
};
|
|
})(jQuery);
|
|
|
|
$.fn.setCursorPosition = function(pos)
|
|
{
|
|
this.each(function(index, elem)
|
|
{
|
|
if(elem.setSelectionRange) elem.setSelectionRange(pos, pos);
|
|
else if(elem.createTextRange)
|
|
{
|
|
var range = elem.createTextRange();
|
|
range.collapse(true);
|
|
range.moveEnd('character', pos);
|
|
range.moveStart('character', pos);
|
|
range.select();
|
|
}
|
|
});
|
|
return this;
|
|
};
|
|
|
|
$.prototype.addButton = function(sType, sTitle, oClickLink, sId, sButtonClass, sTmpVar)
|
|
{
|
|
$This = $(this);
|
|
var asAttributes = {id:(sId || ''), 'class':'button round'+(typeof sButtonClass != 'undefined'?' '+sButtonClass:'')};
|
|
|
|
//Link
|
|
var bLink = (typeof oClickLink == 'string');
|
|
if(bLink)
|
|
{
|
|
asAttributes.href = oClickLink;
|
|
asAttributes.target = '_blank';
|
|
}
|
|
var $Button = $('<a>', asAttributes)
|
|
.append($('<i>', {'class':'icon fa fa-c-'+sType}))
|
|
.append($('<span>', {'class':'value'}).text(sTitle))
|
|
.appendTo($This);
|
|
|
|
//Function
|
|
if(!bLink) $Button.click(function(e){e.preventDefault(); oClickLink($(this));});
|
|
|
|
//TODO delete use of tmp out of databap class context
|
|
if(typeof sTmpVar != 'undefined') databap.tmp(sTmpVar, $Button);
|
|
|
|
return $This;
|
|
};
|
|
|
|
$.prototype.modifyButton = function(aoInfo)
|
|
{
|
|
$This = $(this);
|
|
$.each(aoInfo, function(sKey, sValue)
|
|
{
|
|
switch(sKey)
|
|
{
|
|
case 'type': $This.find('i.icon').removeClass(function(index, css){return (css.match(/\bfa-c-\S+/g) || []).join(' ');}).addClass('fa-c-'+sValue); break;
|
|
case 'title': $This.find('span.value').text(sValue); break;
|
|
case 'link': $This.attr('href', sValue); break;
|
|
case 'action': $This.off('click').click(function(e){e.preventDefault(); sValue();}); break;
|
|
case 'id': $This.attr('id', sValue); break;
|
|
case 'class': $This.attr('class', 'button round '+sValue); break;
|
|
case 'var': databap.tmp(sValue, $This); break; //TODO delete use of tmp out of databap class context
|
|
}
|
|
});
|
|
return $This;
|
|
};
|
|
|
|
$.prototype.getEmptyHeight = function()
|
|
{
|
|
var $This = $(this), iTotalHeight = 0;
|
|
$This.children(':visible').not('.scrollbar').each(function()
|
|
{
|
|
//debug('#'+$(this).attr('id')+'|.'+$(this).attr('class')+' gives '+$(this).outerHeight(true));
|
|
iTotalHeight += $(this).outerHeight(true);
|
|
});
|
|
return $This.height() - iTotalHeight;
|
|
};
|
|
|
|
$.prototype.getEmptyWidth = function()
|
|
{
|
|
var $This = $(this), iTotalWidth = 0;
|
|
$This.children(':visible').not('.scrollbar').each(function()
|
|
{
|
|
iTotalWidth += $(this).outerWidth(true);
|
|
});
|
|
return $This.width() - iTotalWidth;
|
|
};
|
|
|
|
$.prototype.addDefaultValue = function(sDefaultValue, sInitValue)
|
|
{
|
|
sInitValue = sInitValue || '';
|
|
return $(this)
|
|
.data('default_value', sDefaultValue)
|
|
.val(sInitValue==''?sDefaultValue:sInitValue)
|
|
.addClass(sInitValue==''?'default_text':'')
|
|
.focus(function()
|
|
{
|
|
var $This = $(this);
|
|
if($This.val() == $This.data('default_value')) $This.val('');
|
|
$This.removeClass('default_text');
|
|
})
|
|
.blur(function()
|
|
{
|
|
var $This = $(this);
|
|
if($This.val() == '') $This.val($This.data('default_value')).addClass('default_text');
|
|
});
|
|
};
|
|
|
|
$.prototype.checkForm = function(sSelector)
|
|
{
|
|
sSelector = sSelector || 'input[type="password"], input[type="text"], textarea';
|
|
var $This = $(this);
|
|
var bOk = true;
|
|
$This.find(sSelector).each(function()
|
|
{
|
|
$This = $(this);
|
|
bOk = bOk && $This.val()!='' && $This.val()!=$This.data('default_value');
|
|
});
|
|
return bOk;
|
|
};
|
|
|
|
/* Common functions */
|
|
|
|
String.prototype.stripVowelAccent = function()
|
|
{
|
|
var sec = ['193','225','192','224','194','226','461','462','258','259','195','227','7842','7843','7840','7841','196','228','197','229','256','257','260','261','7844','7845','7846','7847','7850','7851','7848','7849','7852','7853','7854','7855','7856','7857','7860','7861','7858','7859','7862','7863','506','507','262','263','264','265','268','269','266','267','199','231','270','271','272','273','201','233','200','232','202','234','282','283','276','277','7868','7869','7866','7867','278','279','203','235','274','275','280','281','7870','7871','7872','7873','7876','7877','7874','7875','7864','7865','7878','7879','286','287','284','285','288','289','290','291','292','293','294','295','205','237','204','236','300','301','206','238','463','464','207','239','296','297','302','303','298','299','7880','7881','7882','7883','308','309','310','311','313','314','317','318','315','316','321','322','319','320','323','324','327','328','209','241','325','326','211','243','210','242','334','335','212','244','7888','7889','7890','7891','7894','7895','7892','7893','465','466','214','246','336','337','213','245','216','248','510','511','332','333','7886','7887','416','417','7898','7899','7900','7901','7904','7905','7902','7903','7906','7907','7884','7885','7896','7897','7764','7765','7766','7767','340','341','344','345','342','343','346','347','348','349','352','353','350','351','356','357','354','355','358','359','218','250','217','249','364','365','219','251','467','468','366','367','220','252','471','472','475','476','473','474','469','470','368','369','360','361','370','371','362','363','7910','7911','431','432','7912','7913','7914','7915','7918','7919','7916','7917','7920','7921','7908','7909','7810','7811','7808','7809','372','373','7812','7813','221','253','7922','7923','374','375','376','255','7928','7929','7926','7927','7924','7925','377','378','381','382','379','380','208'];
|
|
var rep = ['A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','A','a','C','c','C','c','C','c','C','c','C','c','D','d','D','d','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','E','e','G','g','G','g','G','g','G','g','H','h','H','h','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','I','i','J','j','K','k','L','l','L','l','L','l','L','l','L','l','N','n','N','n','N','n','N','n','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','O','o','P','p','P','p','R','r','R','r','R','r','S','s','S','s','S','s','S','s','T','t','T','t','T','t','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','U','u','W','w','W','w','W','w','W','w','Y','y','Y','y','Y','y','Y','y','Y','y','Y','y','Y','y','Z','z','Z','z','Z','z','D'];
|
|
|
|
var seclen = sec.length;
|
|
var repwith = -1;
|
|
var text = this;
|
|
text = text.replace(/\r/g,'').split('\n');
|
|
var textout = new Array();
|
|
var linecnt = text.length;
|
|
var toremout = '';
|
|
var chcoat = '';
|
|
for(var x=0;x<linecnt;x++)
|
|
{
|
|
torem = text[x].split('');
|
|
toremout = new Array();
|
|
toremlen = torem.length;
|
|
for(var y=0;y<toremlen;y++)
|
|
{
|
|
chcoat = torem[y].charCodeAt(0);
|
|
if(chcoat > 124)
|
|
{
|
|
for(var z=0;z<seclen;z++)
|
|
{
|
|
if(chcoat == sec[z])
|
|
{
|
|
repwith = rep[z];
|
|
z = seclen;
|
|
}
|
|
}
|
|
}
|
|
if(repwith != -1)
|
|
{
|
|
toremout[y] = repwith;
|
|
repwith = -1;
|
|
}
|
|
else toremout[y] = torem[y];
|
|
}
|
|
textout[x] = toremout.join('');
|
|
}
|
|
return textout.join('\n');
|
|
}
|
|
|
|
String.prototype.replaceAll = function(regex, text)
|
|
{
|
|
return this.replace(new RegExp(regex, 'g'), text);
|
|
};
|
|
|
|
function copyArray(asArray)
|
|
{
|
|
return asArray.slice(0); //trick to copy array
|
|
}
|
|
|
|
function expand($eventElem)
|
|
{
|
|
var tag = '.'+$eventElem.attr('id').substr(7);
|
|
if($eventElem.hasClass('minus'))
|
|
{
|
|
$eventElem.removeClass('minus');
|
|
$eventElem.addClass('plus');
|
|
$(tag).hide('fast');
|
|
}
|
|
else
|
|
{
|
|
$eventElem.removeClass('plus');
|
|
$eventElem.addClass('minus');
|
|
$(tag).show('fast');
|
|
}
|
|
}
|
|
|
|
function array_filter(arr, func)
|
|
{
|
|
var retObj = {};
|
|
for(var k in arr)
|
|
{
|
|
if(func(arr[k]))
|
|
{
|
|
retObj[k] = arr[k];
|
|
}
|
|
}
|
|
|
|
return retObj;
|
|
}
|
|
|
|
function isNumeric(input)
|
|
{
|
|
return (input - 0) == input && input.length > 0;
|
|
}
|
|
|
|
function ucwords(text)
|
|
{
|
|
return (t = text + '').replace
|
|
(
|
|
/^([a-z])|\s+([a-z])/g,
|
|
function($1)
|
|
{
|
|
return $1.toUpperCase();
|
|
}
|
|
);
|
|
}
|
|
|
|
function getTimeString()
|
|
{
|
|
var currentTime = new Date();
|
|
var hours = currentTime.getHours();
|
|
var minutes = currentTime.getMinutes();
|
|
var secondes = currentTime.getSeconds();
|
|
|
|
hours = sprintf(hours, 2, '0');
|
|
minutes = sprintf(minutes, 2, '0');
|
|
secondes = sprintf(secondes, 2, '0');
|
|
|
|
return hours+':'+minutes+':'+secondes;
|
|
}
|
|
|
|
function sprintf(value, length, char)
|
|
{
|
|
var buffer = '';
|
|
missingCharsNb = Math.max(0, length - value.length);
|
|
for(var i=0;i<=missingCharsNb;i++)
|
|
{
|
|
buffer += char;
|
|
}
|
|
|
|
return buffer+value;
|
|
}
|
|
|
|
function chr(codePt)
|
|
{
|
|
if (codePt > 0xFFFF)
|
|
{
|
|
return String.fromCharCode(0xD800 + (codePt >> 10), 0xDC00 + (codePt & 0x3FF));
|
|
}
|
|
return String.fromCharCode(codePt);
|
|
}
|
|
|
|
function explode(delimiter, string, limit)
|
|
{
|
|
var emptyArray = {0:''};
|
|
|
|
if(arguments.length < 2 || typeof arguments[0] == 'undefined' || typeof arguments[1] == 'undefined') return null;
|
|
|
|
if(delimiter === '' || delimiter === false || delimiter === null) return false;
|
|
|
|
if(typeof delimiter == 'function' || typeof delimiter == 'object' || typeof string == 'function' || typeof string == 'object') return emptyArray;
|
|
|
|
if(delimiter === true) delimiter = '1';
|
|
|
|
if(!limit) return string.toString().split(delimiter.toString());
|
|
else
|
|
{
|
|
// support for limit argument
|
|
var splitted = string.toString().split(delimiter.toString());
|
|
var partA = splitted.splice(0, limit - 1);
|
|
var partB = splitted.join(delimiter.toString());
|
|
partA.push(partB);
|
|
return partA;
|
|
}
|
|
}
|
|
|
|
function implode(glue, pieces)
|
|
{
|
|
var i = '', retVal = '', tGlue = '';
|
|
|
|
if(arguments.length === 1)
|
|
{
|
|
pieces = glue;
|
|
glue = '';
|
|
}
|
|
|
|
if(typeof(pieces) === 'object')
|
|
{
|
|
if(pieces instanceof Array) return pieces.join(glue);
|
|
else
|
|
{
|
|
for (i in pieces)
|
|
{
|
|
retVal += tGlue + pieces[i];
|
|
tGlue = glue;
|
|
}
|
|
return retVal;
|
|
}
|
|
}
|
|
else return pieces;
|
|
}
|
|
|
|
function file_exists(url)
|
|
{
|
|
var req = this.window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
|
|
if(!req)
|
|
{
|
|
throw new Error('XMLHttpRequest not supported');
|
|
}
|
|
|
|
// HEAD Results are usually shorter (faster) than GET
|
|
req.open('HEAD', url, false);
|
|
req.send(null); if (req.status == 200)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function basename(path, suffix)
|
|
{
|
|
var b = path.replace(/^.*[\/\\]/g, '');
|
|
if (typeof(suffix) == 'string' && b.substr(b.length - suffix.length) == suffix)
|
|
{
|
|
b = b.substr(0, b.length - suffix.length);
|
|
}
|
|
return b;
|
|
}
|
|
|
|
function getElem(aoAnchor, asPath)
|
|
{
|
|
return (typeof asPath == 'object' && asPath.length > 1)?getElem(aoAnchor[asPath.shift()], asPath):aoAnchor[(typeof asPath == 'object')?asPath.shift():asPath];
|
|
}
|
|
|
|
function setElem(aoAnchor, asPath, oValue)
|
|
{
|
|
var asTypes = {boolean:false, string:'', integer:0, int:0, array:[], object:{}};
|
|
if(typeof asPath == 'object' && asPath.length > 1)
|
|
{
|
|
var nextlevel = asPath.shift();
|
|
if(!(nextlevel in aoAnchor)) aoAnchor[nextlevel] = {}; //Creating a new level
|
|
if(typeof aoAnchor[nextlevel] !== 'object') debug('Error - setElem() : Already existing path at level "'+nextlevel+'". Cancelling setElem() action');
|
|
return setElem(aoAnchor[nextlevel], asPath, oValue);
|
|
}
|
|
else
|
|
{
|
|
var sKey = (typeof asPath == 'object')?asPath.shift():asPath;
|
|
return aoAnchor[sKey] = (!(sKey in aoAnchor) && (oValue in asTypes))?asTypes[oValue]:oValue;
|
|
}
|
|
}
|
|
|
|
function array_search(needle, haystack, argStrict)
|
|
{
|
|
var strict = !! argStrict,
|
|
key = '';
|
|
if(typeof needle === 'object' && needle.exec)
|
|
{
|
|
// Duck-type for RegExp
|
|
if(!strict)
|
|
{
|
|
// Let's consider case sensitive searches as strict
|
|
var flags = 'i' + (needle.global ? 'g' : '') + (needle.multiline ? 'm' : '') + (needle.sticky ? 'y' : '');
|
|
needle = new RegExp(needle.source, flags);
|
|
}
|
|
for(key in haystack)
|
|
{
|
|
if(haystack.hasOwnProperty(key))
|
|
{
|
|
if(needle.test(haystack[key])) return key;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
for(key in haystack)
|
|
{
|
|
if(haystack.hasOwnProperty(key))
|
|
{
|
|
if((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) return key;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
//Queue element
|
|
(
|
|
function($)
|
|
{
|
|
$.fn.delaying = function(delay, reloadAction, minLength)
|
|
{
|
|
var options={delay:delay, reload_action:reloadAction, min_length:minLength};
|
|
this.each
|
|
(
|
|
function()
|
|
{
|
|
$(this).data('tsb',new Delayer($(this), options));
|
|
}
|
|
);
|
|
return this;
|
|
};
|
|
|
|
function Delayer(elem, options)
|
|
{
|
|
var self = this;
|
|
var delays, min_length, previous_values,
|
|
temp_values, reload_action, processing_requests;
|
|
|
|
this.init = function()
|
|
{
|
|
delays = options.delay;
|
|
min_length = options.min_length;
|
|
previous_values = '';
|
|
temp_values = '';
|
|
reload_action = options.reload_action;
|
|
processing_requests = false;
|
|
};
|
|
|
|
this.request = function(val)
|
|
{
|
|
var requestOk = false;
|
|
|
|
//Prevent from loading request with too few elements or twice the same request
|
|
if(val.length > queue.min_length[id] && val != queue.previous_values[id])
|
|
{
|
|
//Prevent from spamming server with requests and wait for value stabilization
|
|
if(queue.processing_requests[id] == false && val == queue.temp_values[id])
|
|
{
|
|
queue.previous_values[id] = val;
|
|
requestOk = true;
|
|
}
|
|
else
|
|
{
|
|
queue.temp_values[id] = val;
|
|
setTimeout(queue.reload_action[id], queue.delays[id]);
|
|
}
|
|
}
|
|
return requestOk;
|
|
};
|
|
}
|
|
}
|
|
)
|
|
(jQuery);
|
|
*/
|
|
|
|
function debug(text, bQuery)
|
|
{
|
|
if(window.console) console.log(text);
|
|
}
|
|
|
|
function getLoginToken(sPass)
|
|
{
|
|
return hex_md5(sPass+window.location.origin+window.location.pathname);
|
|
}
|
|
|
|
/* md5 */
|
|
|
|
/*
|
|
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
|
|
* Digest Algorithm, as defined in RFC 1321.
|
|
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
|
|
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
|
|
* Distributed under the BSD License
|
|
* See http://pajhome.org.uk/crypt/md5 for more info.
|
|
*/
|
|
|
|
/*
|
|
* Configurable variables. You may need to tweak these to be compatible with
|
|
* the server-side, but the defaults work in most cases.
|
|
*/
|
|
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
|
|
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
|
|
|
|
/*
|
|
* These are the functions you'll usually want to call
|
|
* They take string arguments and return either hex or base-64 encoded strings
|
|
*/
|
|
function hex_md5(s) { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }
|
|
function b64_md5(s) { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }
|
|
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }
|
|
function hex_hmac_md5(k, d)
|
|
{ return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
|
|
function b64_hmac_md5(k, d)
|
|
{ return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }
|
|
function any_hmac_md5(k, d, e)
|
|
{ return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }
|
|
|
|
/*
|
|
* Perform a simple self-test to see if the VM is working
|
|
*/
|
|
function md5_vm_test()
|
|
{
|
|
return hex_md5("abc").toLowerCase() == "900150983cd24fb0d6963f7d28e17f72";
|
|
}
|
|
|
|
/*
|
|
* Calculate the MD5 of a raw string
|
|
*/
|
|
function rstr_md5(s)
|
|
{
|
|
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));
|
|
}
|
|
|
|
/*
|
|
* Calculate the HMAC-MD5, of a key and some data (raw strings)
|
|
*/
|
|
function rstr_hmac_md5(key, data)
|
|
{
|
|
var bkey = rstr2binl(key);
|
|
if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8);
|
|
|
|
var ipad = Array(16), opad = Array(16);
|
|
for(var i = 0; i < 16; i++)
|
|
{
|
|
ipad[i] = bkey[i] ^ 0x36363636;
|
|
opad[i] = bkey[i] ^ 0x5C5C5C5C;
|
|
}
|
|
|
|
var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
|
|
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));
|
|
}
|
|
|
|
/*
|
|
* Convert a raw string to a hex string
|
|
*/
|
|
function rstr2hex(input)
|
|
{
|
|
try { hexcase } catch(e) { hexcase=0; }
|
|
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
|
|
var output = "";
|
|
var x;
|
|
for(var i = 0; i < input.length; i++)
|
|
{
|
|
x = input.charCodeAt(i);
|
|
output += hex_tab.charAt((x >>> 4) & 0x0F)
|
|
+ hex_tab.charAt( x & 0x0F);
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Convert a raw string to a base-64 string
|
|
*/
|
|
function rstr2b64(input)
|
|
{
|
|
try { b64pad } catch(e) { b64pad=''; }
|
|
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
var output = "";
|
|
var len = input.length;
|
|
for(var i = 0; i < len; i += 3)
|
|
{
|
|
var triplet = (input.charCodeAt(i) << 16)
|
|
| (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
|
|
| (i + 2 < len ? input.charCodeAt(i+2) : 0);
|
|
for(var j = 0; j < 4; j++)
|
|
{
|
|
if(i * 8 + j * 6 > input.length * 8) output += b64pad;
|
|
else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Convert a raw string to an arbitrary string encoding
|
|
*/
|
|
function rstr2any(input, encoding)
|
|
{
|
|
var divisor = encoding.length;
|
|
var i, j, q, x, quotient;
|
|
|
|
/* Convert to an array of 16-bit big-endian values, forming the dividend */
|
|
var dividend = Array(Math.ceil(input.length / 2));
|
|
for(i = 0; i < dividend.length; i++)
|
|
{
|
|
dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
|
|
}
|
|
|
|
/*
|
|
* Repeatedly perform a long division. The binary array forms the dividend,
|
|
* the length of the encoding is the divisor. Once computed, the quotient
|
|
* forms the dividend for the next step. All remainders are stored for later
|
|
* use.
|
|
*/
|
|
var full_length = Math.ceil(input.length * 8 /
|
|
(Math.log(encoding.length) / Math.log(2)));
|
|
var remainders = Array(full_length);
|
|
for(j = 0; j < full_length; j++)
|
|
{
|
|
quotient = Array();
|
|
x = 0;
|
|
for(i = 0; i < dividend.length; i++)
|
|
{
|
|
x = (x << 16) + dividend[i];
|
|
q = Math.floor(x / divisor);
|
|
x -= q * divisor;
|
|
if(quotient.length > 0 || q > 0)
|
|
quotient[quotient.length] = q;
|
|
}
|
|
remainders[j] = x;
|
|
dividend = quotient;
|
|
}
|
|
|
|
/* Convert the remainders to the output string */
|
|
var output = "";
|
|
for(i = remainders.length - 1; i >= 0; i--)
|
|
output += encoding.charAt(remainders[i]);
|
|
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Encode a string as utf-8.
|
|
* For efficiency, this assumes the input is valid utf-16.
|
|
*/
|
|
function str2rstr_utf8(input)
|
|
{
|
|
var output = "";
|
|
var i = -1;
|
|
var x, y;
|
|
|
|
while(++i < input.length)
|
|
{
|
|
/* Decode utf-16 surrogate pairs */
|
|
x = input.charCodeAt(i);
|
|
y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0;
|
|
if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF)
|
|
{
|
|
x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
|
|
i++;
|
|
}
|
|
|
|
/* Encode output as utf-8 */
|
|
if(x <= 0x7F)
|
|
output += String.fromCharCode(x);
|
|
else if(x <= 0x7FF)
|
|
output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
|
|
0x80 | ( x & 0x3F));
|
|
else if(x <= 0xFFFF)
|
|
output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
|
|
0x80 | ((x >>> 6 ) & 0x3F),
|
|
0x80 | ( x & 0x3F));
|
|
else if(x <= 0x1FFFFF)
|
|
output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
|
|
0x80 | ((x >>> 12) & 0x3F),
|
|
0x80 | ((x >>> 6 ) & 0x3F),
|
|
0x80 | ( x & 0x3F));
|
|
}
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Encode a string as utf-16
|
|
*/
|
|
function str2rstr_utf16le(input)
|
|
{
|
|
var output = "";
|
|
for(var i = 0; i < input.length; i++)
|
|
output += String.fromCharCode( input.charCodeAt(i) & 0xFF,
|
|
(input.charCodeAt(i) >>> 8) & 0xFF);
|
|
return output;
|
|
}
|
|
|
|
function str2rstr_utf16be(input)
|
|
{
|
|
var output = "";
|
|
for(var i = 0; i < input.length; i++)
|
|
output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF,
|
|
input.charCodeAt(i) & 0xFF);
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Convert a raw string to an array of little-endian words
|
|
* Characters >255 have their high-byte silently ignored.
|
|
*/
|
|
function rstr2binl(input)
|
|
{
|
|
var output = Array(input.length >> 2);
|
|
for(var i = 0; i < output.length; i++)
|
|
output[i] = 0;
|
|
for(var i = 0; i < input.length * 8; i += 8)
|
|
output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Convert an array of little-endian words to a string
|
|
*/
|
|
function binl2rstr(input)
|
|
{
|
|
var output = "";
|
|
for(var i = 0; i < input.length * 32; i += 8)
|
|
output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
|
|
return output;
|
|
}
|
|
|
|
/*
|
|
* Calculate the MD5 of an array of little-endian words, and a bit length.
|
|
*/
|
|
function binl_md5(x, len)
|
|
{
|
|
/* append padding */
|
|
x[len >> 5] |= 0x80 << ((len) % 32);
|
|
x[(((len + 64) >>> 9) << 4) + 14] = len;
|
|
|
|
var a = 1732584193;
|
|
var b = -271733879;
|
|
var c = -1732584194;
|
|
var d = 271733878;
|
|
|
|
for(var i = 0; i < x.length; i += 16)
|
|
{
|
|
var olda = a;
|
|
var oldb = b;
|
|
var oldc = c;
|
|
var oldd = d;
|
|
|
|
a = md5_ff(a, b, c, d, x[i+ 0], 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+ 0], 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+ 0], 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+ 0], 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 Array(a, b, c, d);
|
|
}
|
|
|
|
/*
|
|
* These functions implement the four basic operations the algorithm uses.
|
|
*/
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
|
|
* to work around bugs in some JS interpreters.
|
|
*/
|
|
function safe_add(x, y)
|
|
{
|
|
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
|
|
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
|
|
return (msw << 16) | (lsw & 0xFFFF);
|
|
}
|
|
|
|
/*
|
|
* Bitwise rotate a 32-bit number to the left.
|
|
*/
|
|
function bit_rol(num, cnt)
|
|
{
|
|
return (num << cnt) | (num >>> (32 - cnt));
|
|
} |