Show More
Commit Description:
force log out when password change
Commit Description:
force log out when password change
References:
File last commit:
Show/Diff file:
Action:
node_modules/jszip/lib/utils.js
| 476 lines
| 15.3 KiB
| application/javascript
| JavascriptLexer
|
r789 | 'use strict'; | |||
var support = require('./support'); | ||||
var base64 = require('./base64'); | ||||
var nodejsUtils = require('./nodejsUtils'); | ||||
var setImmediate = require('set-immediate-shim'); | ||||
var external = require("./external"); | ||||
/** | ||||
* Convert a string that pass as a "binary string": it should represent a byte | ||||
* array but may have > 255 char codes. Be sure to take only the first byte | ||||
* and returns the byte array. | ||||
* @param {String} str the string to transform. | ||||
* @return {Array|Uint8Array} the string in a binary format. | ||||
*/ | ||||
function string2binary(str) { | ||||
var result = null; | ||||
if (support.uint8array) { | ||||
result = new Uint8Array(str.length); | ||||
} else { | ||||
result = new Array(str.length); | ||||
} | ||||
return stringToArrayLike(str, result); | ||||
} | ||||
/** | ||||
* Create a new blob with the given content and the given type. | ||||
* @param {String|ArrayBuffer} part the content to put in the blob. DO NOT use | ||||
* an Uint8Array because the stock browser of android 4 won't accept it (it | ||||
* will be silently converted to a string, "[object Uint8Array]"). | ||||
* | ||||
* Use only ONE part to build the blob to avoid a memory leak in IE11 / Edge: | ||||
* when a large amount of Array is used to create the Blob, the amount of | ||||
* memory consumed is nearly 100 times the original data amount. | ||||
* | ||||
* @param {String} type the mime type of the blob. | ||||
* @return {Blob} the created blob. | ||||
*/ | ||||
exports.newBlob = function(part, type) { | ||||
exports.checkSupport("blob"); | ||||
try { | ||||
// Blob constructor | ||||
return new Blob([part], { | ||||
type: type | ||||
}); | ||||
} | ||||
catch (e) { | ||||
try { | ||||
// deprecated, browser only, old way | ||||
var Builder = self.BlobBuilder || self.WebKitBlobBuilder || self.MozBlobBuilder || self.MSBlobBuilder; | ||||
var builder = new Builder(); | ||||
builder.append(part); | ||||
return builder.getBlob(type); | ||||
} | ||||
catch (e) { | ||||
// well, fuck ?! | ||||
throw new Error("Bug : can't construct the Blob."); | ||||
} | ||||
} | ||||
}; | ||||
/** | ||||
* The identity function. | ||||
* @param {Object} input the input. | ||||
* @return {Object} the same input. | ||||
*/ | ||||
function identity(input) { | ||||
return input; | ||||
} | ||||
/** | ||||
* Fill in an array with a string. | ||||
* @param {String} str the string to use. | ||||
* @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to fill in (will be mutated). | ||||
* @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated array. | ||||
*/ | ||||
function stringToArrayLike(str, array) { | ||||
for (var i = 0; i < str.length; ++i) { | ||||
array[i] = str.charCodeAt(i) & 0xFF; | ||||
} | ||||
return array; | ||||
} | ||||
/** | ||||
* An helper for the function arrayLikeToString. | ||||
* This contains static information and functions that | ||||
* can be optimized by the browser JIT compiler. | ||||
*/ | ||||
var arrayToStringHelper = { | ||||
/** | ||||
* Transform an array of int into a string, chunk by chunk. | ||||
* See the performances notes on arrayLikeToString. | ||||
* @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. | ||||
* @param {String} type the type of the array. | ||||
* @param {Integer} chunk the chunk size. | ||||
* @return {String} the resulting string. | ||||
* @throws Error if the chunk is too big for the stack. | ||||
*/ | ||||
stringifyByChunk: function(array, type, chunk) { | ||||
var result = [], k = 0, len = array.length; | ||||
// shortcut | ||||
if (len <= chunk) { | ||||
return String.fromCharCode.apply(null, array); | ||||
} | ||||
while (k < len) { | ||||
if (type === "array" || type === "nodebuffer") { | ||||
result.push(String.fromCharCode.apply(null, array.slice(k, Math.min(k + chunk, len)))); | ||||
} | ||||
else { | ||||
result.push(String.fromCharCode.apply(null, array.subarray(k, Math.min(k + chunk, len)))); | ||||
} | ||||
k += chunk; | ||||
} | ||||
return result.join(""); | ||||
}, | ||||
/** | ||||
* Call String.fromCharCode on every item in the array. | ||||
* This is the naive implementation, which generate A LOT of intermediate string. | ||||
* This should be used when everything else fail. | ||||
* @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. | ||||
* @return {String} the result. | ||||
*/ | ||||
stringifyByChar: function(array){ | ||||
var resultStr = ""; | ||||
for(var i = 0; i < array.length; i++) { | ||||
resultStr += String.fromCharCode(array[i]); | ||||
} | ||||
return resultStr; | ||||
}, | ||||
applyCanBeUsed : { | ||||
/** | ||||
* true if the browser accepts to use String.fromCharCode on Uint8Array | ||||
*/ | ||||
uint8array : (function () { | ||||
try { | ||||
return support.uint8array && String.fromCharCode.apply(null, new Uint8Array(1)).length === 1; | ||||
} catch (e) { | ||||
return false; | ||||
} | ||||
})(), | ||||
/** | ||||
* true if the browser accepts to use String.fromCharCode on nodejs Buffer. | ||||
*/ | ||||
nodebuffer : (function () { | ||||
try { | ||||
return support.nodebuffer && String.fromCharCode.apply(null, nodejsUtils.allocBuffer(1)).length === 1; | ||||
} catch (e) { | ||||
return false; | ||||
} | ||||
})() | ||||
} | ||||
}; | ||||
/** | ||||
* Transform an array-like object to a string. | ||||
* @param {Array|ArrayBuffer|Uint8Array|Buffer} array the array to transform. | ||||
* @return {String} the result. | ||||
*/ | ||||
function arrayLikeToString(array) { | ||||
// Performances notes : | ||||
// -------------------- | ||||
// String.fromCharCode.apply(null, array) is the fastest, see | ||||
// see http://jsperf.com/converting-a-uint8array-to-a-string/2 | ||||
// but the stack is limited (and we can get huge arrays !). | ||||
// | ||||
// result += String.fromCharCode(array[i]); generate too many strings ! | ||||
// | ||||
// This code is inspired by http://jsperf.com/arraybuffer-to-string-apply-performance/2 | ||||
// TODO : we now have workers that split the work. Do we still need that ? | ||||
var chunk = 65536, | ||||
type = exports.getTypeOf(array), | ||||
canUseApply = true; | ||||
if (type === "uint8array") { | ||||
canUseApply = arrayToStringHelper.applyCanBeUsed.uint8array; | ||||
} else if (type === "nodebuffer") { | ||||
canUseApply = arrayToStringHelper.applyCanBeUsed.nodebuffer; | ||||
} | ||||
if (canUseApply) { | ||||
while (chunk > 1) { | ||||
try { | ||||
return arrayToStringHelper.stringifyByChunk(array, type, chunk); | ||||
} catch (e) { | ||||
chunk = Math.floor(chunk / 2); | ||||
} | ||||
} | ||||
} | ||||
// no apply or chunk error : slow and painful algorithm | ||||
// default browser on android 4.* | ||||
return arrayToStringHelper.stringifyByChar(array); | ||||
} | ||||
exports.applyFromCharCode = arrayLikeToString; | ||||
/** | ||||
* Copy the data from an array-like to an other array-like. | ||||
* @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayFrom the origin array. | ||||
* @param {Array|ArrayBuffer|Uint8Array|Buffer} arrayTo the destination array which will be mutated. | ||||
* @return {Array|ArrayBuffer|Uint8Array|Buffer} the updated destination array. | ||||
*/ | ||||
function arrayLikeToArrayLike(arrayFrom, arrayTo) { | ||||
for (var i = 0; i < arrayFrom.length; i++) { | ||||
arrayTo[i] = arrayFrom[i]; | ||||
} | ||||
return arrayTo; | ||||
} | ||||
// a matrix containing functions to transform everything into everything. | ||||
var transform = {}; | ||||
// string to ? | ||||
transform["string"] = { | ||||
"string": identity, | ||||
"array": function(input) { | ||||
return stringToArrayLike(input, new Array(input.length)); | ||||
}, | ||||
"arraybuffer": function(input) { | ||||
return transform["string"]["uint8array"](input).buffer; | ||||
}, | ||||
"uint8array": function(input) { | ||||
return stringToArrayLike(input, new Uint8Array(input.length)); | ||||
}, | ||||
"nodebuffer": function(input) { | ||||
return stringToArrayLike(input, nodejsUtils.allocBuffer(input.length)); | ||||
} | ||||
}; | ||||
// array to ? | ||||
transform["array"] = { | ||||
"string": arrayLikeToString, | ||||
"array": identity, | ||||
"arraybuffer": function(input) { | ||||
return (new Uint8Array(input)).buffer; | ||||
}, | ||||
"uint8array": function(input) { | ||||
return new Uint8Array(input); | ||||
}, | ||||
"nodebuffer": function(input) { | ||||
return nodejsUtils.newBufferFrom(input); | ||||
} | ||||
}; | ||||
// arraybuffer to ? | ||||
transform["arraybuffer"] = { | ||||
"string": function(input) { | ||||
return arrayLikeToString(new Uint8Array(input)); | ||||
}, | ||||
"array": function(input) { | ||||
return arrayLikeToArrayLike(new Uint8Array(input), new Array(input.byteLength)); | ||||
}, | ||||
"arraybuffer": identity, | ||||
"uint8array": function(input) { | ||||
return new Uint8Array(input); | ||||
}, | ||||
"nodebuffer": function(input) { | ||||
return nodejsUtils.newBufferFrom(new Uint8Array(input)); | ||||
} | ||||
}; | ||||
// uint8array to ? | ||||
transform["uint8array"] = { | ||||
"string": arrayLikeToString, | ||||
"array": function(input) { | ||||
return arrayLikeToArrayLike(input, new Array(input.length)); | ||||
}, | ||||
"arraybuffer": function(input) { | ||||
return input.buffer; | ||||
}, | ||||
"uint8array": identity, | ||||
"nodebuffer": function(input) { | ||||
return nodejsUtils.newBufferFrom(input); | ||||
} | ||||
}; | ||||
// nodebuffer to ? | ||||
transform["nodebuffer"] = { | ||||
"string": arrayLikeToString, | ||||
"array": function(input) { | ||||
return arrayLikeToArrayLike(input, new Array(input.length)); | ||||
}, | ||||
"arraybuffer": function(input) { | ||||
return transform["nodebuffer"]["uint8array"](input).buffer; | ||||
}, | ||||
"uint8array": function(input) { | ||||
return arrayLikeToArrayLike(input, new Uint8Array(input.length)); | ||||
}, | ||||
"nodebuffer": identity | ||||
}; | ||||
/** | ||||
* Transform an input into any type. | ||||
* The supported output type are : string, array, uint8array, arraybuffer, nodebuffer. | ||||
* If no output type is specified, the unmodified input will be returned. | ||||
* @param {String} outputType the output type. | ||||
* @param {String|Array|ArrayBuffer|Uint8Array|Buffer} input the input to convert. | ||||
* @throws {Error} an Error if the browser doesn't support the requested output type. | ||||
*/ | ||||
exports.transformTo = function(outputType, input) { | ||||
if (!input) { | ||||
// undefined, null, etc | ||||
// an empty string won't harm. | ||||
input = ""; | ||||
} | ||||
if (!outputType) { | ||||
return input; | ||||
} | ||||
exports.checkSupport(outputType); | ||||
var inputType = exports.getTypeOf(input); | ||||
var result = transform[inputType][outputType](input); | ||||
return result; | ||||
}; | ||||
/** | ||||
* Return the type of the input. | ||||
* The type will be in a format valid for JSZip.utils.transformTo : string, array, uint8array, arraybuffer. | ||||
* @param {Object} input the input to identify. | ||||
* @return {String} the (lowercase) type of the input. | ||||
*/ | ||||
exports.getTypeOf = function(input) { | ||||
if (typeof input === "string") { | ||||
return "string"; | ||||
} | ||||
if (Object.prototype.toString.call(input) === "[object Array]") { | ||||
return "array"; | ||||
} | ||||
if (support.nodebuffer && nodejsUtils.isBuffer(input)) { | ||||
return "nodebuffer"; | ||||
} | ||||
if (support.uint8array && input instanceof Uint8Array) { | ||||
return "uint8array"; | ||||
} | ||||
if (support.arraybuffer && input instanceof ArrayBuffer) { | ||||
return "arraybuffer"; | ||||
} | ||||
}; | ||||
/** | ||||
* Throw an exception if the type is not supported. | ||||
* @param {String} type the type to check. | ||||
* @throws {Error} an Error if the browser doesn't support the requested type. | ||||
*/ | ||||
exports.checkSupport = function(type) { | ||||
var supported = support[type.toLowerCase()]; | ||||
if (!supported) { | ||||
throw new Error(type + " is not supported by this platform"); | ||||
} | ||||
}; | ||||
exports.MAX_VALUE_16BITS = 65535; | ||||
exports.MAX_VALUE_32BITS = -1; // well, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" is parsed as -1 | ||||
/** | ||||
* Prettify a string read as binary. | ||||
* @param {string} str the string to prettify. | ||||
* @return {string} a pretty string. | ||||
*/ | ||||
exports.pretty = function(str) { | ||||
var res = '', | ||||
code, i; | ||||
for (i = 0; i < (str || "").length; i++) { | ||||
code = str.charCodeAt(i); | ||||
res += '\\x' + (code < 16 ? "0" : "") + code.toString(16).toUpperCase(); | ||||
} | ||||
return res; | ||||
}; | ||||
/** | ||||
* Defer the call of a function. | ||||
* @param {Function} callback the function to call asynchronously. | ||||
* @param {Array} args the arguments to give to the callback. | ||||
*/ | ||||
exports.delay = function(callback, args, self) { | ||||
setImmediate(function () { | ||||
callback.apply(self || null, args || []); | ||||
}); | ||||
}; | ||||
/** | ||||
* Extends a prototype with an other, without calling a constructor with | ||||
* side effects. Inspired by nodejs' `utils.inherits` | ||||
* @param {Function} ctor the constructor to augment | ||||
* @param {Function} superCtor the parent constructor to use | ||||
*/ | ||||
exports.inherits = function (ctor, superCtor) { | ||||
var Obj = function() {}; | ||||
Obj.prototype = superCtor.prototype; | ||||
ctor.prototype = new Obj(); | ||||
}; | ||||
/** | ||||
* Merge the objects passed as parameters into a new one. | ||||
* @private | ||||
* @param {...Object} var_args All objects to merge. | ||||
* @return {Object} a new object with the data of the others. | ||||
*/ | ||||
exports.extend = function() { | ||||
var result = {}, i, attr; | ||||
for (i = 0; i < arguments.length; i++) { // arguments is not enumerable in some browsers | ||||
for (attr in arguments[i]) { | ||||
if (arguments[i].hasOwnProperty(attr) && typeof result[attr] === "undefined") { | ||||
result[attr] = arguments[i][attr]; | ||||
} | ||||
} | ||||
} | ||||
return result; | ||||
}; | ||||
/** | ||||
* Transform arbitrary content into a Promise. | ||||
* @param {String} name a name for the content being processed. | ||||
* @param {Object} inputData the content to process. | ||||
* @param {Boolean} isBinary true if the content is not an unicode string | ||||
* @param {Boolean} isOptimizedBinaryString true if the string content only has one byte per character. | ||||
* @param {Boolean} isBase64 true if the string content is encoded with base64. | ||||
* @return {Promise} a promise in a format usable by JSZip. | ||||
*/ | ||||
exports.prepareContent = function(name, inputData, isBinary, isOptimizedBinaryString, isBase64) { | ||||
// if inputData is already a promise, this flatten it. | ||||
var promise = external.Promise.resolve(inputData).then(function(data) { | ||||
var isBlob = support.blob && (data instanceof Blob || ['[object File]', '[object Blob]'].indexOf(Object.prototype.toString.call(data)) !== -1); | ||||
if (isBlob && typeof FileReader !== "undefined") { | ||||
return new external.Promise(function (resolve, reject) { | ||||
var reader = new FileReader(); | ||||
reader.onload = function(e) { | ||||
resolve(e.target.result); | ||||
}; | ||||
reader.onerror = function(e) { | ||||
reject(e.target.error); | ||||
}; | ||||
reader.readAsArrayBuffer(data); | ||||
}); | ||||
} else { | ||||
return data; | ||||
} | ||||
}); | ||||
return promise.then(function(data) { | ||||
var dataType = exports.getTypeOf(data); | ||||
if (!dataType) { | ||||
return external.Promise.reject( | ||||
new Error("Can't read the data of '" + name + "'. Is it " + | ||||
"in a supported JavaScript type (String, Blob, ArrayBuffer, etc) ?") | ||||
); | ||||
} | ||||
// special case : it's way easier to work with Uint8Array than with ArrayBuffer | ||||
if (dataType === "arraybuffer") { | ||||
data = exports.transformTo("uint8array", data); | ||||
} else if (dataType === "string") { | ||||
if (isBase64) { | ||||
data = base64.decode(data); | ||||
} | ||||
else if (isBinary) { | ||||
// optimizedBinaryString === true means that the file has already been filtered with a 0xFF mask | ||||
if (isOptimizedBinaryString !== true) { | ||||
// this is a string, not in a base64 format. | ||||
// Be sure that this is a correct "binary string" | ||||
data = string2binary(data); | ||||
} | ||||
} | ||||
} | ||||
return data; | ||||
}); | ||||
}; | ||||