1 /* base64x-1.1.12 (c) 2012-2017 Kenji Urushima | kjur.github.com/jsrsasign/license 2 */ 3 /* 4 * base64x.js - Base64url and supplementary functions for Tom Wu's base64.js library 5 * 6 * version: 1.1.12 (2017-Jun-03) 7 * 8 * Copyright (c) 2012-2017 Kenji Urushima (kenji.urushima@gmail.com) 9 * 10 * This software is licensed under the terms of the MIT License. 11 * https://kjur.github.io/jsjws/license/ 12 * 13 * The above copyright and license notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * DEPENDS ON: 17 * - base64.js - Tom Wu's Base64 library 18 */ 19 20 /** 21 * @fileOverview 22 * @name base64x-1.1.js 23 * @author Kenji Urushima kenji.urushima@gmail.com 24 * @version jsrsasign 7.2.1 base64x 1.1.12 (2017-Jun-03) 25 * @since jsrsasign 2.1 26 * @license <a href="https://kjur.github.io/jsrsasign/license/">MIT License</a> 27 */ 28 29 var KJUR; 30 if (typeof KJUR == "undefined" || !KJUR) KJUR = {}; 31 if (typeof KJUR.lang == "undefined" || !KJUR.lang) KJUR.lang = {}; 32 33 /** 34 * String and its utility class <br/> 35 * This class provides some static utility methods for string. 36 * @class String and its utility class 37 * @author Kenji Urushima 38 * @version 1.0 (2016-Aug-05) 39 * @since base64x 1.1.7 jsrsasign 5.0.13 40 * @description 41 * <br/> 42 * This class provides static methods for string utility. 43 * <dl> 44 * <dt><b>STRING TYPE CHECKERS</b> 45 * <dd> 46 * <ul> 47 * <li>{@link KJUR.lang.String.isInteger} - check whether argument is an integer</li> 48 * <li>{@link KJUR.lang.String.isHex} - check whether argument is a hexadecimal string</li> 49 * <li>{@link KJUR.lang.String.isBase64} - check whether argument is a Base64 encoded string</li> 50 * <li>{@link KJUR.lang.String.isBase64URL} - check whether argument is a Base64URL encoded string</li> 51 * <li>{@link KJUR.lang.String.isIntegerArray} - check whether argument is an array of integers</li> 52 * </ul> 53 * </dl> 54 */ 55 KJUR.lang.String = function() {}; 56 57 /** 58 * Base64URL and supplementary functions for Tom Wu's base64.js library.<br/> 59 * This class is just provide information about global functions 60 * defined in 'base64x.js'. The 'base64x.js' script file provides 61 * global functions for converting following data each other. 62 * <ul> 63 * <li>(ASCII) String</li> 64 * <li>UTF8 String including CJK, Latin and other characters</li> 65 * <li>byte array</li> 66 * <li>hexadecimal encoded String</li> 67 * <li>Full URIComponent encoded String (such like "%69%94")</li> 68 * <li>Base64 encoded String</li> 69 * <li>Base64URL encoded String</li> 70 * </ul> 71 * All functions in 'base64x.js' are defined in {@link global__} and not 72 * in this class. 73 * 74 * @class Base64URL and supplementary functions for Tom Wu's base64.js library 75 * @author Kenji Urushima 76 * @version 1.1 (07 May 2012) 77 * @requires base64.js 78 * @see <a href="https://kjur.github.io/jsjws/">'jwjws'(JWS JavaScript Library) home page https://kjur.github.io/jsjws/</a> 79 * @see <a href="https://kjur.github.io/jsrsasigns/">'jwrsasign'(RSA Sign JavaScript Library) home page https://kjur.github.io/jsrsasign/</a> 80 */ 81 function Base64x() { 82 } 83 84 // ==== string / byte array ================================ 85 /** 86 * convert a string to an array of character codes 87 * @name stoBA 88 * @function 89 * @param {String} s 90 * @return {Array of Numbers} 91 */ 92 function stoBA(s) { 93 var a = new Array(); 94 for (var i = 0; i < s.length; i++) { 95 a[i] = s.charCodeAt(i); 96 } 97 return a; 98 } 99 100 /** 101 * convert an array of character codes to a string 102 * @name BAtos 103 * @function 104 * @param {Array of Numbers} a array of character codes 105 * @return {String} s 106 */ 107 function BAtos(a) { 108 var s = ""; 109 for (var i = 0; i < a.length; i++) { 110 s = s + String.fromCharCode(a[i]); 111 } 112 return s; 113 } 114 115 // ==== byte array / hex ================================ 116 /** 117 * convert an array of bytes(Number) to hexadecimal string.<br/> 118 * @name BAtohex 119 * @function 120 * @param {Array of Numbers} a array of bytes 121 * @return {String} hexadecimal string 122 */ 123 function BAtohex(a) { 124 var s = ""; 125 for (var i = 0; i < a.length; i++) { 126 var hex1 = a[i].toString(16); 127 if (hex1.length == 1) hex1 = "0" + hex1; 128 s = s + hex1; 129 } 130 return s; 131 } 132 133 // ==== string / hex ================================ 134 /** 135 * convert a ASCII string to a hexadecimal string of ASCII codes.<br/> 136 * NOTE: This can't be used for non ASCII characters. 137 * @name stohex 138 * @function 139 * @param {s} s ASCII string 140 * @return {String} hexadecimal string 141 */ 142 function stohex(s) { 143 return BAtohex(stoBA(s)); 144 } 145 146 // ==== string / base64 ================================ 147 /** 148 * convert a ASCII string to a Base64 encoded string.<br/> 149 * NOTE: This can't be used for non ASCII characters. 150 * @name stob64 151 * @function 152 * @param {s} s ASCII string 153 * @return {String} Base64 encoded string 154 */ 155 function stob64(s) { 156 return hex2b64(stohex(s)); 157 } 158 159 // ==== string / base64url ================================ 160 /** 161 * convert a ASCII string to a Base64URL encoded string.<br/> 162 * NOTE: This can't be used for non ASCII characters. 163 * @name stob64u 164 * @function 165 * @param {s} s ASCII string 166 * @return {String} Base64URL encoded string 167 */ 168 function stob64u(s) { 169 return b64tob64u(hex2b64(stohex(s))); 170 } 171 172 /** 173 * convert a Base64URL encoded string to a ASCII string.<br/> 174 * NOTE: This can't be used for Base64URL encoded non ASCII characters. 175 * @name b64utos 176 * @function 177 * @param {s} s Base64URL encoded string 178 * @return {String} ASCII string 179 */ 180 function b64utos(s) { 181 return BAtos(b64toBA(b64utob64(s))); 182 } 183 184 // ==== base64 / base64url ================================ 185 /** 186 * convert a Base64 encoded string to a Base64URL encoded string.<br/> 187 * @name b64tob64u 188 * @function 189 * @param {String} s Base64 encoded string 190 * @return {String} Base64URL encoded string 191 * @example 192 * b64tob64u("ab+c3f/==") → "ab-c3f_" 193 */ 194 function b64tob64u(s) { 195 s = s.replace(/\=/g, ""); 196 s = s.replace(/\+/g, "-"); 197 s = s.replace(/\//g, "_"); 198 return s; 199 } 200 201 /** 202 * convert a Base64URL encoded string to a Base64 encoded string.<br/> 203 * @name b64utob64 204 * @function 205 * @param {String} s Base64URL encoded string 206 * @return {String} Base64 encoded string 207 * @example 208 * b64utob64("ab-c3f_") → "ab+c3f/==" 209 */ 210 function b64utob64(s) { 211 if (s.length % 4 == 2) s = s + "=="; 212 else if (s.length % 4 == 3) s = s + "="; 213 s = s.replace(/-/g, "+"); 214 s = s.replace(/_/g, "/"); 215 return s; 216 } 217 218 // ==== hex / base64url ================================ 219 /** 220 * convert a hexadecimal string to a Base64URL encoded string.<br/> 221 * @name hextob64u 222 * @function 223 * @param {String} s hexadecimal string 224 * @return {String} Base64URL encoded string 225 * @description 226 * convert a hexadecimal string to a Base64URL encoded string. 227 * NOTE: If leading "0" is omitted and odd number length for 228 * hexadecimal leading "0" is automatically added. 229 */ 230 function hextob64u(s) { 231 if (s.length % 2 == 1) s = "0" + s; 232 return b64tob64u(hex2b64(s)); 233 } 234 235 /** 236 * convert a Base64URL encoded string to a hexadecimal string.<br/> 237 * @name b64utohex 238 * @function 239 * @param {String} s Base64URL encoded string 240 * @return {String} hexadecimal string 241 */ 242 function b64utohex(s) { 243 return b64tohex(b64utob64(s)); 244 } 245 246 // ==== utf8 / base64url ================================ 247 248 /** 249 * convert a UTF-8 encoded string including CJK or Latin to a Base64URL encoded string.<br/> 250 * @name utf8tob64u 251 * @function 252 * @param {String} s UTF-8 encoded string 253 * @return {String} Base64URL encoded string 254 * @since 1.1 255 */ 256 257 /** 258 * convert a Base64URL encoded string to a UTF-8 encoded string including CJK or Latin.<br/> 259 * @name b64utoutf8 260 * @function 261 * @param {String} s Base64URL encoded string 262 * @return {String} UTF-8 encoded string 263 * @since 1.1 264 */ 265 266 var utf8tob64u, b64utoutf8; 267 268 if (typeof Buffer === 'function') { 269 utf8tob64u = function (s) { 270 return b64tob64u(new Buffer(s, 'utf8').toString('base64')); 271 }; 272 273 b64utoutf8 = function (s) { 274 return new Buffer(b64utob64(s), 'base64').toString('utf8'); 275 }; 276 } else { 277 utf8tob64u = function (s) { 278 return hextob64u(uricmptohex(encodeURIComponentAll(s))); 279 }; 280 281 b64utoutf8 = function (s) { 282 return decodeURIComponent(hextouricmp(b64utohex(s))); 283 }; 284 } 285 286 // ==== utf8 / base64url ================================ 287 /** 288 * convert a UTF-8 encoded string including CJK or Latin to a Base64 encoded string.<br/> 289 * @name utf8tob64 290 * @function 291 * @param {String} s UTF-8 encoded string 292 * @return {String} Base64 encoded string 293 * @since 1.1.1 294 */ 295 function utf8tob64(s) { 296 return hex2b64(uricmptohex(encodeURIComponentAll(s))); 297 } 298 299 /** 300 * convert a Base64 encoded string to a UTF-8 encoded string including CJK or Latin.<br/> 301 * @name b64toutf8 302 * @function 303 * @param {String} s Base64 encoded string 304 * @return {String} UTF-8 encoded string 305 * @since 1.1.1 306 */ 307 function b64toutf8(s) { 308 return decodeURIComponent(hextouricmp(b64tohex(s))); 309 } 310 311 // ==== utf8 / hex ================================ 312 /** 313 * convert a UTF-8 encoded string including CJK or Latin to a hexadecimal encoded string.<br/> 314 * @name utf8tohex 315 * @function 316 * @param {String} s UTF-8 encoded string 317 * @return {String} hexadecimal encoded string 318 * @since 1.1.1 319 */ 320 function utf8tohex(s) { 321 return uricmptohex(encodeURIComponentAll(s)); 322 } 323 324 /** 325 * convert a hexadecimal encoded string to a UTF-8 encoded string including CJK or Latin.<br/> 326 * Note that when input is improper hexadecimal string as UTF-8 string, this function returns 327 * 'null'. 328 * @name hextoutf8 329 * @function 330 * @param {String} s hexadecimal encoded string 331 * @return {String} UTF-8 encoded string or null 332 * @since 1.1.1 333 */ 334 function hextoutf8(s) { 335 return decodeURIComponent(hextouricmp(s)); 336 } 337 338 /** 339 * convert a hexadecimal encoded string to raw string including non printable characters.<br/> 340 * @name hextorstr 341 * @function 342 * @param {String} s hexadecimal encoded string 343 * @return {String} raw string 344 * @since 1.1.2 345 * @example 346 * hextorstr("610061") → "a\x00a" 347 */ 348 function hextorstr(sHex) { 349 var s = ""; 350 for (var i = 0; i < sHex.length - 1; i += 2) { 351 s += String.fromCharCode(parseInt(sHex.substr(i, 2), 16)); 352 } 353 return s; 354 } 355 356 /** 357 * convert a raw string including non printable characters to hexadecimal encoded string.<br/> 358 * @name rstrtohex 359 * @function 360 * @param {String} s raw string 361 * @return {String} hexadecimal encoded string 362 * @since 1.1.2 363 * @example 364 * rstrtohex("a\x00a") → "610061" 365 */ 366 function rstrtohex(s) { 367 var result = ""; 368 for (var i = 0; i < s.length; i++) { 369 result += ("0" + s.charCodeAt(i).toString(16)).slice(-2); 370 } 371 return result; 372 } 373 374 // ==== hex / b64nl ======================================= 375 376 /** 377 * convert a hexadecimal string to Base64 encoded string<br/> 378 * @name hextob64 379 * @function 380 * @param {String} s hexadecimal string 381 * @return {String} resulted Base64 encoded string 382 * @since base64x 1.1.3 383 * @description 384 * This function converts from a hexadecimal string to Base64 encoded 385 * string without new lines. 386 * @example 387 * hextob64("616161") → "YWFh" 388 */ 389 function hextob64(s) { 390 return hex2b64(s); 391 } 392 393 /** 394 * convert a hexadecimal string to Base64 encoded string with new lines<br/> 395 * @name hextob64nl 396 * @function 397 * @param {String} s hexadecimal string 398 * @return {String} resulted Base64 encoded string with new lines 399 * @since base64x 1.1.3 400 * @description 401 * This function converts from a hexadecimal string to Base64 encoded 402 * string with new lines for each 64 characters. This is useful for 403 * PEM encoded file. 404 * @example 405 * hextob64nl("123456789012345678901234567890123456789012345678901234567890") 406 * → 407 * MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4 // new line 408 * OTAxMjM0NTY3ODkwCg== 409 */ 410 function hextob64nl(s) { 411 var b64 = hextob64(s); 412 var b64nl = b64.replace(/(.{64})/g, "$1\r\n"); 413 b64nl = b64nl.replace(/\r\n$/, ''); 414 return b64nl; 415 } 416 417 /** 418 * convert a Base64 encoded string with new lines to a hexadecimal string<br/> 419 * @name b64nltohex 420 * @function 421 * @param {String} s Base64 encoded string with new lines 422 * @return {String} hexadecimal string 423 * @since base64x 1.1.3 424 * @description 425 * This function converts from a Base64 encoded 426 * string with new lines to a hexadecimal string. 427 * This is useful to handle PEM encoded file. 428 * This function removes any non-Base64 characters (i.e. not 0-9,A-Z,a-z,\,+,=) 429 * including new line. 430 * @example 431 * hextob64nl( 432 * "MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4\r\n" + 433 * "OTAxMjM0NTY3ODkwCg==\r\n") 434 * → 435 * "123456789012345678901234567890123456789012345678901234567890" 436 */ 437 function b64nltohex(s) { 438 var b64 = s.replace(/[^0-9A-Za-z\/+=]*/g, ''); 439 var hex = b64tohex(b64); 440 return hex; 441 } 442 443 // ==== hex / pem ========================================= 444 445 /** 446 * get PEM string from hexadecimal data and header string 447 * @name hextopem 448 * @function 449 * @param {String} dataHex hexadecimal string of PEM body 450 * @param {String} pemHeader PEM header string (ex. 'RSA PRIVATE KEY') 451 * @return {String} PEM formatted string of input data 452 * @since jsrasign 7.2.1 base64x 1.1.12 453 * @description 454 * This function converts a hexadecimal string to a PEM string with 455 * a specified header. Its line break will be CRLF("\r\n"). 456 * @example 457 * hextopem('616161', 'RSA PRIVATE KEY') → 458 * -----BEGIN PRIVATE KEY----- 459 * YWFh 460 * -----END PRIVATE KEY----- 461 */ 462 function hextopem(dataHex, pemHeader) { 463 var pemBody = hextob64nl(dataHex); 464 return "-----BEGIN " + pemHeader + "-----\r\n" + 465 pemBody + 466 "\r\n-----END " + pemHeader + "-----\r\n"; 467 } 468 469 /** 470 * get hexacedimal string from PEM format data<br/> 471 * @name pemtohex 472 * @function 473 * @param {String} s PEM formatted string 474 * @param {String} sHead PEM header string without BEGIN/END(OPTION) 475 * @return {String} hexadecimal string data of PEM contents 476 * @since jsrsasign 7.2.1 base64x 1.1.12 477 * @description 478 * This static method gets a hexacedimal string of contents 479 * from PEM format data. You can explicitly specify PEM header 480 * by sHead argument. 481 * Any space characters such as white space or new line 482 * will be omitted.<br/> 483 * NOTE: Now {@link KEYUTIL.getHexFromPEM} and {@link X509.pemToHex} 484 * have been deprecated since jsrsasign 7.2.1. 485 * Please use this method instead. 486 * @example 487 * pemtohex("-----BEGIN PUBLIC KEY...") → "3082..." 488 * pemtohex("-----BEGIN CERTIFICATE...", "CERTIFICATE") → "3082..." 489 * pemtohex(" \r\n-----BEGIN DSA PRIVATE KEY...") → "3082..." 490 */ 491 function pemtohex(s, sHead) { 492 if (s.indexOf("-----BEGIN ") == -1) 493 throw "can't find PEM header: " + sHead; 494 495 if (sHead !== undefined) { 496 s = s.replace("-----BEGIN " + sHead + "-----", ""); 497 s = s.replace("-----END " + sHead + "-----", ""); 498 } else { 499 s = s.replace(/-----BEGIN [^-]+-----/, ''); 500 s = s.replace(/-----END [^-]+-----/, ''); 501 } 502 return b64nltohex(s); 503 } 504 505 // ==== hex / ArrayBuffer ================================= 506 507 /** 508 * convert a hexadecimal string to an ArrayBuffer<br/> 509 * @name hextoArrayBuffer 510 * @function 511 * @param {String} hex hexadecimal string 512 * @return {ArrayBuffer} ArrayBuffer 513 * @since jsrsasign 6.1.4 base64x 1.1.8 514 * @description 515 * This function converts from a hexadecimal string to an ArrayBuffer. 516 * @example 517 * hextoArrayBuffer("fffa01") → ArrayBuffer of [255, 250, 1] 518 */ 519 function hextoArrayBuffer(hex) { 520 if (hex.length % 2 != 0) throw "input is not even length"; 521 if (hex.match(/^[0-9A-Fa-f]+$/) == null) throw "input is not hexadecimal"; 522 523 var buffer = new ArrayBuffer(hex.length / 2); 524 var view = new DataView(buffer); 525 526 for (var i = 0; i < hex.length / 2; i++) { 527 view.setUint8(i, parseInt(hex.substr(i * 2, 2), 16)); 528 } 529 530 return buffer; 531 } 532 533 // ==== ArrayBuffer / hex ================================= 534 535 /** 536 * convert an ArrayBuffer to a hexadecimal string<br/> 537 * @name ArrayBuffertohex 538 * @function 539 * @param {ArrayBuffer} buffer ArrayBuffer 540 * @return {String} hexadecimal string 541 * @since jsrsasign 6.1.4 base64x 1.1.8 542 * @description 543 * This function converts from an ArrayBuffer to a hexadecimal string. 544 * @example 545 * var buffer = new ArrayBuffer(3); 546 * var view = new DataView(buffer); 547 * view.setUint8(0, 0xfa); 548 * view.setUint8(1, 0xfb); 549 * view.setUint8(2, 0x01); 550 * ArrayBuffertohex(buffer) → "fafb01" 551 */ 552 function ArrayBuffertohex(buffer) { 553 var hex = ""; 554 var view = new DataView(buffer); 555 556 for (var i = 0; i < buffer.byteLength; i++) { 557 hex += ("00" + view.getUint8(i).toString(16)).slice(-2); 558 } 559 560 return hex; 561 } 562 563 // ==== zulu / int ================================= 564 /** 565 * GeneralizedTime or UTCTime string to milliseconds from Unix origin<br> 566 * @name zulutomsec 567 * @function 568 * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 569 * @return {Number} milliseconds from Unix origin time (i.e. Jan 1, 1970 0:00:00 UTC) 570 * @since jsrsasign 7.1.3 base64x 1.1.9 571 * @description 572 * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 573 * UTCTime string (i.e. YYMMDDHHmmSSZ) to milliseconds from Unix origin time 574 * (i.e. Jan 1 1970 0:00:00 UTC). 575 * Argument string may have fraction of seconds and 576 * its length is one or more digits such as "20170410235959.1234567Z". 577 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 578 * If year "YY" is equal or greater than 50 then it is 19YY. 579 * @example 580 * zulutomsec( "071231235959Z") → 1199145599000 #Mon, 31 Dec 2007 23:59:59 GMT 581 * zulutomsec( "071231235959.1Z") → 1199145599100 #Mon, 31 Dec 2007 23:59:59 GMT 582 * zulutomsec( "071231235959.12345Z") → 1199145599123 #Mon, 31 Dec 2007 23:59:59 GMT 583 * zulutomsec("20071231235959Z") → 1199145599000 #Mon, 31 Dec 2007 23:59:59 GMT 584 * zulutomsec( "931231235959Z") → -410227201000 #Mon, 31 Dec 1956 23:59:59 GMT 585 */ 586 function zulutomsec(s) { 587 var year, month, day, hour, min, sec, msec, d; 588 var sYear, sFrac, sMsec, matchResult; 589 590 matchResult = s.match(/^(\d{2}|\d{4})(\d\d)(\d\d)(\d\d)(\d\d)(\d\d)(|\.\d+)Z$/); 591 592 if (matchResult) { 593 sYear = matchResult[1]; 594 year = parseInt(sYear); 595 if (sYear.length === 2) { 596 if (50 <= year && year < 100) { 597 year = 1900 + year; 598 } else if (0 <= year && year < 50) { 599 year = 2000 + year; 600 } 601 } 602 month = parseInt(matchResult[2]) - 1; 603 day = parseInt(matchResult[3]); 604 hour = parseInt(matchResult[4]); 605 min = parseInt(matchResult[5]); 606 sec = parseInt(matchResult[6]); 607 msec = 0; 608 609 sFrac = matchResult[7]; 610 if (sFrac !== "") { 611 sMsec = (sFrac.substr(1) + "00").substr(0, 3); // .12 -> 012 612 msec = parseInt(sMsec); 613 } 614 return Date.UTC(year, month, day, hour, min, sec, msec); 615 } 616 throw "unsupported zulu format: " + s; 617 } 618 619 /** 620 * GeneralizedTime or UTCTime string to seconds from Unix origin<br> 621 * @name zulutosec 622 * @function 623 * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 624 * @return {Number} seconds from Unix origin time (i.e. Jan 1, 1970 0:00:00 UTC) 625 * @since jsrsasign 7.1.3 base64x 1.1.9 626 * @description 627 * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 628 * UTCTime string (i.e. YYMMDDHHmmSSZ) to seconds from Unix origin time 629 * (i.e. Jan 1 1970 0:00:00 UTC). Argument string may have fraction of seconds 630 * however result value will be omitted. 631 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 632 * If year "YY" is equal or greater than 50 then it is 19YY. 633 * @example 634 * zulutosec( "071231235959Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT 635 * zulutosec( "071231235959.1Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT 636 * zulutosec("20071231235959Z") → 1199145599 #Mon, 31 Dec 2007 23:59:59 GMT 637 */ 638 function zulutosec(s) { 639 var msec = zulutomsec(s); 640 return ~~(msec / 1000); 641 } 642 643 // ==== zulu / Date ================================= 644 645 /** 646 * GeneralizedTime or UTCTime string to Date object<br> 647 * @name zulutodate 648 * @function 649 * @param {String} s GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 650 * @return {Date} Date object for specified time 651 * @since jsrsasign 7.1.3 base64x 1.1.9 652 * @description 653 * This function converts from GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 654 * UTCTime string (i.e. YYMMDDHHmmSSZ) to Date object. 655 * Argument string may have fraction of seconds and 656 * its length is one or more digits such as "20170410235959.1234567Z". 657 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 658 * If year "YY" is equal or greater than 50 then it is 19YY. 659 * @example 660 * zulutodate( "071231235959Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT" 661 * zulutodate( "071231235959.1Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT" 662 * zulutodate("20071231235959Z").toUTCString() → "Mon, 31 Dec 2007 23:59:59 GMT" 663 * zulutodate( "071231235959.34").getMilliseconds() → 340 664 */ 665 function zulutodate(s) { 666 return new Date(zulutomsec(s)); 667 } 668 669 // ==== Date / zulu ================================= 670 671 /** 672 * Date object to zulu time string<br> 673 * @name datetozulu 674 * @function 675 * @param {Date} d Date object for specified time 676 * @param {Boolean} flagUTCTime if this is true year will be YY otherwise YYYY 677 * @param {Boolean} flagMilli if this is true result concludes milliseconds 678 * @return {String} GeneralizedTime or UTCTime string (ex. 20170412235959.384Z) 679 * @since jsrsasign 7.2.0 base64x 1.1.11 680 * @description 681 * This function converts from Date object to GeneralizedTime string (i.e. YYYYMMDDHHmmSSZ) or 682 * UTCTime string (i.e. YYMMDDHHmmSSZ). 683 * As for UTCTime, if year "YY" is equal or less than 49 then it is 20YY. 684 * If year "YY" is equal or greater than 50 then it is 19YY. 685 * If flagMilli is true its result concludes milliseconds such like 686 * "20170520235959.42Z". 687 * @example 688 * d = new Date(Date.UTC(2017,4,20,23,59,59,670)); 689 * datetozulu(d) → "20170520235959Z" 690 * datetozulu(d, true) → "170520235959Z" 691 * datetozulu(d, false, true) → "20170520235959.67Z" 692 */ 693 function datetozulu(d, flagUTCTime, flagMilli) { 694 var s; 695 var year = d.getUTCFullYear(); 696 if (flagUTCTime) { 697 if (year < 1950 || 2049 < year) 698 throw "not proper year for UTCTime: " + year; 699 s = ("" + year).slice(-2); 700 } else { 701 s = ("000" + year).slice(-4); 702 } 703 s += ("0" + (d.getUTCMonth() + 1)).slice(-2); 704 s += ("0" + d.getUTCDate()).slice(-2); 705 s += ("0" + d.getUTCHours()).slice(-2); 706 s += ("0" + d.getUTCMinutes()).slice(-2); 707 s += ("0" + d.getUTCSeconds()).slice(-2); 708 if (flagMilli) { 709 var milli = d.getUTCMilliseconds(); 710 if (milli !== 0) { 711 milli = ("00" + milli).slice(-3); 712 milli = milli.replace(/0+$/g, ""); 713 s += "." + milli; 714 } 715 } 716 s += "Z"; 717 return s; 718 } 719 720 // ==== URIComponent / hex ================================ 721 /** 722 * convert a URLComponent string such like "%67%68" to a hexadecimal string.<br/> 723 * @name uricmptohex 724 * @function 725 * @param {String} s URIComponent string such like "%67%68" 726 * @return {String} hexadecimal string 727 * @since 1.1 728 */ 729 function uricmptohex(s) { 730 return s.replace(/%/g, ""); 731 } 732 733 /** 734 * convert a hexadecimal string to a URLComponent string such like "%67%68".<br/> 735 * @name hextouricmp 736 * @function 737 * @param {String} s hexadecimal string 738 * @return {String} URIComponent string such like "%67%68" 739 * @since 1.1 740 */ 741 function hextouricmp(s) { 742 return s.replace(/(..)/g, "%$1"); 743 } 744 745 // ==== URIComponent ================================ 746 /** 747 * convert UTFa hexadecimal string to a URLComponent string such like "%67%68".<br/> 748 * Note that these "<code>0-9A-Za-z!'()*-._~</code>" characters will not 749 * converted to "%xx" format by builtin 'encodeURIComponent()' function. 750 * However this 'encodeURIComponentAll()' function will convert 751 * all of characters into "%xx" format. 752 * @name encodeURIComponentAll 753 * @function 754 * @param {String} s hexadecimal string 755 * @return {String} URIComponent string such like "%67%68" 756 * @since 1.1 757 */ 758 function encodeURIComponentAll(u8) { 759 var s = encodeURIComponent(u8); 760 var s2 = ""; 761 for (var i = 0; i < s.length; i++) { 762 if (s[i] == "%") { 763 s2 = s2 + s.substr(i, 3); 764 i = i + 2; 765 } else { 766 s2 = s2 + "%" + stohex(s[i]); 767 } 768 } 769 return s2; 770 } 771 772 // ==== new lines ================================ 773 /** 774 * convert all DOS new line("\r\n") to UNIX new line("\n") in 775 * a String "s". 776 * @name newline_toUnix 777 * @function 778 * @param {String} s string 779 * @return {String} converted string 780 */ 781 function newline_toUnix(s) { 782 s = s.replace(/\r\n/mg, "\n"); 783 return s; 784 } 785 786 /** 787 * convert all UNIX new line("\r\n") to DOS new line("\n") in 788 * a String "s". 789 * @name newline_toDos 790 * @function 791 * @param {String} s string 792 * @return {String} converted string 793 */ 794 function newline_toDos(s) { 795 s = s.replace(/\r\n/mg, "\n"); 796 s = s.replace(/\n/mg, "\r\n"); 797 return s; 798 } 799 800 // ==== string type checker =================== 801 802 /** 803 * check whether a string is an integer string or not<br/> 804 * @name isInteger 805 * @memberOf KJUR.lang.String 806 * @function 807 * @static 808 * @param {String} s input string 809 * @return {Boolean} true if a string "s" is an integer string otherwise false 810 * @since base64x 1.1.7 jsrsasign 5.0.13 811 * @example 812 * KJUR.lang.String.isInteger("12345") → true 813 * KJUR.lang.String.isInteger("123ab") → false 814 */ 815 KJUR.lang.String.isInteger = function(s) { 816 if (s.match(/^[0-9]+$/)) { 817 return true; 818 } else if (s.match(/^-[0-9]+$/)) { 819 return true; 820 } else { 821 return false; 822 } 823 }; 824 825 /** 826 * check whether a string is an hexadecimal string or not<br/> 827 * @name isHex 828 * @memberOf KJUR.lang.String 829 * @function 830 * @static 831 * @param {String} s input string 832 * @return {Boolean} true if a string "s" is an hexadecimal string otherwise false 833 * @since base64x 1.1.7 jsrsasign 5.0.13 834 * @example 835 * KJUR.lang.String.isHex("1234") → true 836 * KJUR.lang.String.isHex("12ab") → true 837 * KJUR.lang.String.isHex("12AB") → true 838 * KJUR.lang.String.isHex("12ZY") → false 839 * KJUR.lang.String.isHex("121") → false -- odd length 840 */ 841 KJUR.lang.String.isHex = function(s) { 842 if (s.length % 2 == 0 && 843 (s.match(/^[0-9a-f]+$/) || s.match(/^[0-9A-F]+$/))) { 844 return true; 845 } else { 846 return false; 847 } 848 }; 849 850 /** 851 * check whether a string is a base64 encoded string or not<br/> 852 * Input string can conclude new lines or space characters. 853 * @name isBase64 854 * @memberOf KJUR.lang.String 855 * @function 856 * @static 857 * @param {String} s input string 858 * @return {Boolean} true if a string "s" is a base64 encoded string otherwise false 859 * @since base64x 1.1.7 jsrsasign 5.0.13 860 * @example 861 * KJUR.lang.String.isBase64("YWE=") → true 862 * KJUR.lang.String.isBase64("YW_=") → false 863 * KJUR.lang.String.isBase64("YWE") → false -- length shall be multiples of 4 864 */ 865 KJUR.lang.String.isBase64 = function(s) { 866 s = s.replace(/\s+/g, ""); 867 if (s.match(/^[0-9A-Za-z+\/]+={0,3}$/) && s.length % 4 == 0) { 868 return true; 869 } else { 870 return false; 871 } 872 }; 873 874 /** 875 * check whether a string is a base64url encoded string or not<br/> 876 * Input string can conclude new lines or space characters. 877 * @name isBase64URL 878 * @memberOf KJUR.lang.String 879 * @function 880 * @static 881 * @param {String} s input string 882 * @return {Boolean} true if a string "s" is a base64url encoded string otherwise false 883 * @since base64x 1.1.7 jsrsasign 5.0.13 884 * @example 885 * KJUR.lang.String.isBase64URL("YWE") → true 886 * KJUR.lang.String.isBase64URL("YW-") → true 887 * KJUR.lang.String.isBase64URL("YW+") → false 888 */ 889 KJUR.lang.String.isBase64URL = function(s) { 890 if (s.match(/[+/=]/)) return false; 891 s = b64utob64(s); 892 return KJUR.lang.String.isBase64(s); 893 }; 894 895 /** 896 * check whether a string is a string of integer array or not<br/> 897 * Input string can conclude new lines or space characters. 898 * @name isIntegerArray 899 * @memberOf KJUR.lang.String 900 * @function 901 * @static 902 * @param {String} s input string 903 * @return {Boolean} true if a string "s" is a string of integer array otherwise false 904 * @since base64x 1.1.7 jsrsasign 5.0.13 905 * @example 906 * KJUR.lang.String.isIntegerArray("[1,2,3]") → true 907 * KJUR.lang.String.isIntegerArray(" [1, 2, 3 ] ") → true 908 * KJUR.lang.String.isIntegerArray("[a,2]") → false 909 */ 910 KJUR.lang.String.isIntegerArray = function(s) { 911 s = s.replace(/\s+/g, ""); 912 if (s.match(/^\[[0-9,]+\]$/)) { 913 return true; 914 } else { 915 return false; 916 } 917 }; 918 919 // ==== others ================================ 920 921 /** 922 * canonicalize hexadecimal string of positive integer<br/> 923 * @name hextoposhex 924 * @function 925 * @param {String} s hexadecimal string 926 * @return {String} canonicalized hexadecimal string of positive integer 927 * @since base64x 1.1.10 jsrsasign 7.1.4 928 * @description 929 * This method canonicalize a hexadecimal string of positive integer 930 * for two's complement representation. 931 * Canonicalized hexadecimal string of positive integer will be: 932 * <ul> 933 * <li>Its length is always even.</li> 934 * <li>If odd length it will be padded with leading zero.<li> 935 * <li>If it is even length and its first character is "8" or greater, 936 * it will be padded with "00" to make it positive integer.</li> 937 * </ul> 938 * @example 939 * hextoposhex("abcd") → "00abcd" 940 * hextoposhex("1234") → "1234" 941 * hextoposhex("12345") → "012345" 942 */ 943 function hextoposhex(s) { 944 if (s.length % 2 == 1) return "0" + s; 945 if (s.substr(0, 1) > "7") return "00" + s; 946 return s; 947 } 948 949 /** 950 * convert string of integer array to hexadecimal string.<br/> 951 * @name intarystrtohex 952 * @function 953 * @param {String} s string of integer array 954 * @return {String} hexadecimal string 955 * @since base64x 1.1.6 jsrsasign 5.0.2 956 * @throws "malformed integer array string: *" for wrong input 957 * @description 958 * This function converts a string of JavaScript integer array to 959 * a hexadecimal string. Each integer value shall be in a range 960 * from 0 to 255 otherwise it raise exception. Input string can 961 * have extra space or newline string so that they will be ignored. 962 * 963 * @example 964 * intarystrtohex(" [123, 34, 101, 34, 58] ") 965 * → 7b2265223a (i.e. '{"e":' as string) 966 */ 967 function intarystrtohex(s) { 968 s = s.replace(/^\s*\[\s*/, ''); 969 s = s.replace(/\s*\]\s*$/, ''); 970 s = s.replace(/\s*/g, ''); 971 try { 972 var hex = s.split(/,/).map(function(element, index, array) { 973 var i = parseInt(element); 974 if (i < 0 || 255 < i) throw "integer not in range 0-255"; 975 var hI = ("00" + i.toString(16)).slice(-2); 976 return hI; 977 }).join(''); 978 return hex; 979 } catch(ex) { 980 throw "malformed integer array string: " + ex; 981 } 982 } 983 984 /** 985 * find index of string where two string differs 986 * @name strdiffidx 987 * @function 988 * @param {String} s1 string to compare 989 * @param {String} s2 string to compare 990 * @return {Number} string index of where character differs. Return -1 if same. 991 * @since jsrsasign 4.9.0 base64x 1.1.5 992 * @example 993 * strdiffidx("abcdefg", "abcd4fg") -> 4 994 * strdiffidx("abcdefg", "abcdefg") -> -1 995 * strdiffidx("abcdefg", "abcdef") -> 6 996 * strdiffidx("abcdefgh", "abcdef") -> 6 997 */ 998 var strdiffidx = function(s1, s2) { 999 var n = s1.length; 1000 if (s1.length > s2.length) n = s2.length; 1001 for (var i = 0; i < n; i++) { 1002 if (s1.charCodeAt(i) != s2.charCodeAt(i)) return i; 1003 } 1004 if (s1.length != s2.length) return n; 1005 return -1; // same 1006 }; 1007 1008 1009