| /* |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| |
| /* global cordova, FileSystem */ |
| |
| var argscheck = require('cordova/argscheck'); |
| var exec = require('cordova/exec'); |
| var FileTransferError = require('./FileTransferError'); |
| var ProgressEvent = require('cordova-plugin-file.ProgressEvent'); |
| |
| function newProgressEvent (result) { |
| var pe = new ProgressEvent(); |
| pe.lengthComputable = result.lengthComputable; |
| pe.loaded = result.loaded; |
| pe.total = result.total; |
| return pe; |
| } |
| |
| function getUrlCredentials (urlString) { |
| var credentialsPattern = /^https?:\/\/(?:(?:(([^:@/]*)(?::([^@/]*))?)?@)?([^:/?#]*)(?::(\d*))?).*$/; |
| var credentials = credentialsPattern.exec(urlString); |
| |
| return credentials && credentials[1]; |
| } |
| |
| function getBasicAuthHeader (urlString) { |
| var header = null; |
| |
| // This is changed due to MS Windows doesn't support credentials in http uris |
| // so we detect them by regexp and strip off from result url |
| // Proof: http://social.msdn.microsoft.com/Forums/windowsapps/en-US/a327cf3c-f033-4a54-8b7f-03c56ba3203f/windows-foundation-uri-security-problem |
| |
| if (window.btoa) { |
| var credentials = getUrlCredentials(urlString); |
| if (credentials) { |
| var authHeader = 'Authorization'; |
| var authHeaderValue = 'Basic ' + window.btoa(credentials); |
| |
| header = { |
| name: authHeader, |
| value: authHeaderValue |
| }; |
| } |
| } |
| |
| return header; |
| } |
| |
| function convertHeadersToArray (headers) { |
| var result = []; |
| for (var header in headers) { |
| if (Object.prototype.hasOwnProperty.call(headers, header)) { |
| var headerValue = headers[header]; |
| result.push({ |
| name: header, |
| value: headerValue.toString() |
| }); |
| } |
| } |
| return result; |
| } |
| |
| var idCounter = 0; |
| |
| /** |
| * FileTransfer uploads a file to a remote server. |
| * @constructor |
| */ |
| var FileTransfer = function () { |
| this._id = ++idCounter; |
| this.onprogress = null; // optional callback |
| }; |
| |
| /** |
| * Given an absolute file path, uploads a file on the device to a remote server |
| * using a multipart HTTP request. |
| * @param filePath {String} Full path of the file on the device |
| * @param server {String} URL of the server to receive the file |
| * @param successCallback (Function} Callback to be invoked when upload has completed |
| * @param errorCallback {Function} Callback to be invoked upon error |
| * @param options {FileUploadOptions} Optional parameters such as file name and mimetype |
| * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false |
| */ |
| FileTransfer.prototype.upload = function (filePath, server, successCallback, errorCallback, options, trustAllHosts) { |
| argscheck.checkArgs('ssFFO*', 'FileTransfer.upload', arguments); |
| // check for options |
| var fileKey = null; |
| var fileName = null; |
| var mimeType = null; |
| var params = null; |
| var chunkedMode = true; |
| var headers = null; |
| var httpMethod = null; |
| var basicAuthHeader = getBasicAuthHeader(server); |
| if (basicAuthHeader) { |
| server = server.replace(getUrlCredentials(server) + '@', ''); |
| |
| options = options || {}; |
| options.headers = options.headers || {}; |
| options.headers[basicAuthHeader.name] = basicAuthHeader.value; |
| } |
| |
| if (options) { |
| fileKey = options.fileKey; |
| fileName = options.fileName; |
| mimeType = options.mimeType; |
| headers = options.headers; |
| httpMethod = options.httpMethod || 'POST'; |
| if (httpMethod.toUpperCase() === 'PUT') { |
| httpMethod = 'PUT'; |
| } else { |
| httpMethod = 'POST'; |
| } |
| if (options.chunkedMode !== null || typeof options.chunkedMode !== 'undefined') { |
| chunkedMode = options.chunkedMode; |
| } |
| if (options.params) { |
| params = options.params; |
| } else { |
| params = {}; |
| } |
| } |
| |
| if (cordova.platformId === 'windowsphone') { |
| headers = headers && convertHeadersToArray(headers); |
| params = params && convertHeadersToArray(params); |
| } |
| |
| var fail = |
| errorCallback && |
| function (e) { |
| var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception); |
| errorCallback(error); |
| }; |
| |
| var self = this; |
| var win = function (result) { |
| if (typeof result.lengthComputable !== 'undefined') { |
| if (self.onprogress) { |
| self.onprogress(newProgressEvent(result)); |
| } |
| } else { |
| if (successCallback) { |
| successCallback(result); |
| } |
| } |
| }; |
| exec(win, fail, 'FileTransfer', 'upload', [ |
| filePath, |
| server, |
| fileKey, |
| fileName, |
| mimeType, |
| params, |
| trustAllHosts, |
| chunkedMode, |
| headers, |
| this._id, |
| httpMethod |
| ]); |
| }; |
| |
| /** |
| * Downloads a file form a given URL and saves it to the specified directory. |
| * @param source {String} URL of the server to receive the file |
| * @param target {String} Full path of the file on the device |
| * @param successCallback (Function} Callback to be invoked when upload has completed |
| * @param errorCallback {Function} Callback to be invoked upon error |
| * @param trustAllHosts {Boolean} Optional trust all hosts (e.g. for self-signed certs), defaults to false |
| * @param options {FileDownloadOptions} Optional parameters such as headers |
| */ |
| FileTransfer.prototype.download = function (source, target, successCallback, errorCallback, trustAllHosts, options) { |
| argscheck.checkArgs('ssFF*', 'FileTransfer.download', arguments); |
| var self = this; |
| |
| var basicAuthHeader = getBasicAuthHeader(source); |
| if (basicAuthHeader) { |
| source = source.replace(getUrlCredentials(source) + '@', ''); |
| |
| options = options || {}; |
| options.headers = options.headers || {}; |
| options.headers[basicAuthHeader.name] = basicAuthHeader.value; |
| } |
| |
| var headers = null; |
| if (options) { |
| headers = options.headers || null; |
| } |
| |
| if (cordova.platformId === 'windowsphone' && headers) { |
| headers = convertHeadersToArray(headers); |
| } |
| |
| var win = function (result) { |
| if (typeof result.lengthComputable !== 'undefined') { |
| if (self.onprogress) { |
| return self.onprogress(newProgressEvent(result)); |
| } |
| } else if (successCallback) { |
| var entry = null; |
| if (result.isDirectory) { |
| entry = new (require('cordova-plugin-file.DirectoryEntry'))(); |
| } else if (result.isFile) { |
| entry = new (require('cordova-plugin-file.FileEntry'))(); |
| } |
| entry.isDirectory = result.isDirectory; |
| entry.isFile = result.isFile; |
| entry.name = result.name; |
| entry.fullPath = result.fullPath; |
| entry.filesystem = new FileSystem( |
| result.filesystemName || (result.filesystem === window.PERSISTENT ? 'persistent' : 'temporary') |
| ); |
| entry.nativeURL = result.nativeURL; |
| successCallback(entry); |
| } |
| }; |
| |
| var fail = |
| errorCallback && |
| function (e) { |
| var error = new FileTransferError(e.code, e.source, e.target, e.http_status, e.body, e.exception); |
| errorCallback(error); |
| }; |
| |
| exec(win, fail, 'FileTransfer', 'download', [source, target, trustAllHosts, this._id, headers]); |
| }; |
| |
| /** |
| * Aborts the ongoing file transfer on this object. The original error |
| * callback for the file transfer will be called if necessary. |
| */ |
| FileTransfer.prototype.abort = function () { |
| exec(null, null, 'FileTransfer', 'abort', [this._id]); |
| }; |
| |
| module.exports = FileTransfer; |