123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- /*
- * Copyright 2018 Scytl Secure Electronic Voting SA
- *
- * All rights reserved
- *
- * See our extended copyright notice in *file 'Copyright.txt' which is part of this source code package
- */
- cryptolib.modules.commons = cryptolib.modules.commons || {};
- /** namespace commons/utils */
- cryptolib.modules.commons.utils = function(box) {
- 'use strict';
- box.commons = box.commons || {};
- /**
- * A module that holds utility functionalities.
- *
- * @exports commons/utils
- */
- box.commons.utils = {};
- var exceptions;
- cryptolib('commons.exceptions', function(box) {
- exceptions = box.commons.exceptions;
- });
- /**
- * Defines some useful functions for data manipulation and type conversion.
- *
- * @class
- */
- box.commons.utils.Converters = function() {};
- box.commons.utils.Converters.prototype = {
- /**
- * Base64 encodes some data.
- *
- * @function
- * @param {string}
- * data data to Base64 encode.
- * @param {number}
- * lineLength line length of encoding (No line breaks if not
- * specified).
- * @returns {string} base64 encoded data.
- */
- base64Encode: function(data, lineLength) {
- if (lineLength === undefined || lineLength === null) {
- return forge.util.encode64(data);
- } else {
- return forge.util.encode64(data, lineLength);
- }
- },
- /**
- * Base64 decodes some data.
- *
- * @function
- * @param {string}
- * dataB64 data to Base64 decode.
- * @returns {string} base64 decoded data.
- */
- base64Decode: function(dataB64) {
- return forge.util.decode64(dataB64);
- },
- /**
- * Converts a string to a collection of bytes.
- *
- * @function
- * @param {string}
- * str string to convert to collection of bytes.
- * @returns collection of bytes from string.
- */
- bytesFromString: function(str) {
- var bytes = [];
- for (var i = 0; i < str.length; i++) {
- bytes.push(str.charCodeAt(i));
- }
- return bytes;
- },
- /**
- * Converts a collection of bytes to a string.
- *
- * @function
- * @param {string}
- * bytes collection of bytes to convert to string.
- * @return {string} string from collection of bytes.
- */
- bytesToString: function(bytes) {
- var string = '';
- for (var i = 0; i < bytes.length; i++) {
- string += String.fromCharCode(bytes[i]);
- }
- return string;
- },
- /**
- * Converts a string to a hexadecimal string.
- *
- * @function
- * @param {string}
- * str String to convert.
- * @returns string string in hexadecimal format.
- */
- hexFromString: function(str) {
- return forge.util.bytesToHex(str);
- },
- /**
- * Converts a hexadecimal string to a string.
- *
- * @function
- * @param {string}
- * hexStr hexadecimal string to convert.
- * @returns {string} String from conversion.
- */
- hexToString: function(hexStr) {
- return forge.util.hexToBytes(hexStr);
- },
- /**
- * Converts a BigInteger object to a base64 string.
- *
- * @function
- * @param {object}
- * bigInteger forge.jsbn.BigInteger to convert.
- * @returns {string} base64 string from conversion.
- */
- base64FromBigInteger: function(bigInteger) {
- var array = new Uint8Array(bigInteger.toByteArray());
- return box.forge.util.binary.base64.encode(array);
- },
- /**
- * Converts a base64 string to a BigInteger object.
- *
- * @function
- * @param {string}
- * base64Str base64 string to convert.
- * @returns {object} forge.jsbn.BigInteger from conversion.
- */
- base64ToBigInteger: function(base64Str) {
- var buffer = this.base64Decode(base64Str);
- var hex = this.hexFromString(buffer);
- return new forge.jsbn.BigInteger(hex, 16);
- }
- };
- /**
- * Defines a set of bit operator utilities.
- *
- * @class
- */
- box.commons.utils.BitOperators = function() {};
- box.commons.utils.BitOperators.prototype = {
- /**
- * Bit-wise concatenates some data to some existing data.
- *
- * @function
- * @param {string}
- * data1 existing data, as string.
- * @param {string}
- * data2 data to concatenate, as string.
- * @returns {string} bit-wise concatenation of data, as string.
- */
- concatenate: function(data1, data2) {
- try {
- var converters = new box.commons.utils.Converters();
- var data1Bytes = converters.bytesFromString(data1);
- var data2Bytes = converters.bytesFromString(data2);
- var concatDataBytes = data1Bytes.concat(data2Bytes);
- return converters.bytesToString(concatDataBytes);
- } catch (error) {
- throw new exceptions.CryptoLibException(
- 'Data could not be bit-wise concatenated.', error);
- }
- },
- /**
- * Unpacks a data subset from a bitwise concatenation of data.
- *
- * @function
- * @param {string}
- * concatData bit-wise concatenation of data, as string.
- * @param {number}
- * offset offset of data subset in concatenation.
- * @param {number}
- * size size of data subset.
- * @returns {string} data subset, as string.
- */
- extract: function(concatData, offset, size) {
- try {
- var converters = new box.commons.utils.Converters();
- var concatDataBytes = converters.bytesFromString(concatData);
- var dataSubsetBytes = concatDataBytes.slice(offset, size);
- return converters.bytesToString(dataSubsetBytes);
- } catch (error) {
- throw new exceptions.CryptoLibException(
- 'Data could not be bit-wise extracted.', error);
- }
- }
- };
- /**
- * Defines a set of time utilities.
- *
- * @class
- */
- box.commons.utils.TimeUtils = function() {};
- box.commons.utils.TimeUtils.prototype = {
- /**
- * Generates a time stamp in Unix time, i.e. the number of seconds that
- * have elapsed since 00:00:00 Coordinated Universal Time (UTC), 1
- * January 1970.
- *
- * @function
- * @returns {number} time stamp in seconds, as integer.
- */
- unixTimeStamp: function() {
- try {
- return Math.round(new Date().getTime() / 1000);
- } catch (error) {
- throw new exceptions.CryptoLibException(
- 'Could not generate Unix timestamp.', error);
- }
- },
- /**
- * Generates a time stamp in Unix time, i.e. the number of seconds that
- * have elapsed since 00:00:00 Coordinated Universal Time (UTC), 1
- * January 1970. The value is returned as a floating point number.
- *
- * @function
- * @returns {number} time stamp in seconds, as floating point number.
- */
- unixTimeStampFloat: function() {
- try {
- return new Date().getTime() / 1000;
- } catch (error) {
- throw new exceptions.CryptoLibException(
- 'Could not generate Unix timestamp.', error);
- }
- }
- };
- /**
- * Defines a set of xpath utilities.
- *
- * @class
- * @param {string}
- * path path in XPathForm notation Eg.
- * <form><name>test</name></form> to '/form/name'
- */
- box.commons.utils.XPath = function(xml, path) {
- this.path = path;
- this.node = xml;
- var pathTree = path ? path.split('/') : [];
- for (var i = 0; i < pathTree.length; i++) {
- if (pathTree[i] && this.node) {
- var found = false;
- for (var j = 0; j < this.node.childNodes.length; j++) {
- var child = this.node.childNodes[j];
- // we found the node
- if (child.nodeType === Node.ELEMENT_NODE &&
- child.tagName.toLowerCase() === pathTree[i].toLowerCase()) {
- this.node = child;
- found = true;
- break;
- }
- }
- // invalid xpath
- if (!found) {
- this.node = null;
- throw new exceptions.CryptoLibException('Invalid xpath for: ' + path);
- }
- }
- }
- };
- box.commons.utils.XPath.prototype = {
- /**
- * Gets the value of a node. For example <node>value</node> returns
- * value.
- *
- * @function
- * @returns {string} the value, as string.
- */
- getValue: function() {
- return this.node ? this.node.childNodes[0].nodeValue : '';
- },
- /**
- * Returns the value of an attribute of a node. For example <node
- * attr="attr value">node value</node> returns "attr value".
- *
- * @function
- * @param {object}
- * attribute attribute to get the value.
- * @returns attribute value, as string.
- */
- getAttribute: function(attribute) {
- return this.node ? this.node.getAttribute(attribute) : '';
- },
- /**
- * Gets the node itself-
- *
- * @function
- * @returns {object} xml document, as a DOM object.
- */
- getXml: function() {
- return this.node;
- },
- /**
- * Gets an array of child nodes
- *
- * @function
- * @returns {object} xml document array with all children as DOM
- * objects.
- */
- getChildren: function() {
- return this.node ? this.node.childNodes : '';
- }
- };
- /**
- * Defines a set of string utilities.
- *
- * @class
- */
- box.commons.utils.StringUtils = function() {
- };
- box.commons.utils.StringUtils.prototype = {
- /**
- * Check if a string is within another string
- *
- * @function
- * @param {string}
- * main text
- * @param {string}
- * substring substring to search in the main text
- * @param caseSensitive
- * boolean, case sensitive the search
- *
- * @returns {boolean} boolean, true if found
- */
- containsSubString: function(string, substring, caseSensitive) {
- var main = string, sub = substring;
- if (!caseSensitive) {
- main = main.toLowerCase();
- sub = sub.toLowerCase();
- }
- return main.indexOf(sub) > -1;
- }
- };
- /**
- * Defines a set of parser utilities.
- *
- * @class
- */
- box.commons.utils.Parsers = function() {};
- box.commons.utils.Parsers.prototype = {
- /**
- * Converts a string to an XML document.
- *
- * @function
- * @param {string}
- * str String to convert.
- * @returns {string} XML document, as string.
- */
- xmlFromString: function(str) {
- if (this.isIE()) {
- // Remove null terminating character if exists
- var strNoNull = this.removeNullTerminatingChar(str);
- var xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM');
- xmlDoc.async = false;
- xmlDoc.loadXML(strNoNull);
- return xmlDoc;
- } else if (typeof window.DOMParser !== 'undefined') {
- return (new window.DOMParser()).parseFromString(str, 'text/xml');
- } else {
- throw new exceptions.CryptoLibException(
- 'XML string could not be parsed.');
- }
- },
- /**
- * Converts an XML document to a string.
- *
- * @fuction
- * @param {string}
- * xmlDoc xml document to convert, as string.
- * @param {boolean}
- * removeSelfClosingTags removes self closing tags to
- * explicit tags. Example: <tag/> to <tag></tag>
- * @returns {string} string from conversion.
- */
- xmlToString: function(xmlDoc, removeSelfClosingTags) {
- var result = this.xmlToStringIeCompatible(xmlDoc);
- if (removeSelfClosingTags) {
- result = this.xmlRemoveSelfClosingTags(result);
- }
- return result;
- },
- xmlRemoveSelfClosingTags: function(data) {
- var split = data.split('/>');
- var newXml = '';
- for (var i = 0; i < split.length - 1; i++) {
- var edsplit = split[i].split('<');
- newXml +=
- split[i] + '></' + edsplit[edsplit.length - 1].split(' ')[0] + '>';
- }
- return newXml + split[split.length - 1];
- },
- xmlToStringIeCompatible: function(xmlNode) {
- if (this.isIE()) {
- return xmlNode.xml;
- } else if (typeof window.XMLSerializer !== 'undefined') {
- return (new window.XMLSerializer()).serializeToString(xmlNode);
- } else {
- throw new exceptions.CryptoLibException(
- 'Error while tring to construct XML from String.');
- }
- },
- /**
- * Removes all newline characters from some data.
- *
- * @function
- * @param {string}
- * data data from which to remove all newline characters, as
- * string.
- * @returns {string} data with all newline characters removed, as
- * string.
- */
- removeNewLineChars: function(data) {
- return data.replace(/(\r\n|\n|\r)/gm, '');
- },
- /**
- * Removes all carriage return characters from some data.
- *
- * @param data
- * Data from which to remove all carriage return characters,
- * as string.
- * @return Data with all carriage return characters removed, as string.
- */
- removeCarriageReturnChars: function(data) {
- return data.replace(/(\r)/gm, '');
- },
- /**
- * Removes the null terminating character from some data.
- *
- * @function
- * @param {string}
- * data Data from which to remove the null terminating
- * character, as string.
- * @returns {string} data with null terminating character removed, as
- * string.
- */
- removeNullTerminatingChar: function(data) {
- return data.replace(/\x00+$/, '');
- },
- /**
- * Removes the XML header from a string representing an XML.
- *
- * @param data
- * The XML string from which to remove the XML header.
- * @return XML string with the XML header removed.
- */
- removeXmlHeaderFromString: function(data) {
- return data.replace('<?xml version="1.0" encoding="UTF-8"?>', '');
- },
- /**
- * Removes the signature node from a string representing an XML.
- *
- * @param data
- * The XML string from which to remove the signature node.
- * @return XML string with the signature node removed.
- */
- removeXmlSignature: function(data) {
- return data.replace(/<Signature[\s\S]*?Signature>/g, '');
- },
- /**
- * Detects if the client agent is Microsoft Internet Explorer. This has
- * been tested to work with Internet Explorer 9, 10 and 11. If this
- * software is to be used on other versions, then it should be checked
- * if those versions are supported by this function and if they are not
- * then this function should be updated.
- */
- isIE: function() {
- var ua = window.navigator.userAgent;
- var msie = ua.indexOf('MSIE ');
- if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
- return true;
- } else {
- return false;
- }
- }
- };
- /**
- * Defines a set of connectors.
- *
- * @class
- */
- box.commons.utils.Connectors = function() {};
- box.commons.utils.Connectors.prototype = {
- /**
- * Posts a request message to a destination via HTTP.
- *
- * @function
- * @param {string}
- * request request message to post, as string.
- * @param {string}
- * url url of request destination, as string.
- * @param {boolean}
- * isAsynch boolean indicating whether the post is
- * asynchronous.
- * @return {string} response retrieved from request destination, as
- * string.
- */
- postHttpRequestMessage: function(request, url, isAsynch) {
- // Check if a post destination was provided.
- if (url === '') {
- throw new exceptions.CryptoLibException(
- 'No URL provided for posting HTTP request.');
- }
- // Create HTTP request object.
- var httpRequest;
- var done;
- if (window.XMLHttpRequest) {
- httpRequest = new XMLHttpRequest();
- done = XMLHttpRequest.DONE;
- } else {
- throw new exceptions.CryptoLibException(
- 'Could not create HTTP request object for this browser.');
- }
- // Define post response message handling.
- var response;
- httpRequest.onreadystatechange = function() {
- if (httpRequest.readyState === done) {
- if (httpRequest.status === 200) {
- response = httpRequest.responseText;
- } else {
- var errorMsg =
- 'HTTP request message POST was not successful.\n Status: ' +
- httpRequest.status + ', Message: ' + httpRequest.statusText;
- throw new exceptions.CryptoLibException(errorMsg);
- }
- }
- };
- // Open HTTP request object for synchronous post.
- httpRequest.open('POST', url, isAsynch);
- // Post HTTP request message.
- try {
- httpRequest.send(request);
- } catch (error) {
- var errorMsg =
- 'Could not post HTTP request message; IP of web application might be incorrect.';
- throw new exceptions.CryptoLibException(errorMsg, error);
- }
- return response;
- }
- };
- /**
- * Defines a progress meter.
- *
- * @param {integer}
- * progressMax Maximum amount of progress to be attained.
- * @param {integer}
- * progressCallback Progress callback function.
- * @param {integer}
- * progressPercentMinCheckInterval Progress percentage minimum
- * check interval (optional) (default: 10%).
- * @class
- */
- box.commons.utils.ProgressMeter = function(
- progressMax, progressCallback, progressPercentMinCheckInterval) {
- this.progressMax = progressMax;
- this.progressCallback = progressCallback;
- this.progressPercentMinCheckInterval =
- progressPercentMinCheckInterval || 10;
- this.lastProgressPercent = 0;
- };
- box.commons.utils.ProgressMeter.prototype = {
- /**
- * Calculates the progress as a percentage of the total and provides it
- * as input to the provided callback function.
- *
- * @function
- * @param {integer}
- * progress Present amount of progress.
- */
- update: function(progress) {
- if (typeof this.progressCallback === 'undefined') {
- return;
- }
- var progressPercent = Math.floor((progress / this.progressMax) * 100);
- progressPercent = Math.min(progressPercent, 100);
- var progressPercentChange = progressPercent - this.lastProgressPercent;
- if (progressPercentChange > 0) {
- var checkProgress =
- (progressPercentChange >= this.progressPercentMinCheckInterval) ||
- (progressPercent === 100);
- if (checkProgress) {
- this.lastProgressPercent = progressPercent;
- this.progressCallback(progressPercent);
- }
- }
- }
- };
- };
|