Cordova plugin file und file-transfer geadded

This commit is contained in:
2016-01-08 00:06:37 +01:00
parent 23a833a31b
commit 36c7e2c8e2
234 changed files with 49402 additions and 81 deletions

View File

@@ -14,4 +14,5 @@
</application>
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
<uses-permission android:name="com.android.vending.BILLING" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</manifest>

View File

@@ -12,6 +12,12 @@
"xml": "<uses-permission android:name=\"com.android.vending.BILLING\" />",
"count": 1
}
],
"/*": [
{
"xml": "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />",
"count": 2
}
]
}
},
@@ -45,6 +51,14 @@
{
"xml": "<feature name=\"InAppBrowser\"><param name=\"android-package\" value=\"org.apache.cordova.inappbrowser.InAppBrowser\" /></feature>",
"count": 1
},
{
"xml": "<feature name=\"File\"><param name=\"android-package\" value=\"org.apache.cordova.file.FileUtils\" /><param name=\"onload\" value=\"true\" /></feature>",
"count": 1
},
{
"xml": "<feature name=\"FileTransfer\"><param name=\"android-package\" value=\"org.apache.cordova.filetransfer.FileTransfer\" /></feature>",
"count": 1
}
]
}
@@ -58,6 +72,16 @@
}
]
}
},
"config.xml": {
"parents": {
"/*": [
{
"xml": "<preference name=\"AndroidPersistentFileLocation\" value=\"Internal\" />",
"count": 1
}
]
}
}
}
},
@@ -86,6 +110,12 @@
},
"cordova-plugin-inappbrowser": {
"PACKAGE_NAME": "com.raataar.wolle_rosen_kaufen"
},
"cordova-plugin-file": {
"PACKAGE_NAME": "com.raataar.wolle_rosen_kaufen"
},
"cordova-plugin-file-transfer": {
"PACKAGE_NAME": "com.raataar.wolle_rosen_kaufen"
}
},
"dependent_plugins": {},
@@ -145,6 +175,189 @@
"cordova.InAppBrowser.open",
"window.open"
]
},
{
"file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
"id": "cordova-plugin-file.DirectoryEntry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.DirectoryEntry"
]
},
{
"file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
"id": "cordova-plugin-file.DirectoryReader",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.DirectoryReader"
]
},
{
"file": "plugins/cordova-plugin-file/www/Entry.js",
"id": "cordova-plugin-file.Entry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Entry"
]
},
{
"file": "plugins/cordova-plugin-file/www/File.js",
"id": "cordova-plugin-file.File",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.File"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileEntry.js",
"id": "cordova-plugin-file.FileEntry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileEntry"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileError.js",
"id": "cordova-plugin-file.FileError",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileError"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileReader.js",
"id": "cordova-plugin-file.FileReader",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileReader"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileSystem.js",
"id": "cordova-plugin-file.FileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
"id": "cordova-plugin-file.FileUploadOptions",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileUploadOptions"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
"id": "cordova-plugin-file.FileUploadResult",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileUploadResult"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileWriter.js",
"id": "cordova-plugin-file.FileWriter",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileWriter"
]
},
{
"file": "plugins/cordova-plugin-file/www/Flags.js",
"id": "cordova-plugin-file.Flags",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Flags"
]
},
{
"file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
"id": "cordova-plugin-file.LocalFileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.LocalFileSystem"
],
"merges": [
"window"
]
},
{
"file": "plugins/cordova-plugin-file/www/Metadata.js",
"id": "cordova-plugin-file.Metadata",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Metadata"
]
},
{
"file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
"id": "cordova-plugin-file.ProgressEvent",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.ProgressEvent"
]
},
{
"file": "plugins/cordova-plugin-file/www/fileSystems.js",
"id": "cordova-plugin-file.fileSystems",
"pluginId": "cordova-plugin-file"
},
{
"file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
"id": "cordova-plugin-file.requestFileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.requestFileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
"id": "cordova-plugin-file.resolveLocalFileSystemURI",
"pluginId": "cordova-plugin-file",
"merges": [
"window"
]
},
{
"file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
"id": "cordova-plugin-file.androidFileSystem",
"pluginId": "cordova-plugin-file",
"merges": [
"FileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
"id": "cordova-plugin-file.fileSystems-roots",
"pluginId": "cordova-plugin-file",
"runs": true
},
{
"file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
"id": "cordova-plugin-file.fileSystemPaths",
"pluginId": "cordova-plugin-file",
"merges": [
"cordova"
],
"runs": true
},
{
"file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js",
"id": "cordova-plugin-file-transfer.FileTransferError",
"pluginId": "cordova-plugin-file-transfer",
"clobbers": [
"window.FileTransferError"
]
},
{
"file": "plugins/cordova-plugin-file-transfer/www/FileTransfer.js",
"id": "cordova-plugin-file-transfer.FileTransfer",
"pluginId": "cordova-plugin-file-transfer",
"clobbers": [
"window.FileTransfer"
]
}
],
"plugin_metadata": {
@@ -155,6 +368,8 @@
"cordova-plugin-statusbar": "2.0.0",
"cordova-plugin-whitelist": "1.2.0",
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1"
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
}
}

View File

@@ -55,6 +55,189 @@ module.exports = [
"cordova.InAppBrowser.open",
"window.open"
]
},
{
"file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
"id": "cordova-plugin-file.DirectoryEntry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.DirectoryEntry"
]
},
{
"file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
"id": "cordova-plugin-file.DirectoryReader",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.DirectoryReader"
]
},
{
"file": "plugins/cordova-plugin-file/www/Entry.js",
"id": "cordova-plugin-file.Entry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Entry"
]
},
{
"file": "plugins/cordova-plugin-file/www/File.js",
"id": "cordova-plugin-file.File",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.File"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileEntry.js",
"id": "cordova-plugin-file.FileEntry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileEntry"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileError.js",
"id": "cordova-plugin-file.FileError",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileError"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileReader.js",
"id": "cordova-plugin-file.FileReader",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileReader"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileSystem.js",
"id": "cordova-plugin-file.FileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
"id": "cordova-plugin-file.FileUploadOptions",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileUploadOptions"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
"id": "cordova-plugin-file.FileUploadResult",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileUploadResult"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileWriter.js",
"id": "cordova-plugin-file.FileWriter",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileWriter"
]
},
{
"file": "plugins/cordova-plugin-file/www/Flags.js",
"id": "cordova-plugin-file.Flags",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Flags"
]
},
{
"file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
"id": "cordova-plugin-file.LocalFileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.LocalFileSystem"
],
"merges": [
"window"
]
},
{
"file": "plugins/cordova-plugin-file/www/Metadata.js",
"id": "cordova-plugin-file.Metadata",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Metadata"
]
},
{
"file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
"id": "cordova-plugin-file.ProgressEvent",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.ProgressEvent"
]
},
{
"file": "plugins/cordova-plugin-file/www/fileSystems.js",
"id": "cordova-plugin-file.fileSystems",
"pluginId": "cordova-plugin-file"
},
{
"file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
"id": "cordova-plugin-file.requestFileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.requestFileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
"id": "cordova-plugin-file.resolveLocalFileSystemURI",
"pluginId": "cordova-plugin-file",
"merges": [
"window"
]
},
{
"file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
"id": "cordova-plugin-file.androidFileSystem",
"pluginId": "cordova-plugin-file",
"merges": [
"FileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
"id": "cordova-plugin-file.fileSystems-roots",
"pluginId": "cordova-plugin-file",
"runs": true
},
{
"file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
"id": "cordova-plugin-file.fileSystemPaths",
"pluginId": "cordova-plugin-file",
"merges": [
"cordova"
],
"runs": true
},
{
"file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js",
"id": "cordova-plugin-file-transfer.FileTransferError",
"pluginId": "cordova-plugin-file-transfer",
"clobbers": [
"window.FileTransferError"
]
},
{
"file": "plugins/cordova-plugin-file-transfer/www/FileTransfer.js",
"id": "cordova-plugin-file-transfer.FileTransfer",
"pluginId": "cordova-plugin-file-transfer",
"clobbers": [
"window.FileTransfer"
]
}
];
module.exports.metadata =
@@ -67,7 +250,9 @@ module.exports.metadata =
"cordova-plugin-statusbar": "2.0.0",
"cordova-plugin-whitelist": "1.2.0",
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1"
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
}
// BOTTOM OF METADATA
});

View File

@@ -25,7 +25,7 @@
<script src="js/controllers.js"></script>
<script src="js/services.js"></script>
</head>
<body ng-app="starter" class="platform-android platform-cordova platform-webview">
<body ng-app="starter">
<!--
The nav bar that will be updated as we navigate between views.
-->

View File

@@ -1,25 +1,14 @@
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope,$ionicPopup,$http) {
.controller('DashCtrl', function($scope,$ionicPopup,$http, $localstorage) {
$scope.preis="";
$scope.name="";
$scope.freitext="";
var showAlert=0;
$scope.items=[];
$scope.item=[];
$scope.validate = function() {
showAlert=0;
if ($scope.name.length < 1){
showAlert=1;
}
if ($scope.freitext.length < 1){
showAlert=1;
}
if (showAlert==1){
$scope.showAlert();
return;
}
var link = 'http://api.raataar.de/rosen/vorschau.php';
@@ -31,21 +20,19 @@ angular.module('starter.controllers', [])
};
$scope.showAlert = function() {
var alertPopup = $ionicPopup.alert({
title: 'Uuuupppsssiii',
template: 'Bitte prüfe deine Eingaben.'
});
alertPopup.then(function(res) {
console.log('Thank you for not eating my delicious ice cream cone');
});
};
$scope.loaddata = function() {
$scope.items=$localstorage.getObject('items');
alert(JSON.stringify($scope.items));
};
function buysuccessHandler (result) {
inappbilling.consumePurchase(successHandler, errorHandler, "3xrose");
}
$scope.savedata = function() {
$scope.item={name: $scope.name, freitext: $scope.freitext, rosen: $scope.preis, bild: "test"};
alert(JSON.stringify($scope.item));
$scope.items.push($scope.item);
$localstorage.setObject('items',$scope.items);
};
function successHandler (result) {
function successBuyHandler (result) {
var strResult = "";
if(typeof result === 'object') {
strResult = JSON.stringify(result);
@@ -55,16 +42,35 @@ angular.module('starter.controllers', [])
alert("SUCCESS: \r\n"+strResult );
}
function errorHandler (error) {
function successConsumeHandler (result) {
var strResult = "";
if(typeof result === 'object') {
strResult = JSON.stringify(result);
} else {
strResult = result;
}
alert("SUCCESS: \r\n"+strResult );
}
function errorBuyHandler (error) {
alert("ERROR: \r\n"+error );
}
}
$scope.buyAdFree = function() {
function errorConsumeHandler (error) {
alert("ERROR: \r\n"+error );
}
alert($scope.preis);
function buysuccessHandler (result) {
inappbilling.consumePurchase(successConsumeHandler, errorConsumeHandler, $scope.preis);
}
$scope.buyRose = function() {
//alert($scope.preis);
if((window.device && device.platform == "Android") && typeof inappbilling !== "undefined") {
inappbilling.buy(buysuccessHandler, errorHandler,"3xrose");
inappbilling.buy(successBuyHandler, errorBuyHandler, $scope.preis);
}
}

View File

@@ -1,50 +1,19 @@
angular.module('starter.services', [])
.factory('Chats', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var chats = [{
id: 0,
name: 'Ben Sparrow',
lastText: 'You on your way?',
face: 'img/ben.png'
}, {
id: 1,
name: 'Max Lynx',
lastText: 'Hey, it\'s me',
face: 'img/max.png'
}, {
id: 2,
name: 'Adam Bradleyson',
lastText: 'I should buy a boat',
face: 'img/adam.jpg'
}, {
id: 3,
name: 'Perry Governor',
lastText: 'Look at my mukluks!',
face: 'img/perry.png'
}, {
id: 4,
name: 'Mike Harrington',
lastText: 'This is wicked good ice cream.',
face: 'img/mike.png'
}];
.factory('$localstorage', ['$window', function($window) {
return {
all: function() {
return chats;
set: function(key, value) {
$window.localStorage[key] = value;
},
remove: function(chat) {
chats.splice(chats.indexOf(chat), 1);
get: function(key, defaultValue) {
return $window.localStorage[key] || defaultValue;
},
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
setObject: function(key, value) {
$window.localStorage[key] = JSON.stringify(value);
},
getObject: function(key) {
return JSON.parse($window.localStorage[key] || '{}');
}
};
});
}
}]);

View File

@@ -0,0 +1,237 @@
cordova.define("cordova-plugin-file-transfer.FileTransfer", function(require, exports, module) { /*
*
* 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.
*
*/
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
FileTransferError = require('./FileTransferError'),
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*))?).*$/,
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 (headers.hasOwnProperty(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 {
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;
});

View File

@@ -0,0 +1,43 @@
cordova.define("cordova-plugin-file-transfer.FileTransferError", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* FileTransferError
* @constructor
*/
var FileTransferError = function(code, source, target, status, body, exception) {
this.code = code || null;
this.source = source || null;
this.target = target || null;
this.http_status = status || null;
this.body = body || null;
this.exception = exception || null;
};
FileTransferError.FILE_NOT_FOUND_ERR = 1;
FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
FileTransferError.ABORT_ERR = 4;
FileTransferError.NOT_MODIFIED_ERR = 5;
module.exports = FileTransferError;
});

View File

@@ -0,0 +1,119 @@
cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) { /*
*
* 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.
*
*/
var argscheck = require('cordova/argscheck'),
utils = require('cordova/utils'),
exec = require('cordova/exec'),
Entry = require('./Entry'),
FileError = require('./FileError'),
DirectoryReader = require('./DirectoryReader');
/**
* An interface representing a directory on the file system.
*
* {boolean} isFile always false (readonly)
* {boolean} isDirectory always true (readonly)
* {DOMString} name of the directory, excluding the path leading to it (readonly)
* {DOMString} fullPath the absolute full path to the directory (readonly)
* {FileSystem} filesystem on which the directory resides (readonly)
*/
var DirectoryEntry = function(name, fullPath, fileSystem, nativeURL) {
// add trailing slash if it is missing
if ((fullPath) && !/\/$/.test(fullPath)) {
fullPath += "/";
}
// add trailing slash if it is missing
if (nativeURL && !/\/$/.test(nativeURL)) {
nativeURL += "/";
}
DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
};
utils.extend(DirectoryEntry, Entry);
/**
* Creates a new DirectoryReader to read entries from this directory
*/
DirectoryEntry.prototype.createReader = function() {
return new DirectoryReader(this.toInternalURL());
};
/**
* Creates or looks up a directory
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
* @param {Flags} options to create or exclusively create the directory
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
var fs = this.filesystem;
var win = successCallback && function(result) {
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
successCallback(entry);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getDirectory", [this.toInternalURL(), path, options]);
};
/**
* Deletes a directory and all of it's contents
*
* @param {Function} successCallback is called with no parameters
* @param {Function} errorCallback is called with a FileError
*/
DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(successCallback, fail, "File", "removeRecursively", [this.toInternalURL()]);
};
/**
* Creates or looks up a file
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
* @param {Flags} options to create or exclusively create the file
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
var fs = this.filesystem;
var win = successCallback && function(result) {
var FileEntry = require('./FileEntry');
var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
successCallback(entry);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getFile", [this.toInternalURL(), path, options]);
};
module.exports = DirectoryEntry;
});

View File

@@ -0,0 +1,75 @@
cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec'),
FileError = require('./FileError') ;
/**
* An interface that lists the files and directories in a directory.
*/
function DirectoryReader(localURL) {
this.localURL = localURL || null;
this.hasReadEntries = false;
}
/**
* Returns a list of entries from a directory.
*
* @param {Function} successCallback is called with a list of entries
* @param {Function} errorCallback is called with a FileError
*/
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
// If we've already read and passed on this directory's entries, return an empty list.
if (this.hasReadEntries) {
successCallback([]);
return;
}
var reader = this;
var win = typeof successCallback !== 'function' ? null : function(result) {
var retVal = [];
for (var i=0; i<result.length; i++) {
var entry = null;
if (result[i].isDirectory) {
entry = new (require('./DirectoryEntry'))();
}
else if (result[i].isFile) {
entry = new (require('./FileEntry'))();
}
entry.isDirectory = result[i].isDirectory;
entry.isFile = result[i].isFile;
entry.name = result[i].name;
entry.fullPath = result[i].fullPath;
entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
entry.nativeURL = result[i].nativeURL;
retVal.push(entry);
}
reader.hasReadEntries = true;
successCallback(retVal);
};
var fail = typeof errorCallback !== 'function' ? null : function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "readEntries", [this.localURL]);
};
module.exports = DirectoryReader;
});

View File

@@ -0,0 +1,262 @@
cordova.define("cordova-plugin-file.Entry", function(require, exports, module) { /*
*
* 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.
*
*/
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
FileError = require('./FileError'),
Metadata = require('./Metadata');
/**
* Represents a file or directory on the local file system.
*
* @param isFile
* {boolean} true if Entry is a file (readonly)
* @param isDirectory
* {boolean} true if Entry is a directory (readonly)
* @param name
* {DOMString} name of the file or directory, excluding the path
* leading to it (readonly)
* @param fullPath
* {DOMString} the absolute full path to the file or directory
* (readonly)
* @param fileSystem
* {FileSystem} the filesystem on which this entry resides
* (readonly)
* @param nativeURL
* {DOMString} an alternate URL which can be used by native
* webview controls, for example media players.
* (optional, readonly)
*/
function Entry(isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
this.isFile = !!isFile;
this.isDirectory = !!isDirectory;
this.name = name || '';
this.fullPath = fullPath || '';
this.filesystem = fileSystem || null;
this.nativeURL = nativeURL || null;
}
/**
* Look up the metadata of the entry.
*
* @param successCallback
* {Function} is called with a Metadata object
* @param errorCallback
* {Function} is called with a FileError
*/
Entry.prototype.getMetadata = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
var success = successCallback && function(entryMetadata) {
var metadata = new Metadata({
size: entryMetadata.size,
modificationTime: entryMetadata.lastModifiedDate
});
successCallback(metadata);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(success, fail, "File", "getFileMetadata", [this.toInternalURL()]);
};
/**
* Set the metadata of the entry.
*
* @param successCallback
* {Function} is called with a Metadata object
* @param errorCallback
* {Function} is called with a FileError
* @param metadataObject
* {Object} keys and values to set
*/
Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) {
argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
exec(successCallback, errorCallback, "File", "setMetadata", [this.toInternalURL(), metadataObject]);
};
/**
* Move a file or directory to a new location.
*
* @param parent
* {DirectoryEntry} the directory to which to move this entry
* @param newName
* {DOMString} new name of the entry, defaults to the current name
* @param successCallback
* {Function} called with the new DirectoryEntry object
* @param errorCallback
* {Function} called with a FileError
*/
Entry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
var filesystem = this.filesystem,
srcURL = this.toInternalURL(),
// entry name
name = newName || this.name,
success = function(entry) {
if (entry) {
if (successCallback) {
// create appropriate Entry object
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
successCallback(result);
}
}
else {
// no Entry object returned
fail && fail(FileError.NOT_FOUND_ERR);
}
};
// copy
exec(success, fail, "File", "moveTo", [srcURL, parent.toInternalURL(), name]);
};
/**
* Copy a directory to a different location.
*
* @param parent
* {DirectoryEntry} the directory to which to copy the entry
* @param newName
* {DOMString} new name of the entry, defaults to the current name
* @param successCallback
* {Function} called with the new Entry object
* @param errorCallback
* {Function} called with a FileError
*/
Entry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
var filesystem = this.filesystem,
srcURL = this.toInternalURL(),
// entry name
name = newName || this.name,
// success callback
success = function(entry) {
if (entry) {
if (successCallback) {
// create appropriate Entry object
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
successCallback(result);
}
}
else {
// no Entry object returned
fail && fail(FileError.NOT_FOUND_ERR);
}
};
// copy
exec(success, fail, "File", "copyTo", [srcURL, parent.toInternalURL(), name]);
};
/**
* Return a URL that can be passed across the bridge to identify this entry.
*/
Entry.prototype.toInternalURL = function() {
if (this.filesystem && this.filesystem.__format__) {
return this.filesystem.__format__(this.fullPath, this.nativeURL);
}
};
/**
* Return a URL that can be used to identify this entry.
* Use a URL that can be used to as the src attribute of a <video> or
* <audio> tag. If that is not possible, construct a cdvfile:// URL.
*/
Entry.prototype.toURL = function() {
if (this.nativeURL) {
return this.nativeURL;
}
// fullPath attribute may contain the full URL in the case that
// toInternalURL fails.
return this.toInternalURL() || "file://localhost" + this.fullPath;
};
/**
* Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
* cdvfile:// URL, and this method was necessary to obtain URLs usable by the
* webview.
* See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
* and CB-6300.
*/
Entry.prototype.toNativeURL = function() {
console.log("DEPRECATED: Update your code to use 'toURL'");
return this.toURL();
};
/**
* Returns a URI that can be used to identify this entry.
*
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
* @return uri
*/
Entry.prototype.toURI = function(mimeType) {
console.log("DEPRECATED: Update your code to use 'toURL'");
return this.toURL();
};
/**
* Remove a file or directory. It is an error to attempt to delete a
* directory that is not empty. It is an error to attempt to delete a
* root directory of a file system.
*
* @param successCallback {Function} called with no parameters
* @param errorCallback {Function} called with a FileError
*/
Entry.prototype.remove = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'Entry.remove', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(successCallback, fail, "File", "remove", [this.toInternalURL()]);
};
/**
* Look up the parent DirectoryEntry of this entry.
*
* @param successCallback {Function} called with the parent DirectoryEntry object
* @param errorCallback {Function} called with a FileError
*/
Entry.prototype.getParent = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'Entry.getParent', arguments);
var fs = this.filesystem;
var win = successCallback && function(result) {
var DirectoryEntry = require('./DirectoryEntry');
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
successCallback(entry);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getParent", [this.toInternalURL()]);
};
module.exports = Entry;
});

View File

@@ -0,0 +1,81 @@
cordova.define("cordova-plugin-file.File", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Constructor.
* name {DOMString} name of the file, without path information
* fullPath {DOMString} the full path of the file, including the name
* type {DOMString} mime type
* lastModifiedDate {Date} last modified date
* size {Number} size of the file in bytes
*/
var File = function(name, localURL, type, lastModifiedDate, size){
this.name = name || '';
this.localURL = localURL || null;
this.type = type || null;
this.lastModified = lastModifiedDate || null;
// For backwards compatibility, store the timestamp in lastModifiedDate as well
this.lastModifiedDate = lastModifiedDate || null;
this.size = size || 0;
// These store the absolute start and end for slicing the file.
this.start = 0;
this.end = this.size;
};
/**
* Returns a "slice" of the file. Since Cordova Files don't contain the actual
* content, this really returns a File with adjusted start and end.
* Slices of slices are supported.
* start {Number} The index at which to start the slice (inclusive).
* end {Number} The index at which to end the slice (exclusive).
*/
File.prototype.slice = function(start, end) {
var size = this.end - this.start;
var newStart = 0;
var newEnd = size;
if (arguments.length) {
if (start < 0) {
newStart = Math.max(size + start, 0);
} else {
newStart = Math.min(size, start);
}
}
if (arguments.length >= 2) {
if (end < 0) {
newEnd = Math.max(size + end, 0);
} else {
newEnd = Math.min(end, size);
}
}
var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
newFile.start = this.start + newStart;
newFile.end = this.start + newEnd;
return newFile;
};
module.exports = File;
});

View File

@@ -0,0 +1,83 @@
cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) { /*
*
* 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.
*
*/
var utils = require('cordova/utils'),
exec = require('cordova/exec'),
Entry = require('./Entry'),
FileWriter = require('./FileWriter'),
File = require('./File'),
FileError = require('./FileError');
/**
* An interface representing a file on the file system.
*
* {boolean} isFile always true (readonly)
* {boolean} isDirectory always false (readonly)
* {DOMString} name of the file, excluding the path leading to it (readonly)
* {DOMString} fullPath the absolute full path to the file (readonly)
* {FileSystem} filesystem on which the file resides (readonly)
*/
var FileEntry = function(name, fullPath, fileSystem, nativeURL) {
FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
};
utils.extend(FileEntry, Entry);
/**
* Creates a new FileWriter associated with the file that this FileEntry represents.
*
* @param {Function} successCallback is called with the new FileWriter
* @param {Function} errorCallback is called with a FileError
*/
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
this.file(function(filePointer) {
var writer = new FileWriter(filePointer);
if (writer.localURL === null || writer.localURL === "") {
errorCallback && errorCallback(new FileError(FileError.INVALID_STATE_ERR));
} else {
successCallback && successCallback(writer);
}
}, errorCallback);
};
/**
* Returns a File that represents the current state of the file that this FileEntry represents.
*
* @param {Function} successCallback is called with the new File object
* @param {Function} errorCallback is called with a FileError
*/
FileEntry.prototype.file = function(successCallback, errorCallback) {
var localURL = this.toInternalURL();
var win = successCallback && function(f) {
var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
successCallback(file);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getFileMetadata", [localURL]);
};
module.exports = FileEntry;
});

View File

@@ -0,0 +1,48 @@
cordova.define("cordova-plugin-file.FileError", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* FileError
*/
function FileError(error) {
this.code = error || null;
}
// File error codes
// Found in DOMException
FileError.NOT_FOUND_ERR = 1;
FileError.SECURITY_ERR = 2;
FileError.ABORT_ERR = 3;
// Added by File API specification
FileError.NOT_READABLE_ERR = 4;
FileError.ENCODING_ERR = 5;
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
FileError.INVALID_STATE_ERR = 7;
FileError.SYNTAX_ERR = 8;
FileError.INVALID_MODIFICATION_ERR = 9;
FileError.QUOTA_EXCEEDED_ERR = 10;
FileError.TYPE_MISMATCH_ERR = 11;
FileError.PATH_EXISTS_ERR = 12;
module.exports = FileError;
});

View File

@@ -0,0 +1,392 @@
cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec'),
modulemapper = require('cordova/modulemapper'),
utils = require('cordova/utils'),
File = require('./File'),
FileError = require('./FileError'),
ProgressEvent = require('./ProgressEvent'),
origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
/**
* This class reads the mobile device file system.
*
* For Android:
* The root directory is the root of the file system.
* To read from the SD card, the file name is "sdcard/my_file.txt"
* @constructor
*/
var FileReader = function() {
this._readyState = 0;
this._error = null;
this._result = null;
this._localURL = '';
this._realReader = origFileReader ? new origFileReader() : {};
};
// States
FileReader.EMPTY = 0;
FileReader.LOADING = 1;
FileReader.DONE = 2;
utils.defineGetter(FileReader.prototype, 'readyState', function() {
return this._localURL ? this._readyState : this._realReader.readyState;
});
utils.defineGetter(FileReader.prototype, 'error', function() {
return this._localURL ? this._error: this._realReader.error;
});
utils.defineGetter(FileReader.prototype, 'result', function() {
return this._localURL ? this._result: this._realReader.result;
});
function defineEvent(eventName) {
utils.defineGetterSetter(FileReader.prototype, eventName, function() {
return this._realReader[eventName] || null;
}, function(value) {
this._realReader[eventName] = value;
});
}
defineEvent('onloadstart'); // When the read starts.
defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
defineEvent('onload'); // When the read has successfully completed.
defineEvent('onerror'); // When the read has failed (see errors).
defineEvent('onloadend'); // When the request has completed (either in success or failure).
defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
function initRead(reader, file) {
// Already loading something
if (reader.readyState == FileReader.LOADING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
reader._result = null;
reader._error = null;
reader._readyState = FileReader.LOADING;
if (typeof file.localURL == 'string') {
reader._localURL = file.localURL;
} else {
reader._localURL = '';
return true;
}
reader.onloadstart && reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
}
/**
* Abort reading file.
*/
FileReader.prototype.abort = function() {
if (origFileReader && !this._localURL) {
return this._realReader.abort();
}
this._result = null;
if (this._readyState == FileReader.DONE || this._readyState == FileReader.EMPTY) {
return;
}
this._readyState = FileReader.DONE;
// If abort callback
if (typeof this.onabort === 'function') {
this.onabort(new ProgressEvent('abort', {target:this}));
}
// If load end callback
if (typeof this.onloadend === 'function') {
this.onloadend(new ProgressEvent('loadend', {target:this}));
}
};
/**
* Read text file.
*
* @param file {File} File object containing file properties
* @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
*/
FileReader.prototype.readAsText = function(file, encoding) {
if (initRead(this, file)) {
return this._realReader.readAsText(file, encoding);
}
// Default encoding is UTF-8
var enc = encoding ? encoding : "UTF-8";
var me = this;
var execArgs = [this._localURL, enc, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
// Save result
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
// null result
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsText", execArgs);
};
/**
* Read file and return data as a base64 encoded data url.
* A data url is of the form:
* data:[<mediatype>][;base64],<data>
*
* @param file {File} File object containing file properties
*/
FileReader.prototype.readAsDataURL = function(file) {
if (initRead(this, file)) {
return this._realReader.readAsDataURL(file);
}
var me = this;
var execArgs = [this._localURL, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
// Save result
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsDataURL", execArgs);
};
/**
* Read file and return data as a binary data.
*
* @param file {File} File object containing file properties
*/
FileReader.prototype.readAsBinaryString = function(file) {
if (initRead(this, file)) {
return this._realReader.readAsBinaryString(file);
}
var me = this;
var execArgs = [this._localURL, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsBinaryString", execArgs);
};
/**
* Read file and return data as a binary data.
*
* @param file {File} File object containing file properties
*/
FileReader.prototype.readAsArrayBuffer = function(file) {
if (initRead(this, file)) {
return this._realReader.readAsArrayBuffer(file);
}
var me = this;
var execArgs = [this._localURL, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
if (r instanceof Array) {
r = new Uint8Array(r).buffer;
}
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsArrayBuffer", execArgs);
};
module.exports = FileReader;
});

View File

@@ -0,0 +1,50 @@
cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
var DirectoryEntry = require('./DirectoryEntry');
/**
* An interface representing a file system
*
* @constructor
* {DOMString} name the unique name of the file system (readonly)
* {DirectoryEntry} root directory of the file system (readonly)
*/
var FileSystem = function(name, root) {
this.name = name;
if (root) {
this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
} else {
this.root = new DirectoryEntry(this.name, '/', this);
}
};
FileSystem.prototype.__format__ = function(fullPath, nativeUrl) {
return fullPath;
};
FileSystem.prototype.toJSON = function() {
return "<FileSystem: " + this.name + ">";
};
module.exports = FileSystem;
});

View File

@@ -0,0 +1,43 @@
cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Options to customize the HTTP request used to upload files.
* @constructor
* @param fileKey {String} Name of file request parameter.
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
* @param params {Object} Object with key: value params to send to the server.
* @param headers {Object} Keys are header names, values are header values. Multiple
* headers of the same name are not supported.
*/
var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers, httpMethod) {
this.fileKey = fileKey || null;
this.fileName = fileName || null;
this.mimeType = mimeType || null;
this.params = params || null;
this.headers = headers || null;
this.httpMethod = httpMethod || null;
};
module.exports = FileUploadOptions;
});

View File

@@ -0,0 +1,31 @@
cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* FileUploadResult
* @constructor
*/
module.exports = function FileUploadResult(size, code, content) {
this.bytesSent = size;
this.responseCode = code;
this.response = content;
};
});

View File

@@ -0,0 +1,304 @@
cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec'),
FileError = require('./FileError'),
ProgressEvent = require('./ProgressEvent');
/**
* This class writes to the mobile device file system.
*
* For Android:
* The root directory is the root of the file system.
* To write to the SD card, the file name is "sdcard/my_file.txt"
*
* @constructor
* @param file {File} File object containing file properties
* @param append if true write to the end of the file, otherwise overwrite the file
*/
var FileWriter = function(file) {
this.fileName = "";
this.length = 0;
if (file) {
this.localURL = file.localURL || file;
this.length = file.size || 0;
}
// default is to write at the beginning of the file
this.position = 0;
this.readyState = 0; // EMPTY
this.result = null;
// Error
this.error = null;
// Event handlers
this.onwritestart = null; // When writing starts
this.onprogress = null; // While writing the file, and reporting partial file data
this.onwrite = null; // When the write has successfully completed.
this.onwriteend = null; // When the request has completed (either in success or failure).
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
this.onerror = null; // When the write has failed (see errors).
};
// States
FileWriter.INIT = 0;
FileWriter.WRITING = 1;
FileWriter.DONE = 2;
/**
* Abort writing file.
*/
FileWriter.prototype.abort = function() {
// check for invalid state
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// set error
this.error = new FileError(FileError.ABORT_ERR);
this.readyState = FileWriter.DONE;
// If abort callback
if (typeof this.onabort === "function") {
this.onabort(new ProgressEvent("abort", {"target":this}));
}
// If write end callback
if (typeof this.onwriteend === "function") {
this.onwriteend(new ProgressEvent("writeend", {"target":this}));
}
};
/**
* Writes data to the file
*
* @param data text or blob to be written
*/
FileWriter.prototype.write = function(data) {
var that=this;
var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
var isBinary;
// Check to see if the incoming data is a blob
if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
var fileReader = new FileReader();
fileReader.onload = function() {
// Call this method again, with the arraybuffer as argument
FileWriter.prototype.write.call(that, this.result);
};
if (supportsBinary) {
fileReader.readAsArrayBuffer(data);
} else {
fileReader.readAsText(data);
}
return;
}
// Mark data type for safer transport over the binary bridge
isBinary = supportsBinary && (data instanceof ArrayBuffer);
if (isBinary && cordova.platformId === "windowsphone") {
// create a plain array, using the keys from the Uint8Array view so that we can serialize it
data = Array.apply(null, new Uint8Array(data));
}
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// WRITING state
this.readyState = FileWriter.WRITING;
var me = this;
// If onwritestart callback
if (typeof me.onwritestart === "function") {
me.onwritestart(new ProgressEvent("writestart", {"target":me}));
}
// Write file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// position always increases by bytes written because file would be extended
me.position += r;
// The length of the file is now where we are done writing.
me.length = me.position;
// DONE state
me.readyState = FileWriter.DONE;
// If onwrite callback
if (typeof me.onwrite === "function") {
me.onwrite(new ProgressEvent("write", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Save error
me.error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
}, "File", "write", [this.localURL, data, this.position, isBinary]);
};
/**
* Moves the file pointer to the location specified.
*
* If the offset is a negative number the position of the file
* pointer is rewound. If the offset is greater than the file
* size the position is set to the end of the file.
*
* @param offset is the location to move the file pointer to.
*/
FileWriter.prototype.seek = function(offset) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
if (!offset && offset !== 0) {
return;
}
// See back from end of file.
if (offset < 0) {
this.position = Math.max(offset + this.length, 0);
}
// Offset is bigger than file size so set position
// to the end of the file.
else if (offset > this.length) {
this.position = this.length;
}
// Offset is between 0 and file size so set the position
// to start writing.
else {
this.position = offset;
}
};
/**
* Truncates the file to the size specified.
*
* @param size to chop the file at.
*/
FileWriter.prototype.truncate = function(size) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// WRITING state
this.readyState = FileWriter.WRITING;
var me = this;
// If onwritestart callback
if (typeof me.onwritestart === "function") {
me.onwritestart(new ProgressEvent("writestart", {"target":this}));
}
// Write file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Update the length of the file
me.length = r;
me.position = Math.min(me.position, r);
// If onwrite callback
if (typeof me.onwrite === "function") {
me.onwrite(new ProgressEvent("write", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Save error
me.error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
}, "File", "truncate", [this.localURL, size]);
};
module.exports = FileWriter;
});

View File

@@ -0,0 +1,38 @@
cordova.define("cordova-plugin-file.Flags", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Supplies arguments to methods that lookup or create files and directories.
*
* @param create
* {boolean} file or directory if it doesn't exist
* @param exclusive
* {boolean} used with create; if true the command will fail if
* target path exists
*/
function Flags(create, exclusive) {
this.create = create || false;
this.exclusive = exclusive || false;
}
module.exports = Flags;
});

View File

@@ -0,0 +1,25 @@
cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
exports.TEMPORARY = 0;
exports.PERSISTENT = 1;
});

View File

@@ -0,0 +1,42 @@
cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Information about the state of the file or directory
*
* {Date} modificationTime (readonly)
*/
var Metadata = function(metadata) {
if (typeof metadata == "object") {
this.modificationTime = new Date(metadata.modificationTime);
this.size = metadata.size || 0;
} else if (typeof metadata == "undefined") {
this.modificationTime = null;
this.size = 0;
} else {
/* Backwards compatiblity with platforms that only return a timestamp */
this.modificationTime = new Date(metadata);
}
};
module.exports = Metadata;
});

View File

@@ -0,0 +1,69 @@
cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) { /*
*
* 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.
*
*/
// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
// Feature test: See if we can instantiate a native ProgressEvent;
// if so, use that approach,
// otherwise fill-in with our own implementation.
//
// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
var ProgressEvent = (function() {
/*
var createEvent = function(data) {
var event = document.createEvent('Events');
event.initEvent('ProgressEvent', false, false);
if (data) {
for (var i in data) {
if (data.hasOwnProperty(i)) {
event[i] = data[i];
}
}
if (data.target) {
// TODO: cannot call <some_custom_object>.dispatchEvent
// need to first figure out how to implement EventTarget
}
}
return event;
};
try {
var ev = createEvent({type:"abort",target:document});
return function ProgressEvent(type, data) {
data.type = type;
return createEvent(data);
};
} catch(e){
*/
return function ProgressEvent(type, dict) {
this.type = type;
this.bubbles = false;
this.cancelBubble = false;
this.cancelable = false;
this.lengthComputable = false;
this.loaded = dict && dict.loaded ? dict.loaded : 0;
this.total = dict && dict.total ? dict.total : 0;
this.target = dict && dict.target ? dict.target : null;
};
//}
})();
module.exports = ProgressEvent;
});

View File

@@ -0,0 +1,38 @@
cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
FILESYSTEM_PROTOCOL = "cdvfile";
module.exports = {
__format__: function(fullPath, nativeUrl) {
var path = '/' + this.name + '/' + encodeURI(fullPath);
path = path.replace('//','/');
var ret = FILESYSTEM_PROTOCOL + '://localhost' + path;
var m = /\?.*/.exec(nativeUrl);
if (m) {
ret += m[0];
}
return ret;
}
};
});

View File

@@ -0,0 +1,65 @@
cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec');
var channel = require('cordova/channel');
exports.file = {
// Read-only directory where the application is installed.
applicationDirectory: null,
// Root of app's private writable storage
applicationStorageDirectory: null,
// Where to put app-specific data files.
dataDirectory: null,
// Cached files that should survive app restarts.
// Apps should not rely on the OS to delete files in here.
cacheDirectory: null,
// Android: the application space on external storage.
externalApplicationStorageDirectory: null,
// Android: Where to put app-specific data files on external storage.
externalDataDirectory: null,
// Android: the application cache on external storage.
externalCacheDirectory: null,
// Android: the external storage (SD card) root.
externalRootDirectory: null,
// iOS: Temp directory that the OS can clear at will.
tempDirectory: null,
// iOS: Holds app-specific files that should be synced (e.g. to iCloud).
syncedDataDirectory: null,
// iOS: Files private to the app, but that are meaningful to other applciations (e.g. Office files)
documentsDirectory: null,
// BlackBerry10: Files globally available to all apps
sharedDirectory: null
};
channel.waitForInitialization('onFileSystemPathsReady');
channel.onCordovaReady.subscribe(function() {
function after(paths) {
for (var k in paths) {
exports.file[k] = paths[k];
}
channel.initializationComplete('onFileSystemPathsReady');
}
exec(after, null, 'File', 'requestAllPaths', []);
});
});

View File

@@ -0,0 +1,46 @@
cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) { /*
*
* 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.
*
*/
// Map of fsName -> FileSystem.
var fsMap = null;
var FileSystem = require('./FileSystem');
var exec = require('cordova/exec');
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
require('./fileSystems').getFs = function(name, callback) {
if (fsMap) {
callback(fsMap[name]);
} else {
exec(success, null, "File", "requestAllFileSystems", []);
function success(response) {
fsMap = {};
for (var i = 0; i < response.length; ++i) {
var fsRoot = response[i];
var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
fsMap[fs.name] = fs;
}
callback(fsMap[name]);
}
}
};
});

View File

@@ -0,0 +1,27 @@
cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) { /*
*
* 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.
*
*/
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
module.exports.getFs = function(name, callback) {
callback(null);
};
});

View File

@@ -0,0 +1,78 @@
cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
//For browser platform: not all browsers use this file.
function checkBrowser() {
if (cordova.platformId === "browser" && navigator.userAgent.search(/Chrome/) > 0) {
var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
module.exports = requestFileSystem;
return;
}
}
checkBrowser();
var argscheck = require('cordova/argscheck'),
FileError = require('./FileError'),
FileSystem = require('./FileSystem'),
exec = require('cordova/exec');
var fileSystems = require('./fileSystems');
/**
* Request a file system in which to store application data.
* @param type local file system type
* @param size indicates how much storage space, in bytes, the application expects to need
* @param successCallback invoked with a FileSystem object
* @param errorCallback invoked if error occurs retrieving file system
*/
var requestFileSystem = function(type, size, successCallback, errorCallback) {
argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
var fail = function(code) {
errorCallback && errorCallback(new FileError(code));
};
if (type < 0) {
fail(FileError.SYNTAX_ERR);
} else {
// if successful, return a FileSystem object
var success = function(file_system) {
if (file_system) {
if (successCallback) {
fileSystems.getFs(file_system.name, function(fs) {
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
if (!fs) {
fs = new FileSystem(file_system.name, file_system.root);
}
successCallback(fs);
});
}
}
else {
// no FileSystem object returned
fail(FileError.NOT_FOUND_ERR);
}
};
exec(success, fail, "File", "requestFileSystem", [type, size]);
}
};
module.exports = requestFileSystem;
});

View File

@@ -0,0 +1,89 @@
cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) { /*
*
* 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.
*
*/
//For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
function checkBrowser() {
if (cordova.platformId === "browser" && navigator.userAgent.search(/Chrome/) > 0) {
var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
module.exports = requestFileSystem;
return;
}
}
checkBrowser();
var argscheck = require('cordova/argscheck'),
DirectoryEntry = require('./DirectoryEntry'),
FileEntry = require('./FileEntry'),
FileError = require('./FileError'),
exec = require('cordova/exec');
var fileSystems = require('./fileSystems');
/**
* Look up file system Entry referred to by local URI.
* @param {DOMString} uri URI referring to a local file or directory
* @param successCallback invoked with Entry object corresponding to URI
* @param errorCallback invoked if error occurs retrieving file system entry
*/
module.exports.resolveLocalFileSystemURL = function(uri, successCallback, errorCallback) {
argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
// error callback
var fail = function(error) {
errorCallback && errorCallback(new FileError(error));
};
// sanity check for 'not:valid:filename' or '/not:valid:filename'
// file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
if(!uri || uri.split(":").length > 2) {
setTimeout( function() {
fail(FileError.ENCODING_ERR);
},0);
return;
}
// if successful, return either a file or directory entry
var success = function(entry) {
if (entry) {
if (successCallback) {
// create appropriate Entry object
var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary');
fileSystems.getFs(fsName, function(fs) {
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
if (!fs) {
fs = new FileSystem(fsName, {name:"", fullPath:"/"});
}
var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
successCallback(result);
});
}
}
else {
// no Entry object returned
fail(FileError.NOT_FOUND_ERR);
}
};
exec(success, fail, "File", "resolveLocalFileSystemURI", [uri]);
};
module.exports.resolveLocalFileSystemURI = function() {
console.log("resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.");
module.exports.resolveLocalFileSystemURL.apply(this, arguments);
};
});

View File

@@ -40,9 +40,13 @@
<div class="row">
<div class="col col-50"><button class="button button-full button-small icon-left ion-image button-custom" ng-disabled="!$parent.preis || !$parent.name || !$parent.freitext" ng-click="validate()">Vorschau</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="buyAdFree()">Jetzt Kaufen</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="buyRose()">Jetzt Kaufen</button></div>
</div>
<div class="row">
<div class="col col-50"><button class="button button-full button-small icon-left ion-image button-custom" ng-disabled="!$parent.preis || !$parent.name || !$parent.freitext" ng-click="loaddata()">Laden</button></div>
<div class="col col-50"><button class="button button-full button-small icon-left ion-social-euro button-custom" ng-disabled="!$parent.preis || !$parent.freitext || !$parent.name" ng-click="savedata()">Speichern</button></div>
</div>
</div>

View File

@@ -55,6 +55,189 @@ module.exports = [
"cordova.InAppBrowser.open",
"window.open"
]
},
{
"file": "plugins/cordova-plugin-file/www/DirectoryEntry.js",
"id": "cordova-plugin-file.DirectoryEntry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.DirectoryEntry"
]
},
{
"file": "plugins/cordova-plugin-file/www/DirectoryReader.js",
"id": "cordova-plugin-file.DirectoryReader",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.DirectoryReader"
]
},
{
"file": "plugins/cordova-plugin-file/www/Entry.js",
"id": "cordova-plugin-file.Entry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Entry"
]
},
{
"file": "plugins/cordova-plugin-file/www/File.js",
"id": "cordova-plugin-file.File",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.File"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileEntry.js",
"id": "cordova-plugin-file.FileEntry",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileEntry"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileError.js",
"id": "cordova-plugin-file.FileError",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileError"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileReader.js",
"id": "cordova-plugin-file.FileReader",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileReader"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileSystem.js",
"id": "cordova-plugin-file.FileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileUploadOptions.js",
"id": "cordova-plugin-file.FileUploadOptions",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileUploadOptions"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileUploadResult.js",
"id": "cordova-plugin-file.FileUploadResult",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileUploadResult"
]
},
{
"file": "plugins/cordova-plugin-file/www/FileWriter.js",
"id": "cordova-plugin-file.FileWriter",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.FileWriter"
]
},
{
"file": "plugins/cordova-plugin-file/www/Flags.js",
"id": "cordova-plugin-file.Flags",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Flags"
]
},
{
"file": "plugins/cordova-plugin-file/www/LocalFileSystem.js",
"id": "cordova-plugin-file.LocalFileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.LocalFileSystem"
],
"merges": [
"window"
]
},
{
"file": "plugins/cordova-plugin-file/www/Metadata.js",
"id": "cordova-plugin-file.Metadata",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.Metadata"
]
},
{
"file": "plugins/cordova-plugin-file/www/ProgressEvent.js",
"id": "cordova-plugin-file.ProgressEvent",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.ProgressEvent"
]
},
{
"file": "plugins/cordova-plugin-file/www/fileSystems.js",
"id": "cordova-plugin-file.fileSystems",
"pluginId": "cordova-plugin-file"
},
{
"file": "plugins/cordova-plugin-file/www/requestFileSystem.js",
"id": "cordova-plugin-file.requestFileSystem",
"pluginId": "cordova-plugin-file",
"clobbers": [
"window.requestFileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/resolveLocalFileSystemURI.js",
"id": "cordova-plugin-file.resolveLocalFileSystemURI",
"pluginId": "cordova-plugin-file",
"merges": [
"window"
]
},
{
"file": "plugins/cordova-plugin-file/www/android/FileSystem.js",
"id": "cordova-plugin-file.androidFileSystem",
"pluginId": "cordova-plugin-file",
"merges": [
"FileSystem"
]
},
{
"file": "plugins/cordova-plugin-file/www/fileSystems-roots.js",
"id": "cordova-plugin-file.fileSystems-roots",
"pluginId": "cordova-plugin-file",
"runs": true
},
{
"file": "plugins/cordova-plugin-file/www/fileSystemPaths.js",
"id": "cordova-plugin-file.fileSystemPaths",
"pluginId": "cordova-plugin-file",
"merges": [
"cordova"
],
"runs": true
},
{
"file": "plugins/cordova-plugin-file-transfer/www/FileTransferError.js",
"id": "cordova-plugin-file-transfer.FileTransferError",
"pluginId": "cordova-plugin-file-transfer",
"clobbers": [
"window.FileTransferError"
]
},
{
"file": "plugins/cordova-plugin-file-transfer/www/FileTransfer.js",
"id": "cordova-plugin-file-transfer.FileTransfer",
"pluginId": "cordova-plugin-file-transfer",
"clobbers": [
"window.FileTransfer"
]
}
];
module.exports.metadata =
@@ -67,7 +250,9 @@ module.exports.metadata =
"cordova-plugin-statusbar": "2.0.0",
"cordova-plugin-whitelist": "1.2.0",
"ionic-plugin-keyboard": "1.0.8",
"cordova-plugin-inappbrowser": "1.1.1"
"cordova-plugin-inappbrowser": "1.1.1",
"cordova-plugin-file": "3.0.0",
"cordova-plugin-file-transfer": "1.4.0"
}
// BOTTOM OF METADATA
});

View File

@@ -0,0 +1,237 @@
cordova.define("cordova-plugin-file-transfer.FileTransfer", function(require, exports, module) { /*
*
* 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.
*
*/
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
FileTransferError = require('./FileTransferError'),
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*))?).*$/,
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 (headers.hasOwnProperty(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 {
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;
});

View File

@@ -0,0 +1,43 @@
cordova.define("cordova-plugin-file-transfer.FileTransferError", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* FileTransferError
* @constructor
*/
var FileTransferError = function(code, source, target, status, body, exception) {
this.code = code || null;
this.source = source || null;
this.target = target || null;
this.http_status = status || null;
this.body = body || null;
this.exception = exception || null;
};
FileTransferError.FILE_NOT_FOUND_ERR = 1;
FileTransferError.INVALID_URL_ERR = 2;
FileTransferError.CONNECTION_ERR = 3;
FileTransferError.ABORT_ERR = 4;
FileTransferError.NOT_MODIFIED_ERR = 5;
module.exports = FileTransferError;
});

View File

@@ -0,0 +1,119 @@
cordova.define("cordova-plugin-file.DirectoryEntry", function(require, exports, module) { /*
*
* 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.
*
*/
var argscheck = require('cordova/argscheck'),
utils = require('cordova/utils'),
exec = require('cordova/exec'),
Entry = require('./Entry'),
FileError = require('./FileError'),
DirectoryReader = require('./DirectoryReader');
/**
* An interface representing a directory on the file system.
*
* {boolean} isFile always false (readonly)
* {boolean} isDirectory always true (readonly)
* {DOMString} name of the directory, excluding the path leading to it (readonly)
* {DOMString} fullPath the absolute full path to the directory (readonly)
* {FileSystem} filesystem on which the directory resides (readonly)
*/
var DirectoryEntry = function(name, fullPath, fileSystem, nativeURL) {
// add trailing slash if it is missing
if ((fullPath) && !/\/$/.test(fullPath)) {
fullPath += "/";
}
// add trailing slash if it is missing
if (nativeURL && !/\/$/.test(nativeURL)) {
nativeURL += "/";
}
DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, fileSystem, nativeURL);
};
utils.extend(DirectoryEntry, Entry);
/**
* Creates a new DirectoryReader to read entries from this directory
*/
DirectoryEntry.prototype.createReader = function() {
return new DirectoryReader(this.toInternalURL());
};
/**
* Creates or looks up a directory
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a directory
* @param {Flags} options to create or exclusively create the directory
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
DirectoryEntry.prototype.getDirectory = function(path, options, successCallback, errorCallback) {
argscheck.checkArgs('sOFF', 'DirectoryEntry.getDirectory', arguments);
var fs = this.filesystem;
var win = successCallback && function(result) {
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
successCallback(entry);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getDirectory", [this.toInternalURL(), path, options]);
};
/**
* Deletes a directory and all of it's contents
*
* @param {Function} successCallback is called with no parameters
* @param {Function} errorCallback is called with a FileError
*/
DirectoryEntry.prototype.removeRecursively = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'DirectoryEntry.removeRecursively', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(successCallback, fail, "File", "removeRecursively", [this.toInternalURL()]);
};
/**
* Creates or looks up a file
*
* @param {DOMString} path either a relative or absolute path from this directory in which to look up or create a file
* @param {Flags} options to create or exclusively create the file
* @param {Function} successCallback is called with the new entry
* @param {Function} errorCallback is called with a FileError
*/
DirectoryEntry.prototype.getFile = function(path, options, successCallback, errorCallback) {
argscheck.checkArgs('sOFF', 'DirectoryEntry.getFile', arguments);
var fs = this.filesystem;
var win = successCallback && function(result) {
var FileEntry = require('./FileEntry');
var entry = new FileEntry(result.name, result.fullPath, fs, result.nativeURL);
successCallback(entry);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getFile", [this.toInternalURL(), path, options]);
};
module.exports = DirectoryEntry;
});

View File

@@ -0,0 +1,75 @@
cordova.define("cordova-plugin-file.DirectoryReader", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec'),
FileError = require('./FileError') ;
/**
* An interface that lists the files and directories in a directory.
*/
function DirectoryReader(localURL) {
this.localURL = localURL || null;
this.hasReadEntries = false;
}
/**
* Returns a list of entries from a directory.
*
* @param {Function} successCallback is called with a list of entries
* @param {Function} errorCallback is called with a FileError
*/
DirectoryReader.prototype.readEntries = function(successCallback, errorCallback) {
// If we've already read and passed on this directory's entries, return an empty list.
if (this.hasReadEntries) {
successCallback([]);
return;
}
var reader = this;
var win = typeof successCallback !== 'function' ? null : function(result) {
var retVal = [];
for (var i=0; i<result.length; i++) {
var entry = null;
if (result[i].isDirectory) {
entry = new (require('./DirectoryEntry'))();
}
else if (result[i].isFile) {
entry = new (require('./FileEntry'))();
}
entry.isDirectory = result[i].isDirectory;
entry.isFile = result[i].isFile;
entry.name = result[i].name;
entry.fullPath = result[i].fullPath;
entry.filesystem = new (require('./FileSystem'))(result[i].filesystemName);
entry.nativeURL = result[i].nativeURL;
retVal.push(entry);
}
reader.hasReadEntries = true;
successCallback(retVal);
};
var fail = typeof errorCallback !== 'function' ? null : function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "readEntries", [this.localURL]);
};
module.exports = DirectoryReader;
});

View File

@@ -0,0 +1,262 @@
cordova.define("cordova-plugin-file.Entry", function(require, exports, module) { /*
*
* 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.
*
*/
var argscheck = require('cordova/argscheck'),
exec = require('cordova/exec'),
FileError = require('./FileError'),
Metadata = require('./Metadata');
/**
* Represents a file or directory on the local file system.
*
* @param isFile
* {boolean} true if Entry is a file (readonly)
* @param isDirectory
* {boolean} true if Entry is a directory (readonly)
* @param name
* {DOMString} name of the file or directory, excluding the path
* leading to it (readonly)
* @param fullPath
* {DOMString} the absolute full path to the file or directory
* (readonly)
* @param fileSystem
* {FileSystem} the filesystem on which this entry resides
* (readonly)
* @param nativeURL
* {DOMString} an alternate URL which can be used by native
* webview controls, for example media players.
* (optional, readonly)
*/
function Entry(isFile, isDirectory, name, fullPath, fileSystem, nativeURL) {
this.isFile = !!isFile;
this.isDirectory = !!isDirectory;
this.name = name || '';
this.fullPath = fullPath || '';
this.filesystem = fileSystem || null;
this.nativeURL = nativeURL || null;
}
/**
* Look up the metadata of the entry.
*
* @param successCallback
* {Function} is called with a Metadata object
* @param errorCallback
* {Function} is called with a FileError
*/
Entry.prototype.getMetadata = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'Entry.getMetadata', arguments);
var success = successCallback && function(entryMetadata) {
var metadata = new Metadata({
size: entryMetadata.size,
modificationTime: entryMetadata.lastModifiedDate
});
successCallback(metadata);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(success, fail, "File", "getFileMetadata", [this.toInternalURL()]);
};
/**
* Set the metadata of the entry.
*
* @param successCallback
* {Function} is called with a Metadata object
* @param errorCallback
* {Function} is called with a FileError
* @param metadataObject
* {Object} keys and values to set
*/
Entry.prototype.setMetadata = function(successCallback, errorCallback, metadataObject) {
argscheck.checkArgs('FFO', 'Entry.setMetadata', arguments);
exec(successCallback, errorCallback, "File", "setMetadata", [this.toInternalURL(), metadataObject]);
};
/**
* Move a file or directory to a new location.
*
* @param parent
* {DirectoryEntry} the directory to which to move this entry
* @param newName
* {DOMString} new name of the entry, defaults to the current name
* @param successCallback
* {Function} called with the new DirectoryEntry object
* @param errorCallback
* {Function} called with a FileError
*/
Entry.prototype.moveTo = function(parent, newName, successCallback, errorCallback) {
argscheck.checkArgs('oSFF', 'Entry.moveTo', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
var filesystem = this.filesystem,
srcURL = this.toInternalURL(),
// entry name
name = newName || this.name,
success = function(entry) {
if (entry) {
if (successCallback) {
// create appropriate Entry object
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
successCallback(result);
}
}
else {
// no Entry object returned
fail && fail(FileError.NOT_FOUND_ERR);
}
};
// copy
exec(success, fail, "File", "moveTo", [srcURL, parent.toInternalURL(), name]);
};
/**
* Copy a directory to a different location.
*
* @param parent
* {DirectoryEntry} the directory to which to copy the entry
* @param newName
* {DOMString} new name of the entry, defaults to the current name
* @param successCallback
* {Function} called with the new Entry object
* @param errorCallback
* {Function} called with a FileError
*/
Entry.prototype.copyTo = function(parent, newName, successCallback, errorCallback) {
argscheck.checkArgs('oSFF', 'Entry.copyTo', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
var filesystem = this.filesystem,
srcURL = this.toInternalURL(),
// entry name
name = newName || this.name,
// success callback
success = function(entry) {
if (entry) {
if (successCallback) {
// create appropriate Entry object
var newFSName = entry.filesystemName || (entry.filesystem && entry.filesystem.name);
var fs = newFSName ? new FileSystem(newFSName, { name: "", fullPath: "/" }) : new FileSystem(parent.filesystem.name, { name: "", fullPath: "/" });
var result = (entry.isDirectory) ? new (require('./DirectoryEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL) : new (require('cordova-plugin-file.FileEntry'))(entry.name, entry.fullPath, fs, entry.nativeURL);
successCallback(result);
}
}
else {
// no Entry object returned
fail && fail(FileError.NOT_FOUND_ERR);
}
};
// copy
exec(success, fail, "File", "copyTo", [srcURL, parent.toInternalURL(), name]);
};
/**
* Return a URL that can be passed across the bridge to identify this entry.
*/
Entry.prototype.toInternalURL = function() {
if (this.filesystem && this.filesystem.__format__) {
return this.filesystem.__format__(this.fullPath, this.nativeURL);
}
};
/**
* Return a URL that can be used to identify this entry.
* Use a URL that can be used to as the src attribute of a <video> or
* <audio> tag. If that is not possible, construct a cdvfile:// URL.
*/
Entry.prototype.toURL = function() {
if (this.nativeURL) {
return this.nativeURL;
}
// fullPath attribute may contain the full URL in the case that
// toInternalURL fails.
return this.toInternalURL() || "file://localhost" + this.fullPath;
};
/**
* Backwards-compatibility: In v1.0.0 - 1.0.2, .toURL would only return a
* cdvfile:// URL, and this method was necessary to obtain URLs usable by the
* webview.
* See CB-6051, CB-6106, CB-6117, CB-6152, CB-6199, CB-6201, CB-6243, CB-6249,
* and CB-6300.
*/
Entry.prototype.toNativeURL = function() {
console.log("DEPRECATED: Update your code to use 'toURL'");
return this.toURL();
};
/**
* Returns a URI that can be used to identify this entry.
*
* @param {DOMString} mimeType for a FileEntry, the mime type to be used to interpret the file, when loaded through this URI.
* @return uri
*/
Entry.prototype.toURI = function(mimeType) {
console.log("DEPRECATED: Update your code to use 'toURL'");
return this.toURL();
};
/**
* Remove a file or directory. It is an error to attempt to delete a
* directory that is not empty. It is an error to attempt to delete a
* root directory of a file system.
*
* @param successCallback {Function} called with no parameters
* @param errorCallback {Function} called with a FileError
*/
Entry.prototype.remove = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'Entry.remove', arguments);
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(successCallback, fail, "File", "remove", [this.toInternalURL()]);
};
/**
* Look up the parent DirectoryEntry of this entry.
*
* @param successCallback {Function} called with the parent DirectoryEntry object
* @param errorCallback {Function} called with a FileError
*/
Entry.prototype.getParent = function(successCallback, errorCallback) {
argscheck.checkArgs('FF', 'Entry.getParent', arguments);
var fs = this.filesystem;
var win = successCallback && function(result) {
var DirectoryEntry = require('./DirectoryEntry');
var entry = new DirectoryEntry(result.name, result.fullPath, fs, result.nativeURL);
successCallback(entry);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getParent", [this.toInternalURL()]);
};
module.exports = Entry;
});

View File

@@ -0,0 +1,81 @@
cordova.define("cordova-plugin-file.File", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Constructor.
* name {DOMString} name of the file, without path information
* fullPath {DOMString} the full path of the file, including the name
* type {DOMString} mime type
* lastModifiedDate {Date} last modified date
* size {Number} size of the file in bytes
*/
var File = function(name, localURL, type, lastModifiedDate, size){
this.name = name || '';
this.localURL = localURL || null;
this.type = type || null;
this.lastModified = lastModifiedDate || null;
// For backwards compatibility, store the timestamp in lastModifiedDate as well
this.lastModifiedDate = lastModifiedDate || null;
this.size = size || 0;
// These store the absolute start and end for slicing the file.
this.start = 0;
this.end = this.size;
};
/**
* Returns a "slice" of the file. Since Cordova Files don't contain the actual
* content, this really returns a File with adjusted start and end.
* Slices of slices are supported.
* start {Number} The index at which to start the slice (inclusive).
* end {Number} The index at which to end the slice (exclusive).
*/
File.prototype.slice = function(start, end) {
var size = this.end - this.start;
var newStart = 0;
var newEnd = size;
if (arguments.length) {
if (start < 0) {
newStart = Math.max(size + start, 0);
} else {
newStart = Math.min(size, start);
}
}
if (arguments.length >= 2) {
if (end < 0) {
newEnd = Math.max(size + end, 0);
} else {
newEnd = Math.min(end, size);
}
}
var newFile = new File(this.name, this.localURL, this.type, this.lastModified, this.size);
newFile.start = this.start + newStart;
newFile.end = this.start + newEnd;
return newFile;
};
module.exports = File;
});

View File

@@ -0,0 +1,83 @@
cordova.define("cordova-plugin-file.FileEntry", function(require, exports, module) { /*
*
* 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.
*
*/
var utils = require('cordova/utils'),
exec = require('cordova/exec'),
Entry = require('./Entry'),
FileWriter = require('./FileWriter'),
File = require('./File'),
FileError = require('./FileError');
/**
* An interface representing a file on the file system.
*
* {boolean} isFile always true (readonly)
* {boolean} isDirectory always false (readonly)
* {DOMString} name of the file, excluding the path leading to it (readonly)
* {DOMString} fullPath the absolute full path to the file (readonly)
* {FileSystem} filesystem on which the file resides (readonly)
*/
var FileEntry = function(name, fullPath, fileSystem, nativeURL) {
FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, fileSystem, nativeURL]);
};
utils.extend(FileEntry, Entry);
/**
* Creates a new FileWriter associated with the file that this FileEntry represents.
*
* @param {Function} successCallback is called with the new FileWriter
* @param {Function} errorCallback is called with a FileError
*/
FileEntry.prototype.createWriter = function(successCallback, errorCallback) {
this.file(function(filePointer) {
var writer = new FileWriter(filePointer);
if (writer.localURL === null || writer.localURL === "") {
errorCallback && errorCallback(new FileError(FileError.INVALID_STATE_ERR));
} else {
successCallback && successCallback(writer);
}
}, errorCallback);
};
/**
* Returns a File that represents the current state of the file that this FileEntry represents.
*
* @param {Function} successCallback is called with the new File object
* @param {Function} errorCallback is called with a FileError
*/
FileEntry.prototype.file = function(successCallback, errorCallback) {
var localURL = this.toInternalURL();
var win = successCallback && function(f) {
var file = new File(f.name, localURL, f.type, f.lastModifiedDate, f.size);
successCallback(file);
};
var fail = errorCallback && function(code) {
errorCallback(new FileError(code));
};
exec(win, fail, "File", "getFileMetadata", [localURL]);
};
module.exports = FileEntry;
});

View File

@@ -0,0 +1,48 @@
cordova.define("cordova-plugin-file.FileError", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* FileError
*/
function FileError(error) {
this.code = error || null;
}
// File error codes
// Found in DOMException
FileError.NOT_FOUND_ERR = 1;
FileError.SECURITY_ERR = 2;
FileError.ABORT_ERR = 3;
// Added by File API specification
FileError.NOT_READABLE_ERR = 4;
FileError.ENCODING_ERR = 5;
FileError.NO_MODIFICATION_ALLOWED_ERR = 6;
FileError.INVALID_STATE_ERR = 7;
FileError.SYNTAX_ERR = 8;
FileError.INVALID_MODIFICATION_ERR = 9;
FileError.QUOTA_EXCEEDED_ERR = 10;
FileError.TYPE_MISMATCH_ERR = 11;
FileError.PATH_EXISTS_ERR = 12;
module.exports = FileError;
});

View File

@@ -0,0 +1,392 @@
cordova.define("cordova-plugin-file.FileReader", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec'),
modulemapper = require('cordova/modulemapper'),
utils = require('cordova/utils'),
File = require('./File'),
FileError = require('./FileError'),
ProgressEvent = require('./ProgressEvent'),
origFileReader = modulemapper.getOriginalSymbol(window, 'FileReader');
/**
* This class reads the mobile device file system.
*
* For Android:
* The root directory is the root of the file system.
* To read from the SD card, the file name is "sdcard/my_file.txt"
* @constructor
*/
var FileReader = function() {
this._readyState = 0;
this._error = null;
this._result = null;
this._localURL = '';
this._realReader = origFileReader ? new origFileReader() : {};
};
// States
FileReader.EMPTY = 0;
FileReader.LOADING = 1;
FileReader.DONE = 2;
utils.defineGetter(FileReader.prototype, 'readyState', function() {
return this._localURL ? this._readyState : this._realReader.readyState;
});
utils.defineGetter(FileReader.prototype, 'error', function() {
return this._localURL ? this._error: this._realReader.error;
});
utils.defineGetter(FileReader.prototype, 'result', function() {
return this._localURL ? this._result: this._realReader.result;
});
function defineEvent(eventName) {
utils.defineGetterSetter(FileReader.prototype, eventName, function() {
return this._realReader[eventName] || null;
}, function(value) {
this._realReader[eventName] = value;
});
}
defineEvent('onloadstart'); // When the read starts.
defineEvent('onprogress'); // While reading (and decoding) file or fileBlob data, and reporting partial file data (progress.loaded/progress.total)
defineEvent('onload'); // When the read has successfully completed.
defineEvent('onerror'); // When the read has failed (see errors).
defineEvent('onloadend'); // When the request has completed (either in success or failure).
defineEvent('onabort'); // When the read has been aborted. For instance, by invoking the abort() method.
function initRead(reader, file) {
// Already loading something
if (reader.readyState == FileReader.LOADING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
reader._result = null;
reader._error = null;
reader._readyState = FileReader.LOADING;
if (typeof file.localURL == 'string') {
reader._localURL = file.localURL;
} else {
reader._localURL = '';
return true;
}
reader.onloadstart && reader.onloadstart(new ProgressEvent("loadstart", {target:reader}));
}
/**
* Abort reading file.
*/
FileReader.prototype.abort = function() {
if (origFileReader && !this._localURL) {
return this._realReader.abort();
}
this._result = null;
if (this._readyState == FileReader.DONE || this._readyState == FileReader.EMPTY) {
return;
}
this._readyState = FileReader.DONE;
// If abort callback
if (typeof this.onabort === 'function') {
this.onabort(new ProgressEvent('abort', {target:this}));
}
// If load end callback
if (typeof this.onloadend === 'function') {
this.onloadend(new ProgressEvent('loadend', {target:this}));
}
};
/**
* Read text file.
*
* @param file {File} File object containing file properties
* @param encoding [Optional] (see http://www.iana.org/assignments/character-sets)
*/
FileReader.prototype.readAsText = function(file, encoding) {
if (initRead(this, file)) {
return this._realReader.readAsText(file, encoding);
}
// Default encoding is UTF-8
var enc = encoding ? encoding : "UTF-8";
var me = this;
var execArgs = [this._localURL, enc, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
// Save result
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
// null result
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsText", execArgs);
};
/**
* Read file and return data as a base64 encoded data url.
* A data url is of the form:
* data:[<mediatype>][;base64],<data>
*
* @param file {File} File object containing file properties
*/
FileReader.prototype.readAsDataURL = function(file) {
if (initRead(this, file)) {
return this._realReader.readAsDataURL(file);
}
var me = this;
var execArgs = [this._localURL, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
// Save result
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsDataURL", execArgs);
};
/**
* Read file and return data as a binary data.
*
* @param file {File} File object containing file properties
*/
FileReader.prototype.readAsBinaryString = function(file) {
if (initRead(this, file)) {
return this._realReader.readAsBinaryString(file);
}
var me = this;
var execArgs = [this._localURL, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsBinaryString", execArgs);
};
/**
* Read file and return data as a binary data.
*
* @param file {File} File object containing file properties
*/
FileReader.prototype.readAsArrayBuffer = function(file) {
if (initRead(this, file)) {
return this._realReader.readAsArrayBuffer(file);
}
var me = this;
var execArgs = [this._localURL, file.start, file.end];
// Read file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
if (r instanceof Array) {
r = new Uint8Array(r).buffer;
}
me._result = r;
// If onload callback
if (typeof me.onload === "function") {
me.onload(new ProgressEvent("load", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me._readyState === FileReader.DONE) {
return;
}
// DONE state
me._readyState = FileReader.DONE;
me._result = null;
// Save error
me._error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {target:me}));
}
// If onloadend callback
if (typeof me.onloadend === "function") {
me.onloadend(new ProgressEvent("loadend", {target:me}));
}
}, "File", "readAsArrayBuffer", execArgs);
};
module.exports = FileReader;
});

View File

@@ -0,0 +1,50 @@
cordova.define("cordova-plugin-file.FileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
var DirectoryEntry = require('./DirectoryEntry');
/**
* An interface representing a file system
*
* @constructor
* {DOMString} name the unique name of the file system (readonly)
* {DirectoryEntry} root directory of the file system (readonly)
*/
var FileSystem = function(name, root) {
this.name = name;
if (root) {
this.root = new DirectoryEntry(root.name, root.fullPath, this, root.nativeURL);
} else {
this.root = new DirectoryEntry(this.name, '/', this);
}
};
FileSystem.prototype.__format__ = function(fullPath, nativeUrl) {
return fullPath;
};
FileSystem.prototype.toJSON = function() {
return "<FileSystem: " + this.name + ">";
};
module.exports = FileSystem;
});

View File

@@ -0,0 +1,43 @@
cordova.define("cordova-plugin-file.FileUploadOptions", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Options to customize the HTTP request used to upload files.
* @constructor
* @param fileKey {String} Name of file request parameter.
* @param fileName {String} Filename to be used by the server. Defaults to image.jpg.
* @param mimeType {String} Mimetype of the uploaded file. Defaults to image/jpeg.
* @param params {Object} Object with key: value params to send to the server.
* @param headers {Object} Keys are header names, values are header values. Multiple
* headers of the same name are not supported.
*/
var FileUploadOptions = function(fileKey, fileName, mimeType, params, headers, httpMethod) {
this.fileKey = fileKey || null;
this.fileName = fileName || null;
this.mimeType = mimeType || null;
this.params = params || null;
this.headers = headers || null;
this.httpMethod = httpMethod || null;
};
module.exports = FileUploadOptions;
});

View File

@@ -0,0 +1,31 @@
cordova.define("cordova-plugin-file.FileUploadResult", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* FileUploadResult
* @constructor
*/
module.exports = function FileUploadResult(size, code, content) {
this.bytesSent = size;
this.responseCode = code;
this.response = content;
};
});

View File

@@ -0,0 +1,304 @@
cordova.define("cordova-plugin-file.FileWriter", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec'),
FileError = require('./FileError'),
ProgressEvent = require('./ProgressEvent');
/**
* This class writes to the mobile device file system.
*
* For Android:
* The root directory is the root of the file system.
* To write to the SD card, the file name is "sdcard/my_file.txt"
*
* @constructor
* @param file {File} File object containing file properties
* @param append if true write to the end of the file, otherwise overwrite the file
*/
var FileWriter = function(file) {
this.fileName = "";
this.length = 0;
if (file) {
this.localURL = file.localURL || file;
this.length = file.size || 0;
}
// default is to write at the beginning of the file
this.position = 0;
this.readyState = 0; // EMPTY
this.result = null;
// Error
this.error = null;
// Event handlers
this.onwritestart = null; // When writing starts
this.onprogress = null; // While writing the file, and reporting partial file data
this.onwrite = null; // When the write has successfully completed.
this.onwriteend = null; // When the request has completed (either in success or failure).
this.onabort = null; // When the write has been aborted. For instance, by invoking the abort() method.
this.onerror = null; // When the write has failed (see errors).
};
// States
FileWriter.INIT = 0;
FileWriter.WRITING = 1;
FileWriter.DONE = 2;
/**
* Abort writing file.
*/
FileWriter.prototype.abort = function() {
// check for invalid state
if (this.readyState === FileWriter.DONE || this.readyState === FileWriter.INIT) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// set error
this.error = new FileError(FileError.ABORT_ERR);
this.readyState = FileWriter.DONE;
// If abort callback
if (typeof this.onabort === "function") {
this.onabort(new ProgressEvent("abort", {"target":this}));
}
// If write end callback
if (typeof this.onwriteend === "function") {
this.onwriteend(new ProgressEvent("writeend", {"target":this}));
}
};
/**
* Writes data to the file
*
* @param data text or blob to be written
*/
FileWriter.prototype.write = function(data) {
var that=this;
var supportsBinary = (typeof window.Blob !== 'undefined' && typeof window.ArrayBuffer !== 'undefined');
var isProxySupportBlobNatively = (cordova.platformId === "windows8" || cordova.platformId === "windows");
var isBinary;
// Check to see if the incoming data is a blob
if (data instanceof File || (!isProxySupportBlobNatively && supportsBinary && data instanceof Blob)) {
var fileReader = new FileReader();
fileReader.onload = function() {
// Call this method again, with the arraybuffer as argument
FileWriter.prototype.write.call(that, this.result);
};
if (supportsBinary) {
fileReader.readAsArrayBuffer(data);
} else {
fileReader.readAsText(data);
}
return;
}
// Mark data type for safer transport over the binary bridge
isBinary = supportsBinary && (data instanceof ArrayBuffer);
if (isBinary && cordova.platformId === "windowsphone") {
// create a plain array, using the keys from the Uint8Array view so that we can serialize it
data = Array.apply(null, new Uint8Array(data));
}
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// WRITING state
this.readyState = FileWriter.WRITING;
var me = this;
// If onwritestart callback
if (typeof me.onwritestart === "function") {
me.onwritestart(new ProgressEvent("writestart", {"target":me}));
}
// Write file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// position always increases by bytes written because file would be extended
me.position += r;
// The length of the file is now where we are done writing.
me.length = me.position;
// DONE state
me.readyState = FileWriter.DONE;
// If onwrite callback
if (typeof me.onwrite === "function") {
me.onwrite(new ProgressEvent("write", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Save error
me.error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
}, "File", "write", [this.localURL, data, this.position, isBinary]);
};
/**
* Moves the file pointer to the location specified.
*
* If the offset is a negative number the position of the file
* pointer is rewound. If the offset is greater than the file
* size the position is set to the end of the file.
*
* @param offset is the location to move the file pointer to.
*/
FileWriter.prototype.seek = function(offset) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
if (!offset && offset !== 0) {
return;
}
// See back from end of file.
if (offset < 0) {
this.position = Math.max(offset + this.length, 0);
}
// Offset is bigger than file size so set position
// to the end of the file.
else if (offset > this.length) {
this.position = this.length;
}
// Offset is between 0 and file size so set the position
// to start writing.
else {
this.position = offset;
}
};
/**
* Truncates the file to the size specified.
*
* @param size to chop the file at.
*/
FileWriter.prototype.truncate = function(size) {
// Throw an exception if we are already writing a file
if (this.readyState === FileWriter.WRITING) {
throw new FileError(FileError.INVALID_STATE_ERR);
}
// WRITING state
this.readyState = FileWriter.WRITING;
var me = this;
// If onwritestart callback
if (typeof me.onwritestart === "function") {
me.onwritestart(new ProgressEvent("writestart", {"target":this}));
}
// Write file
exec(
// Success callback
function(r) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Update the length of the file
me.length = r;
me.position = Math.min(me.position, r);
// If onwrite callback
if (typeof me.onwrite === "function") {
me.onwrite(new ProgressEvent("write", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
},
// Error callback
function(e) {
// If DONE (cancelled), then don't do anything
if (me.readyState === FileWriter.DONE) {
return;
}
// DONE state
me.readyState = FileWriter.DONE;
// Save error
me.error = new FileError(e);
// If onerror callback
if (typeof me.onerror === "function") {
me.onerror(new ProgressEvent("error", {"target":me}));
}
// If onwriteend callback
if (typeof me.onwriteend === "function") {
me.onwriteend(new ProgressEvent("writeend", {"target":me}));
}
}, "File", "truncate", [this.localURL, size]);
};
module.exports = FileWriter;
});

View File

@@ -0,0 +1,38 @@
cordova.define("cordova-plugin-file.Flags", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Supplies arguments to methods that lookup or create files and directories.
*
* @param create
* {boolean} file or directory if it doesn't exist
* @param exclusive
* {boolean} used with create; if true the command will fail if
* target path exists
*/
function Flags(create, exclusive) {
this.create = create || false;
this.exclusive = exclusive || false;
}
module.exports = Flags;
});

View File

@@ -0,0 +1,25 @@
cordova.define("cordova-plugin-file.LocalFileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
exports.TEMPORARY = 0;
exports.PERSISTENT = 1;
});

View File

@@ -0,0 +1,42 @@
cordova.define("cordova-plugin-file.Metadata", function(require, exports, module) { /*
*
* 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.
*
*/
/**
* Information about the state of the file or directory
*
* {Date} modificationTime (readonly)
*/
var Metadata = function(metadata) {
if (typeof metadata == "object") {
this.modificationTime = new Date(metadata.modificationTime);
this.size = metadata.size || 0;
} else if (typeof metadata == "undefined") {
this.modificationTime = null;
this.size = 0;
} else {
/* Backwards compatiblity with platforms that only return a timestamp */
this.modificationTime = new Date(metadata);
}
};
module.exports = Metadata;
});

View File

@@ -0,0 +1,69 @@
cordova.define("cordova-plugin-file.ProgressEvent", function(require, exports, module) { /*
*
* 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.
*
*/
// If ProgressEvent exists in global context, use it already, otherwise use our own polyfill
// Feature test: See if we can instantiate a native ProgressEvent;
// if so, use that approach,
// otherwise fill-in with our own implementation.
//
// NOTE: right now we always fill in with our own. Down the road would be nice if we can use whatever is native in the webview.
var ProgressEvent = (function() {
/*
var createEvent = function(data) {
var event = document.createEvent('Events');
event.initEvent('ProgressEvent', false, false);
if (data) {
for (var i in data) {
if (data.hasOwnProperty(i)) {
event[i] = data[i];
}
}
if (data.target) {
// TODO: cannot call <some_custom_object>.dispatchEvent
// need to first figure out how to implement EventTarget
}
}
return event;
};
try {
var ev = createEvent({type:"abort",target:document});
return function ProgressEvent(type, data) {
data.type = type;
return createEvent(data);
};
} catch(e){
*/
return function ProgressEvent(type, dict) {
this.type = type;
this.bubbles = false;
this.cancelBubble = false;
this.cancelable = false;
this.lengthComputable = false;
this.loaded = dict && dict.loaded ? dict.loaded : 0;
this.total = dict && dict.total ? dict.total : 0;
this.target = dict && dict.target ? dict.target : null;
};
//}
})();
module.exports = ProgressEvent;
});

View File

@@ -0,0 +1,38 @@
cordova.define("cordova-plugin-file.androidFileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
FILESYSTEM_PROTOCOL = "cdvfile";
module.exports = {
__format__: function(fullPath, nativeUrl) {
var path = '/' + this.name + '/' + encodeURI(fullPath);
path = path.replace('//','/');
var ret = FILESYSTEM_PROTOCOL + '://localhost' + path;
var m = /\?.*/.exec(nativeUrl);
if (m) {
ret += m[0];
}
return ret;
}
};
});

View File

@@ -0,0 +1,65 @@
cordova.define("cordova-plugin-file.fileSystemPaths", function(require, exports, module) { /*
*
* 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.
*
*/
var exec = require('cordova/exec');
var channel = require('cordova/channel');
exports.file = {
// Read-only directory where the application is installed.
applicationDirectory: null,
// Root of app's private writable storage
applicationStorageDirectory: null,
// Where to put app-specific data files.
dataDirectory: null,
// Cached files that should survive app restarts.
// Apps should not rely on the OS to delete files in here.
cacheDirectory: null,
// Android: the application space on external storage.
externalApplicationStorageDirectory: null,
// Android: Where to put app-specific data files on external storage.
externalDataDirectory: null,
// Android: the application cache on external storage.
externalCacheDirectory: null,
// Android: the external storage (SD card) root.
externalRootDirectory: null,
// iOS: Temp directory that the OS can clear at will.
tempDirectory: null,
// iOS: Holds app-specific files that should be synced (e.g. to iCloud).
syncedDataDirectory: null,
// iOS: Files private to the app, but that are meaningful to other applciations (e.g. Office files)
documentsDirectory: null,
// BlackBerry10: Files globally available to all apps
sharedDirectory: null
};
channel.waitForInitialization('onFileSystemPathsReady');
channel.onCordovaReady.subscribe(function() {
function after(paths) {
for (var k in paths) {
exports.file[k] = paths[k];
}
channel.initializationComplete('onFileSystemPathsReady');
}
exec(after, null, 'File', 'requestAllPaths', []);
});
});

View File

@@ -0,0 +1,46 @@
cordova.define("cordova-plugin-file.fileSystems-roots", function(require, exports, module) { /*
*
* 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.
*
*/
// Map of fsName -> FileSystem.
var fsMap = null;
var FileSystem = require('./FileSystem');
var exec = require('cordova/exec');
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
require('./fileSystems').getFs = function(name, callback) {
if (fsMap) {
callback(fsMap[name]);
} else {
exec(success, null, "File", "requestAllFileSystems", []);
function success(response) {
fsMap = {};
for (var i = 0; i < response.length; ++i) {
var fsRoot = response[i];
var fs = new FileSystem(fsRoot.filesystemName, fsRoot);
fsMap[fs.name] = fs;
}
callback(fsMap[name]);
}
}
};
});

View File

@@ -0,0 +1,27 @@
cordova.define("cordova-plugin-file.fileSystems", function(require, exports, module) { /*
*
* 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.
*
*/
// Overridden by Android, BlackBerry 10 and iOS to populate fsMap.
module.exports.getFs = function(name, callback) {
callback(null);
};
});

View File

@@ -0,0 +1,78 @@
cordova.define("cordova-plugin-file.requestFileSystem", function(require, exports, module) { /*
*
* 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.
*
*/
//For browser platform: not all browsers use this file.
function checkBrowser() {
if (cordova.platformId === "browser" && navigator.userAgent.search(/Chrome/) > 0) {
var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
module.exports = requestFileSystem;
return;
}
}
checkBrowser();
var argscheck = require('cordova/argscheck'),
FileError = require('./FileError'),
FileSystem = require('./FileSystem'),
exec = require('cordova/exec');
var fileSystems = require('./fileSystems');
/**
* Request a file system in which to store application data.
* @param type local file system type
* @param size indicates how much storage space, in bytes, the application expects to need
* @param successCallback invoked with a FileSystem object
* @param errorCallback invoked if error occurs retrieving file system
*/
var requestFileSystem = function(type, size, successCallback, errorCallback) {
argscheck.checkArgs('nnFF', 'requestFileSystem', arguments);
var fail = function(code) {
errorCallback && errorCallback(new FileError(code));
};
if (type < 0) {
fail(FileError.SYNTAX_ERR);
} else {
// if successful, return a FileSystem object
var success = function(file_system) {
if (file_system) {
if (successCallback) {
fileSystems.getFs(file_system.name, function(fs) {
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
if (!fs) {
fs = new FileSystem(file_system.name, file_system.root);
}
successCallback(fs);
});
}
}
else {
// no FileSystem object returned
fail(FileError.NOT_FOUND_ERR);
}
};
exec(success, fail, "File", "requestFileSystem", [type, size]);
}
};
module.exports = requestFileSystem;
});

View File

@@ -0,0 +1,89 @@
cordova.define("cordova-plugin-file.resolveLocalFileSystemURI", function(require, exports, module) { /*
*
* 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.
*
*/
//For browser platform: not all browsers use overrided `resolveLocalFileSystemURL`.
function checkBrowser() {
if (cordova.platformId === "browser" && navigator.userAgent.search(/Chrome/) > 0) {
var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
module.exports = requestFileSystem;
return;
}
}
checkBrowser();
var argscheck = require('cordova/argscheck'),
DirectoryEntry = require('./DirectoryEntry'),
FileEntry = require('./FileEntry'),
FileError = require('./FileError'),
exec = require('cordova/exec');
var fileSystems = require('./fileSystems');
/**
* Look up file system Entry referred to by local URI.
* @param {DOMString} uri URI referring to a local file or directory
* @param successCallback invoked with Entry object corresponding to URI
* @param errorCallback invoked if error occurs retrieving file system entry
*/
module.exports.resolveLocalFileSystemURL = function(uri, successCallback, errorCallback) {
argscheck.checkArgs('sFF', 'resolveLocalFileSystemURI', arguments);
// error callback
var fail = function(error) {
errorCallback && errorCallback(new FileError(error));
};
// sanity check for 'not:valid:filename' or '/not:valid:filename'
// file.spec.12 window.resolveLocalFileSystemURI should error (ENCODING_ERR) when resolving invalid URI with leading /.
if(!uri || uri.split(":").length > 2) {
setTimeout( function() {
fail(FileError.ENCODING_ERR);
},0);
return;
}
// if successful, return either a file or directory entry
var success = function(entry) {
if (entry) {
if (successCallback) {
// create appropriate Entry object
var fsName = entry.filesystemName || (entry.filesystem && entry.filesystem.name) || (entry.filesystem == window.PERSISTENT ? 'persistent' : 'temporary');
fileSystems.getFs(fsName, function(fs) {
// This should happen only on platforms that haven't implemented requestAllFileSystems (windows)
if (!fs) {
fs = new FileSystem(fsName, {name:"", fullPath:"/"});
}
var result = (entry.isDirectory) ? new DirectoryEntry(entry.name, entry.fullPath, fs, entry.nativeURL) : new FileEntry(entry.name, entry.fullPath, fs, entry.nativeURL);
successCallback(result);
});
}
}
else {
// no Entry object returned
fail(FileError.NOT_FOUND_ERR);
}
};
exec(success, fail, "File", "resolveLocalFileSystemURI", [uri]);
};
module.exports.resolveLocalFileSystemURI = function() {
console.log("resolveLocalFileSystemURI is deprecated. Please call resolveLocalFileSystemURL instead.");
module.exports.resolveLocalFileSystemURL.apply(this, arguments);
};
});

View File

@@ -26,6 +26,14 @@
<feature name="InAppBrowser">
<param name="android-package" value="org.apache.cordova.inappbrowser.InAppBrowser" />
</feature>
<preference name="AndroidPersistentFileLocation" value="Internal" />
<feature name="File">
<param name="android-package" value="org.apache.cordova.file.FileUtils" />
<param name="onload" value="true" />
</feature>
<feature name="FileTransfer">
<param name="android-package" value="org.apache.cordova.filetransfer.FileTransfer" />
</feature>
<icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
<icon density="mdpi" src="resources/android/icon/drawable-mdpi-icon.png" />
<icon density="hdpi" src="resources/android/icon/drawable-hdpi-icon.png" />

View File

@@ -0,0 +1,283 @@
/*
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.
*/
package org.apache.cordova.file;
import android.content.res.AssetManager;
import android.net.Uri;
import android.util.Log;
import org.apache.cordova.CordovaResourceApi;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.HashMap;
import java.util.Map;
public class AssetFilesystem extends Filesystem {
private final AssetManager assetManager;
// A custom gradle hook creates the cdvasset.manifest file, which speeds up asset listing a tonne.
// See: http://stackoverflow.com/questions/16911558/android-assetmanager-list-incredibly-slow
private static Object listCacheLock = new Object();
private static boolean listCacheFromFile;
private static Map<String, String[]> listCache;
private static Map<String, Long> lengthCache;
private void lazyInitCaches() {
synchronized (listCacheLock) {
if (listCache == null) {
ObjectInputStream ois = null;
try {
ois = new ObjectInputStream(assetManager.open("cdvasset.manifest"));
listCache = (Map<String, String[]>) ois.readObject();
lengthCache = (Map<String, Long>) ois.readObject();
listCacheFromFile = true;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
// Asset manifest won't exist if the gradle hook isn't set up correctly.
} finally {
if (ois != null) {
try {
ois.close();
} catch (IOException e) {
}
}
}
if (listCache == null) {
Log.w("AssetFilesystem", "Asset manifest not found. Recursive copies and directory listing will be slow.");
listCache = new HashMap<String, String[]>();
}
}
}
}
private String[] listAssets(String assetPath) throws IOException {
if (assetPath.startsWith("/")) {
assetPath = assetPath.substring(1);
}
lazyInitCaches();
String[] ret = listCache.get(assetPath);
if (ret == null) {
if (listCacheFromFile) {
ret = new String[0];
} else {
ret = assetManager.list(assetPath);
listCache.put(assetPath, ret);
}
}
return ret;
}
private long getAssetSize(String assetPath) throws FileNotFoundException {
if (assetPath.startsWith("/")) {
assetPath = assetPath.substring(1);
}
lazyInitCaches();
if (lengthCache != null) {
Long ret = lengthCache.get(assetPath);
if (ret == null) {
throw new FileNotFoundException("Asset not found: " + assetPath);
}
return ret;
}
CordovaResourceApi.OpenForReadResult offr = null;
try {
offr = resourceApi.openForRead(nativeUriForFullPath(assetPath));
long length = offr.length;
if (length < 0) {
// available() doesn't always yield the file size, but for assets it does.
length = offr.inputStream.available();
}
return length;
} catch (IOException e) {
throw new FileNotFoundException("File not found: " + assetPath);
} finally {
if (offr != null) {
try {
offr.inputStream.close();
} catch (IOException e) {
}
}
}
}
public AssetFilesystem(AssetManager assetManager, CordovaResourceApi resourceApi) {
super(Uri.parse("file:///android_asset/"), "assets", resourceApi);
this.assetManager = assetManager;
}
@Override
public Uri toNativeUri(LocalFilesystemURL inputURL) {
return nativeUriForFullPath(inputURL.path);
}
@Override
public LocalFilesystemURL toLocalUri(Uri inputURL) {
if (!"file".equals(inputURL.getScheme())) {
return null;
}
File f = new File(inputURL.getPath());
// Removes and duplicate /s (e.g. file:///a//b/c)
Uri resolvedUri = Uri.fromFile(f);
String rootUriNoTrailingSlash = rootUri.getEncodedPath();
rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
return null;
}
String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
// Strip leading slash
if (!subPath.isEmpty()) {
subPath = subPath.substring(1);
}
Uri.Builder b = new Uri.Builder()
.scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
.authority("localhost")
.path(name);
if (!subPath.isEmpty()) {
b.appendEncodedPath(subPath);
}
if (isDirectory(subPath) || inputURL.getPath().endsWith("/")) {
// Add trailing / for directories.
b.appendEncodedPath("");
}
return LocalFilesystemURL.parse(b.build());
}
private boolean isDirectory(String assetPath) {
try {
return listAssets(assetPath).length != 0;
} catch (IOException e) {
return false;
}
}
@Override
public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
String pathNoSlashes = inputURL.path.substring(1);
if (pathNoSlashes.endsWith("/")) {
pathNoSlashes = pathNoSlashes.substring(0, pathNoSlashes.length() - 1);
}
String[] files;
try {
files = listAssets(pathNoSlashes);
} catch (IOException e) {
throw new FileNotFoundException();
}
LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
for (int i = 0; i < files.length; ++i) {
entries[i] = localUrlforFullPath(new File(inputURL.path, files[i]).getPath());
}
return entries;
}
@Override
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
String path, JSONObject options, boolean directory)
throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
if (options != null && options.optBoolean("create")) {
throw new UnsupportedOperationException("Assets are read-only");
}
// Check whether the supplied path is absolute or relative
if (directory && !path.endsWith("/")) {
path += "/";
}
LocalFilesystemURL requestedURL;
if (path.startsWith("/")) {
requestedURL = localUrlforFullPath(normalizePath(path));
} else {
requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
}
// Throws a FileNotFoundException if it doesn't exist.
getFileMetadataForLocalURL(requestedURL);
boolean isDir = isDirectory(requestedURL.path);
if (directory && !isDir) {
throw new TypeMismatchException("path doesn't exist or is file");
} else if (!directory && isDir) {
throw new TypeMismatchException("path doesn't exist or is directory");
}
// Return the directory
return makeEntryForURL(requestedURL);
}
@Override
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
JSONObject metadata = new JSONObject();
long size = inputURL.isDirectory ? 0 : getAssetSize(inputURL.path);
try {
metadata.put("size", size);
metadata.put("type", inputURL.isDirectory ? "text/directory" : resourceApi.getMimeType(toNativeUri(inputURL)));
metadata.put("name", new File(inputURL.path).getName());
metadata.put("fullPath", inputURL.path);
metadata.put("lastModifiedDate", 0);
} catch (JSONException e) {
return null;
}
return metadata;
}
@Override
public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
return false;
}
@Override
long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset, boolean isBinary) throws NoModificationAllowedException, IOException {
throw new NoModificationAllowedException("Assets are read-only");
}
@Override
long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException, NoModificationAllowedException {
throw new NoModificationAllowedException("Assets are read-only");
}
@Override
String filesystemPathForURL(LocalFilesystemURL url) {
return null;
}
@Override
LocalFilesystemURL URLforFilesystemPath(String path) {
return null;
}
@Override
boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException {
throw new NoModificationAllowedException("Assets are read-only");
}
@Override
boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws NoModificationAllowedException {
throw new NoModificationAllowedException("Assets are read-only");
}
}

View File

@@ -0,0 +1,215 @@
/*
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.
*/
package org.apache.cordova.file;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import org.apache.cordova.CordovaResourceApi;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.provider.MediaStore;
import android.provider.OpenableColumns;
public class ContentFilesystem extends Filesystem {
private final Context context;
public ContentFilesystem(Context context, CordovaResourceApi resourceApi) {
super(Uri.parse("content://"), "content", resourceApi);
this.context = context;
}
@Override
public Uri toNativeUri(LocalFilesystemURL inputURL) {
String authorityAndPath = inputURL.uri.getEncodedPath().substring(this.name.length() + 2);
if (authorityAndPath.length() < 2) {
return null;
}
String ret = "content://" + authorityAndPath;
String query = inputURL.uri.getEncodedQuery();
if (query != null) {
ret += '?' + query;
}
String frag = inputURL.uri.getEncodedFragment();
if (frag != null) {
ret += '#' + frag;
}
return Uri.parse(ret);
}
@Override
public LocalFilesystemURL toLocalUri(Uri inputURL) {
if (!"content".equals(inputURL.getScheme())) {
return null;
}
String subPath = inputURL.getEncodedPath();
if (subPath.length() > 0) {
subPath = subPath.substring(1);
}
Uri.Builder b = new Uri.Builder()
.scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
.authority("localhost")
.path(name)
.appendPath(inputURL.getAuthority());
if (subPath.length() > 0) {
b.appendEncodedPath(subPath);
}
Uri localUri = b.encodedQuery(inputURL.getEncodedQuery())
.encodedFragment(inputURL.getEncodedFragment())
.build();
return LocalFilesystemURL.parse(localUri);
}
@Override
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
String fileName, JSONObject options, boolean directory) throws IOException, TypeMismatchException, JSONException {
throw new UnsupportedOperationException("getFile() not supported for content:. Use resolveLocalFileSystemURL instead.");
}
@Override
public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL)
throws NoModificationAllowedException {
Uri contentUri = toNativeUri(inputURL);
try {
context.getContentResolver().delete(contentUri, null, null);
} catch (UnsupportedOperationException t) {
// Was seeing this on the File mobile-spec tests on 4.0.3 x86 emulator.
// The ContentResolver applies only when the file was registered in the
// first case, which is generally only the case with images.
throw new NoModificationAllowedException("Deleting not supported for content uri: " + contentUri);
}
return true;
}
@Override
public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL)
throws NoModificationAllowedException {
throw new NoModificationAllowedException("Cannot remove content url");
}
@Override
public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
throw new UnsupportedOperationException("readEntriesAtLocalURL() not supported for content:. Use resolveLocalFileSystemURL instead.");
}
@Override
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
long size = -1;
long lastModified = 0;
Uri nativeUri = toNativeUri(inputURL);
String mimeType = resourceApi.getMimeType(nativeUri);
Cursor cursor = openCursorForURL(nativeUri);
try {
if (cursor != null && cursor.moveToFirst()) {
size = resourceSizeForCursor(cursor);
lastModified = lastModifiedDateForCursor(cursor);
} else {
// Some content providers don't support cursors at all!
CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(nativeUri);
size = offr.length;
}
} catch (IOException e) {
throw new FileNotFoundException();
} finally {
if (cursor != null)
cursor.close();
}
JSONObject metadata = new JSONObject();
try {
metadata.put("size", size);
metadata.put("type", mimeType);
metadata.put("name", name);
metadata.put("fullPath", inputURL.path);
metadata.put("lastModifiedDate", lastModified);
} catch (JSONException e) {
return null;
}
return metadata;
}
@Override
public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
int offset, boolean isBinary) throws NoModificationAllowedException {
throw new NoModificationAllowedException("Couldn't write to file given its content URI");
}
@Override
public long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
throws NoModificationAllowedException {
throw new NoModificationAllowedException("Couldn't truncate file given its content URI");
}
protected Cursor openCursorForURL(Uri nativeUri) {
ContentResolver contentResolver = context.getContentResolver();
try {
return contentResolver.query(nativeUri, null, null, null, null);
} catch (UnsupportedOperationException e) {
return null;
}
}
private Long resourceSizeForCursor(Cursor cursor) {
int columnIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
if (columnIndex != -1) {
String sizeStr = cursor.getString(columnIndex);
if (sizeStr != null) {
return Long.parseLong(sizeStr);
}
}
return null;
}
protected Long lastModifiedDateForCursor(Cursor cursor) {
final String[] LOCAL_FILE_PROJECTION = { MediaStore.MediaColumns.DATE_MODIFIED };
int columnIndex = cursor.getColumnIndex(LOCAL_FILE_PROJECTION[0]);
if (columnIndex != -1) {
String dateStr = cursor.getString(columnIndex);
if (dateStr != null) {
return Long.parseLong(dateStr);
}
}
return null;
}
@Override
public String filesystemPathForURL(LocalFilesystemURL url) {
File f = resourceApi.mapUriToFile(toNativeUri(url));
return f == null ? null : f.getAbsolutePath();
}
@Override
public LocalFilesystemURL URLforFilesystemPath(String path) {
// Returns null as we don't support reverse mapping back to content:// URLs
return null;
}
@Override
public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
return true;
}
}

View File

@@ -0,0 +1,133 @@
/*
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.
*/
package org.apache.cordova.file;
import android.os.Environment;
import android.os.StatFs;
import java.io.File;
/**
* This class provides file directory utilities.
* All file operations are performed on the SD card.
*
* It is used by the FileUtils class.
*/
public class DirectoryManager {
@SuppressWarnings("unused")
private static final String LOG_TAG = "DirectoryManager";
/**
* Determine if a file or directory exists.
* @param name The name of the file to check.
* @return T=exists, F=not found
*/
public static boolean testFileExists(String name) {
boolean status;
// If SD card exists
if ((testSaveLocationExists()) && (!name.equals(""))) {
File path = Environment.getExternalStorageDirectory();
File newPath = constructFilePaths(path.toString(), name);
status = newPath.exists();
}
// If no SD card
else {
status = false;
}
return status;
}
/**
* Get the free disk space
*
* @return Size in KB or -1 if not available
*/
public static long getFreeDiskSpace(boolean checkInternal) {
String status = Environment.getExternalStorageState();
long freeSpace = 0;
// If SD card exists
if (status.equals(Environment.MEDIA_MOUNTED)) {
freeSpace = freeSpaceCalculation(Environment.getExternalStorageDirectory().getPath());
}
else if (checkInternal) {
freeSpace = freeSpaceCalculation("/");
}
// If no SD card and we haven't been asked to check the internal directory then return -1
else {
return -1;
}
return freeSpace;
}
/**
* Given a path return the number of free KB
*
* @param path to the file system
* @return free space in KB
*/
private static long freeSpaceCalculation(String path) {
StatFs stat = new StatFs(path);
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return availableBlocks * blockSize / 1024;
}
/**
* Determine if SD card exists.
*
* @return T=exists, F=not found
*/
public static boolean testSaveLocationExists() {
String sDCardStatus = Environment.getExternalStorageState();
boolean status;
// If SD card is mounted
if (sDCardStatus.equals(Environment.MEDIA_MOUNTED)) {
status = true;
}
// If no SD card
else {
status = false;
}
return status;
}
/**
* Create a new file object from two file paths.
*
* @param file1 Base file path
* @param file2 Remaining file path
* @return File object
*/
private static File constructFilePaths (String file1, String file2) {
File newPath;
if (file2.startsWith(file1)) {
newPath = new File(file2);
}
else {
newPath = new File(file1 + "/" + file2);
}
return newPath;
}
}

View File

@@ -0,0 +1,29 @@
/*
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.
*/
package org.apache.cordova.file;
@SuppressWarnings("serial")
public class EncodingException extends Exception {
public EncodingException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,29 @@
/*
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.
*/
package org.apache.cordova.file;
@SuppressWarnings("serial")
public class FileExistsException extends Exception {
public FileExistsException(String msg) {
super(msg);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,325 @@
/*
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.
*/
package org.apache.cordova.file;
import android.net.Uri;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.cordova.CordovaResourceApi;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
public abstract class Filesystem {
protected final Uri rootUri;
protected final CordovaResourceApi resourceApi;
public final String name;
private JSONObject rootEntry;
public Filesystem(Uri rootUri, String name, CordovaResourceApi resourceApi) {
this.rootUri = rootUri;
this.name = name;
this.resourceApi = resourceApi;
}
public interface ReadFileCallback {
public void handleData(InputStream inputStream, String contentType) throws IOException;
}
public static JSONObject makeEntryForURL(LocalFilesystemURL inputURL, Uri nativeURL) {
try {
String path = inputURL.path;
int end = path.endsWith("/") ? 1 : 0;
String[] parts = path.substring(0, path.length() - end).split("/+");
String fileName = parts[parts.length - 1];
JSONObject entry = new JSONObject();
entry.put("isFile", !inputURL.isDirectory);
entry.put("isDirectory", inputURL.isDirectory);
entry.put("name", fileName);
entry.put("fullPath", path);
// The file system can't be specified, as it would lead to an infinite loop,
// but the filesystem name can be.
entry.put("filesystemName", inputURL.fsName);
// Backwards compatibility
entry.put("filesystem", "temporary".equals(inputURL.fsName) ? 0 : 1);
String nativeUrlStr = nativeURL.toString();
if (inputURL.isDirectory && !nativeUrlStr.endsWith("/")) {
nativeUrlStr += "/";
}
entry.put("nativeURL", nativeUrlStr);
return entry;
} catch (JSONException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public JSONObject makeEntryForURL(LocalFilesystemURL inputURL) {
Uri nativeUri = toNativeUri(inputURL);
return nativeUri == null ? null : makeEntryForURL(inputURL, nativeUri);
}
public JSONObject makeEntryForNativeUri(Uri nativeUri) {
LocalFilesystemURL inputUrl = toLocalUri(nativeUri);
return inputUrl == null ? null : makeEntryForURL(inputUrl, nativeUri);
}
public JSONObject getEntryForLocalURL(LocalFilesystemURL inputURL) throws IOException {
return makeEntryForURL(inputURL);
}
public JSONObject makeEntryForFile(File file) {
return makeEntryForNativeUri(Uri.fromFile(file));
}
abstract JSONObject getFileForLocalURL(LocalFilesystemURL inputURL, String path,
JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException;
abstract boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException, NoModificationAllowedException;
abstract boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException, NoModificationAllowedException;
abstract LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException;
public final JSONArray readEntriesAtLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
LocalFilesystemURL[] children = listChildren(inputURL);
JSONArray entries = new JSONArray();
if (children != null) {
for (LocalFilesystemURL url : children) {
entries.put(makeEntryForURL(url));
}
}
return entries;
}
abstract JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException;
public Uri getRootUri() {
return rootUri;
}
public boolean exists(LocalFilesystemURL inputURL) {
try {
getFileMetadataForLocalURL(inputURL);
} catch (FileNotFoundException e) {
return false;
}
return true;
}
public Uri nativeUriForFullPath(String fullPath) {
Uri ret = null;
if (fullPath != null) {
String encodedPath = Uri.fromFile(new File(fullPath)).getEncodedPath();
if (encodedPath.startsWith("/")) {
encodedPath = encodedPath.substring(1);
}
ret = rootUri.buildUpon().appendEncodedPath(encodedPath).build();
}
return ret;
}
public LocalFilesystemURL localUrlforFullPath(String fullPath) {
Uri nativeUri = nativeUriForFullPath(fullPath);
if (nativeUri != null) {
return toLocalUri(nativeUri);
}
return null;
}
/**
* Removes multiple repeated //s, and collapses processes ../s.
*/
protected static String normalizePath(String rawPath) {
// If this is an absolute path, trim the leading "/" and replace it later
boolean isAbsolutePath = rawPath.startsWith("/");
if (isAbsolutePath) {
rawPath = rawPath.replaceFirst("/+", "");
}
ArrayList<String> components = new ArrayList<String>(Arrays.asList(rawPath.split("/+")));
for (int index = 0; index < components.size(); ++index) {
if (components.get(index).equals("..")) {
components.remove(index);
if (index > 0) {
components.remove(index-1);
--index;
}
}
}
StringBuilder normalizedPath = new StringBuilder();
for(String component: components) {
normalizedPath.append("/");
normalizedPath.append(component);
}
if (isAbsolutePath) {
return normalizedPath.toString();
} else {
return normalizedPath.toString().substring(1);
}
}
public abstract Uri toNativeUri(LocalFilesystemURL inputURL);
public abstract LocalFilesystemURL toLocalUri(Uri inputURL);
public JSONObject getRootEntry() {
if (rootEntry == null) {
rootEntry = makeEntryForNativeUri(rootUri);
}
return rootEntry;
}
public JSONObject getParentForLocalURL(LocalFilesystemURL inputURL) throws IOException {
Uri parentUri = inputURL.uri;
String parentPath = new File(inputURL.uri.getPath()).getParent();
if (!"/".equals(parentPath)) {
parentUri = inputURL.uri.buildUpon().path(parentPath + '/').build();
}
return getEntryForLocalURL(LocalFilesystemURL.parse(parentUri));
}
protected LocalFilesystemURL makeDestinationURL(String newName, LocalFilesystemURL srcURL, LocalFilesystemURL destURL, boolean isDirectory) {
// I know this looks weird but it is to work around a JSON bug.
if ("null".equals(newName) || "".equals(newName)) {
newName = srcURL.uri.getLastPathSegment();;
}
String newDest = destURL.uri.toString();
if (newDest.endsWith("/")) {
newDest = newDest + newName;
} else {
newDest = newDest + "/" + newName;
}
if (isDirectory) {
newDest += '/';
}
return LocalFilesystemURL.parse(newDest);
}
/* Read a source URL (possibly from a different filesystem, srcFs,) and copy it to
* the destination URL on this filesystem, optionally with a new filename.
* If move is true, then this method should either perform an atomic move operation
* or remove the source file when finished.
*/
public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
// First, check to see that we can do it
if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
throw new NoModificationAllowedException("Cannot move file at source URL");
}
final LocalFilesystemURL destination = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
Uri srcNativeUri = srcFs.toNativeUri(srcURL);
CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(srcNativeUri);
OutputStream os = null;
try {
os = getOutputStreamForURL(destination);
} catch (IOException e) {
ofrr.inputStream.close();
throw e;
}
// Closes streams.
resourceApi.copyResource(ofrr, os);
if (move) {
srcFs.removeFileAtLocalURL(srcURL);
}
return getEntryForLocalURL(destination);
}
public OutputStream getOutputStreamForURL(LocalFilesystemURL inputURL) throws IOException {
return resourceApi.openOutputStream(toNativeUri(inputURL));
}
public void readFileAtURL(LocalFilesystemURL inputURL, long start, long end,
ReadFileCallback readFileCallback) throws IOException {
CordovaResourceApi.OpenForReadResult ofrr = resourceApi.openForRead(toNativeUri(inputURL));
if (end < 0) {
end = ofrr.length;
}
long numBytesToRead = end - start;
try {
if (start > 0) {
ofrr.inputStream.skip(start);
}
InputStream inputStream = ofrr.inputStream;
if (end < ofrr.length) {
inputStream = new LimitedInputStream(inputStream, numBytesToRead);
}
readFileCallback.handleData(inputStream, ofrr.mimeType);
} finally {
ofrr.inputStream.close();
}
}
abstract long writeToFileAtURL(LocalFilesystemURL inputURL, String data, int offset,
boolean isBinary) throws NoModificationAllowedException, IOException;
abstract long truncateFileAtURL(LocalFilesystemURL inputURL, long size)
throws IOException, NoModificationAllowedException;
// This method should return null if filesystem urls cannot be mapped to paths
abstract String filesystemPathForURL(LocalFilesystemURL url);
abstract LocalFilesystemURL URLforFilesystemPath(String path);
abstract boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL);
protected class LimitedInputStream extends FilterInputStream {
long numBytesToRead;
public LimitedInputStream(InputStream in, long numBytesToRead) {
super(in);
this.numBytesToRead = numBytesToRead;
}
@Override
public int read() throws IOException {
if (numBytesToRead <= 0) {
return -1;
}
numBytesToRead--;
return in.read();
}
@Override
public int read(byte[] buffer, int byteOffset, int byteCount) throws IOException {
if (numBytesToRead <= 0) {
return -1;
}
int bytesToRead = byteCount;
if (byteCount > numBytesToRead) {
bytesToRead = (int)numBytesToRead; // Cast okay; long is less than int here.
}
int numBytesRead = in.read(buffer, byteOffset, bytesToRead);
numBytesToRead -= numBytesRead;
return numBytesRead;
}
}
}

View File

@@ -0,0 +1,30 @@
/*
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.
*/
package org.apache.cordova.file;
@SuppressWarnings("serial")
public class InvalidModificationException extends Exception {
public InvalidModificationException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,505 @@
/*
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.
*/
package org.apache.cordova.file;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import org.apache.cordova.CordovaResourceApi;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.Build;
import android.os.Environment;
import android.util.Base64;
import android.net.Uri;
import android.content.Context;
import android.content.Intent;
public class LocalFilesystem extends Filesystem {
private final Context context;
public LocalFilesystem(String name, Context context, CordovaResourceApi resourceApi, File fsRoot) {
super(Uri.fromFile(fsRoot).buildUpon().appendEncodedPath("").build(), name, resourceApi);
this.context = context;
}
public String filesystemPathForFullPath(String fullPath) {
return new File(rootUri.getPath(), fullPath).toString();
}
@Override
public String filesystemPathForURL(LocalFilesystemURL url) {
return filesystemPathForFullPath(url.path);
}
private String fullPathForFilesystemPath(String absolutePath) {
if (absolutePath != null && absolutePath.startsWith(rootUri.getPath())) {
return absolutePath.substring(rootUri.getPath().length() - 1);
}
return null;
}
@Override
public Uri toNativeUri(LocalFilesystemURL inputURL) {
return nativeUriForFullPath(inputURL.path);
}
@Override
public LocalFilesystemURL toLocalUri(Uri inputURL) {
if (!"file".equals(inputURL.getScheme())) {
return null;
}
File f = new File(inputURL.getPath());
// Removes and duplicate /s (e.g. file:///a//b/c)
Uri resolvedUri = Uri.fromFile(f);
String rootUriNoTrailingSlash = rootUri.getEncodedPath();
rootUriNoTrailingSlash = rootUriNoTrailingSlash.substring(0, rootUriNoTrailingSlash.length() - 1);
if (!resolvedUri.getEncodedPath().startsWith(rootUriNoTrailingSlash)) {
return null;
}
String subPath = resolvedUri.getEncodedPath().substring(rootUriNoTrailingSlash.length());
// Strip leading slash
if (!subPath.isEmpty()) {
subPath = subPath.substring(1);
}
Uri.Builder b = new Uri.Builder()
.scheme(LocalFilesystemURL.FILESYSTEM_PROTOCOL)
.authority("localhost")
.path(name);
if (!subPath.isEmpty()) {
b.appendEncodedPath(subPath);
}
if (f.isDirectory() || inputURL.getPath().endsWith("/")) {
// Add trailing / for directories.
b.appendEncodedPath("");
}
return LocalFilesystemURL.parse(b.build());
}
@Override
public LocalFilesystemURL URLforFilesystemPath(String path) {
return localUrlforFullPath(fullPathForFilesystemPath(path));
}
@Override
public JSONObject getFileForLocalURL(LocalFilesystemURL inputURL,
String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
boolean create = false;
boolean exclusive = false;
if (options != null) {
create = options.optBoolean("create");
if (create) {
exclusive = options.optBoolean("exclusive");
}
}
// Check for a ":" character in the file to line up with BB and iOS
if (path.contains(":")) {
throw new EncodingException("This path has an invalid \":\" in it.");
}
LocalFilesystemURL requestedURL;
// Check whether the supplied path is absolute or relative
if (directory && !path.endsWith("/")) {
path += "/";
}
if (path.startsWith("/")) {
requestedURL = localUrlforFullPath(normalizePath(path));
} else {
requestedURL = localUrlforFullPath(normalizePath(inputURL.path + "/" + path));
}
File fp = new File(this.filesystemPathForURL(requestedURL));
if (create) {
if (exclusive && fp.exists()) {
throw new FileExistsException("create/exclusive fails");
}
if (directory) {
fp.mkdir();
} else {
fp.createNewFile();
}
if (!fp.exists()) {
throw new FileExistsException("create fails");
}
}
else {
if (!fp.exists()) {
throw new FileNotFoundException("path does not exist");
}
if (directory) {
if (fp.isFile()) {
throw new TypeMismatchException("path doesn't exist or is file");
}
} else {
if (fp.isDirectory()) {
throw new TypeMismatchException("path doesn't exist or is directory");
}
}
}
// Return the directory
return makeEntryForURL(requestedURL);
}
@Override
public boolean removeFileAtLocalURL(LocalFilesystemURL inputURL) throws InvalidModificationException {
File fp = new File(filesystemPathForURL(inputURL));
// You can't delete a directory that is not empty
if (fp.isDirectory() && fp.list().length > 0) {
throw new InvalidModificationException("You can't delete a directory that is not empty.");
}
return fp.delete();
}
@Override
public boolean exists(LocalFilesystemURL inputURL) {
File fp = new File(filesystemPathForURL(inputURL));
return fp.exists();
}
@Override
public boolean recursiveRemoveFileAtLocalURL(LocalFilesystemURL inputURL) throws FileExistsException {
File directory = new File(filesystemPathForURL(inputURL));
return removeDirRecursively(directory);
}
protected boolean removeDirRecursively(File directory) throws FileExistsException {
if (directory.isDirectory()) {
for (File file : directory.listFiles()) {
removeDirRecursively(file);
}
}
if (!directory.delete()) {
throw new FileExistsException("could not delete: " + directory.getName());
} else {
return true;
}
}
@Override
public LocalFilesystemURL[] listChildren(LocalFilesystemURL inputURL) throws FileNotFoundException {
File fp = new File(filesystemPathForURL(inputURL));
if (!fp.exists()) {
// The directory we are listing doesn't exist so we should fail.
throw new FileNotFoundException();
}
File[] files = fp.listFiles();
if (files == null) {
// inputURL is a directory
return null;
}
LocalFilesystemURL[] entries = new LocalFilesystemURL[files.length];
for (int i = 0; i < files.length; i++) {
entries[i] = URLforFilesystemPath(files[i].getPath());
}
return entries;
}
@Override
public JSONObject getFileMetadataForLocalURL(LocalFilesystemURL inputURL) throws FileNotFoundException {
File file = new File(filesystemPathForURL(inputURL));
if (!file.exists()) {
throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
}
JSONObject metadata = new JSONObject();
try {
// Ensure that directories report a size of 0
metadata.put("size", file.isDirectory() ? 0 : file.length());
metadata.put("type", resourceApi.getMimeType(Uri.fromFile(file)));
metadata.put("name", file.getName());
metadata.put("fullPath", inputURL.path);
metadata.put("lastModifiedDate", file.lastModified());
} catch (JSONException e) {
return null;
}
return metadata;
}
private void copyFile(Filesystem srcFs, LocalFilesystemURL srcURL, File destFile, boolean move) throws IOException, InvalidModificationException, NoModificationAllowedException {
if (move) {
String realSrcPath = srcFs.filesystemPathForURL(srcURL);
if (realSrcPath != null) {
File srcFile = new File(realSrcPath);
if (srcFile.renameTo(destFile)) {
return;
}
// Trying to rename the file failed. Possibly because we moved across file system on the device.
}
}
CordovaResourceApi.OpenForReadResult offr = resourceApi.openForRead(srcFs.toNativeUri(srcURL));
copyResource(offr, new FileOutputStream(destFile));
if (move) {
srcFs.removeFileAtLocalURL(srcURL);
}
}
private void copyDirectory(Filesystem srcFs, LocalFilesystemURL srcURL, File dstDir, boolean move) throws IOException, NoModificationAllowedException, InvalidModificationException, FileExistsException {
if (move) {
String realSrcPath = srcFs.filesystemPathForURL(srcURL);
if (realSrcPath != null) {
File srcDir = new File(realSrcPath);
// If the destination directory already exists and is empty then delete it. This is according to spec.
if (dstDir.exists()) {
if (dstDir.list().length > 0) {
throw new InvalidModificationException("directory is not empty");
}
dstDir.delete();
}
// Try to rename the directory
if (srcDir.renameTo(dstDir)) {
return;
}
// Trying to rename the file failed. Possibly because we moved across file system on the device.
}
}
if (dstDir.exists()) {
if (dstDir.list().length > 0) {
throw new InvalidModificationException("directory is not empty");
}
} else {
if (!dstDir.mkdir()) {
// If we can't create the directory then fail
throw new NoModificationAllowedException("Couldn't create the destination directory");
}
}
LocalFilesystemURL[] children = srcFs.listChildren(srcURL);
for (LocalFilesystemURL childLocalUrl : children) {
File target = new File(dstDir, new File(childLocalUrl.path).getName());
if (childLocalUrl.isDirectory) {
copyDirectory(srcFs, childLocalUrl, target, false);
} else {
copyFile(srcFs, childLocalUrl, target, false);
}
}
if (move) {
srcFs.recursiveRemoveFileAtLocalURL(srcURL);
}
}
@Override
public JSONObject copyFileToURL(LocalFilesystemURL destURL, String newName,
Filesystem srcFs, LocalFilesystemURL srcURL, boolean move) throws IOException, InvalidModificationException, JSONException, NoModificationAllowedException, FileExistsException {
// Check to see if the destination directory exists
String newParent = this.filesystemPathForURL(destURL);
File destinationDir = new File(newParent);
if (!destinationDir.exists()) {
// The destination does not exist so we should fail.
throw new FileNotFoundException("The source does not exist");
}
// Figure out where we should be copying to
final LocalFilesystemURL destinationURL = makeDestinationURL(newName, srcURL, destURL, srcURL.isDirectory);
Uri dstNativeUri = toNativeUri(destinationURL);
Uri srcNativeUri = srcFs.toNativeUri(srcURL);
// Check to see if source and destination are the same file
if (dstNativeUri.equals(srcNativeUri)) {
throw new InvalidModificationException("Can't copy onto itself");
}
if (move && !srcFs.canRemoveFileAtLocalURL(srcURL)) {
throw new InvalidModificationException("Source URL is read-only (cannot move)");
}
File destFile = new File(dstNativeUri.getPath());
if (destFile.exists()) {
if (!srcURL.isDirectory && destFile.isDirectory()) {
throw new InvalidModificationException("Can't copy/move a file to an existing directory");
} else if (srcURL.isDirectory && destFile.isFile()) {
throw new InvalidModificationException("Can't copy/move a directory to an existing file");
}
}
if (srcURL.isDirectory) {
// E.g. Copy /sdcard/myDir to /sdcard/myDir/backup
if (dstNativeUri.toString().startsWith(srcNativeUri.toString() + '/')) {
throw new InvalidModificationException("Can't copy directory into itself");
}
copyDirectory(srcFs, srcURL, destFile, move);
} else {
copyFile(srcFs, srcURL, destFile, move);
}
return makeEntryForURL(destinationURL);
}
@Override
public long writeToFileAtURL(LocalFilesystemURL inputURL, String data,
int offset, boolean isBinary) throws IOException, NoModificationAllowedException {
boolean append = false;
if (offset > 0) {
this.truncateFileAtURL(inputURL, offset);
append = true;
}
byte[] rawData;
if (isBinary) {
rawData = Base64.decode(data, Base64.DEFAULT);
} else {
rawData = data.getBytes();
}
ByteArrayInputStream in = new ByteArrayInputStream(rawData);
try
{
byte buff[] = new byte[rawData.length];
String absolutePath = filesystemPathForURL(inputURL);
FileOutputStream out = new FileOutputStream(absolutePath, append);
try {
in.read(buff, 0, buff.length);
out.write(buff, 0, rawData.length);
out.flush();
} finally {
// Always close the output
out.close();
}
if (isPublicDirectory(absolutePath)) {
broadcastNewFile(Uri.fromFile(new File(absolutePath)));
}
}
catch (NullPointerException e)
{
// This is a bug in the Android implementation of the Java Stack
NoModificationAllowedException realException = new NoModificationAllowedException(inputURL.toString());
throw realException;
}
return rawData.length;
}
private boolean isPublicDirectory(String absolutePath) {
// TODO: should expose a way to scan app's private files (maybe via a flag).
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// Lollipop has a bug where SD cards are null.
for (File f : context.getExternalMediaDirs()) {
if(f != null && absolutePath.startsWith(f.getAbsolutePath())) {
return true;
}
}
}
String extPath = Environment.getExternalStorageDirectory().getAbsolutePath();
return absolutePath.startsWith(extPath);
}
/**
* Send broadcast of new file so files appear over MTP
*/
private void broadcastNewFile(Uri nativeUri) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, nativeUri);
context.sendBroadcast(intent);
}
@Override
public long truncateFileAtURL(LocalFilesystemURL inputURL, long size) throws IOException {
File file = new File(filesystemPathForURL(inputURL));
if (!file.exists()) {
throw new FileNotFoundException("File at " + inputURL.uri + " does not exist.");
}
RandomAccessFile raf = new RandomAccessFile(filesystemPathForURL(inputURL), "rw");
try {
if (raf.length() >= size) {
FileChannel channel = raf.getChannel();
channel.truncate(size);
return size;
}
return raf.length();
} finally {
raf.close();
}
}
@Override
public boolean canRemoveFileAtLocalURL(LocalFilesystemURL inputURL) {
String path = filesystemPathForURL(inputURL);
File file = new File(path);
return file.exists();
}
// This is a copy & paste from CordovaResource API that is required since CordovaResourceApi
// has a bug pre-4.0.0.
// TODO: Once cordova-android@4.0.0 is released, delete this copy and make the plugin depend on
// 4.0.0 with an engine tag.
private static void copyResource(CordovaResourceApi.OpenForReadResult input, OutputStream outputStream) throws IOException {
try {
InputStream inputStream = input.inputStream;
if (inputStream instanceof FileInputStream && outputStream instanceof FileOutputStream) {
FileChannel inChannel = ((FileInputStream)input.inputStream).getChannel();
FileChannel outChannel = ((FileOutputStream)outputStream).getChannel();
long offset = 0;
long length = input.length;
if (input.assetFd != null) {
offset = input.assetFd.getStartOffset();
}
// transferFrom()'s 2nd arg is a relative position. Need to set the absolute
// position first.
inChannel.position(offset);
outChannel.transferFrom(inChannel, 0, length);
} else {
final int BUFFER_SIZE = 8192;
byte[] buffer = new byte[BUFFER_SIZE];
for (;;) {
int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
if (bytesRead <= 0) {
break;
}
outputStream.write(buffer, 0, bytesRead);
}
}
} finally {
input.inputStream.close();
if (outputStream != null) {
outputStream.close();
}
}
}
}

View File

@@ -0,0 +1,64 @@
/*
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.
*/
package org.apache.cordova.file;
import android.net.Uri;
public class LocalFilesystemURL {
public static final String FILESYSTEM_PROTOCOL = "cdvfile";
public final Uri uri;
public final String fsName;
public final String path;
public final boolean isDirectory;
private LocalFilesystemURL(Uri uri, String fsName, String fsPath, boolean isDirectory) {
this.uri = uri;
this.fsName = fsName;
this.path = fsPath;
this.isDirectory = isDirectory;
}
public static LocalFilesystemURL parse(Uri uri) {
if (!FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
return null;
}
String path = uri.getPath();
if (path.length() < 1) {
return null;
}
int firstSlashIdx = path.indexOf('/', 1);
if (firstSlashIdx < 0) {
return null;
}
String fsName = path.substring(1, firstSlashIdx);
path = path.substring(firstSlashIdx);
boolean isDirectory = path.charAt(path.length() - 1) == '/';
return new LocalFilesystemURL(uri, fsName, path, isDirectory);
}
public static LocalFilesystemURL parse(String uri) {
return parse(Uri.parse(uri));
}
public String toString() {
return uri.toString();
}
}

View File

@@ -0,0 +1,29 @@
/*
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.
*/
package org.apache.cordova.file;
@SuppressWarnings("serial")
public class NoModificationAllowedException extends Exception {
public NoModificationAllowedException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,30 @@
/*
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.
*/
package org.apache.cordova.file;
@SuppressWarnings("serial")
public class TypeMismatchException extends Exception {
public TypeMismatchException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,63 @@
/*
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.
*/
package org.apache.cordova.filetransfer;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Encapsulates in-progress status of uploading or downloading a file to a remote server.
*/
public class FileProgressResult {
private boolean lengthComputable = false; // declares whether total is known
private long loaded = 0; // bytes sent so far
private long total = 0; // bytes total, if known
public boolean getLengthComputable() {
return lengthComputable;
}
public void setLengthComputable(boolean computable) {
this.lengthComputable = computable;
}
public long getLoaded() {
return loaded;
}
public void setLoaded(long bytes) {
this.loaded = bytes;
}
public long getTotal() {
return total;
}
public void setTotal(long bytes) {
this.total = bytes;
}
public JSONObject toJSONObject() throws JSONException {
return new JSONObject(
"{loaded:" + loaded +
",total:" + total +
",lengthComputable:" + (lengthComputable ? "true" : "false") + "}");
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,73 @@
/*
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.
*/
package org.apache.cordova.filetransfer;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Encapsulates the result and/or status of uploading a file to a remote server.
*/
public class FileUploadResult {
private long bytesSent = 0; // bytes sent
private int responseCode = -1; // HTTP response code
private String response = null; // HTTP response
private String objectId = null; // FileTransfer object id
public long getBytesSent() {
return bytesSent;
}
public void setBytesSent(long bytes) {
this.bytesSent = bytes;
}
public int getResponseCode() {
return responseCode;
}
public void setResponseCode(int responseCode) {
this.responseCode = responseCode;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public String getObjectId() {
return objectId;
}
public void setObjectId(String objectId) {
this.objectId = objectId;
}
public JSONObject toJSONObject() throws JSONException {
return new JSONObject(
"{bytesSent:" + bytesSent +
",responseCode:" + responseCode +
",response:" + JSONObject.quote(response) +
",objectId:" + JSONObject.quote(objectId) + "}");
}
}