1/* 2 * jQuery Cryptography Plug-in 3 * version: 1.0.0 (24 Sep 2008) 4 * copyright 2008 Scott Thompson http://www.itsyndicate.ca - [email protected] 5 * http://www.opensource.org/licenses/mit-license.php 6 * 7 * A set of functions to do some basic cryptography encoding/decoding 8 * I compiled from some javascripts I found into a jQuery plug-in. 9 * Thanks go out to the original authors. 10 * 11 * Also a big thanks to Wade W. Hedgren http://homepages.uc.edu/~hedgreww 12 * for the 1.1.1 upgrade to conform correctly to RFC4648 Sec5 url save base64 13 * 14 * Changelog: 1.1.0 15 * - rewrote plugin to use only one item in the namespace 16 * 17 * Changelog: 1.1.1 18 * - added code to base64 to allow URL and Filename Safe Alphabet (RFC4648 Sec5) 19 * 20 * --- Base64 Encoding and Decoding code was written by 21 * 22 * Base64 code from Tyler Akins -- http://rumkin.com 23 * and is placed in the public domain 24 * 25 * 26 * --- MD5 and SHA1 Functions based upon Paul Johnston's javascript libraries. 27 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 28 * Digest Algorithm, as defined in RFC 1321. 29 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. 30 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 31 * Distributed under the BSD License 32 * See http://pajhome.org.uk/crypt/md5 for more info. 33 * 34 * xTea Encrypt and Decrypt 35 * copyright 2000-2005 Chris Veness 36 * http://www.movable-type.co.uk 37 * 38 * 39 * Examples: 40 * 41 var md5 = $().crypt({method:"md5",source:$("#phrase").val()}); 42 var sha1 = $().crypt({method:"sha1",source:$("#phrase").val()}); 43 var b64 = $().crypt({method:"b64enc",source:$("#phrase").val()}); 44 var b64dec = $().crypt({method:"b64dec",source:b64}); 45 var xtea = $().crypt({method:"xteaenc",source:$("#phrase").val(),keyPass:$("#passPhrase").val()}); 46 var xteadec = $().crypt({method:"xteadec",source:xtea,keyPass:$("#passPhrase").val()}); 47 var xteab64 = $().crypt({method:"xteab64enc",source:$("#phrase").val(),keyPass:$("#passPhrase").val()}); 48 var xteab64dec = $().crypt({method:"xteab64dec",source:xteab64,keyPass:$("#passPhrase").val()}); 49 50 You can also pass source this way. 51 var md5 = $("#idOfSource").crypt({method:"md5"}); 52 * 53 */ 54(function($){ 55 $.fn.crypt = function(options) { 56 var defaults = { 57 b64Str : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!-", 58 strKey : "123", 59 method : "md5", 60 source : "", 61 chrsz : 8, /* md5 - bits per input character. 8 - ASCII; 16 - Unicode */ 62 hexcase : 0 /* md5 - hex output format. 0 - lowercase; 1 - uppercase */ 63 }; 64 65 // code to enable URL and Filename Safe Alphabet (RFC4648 Sec5) 66/* 67 if (typeof(options.urlsafe) == 'undefined'){ 68 defaults.b64Str += '+/='; 69 options.urlsafe = false; 70 }else if (options.urlsafe){ 71 defaults.b64Str += '-_='; 72 }else{ 73 defaults.b64Str += '+/='; 74 } 75*/ 76 var opts = $.extend(defaults, options); 77 78 // support for $("#name").crypt..... 79 if (!opts.source) { 80 var $this = $(this); 81 // determine if it's a div or a textarea 82 if ($this.html()) opts.source = $this.html(); 83 else if ($this.val()) opts.source = $this.val(); 84 else {alert("Please provide source text");return false;}; 85 }; 86 87 if (opts.method == 'md5') { 88 return md5(opts); 89 } else if (opts.method == 'sha1') { 90 return sha1(opts); 91 } else if (opts.method == 'b64enc') { 92 return b64enc(opts); 93 } else if (opts.method == 'b64dec') { 94 return b64dec(opts); 95 } else if (opts.method == 'xteaenc') { 96 return xteaenc(opts); 97 } else if (opts.method == 'xteadec') { 98 return xteadec(opts); 99 } else if (opts.method == 'xteab64enc') { 100 var tmpenc = xteaenc(opts); 101 opts.method = "b64enc"; 102 opts.source = tmpenc; 103 return b64enc(opts); 104 } else if (opts.method == 'xteab64dec') { 105 var tmpdec = b64dec(opts); 106 opts.method = "xteadec"; 107 opts.source = tmpdec; 108 return xteadec(opts); 109 } 110 111 112 function b64enc(params) { 113 114 var output = ""; 115 var chr1, chr2, chr3; 116 var enc1, enc2, enc3, enc4; 117 var i = 0; 118 119 do { 120 chr1 = params.source.charCodeAt(i++); 121 chr2 = params.source.charCodeAt(i++); 122 chr3 = params.source.charCodeAt(i++); 123 124 enc1 = chr1 >> 2; 125 enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); 126 enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); 127 enc4 = chr3 & 63; 128 129 if (isNaN(chr2)) { 130 enc3 = enc4 = 64; 131 } else if (isNaN(chr3)) { 132 enc4 = 64; 133 }; 134 135 output += params.b64Str.charAt(enc1) 136 + params.b64Str.charAt(enc2) 137 + params.b64Str.charAt(enc3) 138 + params.b64Str.charAt(enc4); 139 140 141 } while (i < params.source.length); 142 143 return output; 144 145 }; 146 147 function b64dec(params) { 148 149 var output = ""; 150 var chr1, chr2, chr3; 151 var enc1, enc2, enc3, enc4; 152 var i = 0; 153 154 // remove all characters that are not A-Z, a-z, 0-9, !, -, or _ 155 156 // remove all characters that are not A-Z, a-z, 0-9, !, -, or _ 157 // params.source = params.source.replace(/[^A-Za-z0-9!_-]/g, ""); 158 159 var re = new RegExp ('[^A-Za-z0-9' + params.b64Str.substr(-3) + ']', 'g'); 160 params.source = params.source.replace(re, ""); 161 162 do { 163 enc1 = params.b64Str.indexOf(params.source.charAt(i++)); 164 enc2 = params.b64Str.indexOf(params.source.charAt(i++)); 165 enc3 = params.b64Str.indexOf(params.source.charAt(i++)); 166 enc4 = params.b64Str.indexOf(params.source.charAt(i++)); 167 168 chr1 = (enc1 << 2) | (enc2 >> 4); 169 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); 170 chr3 = ((enc3 & 3) << 6) | enc4; 171 172 output = output + String.fromCharCode(chr1); 173 174 if (enc3 != 64) { 175 output = output + String.fromCharCode(chr2); 176 } 177 if (enc4 != 64) { 178 output = output + String.fromCharCode(chr3); 179 } 180 } while (i < params.source.length); 181 182 return output; 183 }; 184 185 186 function md5(params) { 187 /* This is a trimmed version of Paul Johnsons JavaScript 188 * 189 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message 190 * Digest Algorithm, as defined in RFC 1321. 191 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. 192 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet 193 * Distributed under the BSD License 194 * See http://pajhome.org.uk/crypt/md5 for more info. 195 */ 196 197 //var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ 198 //var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ 199 200 return binl2hex(core_md5(str2binl(params.source), params.source.length * params.chrsz)); 201 202 /* 203 * Convert an array of little-endian words to a hex string. 204 */ 205 function binl2hex(binarray) 206 { 207 var hex_tab = params.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 208 var str = ""; 209 for(var i = 0; i < binarray.length * 4; i++) 210 { 211 str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + 212 hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); 213 }; 214 return str; 215 }; 216 217 /* 218 * Calculate the HMAC-MD5, of a key and some data 219 */ 220 function core_hmac_md5(key, data) 221 { 222 var bkey = str2binl(key); 223 if(bkey.length > 16) bkey = core_md5(bkey, key.length * params.chrsz); 224 225 var ipad = Array(16), opad = Array(16); 226 for(var i = 0; i < 16; i++) 227 { 228 ipad[i] = bkey[i] ^ 0x36363636; 229 opad[i] = bkey[i] ^ 0x5C5C5C5C; 230 }; 231 232 var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * params.chrsz); 233 return core_md5(opad.concat(hash), 512 + 128); 234 }; 235 236 /* 237 * Convert a string to an array of little-endian words 238 * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. 239 */ 240 function str2binl(str) 241 { 242 var bin = Array(); 243 var mask = (1 << params.chrsz) - 1; 244 for(var i = 0; i < str.length * params.chrsz; i += params.chrsz) 245 bin[i>>5] |= (str.charCodeAt(i / params.chrsz) & mask) << (i%32); 246 return bin; 247 } 248 249 250 /* 251 * Bitwise rotate a 32-bit number to the left. 252 */ 253 function bit_rol(num, cnt) 254 { 255 return (num << cnt) | (num >>> (32 - cnt)); 256 } 257 258 259 /* 260 * These functions implement the four basic operations the algorithm uses. 261 */ 262 function md5_cmn(q, a, b, x, s, t) 263 { 264 return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); 265 } 266 function md5_ff(a, b, c, d, x, s, t) 267 { 268 return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); 269 } 270 function md5_gg(a, b, c, d, x, s, t) 271 { 272 return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); 273 } 274 function md5_hh(a, b, c, d, x, s, t) 275 { 276 return md5_cmn(b ^ c ^ d, a, b, x, s, t); 277 } 278 function md5_ii(a, b, c, d, x, s, t) 279 { 280 return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); 281 } 282 283 /* 284 * Calculate the MD5 of an array of little-endian words, and a bit length 285 */ 286 function core_md5(x, len) 287 { 288 /* append padding */ 289 x[len >> 5] |= 0x80 << ((len) % 32); 290 x[(((len + 64) >>> 9) << 4) + 14] = len; 291 292 var a = 1732584193; 293 var b = -271733879; 294 var c = -1732584194; 295 var d = 271733878; 296 297 for(var i = 0; i < x.length; i += 16) 298 { 299 var olda = a; 300 var oldb = b; 301 var oldc = c; 302 var oldd = d; 303 304 a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); 305 d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); 306 c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); 307 b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); 308 a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
309 d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); 310 c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); 311 b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); 312 a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); 313 d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); 314 c = md5_ff(c, d, a, b, x[i+10], 17, -42063); 315 b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); 316 a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); 317 d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); 318 c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); 319 b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); 320 321 a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); 322 d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); 323 c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); 324 b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); 325 a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); 326 d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); 327 c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); 328 b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); 329 a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); 330 d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); 331 c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); 332 b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); 333 a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); 334 d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); 335 c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); 336 b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); 337 338 a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); 339 d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); 340 c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); 341 b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); 342 a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); 343 d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); 344 c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); 345 b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); 346 a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); 347 d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); 348 c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); 349 b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); 350 a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); 351 d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); 352 c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); 353 b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); 354 355 a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); 356 d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); 357 c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); 358 b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); 359 a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); 360 d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); 361 c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); 362 b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); 363 a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); 364 d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); 365 c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); 366 b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); 367 a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); 368 d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); 369 c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); 370 b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); 371 372 a = safe_add(a, olda); 373 b = safe_add(b, oldb); 374 c = safe_add(c, oldc); 375 d = safe_add(d, oldd); 376 }; 377 return Array(a, b, c, d); 378 379 }; 380 381 }; 382 383 /* 384 * Add integers, wrapping at 2^32. This uses 16-bit operations internally 385 * to work around bugs in some JS interpreters. (used by md5 and sha1) 386 */ 387 function safe_add(x, y) 388 { 389 var lsw = (x & 0xFFFF) + (y & 0xFFFF); 390 var msw = (x >> 16) + (y >> 16) + (lsw >> 16); 391 return (msw << 16) | (lsw & 0xFFFF); 392 }; 393 394 function sha1(params) { 395 return binb2hex(core_sha1(str2binb(params.source),params.source.length * params.chrsz)); 396 397 /* 398 * Calculate the SHA-1 of an array of big-endian words, and a bit length 399 */ 400 function core_sha1(x, len) 401 { 402 /* append padding */ 403 x[len >> 5] |= 0x80 << (24 - len % 32); 404 x[((len + 64 >> 9) << 4) + 15] = len; 405 406 var w = Array(80); 407 var a = 1732584193; 408 var b = -271733879; 409 var c = -1732584194; 410 var d = 271733878; 411 var e = -1009589776; 412 413 for(var i = 0; i < x.length; i += 16) 414 { 415 var olda = a; 416 var oldb = b; 417 var oldc = c; 418 var oldd = d; 419 var olde = e; 420 421 for(var j = 0; j < 80; j++) 422 { 423 if(j < 16) w[j] = x[i + j]; 424 else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); 425 var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), 426 safe_add(safe_add(e, w[j]), sha1_kt(j))); 427 e = d; 428 d = c; 429 c = rol(b, 30); 430 b = a; 431 a = t; 432 } 433 434 a = safe_add(a, olda); 435 b = safe_add(b, oldb); 436 c = safe_add(c, oldc); 437 d = safe_add(d, oldd); 438 e = safe_add(e, olde); 439 } 440 return Array(a, b, c, d, e); 441 442 } 443 /* 444 * Bitwise rotate a 32-bit number to the left. 445 */ 446 function rol(num, cnt) 447 { 448 return (num << cnt) | (num >>> (32 - cnt)); 449 } 450 451 /* 452 * Determine the appropriate additive constant for the current iteration 453 */ 454 function sha1_kt(t) 455 { 456 return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : 457 (t < 60) ? -1894007588 : -899497514; 458 } 459 /* 460 * Perform the appropriate triplet combination function for the current 461 * iteration 462 */ 463 function sha1_ft(t, b, c, d) 464 { 465 if(t < 20) return (b & c) | ((~b) & d); 466 if(t < 40) return b ^ c ^ d; 467 if(t < 60) return (b & c) | (b & d) | (c & d); 468 return b ^ c ^ d; 469 } 470 471 /* 472 * Convert an array of big-endian words to a hex string. 473 */ 474 function binb2hex(binarray) 475 { 476 var hex_tab = params.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; 477 var str = ""; 478 for(var i = 0; i < binarray.length * 4; i++) 479 { 480 str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + 481 hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); 482 } 483 return str; 484 } 485 486 487 /* 488 * Convert an 8-bit or 16-bit string to an array of big-endian words 489 * In 8-bit function, characters >255 have their hi-byte silently ignored. 490 */ 491 function str2binb(str) 492 { 493 var bin = Array(); 494 var mask = (1 << params.chrsz) - 1; 495 for(var i = 0; i < str.length * params.chrsz; i += params.chrsz) 496 bin[i>>5] |= (str.charCodeAt(i / params.chrsz) & mask) << (32 - params.chrsz - i%32); 497 return bin; 498 } 499 500 }; 501 502 function xteaenc(params) { 503 var v = new Array(2), k = new Array(4), s = "", i; 504 505 params.source = escape(params.source); // use escape() so only have single-byte chars to encode 506 507 // build key directly from 1st 16 chars of strKey 508 for (var i=0; i<4; i++) k[i] = Str4ToLong(params.strKey.slice(i*4,(i+1)*4)); 509 510 for (i=0; i<params.source.length; i+=8) { // encode strSource into s in 64-bit (8 char) blocks 511 v[0] = Str4ToLong(params.source.slice(i,i+4)); // ... note this is 'electronic codebook' mode 512 v[1] = Str4ToLong(params.source.slice(i+4,i+8)); 513 code(v, k); 514 s += LongToStr4(v[0]) + LongToStr4(v[1]); 515 } 516 517 return escCtrlCh(s); 518 // note: if strSource or strKey are passed as string objects, rather than strings, this 519 // function will throw an 'Object doesn't support this property or method' error 520 521 function code(v, k) { 522 // Extended TEA: this is the 1997 revised version of Needham & Wheeler's algorithm 523 // params: v[2] 64-bit value block; k[4] 128-bit key 524 var y = v[0], z = v[1]; 525 var delta = 0x9E3779B9, limit = delta*32, sum = 0; 526 527 while (sum != limit) { 528 y += (z<<4 ^ z>>>5)+z ^ sum+k[sum & 3]; 529 sum += delta; 530 z += (y<<4 ^ y>>>5)+y ^ sum+k[sum>>>11 & 3]; 531 // note: unsigned right-shift '>>>' is used in place of original '>>', due to lack 532 // of 'unsigned' type declaration in JavaScript (thanks to Karsten Kraus for this) 533 } 534 v[0] = y;v[1] = z; 535 } 536 }; 537 538 function xteadec(params) { 539 var v = new Array(2), k = new Array(4), s = "", i; 540 541 for (var i=0; i<4; i++) k[i] = Str4ToLong(params.strKey.slice(i*4,(i+1)*4)); 542 543 ciphertext = unescCtrlCh(params.source); 544 for (i=0; i<ciphertext.length; i+=8) { // decode ciphertext into s in 64-bit (8 char) blocks 545 v[0] = Str4ToLong(ciphertext.slice(i,i+4)); 546 v[1] = Str4ToLong(ciphertext.slice(i+4,i+8)); 547 decode(v, k); 548 s += LongToStr4(v[0]) + LongToStr4(v[1]); 549 } 550 551 // strip trailing null chars resulting from filling 4-char blocks: 552 s = s.replace(/\0+$/, ''); 553 554 return unescape(s); 555 556 557 function decode(v, k) { 558 var y = v[0], z = v[1]; 559 var delta = 0x9E3779B9, sum = delta*32; 560 561 while (sum != 0) { 562 z -= (y<<4 ^ y>>>5)+y ^ sum+k[sum>>>11 & 3]; 563 sum -= delta; 564 y -= (z<<4 ^ z>>>5)+z ^ sum+k[sum & 3]; 565 } 566 v[0] = y;v[1] = z; 567 } 568 569 }; 570 571 // xtea supporting functions 572 function Str4ToLong(s) { // convert 4 chars of s to a numeric long 573 var v = 0; 574 for (var i=0; i<4;
574 i++) v |= s.charCodeAt(i) << i*8; 575 return isNaN(v) ? 0 : v; 576 }; 577 578 function LongToStr4(v) { // convert a numeric long to 4 char string 579 var s = String.fromCharCode(v & 0xFF, v>>8 & 0xFF, v>>16 & 0xFF, v>>24 & 0xFF); 580 return s; 581 }; 582 583 function escCtrlCh(str) { // escape control chars which might cause problems with encrypted texts 584 return str.replace(/[\0\t\n\v\f\r\xa0'"!]/g, function(c) {return '!' + c.charCodeAt(0) + '!';}); 585 }; 586 587 function unescCtrlCh(str) { // unescape potentially problematic nulls and control characters 588 return str.replace(/!\d\d?\d?!/g, function(c) {return String.fromCharCode(c.slice(1,-1));}); 589 }; 590 591 592 593 }; 594})(jQuery); 595
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.