diff options
Diffstat (limited to 'StoneIsland/plugins/cordova-plugin-advanced-http/www/helpers.js')
| -rw-r--r-- | StoneIsland/plugins/cordova-plugin-advanced-http/www/helpers.js | 503 |
1 files changed, 503 insertions, 0 deletions
diff --git a/StoneIsland/plugins/cordova-plugin-advanced-http/www/helpers.js b/StoneIsland/plugins/cordova-plugin-advanced-http/www/helpers.js new file mode 100644 index 00000000..b88d7769 --- /dev/null +++ b/StoneIsland/plugins/cordova-plugin-advanced-http/www/helpers.js @@ -0,0 +1,503 @@ +module.exports = function init(global, jsUtil, cookieHandler, messages, base64, errorCodes, dependencyValidator, ponyfills) { + var validSerializers = ['urlencoded', 'json', 'utf8', 'raw', 'multipart']; + var validCertModes = ['default', 'nocheck', 'pinned', 'legacy']; + var validClientAuthModes = ['none', 'systemstore', 'buffer']; + var validHttpMethods = ['get', 'put', 'post', 'patch', 'head', 'delete', 'options', 'upload', 'download']; + var validResponseTypes = ['text', 'json', 'arraybuffer', 'blob']; + + var interface = { + b64EncodeUnicode: b64EncodeUnicode, + checkClientAuthMode: checkClientAuthMode, + checkClientAuthOptions: checkClientAuthOptions, + checkDownloadFilePath: checkDownloadFilePath, + checkFollowRedirectValue: checkFollowRedirectValue, + checkForBlacklistedHeaderKey: checkForBlacklistedHeaderKey, + checkForInvalidHeaderValue: checkForInvalidHeaderValue, + checkSerializer: checkSerializer, + checkSSLCertMode: checkSSLCertMode, + checkTimeoutValue: checkTimeoutValue, + checkUploadFileOptions: checkUploadFileOptions, + getMergedHeaders: getMergedHeaders, + processData: processData, + handleMissingCallbacks: handleMissingCallbacks, + handleMissingOptions: handleMissingOptions, + injectCookieHandler: injectCookieHandler, + injectFileEntryHandler: injectFileEntryHandler, + injectRawResponseHandler: injectRawResponseHandler, + }; + + // expose all functions for testing purposes + if (init.debug) { + interface.mergeHeaders = mergeHeaders; + interface.checkForValidStringValue = checkForValidStringValue; + interface.checkKeyValuePairObject = checkKeyValuePairObject; + interface.checkHttpMethod = checkHttpMethod; + interface.checkResponseType = checkResponseType; + interface.checkHeadersObject = checkHeadersObject; + interface.checkParamsObject = checkParamsObject; + interface.resolveCookieString = resolveCookieString; + interface.createFileEntry = createFileEntry; + interface.getCookieHeader = getCookieHeader; + interface.getMatchingHostHeaders = getMatchingHostHeaders; + interface.getAllowedDataTypes = getAllowedDataTypes; + } + + return interface; + + // Thanks Mozilla: https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding#The_.22Unicode_Problem.22 + function b64EncodeUnicode(str) { + return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) { + return String.fromCharCode('0x' + p1); + })); + } + + function mergeHeaders(globalHeaders, localHeaders) { + var globalKeys = Object.keys(globalHeaders); + var key; + + for (var i = 0; i < globalKeys.length; i++) { + key = globalKeys[i]; + + if (!localHeaders.hasOwnProperty(key)) { + localHeaders[key] = globalHeaders[key]; + } + } + + return localHeaders; + } + + function checkForValidStringValue(list, value, onInvalidValueMessage) { + if (jsUtil.getTypeOf(value) !== 'String') { + throw new Error(onInvalidValueMessage + ' ' + list.join(', ')); + } + + value = value.trim().toLowerCase(); + + if (list.indexOf(value) === -1) { + throw new Error(onInvalidValueMessage + ' ' + list.join(', ')); + } + + return value; + } + + function checkKeyValuePairObject(obj, allowedChildren, onInvalidValueMessage) { + if (jsUtil.getTypeOf(obj) !== 'Object') { + throw new Error(onInvalidValueMessage); + } + + var keys = Object.keys(obj); + + for (var i = 0; i < keys.length; i++) { + if (allowedChildren.indexOf(jsUtil.getTypeOf(obj[keys[i]])) === -1) { + throw new Error(onInvalidValueMessage); + } + } + + return obj; + } + + function checkArray(array, allowedDataTypes, onInvalidValueMessage) { + if (jsUtil.getTypeOf(array) !== 'Array') { + throw new Error(onInvalidValueMessage); + } + + for (var i = 0; i < array.length; ++i) { + if (allowedDataTypes.indexOf(jsUtil.getTypeOf(array[i])) === -1) { + throw new Error(onInvalidValueMessage); + } + } + + return array; + } + + function checkHttpMethod(method) { + return checkForValidStringValue(validHttpMethods, method, messages.INVALID_HTTP_METHOD); + } + + function checkResponseType(type) { + return checkForValidStringValue(validResponseTypes, type, messages.INVALID_RESPONSE_TYPE); + } + + function checkSerializer(serializer) { + return checkForValidStringValue(validSerializers, serializer, messages.INVALID_DATA_SERIALIZER); + } + + function checkSSLCertMode(mode) { + return checkForValidStringValue(validCertModes, mode, messages.INVALID_SSL_CERT_MODE); + } + + function checkClientAuthMode(mode) { + return checkForValidStringValue(validClientAuthModes, mode, messages.INVALID_CLIENT_AUTH_MODE); + } + + function checkClientAuthOptions(mode, options) { + options = options || {}; + + // none + if (mode === validClientAuthModes[0]) { + return { + alias: null, + rawPkcs: null, + pkcsPassword: '' + }; + } + + if (jsUtil.getTypeOf(options) !== 'Object') { + throw new Error(messages.INVALID_CLIENT_AUTH_OPTIONS); + } + + // systemstore + if (mode === validClientAuthModes[1]) { + if (jsUtil.getTypeOf(options.alias) !== 'String' + && jsUtil.getTypeOf(options.alias) !== 'Undefined') { + throw new Error(messages.INVALID_CLIENT_AUTH_ALIAS); + } + + return { + alias: jsUtil.getTypeOf(options.alias) === 'Undefined' ? null : options.alias, + rawPkcs: null, + pkcsPassword: '' + }; + } + + // buffer + if (mode === validClientAuthModes[2]) { + if (jsUtil.getTypeOf(options.rawPkcs) !== 'ArrayBuffer') { + throw new Error(messages.INVALID_CLIENT_AUTH_RAW_PKCS); + } + + if (jsUtil.getTypeOf(options.pkcsPassword) !== 'String') { + throw new Error(messages.INVALID_CLIENT_AUTH_PKCS_PASSWORD); + } + + return { + alias: null, + rawPkcs: options.rawPkcs, + pkcsPassword: options.pkcsPassword + } + } + } + + function checkForBlacklistedHeaderKey(key) { + if (key.toLowerCase() === 'cookie') { + throw new Error(messages.ADDING_COOKIES_NOT_SUPPORTED); + } + + return key; + } + + function checkForInvalidHeaderValue(value) { + var type = jsUtil.getTypeOf(value); + + if (type !== 'String' && type !== 'Null') { + throw new Error(messages.INVALID_HEADER_VALUE); + } + + return value; + } + + function checkTimeoutValue(timeout) { + if (jsUtil.getTypeOf(timeout) !== 'Number' || timeout < 0) { + throw new Error(messages.INVALID_TIMEOUT_VALUE); + } + + return timeout; + } + + function checkFollowRedirectValue(follow) { + if (jsUtil.getTypeOf(follow) !== 'Boolean') { + throw new Error(messages.INVALID_FOLLOW_REDIRECT_VALUE); + } + + return follow; + } + + function checkHeadersObject(headers) { + return checkKeyValuePairObject(headers, ['String'], messages.TYPE_MISMATCH_HEADERS); + } + + function checkParamsObject(params) { + return checkKeyValuePairObject(params, ['String', 'Array'], messages.TYPE_MISMATCH_PARAMS); + } + + function checkDownloadFilePath(filePath) { + if (!filePath || jsUtil.getTypeOf(filePath) !== 'String') { + throw new Error(messages.INVALID_DOWNLOAD_FILE_PATH); + } + + return filePath; + } + + function checkUploadFileOptions(filePaths, names) { + if (jsUtil.getTypeOf(filePaths) === 'String') { + filePaths = [filePaths]; + } + + if (jsUtil.getTypeOf(names) === 'String') { + names = [names]; + } + + var opts = { + filePaths: checkArray(filePaths, ['String'], messages.TYPE_MISMATCH_FILE_PATHS), + names: checkArray(names, ['String'], messages.TYPE_MISMATCH_NAMES) + }; + + if (!opts.filePaths.length) { + throw new Error(messages.EMPTY_FILE_PATHS); + } + + if (!opts.names.length) { + throw new Error(messages.EMPTY_NAMES); + } + + return opts; + } + + function resolveCookieString(headers) { + var keys = Object.keys(headers || {}); + + for (var i = 0; i < keys.length; ++i) { + if (keys[i].match(/^set-cookie$/i)) { + return headers[keys[i]]; + } + } + + return null; + } + + function createFileEntry(rawEntry) { + var entry = new (require('cordova-plugin-file.FileEntry'))(); + + entry.isDirectory = rawEntry.isDirectory; + entry.isFile = rawEntry.isFile; + entry.name = rawEntry.name; + entry.fullPath = rawEntry.fullPath; + entry.filesystem = new FileSystem(rawEntry.filesystemName || (rawEntry.filesystem == global.PERSISTENT ? 'persistent' : 'temporary')); + entry.nativeURL = rawEntry.nativeURL; + + return entry; + } + + function injectCookieHandler(url, cb) { + return function (response) { + cookieHandler.setCookieFromString(url, resolveCookieString(response.headers)); + cb(response); + } + } + + function injectRawResponseHandler(responseType, success, failure) { + return function (response) { + var dataType = jsUtil.getTypeOf(response.data); + + // don't need post-processing if it's already binary type (on browser platform) + if (dataType === 'ArrayBuffer' || dataType === 'Blob') { + return success(response); + } + + try { + // json + if (responseType === validResponseTypes[1]) { + response.data = response.data === '' + ? undefined + : JSON.parse(response.data); + } + + // arraybuffer + else if (responseType === validResponseTypes[2]) { + response.data = response.data === '' + ? null + : base64.toArrayBuffer(response.data); + } + + // blob + else if (responseType === validResponseTypes[3]) { + if (response.data === '') { + response.data = null; + } else { + var buffer = base64.toArrayBuffer(response.data); + var type = response.headers['content-type'] || ''; + var blob = new Blob([buffer], { type: type }); + response.data = blob; + } + } + + success(response); + } catch (error) { + failure({ + status: errorCodes.POST_PROCESSING_FAILED, + error: messages.POST_PROCESSING_FAILED + ' ' + error.message, + url: response.url, + headers: response.headers + }); + } + } + } + + function injectFileEntryHandler(cb) { + return function (response) { + cb(createFileEntry(response.file)); + } + } + + function getCookieHeader(url) { + var cookieString = cookieHandler.getCookieString(url); + + if (cookieString.length) { + return { Cookie: cookieHandler.getCookieString(url) }; + } + + return {}; + } + + function getMatchingHostHeaders(url, headersList) { + var matches = url.match(/^https?\:\/\/([^\/?#]+)(?:[\/?#]|$)/i); + var domain = matches && matches[1]; + + return headersList[domain] || null; + } + + function getMergedHeaders(url, requestHeaders, predefinedHeaders) { + var globalHeaders = predefinedHeaders['*'] || {}; + var hostHeaders = getMatchingHostHeaders(url, predefinedHeaders) || {}; + var mergedHeaders = mergeHeaders(globalHeaders, hostHeaders); + + mergedHeaders = mergeHeaders(mergedHeaders, requestHeaders); + mergedHeaders = mergeHeaders(mergedHeaders, getCookieHeader(url)); + + return mergedHeaders; + } + + function getAllowedDataTypes(dataSerializer) { + switch (dataSerializer) { + case 'utf8': + return ['String']; + case 'urlencoded': + return ['Object']; + case 'json': + return ['Array', 'Object']; + case 'raw': + return ['Uint8Array', 'ArrayBuffer']; + default: + return []; + } + } + + function getAllowedInstanceTypes(dataSerializer) { + return dataSerializer === 'multipart' ? ['FormData'] : null; + } + + function processData(data, dataSerializer, cb) { + var currentDataType = jsUtil.getTypeOf(data); + var allowedDataTypes = getAllowedDataTypes(dataSerializer); + var allowedInstanceTypes = getAllowedInstanceTypes(dataSerializer); + + if (allowedInstanceTypes) { + var isCorrectInstanceType = false; + + allowedInstanceTypes.forEach(function (type) { + if ((global[type] && data instanceof global[type]) || (ponyfills[type] && data instanceof ponyfills[type])) { + isCorrectInstanceType = true; + } + }); + + if (!isCorrectInstanceType) { + throw new Error(messages.INSTANCE_TYPE_MISMATCH_DATA + ' ' + allowedInstanceTypes.join(', ')); + } + } + + if (!allowedInstanceTypes && allowedDataTypes.indexOf(currentDataType) === -1) { + throw new Error(messages.TYPE_MISMATCH_DATA + ' ' + allowedDataTypes.join(', ')); + } + + switch (dataSerializer) { + case 'utf8': + return cb({ text: data }); + case 'raw': + return cb(currentDataType === 'Uint8Array' ? data.buffer : data); + case 'multipart': + return processFormData(data, cb); + default: + return cb(data); + } + } + + function processFormData(data, cb) { + dependencyValidator.checkBlobApi(); + dependencyValidator.checkFileReaderApi(); + dependencyValidator.checkTextEncoderApi(); + dependencyValidator.checkFormDataInstance(data); + + var textEncoder = new global.TextEncoder('utf8'); + var iterator = data.entries(); + + var result = { + buffers: [], + names: [], + fileNames: [], + types: [] + }; + + processFormDataIterator(iterator, textEncoder, result, cb); + } + + function processFormDataIterator(iterator, textEncoder, result, onFinished) { + var entry = iterator.next(); + + if (entry.done) { + return onFinished(result); + } + + if (entry.value[1] instanceof global.Blob || entry.value[1] instanceof global.File) { + var reader = new global.FileReader(); + + reader.onload = function () { + result.buffers.push(base64.fromArrayBuffer(reader.result)); + result.names.push(entry.value[0]); + result.fileNames.push(entry.value[1].name !== undefined ? entry.value[1].name : 'blob'); + result.types.push(entry.value[1].type || ''); + processFormDataIterator(iterator, textEncoder, result, onFinished); + }; + + return reader.readAsArrayBuffer(entry.value[1]); + } + + if (jsUtil.getTypeOf(entry.value[1]) === 'String') { + result.buffers.push(base64.fromArrayBuffer(textEncoder.encode(entry.value[1]).buffer)); + result.names.push(entry.value[0]); + result.fileNames.push(null); + result.types.push('text/plain'); + + return processFormDataIterator(iterator, textEncoder, result, onFinished) + } + + // skip items which are not supported + processFormDataIterator(iterator, textEncoder, result, onFinished); + } + + function handleMissingCallbacks(successFn, failFn) { + if (jsUtil.getTypeOf(successFn) !== 'Function') { + throw new Error(messages.MANDATORY_SUCCESS); + } + + if (jsUtil.getTypeOf(failFn) !== 'Function') { + throw new Error(messages.MANDATORY_FAIL); + } + } + + function handleMissingOptions(options, globals) { + options = options || {}; + + return { + data: jsUtil.getTypeOf(options.data) === 'Undefined' ? null : options.data, + filePath: options.filePath, + followRedirect: checkFollowRedirectValue(options.followRedirect || globals.followRedirect), + headers: checkHeadersObject(options.headers || {}), + method: checkHttpMethod(options.method || validHttpMethods[0]), + name: options.name, + params: checkParamsObject(options.params || {}), + responseType: checkResponseType(options.responseType || validResponseTypes[0]), + serializer: checkSerializer(options.serializer || globals.serializer), + timeout: checkTimeoutValue(options.timeout || globals.timeout), + }; + } +}; |
