summaryrefslogtreecommitdiff
path: root/plugins/cordova-plugin-file/src
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/cordova-plugin-file/src')
-rw-r--r--plugins/cordova-plugin-file/src/android/AssetFilesystem.java283
-rw-r--r--plugins/cordova-plugin-file/src/android/ContentFilesystem.java215
-rw-r--r--plugins/cordova-plugin-file/src/android/DirectoryManager.java133
-rw-r--r--plugins/cordova-plugin-file/src/android/EncodingException.java29
-rw-r--r--plugins/cordova-plugin-file/src/android/FileExistsException.java29
-rw-r--r--plugins/cordova-plugin-file/src/android/FileUtils.java1027
-rw-r--r--plugins/cordova-plugin-file/src/android/Filesystem.java325
-rw-r--r--plugins/cordova-plugin-file/src/android/InvalidModificationException.java30
-rw-r--r--plugins/cordova-plugin-file/src/android/LocalFilesystem.java505
-rw-r--r--plugins/cordova-plugin-file/src/android/LocalFilesystemURL.java64
-rw-r--r--plugins/cordova-plugin-file/src/android/NoModificationAllowedException.java29
-rw-r--r--plugins/cordova-plugin-file/src/android/TypeMismatchException.java30
-rw-r--r--plugins/cordova-plugin-file/src/android/build-extras.gradle47
-rw-r--r--plugins/cordova-plugin-file/src/blackberry10/index.js44
-rw-r--r--plugins/cordova-plugin-file/src/browser/FileProxy.js964
-rw-r--r--plugins/cordova-plugin-file/src/firefoxos/FileProxy.js785
-rw-r--r--plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.h30
-rw-r--r--plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.m253
-rw-r--r--plugins/cordova-plugin-file/src/ios/CDVFile.h157
-rw-r--r--plugins/cordova-plugin-file/src/ios/CDVFile.m1092
-rw-r--r--plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.h32
-rw-r--r--plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.m734
-rw-r--r--plugins/cordova-plugin-file/src/ubuntu/file.cpp912
-rw-r--r--plugins/cordova-plugin-file/src/ubuntu/file.h81
-rw-r--r--plugins/cordova-plugin-file/src/windows/FileProxy.js1186
-rw-r--r--plugins/cordova-plugin-file/src/wp/File.cs1800
26 files changed, 0 insertions, 10816 deletions
diff --git a/plugins/cordova-plugin-file/src/android/AssetFilesystem.java b/plugins/cordova-plugin-file/src/android/AssetFilesystem.java
deleted file mode 100644
index f501b279..00000000
--- a/plugins/cordova-plugin-file/src/android/AssetFilesystem.java
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- 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");
- }
-
-}
diff --git a/plugins/cordova-plugin-file/src/android/ContentFilesystem.java b/plugins/cordova-plugin-file/src/android/ContentFilesystem.java
deleted file mode 100644
index 883e7cf5..00000000
--- a/plugins/cordova-plugin-file/src/android/ContentFilesystem.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- 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;
- }
-}
diff --git a/plugins/cordova-plugin-file/src/android/DirectoryManager.java b/plugins/cordova-plugin-file/src/android/DirectoryManager.java
deleted file mode 100644
index bcc005b2..00000000
--- a/plugins/cordova-plugin-file/src/android/DirectoryManager.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- 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;
- }
-}
diff --git a/plugins/cordova-plugin-file/src/android/EncodingException.java b/plugins/cordova-plugin-file/src/android/EncodingException.java
deleted file mode 100644
index e9e1653b..00000000
--- a/plugins/cordova-plugin-file/src/android/EncodingException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- 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);
- }
-
-}
diff --git a/plugins/cordova-plugin-file/src/android/FileExistsException.java b/plugins/cordova-plugin-file/src/android/FileExistsException.java
deleted file mode 100644
index 5c4d83dc..00000000
--- a/plugins/cordova-plugin-file/src/android/FileExistsException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- 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);
- }
-
-}
diff --git a/plugins/cordova-plugin-file/src/android/FileUtils.java b/plugins/cordova-plugin-file/src/android/FileUtils.java
deleted file mode 100644
index f57d26b3..00000000
--- a/plugins/cordova-plugin-file/src/android/FileUtils.java
+++ /dev/null
@@ -1,1027 +0,0 @@
-/*
- 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.app.Activity;
-import android.content.Context;
-import android.net.Uri;
-import android.os.Environment;
-import android.util.Base64;
-import android.util.Log;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaInterface;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.CordovaWebView;
-import org.apache.cordova.PluginResult;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-
-/**
- * This class provides file and directory services to JavaScript.
- */
-public class FileUtils extends CordovaPlugin {
- private static final String LOG_TAG = "FileUtils";
-
- public static int NOT_FOUND_ERR = 1;
- public static int SECURITY_ERR = 2;
- public static int ABORT_ERR = 3;
-
- public static int NOT_READABLE_ERR = 4;
- public static int ENCODING_ERR = 5;
- public static int NO_MODIFICATION_ALLOWED_ERR = 6;
- public static int INVALID_STATE_ERR = 7;
- public static int SYNTAX_ERR = 8;
- public static int INVALID_MODIFICATION_ERR = 9;
- public static int QUOTA_EXCEEDED_ERR = 10;
- public static int TYPE_MISMATCH_ERR = 11;
- public static int PATH_EXISTS_ERR = 12;
-
- public static int UNKNOWN_ERR = 1000;
-
- private boolean configured = false;
-
- // This field exists only to support getEntry, below, which has been deprecated
- private static FileUtils filePlugin;
-
- private interface FileOp {
- void run(JSONArray args) throws Exception;
- }
-
- private ArrayList<Filesystem> filesystems;
-
- public void registerFilesystem(Filesystem fs) {
- if (fs != null && filesystemForName(fs.name)== null) {
- this.filesystems.add(fs);
- }
- }
-
- private Filesystem filesystemForName(String name) {
- for (Filesystem fs:filesystems) {
- if (fs != null && fs.name != null && fs.name.equals(name)) {
- return fs;
- }
- }
- return null;
- }
-
- protected String[] getExtraFileSystemsPreference(Activity activity) {
- String fileSystemsStr = activity.getIntent().getStringExtra("androidextrafilesystems");
- if (fileSystemsStr == null) {
- fileSystemsStr = "files,files-external,documents,sdcard,cache,cache-external,root";
- }
- return fileSystemsStr.split(",");
- }
-
- protected void registerExtraFileSystems(String[] filesystems, HashMap<String, String> availableFileSystems) {
- HashSet<String> installedFileSystems = new HashSet<String>();
-
- /* Register filesystems in order */
- for (String fsName : filesystems) {
- if (!installedFileSystems.contains(fsName)) {
- String fsRoot = availableFileSystems.get(fsName);
- if (fsRoot != null) {
- File newRoot = new File(fsRoot);
- if (newRoot.mkdirs() || newRoot.isDirectory()) {
- registerFilesystem(new LocalFilesystem(fsName, webView.getContext(), webView.getResourceApi(), newRoot));
- installedFileSystems.add(fsName);
- } else {
- Log.d(LOG_TAG, "Unable to create root dir for filesystem \"" + fsName + "\", skipping");
- }
- } else {
- Log.d(LOG_TAG, "Unrecognized extra filesystem identifier: " + fsName);
- }
- }
- }
- }
-
- protected HashMap<String, String> getAvailableFileSystems(Activity activity) {
- Context context = activity.getApplicationContext();
- HashMap<String, String> availableFileSystems = new HashMap<String,String>();
-
- availableFileSystems.put("files", context.getFilesDir().getAbsolutePath());
- availableFileSystems.put("documents", new File(context.getFilesDir(), "Documents").getAbsolutePath());
- availableFileSystems.put("cache", context.getCacheDir().getAbsolutePath());
- availableFileSystems.put("root", "/");
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- try {
- availableFileSystems.put("files-external", context.getExternalFilesDir(null).getAbsolutePath());
- availableFileSystems.put("sdcard", Environment.getExternalStorageDirectory().getAbsolutePath());
- availableFileSystems.put("cache-external", context.getExternalCacheDir().getAbsolutePath());
- }
- catch(NullPointerException e) {
- Log.d(LOG_TAG, "External storage unavailable, check to see if USB Mass Storage Mode is on");
- }
- }
-
- return availableFileSystems;
- }
-
- @Override
- public void initialize(CordovaInterface cordova, CordovaWebView webView) {
- super.initialize(cordova, webView);
- this.filesystems = new ArrayList<Filesystem>();
-
- String tempRoot = null;
- String persistentRoot = null;
-
- Activity activity = cordova.getActivity();
- String packageName = activity.getPackageName();
-
- String location = activity.getIntent().getStringExtra("androidpersistentfilelocation");
- if (location == null) {
- location = "compatibility";
- }
- tempRoot = activity.getCacheDir().getAbsolutePath();
- if ("internal".equalsIgnoreCase(location)) {
- persistentRoot = activity.getFilesDir().getAbsolutePath() + "/files/";
- this.configured = true;
- } else if ("compatibility".equalsIgnoreCase(location)) {
- /*
- * Fall-back to compatibility mode -- this is the logic implemented in
- * earlier versions of this plugin, and should be maintained here so
- * that apps which were originally deployed with older versions of the
- * plugin can continue to provide access to files stored under those
- * versions.
- */
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- persistentRoot = Environment.getExternalStorageDirectory().getAbsolutePath();
- tempRoot = Environment.getExternalStorageDirectory().getAbsolutePath() +
- "/Android/data/" + packageName + "/cache/";
- } else {
- persistentRoot = "/data/data/" + packageName;
- }
- this.configured = true;
- }
-
- if (this.configured) {
- // Create the directories if they don't exist.
- File tmpRootFile = new File(tempRoot);
- File persistentRootFile = new File(persistentRoot);
- tmpRootFile.mkdirs();
- persistentRootFile.mkdirs();
-
- // Register initial filesystems
- // Note: The temporary and persistent filesystems need to be the first two
- // registered, so that they will match window.TEMPORARY and window.PERSISTENT,
- // per spec.
- this.registerFilesystem(new LocalFilesystem("temporary", webView.getContext(), webView.getResourceApi(), tmpRootFile));
- this.registerFilesystem(new LocalFilesystem("persistent", webView.getContext(), webView.getResourceApi(), persistentRootFile));
- this.registerFilesystem(new ContentFilesystem(webView.getContext(), webView.getResourceApi()));
- this.registerFilesystem(new AssetFilesystem(webView.getContext().getAssets(), webView.getResourceApi()));
-
- registerExtraFileSystems(getExtraFileSystemsPreference(activity), getAvailableFileSystems(activity));
-
- // Initialize static plugin reference for deprecated getEntry method
- if (filePlugin == null) {
- FileUtils.filePlugin = this;
- }
- } else {
- Log.e(LOG_TAG, "File plugin configuration error: Please set AndroidPersistentFileLocation in config.xml to one of \"internal\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
- activity.finish();
- }
- }
-
- public static FileUtils getFilePlugin() {
- return filePlugin;
- }
-
- private Filesystem filesystemForURL(LocalFilesystemURL localURL) {
- if (localURL == null) return null;
- return filesystemForName(localURL.fsName);
- }
-
- @Override
- public Uri remapUri(Uri uri) {
- // Remap only cdvfile: URLs (not content:).
- if (!LocalFilesystemURL.FILESYSTEM_PROTOCOL.equals(uri.getScheme())) {
- return null;
- }
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- return null;
- }
- String path = fs.filesystemPathForURL(inputURL);
- if (path != null) {
- return Uri.parse("file://" + fs.filesystemPathForURL(inputURL));
- }
- return null;
- } catch (IllegalArgumentException e) {
- return null;
- }
- }
-
- public boolean execute(String action, final String rawArgs, final CallbackContext callbackContext) {
- if (!configured) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, "File plugin is not configured. Please see the README.md file for details on how to update config.xml"));
- return true;
- }
- if (action.equals("testSaveLocationExists")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) {
- boolean b = DirectoryManager.testSaveLocationExists();
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getFreeDiskSpace")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) {
- long l = DirectoryManager.getFreeDiskSpace(false);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, l));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("testFileExists")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException {
- String fname=args.getString(0);
- boolean b = DirectoryManager.testFileExists(fname);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("testDirectoryExists")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException {
- String fname=args.getString(0);
- boolean b = DirectoryManager.testFileExists(fname);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsText")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- String encoding = args.getString(1);
- int start = args.getInt(2);
- int end = args.getInt(3);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsDataURL")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- int start = args.getInt(1);
- int end = args.getInt(2);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, null, -1);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsArrayBuffer")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- int start = args.getInt(1);
- int end = args.getInt(2);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readAsBinaryString")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, MalformedURLException {
- int start = args.getInt(1);
- int end = args.getInt(2);
- String fname=args.getString(0);
- readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("write")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
- String fname=args.getString(0);
- String data=args.getString(1);
- int offset=args.getInt(2);
- Boolean isBinary=args.getBoolean(3);
- long fileSize = write(fname, data, offset, isBinary);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("truncate")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileNotFoundException, IOException, NoModificationAllowedException {
- String fname=args.getString(0);
- int offset=args.getInt(1);
- long fileSize = truncateFile(fname, offset);
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize));
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("requestAllFileSystems")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws IOException, JSONException {
- callbackContext.success(requestAllFileSystems());
- }
- }, rawArgs, callbackContext);
- } else if (action.equals("requestAllPaths")) {
- cordova.getThreadPool().execute(
- new Runnable() {
- public void run() {
- try {
- callbackContext.success(requestAllPaths());
- } catch (JSONException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- );
- } else if (action.equals("requestFileSystem")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws IOException, JSONException {
- int fstype=args.getInt(0);
- long size = args.optLong(1);
- if (size != 0 && size > (DirectoryManager.getFreeDiskSpace(true) * 1024)) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, FileUtils.QUOTA_EXCEEDED_ERR));
- } else {
- JSONObject obj = requestFileSystem(fstype);
- callbackContext.success(obj);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("resolveLocalFileSystemURI")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws IOException, JSONException {
- String fname=args.getString(0);
- JSONObject obj = resolveLocalFileSystemURI(fname);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getFileMetadata")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
- String fname=args.getString(0);
- JSONObject obj = getFileMetadata(fname);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getParent")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, IOException {
- String fname=args.getString(0);
- JSONObject obj = getParent(fname);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getDirectory")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- String dirname=args.getString(0);
- String path=args.getString(1);
- JSONObject obj = getFile(dirname, path, args.optJSONObject(2), true);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("getFile")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- String dirname=args.getString(0);
- String path=args.getString(1);
- JSONObject obj = getFile(dirname, path, args.optJSONObject(2), false);
- callbackContext.success(obj);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("remove")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, NoModificationAllowedException, InvalidModificationException, MalformedURLException {
- String fname=args.getString(0);
- boolean success = remove(fname);
- if (success) {
- callbackContext.success();
- } else {
- callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("removeRecursively")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, FileExistsException, MalformedURLException, NoModificationAllowedException {
- String fname=args.getString(0);
- boolean success = removeRecursively(fname);
- if (success) {
- callbackContext.success();
- } else {
- callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- }
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("moveTo")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- String fname=args.getString(0);
- String newParent=args.getString(1);
- String newName=args.getString(2);
- JSONObject entry = transferTo(fname, newParent, newName, true);
- callbackContext.success(entry);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("copyTo")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- String fname=args.getString(0);
- String newParent=args.getString(1);
- String newName=args.getString(2);
- JSONObject entry = transferTo(fname, newParent, newName, false);
- callbackContext.success(entry);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("readEntries")) {
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
- String fname=args.getString(0);
- JSONArray entries = readEntries(fname);
- callbackContext.success(entries);
- }
- }, rawArgs, callbackContext);
- }
- else if (action.equals("_getLocalFilesystemPath")) {
- // Internal method for testing: Get the on-disk location of a local filesystem url.
- // [Currently used for testing file-transfer]
- threadhelper( new FileOp( ){
- public void run(JSONArray args) throws FileNotFoundException, JSONException, MalformedURLException {
- String localURLstr = args.getString(0);
- String fname = filesystemPathForURL(localURLstr);
- callbackContext.success(fname);
- }
- }, rawArgs, callbackContext);
- }
- else {
- return false;
- }
- return true;
- }
-
- public LocalFilesystemURL resolveNativeUri(Uri nativeUri) {
- LocalFilesystemURL localURL = null;
-
- // Try all installed filesystems. Return the best matching URL
- // (determined by the shortest resulting URL)
- for (Filesystem fs : filesystems) {
- LocalFilesystemURL url = fs.toLocalUri(nativeUri);
- if (url != null) {
- // A shorter fullPath implies that the filesystem is a better
- // match for the local path than the previous best.
- if (localURL == null || (url.uri.toString().length() < localURL.toString().length())) {
- localURL = url;
- }
- }
- }
- return localURL;
- }
-
- /*
- * These two native-only methods can be used by other plugins to translate between
- * device file system paths and URLs. By design, there is no direct JavaScript
- * interface to these methods.
- */
-
- public String filesystemPathForURL(String localURLstr) throws MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(localURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.filesystemPathForURL(inputURL);
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-
- public LocalFilesystemURL filesystemURLforLocalPath(String localPath) {
- LocalFilesystemURL localURL = null;
- int shortestFullPath = 0;
-
- // Try all installed filesystems. Return the best matching URL
- // (determined by the shortest resulting URL)
- for (Filesystem fs: filesystems) {
- LocalFilesystemURL url = fs.URLforFilesystemPath(localPath);
- if (url != null) {
- // A shorter fullPath implies that the filesystem is a better
- // match for the local path than the previous best.
- if (localURL == null || (url.path.length() < shortestFullPath)) {
- localURL = url;
- shortestFullPath = url.path.length();
- }
- }
- }
- return localURL;
- }
-
-
- /* helper to execute functions async and handle the result codes
- *
- */
- private void threadhelper(final FileOp f, final String rawArgs, final CallbackContext callbackContext){
- cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- try {
- JSONArray args = new JSONArray(rawArgs);
- f.run(args);
- } catch ( Exception e) {
- if( e instanceof EncodingException){
- callbackContext.error(FileUtils.ENCODING_ERR);
- } else if(e instanceof FileNotFoundException) {
- callbackContext.error(FileUtils.NOT_FOUND_ERR);
- } else if(e instanceof FileExistsException) {
- callbackContext.error(FileUtils.PATH_EXISTS_ERR);
- } else if(e instanceof NoModificationAllowedException ) {
- callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR);
- } else if(e instanceof InvalidModificationException ) {
- callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
- } else if(e instanceof MalformedURLException ) {
- callbackContext.error(FileUtils.ENCODING_ERR);
- } else if(e instanceof IOException ) {
- callbackContext.error(FileUtils.INVALID_MODIFICATION_ERR);
- } else if(e instanceof EncodingException ) {
- callbackContext.error(FileUtils.ENCODING_ERR);
- } else if(e instanceof TypeMismatchException ) {
- callbackContext.error(FileUtils.TYPE_MISMATCH_ERR);
- } else if(e instanceof JSONException ) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION));
- } else {
- e.printStackTrace();
- callbackContext.error(FileUtils.UNKNOWN_ERR);
- }
- }
- }
- });
- }
-
- /**
- * Allows the user to look up the Entry for a file or directory referred to by a local URI.
- *
- * @param uriString of the file/directory to look up
- * @return a JSONObject representing a Entry from the filesystem
- * @throws MalformedURLException if the url is not valid
- * @throws FileNotFoundException if the file does not exist
- * @throws IOException if the user can't read the file
- * @throws JSONException
- */
- private JSONObject resolveLocalFileSystemURI(String uriString) throws IOException, JSONException {
- if (uriString == null) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- Uri uri = Uri.parse(uriString);
-
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(uri);
- if (inputURL == null) {
- /* Check for file://, content:// urls */
- inputURL = resolveNativeUri(uri);
- }
-
- try {
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- if (fs.exists(inputURL)) {
- return fs.getEntryForLocalURL(inputURL);
- }
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- throw new FileNotFoundException();
- }
-
- /**
- * Read the list of files from this directory.
- *
- * @return a JSONArray containing JSONObjects that represent Entry objects.
- * @throws FileNotFoundException if the directory is not found.
- * @throws JSONException
- * @throws MalformedURLException
- */
- private JSONArray readEntries(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.readEntriesAtLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-
- /**
- * A setup method that handles the move/copy of files/directories
- *
- * @param newName for the file directory to be called, if null use existing file name
- * @param move if false do a copy, if true do a move
- * @return a Entry object
- * @throws NoModificationAllowedException
- * @throws IOException
- * @throws InvalidModificationException
- * @throws EncodingException
- * @throws JSONException
- * @throws FileExistsException
- */
- private JSONObject transferTo(String srcURLstr, String destURLstr, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException {
- if (srcURLstr == null || destURLstr == null) {
- // either no source or no destination provided
- throw new FileNotFoundException();
- }
-
- LocalFilesystemURL srcURL = LocalFilesystemURL.parse(srcURLstr);
- LocalFilesystemURL destURL = LocalFilesystemURL.parse(destURLstr);
-
- Filesystem srcFs = this.filesystemForURL(srcURL);
- Filesystem destFs = this.filesystemForURL(destURL);
-
- // Check for invalid file name
- if (newName != null && newName.contains(":")) {
- throw new EncodingException("Bad file name");
- }
-
- return destFs.copyFileToURL(destURL, newName, srcFs, srcURL, move);
- }
-
- /**
- * Deletes a directory and all of its contents, if any. In the event of an error
- * [e.g. trying to delete a directory that contains a file that cannot be removed],
- * some of the contents of the directory may be deleted.
- * It is an error to attempt to delete the root directory of a filesystem.
- *
- * @return a boolean representing success of failure
- * @throws FileExistsException
- * @throws NoModificationAllowedException
- * @throws MalformedURLException
- */
- private boolean removeRecursively(String baseURLstr) throws FileExistsException, NoModificationAllowedException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- // You can't delete the root directory.
- if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
- throw new NoModificationAllowedException("You can't delete the root directory");
- }
-
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.recursiveRemoveFileAtLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-
-
- /**
- * Deletes 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 the root directory of a filesystem.
- *
- * @return a boolean representing success of failure
- * @throws NoModificationAllowedException
- * @throws InvalidModificationException
- * @throws MalformedURLException
- */
- private boolean remove(String baseURLstr) throws NoModificationAllowedException, InvalidModificationException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- // You can't delete the root directory.
- if ("".equals(inputURL.path) || "/".equals(inputURL.path)) {
-
- throw new NoModificationAllowedException("You can't delete the root directory");
- }
-
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.removeFileAtLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-
- /**
- * Creates or looks up a file.
- *
- * @param baseURLstr base directory
- * @param path file/directory to lookup or create
- * @param options specify whether to create or not
- * @param directory if true look up directory, if false look up file
- * @return a Entry object
- * @throws FileExistsException
- * @throws IOException
- * @throws TypeMismatchException
- * @throws EncodingException
- * @throws JSONException
- */
- private JSONObject getFile(String baseURLstr, String path, JSONObject options, boolean directory) throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.getFileForLocalURL(inputURL, path, options, directory);
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
-
- }
-
- /**
- * Look up the parent DirectoryEntry containing this Entry.
- * If this Entry is the root of its filesystem, its parent is itself.
- */
- private JSONObject getParent(String baseURLstr) throws JSONException, IOException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.getParentForLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-
- /**
- * Returns a File that represents the current state of the file that this FileEntry represents.
- *
- * @return returns a JSONObject represent a W3C File object
- */
- private JSONObject getFileMetadata(String baseURLstr) throws FileNotFoundException, JSONException, MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(baseURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
- return fs.getFileMetadataForLocalURL(inputURL);
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-
- /**
- * Requests a filesystem in which to store application data.
- *
- * @param type of file system requested
- * @return a JSONObject representing the file system
- * @throws IOException
- * @throws JSONException
- */
- private JSONObject requestFileSystem(int type) throws IOException, JSONException {
- JSONObject fs = new JSONObject();
- Filesystem rootFs = null;
- try {
- rootFs = this.filesystems.get(type);
- } catch (ArrayIndexOutOfBoundsException e) {
- // Pass null through
- }
- if (rootFs == null) {
- throw new IOException("No filesystem of type requested");
- }
- fs.put("name", rootFs.name);
- fs.put("root", rootFs.getRootEntry());
- return fs;
- }
-
-
- /**
- * Requests a filesystem in which to store application data.
- *
- * @return a JSONObject representing the file system
- */
- private JSONArray requestAllFileSystems() throws IOException, JSONException {
- JSONArray ret = new JSONArray();
- for (Filesystem fs : filesystems) {
- ret.put(fs.getRootEntry());
- }
- return ret;
- }
-
- private static String toDirUrl(File f) {
- return Uri.fromFile(f).toString() + '/';
- }
-
- private JSONObject requestAllPaths() throws JSONException {
- Context context = cordova.getActivity();
- JSONObject ret = new JSONObject();
- ret.put("applicationDirectory", "file:///android_asset/");
- ret.put("applicationStorageDirectory", toDirUrl(context.getFilesDir().getParentFile()));
- ret.put("dataDirectory", toDirUrl(context.getFilesDir()));
- ret.put("cacheDirectory", toDirUrl(context.getCacheDir()));
- if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
- try {
- ret.put("externalApplicationStorageDirectory", toDirUrl(context.getExternalFilesDir(null).getParentFile()));
- ret.put("externalDataDirectory", toDirUrl(context.getExternalFilesDir(null)));
- ret.put("externalCacheDirectory", toDirUrl(context.getExternalCacheDir()));
- ret.put("externalRootDirectory", toDirUrl(Environment.getExternalStorageDirectory()));
- }
- catch(NullPointerException e) {
- /* If external storage is unavailable, context.getExternal* returns null */
- Log.d(LOG_TAG, "Unable to access these paths, most liklely due to USB storage");
- }
- }
- return ret;
- }
-
- /**
- * Returns a JSON object representing the given File. Internal APIs should be modified
- * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
- *
- * @param file the File to convert
- * @return a JSON representation of the given File
- * @throws JSONException
- */
- public JSONObject getEntryForFile(File file) throws JSONException {
- JSONObject entry;
-
- for (Filesystem fs : filesystems) {
- entry = fs.makeEntryForFile(file);
- if (entry != null) {
- return entry;
- }
- }
- return null;
- }
-
- /**
- * Returns a JSON object representing the given File. Deprecated, as this is only used by
- * FileTransfer, and because it is a static method that should really be an instance method,
- * since it depends on the actual filesystem roots in use. Internal APIs should be modified
- * to use URLs instead of raw FS paths wherever possible, when interfacing with this plugin.
- *
- * @param file the File to convert
- * @return a JSON representation of the given File
- * @throws JSONException
- */
- @Deprecated
- public static JSONObject getEntry(File file) throws JSONException {
- if (getFilePlugin() != null) {
- return getFilePlugin().getEntryForFile(file);
- }
- return null;
- }
-
- /**
- * Read the contents of a file.
- * This is done in a background thread; the result is sent to the callback.
- *
- * @param start Start position in the file.
- * @param end End position to stop at (exclusive).
- * @param callbackContext The context through which to send the result.
- * @param encoding The encoding to return contents as. Typical value is UTF-8. (see http://www.iana.org/assignments/character-sets)
- * @param resultType The desired type of data to send to the callback.
- * @return Contents of file.
- */
- public void readFileAs(final String srcURLstr, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) throws MalformedURLException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
-
- fs.readFileAtURL(inputURL, start, end, new Filesystem.ReadFileCallback() {
- public void handleData(InputStream inputStream, String contentType) {
- try {
- ByteArrayOutputStream os = new ByteArrayOutputStream();
- final int BUFFER_SIZE = 8192;
- byte[] buffer = new byte[BUFFER_SIZE];
-
- for (;;) {
- int bytesRead = inputStream.read(buffer, 0, BUFFER_SIZE);
-
- if (bytesRead <= 0) {
- break;
- }
- os.write(buffer, 0, bytesRead);
- }
-
- PluginResult result;
- switch (resultType) {
- case PluginResult.MESSAGE_TYPE_STRING:
- result = new PluginResult(PluginResult.Status.OK, os.toString(encoding));
- break;
- case PluginResult.MESSAGE_TYPE_ARRAYBUFFER:
- result = new PluginResult(PluginResult.Status.OK, os.toByteArray());
- break;
- case PluginResult.MESSAGE_TYPE_BINARYSTRING:
- result = new PluginResult(PluginResult.Status.OK, os.toByteArray(), true);
- break;
- default: // Base64.
- byte[] base64 = Base64.encode(os.toByteArray(), Base64.NO_WRAP);
- String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII");
- result = new PluginResult(PluginResult.Status.OK, s);
- }
-
- callbackContext.sendPluginResult(result);
- } catch (IOException e) {
- Log.d(LOG_TAG, e.getLocalizedMessage());
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
- }
- }
- });
-
-
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- } catch (FileNotFoundException e) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_FOUND_ERR));
- } catch (IOException e) {
- Log.d(LOG_TAG, e.getLocalizedMessage());
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.IO_EXCEPTION, NOT_READABLE_ERR));
- }
- }
-
-
- /**
- * Write contents of file.
- *
- * @param data The contents of the file.
- * @param offset The position to begin writing the file.
- * @param isBinary True if the file contents are base64-encoded binary data
- */
- /**/
- public long write(String srcURLstr, String data, int offset, boolean isBinary) throws FileNotFoundException, IOException, NoModificationAllowedException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
-
- long x = fs.writeToFileAtURL(inputURL, data, offset, isBinary); Log.d("TEST",srcURLstr + ": "+x); return x;
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
-
- }
-
- /**
- * Truncate the file to size
- */
- private long truncateFile(String srcURLstr, long size) throws FileNotFoundException, IOException, NoModificationAllowedException {
- try {
- LocalFilesystemURL inputURL = LocalFilesystemURL.parse(srcURLstr);
- Filesystem fs = this.filesystemForURL(inputURL);
- if (fs == null) {
- throw new MalformedURLException("No installed handlers for this URL");
- }
-
- return fs.truncateFileAtURL(inputURL, size);
- } catch (IllegalArgumentException e) {
- throw new MalformedURLException("Unrecognized filesystem URL");
- }
- }
-}
diff --git a/plugins/cordova-plugin-file/src/android/Filesystem.java b/plugins/cordova-plugin-file/src/android/Filesystem.java
deleted file mode 100644
index faf31d2a..00000000
--- a/plugins/cordova-plugin-file/src/android/Filesystem.java
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- 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;
- }
- }
-}
diff --git a/plugins/cordova-plugin-file/src/android/InvalidModificationException.java b/plugins/cordova-plugin-file/src/android/InvalidModificationException.java
deleted file mode 100644
index 8f6bec59..00000000
--- a/plugins/cordova-plugin-file/src/android/InvalidModificationException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- 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);
- }
-
-}
diff --git a/plugins/cordova-plugin-file/src/android/LocalFilesystem.java b/plugins/cordova-plugin-file/src/android/LocalFilesystem.java
deleted file mode 100644
index 3b1ecca8..00000000
--- a/plugins/cordova-plugin-file/src/android/LocalFilesystem.java
+++ /dev/null
@@ -1,505 +0,0 @@
-/*
- 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();
- }
- }
- }
-}
diff --git a/plugins/cordova-plugin-file/src/android/LocalFilesystemURL.java b/plugins/cordova-plugin-file/src/android/LocalFilesystemURL.java
deleted file mode 100644
index 74f43db6..00000000
--- a/plugins/cordova-plugin-file/src/android/LocalFilesystemURL.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- 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();
- }
-}
diff --git a/plugins/cordova-plugin-file/src/android/NoModificationAllowedException.java b/plugins/cordova-plugin-file/src/android/NoModificationAllowedException.java
deleted file mode 100644
index 627eafb5..00000000
--- a/plugins/cordova-plugin-file/src/android/NoModificationAllowedException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- 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);
- }
-
-}
diff --git a/plugins/cordova-plugin-file/src/android/TypeMismatchException.java b/plugins/cordova-plugin-file/src/android/TypeMismatchException.java
deleted file mode 100644
index 1315f9a9..00000000
--- a/plugins/cordova-plugin-file/src/android/TypeMismatchException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- 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);
- }
-
-}
diff --git a/plugins/cordova-plugin-file/src/android/build-extras.gradle b/plugins/cordova-plugin-file/src/android/build-extras.gradle
deleted file mode 100644
index a0a7844a..00000000
--- a/plugins/cordova-plugin-file/src/android/build-extras.gradle
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- 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.
- */
-ext.postBuildExtras = {
- def inAssetsDir = file("assets")
- def outAssetsDir = inAssetsDir
- def outFile = new File(outAssetsDir, "cdvasset.manifest")
-
- def newTask = task("cdvCreateAssetManifest") << {
- def contents = new HashMap()
- def sizes = new HashMap()
- contents[""] = inAssetsDir.list()
- def tree = fileTree(dir: inAssetsDir)
- tree.visit { fileDetails ->
- if (fileDetails.isDirectory()) {
- contents[fileDetails.relativePath.toString()] = fileDetails.file.list()
- } else {
- sizes[fileDetails.relativePath.toString()] = fileDetails.file.length()
- }
- }
-
- outAssetsDir.mkdirs()
- outFile.withObjectOutputStream { oos ->
- oos.writeObject(contents)
- oos.writeObject(sizes)
- }
- }
- newTask.inputs.dir inAssetsDir
- newTask.outputs.file outFile
- def preBuildTask = tasks["preBuild"]
- preBuildTask.dependsOn(newTask)
-}
diff --git a/plugins/cordova-plugin-file/src/blackberry10/index.js b/plugins/cordova-plugin-file/src/blackberry10/index.js
deleted file mode 100644
index 913ab30a..00000000
--- a/plugins/cordova-plugin-file/src/blackberry10/index.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * 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.
- *
-*/
-module.exports = {
- setSandbox : function (success, fail, args, env) {
- require("lib/webview").setSandbox(JSON.parse(decodeURIComponent(args[0])));
- new PluginResult(args, env).ok();
- },
-
- getHomePath: function (success, fail, args, env) {
- var homeDir = window.qnx.webplatform.getApplication().getEnv("HOME");
- new PluginResult(args, env).ok(homeDir);
- },
-
- requestAllPaths: function (success, fail, args, env) {
- var homeDir = 'file://' + window.qnx.webplatform.getApplication().getEnv("HOME").replace('/data', ''),
- paths = {
- applicationDirectory: homeDir + '/app/native/',
- applicationStorageDirectory: homeDir + '/',
- dataDirectory: homeDir + '/data/webviews/webfs/persistent/local__0/',
- cacheDirectory: homeDir + '/data/webviews/webfs/temporary/local__0/',
- externalRootDirectory: 'file:///accounts/1000/removable/sdcard/',
- sharedDirectory: homeDir + '/shared/'
- };
- success(paths);
- }
-};
diff --git a/plugins/cordova-plugin-file/src/browser/FileProxy.js b/plugins/cordova-plugin-file/src/browser/FileProxy.js
deleted file mode 100644
index c853db8d..00000000
--- a/plugins/cordova-plugin-file/src/browser/FileProxy.js
+++ /dev/null
@@ -1,964 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-
-/*global require, exports, module*/
-/*global FILESYSTEM_PREFIX*/
-/*global IDBKeyRange*/
-
-/* Heavily based on https://github.com/ebidel/idb.filesystem.js */
-
-// window.webkitRequestFileSystem and window.webkitResolveLocalFileSystemURL
-// are available only in Chrome and possible a good flag to indicate
-// that we're running in Chrome
-var isChrome = window.webkitRequestFileSystem && window.webkitResolveLocalFileSystemURL;
-
-// For chrome we don't need to implement proxy methods
-// All functionality can be accessed natively.
-if (isChrome) {
- var pathsPrefix = {
- // Read-only directory where the application is installed.
- applicationDirectory: location.origin + "/",
- // Where to put app-specific data files.
- dataDirectory: 'filesystem:file:///persistent/',
- // Cached files that should survive app restarts.
- // Apps should not rely on the OS to delete files in here.
- cacheDirectory: 'filesystem:file:///temporary/',
- };
-
- exports.requestAllPaths = function(successCallback) {
- successCallback(pathsPrefix);
- };
-
- require("cordova/exec/proxy").add("File", module.exports);
- return;
-}
-
-var LocalFileSystem = require('./LocalFileSystem'),
- FileSystem = require('./FileSystem'),
- FileEntry = require('./FileEntry'),
- FileError = require('./FileError'),
- DirectoryEntry = require('./DirectoryEntry'),
- File = require('./File');
-
-(function(exports, global) {
- var indexedDB = global.indexedDB || global.mozIndexedDB;
- if (!indexedDB) {
- throw "Firefox OS File plugin: indexedDB not supported";
- }
-
- var fs_ = null;
-
- var idb_ = {};
- idb_.db = null;
- var FILE_STORE_ = 'entries';
-
- var DIR_SEPARATOR = '/';
-
- var pathsPrefix = {
- // Read-only directory where the application is installed.
- applicationDirectory: location.origin + "/",
- // Where to put app-specific data files.
- dataDirectory: 'file:///persistent/',
- // Cached files that should survive app restarts.
- // Apps should not rely on the OS to delete files in here.
- cacheDirectory: 'file:///temporary/',
- };
-
- var unicodeLastChar = 65535;
-
-/*** Exported functionality ***/
-
- exports.requestFileSystem = function(successCallback, errorCallback, args) {
- var type = args[0];
- // Size is ignored since IDB filesystem size depends
- // on browser implementation and can't be set up by user
- var size = args[1]; // jshint ignore: line
-
- if (type !== LocalFileSystem.TEMPORARY && type !== LocalFileSystem.PERSISTENT) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var name = type === LocalFileSystem.TEMPORARY ? 'temporary' : 'persistent';
- var storageName = (location.protocol + location.host).replace(/:/g, '_');
-
- var root = new DirectoryEntry('', DIR_SEPARATOR);
- fs_ = new FileSystem(name, root);
-
- idb_.open(storageName, function() {
- successCallback(fs_);
- }, errorCallback);
- };
-
- // Overridden by Android, BlackBerry 10 and iOS to populate fsMap
- require('./fileSystems').getFs = function(name, callback) {
- callback(new FileSystem(name, fs_.root));
- };
-
- // list a directory's contents (files and folders).
- exports.readEntries = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
-
- if (typeof successCallback !== 'function') {
- throw Error('Expected successCallback argument.');
- }
-
- var path = resolveToFullPath_(fullPath);
-
- exports.getDirectory(function() {
- idb_.getAllEntries(path.fullPath + DIR_SEPARATOR, path.storagePath, function(entries) {
- successCallback(entries);
- }, errorCallback);
- }, function() {
- if (errorCallback) {
- errorCallback(FileError.NOT_FOUND_ERR);
- }
- }, [path.storagePath, path.fullPath, {create: false}]);
- };
-
- exports.getFile = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
- var path = args[1];
- var options = args[2] || {};
-
- // Create an absolute path if we were handed a relative one.
- path = resolveToFullPath_(fullPath, path);
-
- idb_.get(path.storagePath, function(fileEntry) {
- if (options.create === true && options.exclusive === true && fileEntry) {
- // If create and exclusive are both true, and the path already exists,
- // getFile must fail.
-
- if (errorCallback) {
- errorCallback(FileError.PATH_EXISTS_ERR);
- }
- } else if (options.create === true && !fileEntry) {
- // If create is true, the path doesn't exist, and no other error occurs,
- // getFile must create it as a zero-length file and return a corresponding
- // FileEntry.
- var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
-
- newFileEntry.file_ = new MyFile({
- size: 0,
- name: newFileEntry.name,
- lastModifiedDate: new Date(),
- storagePath: path.storagePath
- });
-
- idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
- } else if (options.create === true && fileEntry) {
- if (fileEntry.isFile) {
- // Overwrite file, delete then create new.
- idb_['delete'](path.storagePath, function() {
- var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
-
- newFileEntry.file_ = new MyFile({
- size: 0,
- name: newFileEntry.name,
- lastModifiedDate: new Date(),
- storagePath: path.storagePath
- });
-
- idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
- }, errorCallback);
- } else {
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- }
- } else if ((!options.create || options.create === false) && !fileEntry) {
- // If create is not true and the path doesn't exist, getFile must fail.
- if (errorCallback) {
- errorCallback(FileError.NOT_FOUND_ERR);
- }
- } else if ((!options.create || options.create === false) && fileEntry &&
- fileEntry.isDirectory) {
- // If create is not true and the path exists, but is a directory, getFile
- // must fail.
- if (errorCallback) {
- errorCallback(FileError.TYPE_MISMATCH_ERR);
- }
- } else {
- // Otherwise, if no other error occurs, getFile must return a FileEntry
- // corresponding to path.
-
- successCallback(fileEntryFromIdbEntry(fileEntry));
- }
- }, errorCallback);
- };
-
- exports.getFileMetadata = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
-
- exports.getFile(function(fileEntry) {
- successCallback(new File(fileEntry.file_.name, fileEntry.fullPath, '', fileEntry.file_.lastModifiedDate,
- fileEntry.file_.size));
- }, errorCallback, [fullPath, null]);
- };
-
- exports.getMetadata = function(successCallback, errorCallback, args) {
- exports.getFile(function (fileEntry) {
- successCallback(
- {
- modificationTime: fileEntry.file_.lastModifiedDate,
- size: fileEntry.file_.lastModifiedDate
- });
- }, errorCallback, args);
- };
-
- exports.setMetadata = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
- var metadataObject = args[1];
-
- exports.getFile(function (fileEntry) {
- fileEntry.file_.lastModifiedDate = metadataObject.modificationTime;
- idb_.put(fileEntry, fileEntry.file_.storagePath, successCallback, errorCallback);
- }, errorCallback, [fullPath, null]);
- };
-
- exports.write = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- data = args[1],
- position = args[2],
- isBinary = args[3]; // jshint ignore: line
-
- if (!data) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- if (typeof data === 'string' || data instanceof String) {
- data = new Blob([data]);
- }
-
- exports.getFile(function(fileEntry) {
- var blob_ = fileEntry.file_.blob_;
-
- if (!blob_) {
- blob_ = new Blob([data], {type: data.type});
- } else {
- // Calc the head and tail fragments
- var head = blob_.slice(0, position);
- var tail = blob_.slice(position + (data.size || data.byteLength));
-
- // Calc the padding
- var padding = position - head.size;
- if (padding < 0) {
- padding = 0;
- }
-
- // Do the "write". In fact, a full overwrite of the Blob.
- blob_ = new Blob([head, new Uint8Array(padding), data, tail],
- {type: data.type});
- }
-
- // Set the blob we're writing on this file entry so we can recall it later.
- fileEntry.file_.blob_ = blob_;
- fileEntry.file_.lastModifiedDate = new Date() || null;
- fileEntry.file_.size = blob_.size;
- fileEntry.file_.name = blob_.name;
- fileEntry.file_.type = blob_.type;
-
- idb_.put(fileEntry, fileEntry.file_.storagePath, function() {
- successCallback(data.size || data.byteLength);
- }, errorCallback);
- }, errorCallback, [fileName, null]);
- };
-
- exports.readAsText = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- enc = args[1],
- startPos = args[2],
- endPos = args[3];
-
- readAs('text', fileName, enc, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.readAsDataURL = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- startPos = args[1],
- endPos = args[2];
-
- readAs('dataURL', fileName, null, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.readAsBinaryString = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- startPos = args[1],
- endPos = args[2];
-
- readAs('binaryString', fileName, null, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.readAsArrayBuffer = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- startPos = args[1],
- endPos = args[2];
-
- readAs('arrayBuffer', fileName, null, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.removeRecursively = exports.remove = function(successCallback, errorCallback, args) {
- if (typeof successCallback !== 'function') {
- throw Error('Expected successCallback argument.');
- }
-
- var fullPath = resolveToFullPath_(args[0]).storagePath;
- if (fullPath === pathsPrefix.cacheDirectory || fullPath === pathsPrefix.dataDirectory) {
- errorCallback(FileError.NO_MODIFICATION_ALLOWED_ERR);
- return;
- }
-
- function deleteEntry(isDirectory) {
- // TODO: This doesn't protect against directories that have content in it.
- // Should throw an error instead if the dirEntry is not empty.
- idb_['delete'](fullPath, function() {
- successCallback();
- }, function() {
- if (errorCallback) { errorCallback(); }
- }, isDirectory);
- }
-
- // We need to to understand what we are deleting:
- exports.getDirectory(function(entry) {
- deleteEntry(entry.isDirectory);
- }, function(){
- //DirectoryEntry was already deleted or entry is FileEntry
- deleteEntry(false);
- }, [fullPath, null, {create: false}]);
- };
-
- exports.getDirectory = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
- var path = args[1];
- var options = args[2];
-
- // Create an absolute path if we were handed a relative one.
- path = resolveToFullPath_(fullPath, path);
-
- idb_.get(path.storagePath, function(folderEntry) {
- if (!options) {
- options = {};
- }
-
- if (options.create === true && options.exclusive === true && folderEntry) {
- // If create and exclusive are both true, and the path already exists,
- // getDirectory must fail.
- if (errorCallback) {
- errorCallback(FileError.PATH_EXISTS_ERR);
- }
- // There is a strange bug in mobilespec + FF, which results in coming to multiple else-if's
- // so we are shielding from it with returns.
- return;
- }
-
- if (options.create === true && !folderEntry) {
- // If create is true, the path doesn't exist, and no other error occurs,
- // getDirectory must create it as a zero-length file and return a corresponding
- // MyDirectoryEntry.
- var dirEntry = new DirectoryEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
-
- idb_.put(dirEntry, path.storagePath, successCallback, errorCallback);
- return;
- }
-
- if (options.create === true && folderEntry) {
-
- if (folderEntry.isDirectory) {
- // IDB won't save methods, so we need re-create the MyDirectoryEntry.
- successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem));
- } else {
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- }
- return;
- }
-
- if ((!options.create || options.create === false) && !folderEntry) {
- // Handle root special. It should always exist.
- if (path.fullPath === DIR_SEPARATOR) {
- successCallback(fs_.root);
- return;
- }
-
- // If create is not true and the path doesn't exist, getDirectory must fail.
- if (errorCallback) {
- errorCallback(FileError.NOT_FOUND_ERR);
- }
-
- return;
- }
- if ((!options.create || options.create === false) && folderEntry && folderEntry.isFile) {
- // If create is not true and the path exists, but is a file, getDirectory
- // must fail.
- if (errorCallback) {
- errorCallback(FileError.TYPE_MISMATCH_ERR);
- }
- return;
- }
-
- // Otherwise, if no other error occurs, getDirectory must return a
- // MyDirectoryEntry corresponding to path.
-
- // IDB won't' save methods, so we need re-create MyDirectoryEntry.
- successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.filesystem));
- }, errorCallback);
- };
-
- exports.getParent = function(successCallback, errorCallback, args) {
- if (typeof successCallback !== 'function') {
- throw Error('Expected successCallback argument.');
- }
-
- var fullPath = args[0];
- //fullPath is like this:
- //file:///persistent/path/to/file or
- //file:///persistent/path/to/directory/
-
- if (fullPath === DIR_SEPARATOR || fullPath === pathsPrefix.cacheDirectory ||
- fullPath === pathsPrefix.dataDirectory) {
- successCallback(fs_.root);
- return;
- }
-
- //To delete all slashes at the end
- while (fullPath[fullPath.length - 1] === '/') {
- fullPath = fullPath.substr(0, fullPath.length - 1);
- }
-
- var pathArr = fullPath.split(DIR_SEPARATOR);
- pathArr.pop();
- var parentName = pathArr.pop();
- var path = pathArr.join(DIR_SEPARATOR) + DIR_SEPARATOR;
-
- //To get parent of root files
- var joined = path + parentName + DIR_SEPARATOR;//is like this: file:///persistent/
- if (joined === pathsPrefix.cacheDirectory || joined === pathsPrefix.dataDirectory) {
- exports.getDirectory(successCallback, errorCallback, [joined, DIR_SEPARATOR, {create: false}]);
- return;
- }
-
- exports.getDirectory(successCallback, errorCallback, [path, parentName, {create: false}]);
- };
-
- exports.copyTo = function(successCallback, errorCallback, args) {
- var srcPath = args[0];
- var parentFullPath = args[1];
- var name = args[2];
-
- if (name.indexOf('/') !== -1 || srcPath === parentFullPath + name) {
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
-
- return;
- }
-
- // Read src file
- exports.getFile(function(srcFileEntry) {
-
- var path = resolveToFullPath_(parentFullPath);
- //Check directory
- exports.getDirectory(function() {
-
- // Create dest file
- exports.getFile(function(dstFileEntry) {
-
- exports.write(function() {
- successCallback(dstFileEntry);
- }, errorCallback, [dstFileEntry.file_.storagePath, srcFileEntry.file_.blob_, 0]);
-
- }, errorCallback, [parentFullPath, name, {create: true}]);
-
- }, function() { if (errorCallback) { errorCallback(FileError.NOT_FOUND_ERR); }},
- [path.storagePath, null, {create:false}]);
-
- }, errorCallback, [srcPath, null]);
- };
-
- exports.moveTo = function(successCallback, errorCallback, args) {
- var srcPath = args[0];
- // parentFullPath and name parameters is ignored because
- // args is being passed downstream to exports.copyTo method
- var parentFullPath = args[1]; // jshint ignore: line
- var name = args[2]; // jshint ignore: line
-
- exports.copyTo(function (fileEntry) {
-
- exports.remove(function () {
- successCallback(fileEntry);
- }, errorCallback, [srcPath]);
-
- }, errorCallback, args);
- };
-
- exports.resolveLocalFileSystemURI = function(successCallback, errorCallback, args) {
- var path = args[0];
-
- // Ignore parameters
- if (path.indexOf('?') !== -1) {
- path = String(path).split("?")[0];
- }
-
- // support for encodeURI
- if (/\%5/g.test(path) || /\%20/g.test(path)) {
- path = decodeURI(path);
- }
-
- if (path.trim()[0] === '/') {
- errorCallback && errorCallback(FileError.ENCODING_ERR);
- return;
- }
-
- //support for cdvfile
- if (path.trim().substr(0,7) === "cdvfile") {
- if (path.indexOf("cdvfile://localhost") === -1) {
- errorCallback && errorCallback(FileError.ENCODING_ERR);
- return;
- }
-
- var indexPersistent = path.indexOf("persistent");
- var indexTemporary = path.indexOf("temporary");
-
- //cdvfile://localhost/persistent/path/to/file
- if (indexPersistent !== -1) {
- path = "file:///persistent" + path.substr(indexPersistent + 10);
- } else if (indexTemporary !== -1) {
- path = "file:///temporary" + path.substr(indexTemporary + 9);
- } else {
- errorCallback && errorCallback(FileError.ENCODING_ERR);
- return;
- }
- }
-
- // to avoid path form of '///path/to/file'
- function handlePathSlashes(path) {
- var cutIndex = 0;
- for (var i = 0; i < path.length - 1; i++) {
- if (path[i] === DIR_SEPARATOR && path[i + 1] === DIR_SEPARATOR) {
- cutIndex = i + 1;
- } else break;
- }
-
- return path.substr(cutIndex);
- }
-
- // Handle localhost containing paths (see specs )
- if (path.indexOf('file://localhost/') === 0) {
- path = path.replace('file://localhost/', 'file:///');
- }
-
- if (path.indexOf(pathsPrefix.dataDirectory) === 0) {
- path = path.substring(pathsPrefix.dataDirectory.length - 1);
- path = handlePathSlashes(path);
-
- exports.requestFileSystem(function() {
- exports.getFile(successCallback, function() {
- exports.getDirectory(successCallback, errorCallback, [pathsPrefix.dataDirectory, path,
- {create: false}]);
- }, [pathsPrefix.dataDirectory, path, {create: false}]);
- }, errorCallback, [LocalFileSystem.PERSISTENT]);
- } else if (path.indexOf(pathsPrefix.cacheDirectory) === 0) {
- path = path.substring(pathsPrefix.cacheDirectory.length - 1);
- path = handlePathSlashes(path);
-
- exports.requestFileSystem(function() {
- exports.getFile(successCallback, function() {
- exports.getDirectory(successCallback, errorCallback, [pathsPrefix.cacheDirectory, path,
- {create: false}]);
- }, [pathsPrefix.cacheDirectory, path, {create: false}]);
- }, errorCallback, [LocalFileSystem.TEMPORARY]);
- } else if (path.indexOf(pathsPrefix.applicationDirectory) === 0) {
- path = path.substring(pathsPrefix.applicationDirectory.length);
- //TODO: need to cut out redundant slashes?
-
- var xhr = new XMLHttpRequest();
- xhr.open("GET", path, true);
- xhr.onreadystatechange = function () {
- if (xhr.status === 200 && xhr.readyState === 4) {
- exports.requestFileSystem(function(fs) {
- fs.name = location.hostname;
-
- //TODO: need to call exports.getFile(...) to handle errors correct
- fs.root.getFile(path, {create: true}, writeFile, errorCallback);
- }, errorCallback, [LocalFileSystem.PERSISTENT]);
- }
- };
-
- xhr.onerror = function () {
- errorCallback && errorCallback(FileError.NOT_READABLE_ERR);
- };
-
- xhr.send();
- } else {
- errorCallback && errorCallback(FileError.NOT_FOUND_ERR);
- }
-
- function writeFile(entry) {
- entry.createWriter(function (fileWriter) {
- fileWriter.onwriteend = function (evt) {
- if (!evt.target.error) {
- entry.filesystemName = location.hostname;
- successCallback(entry);
- }
- };
- fileWriter.onerror = function () {
- errorCallback && errorCallback(FileError.NOT_READABLE_ERR);
- };
- fileWriter.write(new Blob([xhr.response]));
- }, errorCallback);
- }
- };
-
- exports.requestAllPaths = function(successCallback) {
- successCallback(pathsPrefix);
- };
-
-/*** Helpers ***/
-
- /**
- * Interface to wrap the native File interface.
- *
- * This interface is necessary for creating zero-length (empty) files,
- * something the Filesystem API allows you to do. Unfortunately, File's
- * constructor cannot be called directly, making it impossible to instantiate
- * an empty File in JS.
- *
- * @param {Object} opts Initial values.
- * @constructor
- */
- function MyFile(opts) {
- var blob_ = new Blob();
-
- this.size = opts.size || 0;
- this.name = opts.name || '';
- this.type = opts.type || '';
- this.lastModifiedDate = opts.lastModifiedDate || null;
- this.storagePath = opts.storagePath || '';
-
- // Need some black magic to correct the object's size/name/type based on the
- // blob that is saved.
- Object.defineProperty(this, 'blob_', {
- enumerable: true,
- get: function() {
- return blob_;
- },
- set: function(val) {
- blob_ = val;
- this.size = blob_.size;
- this.name = blob_.name;
- this.type = blob_.type;
- this.lastModifiedDate = blob_.lastModifiedDate;
- }.bind(this)
- });
- }
-
- MyFile.prototype.constructor = MyFile;
-
- // When saving an entry, the fullPath should always lead with a slash and never
- // end with one (e.g. a directory). Also, resolve '.' and '..' to an absolute
- // one. This method ensures path is legit!
- function resolveToFullPath_(cwdFullPath, path) {
- path = path || '';
- var fullPath = path;
- var prefix = '';
-
- cwdFullPath = cwdFullPath || DIR_SEPARATOR;
- if (cwdFullPath.indexOf(FILESYSTEM_PREFIX) === 0) {
- prefix = cwdFullPath.substring(0, cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
- cwdFullPath = cwdFullPath.substring(cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
- }
-
- var relativePath = path[0] !== DIR_SEPARATOR;
- if (relativePath) {
- fullPath = cwdFullPath;
- if (cwdFullPath !== DIR_SEPARATOR) {
- fullPath += DIR_SEPARATOR + path;
- } else {
- fullPath += path;
- }
- }
-
- // Remove doubled separator substrings
- var re = new RegExp(DIR_SEPARATOR + DIR_SEPARATOR, 'g');
- fullPath = fullPath.replace(re, DIR_SEPARATOR);
-
- // Adjust '..'s by removing parent directories when '..' flows in path.
- var parts = fullPath.split(DIR_SEPARATOR);
- for (var i = 0; i < parts.length; ++i) {
- var part = parts[i];
- if (part === '..') {
- parts[i - 1] = '';
- parts[i] = '';
- }
- }
- fullPath = parts.filter(function(el) {
- return el;
- }).join(DIR_SEPARATOR);
-
- // Add back in leading slash.
- if (fullPath[0] !== DIR_SEPARATOR) {
- fullPath = DIR_SEPARATOR + fullPath;
- }
-
- // Replace './' by current dir. ('./one/./two' -> one/two)
- fullPath = fullPath.replace(/\.\//g, DIR_SEPARATOR);
-
- // Replace '//' with '/'.
- fullPath = fullPath.replace(/\/\//g, DIR_SEPARATOR);
-
- // Replace '/.' with '/'.
- fullPath = fullPath.replace(/\/\./g, DIR_SEPARATOR);
-
- // Remove '/' if it appears on the end.
- if (fullPath[fullPath.length - 1] === DIR_SEPARATOR &&
- fullPath !== DIR_SEPARATOR) {
- fullPath = fullPath.substring(0, fullPath.length - 1);
- }
-
- var storagePath = prefix + fullPath;
- storagePath = decodeURI(storagePath);
- fullPath = decodeURI(fullPath);
-
- return {
- storagePath: storagePath,
- fullPath: fullPath,
- fileName: fullPath.split(DIR_SEPARATOR).pop(),
- fsName: prefix.split(DIR_SEPARATOR).pop()
- };
- }
-
- function fileEntryFromIdbEntry(fileEntry) {
- // IDB won't save methods, so we need re-create the FileEntry.
- var clonedFileEntry = new FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.filesystem);
- clonedFileEntry.file_ = fileEntry.file_;
-
- return clonedFileEntry;
- }
-
- function readAs(what, fullPath, encoding, startPos, endPos, successCallback, errorCallback) {
- exports.getFile(function(fileEntry) {
- var fileReader = new FileReader(),
- blob = fileEntry.file_.blob_.slice(startPos, endPos);
-
- fileReader.onload = function(e) {
- successCallback(e.target.result);
- };
-
- fileReader.onerror = errorCallback;
-
- switch (what) {
- case 'text':
- fileReader.readAsText(blob, encoding);
- break;
- case 'dataURL':
- fileReader.readAsDataURL(blob);
- break;
- case 'arrayBuffer':
- fileReader.readAsArrayBuffer(blob);
- break;
- case 'binaryString':
- fileReader.readAsBinaryString(blob);
- break;
- }
-
- }, errorCallback, [fullPath, null]);
- }
-
-/*** Core logic to handle IDB operations ***/
-
- idb_.open = function(dbName, successCallback, errorCallback) {
- var self = this;
-
- // TODO: FF 12.0a1 isn't liking a db name with : in it.
- var request = indexedDB.open(dbName.replace(':', '_')/*, 1 /*version*/);
-
- request.onerror = errorCallback || onError;
-
- request.onupgradeneeded = function(e) {
- // First open was called or higher db version was used.
-
- // console.log('onupgradeneeded: oldVersion:' + e.oldVersion,
- // 'newVersion:' + e.newVersion);
-
- self.db = e.target.result;
- self.db.onerror = onError;
-
- if (!self.db.objectStoreNames.contains(FILE_STORE_)) {
- self.db.createObjectStore(FILE_STORE_/*,{keyPath: 'id', autoIncrement: true}*/);
- }
- };
-
- request.onsuccess = function(e) {
- self.db = e.target.result;
- self.db.onerror = onError;
- successCallback(e);
- };
-
- request.onblocked = errorCallback || onError;
- };
-
- idb_.close = function() {
- this.db.close();
- this.db = null;
- };
-
- idb_.get = function(fullPath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var tx = this.db.transaction([FILE_STORE_], 'readonly');
-
- var request = tx.objectStore(FILE_STORE_).get(fullPath);
-
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function() {
- successCallback(request.result);
- };
- };
-
- idb_.getAllEntries = function(fullPath, storagePath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var results = [];
-
- if (storagePath[storagePath.length - 1] === DIR_SEPARATOR) {
- storagePath = storagePath.substring(0, storagePath.length - 1);
- }
-
- var range = IDBKeyRange.bound(storagePath + DIR_SEPARATOR + ' ',
- storagePath + DIR_SEPARATOR + String.fromCharCode(unicodeLastChar));
-
- var tx = this.db.transaction([FILE_STORE_], 'readonly');
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function() {
- results = results.filter(function(val) {
- var pathWithoutSlash = val.fullPath;
-
- if (val.fullPath[val.fullPath.length - 1] === DIR_SEPARATOR) {
- pathWithoutSlash = pathWithoutSlash.substr(0, pathWithoutSlash.length - 1);
- }
-
- var valPartsLen = pathWithoutSlash.split(DIR_SEPARATOR).length;
- var fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
-
- /* Input fullPath parameter equals '//' for root folder */
- /* Entries in root folder has valPartsLen equals 2 (see below) */
- if (fullPath[fullPath.length -1] === DIR_SEPARATOR && fullPath.trim().length === 2) {
- fullPathPartsLen = 1;
- } else if (fullPath[fullPath.length -1] === DIR_SEPARATOR) {
- fullPathPartsLen = fullPath.substr(0, fullPath.length - 1).split(DIR_SEPARATOR).length;
- } else {
- fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
- }
-
- if (valPartsLen === fullPathPartsLen + 1) {
- // If this a subfolder and entry is a direct child, include it in
- // the results. Otherwise, it's not an entry of this folder.
- return val;
- } else return false;
- });
-
- successCallback(results);
- };
-
- var request = tx.objectStore(FILE_STORE_).openCursor(range);
-
- request.onsuccess = function(e) {
- var cursor = e.target.result;
- if (cursor) {
- var val = cursor.value;
-
- results.push(val.isFile ? fileEntryFromIdbEntry(val) : new DirectoryEntry(val.name, val.fullPath, val.filesystem));
- cursor['continue']();
- }
- };
- };
-
- idb_['delete'] = function(fullPath, successCallback, errorCallback, isDirectory) {
- if (!idb_.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var tx = this.db.transaction([FILE_STORE_], 'readwrite');
- tx.oncomplete = successCallback;
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function() {
- if (isDirectory) {
- //We delete nested files and folders after deleting parent folder
- //We use ranges: https://developer.mozilla.org/en-US/docs/Web/API/IDBKeyRange
- fullPath = fullPath + DIR_SEPARATOR;
-
- //Range contains all entries in the form fullPath<symbol> where
- //symbol in the range from ' ' to symbol which has code `unicodeLastChar`
- var range = IDBKeyRange.bound(fullPath + ' ', fullPath + String.fromCharCode(unicodeLastChar));
-
- var newTx = this.db.transaction([FILE_STORE_], 'readwrite');
- newTx.oncomplete = successCallback;
- newTx.onabort = errorCallback || onError;
- newTx.objectStore(FILE_STORE_)['delete'](range);
- } else {
- successCallback();
- }
- };
- tx.objectStore(FILE_STORE_)['delete'](fullPath);
- };
-
- idb_.put = function(entry, storagePath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var tx = this.db.transaction([FILE_STORE_], 'readwrite');
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function() {
- // TODO: Error is thrown if we pass the request event back instead.
- successCallback(entry);
- };
-
- tx.objectStore(FILE_STORE_).put(entry, storagePath);
- };
-
- // Global error handler. Errors bubble from request, to transaction, to db.
- function onError(e) {
- switch (e.target.errorCode) {
- case 12:
- console.log('Error - Attempt to open db with a lower version than the ' +
- 'current one.');
- break;
- default:
- console.log('errorCode: ' + e.target.errorCode);
- }
-
- console.log(e, e.code, e.message);
- }
-
-})(module.exports, window);
-
-require("cordova/exec/proxy").add("File", module.exports);
diff --git a/plugins/cordova-plugin-file/src/firefoxos/FileProxy.js b/plugins/cordova-plugin-file/src/firefoxos/FileProxy.js
deleted file mode 100644
index 340ae4bc..00000000
--- a/plugins/cordova-plugin-file/src/firefoxos/FileProxy.js
+++ /dev/null
@@ -1,785 +0,0 @@
-/*
- *
- * 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 LocalFileSystem = require('./LocalFileSystem'),
- FileSystem = require('./FileSystem'),
- FileEntry = require('./FileEntry'),
- FileError = require('./FileError'),
- DirectoryEntry = require('./DirectoryEntry'),
- File = require('./File');
-
-/*
-QUIRKS:
- Does not fail when removing non-empty directories
- Does not support metadata for directories
- Does not support requestAllFileSystems
- Does not support resolveLocalFileSystemURI
- Methods copyTo and moveTo do not support directories
-
- Heavily based on https://github.com/ebidel/idb.filesystem.js
- */
-
-
-(function(exports, global) {
- var indexedDB = global.indexedDB || global.mozIndexedDB;
- if (!indexedDB) {
- throw "Firefox OS File plugin: indexedDB not supported";
- }
-
- var fs_ = null;
-
- var idb_ = {};
- idb_.db = null;
- var FILE_STORE_ = 'entries';
-
- var DIR_SEPARATOR = '/';
- var DIR_OPEN_BOUND = String.fromCharCode(DIR_SEPARATOR.charCodeAt(0) + 1);
-
- var pathsPrefix = {
- // Read-only directory where the application is installed.
- applicationDirectory: location.origin + "/",
- // Where to put app-specific data files.
- dataDirectory: 'file:///persistent/',
- // Cached files that should survive app restarts.
- // Apps should not rely on the OS to delete files in here.
- cacheDirectory: 'file:///temporary/',
- };
-
-/*** Exported functionality ***/
-
- exports.requestFileSystem = function(successCallback, errorCallback, args) {
- var type = args[0];
- var size = args[1];
-
- if (type !== LocalFileSystem.TEMPORARY && type !== LocalFileSystem.PERSISTENT) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var name = type === LocalFileSystem.TEMPORARY ? 'temporary' : 'persistent';
- var storageName = (location.protocol + location.host).replace(/:/g, '_');
-
- var root = new DirectoryEntry('', DIR_SEPARATOR);
- fs_ = new FileSystem(name, root);
-
- idb_.open(storageName, function() {
- successCallback(fs_);
- }, errorCallback);
- };
-
- require('./fileSystems').getFs = function(name, callback) {
- callback(new FileSystem(name, fs_.root));
- };
-
- // list a directory's contents (files and folders).
- exports.readEntries = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
-
- if (!successCallback) {
- throw Error('Expected successCallback argument.');
- }
-
- var path = resolveToFullPath_(fullPath);
-
- idb_.getAllEntries(path.fullPath, path.storagePath, function(entries) {
- successCallback(entries);
- }, errorCallback);
- };
-
- exports.getFile = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
- var path = args[1];
- var options = args[2] || {};
-
- // Create an absolute path if we were handed a relative one.
- path = resolveToFullPath_(fullPath, path);
-
- idb_.get(path.storagePath, function(fileEntry) {
- if (options.create === true && options.exclusive === true && fileEntry) {
- // If create and exclusive are both true, and the path already exists,
- // getFile must fail.
-
- if (errorCallback) {
- errorCallback(FileError.PATH_EXISTS_ERR);
- }
- } else if (options.create === true && !fileEntry) {
- // If create is true, the path doesn't exist, and no other error occurs,
- // getFile must create it as a zero-length file and return a corresponding
- // FileEntry.
- var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
-
- newFileEntry.file_ = new MyFile({
- size: 0,
- name: newFileEntry.name,
- lastModifiedDate: new Date(),
- storagePath: path.storagePath
- });
-
- idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
- } else if (options.create === true && fileEntry) {
- if (fileEntry.isFile) {
- // Overwrite file, delete then create new.
- idb_['delete'](path.storagePath, function() {
- var newFileEntry = new FileEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
-
- newFileEntry.file_ = new MyFile({
- size: 0,
- name: newFileEntry.name,
- lastModifiedDate: new Date(),
- storagePath: path.storagePath
- });
-
- idb_.put(newFileEntry, path.storagePath, successCallback, errorCallback);
- }, errorCallback);
- } else {
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- }
- } else if ((!options.create || options.create === false) && !fileEntry) {
- // If create is not true and the path doesn't exist, getFile must fail.
- if (errorCallback) {
- errorCallback(FileError.NOT_FOUND_ERR);
- }
- } else if ((!options.create || options.create === false) && fileEntry &&
- fileEntry.isDirectory) {
- // If create is not true and the path exists, but is a directory, getFile
- // must fail.
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- } else {
- // Otherwise, if no other error occurs, getFile must return a FileEntry
- // corresponding to path.
-
- successCallback(fileEntryFromIdbEntry(fileEntry));
- }
- }, errorCallback);
- };
-
- exports.getFileMetadata = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
-
- exports.getFile(function(fileEntry) {
- successCallback(new File(fileEntry.file_.name, fileEntry.fullPath, '', fileEntry.file_.lastModifiedDate,
- fileEntry.file_.size));
- }, errorCallback, [fullPath, null]);
- };
-
- exports.getMetadata = function(successCallback, errorCallback, args) {
- exports.getFile(function (fileEntry) {
- successCallback(
- {
- modificationTime: fileEntry.file_.lastModifiedDate,
- size: fileEntry.file_.lastModifiedDate
- });
- }, errorCallback, args);
- };
-
- exports.setMetadata = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
- var metadataObject = args[1];
-
- exports.getFile(function (fileEntry) {
- fileEntry.file_.lastModifiedDate = metadataObject.modificationTime;
- }, errorCallback, [fullPath, null]);
- };
-
- exports.write = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- data = args[1],
- position = args[2],
- isBinary = args[3];
-
- if (!data) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- exports.getFile(function(fileEntry) {
- var blob_ = fileEntry.file_.blob_;
-
- if (!blob_) {
- blob_ = new Blob([data], {type: data.type});
- } else {
- // Calc the head and tail fragments
- var head = blob_.slice(0, position);
- var tail = blob_.slice(position + data.byteLength);
-
- // Calc the padding
- var padding = position - head.size;
- if (padding < 0) {
- padding = 0;
- }
-
- // Do the "write". In fact, a full overwrite of the Blob.
- blob_ = new Blob([head, new Uint8Array(padding), data, tail],
- {type: data.type});
- }
-
- // Set the blob we're writing on this file entry so we can recall it later.
- fileEntry.file_.blob_ = blob_;
- fileEntry.file_.lastModifiedDate = data.lastModifiedDate || null;
- fileEntry.file_.size = blob_.size;
- fileEntry.file_.name = blob_.name;
- fileEntry.file_.type = blob_.type;
-
- idb_.put(fileEntry, fileEntry.file_.storagePath, function() {
- successCallback(data.byteLength);
- }, errorCallback);
- }, errorCallback, [fileName, null]);
- };
-
- exports.readAsText = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- enc = args[1],
- startPos = args[2],
- endPos = args[3];
-
- readAs('text', fileName, enc, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.readAsDataURL = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- startPos = args[1],
- endPos = args[2];
-
- readAs('dataURL', fileName, null, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.readAsBinaryString = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- startPos = args[1],
- endPos = args[2];
-
- readAs('binaryString', fileName, null, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.readAsArrayBuffer = function(successCallback, errorCallback, args) {
- var fileName = args[0],
- startPos = args[1],
- endPos = args[2];
-
- readAs('arrayBuffer', fileName, null, startPos, endPos, successCallback, errorCallback);
- };
-
- exports.removeRecursively = exports.remove = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
-
- // TODO: This doesn't protect against directories that have content in it.
- // Should throw an error instead if the dirEntry is not empty.
- idb_['delete'](fullPath, function() {
- successCallback();
- }, errorCallback);
- };
-
- exports.getDirectory = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
- var path = args[1];
- var options = args[2];
-
- // Create an absolute path if we were handed a relative one.
- path = resolveToFullPath_(fullPath, path);
-
- idb_.get(path.storagePath, function(folderEntry) {
- if (!options) {
- options = {};
- }
-
- if (options.create === true && options.exclusive === true && folderEntry) {
- // If create and exclusive are both true, and the path already exists,
- // getDirectory must fail.
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- } else if (options.create === true && !folderEntry) {
- // If create is true, the path doesn't exist, and no other error occurs,
- // getDirectory must create it as a zero-length file and return a corresponding
- // MyDirectoryEntry.
- var dirEntry = new DirectoryEntry(path.fileName, path.fullPath, new FileSystem(path.fsName, fs_.root));
-
- idb_.put(dirEntry, path.storagePath, successCallback, errorCallback);
- } else if (options.create === true && folderEntry) {
-
- if (folderEntry.isDirectory) {
- // IDB won't save methods, so we need re-create the MyDirectoryEntry.
- successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.fileSystem));
- } else {
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- }
- } else if ((!options.create || options.create === false) && !folderEntry) {
- // Handle root special. It should always exist.
- if (path.fullPath === DIR_SEPARATOR) {
- successCallback(fs_.root);
- return;
- }
-
- // If create is not true and the path doesn't exist, getDirectory must fail.
- if (errorCallback) {
- errorCallback(FileError.NOT_FOUND_ERR);
- }
- } else if ((!options.create || options.create === false) && folderEntry &&
- folderEntry.isFile) {
- // If create is not true and the path exists, but is a file, getDirectory
- // must fail.
- if (errorCallback) {
- errorCallback(FileError.INVALID_MODIFICATION_ERR);
- }
- } else {
- // Otherwise, if no other error occurs, getDirectory must return a
- // MyDirectoryEntry corresponding to path.
-
- // IDB won't' save methods, so we need re-create MyDirectoryEntry.
- successCallback(new DirectoryEntry(folderEntry.name, folderEntry.fullPath, folderEntry.fileSystem));
- }
- }, errorCallback);
- };
-
- exports.getParent = function(successCallback, errorCallback, args) {
- var fullPath = args[0];
-
- if (fullPath === DIR_SEPARATOR) {
- successCallback(fs_.root);
- return;
- }
-
- var pathArr = fullPath.split(DIR_SEPARATOR);
- pathArr.pop();
- var namesa = pathArr.pop();
- var path = pathArr.join(DIR_SEPARATOR);
-
- exports.getDirectory(successCallback, errorCallback, [path, namesa, {create: false}]);
- };
-
- exports.copyTo = function(successCallback, errorCallback, args) {
- var srcPath = args[0];
- var parentFullPath = args[1];
- var name = args[2];
-
- // Read src file
- exports.getFile(function(srcFileEntry) {
-
- // Create dest file
- exports.getFile(function(dstFileEntry) {
-
- exports.write(function() {
- successCallback(dstFileEntry);
- }, errorCallback, [dstFileEntry.file_.storagePath, srcFileEntry.file_.blob_, 0]);
-
- }, errorCallback, [parentFullPath, name, {create: true}]);
-
- }, errorCallback, [srcPath, null]);
- };
-
- exports.moveTo = function(successCallback, errorCallback, args) {
- var srcPath = args[0];
- var parentFullPath = args[1];
- var name = args[2];
-
- exports.copyTo(function (fileEntry) {
-
- exports.remove(function () {
- successCallback(fileEntry);
- }, errorCallback, [srcPath]);
-
- }, errorCallback, args);
- };
-
- exports.resolveLocalFileSystemURI = function(successCallback, errorCallback, args) {
- var path = args[0];
-
- // Ignore parameters
- if (path.indexOf('?') !== -1) {
- path = String(path).split("?")[0];
- }
-
- // support for encodeURI
- if (/\%5/g.test(path)) {
- path = decodeURI(path);
- }
-
- if (path.indexOf(pathsPrefix.dataDirectory) === 0) {
- path = path.substring(pathsPrefix.dataDirectory.length - 1);
-
- exports.requestFileSystem(function(fs) {
- fs.root.getFile(path, {create: false}, successCallback, function() {
- fs.root.getDirectory(path, {create: false}, successCallback, errorCallback);
- });
- }, errorCallback, [LocalFileSystem.PERSISTENT]);
- } else if (path.indexOf(pathsPrefix.cacheDirectory) === 0) {
- path = path.substring(pathsPrefix.cacheDirectory.length - 1);
-
- exports.requestFileSystem(function(fs) {
- fs.root.getFile(path, {create: false}, successCallback, function() {
- fs.root.getDirectory(path, {create: false}, successCallback, errorCallback);
- });
- }, errorCallback, [LocalFileSystem.TEMPORARY]);
- } else if (path.indexOf(pathsPrefix.applicationDirectory) === 0) {
- path = path.substring(pathsPrefix.applicationDirectory.length);
-
- var xhr = new XMLHttpRequest();
- xhr.open("GET", path, true);
- xhr.onreadystatechange = function () {
- if (xhr.status === 200 && xhr.readyState === 4) {
- exports.requestFileSystem(function(fs) {
- fs.name = location.hostname;
- fs.root.getFile(path, {create: true}, writeFile, errorCallback);
- }, errorCallback, [LocalFileSystem.PERSISTENT]);
- }
- };
-
- xhr.onerror = function () {
- errorCallback && errorCallback(FileError.NOT_READABLE_ERR);
- };
-
- xhr.send();
- } else {
- errorCallback && errorCallback(FileError.NOT_FOUND_ERR);
- }
-
- function writeFile(entry) {
- entry.createWriter(function (fileWriter) {
- fileWriter.onwriteend = function (evt) {
- if (!evt.target.error) {
- entry.filesystemName = location.hostname;
- successCallback(entry);
- }
- };
- fileWriter.onerror = function () {
- errorCallback && errorCallback(FileError.NOT_READABLE_ERR);
- };
- fileWriter.write(new Blob([xhr.response]));
- }, errorCallback);
- }
- };
-
- exports.requestAllPaths = function(successCallback) {
- successCallback(pathsPrefix);
- };
-
-/*** Helpers ***/
-
- /**
- * Interface to wrap the native File interface.
- *
- * This interface is necessary for creating zero-length (empty) files,
- * something the Filesystem API allows you to do. Unfortunately, File's
- * constructor cannot be called directly, making it impossible to instantiate
- * an empty File in JS.
- *
- * @param {Object} opts Initial values.
- * @constructor
- */
- function MyFile(opts) {
- var blob_ = new Blob();
-
- this.size = opts.size || 0;
- this.name = opts.name || '';
- this.type = opts.type || '';
- this.lastModifiedDate = opts.lastModifiedDate || null;
- this.storagePath = opts.storagePath || '';
-
- // Need some black magic to correct the object's size/name/type based on the
- // blob that is saved.
- Object.defineProperty(this, 'blob_', {
- enumerable: true,
- get: function() {
- return blob_;
- },
- set: function(val) {
- blob_ = val;
- this.size = blob_.size;
- this.name = blob_.name;
- this.type = blob_.type;
- this.lastModifiedDate = blob_.lastModifiedDate;
- }.bind(this)
- });
- }
-
- MyFile.prototype.constructor = MyFile;
-
- // When saving an entry, the fullPath should always lead with a slash and never
- // end with one (e.g. a directory). Also, resolve '.' and '..' to an absolute
- // one. This method ensures path is legit!
- function resolveToFullPath_(cwdFullPath, path) {
- path = path || '';
- var fullPath = path;
- var prefix = '';
-
- cwdFullPath = cwdFullPath || DIR_SEPARATOR;
- if (cwdFullPath.indexOf(FILESYSTEM_PREFIX) === 0) {
- prefix = cwdFullPath.substring(0, cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
- cwdFullPath = cwdFullPath.substring(cwdFullPath.indexOf(DIR_SEPARATOR, FILESYSTEM_PREFIX.length));
- }
-
- var relativePath = path[0] !== DIR_SEPARATOR;
- if (relativePath) {
- fullPath = cwdFullPath;
- if (cwdFullPath != DIR_SEPARATOR) {
- fullPath += DIR_SEPARATOR + path;
- } else {
- fullPath += path;
- }
- }
-
- // Adjust '..'s by removing parent directories when '..' flows in path.
- var parts = fullPath.split(DIR_SEPARATOR);
- for (var i = 0; i < parts.length; ++i) {
- var part = parts[i];
- if (part == '..') {
- parts[i - 1] = '';
- parts[i] = '';
- }
- }
- fullPath = parts.filter(function(el) {
- return el;
- }).join(DIR_SEPARATOR);
-
- // Add back in leading slash.
- if (fullPath[0] !== DIR_SEPARATOR) {
- fullPath = DIR_SEPARATOR + fullPath;
- }
-
- // Replace './' by current dir. ('./one/./two' -> one/two)
- fullPath = fullPath.replace(/\.\//g, DIR_SEPARATOR);
-
- // Replace '//' with '/'.
- fullPath = fullPath.replace(/\/\//g, DIR_SEPARATOR);
-
- // Replace '/.' with '/'.
- fullPath = fullPath.replace(/\/\./g, DIR_SEPARATOR);
-
- // Remove '/' if it appears on the end.
- if (fullPath[fullPath.length - 1] == DIR_SEPARATOR &&
- fullPath != DIR_SEPARATOR) {
- fullPath = fullPath.substring(0, fullPath.length - 1);
- }
-
- return {
- storagePath: prefix + fullPath,
- fullPath: fullPath,
- fileName: fullPath.split(DIR_SEPARATOR).pop(),
- fsName: prefix.split(DIR_SEPARATOR).pop()
- };
- }
-
- function fileEntryFromIdbEntry(fileEntry) {
- // IDB won't save methods, so we need re-create the FileEntry.
- var clonedFileEntry = new FileEntry(fileEntry.name, fileEntry.fullPath, fileEntry.fileSystem);
- clonedFileEntry.file_ = fileEntry.file_;
-
- return clonedFileEntry;
- }
-
- function readAs(what, fullPath, encoding, startPos, endPos, successCallback, errorCallback) {
- exports.getFile(function(fileEntry) {
- var fileReader = new FileReader(),
- blob = fileEntry.file_.blob_.slice(startPos, endPos);
-
- fileReader.onload = function(e) {
- successCallback(e.target.result);
- };
-
- fileReader.onerror = errorCallback;
-
- switch (what) {
- case 'text':
- fileReader.readAsText(blob, encoding);
- break;
- case 'dataURL':
- fileReader.readAsDataURL(blob);
- break;
- case 'arrayBuffer':
- fileReader.readAsArrayBuffer(blob);
- break;
- case 'binaryString':
- fileReader.readAsBinaryString(blob);
- break;
- }
-
- }, errorCallback, [fullPath, null]);
- }
-
-/*** Core logic to handle IDB operations ***/
-
- idb_.open = function(dbName, successCallback, errorCallback) {
- var self = this;
-
- // TODO: FF 12.0a1 isn't liking a db name with : in it.
- var request = indexedDB.open(dbName.replace(':', '_')/*, 1 /*version*/);
-
- request.onerror = errorCallback || onError;
-
- request.onupgradeneeded = function(e) {
- // First open was called or higher db version was used.
-
- // console.log('onupgradeneeded: oldVersion:' + e.oldVersion,
- // 'newVersion:' + e.newVersion);
-
- self.db = e.target.result;
- self.db.onerror = onError;
-
- if (!self.db.objectStoreNames.contains(FILE_STORE_)) {
- var store = self.db.createObjectStore(FILE_STORE_/*,{keyPath: 'id', autoIncrement: true}*/);
- }
- };
-
- request.onsuccess = function(e) {
- self.db = e.target.result;
- self.db.onerror = onError;
- successCallback(e);
- };
-
- request.onblocked = errorCallback || onError;
- };
-
- idb_.close = function() {
- this.db.close();
- this.db = null;
- };
-
- idb_.get = function(fullPath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var tx = this.db.transaction([FILE_STORE_], 'readonly');
-
- //var request = tx.objectStore(FILE_STORE_).get(fullPath);
- var range = IDBKeyRange.bound(fullPath, fullPath + DIR_OPEN_BOUND,
- false, true);
- var request = tx.objectStore(FILE_STORE_).get(range);
-
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function(e) {
- successCallback(request.result);
- };
- };
-
- idb_.getAllEntries = function(fullPath, storagePath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var results = [];
-
- if (storagePath[storagePath.length - 1] === DIR_SEPARATOR) {
- storagePath = storagePath.substring(0, storagePath.length - 1);
- }
-
- range = IDBKeyRange.bound(
- storagePath + DIR_SEPARATOR, storagePath + DIR_OPEN_BOUND, false, true);
-
- var tx = this.db.transaction([FILE_STORE_], 'readonly');
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function(e) {
- results = results.filter(function(val) {
- var valPartsLen = val.fullPath.split(DIR_SEPARATOR).length;
- var fullPathPartsLen = fullPath.split(DIR_SEPARATOR).length;
-
- if (fullPath === DIR_SEPARATOR && valPartsLen < fullPathPartsLen + 1) {
- // Hack to filter out entries in the root folder. This is inefficient
- // because reading the entires of fs.root (e.g. '/') returns ALL
- // results in the database, then filters out the entries not in '/'.
- return val;
- } else if (fullPath !== DIR_SEPARATOR &&
- valPartsLen === fullPathPartsLen + 1) {
- // If this a subfolder and entry is a direct child, include it in
- // the results. Otherwise, it's not an entry of this folder.
- return val;
- }
- });
-
- successCallback(results);
- };
-
- var request = tx.objectStore(FILE_STORE_).openCursor(range);
-
- request.onsuccess = function(e) {
- var cursor = e.target.result;
- if (cursor) {
- var val = cursor.value;
-
- results.push(val.isFile ? fileEntryFromIdbEntry(val) : new DirectoryEntry(val.name, val.fullPath, val.fileSystem));
- cursor['continue']();
- }
- };
- };
-
- idb_['delete'] = function(fullPath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var tx = this.db.transaction([FILE_STORE_], 'readwrite');
- tx.oncomplete = successCallback;
- tx.onabort = errorCallback || onError;
-
- //var request = tx.objectStore(FILE_STORE_).delete(fullPath);
- var range = IDBKeyRange.bound(
- fullPath, fullPath + DIR_OPEN_BOUND, false, true);
- tx.objectStore(FILE_STORE_)['delete'](range);
- };
-
- idb_.put = function(entry, storagePath, successCallback, errorCallback) {
- if (!this.db) {
- errorCallback && errorCallback(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
- var tx = this.db.transaction([FILE_STORE_], 'readwrite');
- tx.onabort = errorCallback || onError;
- tx.oncomplete = function(e) {
- // TODO: Error is thrown if we pass the request event back instead.
- successCallback(entry);
- };
-
- tx.objectStore(FILE_STORE_).put(entry, storagePath);
- };
-
- // Global error handler. Errors bubble from request, to transaction, to db.
- function onError(e) {
- switch (e.target.errorCode) {
- case 12:
- console.log('Error - Attempt to open db with a lower version than the ' +
- 'current one.');
- break;
- default:
- console.log('errorCode: ' + e.target.errorCode);
- }
-
- console.log(e, e.code, e.message);
- }
-
-// Clean up.
-// TODO: Is there a place for this?
-// global.addEventListener('beforeunload', function(e) {
-// idb_.db && idb_.db.close();
-// }, false);
-
-})(module.exports, window);
-
-require("cordova/exec/proxy").add("File", module.exports);
diff --git a/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.h b/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.h
deleted file mode 100644
index e09e2250..00000000
--- a/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- 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.
- */
-
-#import "CDVFile.h"
-
-extern NSString* const kCDVAssetsLibraryPrefix;
-extern NSString* const kCDVAssetsLibraryScheme;
-
-@interface CDVAssetLibraryFilesystem : NSObject<CDVFileSystem> {
-}
-
-- (id) initWithName:(NSString *)name;
-
-@end
diff --git a/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.m b/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.m
deleted file mode 100644
index 0b95fac3..00000000
--- a/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.m
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- 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.
- */
-
-#import "CDVFile.h"
-#import "CDVAssetLibraryFilesystem.h"
-#import <Cordova/CDV.h>
-#import <AssetsLibrary/ALAsset.h>
-#import <AssetsLibrary/ALAssetRepresentation.h>
-#import <AssetsLibrary/ALAssetsLibrary.h>
-#import <MobileCoreServices/MobileCoreServices.h>
-
-NSString* const kCDVAssetsLibraryPrefix = @"assets-library://";
-NSString* const kCDVAssetsLibraryScheme = @"assets-library";
-
-@implementation CDVAssetLibraryFilesystem
-@synthesize name=_name, urlTransformer;
-
-
-/*
- The CDVAssetLibraryFilesystem works with resources which are identified
- by iOS as
- asset-library://<path>
- and represents them internally as URLs of the form
- cdvfile://localhost/assets-library/<path>
- */
-
-- (NSURL *)assetLibraryURLForLocalURL:(CDVFilesystemURL *)url
-{
- if ([url.url.scheme isEqualToString:kCDVFilesystemURLPrefix]) {
- NSString *path = [[url.url absoluteString] substringFromIndex:[@"cdvfile://localhost/assets-library" length]];
- return [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@", path]];
- }
- return url.url;
-}
-
-- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
-{
- NSDictionary* entry = [self makeEntryForLocalURL:url];
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
-}
-
-- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
- return [self makeEntryForPath:url.fullPath isDirectory:NO];
-}
-
-- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
-{
- NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
- NSString* lastPart = [fullPath lastPathComponent];
- if (isDir && ![fullPath hasSuffix:@"/"]) {
- fullPath = [fullPath stringByAppendingString:@"/"];
- }
- [dirEntry setObject:[NSNumber numberWithBool:!isDir] forKey:@"isFile"];
- [dirEntry setObject:[NSNumber numberWithBool:isDir] forKey:@"isDirectory"];
- [dirEntry setObject:fullPath forKey:@"fullPath"];
- [dirEntry setObject:lastPart forKey:@"name"];
- [dirEntry setObject:self.name forKey: @"filesystemName"];
-
- NSURL* nativeURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@",fullPath]];
- if (self.urlTransformer) {
- nativeURL = self.urlTransformer(nativeURL);
- }
- dirEntry[@"nativeURL"] = [nativeURL absoluteString];
-
- return dirEntry;
-}
-
-/* helper function to get the mimeType from the file extension
- * IN:
- * NSString* fullPath - filename (may include path)
- * OUT:
- * NSString* the mime type as type/subtype. nil if not able to determine
- */
-+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
-{
- NSString* mimeType = nil;
-
- if (fullPath) {
- CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
- if (typeId) {
- mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
- if (!mimeType) {
- // special case for m4a
- if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
- mimeType = @"audio/mp4";
- } else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
- mimeType = @"audio/wav";
- } else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
- mimeType = @"text/css";
- }
- }
- CFRelease(typeId);
- }
- }
- return mimeType;
-}
-
-- (id)initWithName:(NSString *)name
-{
- if (self) {
- _name = name;
- }
- return self;
-}
-
-- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
-{
- // return unsupported result for assets-library URLs
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"getFile not supported for assets-library URLs."];
-}
-
-- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
-{
- // we don't (yet?) support getting the parent of an asset
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR];
-}
-
-- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
-{
- // setMetadata doesn't make sense for asset library files
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
-}
-
-- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
-{
- // return error for assets-library URLs
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
-}
-
-- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
-{
- // return error for assets-library URLs
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"removeRecursively not supported for assets-library URLs."];
-}
-
-- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
-{
- // return unsupported result for assets-library URLs
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"readEntries not supported for assets-library URLs."];
-}
-
-- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
-{
- // assets-library files can't be truncated
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
-}
-
-- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
-{
- // text can't be written into assets-library files
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
-}
-
-- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
-{
- // Copying to an assets library file is not doable, since we can't write it.
- CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
- callback(result);
-}
-
-- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
-{
- NSString *path = nil;
- if ([[url.url scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
- path = [url.url path];
- } else {
- path = url.fullPath;
- }
- if ([path hasSuffix:@"/"]) {
- path = [path substringToIndex:([path length]-1)];
- }
- return path;
-}
-
-- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
-{
- ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
- if (asset) {
- // We have the asset! Get the data and send it off.
- ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
- NSUInteger size = (end > start) ? (end - start) : [assetRepresentation size];
- Byte* buffer = (Byte*)malloc(size);
- NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:start length:size error:nil];
- NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
- NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
-
- callback(data, MIMEType, NO_ERROR);
- } else {
- callback(nil, nil, NOT_FOUND_ERR);
- }
- };
-
- ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
- // Retrieving the asset failed for some reason. Send the appropriate error.
- NSLog(@"Error: %@", error);
- callback(nil, nil, SECURITY_ERR);
- };
-
- ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
- [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
-}
-
-- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
-{
- // In this case, we need to use an asynchronous method to retrieve the file.
- // Because of this, we can't just assign to `result` and send it at the end of the method.
- // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
- ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
- if (asset) {
- // We have the asset! Populate the dictionary and send it off.
- NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
- ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
- [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:[assetRepresentation size]] forKey:@"size"];
- [fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
- NSString* filename = [assetRepresentation filename];
- [fileInfo setObject:filename forKey:@"name"];
- [fileInfo setObject:[CDVAssetLibraryFilesystem getMimeTypeFromPath:filename] forKey:@"type"];
- NSDate* creationDate = [asset valueForProperty:ALAssetPropertyDate];
- NSNumber* msDate = [NSNumber numberWithDouble:[creationDate timeIntervalSince1970] * 1000];
- [fileInfo setObject:msDate forKey:@"lastModifiedDate"];
-
- callback([CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]);
- } else {
- // We couldn't find the asset. Send the appropriate error.
- callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]);
- }
- };
- ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
- // Retrieving the asset failed for some reason. Send the appropriate error.
- callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]);
- };
-
- ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
- [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
- return;
-}
-@end
diff --git a/plugins/cordova-plugin-file/src/ios/CDVFile.h b/plugins/cordova-plugin-file/src/ios/CDVFile.h
deleted file mode 100644
index 33630c03..00000000
--- a/plugins/cordova-plugin-file/src/ios/CDVFile.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- 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.
- */
-
-#import <Foundation/Foundation.h>
-#import <Cordova/CDVPlugin.h>
-
-NSString* const kCDVAssetsLibraryPrefix;
-NSString* const kCDVFilesystemURLPrefix;
-
-enum CDVFileError {
- NO_ERROR = 0,
- NOT_FOUND_ERR = 1,
- SECURITY_ERR = 2,
- ABORT_ERR = 3,
- NOT_READABLE_ERR = 4,
- ENCODING_ERR = 5,
- NO_MODIFICATION_ALLOWED_ERR = 6,
- INVALID_STATE_ERR = 7,
- SYNTAX_ERR = 8,
- INVALID_MODIFICATION_ERR = 9,
- QUOTA_EXCEEDED_ERR = 10,
- TYPE_MISMATCH_ERR = 11,
- PATH_EXISTS_ERR = 12
-};
-typedef int CDVFileError;
-
-@interface CDVFilesystemURL : NSObject {
- NSURL *_url;
- NSString *_fileSystemName;
- NSString *_fullPath;
-}
-
-- (id) initWithString:(NSString*)strURL;
-- (id) initWithURL:(NSURL*)URL;
-+ (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL;
-+ (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL;
-
-- (NSString *)absoluteURL;
-
-@property (atomic) NSURL *url;
-@property (atomic) NSString *fileSystemName;
-@property (atomic) NSString *fullPath;
-
-@end
-
-@interface CDVFilesystemURLProtocol : NSURLProtocol
-@end
-
-@protocol CDVFileSystem
-- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url;
-- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options;
-- (CDVPluginResult *)getParentForURL:(CDVFilesystemURL *)localURI;
-- (CDVPluginResult *)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options;
-- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI;
-- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI;
-- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI;
-- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos;
-- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend;
-- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback;
-- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback;
-- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback;
-
-- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url;
-- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir;
-
-@property (nonatomic,strong) NSString *name;
-@property (nonatomic, copy) NSURL*(^urlTransformer)(NSURL*);
-
-@optional
-- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURI;
-- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path;
-
-@end
-
-@interface CDVFile : CDVPlugin {
- NSString* rootDocsPath;
- NSString* appDocsPath;
- NSString* appLibraryPath;
- NSString* appTempPath;
-
- NSMutableArray* fileSystems_;
- BOOL userHasAllowed;
-}
-
-- (NSNumber*)checkFreeDiskSpace:(NSString*)appPath;
-- (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir;
-- (NSDictionary *)makeEntryForURL:(NSURL *)URL;
-- (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath;
-
-- (NSObject<CDVFileSystem> *)filesystemForURL:(CDVFilesystemURL *)localURL;
-
-/* Native Registration API */
-- (void)registerFilesystem:(NSObject<CDVFileSystem> *)fs;
-- (NSObject<CDVFileSystem> *)fileSystemByName:(NSString *)fsName;
-
-/* Exec API */
-- (void)requestFileSystem:(CDVInvokedUrlCommand*)command;
-- (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command;
-- (void)getDirectory:(CDVInvokedUrlCommand*)command;
-- (void)getFile:(CDVInvokedUrlCommand*)command;
-- (void)getParent:(CDVInvokedUrlCommand*)command;
-- (void)removeRecursively:(CDVInvokedUrlCommand*)command;
-- (void)remove:(CDVInvokedUrlCommand*)command;
-- (void)copyTo:(CDVInvokedUrlCommand*)command;
-- (void)moveTo:(CDVInvokedUrlCommand*)command;
-- (void)getFileMetadata:(CDVInvokedUrlCommand*)command;
-- (void)readEntries:(CDVInvokedUrlCommand*)command;
-- (void)readAsText:(CDVInvokedUrlCommand*)command;
-- (void)readAsDataURL:(CDVInvokedUrlCommand*)command;
-- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command;
-- (void)write:(CDVInvokedUrlCommand*)command;
-- (void)testFileExists:(CDVInvokedUrlCommand*)command;
-- (void)testDirectoryExists:(CDVInvokedUrlCommand*)command;
-- (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command;
-- (void)truncate:(CDVInvokedUrlCommand*)command;
-- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy;
-
-/* Compatibilty with older File API */
-- (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
-- (NSDictionary *)getDirectoryEntry:(NSString *)target isDirectory:(BOOL)bDirRequest;
-
-/* Conversion between filesystem paths and URLs */
-- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)URL;
-
-/* Internal methods for testing */
-- (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command;
-
-@property (nonatomic, strong) NSString* rootDocsPath;
-@property (nonatomic, strong) NSString* appDocsPath;
-@property (nonatomic, strong) NSString* appLibraryPath;
-@property (nonatomic, strong) NSString* appTempPath;
-@property (nonatomic, strong) NSString* persistentPath;
-@property (nonatomic, strong) NSString* temporaryPath;
-@property (nonatomic, strong) NSMutableArray* fileSystems;
-
-@property BOOL userHasAllowed;
-
-@end
-
-#define kW3FileTemporary @"temporary"
-#define kW3FilePersistent @"persistent"
diff --git a/plugins/cordova-plugin-file/src/ios/CDVFile.m b/plugins/cordova-plugin-file/src/ios/CDVFile.m
deleted file mode 100644
index eec8978e..00000000
--- a/plugins/cordova-plugin-file/src/ios/CDVFile.m
+++ /dev/null
@@ -1,1092 +0,0 @@
-/*
- 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.
- */
-
-#import <Cordova/CDV.h>
-#import "CDVFile.h"
-#import "CDVLocalFilesystem.h"
-#import "CDVAssetLibraryFilesystem.h"
-#import <objc/message.h>
-
-CDVFile *filePlugin = nil;
-
-extern NSString * const NSURLIsExcludedFromBackupKey __attribute__((weak_import));
-
-#ifndef __IPHONE_5_1
- NSString* const NSURLIsExcludedFromBackupKey = @"NSURLIsExcludedFromBackupKey";
-#endif
-
-NSString* const kCDVFilesystemURLPrefix = @"cdvfile";
-
-@implementation CDVFilesystemURL
-@synthesize url=_url;
-@synthesize fileSystemName=_fileSystemName;
-@synthesize fullPath=_fullPath;
-
-- (id) initWithString:(NSString *)strURL
-{
- if ( self = [super init] ) {
- NSURL *decodedURL = [NSURL URLWithString:strURL];
- return [self initWithURL:decodedURL];
- }
- return nil;
-}
-
--(id) initWithURL:(NSURL *)URL
-{
- if ( self = [super init] ) {
- _url = URL;
- _fileSystemName = [self filesystemNameForLocalURI:URL];
- _fullPath = [self fullPathForLocalURI:URL];
- }
- return self;
-}
-
-/*
- * IN
- * NSString localURI
- * OUT
- * NSString FileSystem Name for this URI, or nil if it is not recognized.
- */
-- (NSString *)filesystemNameForLocalURI:(NSURL *)uri
-{
- if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
- NSArray *pathComponents = [uri pathComponents];
- if (pathComponents != nil && pathComponents.count > 1) {
- return [pathComponents objectAtIndex:1];
- }
- } else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
- return @"assets-library";
- }
- return nil;
-}
-
-/*
- * IN
- * NSString localURI
- * OUT
- * NSString fullPath component suitable for an Entry object.
- * The incoming URI should be properly escaped. The returned fullPath is unescaped.
- */
-- (NSString *)fullPathForLocalURI:(NSURL *)uri
-{
- if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
- NSString *path = [uri path];
- if ([uri query]) {
- path = [NSString stringWithFormat:@"%@?%@", path, [uri query]];
- }
- NSRange slashRange = [path rangeOfString:@"/" options:0 range:NSMakeRange(1, path.length-1)];
- if (slashRange.location == NSNotFound) {
- return @"";
- }
- return [path substringFromIndex:slashRange.location];
- } else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
- return [[uri absoluteString] substringFromIndex:[kCDVAssetsLibraryScheme length]+2];
- }
- return nil;
-}
-
-+ (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL
-{
- return [[CDVFilesystemURL alloc] initWithString:strURL];
-}
-
-+ (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL
-{
- return [[CDVFilesystemURL alloc] initWithURL:URL];
-}
-
-- (NSString *)absoluteURL
-{
- return [NSString stringWithFormat:@"cdvfile://localhost/%@%@", self.fileSystemName, self.fullPath];
-}
-
-@end
-
-@implementation CDVFilesystemURLProtocol
-
-+ (BOOL)canInitWithRequest:(NSURLRequest*)request
-{
- NSURL* url = [request URL];
- return [[url scheme] isEqualToString:kCDVFilesystemURLPrefix];
-}
-
-+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
-{
- return request;
-}
-
-+ (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
-{
- return [[[requestA URL] resourceSpecifier] isEqualToString:[[requestB URL] resourceSpecifier]];
-}
-
-- (void)startLoading
-{
- CDVFilesystemURL* url = [CDVFilesystemURL fileSystemURLWithURL:[[self request] URL]];
- NSObject<CDVFileSystem> *fs = [filePlugin filesystemForURL:url];
- [fs readFileAtURL:url start:0 end:-1 callback:^void(NSData *data, NSString *mimetype, CDVFileError error) {
- NSMutableDictionary* responseHeaders = [[NSMutableDictionary alloc] init];
- responseHeaders[@"Cache-Control"] = @"no-cache";
-
- if (!error) {
- responseHeaders[@"Content-Type"] = mimetype;
- NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url.url statusCode:200 HTTPVersion:@"HTTP/1.1"headerFields:responseHeaders];
- [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
- [[self client] URLProtocol:self didLoadData:data];
- [[self client] URLProtocolDidFinishLoading:self];
- } else {
- NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url.url statusCode:404 HTTPVersion:@"HTTP/1.1"headerFields:responseHeaders];
- [[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
- [[self client] URLProtocolDidFinishLoading:self];
- }
- }];
-}
-
-- (void)stopLoading
-{}
-
-- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
- willCacheResponse:(NSCachedURLResponse*)cachedResponse {
- return nil;
-}
-
-@end
-
-
-@implementation CDVFile
-
-@synthesize rootDocsPath, appDocsPath, appLibraryPath, appTempPath, userHasAllowed, fileSystems=fileSystems_;
-
-- (void)registerFilesystem:(NSObject<CDVFileSystem> *)fs {
- __weak CDVFile* weakSelf = self;
- SEL sel = NSSelectorFromString(@"urlTransformer");
- // for backwards compatibility - we check if this property is there
- // we create a wrapper block because the urlTransformer property
- // on the commandDelegate might be set dynamically at a future time
- // (and not dependent on plugin loading order)
- if ([self.commandDelegate respondsToSelector:sel]) {
- fs.urlTransformer = ^NSURL*(NSURL* urlToTransform) {
- // grab the block from the commandDelegate
- NSURL* (^urlTransformer)(NSURL*) = ((id(*)(id, SEL))objc_msgSend)(weakSelf.commandDelegate, sel);
- // if block is not null, we call it
- if (urlTransformer) {
- return urlTransformer(urlToTransform);
- } else { // else we return the same url
- return urlToTransform;
- }
- };
- }
- [fileSystems_ addObject:fs];
-}
-
-- (NSObject<CDVFileSystem> *)fileSystemByName:(NSString *)fsName
-{
- if (self.fileSystems != nil) {
- for (NSObject<CDVFileSystem> *fs in self.fileSystems) {
- if ([fs.name isEqualToString:fsName]) {
- return fs;
- }
- }
- }
- return nil;
-
-}
-
-- (NSObject<CDVFileSystem> *)filesystemForURL:(CDVFilesystemURL *)localURL {
- if (localURL.fileSystemName == nil) return nil;
- @try {
- return [self fileSystemByName:localURL.fileSystemName];
- }
- @catch (NSException *e) {
- return nil;
- }
-}
-
-- (NSArray *)getExtraFileSystemsPreference:(UIViewController *)vc
-{
- NSString *filesystemsStr = nil;
- if([self.viewController isKindOfClass:[CDVViewController class]]) {
- CDVViewController *vc = (CDVViewController *)self.viewController;
- NSDictionary *settings = [vc settings];
- filesystemsStr = [settings[@"iosextrafilesystems"] lowercaseString];
- }
- if (!filesystemsStr) {
- filesystemsStr = @"library,library-nosync,documents,documents-nosync,cache,bundle,root";
- }
- return [filesystemsStr componentsSeparatedByString:@","];
-}
-
-- (void)makeNonSyncable:(NSString*)path {
- [[NSFileManager defaultManager] createDirectoryAtPath:path
- withIntermediateDirectories:YES
- attributes:nil
- error:nil];
- NSURL* url = [NSURL fileURLWithPath:path];
- [url setResourceValue: [NSNumber numberWithBool: YES]
- forKey: NSURLIsExcludedFromBackupKey error:nil];
-
-}
-
-- (void)registerExtraFileSystems:(NSArray *)filesystems fromAvailableSet:(NSDictionary *)availableFileSystems
-{
- NSMutableSet *installedFilesystems = [[NSMutableSet alloc] initWithCapacity:7];
-
- /* Build non-syncable directories as necessary */
- for (NSString *nonSyncFS in @[@"library-nosync", @"documents-nosync"]) {
- if ([filesystems containsObject:nonSyncFS]) {
- [self makeNonSyncable:availableFileSystems[nonSyncFS]];
- }
- }
-
- /* Register filesystems in order */
- for (NSString *fsName in filesystems) {
- if (![installedFilesystems containsObject:fsName]) {
- NSString *fsRoot = availableFileSystems[fsName];
- if (fsRoot) {
- [filePlugin registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:fsName root:fsRoot]];
- [installedFilesystems addObject:fsName];
- } else {
- NSLog(@"Unrecognized extra filesystem identifier: %@", fsName);
- }
- }
- }
-}
-
-- (NSDictionary *)getAvailableFileSystems
-{
- NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
- NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
- return @{
- @"library": libPath,
- @"library-nosync": [libPath stringByAppendingPathComponent:@"NoCloud"],
- @"documents": docPath,
- @"documents-nosync": [docPath stringByAppendingPathComponent:@"NoCloud"],
- @"cache": [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0],
- @"bundle": [[NSBundle mainBundle] bundlePath],
- @"root": @"/"
- };
-}
-
-- (void)pluginInitialize
-{
- filePlugin = self;
- [NSURLProtocol registerClass:[CDVFilesystemURLProtocol class]];
-
- fileSystems_ = [[NSMutableArray alloc] initWithCapacity:3];
-
- // Get the Library directory path
- NSArray* paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
- self.appLibraryPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"files"];
-
- // Get the Temporary directory path
- self.appTempPath = [NSTemporaryDirectory()stringByStandardizingPath]; // remove trailing slash from NSTemporaryDirectory()
-
- // Get the Documents directory path
- paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- self.rootDocsPath = [paths objectAtIndex:0];
- self.appDocsPath = [self.rootDocsPath stringByAppendingPathComponent:@"files"];
-
-
- NSString *location = nil;
- if([self.viewController isKindOfClass:[CDVViewController class]]) {
- CDVViewController *vc = (CDVViewController *)self.viewController;
- NSMutableDictionary *settings = vc.settings;
- location = [[settings objectForKey:@"iospersistentfilelocation"] lowercaseString];
- }
- if (location == nil) {
- // Compatibilty by default (if the config preference is not set, or
- // if we're not embedded in a CDVViewController somehow.)
- location = @"compatibility";
- }
-
- NSError *error;
- if ([[NSFileManager defaultManager] createDirectoryAtPath:self.appTempPath
- withIntermediateDirectories:YES
- attributes:nil
- error:&error]) {
- [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"temporary" root:self.appTempPath]];
- } else {
- NSLog(@"Unable to create temporary directory: %@", error);
- }
- if ([location isEqualToString:@"library"]) {
- if ([[NSFileManager defaultManager] createDirectoryAtPath:self.appLibraryPath
- withIntermediateDirectories:YES
- attributes:nil
- error:&error]) {
- [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"persistent" root:self.appLibraryPath]];
- } else {
- NSLog(@"Unable to create library directory: %@", error);
- }
- } else if ([location isEqualToString:@"compatibility"]) {
- /*
- * Fall-back to compatibility mode -- this is the logic implemented in
- * earlier versions of this plugin, and should be maintained here so
- * that apps which were originally deployed with older versions of the
- * plugin can continue to provide access to files stored under those
- * versions.
- */
- [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"persistent" root:self.rootDocsPath]];
- } else {
- NSAssert(false,
- @"File plugin configuration error: Please set iosPersistentFileLocation in config.xml to one of \"library\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
- }
- [self registerFilesystem:[[CDVAssetLibraryFilesystem alloc] initWithName:@"assets-library"]];
-
- [self registerExtraFileSystems:[self getExtraFileSystemsPreference:self.viewController]
- fromAvailableSet:[self getAvailableFileSystems]];
-
-}
-
-- (CDVFilesystemURL *)fileSystemURLforArg:(NSString *)urlArg
-{
- CDVFilesystemURL* ret = nil;
- if ([urlArg hasPrefix:@"file://"]) {
- /* This looks like a file url. Get the path, and see if any handlers recognize it. */
- NSURL *fileURL = [NSURL URLWithString:urlArg];
- NSURL *resolvedFileURL = [fileURL URLByResolvingSymlinksInPath];
- NSString *path = [resolvedFileURL path];
- ret = [self fileSystemURLforLocalPath:path];
- } else {
- ret = [CDVFilesystemURL fileSystemURLWithString:urlArg];
- }
- return ret;
-}
-
-- (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath
-{
- CDVFilesystemURL *localURL = nil;
- NSUInteger shortestFullPath = 0;
-
- // Try all installed filesystems, in order. Return the most match url.
- for (id object in self.fileSystems) {
- if ([object respondsToSelector:@selector(URLforFilesystemPath:)]) {
- CDVFilesystemURL *url = [object URLforFilesystemPath:localPath];
- if (url){
- // A shorter fullPath would imply that the filesystem is a better match for the local path
- if (!localURL || ([[url fullPath] length] < shortestFullPath)) {
- localURL = url;
- shortestFullPath = [[url fullPath] length];
- }
- }
- }
- }
- return localURL;
-}
-
-- (NSNumber*)checkFreeDiskSpace:(NSString*)appPath
-{
- NSFileManager* fMgr = [[NSFileManager alloc] init];
-
- NSError* __autoreleasing pError = nil;
-
- NSDictionary* pDict = [fMgr attributesOfFileSystemForPath:appPath error:&pError];
- NSNumber* pNumAvail = (NSNumber*)[pDict objectForKey:NSFileSystemFreeSize];
-
- return pNumAvail;
-}
-
-/* Request the File System info
- *
- * IN:
- * arguments[0] - type (number as string)
- * TEMPORARY = 0, PERSISTENT = 1;
- * arguments[1] - size
- *
- * OUT:
- * Dictionary representing FileSystem object
- * name - the human readable directory name
- * root = DirectoryEntry object
- * bool isDirectory
- * bool isFile
- * string name
- * string fullPath
- * fileSystem = FileSystem object - !! ignored because creates circular reference !!
- */
-
-- (void)requestFileSystem:(CDVInvokedUrlCommand*)command
-{
- // arguments
- NSString* strType = [command argumentAtIndex:0];
- unsigned long long size = [[command argumentAtIndex:1] longLongValue];
-
- int type = [strType intValue];
- CDVPluginResult* result = nil;
-
- if (type > self.fileSystems.count) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR];
- NSLog(@"No filesystem of type requested");
- } else {
- NSString* fullPath = @"/";
- // check for avail space for size request
- NSNumber* pNumAvail = [self checkFreeDiskSpace:self.rootDocsPath];
- // NSLog(@"Free space: %@", [NSString stringWithFormat:@"%qu", [ pNumAvail unsignedLongLongValue ]]);
- if (pNumAvail && ([pNumAvail unsignedLongLongValue] < size)) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:QUOTA_EXCEEDED_ERR];
- } else {
- NSObject<CDVFileSystem> *rootFs = [self.fileSystems objectAtIndex:type];
- if (rootFs == nil) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR];
- NSLog(@"No filesystem of type requested");
- } else {
- NSMutableDictionary* fileSystem = [NSMutableDictionary dictionaryWithCapacity:2];
- [fileSystem setObject:rootFs.name forKey:@"name"];
- NSDictionary* dirEntry = [self makeEntryForPath:fullPath fileSystemName:rootFs.name isDirectory:YES];
- [fileSystem setObject:dirEntry forKey:@"root"];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileSystem];
- }
- }
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-
-- (void)requestAllFileSystems:(CDVInvokedUrlCommand*)command
-{
- NSMutableArray* ret = [[NSMutableArray alloc] init];
- for (NSObject<CDVFileSystem>* root in fileSystems_) {
- [ret addObject:[self makeEntryForPath:@"/" fileSystemName:root.name isDirectory:YES]];
- }
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:ret];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-- (void)requestAllPaths:(CDVInvokedUrlCommand*)command
-{
- NSString* libPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0];
- NSString* libPathSync = [libPath stringByAppendingPathComponent:@"Cloud"];
- NSString* libPathNoSync = [libPath stringByAppendingPathComponent:@"NoCloud"];
- NSString* docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
- NSString* storagePath = [libPath stringByDeletingLastPathComponent];
- NSString* cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
-
- // Create the directories if necessary.
- [[NSFileManager defaultManager] createDirectoryAtPath:libPathSync withIntermediateDirectories:YES attributes:nil error:nil];
- [[NSFileManager defaultManager] createDirectoryAtPath:libPathNoSync withIntermediateDirectories:YES attributes:nil error:nil];
- // Mark NoSync as non-iCloud.
- [[NSURL fileURLWithPath:libPathNoSync] setResourceValue: [NSNumber numberWithBool: YES]
- forKey: NSURLIsExcludedFromBackupKey error:nil];
-
- NSDictionary* ret = @{
- @"applicationDirectory": [[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]] absoluteString],
- @"applicationStorageDirectory": [[NSURL fileURLWithPath:storagePath] absoluteString],
- @"dataDirectory": [[NSURL fileURLWithPath:libPathNoSync] absoluteString],
- @"syncedDataDirectory": [[NSURL fileURLWithPath:libPathSync] absoluteString],
- @"documentsDirectory": [[NSURL fileURLWithPath:docPath] absoluteString],
- @"cacheDirectory": [[NSURL fileURLWithPath:cachePath] absoluteString],
- @"tempDirectory": [[NSURL fileURLWithPath:NSTemporaryDirectory()] absoluteString]
- };
-
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:ret];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/* Creates and returns a dictionary representing an Entry Object
- *
- * IN:
- * NSString* fullPath of the entry
- * int fsType - FileSystem type
- * BOOL isDirectory - YES if this is a directory, NO if is a file
- * OUT:
- * NSDictionary* Entry object
- * bool as NSNumber isDirectory
- * bool as NSNumber isFile
- * NSString* name - last part of path
- * NSString* fullPath
- * NSString* filesystemName - FileSystem name -- actual filesystem will be created on the JS side if necessary, to avoid
- * creating circular reference (FileSystem contains DirectoryEntry which contains FileSystem.....!!)
- */
-- (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir
-{
- NSObject<CDVFileSystem> *fs = [self fileSystemByName:fsName];
- return [fs makeEntryForPath:fullPath isDirectory:isDir];
-}
-
-- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)localURL
-{
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURL];
- return [fs makeEntryForLocalURL:localURL];
-}
-
-- (NSDictionary *)makeEntryForURL:(NSURL *)URL
-{
- CDVFilesystemURL* fsURL = [self fileSystemURLforArg:[URL absoluteString]];
- return [self makeEntryForLocalURL:fsURL];
-}
-
-/*
- * Given a URI determine the File System information associated with it and return an appropriate W3C entry object
- * IN
- * NSString* localURI: Should be an escaped local filesystem URI
- * OUT
- * Entry object
- * bool isDirectory
- * bool isFile
- * string name
- * string fullPath
- * fileSystem = FileSystem object - !! ignored because creates circular reference FileSystem contains DirectoryEntry which contains FileSystem.....!!
- */
-- (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command
-{
- // arguments
- NSString* localURIstr = [command argumentAtIndex:0];
- CDVPluginResult* result;
-
- localURIstr = [self encodePath:localURIstr]; //encode path before resolving
- CDVFilesystemURL* inputURI = [self fileSystemURLforArg:localURIstr];
-
- if (inputURI == nil || inputURI.fileSystemName == nil) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR];
- } else {
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:inputURI];
- if (fs == nil) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR];
- } else {
- result = [fs entryForLocalURI:inputURI];
- }
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-//encode path with percent escapes
--(NSString *)encodePath:(NSString *)path
-{
- NSString *decodedPath = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //decode incase it's already encoded to avoid encoding twice
- return [decodedPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
-}
-
-
-/* Part of DirectoryEntry interface, creates or returns the specified directory
- * IN:
- * NSString* localURI - local filesystem URI for this directory
- * NSString* path - directory to be created/returned; may be full path or relative path
- * NSDictionary* - Flags object
- * boolean as NSNumber create -
- * if create is true and directory does not exist, create dir and return directory entry
- * if create is true and exclusive is true and directory does exist, return error
- * if create is false and directory does not exist, return error
- * if create is false and the path represents a file, return error
- * boolean as NSNumber exclusive - used in conjunction with create
- * if exclusive is true and create is true - specifies failure if directory already exists
- *
- *
- */
-- (void)getDirectory:(CDVInvokedUrlCommand*)command
-{
- NSMutableArray* arguments = [NSMutableArray arrayWithArray:command.arguments];
- NSMutableDictionary* options = nil;
-
- if ([arguments count] >= 3) {
- options = [command argumentAtIndex:2 withDefault:nil];
- }
- // add getDir to options and call getFile()
- if (options != nil) {
- options = [NSMutableDictionary dictionaryWithDictionary:options];
- } else {
- options = [NSMutableDictionary dictionaryWithCapacity:1];
- }
- [options setObject:[NSNumber numberWithInt:1] forKey:@"getDir"];
- if ([arguments count] >= 3) {
- [arguments replaceObjectAtIndex:2 withObject:options];
- } else {
- [arguments addObject:options];
- }
- CDVInvokedUrlCommand* subCommand =
- [[CDVInvokedUrlCommand alloc] initWithArguments:arguments
- callbackId:command.callbackId
- className:command.className
- methodName:command.methodName];
-
- [self getFile:subCommand];
-}
-
-/* Part of DirectoryEntry interface, creates or returns the specified file
- * IN:
- * NSString* baseURI - local filesytem URI for the base directory to search
- * NSString* requestedPath - file to be created/returned; may be absolute path or relative path
- * NSDictionary* options - Flags object
- * boolean as NSNumber create -
- * if create is true and file does not exist, create file and return File entry
- * if create is true and exclusive is true and file does exist, return error
- * if create is false and file does not exist, return error
- * if create is false and the path represents a directory, return error
- * boolean as NSNumber exclusive - used in conjunction with create
- * if exclusive is true and create is true - specifies failure if file already exists
- */
-- (void)getFile:(CDVInvokedUrlCommand*)command
-{
- NSString* baseURIstr = [command argumentAtIndex:0];
- CDVFilesystemURL* baseURI = [self fileSystemURLforArg:baseURIstr];
- NSString* requestedPath = [command argumentAtIndex:1];
- NSDictionary* options = [command argumentAtIndex:2 withDefault:nil];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:baseURI];
- CDVPluginResult* result = [fs getFileForURL:baseURI requestedPath:requestedPath options:options];
-
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/*
- * Look up the parent Entry containing this Entry.
- * If this Entry is the root of its filesystem, its parent is itself.
- * IN:
- * NSArray* arguments
- * 0 - NSString* localURI
- * NSMutableDictionary* options
- * empty
- */
-- (void)getParent:(CDVInvokedUrlCommand*)command
-{
- // arguments are URL encoded
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
- CDVPluginResult* result = [fs getParentForURL:localURI];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/*
- * set MetaData of entry
- * Currently we only support "com.apple.MobileBackup" (boolean)
- */
-- (void)setMetadata:(CDVInvokedUrlCommand*)command
-{
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSDictionary* options = [command argumentAtIndex:1 withDefault:nil];
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
- CDVPluginResult* result = [fs setMetadataForURL:localURI withObject:options];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/* removes the directory or file entry
- * IN:
- * NSArray* arguments
- * 0 - NSString* localURI
- *
- * returns NO_MODIFICATION_ALLOWED_ERR if is top level directory or no permission to delete dir
- * returns INVALID_MODIFICATION_ERR if is non-empty dir or asset library file
- * returns NOT_FOUND_ERR if file or dir is not found
-*/
-- (void)remove:(CDVInvokedUrlCommand*)command
-{
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- CDVPluginResult* result = nil;
-
- if ([localURI.fullPath isEqualToString:@""]) {
- // error if try to remove top level (documents or tmp) dir
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
- } else {
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
- result = [fs removeFileAtURL:localURI];
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/* recursively removes the directory
- * IN:
- * NSArray* arguments
- * 0 - NSString* localURI
- *
- * returns NO_MODIFICATION_ALLOWED_ERR if is top level directory or no permission to delete dir
- * returns NOT_FOUND_ERR if file or dir is not found
- */
-- (void)removeRecursively:(CDVInvokedUrlCommand*)command
-{
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- CDVPluginResult* result = nil;
-
- if ([localURI.fullPath isEqualToString:@""]) {
- // error if try to remove top level (documents or tmp) dir
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
- } else {
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
- result = [fs recursiveRemoveFileAtURL:localURI];
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-- (void)copyTo:(CDVInvokedUrlCommand*)command
-{
- [self doCopyMove:command isCopy:YES];
-}
-
-- (void)moveTo:(CDVInvokedUrlCommand*)command
-{
- [self doCopyMove:command isCopy:NO];
-}
-
-/* Copy/move a file or directory to a new location
- * IN:
- * NSArray* arguments
- * 0 - NSString* URL of entry to copy
- * 1 - NSString* URL of the directory into which to copy/move the entry
- * 2 - Optionally, the new name of the entry, defaults to the current name
- * BOOL - bCopy YES if copy, NO if move
- */
-- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy
-{
- NSArray* arguments = command.arguments;
-
- // arguments
- NSString* srcURLstr = [command argumentAtIndex:0];
- NSString* destURLstr = [command argumentAtIndex:1];
-
- CDVPluginResult *result;
-
- if (!srcURLstr || !destURLstr) {
- // either no source or no destination provided
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- return;
- }
-
- CDVFilesystemURL* srcURL = [self fileSystemURLforArg:srcURLstr];
- CDVFilesystemURL* destURL = [self fileSystemURLforArg:destURLstr];
-
- NSObject<CDVFileSystem> *srcFs = [self filesystemForURL:srcURL];
- NSObject<CDVFileSystem> *destFs = [self filesystemForURL:destURL];
-
- // optional argument; use last component from srcFullPath if new name not provided
- NSString* newName = ([arguments count] > 2) ? [command argumentAtIndex:2] : [srcURL.url lastPathComponent];
- if ([newName rangeOfString:@":"].location != NSNotFound) {
- // invalid chars in new name
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- return;
- }
-
- [destFs copyFileToURL:destURL withName:newName fromFileSystem:srcFs atURL:srcURL copy:bCopy callback:^(CDVPluginResult* result) {
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }];
-
-}
-
-- (void)getFileMetadata:(CDVInvokedUrlCommand*)command
-{
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
-
- [fs getFileMetadataForURL:localURI callback:^(CDVPluginResult* result) {
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }];
-}
-
-- (void)readEntries:(CDVInvokedUrlCommand*)command
-{
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
- CDVPluginResult *result = [fs readEntriesAtURL:localURI];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/* read and return file data
- * IN:
- * NSArray* arguments
- * 0 - NSString* fullPath
- * 1 - NSString* encoding
- * 2 - NSString* start
- * 3 - NSString* end
- */
-- (void)readAsText:(CDVInvokedUrlCommand*)command
-{
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSString* encoding = [command argumentAtIndex:1];
- NSInteger start = [[command argumentAtIndex:2] integerValue];
- NSInteger end = [[command argumentAtIndex:3] integerValue];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
-
- if (fs == nil) {
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- return;
- }
-
- // TODO: implement
- if ([@"UTF-8" caseInsensitiveCompare : encoding] != NSOrderedSame) {
- NSLog(@"Only UTF-8 encodings are currently supported by readAsText");
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- return;
- }
-
- [self.commandDelegate runInBackground:^ {
- [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
- CDVPluginResult* result = nil;
- if (data != nil) {
- NSString* str = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSUTF8StringEncoding freeWhenDone:NO];
- // Check that UTF8 conversion did not fail.
- if (str != nil) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:str];
- result.associatedObject = data;
- } else {
- errorCode = ENCODING_ERR;
- }
- }
- if (result == nil) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }];
- }];
-}
-
-/* Read content of text file and return as base64 encoded data url.
- * IN:
- * NSArray* arguments
- * 0 - NSString* fullPath
- * 1 - NSString* start
- * 2 - NSString* end
- *
- * Determines the mime type from the file extension, returns ENCODING_ERR if mimetype can not be determined.
- */
-
-- (void)readAsDataURL:(CDVInvokedUrlCommand*)command
-{
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSInteger start = [[command argumentAtIndex:1] integerValue];
- NSInteger end = [[command argumentAtIndex:2] integerValue];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
-
- [self.commandDelegate runInBackground:^ {
- [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
- CDVPluginResult* result = nil;
- if (data != nil) {
- SEL selector = NSSelectorFromString(@"cdv_base64EncodedString");
- if (![data respondsToSelector:selector]) {
- selector = NSSelectorFromString(@"base64EncodedString");
- }
- id (*func)(id, SEL) = (void *)[data methodForSelector:selector];
- NSString* b64Str = func(data, selector);
- NSString* output = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, b64Str];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:output];
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }];
- }];
-}
-
-/* Read content of text file and return as an arraybuffer
- * IN:
- * NSArray* arguments
- * 0 - NSString* fullPath
- * 1 - NSString* start
- * 2 - NSString* end
- */
-
-- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command
-{
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSInteger start = [[command argumentAtIndex:1] integerValue];
- NSInteger end = [[command argumentAtIndex:2] integerValue];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
-
- [self.commandDelegate runInBackground:^ {
- [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
- CDVPluginResult* result = nil;
- if (data != nil) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:data];
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }];
- }];
-}
-
-- (void)readAsBinaryString:(CDVInvokedUrlCommand*)command
-{
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- NSInteger start = [[command argumentAtIndex:1] integerValue];
- NSInteger end = [[command argumentAtIndex:2] integerValue];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
-
- [self.commandDelegate runInBackground:^ {
- [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
- CDVPluginResult* result = nil;
- if (data != nil) {
- NSString* payload = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSASCIIStringEncoding freeWhenDone:NO];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
- result.associatedObject = data;
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
- }];
- }];
-}
-
-
-- (void)truncate:(CDVInvokedUrlCommand*)command
-{
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- unsigned long long pos = (unsigned long long)[[command argumentAtIndex:1] longLongValue];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
- CDVPluginResult *result = [fs truncateFileAtURL:localURI atPosition:pos];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-/* write
- * IN:
- * NSArray* arguments
- * 0 - NSString* localURI of file to write to
- * 1 - NSString* or NSData* data to write
- * 2 - NSNumber* position to begin writing
- */
-- (void)write:(CDVInvokedUrlCommand*)command
-{
- [self.commandDelegate runInBackground:^ {
- NSString* callbackId = command.callbackId;
-
- // arguments
- CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
- id argData = [command argumentAtIndex:1];
- unsigned long long pos = (unsigned long long)[[command argumentAtIndex:2] longLongValue];
-
- NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
-
-
- [fs truncateFileAtURL:localURI atPosition:pos];
- CDVPluginResult *result;
- if ([argData isKindOfClass:[NSString class]]) {
- NSData *encData = [argData dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
- result = [fs writeToFileAtURL:localURI withData:encData append:YES];
- } else if ([argData isKindOfClass:[NSData class]]) {
- result = [fs writeToFileAtURL:localURI withData:argData append:YES];
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid parameter type"];
- }
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
- }];
-}
-
-#pragma mark Methods for converting between URLs and paths
-
-- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURL
-{
- for (NSObject<CDVFileSystem> *fs in self.fileSystems) {
- if ([fs.name isEqualToString:localURL.fileSystemName]) {
- if ([fs respondsToSelector:@selector(filesystemPathForURL:)]) {
- return [fs filesystemPathForURL:localURL];
- }
- }
- }
- return nil;
-}
-
-#pragma mark Undocumented Filesystem API
-
-- (void)testFileExists:(CDVInvokedUrlCommand*)command
-{
- // arguments
- NSString* argPath = [command argumentAtIndex:0];
-
- // Get the file manager
- NSFileManager* fMgr = [NSFileManager defaultManager];
- NSString* appFile = argPath; // [ self getFullPath: argPath];
-
- BOOL bExists = [fMgr fileExistsAtPath:appFile];
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(bExists ? 1 : 0)];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-- (void)testDirectoryExists:(CDVInvokedUrlCommand*)command
-{
- // arguments
- NSString* argPath = [command argumentAtIndex:0];
-
- // Get the file manager
- NSFileManager* fMgr = [[NSFileManager alloc] init];
- NSString* appFile = argPath; // [self getFullPath: argPath];
- BOOL bIsDir = NO;
- BOOL bExists = [fMgr fileExistsAtPath:appFile isDirectory:&bIsDir];
-
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:((bExists && bIsDir) ? 1 : 0)];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-// Returns number of bytes available via callback
-- (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command
-{
- // no arguments
-
- NSNumber* pNumAvail = [self checkFreeDiskSpace:self.appDocsPath];
-
- NSString* strFreeSpace = [NSString stringWithFormat:@"%qu", [pNumAvail unsignedLongLongValue]];
- // NSLog(@"Free space is %@", strFreeSpace );
-
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:strFreeSpace];
-
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-#pragma mark Compatibility with older File API
-
-- (NSString*)getMimeTypeFromPath:(NSString*)fullPath
-{
- return [CDVLocalFilesystem getMimeTypeFromPath:fullPath];
-}
-
-- (NSDictionary *)getDirectoryEntry:(NSString *)localPath isDirectory:(BOOL)bDirRequest
-{
- CDVFilesystemURL *localURL = [self fileSystemURLforLocalPath:localPath];
- return [self makeEntryForPath:localURL.fullPath fileSystemName:localURL.fileSystemName isDirectory:bDirRequest];
-}
-
-#pragma mark Internal methods for testing
-// Internal methods for testing: Get the on-disk location of a local filesystem url.
-// [Currently used for testing file-transfer]
-
-- (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command
-{
- CDVFilesystemURL* localURL = [self fileSystemURLforArg:command.arguments[0]];
-
- NSString* fsPath = [self filesystemPathForURL:localURL];
- CDVPluginResult* result;
- if (fsPath) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:fsPath];
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot resolve URL to a file"];
- }
- [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-}
-
-@end
diff --git a/plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.h b/plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.h
deleted file mode 100644
index a0186c85..00000000
--- a/plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- 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.
- */
-
-#import "CDVFile.h"
-
-@interface CDVLocalFilesystem : NSObject<CDVFileSystem> {
- NSString *_name;
- NSString *_fsRoot;
-}
-
-- (id) initWithName:(NSString *)name root:(NSString *)fsRoot;
-+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath;
-
-@property (nonatomic,strong) NSString *fsRoot;
-
-@end
diff --git a/plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.m b/plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.m
deleted file mode 100644
index 72bc421e..00000000
--- a/plugins/cordova-plugin-file/src/ios/CDVLocalFilesystem.m
+++ /dev/null
@@ -1,734 +0,0 @@
-/*
- 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.
- */
-
-#import "CDVFile.h"
-#import "CDVLocalFilesystem.h"
-#import <Cordova/CDV.h>
-#import <MobileCoreServices/MobileCoreServices.h>
-#import <sys/xattr.h>
-
-@implementation CDVLocalFilesystem
-@synthesize name=_name, fsRoot=_fsRoot, urlTransformer;
-
-- (id) initWithName:(NSString *)name root:(NSString *)fsRoot
-{
- if (self) {
- _name = name;
- _fsRoot = fsRoot;
- }
- return self;
-}
-
-/*
- * IN
- * NSString localURI
- * OUT
- * CDVPluginResult result containing a file or directoryEntry for the localURI, or an error if the
- * URI represents a non-existent path, or is unrecognized or otherwise malformed.
- */
-- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
-{
- CDVPluginResult* result = nil;
- NSDictionary* entry = [self makeEntryForLocalURL:url];
- if (entry) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
- } else {
- // return NOT_FOUND_ERR
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- }
- return result;
-}
-- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
- NSString *path = [self filesystemPathForURL:url];
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
- BOOL isDir = NO;
- // see if exists and is file or dir
- BOOL bExists = [fileMgr fileExistsAtPath:path isDirectory:&isDir];
- if (bExists) {
- return [self makeEntryForPath:url.fullPath isDirectory:isDir];
- } else {
- return nil;
- }
-}
-- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
-{
- NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
- NSString* lastPart = [[self stripQueryParametersFromPath:fullPath] lastPathComponent];
- if (isDir && ![fullPath hasSuffix:@"/"]) {
- fullPath = [fullPath stringByAppendingString:@"/"];
- }
- [dirEntry setObject:[NSNumber numberWithBool:!isDir] forKey:@"isFile"];
- [dirEntry setObject:[NSNumber numberWithBool:isDir] forKey:@"isDirectory"];
- [dirEntry setObject:fullPath forKey:@"fullPath"];
- [dirEntry setObject:lastPart forKey:@"name"];
- [dirEntry setObject:self.name forKey: @"filesystemName"];
-
- NSURL* nativeURL = [NSURL fileURLWithPath:[self filesystemPathForFullPath:fullPath]];
- if (self.urlTransformer) {
- nativeURL = self.urlTransformer(nativeURL);
- }
-
- dirEntry[@"nativeURL"] = [nativeURL absoluteString];
-
- return dirEntry;
-}
-
-- (NSString *)stripQueryParametersFromPath:(NSString *)fullPath
-{
- NSRange questionMark = [fullPath rangeOfString:@"?"];
- if (questionMark.location != NSNotFound) {
- return [fullPath substringWithRange:NSMakeRange(0,questionMark.location)];
- }
- return fullPath;
-}
-
-- (NSString *)filesystemPathForFullPath:(NSString *)fullPath
-{
- NSString *path = nil;
- NSString *strippedFullPath = [self stripQueryParametersFromPath:fullPath];
- path = [NSString stringWithFormat:@"%@%@", self.fsRoot, strippedFullPath];
- if ([path length] > 1 && [path hasSuffix:@"/"]) {
- path = [path substringToIndex:([path length]-1)];
- }
- return path;
-}
-/*
- * IN
- * NSString localURI
- * OUT
- * NSString full local filesystem path for the represented file or directory, or nil if no such path is possible
- * The file or directory does not necessarily have to exist. nil is returned if the filesystem type is not recognized,
- * or if the URL is malformed.
- * The incoming URI should be properly escaped (no raw spaces, etc. URI percent-encoding is expected).
- */
-- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
-{
- return [self filesystemPathForFullPath:url.fullPath];
-}
-
-- (CDVFilesystemURL *)URLforFullPath:(NSString *)fullPath
-{
- if (fullPath) {
- NSString* escapedPath = [fullPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- if ([fullPath hasPrefix:@"/"]) {
- return [CDVFilesystemURL fileSystemURLWithString:[NSString stringWithFormat:@"%@://localhost/%@%@", kCDVFilesystemURLPrefix, self.name, escapedPath]];
- }
- return [CDVFilesystemURL fileSystemURLWithString:[NSString stringWithFormat:@"%@://localhost/%@/%@", kCDVFilesystemURLPrefix, self.name, escapedPath]];
- }
- return nil;
-}
-
-- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path
-{
- return [self URLforFullPath:[self fullPathForFileSystemPath:path]];
-
-}
-
-- (NSString *)normalizePath:(NSString *)rawPath
-{
- // If this is an absolute path, the first path component will be '/'. Skip it if that's the case
- BOOL isAbsolutePath = [rawPath hasPrefix:@"/"];
- if (isAbsolutePath) {
- rawPath = [rawPath substringFromIndex:1];
- }
- NSMutableArray *components = [NSMutableArray arrayWithArray:[rawPath pathComponents]];
- for (int index = 0; index < [components count]; ++index) {
- if ([[components objectAtIndex:index] isEqualToString:@".."]) {
- [components removeObjectAtIndex:index];
- if (index > 0) {
- [components removeObjectAtIndex:index-1];
- --index;
- }
- }
- }
-
- if (isAbsolutePath) {
- return [NSString stringWithFormat:@"/%@", [components componentsJoinedByString:@"/"]];
- } else {
- return [components componentsJoinedByString:@"/"];
- }
-
-
-}
-
-- (BOOL)valueForKeyIsNumber:(NSDictionary*)dict key:(NSString*)key
-{
- BOOL bNumber = NO;
- NSObject* value = dict[key];
- if (value) {
- bNumber = [value isKindOfClass:[NSNumber class]];
- }
- return bNumber;
-}
-
-- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
-{
- CDVPluginResult* result = nil;
- BOOL bDirRequest = NO;
- BOOL create = NO;
- BOOL exclusive = NO;
- int errorCode = 0; // !!! risky - no error code currently defined for 0
-
- if ([self valueForKeyIsNumber:options key:@"create"]) {
- create = [(NSNumber*)[options valueForKey:@"create"] boolValue];
- }
- if ([self valueForKeyIsNumber:options key:@"exclusive"]) {
- exclusive = [(NSNumber*)[options valueForKey:@"exclusive"] boolValue];
- }
- if ([self valueForKeyIsNumber:options key:@"getDir"]) {
- // this will not exist for calls directly to getFile but will have been set by getDirectory before calling this method
- bDirRequest = [(NSNumber*)[options valueForKey:@"getDir"] boolValue];
- }
- // see if the requested path has invalid characters - should we be checking for more than just ":"?
- if ([requestedPath rangeOfString:@":"].location != NSNotFound) {
- errorCode = ENCODING_ERR;
- } else {
- // Build new fullPath for the requested resource.
- // We concatenate the two paths together, and then scan the resulting string to remove
- // parent ("..") references. Any parent references at the beginning of the string are
- // silently removed.
- NSString *combinedPath = [baseURI.fullPath stringByAppendingPathComponent:requestedPath];
- combinedPath = [self normalizePath:combinedPath];
- CDVFilesystemURL* requestedURL = [self URLforFullPath:combinedPath];
-
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
- BOOL bIsDir;
- BOOL bExists = [fileMgr fileExistsAtPath:[self filesystemPathForURL:requestedURL] isDirectory:&bIsDir];
- if (bExists && (create == NO) && (bIsDir == !bDirRequest)) {
- // path exists and is not of requested type - return TYPE_MISMATCH_ERR
- errorCode = TYPE_MISMATCH_ERR;
- } else if (!bExists && (create == NO)) {
- // path does not exist and create is false - return NOT_FOUND_ERR
- errorCode = NOT_FOUND_ERR;
- } else if (bExists && (create == YES) && (exclusive == YES)) {
- // file/dir already exists and exclusive and create are both true - return PATH_EXISTS_ERR
- errorCode = PATH_EXISTS_ERR;
- } else {
- // if bExists and create == YES - just return data
- // if bExists and create == NO - just return data
- // if !bExists and create == YES - create and return data
- BOOL bSuccess = YES;
- NSError __autoreleasing* pError = nil;
- if (!bExists && (create == YES)) {
- if (bDirRequest) {
- // create the dir
- bSuccess = [fileMgr createDirectoryAtPath:[self filesystemPathForURL:requestedURL] withIntermediateDirectories:NO attributes:nil error:&pError];
- } else {
- // create the empty file
- bSuccess = [fileMgr createFileAtPath:[self filesystemPathForURL:requestedURL] contents:nil attributes:nil];
- }
- }
- if (!bSuccess) {
- errorCode = ABORT_ERR;
- if (pError) {
- NSLog(@"error creating directory: %@", [pError localizedDescription]);
- }
- } else {
- // NSLog(@"newly created file/dir (%@) exists: %d", reqFullPath, [fileMgr fileExistsAtPath:reqFullPath]);
- // file existed or was created
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self makeEntryForPath:requestedURL.fullPath isDirectory:bDirRequest]];
- }
- } // are all possible conditions met?
- }
-
- if (errorCode > 0) {
- // create error callback
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
- return result;
-
-}
-
-- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
-{
- CDVPluginResult* result = nil;
- CDVFilesystemURL *newURI = nil;
- if ([localURI.fullPath isEqualToString:@""]) {
- // return self
- newURI = localURI;
- } else {
- newURI = [CDVFilesystemURL fileSystemURLWithURL:[localURI.url URLByDeletingLastPathComponent]]; /* TODO: UGLY - FIX */
- }
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
- BOOL bIsDir;
- BOOL bExists = [fileMgr fileExistsAtPath:[self filesystemPathForURL:newURI] isDirectory:&bIsDir];
- if (bExists) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self makeEntryForPath:newURI.fullPath isDirectory:bIsDir]];
- } else {
- // invalid path or file does not exist
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- }
- return result;
-}
-
-- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
-{
- BOOL ok = NO;
-
- NSString* filePath = [self filesystemPathForURL:localURI];
- // we only care about this iCloud key for now.
- // set to 1/true to skip backup, set to 0/false to back it up (effectively removing the attribute)
- NSString* iCloudBackupExtendedAttributeKey = @"com.apple.MobileBackup";
- id iCloudBackupExtendedAttributeValue = [options objectForKey:iCloudBackupExtendedAttributeKey];
-
- if ((iCloudBackupExtendedAttributeValue != nil) && [iCloudBackupExtendedAttributeValue isKindOfClass:[NSNumber class]]) {
- if (IsAtLeastiOSVersion(@"5.1")) {
- NSURL* url = [NSURL fileURLWithPath:filePath];
- NSError* __autoreleasing error = nil;
-
- ok = [url setResourceValue:[NSNumber numberWithBool:[iCloudBackupExtendedAttributeValue boolValue]] forKey:NSURLIsExcludedFromBackupKey error:&error];
- } else { // below 5.1 (deprecated - only really supported in 5.01)
- u_int8_t value = [iCloudBackupExtendedAttributeValue intValue];
- if (value == 0) { // remove the attribute (allow backup, the default)
- ok = (removexattr([filePath fileSystemRepresentation], [iCloudBackupExtendedAttributeKey cStringUsingEncoding:NSUTF8StringEncoding], 0) == 0);
- } else { // set the attribute (skip backup)
- ok = (setxattr([filePath fileSystemRepresentation], [iCloudBackupExtendedAttributeKey cStringUsingEncoding:NSUTF8StringEncoding], &value, sizeof(value), 0, 0) == 0);
- }
- }
- }
-
- if (ok) {
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
- } else {
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
- }
-}
-
-/* remove the file or directory (recursively)
- * IN:
- * NSString* fullPath - the full path to the file or directory to be removed
- * NSString* callbackId
- * called from remove and removeRecursively - check all pubic api specific error conditions (dir not empty, etc) before calling
- */
-
-- (CDVPluginResult*)doRemove:(NSString*)fullPath
-{
- CDVPluginResult* result = nil;
- BOOL bSuccess = NO;
- NSError* __autoreleasing pError = nil;
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
-
- @try {
- bSuccess = [fileMgr removeItemAtPath:fullPath error:&pError];
- if (bSuccess) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
- } else {
- // see if we can give a useful error
- CDVFileError errorCode = ABORT_ERR;
- NSLog(@"error removing filesystem entry at %@: %@", fullPath, [pError localizedDescription]);
- if ([pError code] == NSFileNoSuchFileError) {
- errorCode = NOT_FOUND_ERR;
- } else if ([pError code] == NSFileWriteNoPermissionError) {
- errorCode = NO_MODIFICATION_ALLOWED_ERR;
- }
-
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
- } @catch(NSException* e) { // NSInvalidArgumentException if path is . or ..
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:SYNTAX_ERR];
- }
-
- return result;
-}
-
-- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
-{
- NSString *fileSystemPath = [self filesystemPathForURL:localURI];
-
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
- BOOL bIsDir = NO;
- BOOL bExists = [fileMgr fileExistsAtPath:fileSystemPath isDirectory:&bIsDir];
- if (!bExists) {
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- }
- if (bIsDir && ([[fileMgr contentsOfDirectoryAtPath:fileSystemPath error:nil] count] != 0)) {
- // dir is not empty
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
- }
- return [self doRemove:fileSystemPath];
-}
-
-- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
-{
- NSString *fileSystemPath = [self filesystemPathForURL:localURI];
- return [self doRemove:fileSystemPath];
-}
-
-/*
- * IN
- * NSString localURI
- * OUT
- * NSString full local filesystem path for the represented file or directory, or nil if no such path is possible
- * The file or directory does not necessarily have to exist. nil is returned if the filesystem type is not recognized,
- * or if the URL is malformed.
- * The incoming URI should be properly escaped (no raw spaces, etc. URI percent-encoding is expected).
- */
-- (NSString *)fullPathForFileSystemPath:(NSString *)fsPath
-{
- if ([fsPath hasPrefix:self.fsRoot]) {
- return [fsPath substringFromIndex:[self.fsRoot length]];
- }
- return nil;
-}
-
-
-- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
-{
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
- NSError* __autoreleasing error = nil;
- NSString *fileSystemPath = [self filesystemPathForURL:localURI];
-
- NSArray* contents = [fileMgr contentsOfDirectoryAtPath:fileSystemPath error:&error];
-
- if (contents) {
- NSMutableArray* entries = [NSMutableArray arrayWithCapacity:1];
- if ([contents count] > 0) {
- // create an Entry (as JSON) for each file/dir
- for (NSString* name in contents) {
- // see if is dir or file
- NSString* entryPath = [fileSystemPath stringByAppendingPathComponent:name];
- BOOL bIsDir = NO;
- [fileMgr fileExistsAtPath:entryPath isDirectory:&bIsDir];
- NSDictionary* entryDict = [self makeEntryForPath:[self fullPathForFileSystemPath:entryPath] isDirectory:bIsDir];
- [entries addObject:entryDict];
- }
- }
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:entries];
- } else {
- // assume not found but could check error for more specific error conditions
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
- }
-}
-
-- (unsigned long long)truncateFile:(NSString*)filePath atPosition:(unsigned long long)pos
-{
- unsigned long long newPos = 0UL;
-
- NSFileHandle* file = [NSFileHandle fileHandleForWritingAtPath:filePath];
-
- if (file) {
- [file truncateFileAtOffset:(unsigned long long)pos];
- newPos = [file offsetInFile];
- [file synchronizeFile];
- [file closeFile];
- }
- return newPos;
-}
-
-- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
-{
- unsigned long long newPos = [self truncateFile:[self filesystemPathForURL:localURI] atPosition:pos];
- return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(int)newPos];
-}
-
-- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
-{
- NSString *filePath = [self filesystemPathForURL:localURL];
-
- CDVPluginResult* result = nil;
- CDVFileError errCode = INVALID_MODIFICATION_ERR;
- int bytesWritten = 0;
-
- if (filePath) {
- NSOutputStream* fileStream = [NSOutputStream outputStreamToFileAtPath:filePath append:shouldAppend];
- if (fileStream) {
- NSUInteger len = [encData length];
- if (len == 0) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:(double)len];
- } else {
- [fileStream open];
-
- bytesWritten = (int)[fileStream write:[encData bytes] maxLength:len];
-
- [fileStream close];
- if (bytesWritten > 0) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:bytesWritten];
- // } else {
- // can probably get more detailed error info via [fileStream streamError]
- // errCode already set to INVALID_MODIFICATION_ERR;
- // bytesWritten = 0; // may be set to -1 on error
- }
- }
- } // else fileStream not created return INVALID_MODIFICATION_ERR
- } else {
- // invalid filePath
- errCode = NOT_FOUND_ERR;
- }
- if (!result) {
- // was an error
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
- }
- return result;
-}
-
-/**
- * Helper function to check to see if the user attempted to copy an entry into its parent without changing its name,
- * or attempted to copy a directory into a directory that it contains directly or indirectly.
- *
- * IN:
- * NSString* srcDir
- * NSString* destinationDir
- * OUT:
- * YES copy/ move is allows
- * NO move is onto itself
- */
-- (BOOL)canCopyMoveSrc:(NSString*)src ToDestination:(NSString*)dest
-{
- // This weird test is to determine if we are copying or moving a directory into itself.
- // Copy /Documents/myDir to /Documents/myDir-backup is okay but
- // Copy /Documents/myDir to /Documents/myDir/backup not okay
- BOOL copyOK = YES;
- NSRange range = [dest rangeOfString:src];
-
- if (range.location != NSNotFound) {
- NSRange testRange = {range.length - 1, ([dest length] - range.length)};
- NSRange resultRange = [dest rangeOfString:@"/" options:0 range:testRange];
- if (resultRange.location != NSNotFound) {
- copyOK = NO;
- }
- }
- return copyOK;
-}
-
-- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
-{
- NSFileManager *fileMgr = [[NSFileManager alloc] init];
- NSString *destRootPath = [self filesystemPathForURL:destURL];
- BOOL bDestIsDir = NO;
- BOOL bDestExists = [fileMgr fileExistsAtPath:destRootPath isDirectory:&bDestIsDir];
-
- NSString *newFileSystemPath = [destRootPath stringByAppendingPathComponent:newName];
- NSString *newFullPath = [self fullPathForFileSystemPath:newFileSystemPath];
-
- BOOL bNewIsDir = NO;
- BOOL bNewExists = [fileMgr fileExistsAtPath:newFileSystemPath isDirectory:&bNewIsDir];
-
- CDVPluginResult *result = nil;
- int errCode = 0;
-
- if (!bDestExists) {
- // the destination root does not exist
- errCode = NOT_FOUND_ERR;
- }
-
- else if ([srcFs isKindOfClass:[CDVLocalFilesystem class]]) {
- /* Same FS, we can shortcut with NSFileManager operations */
- NSString *srcFullPath = [srcFs filesystemPathForURL:srcURL];
-
- BOOL bSrcIsDir = NO;
- BOOL bSrcExists = [fileMgr fileExistsAtPath:srcFullPath isDirectory:&bSrcIsDir];
-
- if (!bSrcExists) {
- // the source does not exist
- errCode = NOT_FOUND_ERR;
- } else if ([newFileSystemPath isEqualToString:srcFullPath]) {
- // source and destination can not be the same
- errCode = INVALID_MODIFICATION_ERR;
- } else if (bSrcIsDir && (bNewExists && !bNewIsDir)) {
- // can't copy/move dir to file
- errCode = INVALID_MODIFICATION_ERR;
- } else { // no errors yet
- NSError* __autoreleasing error = nil;
- BOOL bSuccess = NO;
- if (bCopy) {
- if (bSrcIsDir && ![self canCopyMoveSrc:srcFullPath ToDestination:newFileSystemPath]) {
- // can't copy dir into self
- errCode = INVALID_MODIFICATION_ERR;
- } else if (bNewExists) {
- // the full destination should NOT already exist if a copy
- errCode = PATH_EXISTS_ERR;
- } else {
- bSuccess = [fileMgr copyItemAtPath:srcFullPath toPath:newFileSystemPath error:&error];
- }
- } else { // move
- // iOS requires that destination must not exist before calling moveTo
- // is W3C INVALID_MODIFICATION_ERR error if destination dir exists and has contents
- //
- if (!bSrcIsDir && (bNewExists && bNewIsDir)) {
- // can't move a file to directory
- errCode = INVALID_MODIFICATION_ERR;
- } else if (bSrcIsDir && ![self canCopyMoveSrc:srcFullPath ToDestination:newFileSystemPath]) {
- // can't move a dir into itself
- errCode = INVALID_MODIFICATION_ERR;
- } else if (bNewExists) {
- if (bNewIsDir && ([[fileMgr contentsOfDirectoryAtPath:newFileSystemPath error:NULL] count] != 0)) {
- // can't move dir to a dir that is not empty
- errCode = INVALID_MODIFICATION_ERR;
- newFileSystemPath = nil; // so we won't try to move
- } else {
- // remove destination so can perform the moveItemAtPath
- bSuccess = [fileMgr removeItemAtPath:newFileSystemPath error:NULL];
- if (!bSuccess) {
- errCode = INVALID_MODIFICATION_ERR; // is this the correct error?
- newFileSystemPath = nil;
- }
- }
- } else if (bNewIsDir && [newFileSystemPath hasPrefix:srcFullPath]) {
- // can't move a directory inside itself or to any child at any depth;
- errCode = INVALID_MODIFICATION_ERR;
- newFileSystemPath = nil;
- }
-
- if (newFileSystemPath != nil) {
- bSuccess = [fileMgr moveItemAtPath:srcFullPath toPath:newFileSystemPath error:&error];
- }
- }
- if (bSuccess) {
- // should verify it is there and of the correct type???
- NSDictionary* newEntry = [self makeEntryForPath:newFullPath isDirectory:bSrcIsDir];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry];
- } else {
- if (error) {
- if (([error code] == NSFileReadUnknownError) || ([error code] == NSFileReadTooLargeError)) {
- errCode = NOT_READABLE_ERR;
- } else if ([error code] == NSFileWriteOutOfSpaceError) {
- errCode = QUOTA_EXCEEDED_ERR;
- } else if ([error code] == NSFileWriteNoPermissionError) {
- errCode = NO_MODIFICATION_ALLOWED_ERR;
- }
- }
- }
- }
- } else {
- // Need to copy the hard way
- [srcFs readFileAtURL:srcURL start:0 end:-1 callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
- CDVPluginResult* result = nil;
- if (data != nil) {
- BOOL bSuccess = [data writeToFile:newFileSystemPath atomically:YES];
- if (bSuccess) {
- // should verify it is there and of the correct type???
- NSDictionary* newEntry = [self makeEntryForPath:newFullPath isDirectory:NO];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry];
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ABORT_ERR];
- }
- } else {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
- }
- callback(result);
- }];
- return; // Async IO; return without callback.
- }
- if (result == nil) {
- if (!errCode) {
- errCode = INVALID_MODIFICATION_ERR; // Catch-all default
- }
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errCode];
- }
- callback(result);
-}
-
-/* helper function to get the mimeType from the file extension
- * IN:
- * NSString* fullPath - filename (may include path)
- * OUT:
- * NSString* the mime type as type/subtype. nil if not able to determine
- */
-+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
-{
- NSString* mimeType = nil;
-
- if (fullPath) {
- CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
- if (typeId) {
- mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
- if (!mimeType) {
- // special case for m4a
- if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
- mimeType = @"audio/mp4";
- } else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
- mimeType = @"audio/wav";
- } else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
- mimeType = @"text/css";
- }
- }
- CFRelease(typeId);
- }
- }
- return mimeType;
-}
-
-- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
-{
- NSString *path = [self filesystemPathForURL:localURL];
-
- NSString* mimeType = [CDVLocalFilesystem getMimeTypeFromPath:path];
- if (mimeType == nil) {
- mimeType = @"*/*";
- }
- NSFileHandle* file = [NSFileHandle fileHandleForReadingAtPath:path];
- if (start > 0) {
- [file seekToFileOffset:start];
- }
-
- NSData* readData;
- if (end < 0) {
- readData = [file readDataToEndOfFile];
- } else {
- readData = [file readDataOfLength:(end - start)];
- }
- [file closeFile];
-
- callback(readData, mimeType, readData != nil ? NO_ERROR : NOT_FOUND_ERR);
-}
-
-- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
-{
- NSString *path = [self filesystemPathForURL:localURL];
- CDVPluginResult *result;
- NSFileManager* fileMgr = [[NSFileManager alloc] init];
-
- NSError* __autoreleasing error = nil;
- NSDictionary* fileAttrs = [fileMgr attributesOfItemAtPath:path error:&error];
-
- if (fileAttrs) {
-
- // create dictionary of file info
- NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
-
- [fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
- [fileInfo setObject:@"" forKey:@"type"]; // can't easily get the mimetype unless create URL, send request and read response so skipping
- [fileInfo setObject:[path lastPathComponent] forKey:@"name"];
-
- // Ensure that directories (and other non-regular files) report size of 0
- unsigned long long size = ([fileAttrs fileType] == NSFileTypeRegular ? [fileAttrs fileSize] : 0);
- [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:size] forKey:@"size"];
-
- NSDate* modDate = [fileAttrs fileModificationDate];
- if (modDate) {
- [fileInfo setObject:[NSNumber numberWithDouble:[modDate timeIntervalSince1970] * 1000] forKey:@"lastModifiedDate"];
- }
-
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo];
-
- } else {
- // didn't get fileAttribs
- CDVFileError errorCode = ABORT_ERR;
- NSLog(@"error getting metadata: %@", [error localizedDescription]);
- if ([error code] == NSFileNoSuchFileError || [error code] == NSFileReadNoSuchFileError) {
- errorCode = NOT_FOUND_ERR;
- }
- // log [NSNumber numberWithDouble: theMessage] objCtype to see what it returns
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode];
- }
-
- callback(result);
-}
-
-@end
diff --git a/plugins/cordova-plugin-file/src/ubuntu/file.cpp b/plugins/cordova-plugin-file/src/ubuntu/file.cpp
deleted file mode 100644
index 395ab2dd..00000000
--- a/plugins/cordova-plugin-file/src/ubuntu/file.cpp
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * Licensed 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.
- */
-
-#include "file.h"
-
-#include <QApplication>
-
-namespace {
- class FileError {
- public:
- static const QString kEncodingErr;
- static const QString kTypeMismatchErr;
- static const QString kNotFoundErr;
- static const QString kSecurityErr;
- static const QString kAbortErr;
- static const QString kNotReadableErr;
- static const QString kNoModificationAllowedErr;
- static const QString kInvalidStateErr;
- static const QString kSyntaxErr;
- static const QString kInvalidModificationErr;
- static const QString kQuotaExceededErr;
- static const QString kPathExistsErr;
- };
-
- bool checkFileName(const QString &name) {
- if (name.contains(":")){
- return false;
- }
- return true;
- }
-};
-
-const QString FileError::kEncodingErr("FileError.ENCODING_ERR");
-const QString FileError::kTypeMismatchErr("FileError.TYPE_MISMATCH_ERR");
-const QString FileError::kNotFoundErr("FileError.NOT_FOUND_ERR");
-const QString FileError::kSecurityErr("FileError.SECURITY_ERR");
-const QString FileError::kAbortErr("FileError.ABORT_ERR");
-const QString FileError::kNotReadableErr("FileError.NOT_READABLE_ERR");
-const QString FileError::kNoModificationAllowedErr("FileError.NO_MODIFICATION_ALLOWED_ERR");
-const QString FileError::kInvalidStateErr("FileError.INVALID_STATE_ERR");
-const QString FileError::kSyntaxErr("FileError.SYNTAX_ERR");
-const QString FileError::kInvalidModificationErr("FileError.INVALID_MODIFICATION_ERR");
-const QString FileError::kQuotaExceededErr("FileError.QUOTA_EXCEEDED_ERR");
-const QString FileError::kPathExistsErr("FileError.PATH_EXISTS_ERR");
-
-File::File(Cordova *cordova) :
- CPlugin(cordova),
- _persistentDir(QString("%1/.local/share/%2/persistent").arg(QDir::homePath()).arg(QCoreApplication::applicationName())) {
- QDir::root().mkpath(_persistentDir.absolutePath());
-}
-
-QVariantMap File::file2map(const QFileInfo &fileInfo) {
- QVariantMap res;
-
- res.insert("name", fileInfo.fileName());
- QPair<QString, QString> r = GetRelativePath(fileInfo);
- res.insert("fullPath", QString("/") + r.second);
- res.insert("filesystemName", r.first);
-
- res.insert("nativeURL", QString("file://localhost") + fileInfo.absoluteFilePath());
- res.insert("isDirectory", (int)fileInfo.isDir());
- res.insert("isFile", (int)fileInfo.isFile());
-
- return res;
-}
-
-QVariantMap File::dir2map(const QDir &dir) {
- return file2map(QFileInfo(dir.absolutePath()));
-}
-
-QPair<QString, QString> File::GetRelativePath(const QFileInfo &fileInfo) {
- QString fullPath = fileInfo.isDir() ? QDir::cleanPath(fileInfo.absoluteFilePath()) : fileInfo.absoluteFilePath();
-
- QString relativePath1 = _persistentDir.relativeFilePath(fullPath);
- QString relativePath2 = QDir::temp().relativeFilePath(fullPath);
-
- if (!(relativePath1[0] != '.' || relativePath2[0] != '.')) {
- if (relativePath1.size() > relativePath2.size()) {
- return QPair<QString, QString>("temporary", relativePath2);
- } else {
- return QPair<QString, QString>("persistent", relativePath1);
- }
- }
-
- if (relativePath1[0] != '.')
- return QPair<QString, QString>("persistent", relativePath1);
- return QPair<QString, QString>("temporary", relativePath2);
-}
-
-void File::requestFileSystem(int scId, int ecId, unsigned short type, unsigned long long size) {
- QDir dir;
-
- if (size >= 1000485760){
- this->callback(ecId, FileError::kQuotaExceededErr);
- return;
- }
-
- if (type == 0)
- dir = QDir::temp();
- else
- dir = _persistentDir;
-
- if (type > 1) {
- this->callback(ecId, FileError::kSyntaxErr);
- return;
- } else {
- QVariantMap res;
- res.insert("root", dir2map(dir));
- if (type == 0)
- res.insert("name", "temporary");
- else
- res.insert("name", "persistent");
-
- this->cb(scId, res);
- }
-}
-
-QPair<bool, QFileInfo> File::resolveURI(int ecId, const QString &uri) {
- QPair<bool, QFileInfo> result;
-
- result.first = false;
-
- QUrl url = QUrl::fromUserInput(uri);
-
- if (url.scheme() == "file" && url.isValid()) {
- result.first = true;
- result.second = QFileInfo(url.path());
- return result;
- }
-
- if (url.scheme() != "cdvfile") {
- if (ecId)
- this->callback(ecId, FileError::kTypeMismatchErr);
- return result;
- }
-
- QString path = url.path().replace("//", "/");
- //NOTE: colon is not safe in url, it is not a valid path in Win and Mac, simple disable it here.
- if (path.contains(":") || !url.isValid()){
- if (ecId)
- this->callback(ecId, FileError::kEncodingErr);
- return result;
- }
- if (!path.startsWith("/persistent/") && !path.startsWith("/temporary/")) {
- if (ecId)
- this->callback(ecId, FileError::kEncodingErr);
- return result;
- }
-
- result.first = true;
- if (path.startsWith("/persistent/")) {
- QString relativePath = path.mid(QString("/persistent/").size());
- result.second = QFileInfo(_persistentDir.filePath(relativePath));
- } else {
- QString relativePath = path.mid(QString("/temporary/").size());
- result.second = QFileInfo(QDir::temp().filePath(relativePath));
- }
- return result;
-}
-
-QPair<bool, QFileInfo> File::resolveURI(const QString &uri) {
- return resolveURI(0, uri);
-}
-
-
-void File::_getLocalFilesystemPath(int scId, int ecId, const QString& uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- this->cb(scId, f1.second.absoluteFilePath());
-}
-
-void File::resolveLocalFileSystemURI(int scId, int ecId, const QString &uri) {
- if (uri[0] == '/' || uri[0] == '.') {
- this->callback(ecId, FileError::kEncodingErr);
- return;
- }
-
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFileInfo fileInfo = f1.second;
- if (!fileInfo.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- this->cb(scId, file2map(fileInfo));
-}
-
-void File::getFile(int scId, int ecId, const QString &parentPath, const QString &rpath, const QVariantMap &options) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, parentPath + "/" + rpath);
- if (!f1.first)
- return;
-
- bool create = options.value("create").toBool();
- bool exclusive = options.value("exclusive").toBool();
- QFile file(f1.second.absoluteFilePath());
-
- // if create is false and the path represents a directory, return error
- QFileInfo fileInfo = f1.second;
- if ((!create) && fileInfo.isDir()) {
- this->callback(ecId, FileError::kTypeMismatchErr);
- return;
- }
-
- // if file does exist, and create is true and exclusive is true, return error
- if (file.exists()) {
- if (create && exclusive) {
- this->callback(ecId, FileError::kPathExistsErr);
- return;
- }
- }
- else {
- // if file does not exist and create is false, return error
- if (!create) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- file.open(QIODevice::WriteOnly);
- file.close();
-
- // Check if creation was successfull
- if (!file.exists()) {
- this->callback(ecId, FileError::kNoModificationAllowedErr);
- return;
- }
- }
-
- this->cb(scId, file2map(QFileInfo(file)));
-}
-
-void File::getDirectory(int scId, int ecId, const QString &parentPath, const QString &rpath, const QVariantMap &options) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, parentPath + "/" + rpath);
- if (!f1.first)
- return;
-
- bool create = options.value("create").toBool();
- bool exclusive = options.value("exclusive").toBool();
- QDir dir(f1.second.absoluteFilePath());
-
- QFileInfo &fileInfo = f1.second;
- if ((!create) && fileInfo.isFile()) {
- this->callback(ecId, FileError::kTypeMismatchErr);
- return;
- }
-
- if (dir.exists()) {
- if (create && exclusive) {
- this->callback(ecId, FileError::kPathExistsErr);
- return;
- }
- }
- else {
- if (!create) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- QString folderName = dir.dirName();
- dir.cdUp();
- dir.mkdir(folderName);
- dir.cd(folderName);
-
- if (!dir.exists()) {
- this->callback(ecId, FileError::kNoModificationAllowedErr);
- return;
- }
- }
-
- this->cb(scId, dir2map(dir));
-}
-
-void File::removeRecursively(int scId, int ecId, const QString &uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QDir dir(f1.second.absoluteFilePath());
- if (File::rmDir(dir))
- this->cb(scId);
- else
- this->callback(ecId, FileError::kNoModificationAllowedErr);
-}
-
-void File::write(int scId, int ecId, const QString &uri, const QString &_data, unsigned long long position, bool binary) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFile file(f1.second.absoluteFilePath());
-
- file.open(QIODevice::WriteOnly);
- file.close();
-
- if (!file.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- QFileInfo fileInfo(file);
- if (!file.open(QIODevice::ReadWrite)) {
- this->callback(ecId, FileError::kNoModificationAllowedErr);
- return;
- }
-
- if (!binary) {
- QTextStream textStream(&file);
- textStream.setCodec("UTF-8");
- textStream.setAutoDetectUnicode(true);
-
- if (!textStream.seek(position)) {
- file.close();
- fileInfo.refresh();
-
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- textStream << _data;
- textStream.flush();
- } else {
- QByteArray data(_data.toUtf8());
- if (!file.seek(position)) {
- file.close();
- fileInfo.refresh();
-
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- file.write(data.data(), data.length());
- }
-
- file.flush();
- file.close();
- fileInfo.refresh();
-
- this->cb(scId, fileInfo.size() - position);
-}
-
-void File::truncate(int scId, int ecId, const QString &uri, unsigned long long size) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFile file(f1.second.absoluteFilePath());
-
- if (!file.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- if (!file.resize(size)) {
- this->callback(ecId, FileError::kNoModificationAllowedErr);
- return;
- }
-
- this->cb(scId, size);
-}
-
-void File::getParent(int scId, int ecId, const QString &uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
- QDir dir(f1.second.absoluteFilePath());
-
- //can't cdup more than app's root
- // Try to change into upper directory
- if (dir != _persistentDir && dir != QDir::temp()){
- if (!dir.cdUp()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- }
- this->cb(scId, dir2map(dir));
-}
-
-void File::remove(int scId, int ecId, const QString &uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
- if (!f1.first)
- return;
-
- QFileInfo &fileInfo = f1.second;
- //TODO: fix
- if (!fileInfo.exists() || (fileInfo.absoluteFilePath() == _persistentDir.absolutePath()) || (QDir::temp() == fileInfo.absoluteFilePath())) {
- this->callback(ecId, FileError::kNoModificationAllowedErr);
- return;
- }
-
- if (fileInfo.isDir()) {
- QDir dir(fileInfo.absoluteFilePath());
- if (dir.rmdir(dir.absolutePath())) {
- this->cb(scId);
- return;
- }
- } else {
- QFile file(fileInfo.absoluteFilePath());
- if (file.remove()) {
- this->cb(scId);
- return;
- }
- }
-
- this->callback(ecId, FileError::kInvalidModificationErr);
-}
-
-void File::getFileMetadata(int scId, int ecId, const QString &uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
- QFileInfo &fileInfo = f1.second;
-
- if (!fileInfo.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- } else {
- QMimeType mime = _db.mimeTypeForFile(fileInfo.fileName());
-
- QString args = QString("{name: %1, fullPath: %2, type: %3, lastModifiedDate: new Date(%4), size: %5}")
- .arg(CordovaInternal::format(fileInfo.fileName())).arg(CordovaInternal::format(fileInfo.absoluteFilePath()))
- .arg(CordovaInternal::format(mime.name())).arg(fileInfo.lastModified().toMSecsSinceEpoch())
- .arg(fileInfo.size());
-
- this->callback(scId, args);
- }
-}
-
-void File::getMetadata(int scId, int ecId, const QString &uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
- QFileInfo &fileInfo = f1.second;
-
- if (!fileInfo.exists())
- this->callback(ecId, FileError::kNotFoundErr);
- else {
- QVariantMap obj;
- obj.insert("modificationTime", fileInfo.lastModified().toMSecsSinceEpoch());
- obj.insert("size", fileInfo.isDir() ? 0 : fileInfo.size());
- this->cb(scId, obj);
- }
-}
-
-void File::readEntries(int scId, int ecId, const QString &uri) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
- QDir dir(f1.second.absoluteFilePath());
- QString entriesList;
-
- if (!dir.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- for (const QFileInfo &fileInfo: dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
- entriesList += CordovaInternal::format(file2map(fileInfo)) + ",";
- }
- // Remove trailing comma
- if (entriesList.size() > 0)
- entriesList.remove(entriesList.size() - 1, 1);
-
- entriesList = "new Array(" + entriesList + ")";
-
- this->callback(scId, entriesList);
-}
-
-void File::readAsText(int scId, int ecId, const QString &uri, const QString &/*encoding*/, int sliceStart, int sliceEnd) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFile file(f1.second.absoluteFilePath());
-
- if (!file.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- if (!file.open(QIODevice::ReadOnly)) {
- this->callback(ecId, FileError::kNotReadableErr);
- return;
- }
-
- QByteArray content = file.readAll();
-
- if (sliceEnd == -1)
- sliceEnd = content.size();
- if (sliceEnd < 0) {
- sliceEnd++;
- sliceEnd = std::max(0, content.size() + sliceEnd);
- }
- if (sliceEnd > content.size())
- sliceEnd = content.size();
-
- if (sliceStart < 0)
- sliceStart = std::max(0, content.size() + sliceStart);
- if (sliceStart > content.size())
- sliceStart = content.size();
-
- if (sliceStart > sliceEnd)
- sliceEnd = sliceStart;
-
- //FIXME: encoding
- content = content.mid(sliceStart, sliceEnd - sliceStart);
-
- this->cb(scId, content);
-}
-
-void File::readAsArrayBuffer(int scId, int ecId, const QString &uri, int sliceStart, int sliceEnd) {
- const QString str2array("\
- (function strToArray(str) { \
- var res = new Uint8Array(str.length); \
- for (var i = 0; i < str.length; i++) { \
- res[i] = str.charCodeAt(i); \
- } \
- return res; \
- })(\"%1\")");
-
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFile file(f1.second.absoluteFilePath());
-
- if (!file.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- if (!file.open(QIODevice::ReadOnly)) {
- this->callback(ecId, FileError::kNotReadableErr);
- return;
- }
- QString res;
- QByteArray content = file.readAll();
-
- if (sliceEnd == -1)
- sliceEnd = content.size();
- if (sliceEnd < 0) {
- sliceEnd++;
- sliceEnd = std::max(0, content.size() + sliceEnd);
- }
- if (sliceEnd > content.size())
- sliceEnd = content.size();
-
- if (sliceStart < 0)
- sliceStart = std::max(0, content.size() + sliceStart);
- if (sliceStart > content.size())
- sliceStart = content.size();
-
- if (sliceStart > sliceEnd)
- sliceEnd = sliceStart;
-
- content = content.mid(sliceStart, sliceEnd - sliceStart);
-
- res.reserve(content.length() * 6);
- for (uchar c: content) {
- res += "\\x";
- res += QString::number(c, 16).rightJustified(2, '0').toUpper();
- }
-
- this->callback(scId, str2array.arg(res));
-}
-
-void File::readAsBinaryString(int scId, int ecId, const QString &uri, int sliceStart, int sliceEnd) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFile file(f1.second.absoluteFilePath());
-
- if (!file.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- if (!file.open(QIODevice::ReadOnly)) {
- this->callback(ecId, FileError::kNotReadableErr);
- return;
- }
- QString res;
- QByteArray content = file.readAll();
-
- if (sliceEnd == -1)
- sliceEnd = content.size();
- if (sliceEnd < 0) {
- sliceEnd++;
- sliceEnd = std::max(0, content.size() + sliceEnd);
- }
- if (sliceEnd > content.size())
- sliceEnd = content.size();
-
- if (sliceStart < 0)
- sliceStart = std::max(0, content.size() + sliceStart);
- if (sliceStart > content.size())
- sliceStart = content.size();
-
- if (sliceStart > sliceEnd)
- sliceEnd = sliceStart;
-
- content = content.mid(sliceStart, sliceEnd - sliceStart);
-
- res.reserve(content.length() * 6);
- for (uchar c: content) {
- res += "\\x";
- res += QString::number(c, 16).rightJustified(2, '0').toUpper();
- }
- this->callback(scId, "\"" + res + "\"");
-}
-
-void File::readAsDataURL(int scId, int ecId, const QString &uri, int sliceStart, int sliceEnd) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, uri);
-
- if (!f1.first)
- return;
-
- QFile file(f1.second.absoluteFilePath());
- QFileInfo &fileInfo = f1.second;
-
- if (!file.exists()) {
- this->callback(ecId, FileError::kNotReadableErr);
- return;
- }
-
- if (!file.open(QIODevice::ReadOnly)) {
- this->callback(ecId, FileError::kNotReadableErr);
- return;
- }
-
- QByteArray content = file.readAll();
- QString contentType(_db.mimeTypeForFile(fileInfo.fileName()).name());
-
- if (sliceEnd == -1)
- sliceEnd = content.size();
- if (sliceEnd < 0) {
- sliceEnd++;
- sliceEnd = std::max(0, content.size() + sliceEnd);
- }
- if (sliceEnd > content.size())
- sliceEnd = content.size();
-
- if (sliceStart < 0)
- sliceStart = std::max(0, content.size() + sliceStart);
- if (sliceStart > content.size())
- sliceStart = content.size();
-
- if (sliceStart > sliceEnd)
- sliceEnd = sliceStart;
-
- content = content.mid(sliceStart, sliceEnd - sliceStart);
-
- this->cb(scId, QString("data:%1;base64,").arg(contentType) + content.toBase64());
-}
-
-bool File::rmDir(const QDir &dir) {
- if (dir == _persistentDir || dir == QDir::temp()) {//can't remove root dir
- return false;
- }
- bool result = true;
- if (dir.exists()) {
- // Iterate over entries and remove them
- Q_FOREACH(const QFileInfo &fileInfo, dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)) {
- if (fileInfo.isDir()) {
- result = rmDir(fileInfo.absoluteFilePath());
- }
- else {
- result = QFile::remove(fileInfo.absoluteFilePath());
- }
-
- if (!result) {
- return result;
- }
- }
-
- // Finally remove the current dir
- return dir.rmdir(dir.absolutePath());
- }
- return result;
-}
-
-bool File::copyFile(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName) {
- QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
- QPair<bool, QFileInfo> sourceFile = resolveURI(ecId, sourceUri);
-
- if (!destDir.first || !sourceFile.first)
- return false;
-
- if (!checkFileName(newName)) {
- this->callback(ecId, FileError::kEncodingErr);
- return false;
- }
-
- if (destDir.second.isFile()) {
- this->callback(ecId, FileError::kInvalidModificationErr);
- return false;
- }
-
- if (!destDir.second.isDir()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return false;
- }
-
- QFileInfo &fileInfo = sourceFile.second;
- QString fileName((newName.isEmpty()) ? fileInfo.fileName() : newName);
- QString destinationFile(QDir(destDir.second.absoluteFilePath()).filePath(fileName));
- if (QFile::copy(fileInfo.absoluteFilePath(), destinationFile)){
- this->cb(scId, file2map(QFileInfo(destinationFile)));
- return true;
- }
- this->callback(ecId, FileError::kInvalidModificationErr);
- return false;
-}
-
-void File::copyDir(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName) {
- QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
- QPair<bool, QFileInfo> sourceDir = resolveURI(ecId, sourceUri);
-
- if (!destDir.first || !sourceDir.first)
- return;
- if (!checkFileName(newName)) {
- this->callback(ecId, FileError::kEncodingErr);
- return;
- }
-
- QString targetName = ((newName.isEmpty()) ? sourceDir.second.fileName() : newName);
- QString target(QDir(destDir.second.absoluteFilePath()).filePath(targetName));
-
- if (QFileInfo(target).isFile()){
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- // check: copy directory into itself
- if (QDir(sourceDir.second.absoluteFilePath()).relativeFilePath(target)[0] != '.'){
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- if (!QDir(target).exists()){
- QDir(destDir.second.absoluteFilePath()).mkdir(target);;
- } else{
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- if (copyFolder(sourceDir.second.absoluteFilePath(), target)){
- this->cb(scId, dir2map(QDir(target)));
- return;
- }
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
-}
-
-void File::copyTo(int scId, int ecId, const QString& source, const QString& destinationDir, const QString& newName) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, source);
-
- if (!f1.first)
- return;
-
- if (f1.second.isDir())
- copyDir(scId, ecId, source, destinationDir, newName);
- else
- copyFile(scId, ecId, source, destinationDir, newName);
-}
-
-void File::moveFile(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName) {
- QPair<bool, QFileInfo> sourceFile = resolveURI(ecId, sourceUri);
- QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
-
- if (!destDir.first || !sourceFile.first)
- return;
- if (!checkFileName(newName)) {
- this->callback(ecId, FileError::kEncodingErr);
- return;
- }
-
- QString fileName = ((newName.isEmpty()) ? sourceFile.second.fileName() : newName);
- QString target = QDir(destDir.second.absoluteFilePath()).filePath(fileName);
-
- if (sourceFile.second == QFileInfo(target)) {
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- if (!destDir.second.exists()) {
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
- if (!destDir.second.isDir()){
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- if (QFileInfo(target).exists()) {
- if (!QFile::remove(target)) {
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
- }
-
- QFile::rename(sourceFile.second.absoluteFilePath(), target);
- this->cb(scId, file2map(QFileInfo(target)));
-}
-
-void File::moveDir(int scId, int ecId,const QString& sourceUri, const QString& destinationUri, const QString& newName){
- QPair<bool, QFileInfo> sourceDir = resolveURI(ecId, sourceUri);
- QPair<bool, QFileInfo> destDir = resolveURI(ecId, destinationUri);
-
- if (!destDir.first || !sourceDir.first)
- return;
- if (!checkFileName(newName)) {
- this->callback(ecId, FileError::kEncodingErr);
- return;
- }
-
- QString fileName = ((newName.isEmpty()) ? sourceDir.second.fileName() : newName);
- QString target = QDir(destDir.second.absoluteFilePath()).filePath(fileName);
-
- if (!destDir.second.exists()){
- this->callback(ecId, FileError::kNotFoundErr);
- return;
- }
-
- if (destDir.second.isFile()){
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- // check: copy directory into itself
- if (QDir(sourceDir.second.absoluteFilePath()).relativeFilePath(target)[0] != '.'){
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- if (QFileInfo(target).exists() && !QDir(destDir.second.absoluteFilePath()).rmdir(fileName)) {
- this->callback(ecId, FileError::kInvalidModificationErr);
- return;
- }
-
- if (copyFolder(sourceDir.second.absoluteFilePath(), target)) {
- rmDir(sourceDir.second.absoluteFilePath());
- this->cb(scId, file2map(QFileInfo(target)));
- } else {
- this->callback(ecId, FileError::kNoModificationAllowedErr);
- }
-}
-
-void File::moveTo(int scId, int ecId, const QString& source, const QString& destinationDir, const QString& newName) {
- QPair<bool, QFileInfo> f1 = resolveURI(ecId, source);
-
- if (!f1.first)
- return;
-
- if (f1.second.isDir())
- moveDir(scId, ecId, source, destinationDir, newName);
- else
- moveFile(scId, ecId, source, destinationDir, newName);
-}
-
-bool File::copyFolder(const QString& sourceFolder, const QString& destFolder) {
- QDir sourceDir(sourceFolder);
- if (!sourceDir.exists())
- return false;
- QDir destDir(destFolder);
- if (!destDir.exists()){
- destDir.mkdir(destFolder);
- }
- QStringList files = sourceDir.entryList(QDir::Files);
- for (int i = 0; i< files.count(); i++)
- {
- QString srcName = sourceFolder + "/" + files[i];
- QString destName = destFolder + "/" + files[i];
- QFile::copy(srcName, destName);
- }
- files.clear();
- files = sourceDir.entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
- for (int i = 0; i< files.count(); i++)
- {
- QString srcName = sourceFolder + "/" + files[i];
- QString destName = destFolder + "/" + files[i];
- copyFolder(srcName, destName);
- }
- return true;
-}
diff --git a/plugins/cordova-plugin-file/src/ubuntu/file.h b/plugins/cordova-plugin-file/src/ubuntu/file.h
deleted file mode 100644
index de277623..00000000
--- a/plugins/cordova-plugin-file/src/ubuntu/file.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Licensed 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.
- */
-
-#ifndef FILEAPI_H_SDASDASDAS
-#define FILEAPI_H_SDASDASDAS
-
-#include <QNetworkReply>
-#include <QtCore>
-
-#include <cplugin.h>
-#include <cordova.h>
-
-class File: public CPlugin {
- Q_OBJECT
-public:
- explicit File(Cordova *cordova);
-
- virtual const QString fullName() override {
- return File::fullID();
- }
-
- virtual const QString shortName() override {
- return "File";
- }
-
- static const QString fullID() {
- return "File";
- }
- QPair<bool, QFileInfo> resolveURI(const QString &uri);
- QPair<bool, QFileInfo> resolveURI(int ecId, const QString &uri);
- QVariantMap file2map(const QFileInfo &dir);
-
-public slots:
- void requestFileSystem(int scId, int ecId, unsigned short type, unsigned long long size);
- void resolveLocalFileSystemURI(int scId, int ecId, const QString&);
- void getDirectory(int scId, int ecId, const QString&, const QString&, const QVariantMap&);
- void getFile(int scId, int ecId, const QString &parentPath, const QString &rpath, const QVariantMap &options);
- void readEntries(int scId, int ecId, const QString &uri);
- void getParent(int scId, int ecId, const QString &uri);
- void copyTo(int scId, int ecId, const QString& source, const QString& destinationDir, const QString& newName);
- void moveTo(int scId, int ecId, const QString& source, const QString& destinationDir, const QString& newName);
- void getFileMetadata(int scId, int ecId, const QString &);
- void getMetadata(int scId, int ecId, const QString &);
- void remove(int scId, int ecId, const QString &);
- void removeRecursively(int scId, int ecId, const QString&);
- void write(int scId, int ecId, const QString&, const QString&, unsigned long long position, bool binary);
- void readAsText(int scId, int ecId, const QString&, const QString &encoding, int sliceStart, int sliceEnd);
- void readAsDataURL(int scId, int ecId, const QString&, int sliceStart, int sliceEnd);
- void readAsArrayBuffer(int scId, int ecId, const QString&, int sliceStart, int sliceEnd);
- void readAsBinaryString(int scId, int ecId, const QString&, int sliceStart, int sliceEnd);
- void truncate(int scId, int ecId, const QString&, unsigned long long size);
-
- void _getLocalFilesystemPath(int scId, int ecId, const QString&);
-private:
- void moveFile(int scId, int ecId,const QString&, const QString&, const QString&);
- void moveDir(int scId, int ecId,const QString&, const QString&, const QString&);
- bool copyFile(int scId, int ecId, const QString&, const QString&, const QString&);
- void copyDir(int scId, int ecId, const QString&, const QString&, const QString&);
- bool rmDir(const QDir &dir);
- bool copyFolder(const QString&, const QString&);
-
- QPair<QString, QString> GetRelativePath(const QFileInfo &fileInfo);
- QVariantMap dir2map(const QDir &dir);
-
- QMimeDatabase _db;
- const QDir _persistentDir;
- QNetworkAccessManager _manager;
-};
-
-#endif
diff --git a/plugins/cordova-plugin-file/src/windows/FileProxy.js b/plugins/cordova-plugin-file/src/windows/FileProxy.js
deleted file mode 100644
index d1769b7b..00000000
--- a/plugins/cordova-plugin-file/src/windows/FileProxy.js
+++ /dev/null
@@ -1,1186 +0,0 @@
-/*
- *
- * 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 cordova = require('cordova');
-var File = require('./File'),
- FileError = require('./FileError'),
- Flags = require('./Flags'),
- FileSystem = require('./FileSystem'),
- LocalFileSystem = require('./LocalFileSystem'),
- utils = require('cordova/utils');
-
-function Entry(isFile, isDirectory, name, fullPath, filesystemName, nativeURL) {
- this.isFile = !!isFile;
- this.isDirectory = !!isDirectory;
- this.name = name || '';
- this.fullPath = fullPath || '';
- this.filesystemName = filesystemName || null;
- this.nativeURL = nativeURL || null;
-}
-
-var FileEntry = function(name, fullPath, filesystemName, nativeURL) {
- FileEntry.__super__.constructor.apply(this, [true, false, name, fullPath, filesystemName, nativeURL]);
-};
-
-utils.extend(FileEntry, Entry);
-
-var DirectoryEntry = function(name, fullPath, filesystemName, nativeURL) {
- DirectoryEntry.__super__.constructor.call(this, false, true, name, fullPath, filesystemName, nativeURL);
-};
-
-utils.extend(DirectoryEntry, Entry);
-
-
-var getFolderFromPathAsync = Windows.Storage.StorageFolder.getFolderFromPathAsync;
-var getFileFromPathAsync = Windows.Storage.StorageFile.getFileFromPathAsync;
-
-function writeBytesAsync(storageFile, data, position) {
- return storageFile.openAsync(Windows.Storage.FileAccessMode.readWrite)
- .then(function (output) {
- output.seek(position);
- var dataWriter = new Windows.Storage.Streams.DataWriter(output);
- dataWriter.writeBytes(data);
- return dataWriter.storeAsync().then(function (size) {
- output.size = position+size;
- return dataWriter.flushAsync().then(function() {
- output.close();
- return size;
- });
- });
- });
-}
-
-function writeTextAsync(storageFile, data, position) {
- return storageFile.openAsync(Windows.Storage.FileAccessMode.readWrite)
- .then(function (output) {
- output.seek(position);
- var dataWriter = new Windows.Storage.Streams.DataWriter(output);
- dataWriter.writeString(data);
- return dataWriter.storeAsync().then(function (size) {
- output.size = position+size;
- return dataWriter.flushAsync().then(function() {
- output.close();
- return size;
- });
- });
- });
-}
-
-function writeBlobAsync(storageFile, data, position) {
- return storageFile.openAsync(Windows.Storage.FileAccessMode.readWrite)
- .then(function (output) {
- output.seek(position);
- var dataSize = data.size;
- var input = (data.detachStream || data.msDetachStream).call(data);
-
- // Copy the stream from the blob to the File stream
- return Windows.Storage.Streams.RandomAccessStream.copyAsync(input, output)
- .then(function () {
- output.size = position+dataSize;
- return output.flushAsync().then(function () {
- input.close();
- output.close();
-
- return dataSize;
- });
- });
- });
-}
-
-function writeArrayBufferAsync(storageFile, data, position) {
- return writeBlobAsync(storageFile, new Blob([data]), position);
-}
-
-function cordovaPathToNative(path) {
- // turn / into \\
- var cleanPath = path.replace(/\//g, '\\');
- // turn \\ into \
- cleanPath = cleanPath.replace(/\\+/g, '\\');
- return cleanPath;
-}
-
-function nativePathToCordova(path) {
- var cleanPath = path.replace(/\\/g, '/');
- return cleanPath;
-}
-
-var driveRE = new RegExp("^[/]*([A-Z]:)");
-var invalidNameRE = /[\\?*|"<>:]/;
-function validName(name) {
- return !invalidNameRE.test(name.replace(driveRE,''));
-}
-
-function sanitize(path) {
- var slashesRE = new RegExp('/{2,}','g');
- var components = path.replace(slashesRE, '/').split(/\/+/);
- // Remove double dots, use old school array iteration instead of RegExp
- // since it is impossible to debug them
- for (var index = 0; index < components.length; ++index) {
- if (components[index] === "..") {
- components.splice(index, 1);
- if (index > 0) {
- // if we're not in the start of array then remove preceeding path component,
- // In case if relative path points above the root directory, just ignore double dots
- // See file.spec.111 should not traverse above above the root directory for test case
- components.splice(index-1, 1);
- --index;
- }
- }
- }
- return components.join('/');
-}
-
-var WinFS = function(name, root) {
- this.winpath = root.winpath;
- if (this.winpath && !/\/$/.test(this.winpath)) {
- this.winpath += "/";
- }
- this.makeNativeURL = function(path) {
- return encodeURI(this.root.nativeURL + sanitize(path.replace(':','%3A')));};
- root.fullPath = '/';
- if (!root.nativeURL)
- root.nativeURL = 'file://'+sanitize(this.winpath + root.fullPath).replace(':','%3A');
- WinFS.__super__.constructor.call(this, name, root);
-};
-
-utils.extend(WinFS, FileSystem);
-
-WinFS.prototype.__format__ = function(fullPath) {
- var path = sanitize('/'+this.name+(fullPath[0]==='/'?'':'/')+encodeURI(fullPath));
- return 'cdvfile://localhost' + path;
-};
-
-var AllFileSystems;
-
-function getAllFS() {
- if (!AllFileSystems) {
- var storageFolderPermanent = Windows.Storage.ApplicationData.current.localFolder.path,
- storageFolderTemporary = Windows.Storage.ApplicationData.current.temporaryFolder.path;
- AllFileSystems = {
- 'persistent':
- Object.freeze(new WinFS('persistent', {
- name: 'persistent',
- nativeURL: 'ms-appdata:///local',
- winpath: nativePathToCordova(Windows.Storage.ApplicationData.current.localFolder.path)
- })),
- 'temporary':
- Object.freeze(new WinFS('temporary', {
- name: 'temporary',
- nativeURL: 'ms-appdata:///temp',
- winpath: nativePathToCordova(Windows.Storage.ApplicationData.current.temporaryFolder.path)
- })),
- 'root':
- Object.freeze(new WinFS('root', {
- name: 'root',
- //nativeURL: 'file:///'
- winpath: ''
- }))
- };
- }
- return AllFileSystems;
-}
-
-function getFS(name) {
- return getAllFS()[name];
-}
-
-FileSystem.prototype.__format__ = function(fullPath) {
- return getFS(this.name).__format__(fullPath);
-};
-
-require('./fileSystems').getFs = function(name, callback) {
- setTimeout(function(){callback(getFS(name));});
-};
-
-function getFilesystemFromPath(path) {
- var res;
- var allfs = getAllFS();
- Object.keys(allfs).some(function(fsn) {
- var fs = allfs[fsn];
- if (path.indexOf(fs.winpath) === 0)
- res = fs;
- return res;
- });
- return res;
-}
-
-var msapplhRE = new RegExp('^ms-appdata://localhost/');
-function pathFromURL(url) {
- url=url.replace(msapplhRE,'ms-appdata:///');
- var path = decodeURI(url);
- // support for file name with parameters
- if (/\?/g.test(path)) {
- path = String(path).split("?")[0];
- }
- if (path.indexOf("file:/")===0) {
- if (path.indexOf("file://") !== 0) {
- url = "file:///" + url.substr(6);
- }
- }
-
- ['file://','ms-appdata:///','cdvfile://localhost/'].every(function(p) {
- if (path.indexOf(p)!==0)
- return true;
- var thirdSlash = path.indexOf("/", p.length);
- if (thirdSlash < 0) {
- path = "";
- } else {
- path = sanitize(path.substr(thirdSlash));
- }
- });
-
- return path.replace('%3A',':').replace(driveRE,'$1');
-}
-
-function getFilesystemFromURL(url) {
- url=url.replace(msapplhRE,'ms-appdata:///');
- var res;
- if (url.indexOf("file:/")===0)
- res = getFilesystemFromPath(pathFromURL(url));
- else {
- var allfs = getAllFS();
- Object.keys(allfs).every(function(fsn) {
- var fs = allfs[fsn];
- if (url.indexOf(fs.root.nativeURL) === 0 ||
- url.indexOf('cdvfile://localhost/'+fs.name+'/') === 0)
- {
- res = fs;
- return false;
- }
- return true;
- });
- }
- return res;
-}
-
-function getFsPathForWinPath(fs, wpath) {
- var path = nativePathToCordova(wpath);
- if (path.indexOf(fs.winpath) !== 0)
- return null;
- return path.replace(fs.winpath,'/');
-}
-
-var WinError = {
- invalidArgument: -2147024809,
- fileNotFound: -2147024894,
- accessDenied: -2147024891
-};
-
-function openPath(path, ops) {
- ops=ops?ops:{};
- return new WinJS.Promise(function (complete,failed) {
- getFileFromPathAsync(path).done(
- function(file) {
- complete({file:file});
- },
- function(err) {
- if (err.number != WinError.fileNotFound && err.number != WinError.invalidArgument)
- failed(FileError.NOT_READABLE_ERR);
- getFolderFromPathAsync(path)
- .done(
- function(dir) {
- if (!ops.getContent)
- complete({folder:dir});
- else
- WinJS.Promise.join({
- files:dir.getFilesAsync(),
- folders:dir.getFoldersAsync()
- }).done(
- function(a) {
- complete({
- folder:dir,
- files:a.files,
- folders:a.folders
- });
- },
- function(err) {
- failed(FileError.NOT_READABLE_ERR);
- }
- );
- },
- function(err) {
- if (err.number == WinError.fileNotFound || err.number == WinError.invalidArgument)
- complete({});
- else
- failed(FileError.NOT_READABLE_ERR);
- }
- );
- }
- );
- });
-}
-
-function copyFolder(src,dst,name) {
- name = name?name:src.name;
- return new WinJS.Promise(function (complete,failed) {
- WinJS.Promise.join({
- fld:dst.createFolderAsync(name, Windows.Storage.CreationCollisionOption.openIfExists),
- files:src.getFilesAsync(),
- folders:src.getFoldersAsync()
- }).done(
- function(the) {
- if (!(the.files.length || the.folders.length)) {
- complete();
- return;
- }
- var todo = the.files.length;
- var copyfolders = function() {
- if (!todo--) {
- complete();
- return;
- }
- copyFolder(the.folders[todo],dst)
- .done(function() {copyfolders(); }, failed);
- };
- var copyfiles = function() {
- if (!todo--) {
- todo = the.folders.length;
- copyfolders();
- return;
- }
- the.files[todo].copyAsync(the.fld)
- .done(function() {copyfiles(); }, failed);
- };
- copyfiles();
- },
- failed
- );
- });
-}
-
-function moveFolder(src,dst,name) {
- name = name?name:src.name;
- return new WinJS.Promise(function (complete,failed) {
- var pending = [];
- WinJS.Promise.join({
- fld:dst.createFolderAsync(name, Windows.Storage.CreationCollisionOption.openIfExists),
- files:src.getFilesAsync(),
- folders:src.getFoldersAsync()
- }).done(
- function(the) {
- if (!(the.files.length || the.folders.length)) {
- complete();
- return;
- }
- var todo = the.files.length;
- var movefolders = function() {
- if (!todo--) {
- src.deleteAsync().done(complete,failed);
- return;
- }
- moveFolder(the.folders[todo],dst)
- .done(movefolders,failed);
- };
- var movefiles = function() {
- if (!todo--) {
- todo = the.folders.length;
- movefolders();
- return;
- }
- the.files[todo].moveAsync(the.fld)
- .done(function() {movefiles(); }, failed);
- };
- movefiles();
- },
- failed
- );
- });
-}
-
-function transport(success, fail, args, ops) { // ["fullPath","parent", "newName"]
- var src = args[0];
- var parent = args[1];
- var name = args[2];
-
- var srcFS = getFilesystemFromURL(src);
- var dstFS = getFilesystemFromURL(parent);
- var srcPath = pathFromURL(src);
- var dstPath = pathFromURL(parent);
- if (!(srcFS && dstFS && validName(name))){
- fail(FileError.ENCODING_ERR);
- return;
- }
-
- var srcWinPath = cordovaPathToNative(sanitize(srcFS.winpath + srcPath));
- var dstWinPath = cordovaPathToNative(sanitize(dstFS.winpath + dstPath));
- var tgtFsPath = sanitize(dstPath+'/'+name);
- var tgtWinPath = cordovaPathToNative(sanitize(dstFS.winpath + dstPath+'/'+name));
- if (srcWinPath == dstWinPath || srcWinPath == tgtWinPath) {
- fail(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
-
-
- WinJS.Promise.join({
- src:openPath(srcWinPath),
- dst:openPath(dstWinPath),
- tgt:openPath(tgtWinPath,{getContent:true})
- })
- .done(
- function (the) {
- if ((!the.dst.folder) || !(the.src.folder || the.src.file)) {
- fail(FileError.NOT_FOUND_ERR);
- return;
- }
- if ( (the.src.folder && the.tgt.file)
- || (the.src.file && the.tgt.folder)
- || (the.tgt.folder && (the.tgt.files.length || the.tgt.folders.length)))
- {
- fail(FileError.INVALID_MODIFICATION_ERR);
- return;
- }
- if (the.src.file)
- ops.fileOp(the.src.file,the.dst.folder, name, Windows.Storage.NameCollisionOption.replaceExisting)
- .done(
- function (storageFile) {
- success(new FileEntry(
- name,
- tgtFsPath,
- dstFS.name,
- dstFS.makeNativeURL(tgtFsPath)
- ));
- },
- function (err) {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
- else
- ops.folderOp(the.src.folder, the.dst.folder, name).done(
- function () {
- success(new DirectoryEntry(
- name,
- tgtFsPath,
- dstFS.name,
- dstFS.makeNativeURL(tgtFsPath)
- ));
- },
- function() {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
- },
- function(err) {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
-}
-
-module.exports = {
- requestAllFileSystems: function() {
- return getAllFS();
- },
- getFileMetadata: function (success, fail, args) {
- module.exports.getMetadata(success, fail, args);
- },
-
- getMetadata: function (success, fail, args) {
- var fs = getFilesystemFromURL(args[0]);
- var path = pathFromURL(args[0]);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var fullPath = cordovaPathToNative(fs.winpath + path);
-
- var getMetadataForFile = function (storageFile) {
- storageFile.getBasicPropertiesAsync().then(
- function (basicProperties) {
- success(new File(storageFile.name, storageFile.path, storageFile.fileType, basicProperties.dateModified, basicProperties.size));
- }, function () {
- fail(FileError.NOT_READABLE_ERR);
- }
- );
- };
-
- var getMetadataForFolder = function (storageFolder) {
- storageFolder.getBasicPropertiesAsync().then(
- function (basicProperties) {
- var metadata = {
- size: basicProperties.size,
- lastModifiedDate: basicProperties.dateModified
- };
- success(metadata);
- },
- function () {
- fail(FileError.NOT_READABLE_ERR);
- }
- );
- };
-
- getFileFromPathAsync(fullPath).then(getMetadataForFile,
- function () {
- getFolderFromPathAsync(fullPath).then(getMetadataForFolder,
- function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- }
- );
- },
-
- getParent: function (win, fail, args) { // ["fullPath"]
- var fs = getFilesystemFromURL(args[0]);
- var path = pathFromURL(args[0]);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
- if (!path || (new RegExp('/[^/]*/?$')).test(path)) {
- win(new DirectoryEntry(fs.root.name, fs.root.fullPath, fs.name, fs.makeNativeURL(fs.root.fullPath)));
- return;
- }
-
- var parpath = path.replace(new RegExp('/[^/]+/?$','g'),'');
- var parname = path.substr(parpath.length);
- var fullPath = cordovaPathToNative(fs.winpath + parpath);
-
- var result = new DirectoryEntry(parname, parpath, fs.name, fs.makeNativeURL(parpath));
- getFolderFromPathAsync(fullPath).done(
- function () { win(result); },
- function () { fail(FileError.INVALID_STATE_ERR); }
- );
- },
-
- readAsText: function (win, fail, args) {
-
- var url = args[0],
- enc = args[1],
- startPos = args[2],
- endPos = args[3];
-
- var fs = getFilesystemFromURL(url);
- var path = pathFromURL(url);
- if (!fs){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var wpath = cordovaPathToNative(sanitize(fs.winpath + path));
-
- var encoding = Windows.Storage.Streams.UnicodeEncoding.utf8;
- if (enc == 'Utf16LE' || enc == 'utf16LE') {
- encoding = Windows.Storage.Streams.UnicodeEncoding.utf16LE;
- } else if (enc == 'Utf16BE' || enc == 'utf16BE') {
- encoding = Windows.Storage.Streams.UnicodeEncoding.utf16BE;
- }
-
- getFileFromPathAsync(wpath).then(function(file) {
- return file.openReadAsync();
- }).then(function (stream) {
- startPos = (startPos < 0) ? Math.max(stream.size + startPos, 0) : Math.min(stream.size, startPos);
- endPos = (endPos < 0) ? Math.max(endPos + stream.size, 0) : Math.min(stream.size, endPos);
- stream.seek(startPos);
-
- var readSize = endPos - startPos,
- buffer = new Windows.Storage.Streams.Buffer(readSize);
-
- return stream.readAsync(buffer, readSize, Windows.Storage.Streams.InputStreamOptions.none);
- }).done(function(buffer) {
- win(Windows.Security.Cryptography.CryptographicBuffer.convertBinaryToString(encoding, buffer));
- },function() {
- fail(FileError.NOT_FOUND_ERR);
- });
- },
-
- readAsBinaryString:function(win,fail,args) {
- var url = args[0],
- startPos = args[1],
- endPos = args[2];
-
- var fs = getFilesystemFromURL(url);
- var path = pathFromURL(url);
- if (!fs){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var wpath = cordovaPathToNative(sanitize(fs.winpath + path));
-
- getFileFromPathAsync(wpath).then(
- function (storageFile) {
- Windows.Storage.FileIO.readBufferAsync(storageFile).done(
- function (buffer) {
- var dataReader = Windows.Storage.Streams.DataReader.fromBuffer(buffer);
- // var fileContent = dataReader.readString(buffer.length);
- var byteArray = new Uint8Array(buffer.length),
- byteString = "";
- dataReader.readBytes(byteArray);
- dataReader.close();
- for (var i = 0; i < byteArray.length; i++) {
- var charByte = byteArray[i];
- // var charRepresentation = charByte <= 127 ? String.fromCharCode(charByte) : charByte.toString(16);
- var charRepresentation = String.fromCharCode(charByte);
- byteString += charRepresentation;
- }
- win(byteString.slice(startPos, endPos));
- }
- );
- }, function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- },
-
- readAsArrayBuffer:function(win,fail,args) {
- var url = args[0];
- var fs = getFilesystemFromURL(url);
- var path = pathFromURL(url);
- if (!fs){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var wpath = cordovaPathToNative(sanitize(fs.winpath + path));
-
- getFileFromPathAsync(wpath).then(
- function (storageFile) {
- var blob = MSApp.createFileFromStorageFile(storageFile);
- var url = URL.createObjectURL(blob, { oneTimeOnly: true });
- var xhr = new XMLHttpRequest();
- xhr.open("GET", url, true);
- xhr.responseType = 'arraybuffer';
- xhr.onload = function () {
- var resultArrayBuffer = xhr.response;
- // get start and end position of bytes in buffer to be returned
- var startPos = args[1] || 0,
- endPos = args[2] || resultArrayBuffer.length;
- // if any of them is specified, we'll slice output array
- if (startPos !== 0 || endPos !== resultArrayBuffer.length) {
- // slice method supported only on Windows 8.1, so we need to check if it's available
- // see http://msdn.microsoft.com/en-us/library/ie/dn641192(v=vs.94).aspx
- if (resultArrayBuffer.slice) {
- resultArrayBuffer = resultArrayBuffer.slice(startPos, endPos);
- } else {
- // if slice isn't available, we'll use workaround method
- var tempArray = new Uint8Array(resultArrayBuffer),
- resBuffer = new ArrayBuffer(endPos - startPos),
- resArray = new Uint8Array(resBuffer);
-
- for (var i = 0; i < resArray.length; i++) {
- resArray[i] = tempArray[i + startPos];
- }
- resultArrayBuffer = resBuffer;
- }
- }
- win(resultArrayBuffer);
- };
- xhr.send();
- }, function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- },
-
- readAsDataURL: function (win, fail, args) {
- var url = args[0];
- var fs = getFilesystemFromURL(url);
- var path = pathFromURL(url);
- if (!fs){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var wpath = cordovaPathToNative(sanitize(fs.winpath + path));
-
- getFileFromPathAsync(wpath).then(
- function (storageFile) {
- Windows.Storage.FileIO.readBufferAsync(storageFile).done(
- function (buffer) {
- var strBase64 = Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer);
- //the method encodeToBase64String will add "77u/" as a prefix, so we should remove it
- if(String(strBase64).substr(0,4) == "77u/") {
- strBase64 = strBase64.substr(4);
- }
- var mediaType = storageFile.contentType;
- var result = "data:" + mediaType + ";base64," + strBase64;
- win(result);
- }
- );
- }, function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- },
-
- getDirectory: function (win, fail, args) {
- var dirurl = args[0];
- var path = args[1];
- var options = args[2];
-
- var fs = getFilesystemFromURL(dirurl);
- var dirpath = pathFromURL(dirurl);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var fspath = sanitize(dirpath +'/'+ path);
- var completePath = sanitize(fs.winpath + fspath);
-
- var name = completePath.substring(completePath.lastIndexOf('/')+1);
-
- var wpath = cordovaPathToNative(completePath.substring(0, completePath.lastIndexOf('/')));
-
- var flag = "";
- if (options) {
- flag = new Flags(options.create, options.exclusive);
- } else {
- flag = new Flags(false, false);
- }
-
- getFolderFromPathAsync(wpath).done(
- function (storageFolder) {
- if (flag.create === true && flag.exclusive === true) {
- storageFolder.createFolderAsync(name, Windows.Storage.CreationCollisionOption.failIfExists).done(
- function (storageFolder) {
- win(new DirectoryEntry(storageFolder.name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }, function (err) {
- fail(FileError.PATH_EXISTS_ERR);
- }
- );
- } else if (flag.create === true && flag.exclusive === false) {
- storageFolder.createFolderAsync(name, Windows.Storage.CreationCollisionOption.openIfExists).done(
- function (storageFolder) {
- win(new DirectoryEntry(storageFolder.name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
- } else if (flag.create === false) {
- storageFolder.getFolderAsync(name).done(
- function (storageFolder) {
- win(new DirectoryEntry(storageFolder.name, fspath, fs.name, fs.makeNativeURL(fspath)));
- },
- function () {
- // check if path actually points to a file
- storageFolder.getFileAsync(name).done(
- function () {
- fail(FileError.TYPE_MISMATCH_ERR);
- }, function() {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- }
- );
- }
- }, function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- },
-
- remove: function (win, fail, args) {
- var fs = getFilesystemFromURL(args[0]);
- var path = pathFromURL(args[0]);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
-
- // FileSystem root can't be removed!
- if (!path || path=='/'){
- fail(FileError.NO_MODIFICATION_ALLOWED_ERR);
- return;
- }
- var fullPath = cordovaPathToNative(fs.winpath + path);
-
- getFileFromPathAsync(fullPath).then(
- function (storageFile) {
- storageFile.deleteAsync().done(win, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- });
- },
- function () {
- getFolderFromPathAsync(fullPath).done(
- function (sFolder) {
- sFolder.getFilesAsync()
- // check for files
- .then(function(fileList) {
- if (fileList) {
- if (fileList.length === 0) {
- return sFolder.getFoldersAsync();
- } else {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- }
- })
- // check for folders
- .done(function (folderList) {
- if (folderList) {
- if (folderList.length === 0) {
- sFolder.deleteAsync().done(
- win,
- function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
- } else {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- }
- });
- },
- function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- }
- );
- },
-
- removeRecursively: function (successCallback, fail, args) {
-
- var fs = getFilesystemFromURL(args[0]);
- var path = pathFromURL(args[0]);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
-
- // FileSystem root can't be removed!
- if (!path || path=='/'){
- fail(FileError.NO_MODIFICATION_ALLOWED_ERR);
- return;
- }
- var fullPath = cordovaPathToNative(fs.winpath + path);
-
- getFolderFromPathAsync(fullPath).done(function (storageFolder) {
- storageFolder.deleteAsync().done(function (res) {
- successCallback(res);
- }, function (err) {
- fail(err);
- });
-
- }, function () {
- fail(FileError.FILE_NOT_FOUND_ERR);
- });
- },
-
- getFile: function (win, fail, args) {
-
- var dirurl = args[0];
- var path = args[1];
- var options = args[2];
-
- var fs = getFilesystemFromURL(dirurl);
- var dirpath = pathFromURL(dirurl);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var fspath = sanitize(dirpath +'/'+ path);
- var completePath = sanitize(fs.winpath + fspath);
-
- var fileName = completePath.substring(completePath.lastIndexOf('/')+1);
-
- var wpath = cordovaPathToNative(completePath.substring(0, completePath.lastIndexOf('/')));
-
- var flag = "";
- if (options !== null) {
- flag = new Flags(options.create, options.exclusive);
- } else {
- flag = new Flags(false, false);
- }
-
- getFolderFromPathAsync(wpath).done(
- function (storageFolder) {
- if (flag.create === true && flag.exclusive === true) {
- storageFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.failIfExists).done(
- function (storageFile) {
- win(new FileEntry(storageFile.name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }, function () {
- fail(FileError.PATH_EXISTS_ERR);
- }
- );
- } else if (flag.create === true && flag.exclusive === false) {
- storageFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.openIfExists).done(
- function (storageFile) {
- win(new FileEntry(storageFile.name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }, function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
- } else if (flag.create === false) {
- storageFolder.getFileAsync(fileName).done(
- function (storageFile) {
- win(new FileEntry(storageFile.name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }, function () {
- // check if path actually points to a folder
- storageFolder.getFolderAsync(fileName).done(
- function () {
- fail(FileError.TYPE_MISMATCH_ERR);
- }, function () {
- fail(FileError.NOT_FOUND_ERR);
- });
- }
- );
- }
- }, function (err) {
- fail(
- err.number == WinError.accessDenied?
- FileError.SECURITY_ERR:
- FileError.NOT_FOUND_ERR
- );
- }
- );
- },
-
- readEntries: function (win, fail, args) { // ["fullPath"]
- var fs = getFilesystemFromURL(args[0]);
- var path = pathFromURL(args[0]);
- if (!fs || !validName(path)){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var fullPath = cordovaPathToNative(fs.winpath + path);
-
- var result = [];
-
- getFolderFromPathAsync(fullPath).done(function (storageFolder) {
- var promiseArr = [];
- var index = 0;
- promiseArr[index++] = storageFolder.getFilesAsync().then(function (fileList) {
- if (fileList !== null) {
- for (var i = 0; i < fileList.length; i++) {
- var fspath = getFsPathForWinPath(fs, fileList[i].path);
- if (!fspath) {
- fail(FileError.NOT_FOUND_ERR);
- return;
- }
- result.push(new FileEntry(fileList[i].name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }
- }
- });
- promiseArr[index++] = storageFolder.getFoldersAsync().then(function (folderList) {
- if (folderList !== null) {
- for (var j = 0; j < folderList.length; j++) {
- var fspath = getFsPathForWinPath(fs, folderList[j].path);
- if (!fspath) {
- fail(FileError.NOT_FOUND_ERR);
- return;
- }
- result.push(new DirectoryEntry(folderList[j].name, fspath, fs.name, fs.makeNativeURL(fspath)));
- }
- }
- });
- WinJS.Promise.join(promiseArr).then(function () {
- win(result);
- });
-
- }, function () { fail(FileError.NOT_FOUND_ERR); });
- },
-
- write: function (win, fail, args) {
-
- var url = args[0],
- data = args[1],
- position = args[2],
- isBinary = args[3];
-
- var fs = getFilesystemFromURL(url);
- var path = pathFromURL(url);
- if (!fs){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var completePath = sanitize(fs.winpath + path);
- var fileName = completePath.substring(completePath.lastIndexOf('/')+1);
- var dirpath = completePath.substring(0,completePath.lastIndexOf('/'));
- var wpath = cordovaPathToNative(dirpath);
-
- function getWriteMethodForData(data, isBinary) {
-
- if (data instanceof Blob) {
- return writeBlobAsync;
- }
-
- if (data instanceof ArrayBuffer) {
- return writeArrayBufferAsync;
- }
-
- if (isBinary) {
- return writeBytesAsync;
- }
-
- if (typeof data === 'string') {
- return writeTextAsync;
- }
-
- throw new Error('Unsupported data type for write method');
- }
-
- var writePromise = getWriteMethodForData(data, isBinary);
-
- getFolderFromPathAsync(wpath).done(
- function (storageFolder) {
- storageFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.openIfExists).done(
- function (storageFile) {
- writePromise(storageFile, data, position).done(
- function (bytesWritten) {
- var written = bytesWritten || data.length;
- win(written);
- },
- function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
- },
- function () {
- fail(FileError.INVALID_MODIFICATION_ERR);
- }
- );
-
- },
- function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- },
-
- truncate: function (win, fail, args) { // ["fileName","size"]
- var url = args[0];
- var size = args[1];
-
- var fs = getFilesystemFromURL(url);
- var path = pathFromURL(url);
- if (!fs){
- fail(FileError.ENCODING_ERR);
- return;
- }
- var completePath = sanitize(fs.winpath + path);
- var wpath = cordovaPathToNative(completePath);
- var dirwpath = cordovaPathToNative(completePath.substring(0,completePath.lastIndexOf('/')));
-
- getFileFromPathAsync(wpath).done(function(storageFile){
- //the current length of the file.
- var leng = 0;
-
- storageFile.getBasicPropertiesAsync().then(function (basicProperties) {
- leng = basicProperties.size;
- if (Number(size) >= leng) {
- win(this.length);
- return;
- }
- if (Number(size) >= 0) {
- Windows.Storage.FileIO.readTextAsync(storageFile, Windows.Storage.Streams.UnicodeEncoding.utf8).then(function (fileContent) {
- fileContent = fileContent.substr(0, size);
- var fullPath = storageFile.path;
- var name = storageFile.name;
- storageFile.deleteAsync().then(function () {
- return getFolderFromPathAsync(dirwpath);
- }).done(function (storageFolder) {
- storageFolder.createFileAsync(name).then(function (newStorageFile) {
- Windows.Storage.FileIO.writeTextAsync(newStorageFile, fileContent).done(function () {
- win(String(fileContent).length);
- }, function () {
- fail(FileError.NO_MODIFICATION_ALLOWED_ERR);
- });
- }, function() {
- fail(FileError.NO_MODIFICATION_ALLOWED_ERR);
- });
- });
- }, function () { fail(FileError.NOT_FOUND_ERR); });
- }
- });
- }, function () { fail(FileError.NOT_FOUND_ERR); });
- },
-
- copyTo: function (success, fail, args) { // ["fullPath","parent", "newName"]
- transport(success, fail, args,
- {
- fileOp:function(file,folder,name,coll) {
- return file.copyAsync(folder,name,coll);
- },
- folderOp:function(src,dst,name) {
- return copyFolder(src,dst,name);
- }}
- );
- },
-
- moveTo: function (success, fail, args) {
- transport(success, fail, args,
- {
- fileOp:function(file,folder,name,coll) {
- return file.moveAsync(folder,name,coll);
- },
- folderOp:function(src,dst,name) {
- return moveFolder(src,dst,name);
- }}
- );
- },
- tempFileSystem:null,
-
- persistentFileSystem:null,
-
- requestFileSystem: function (win, fail, args) {
-
- var type = args[0];
- var size = args[1];
- var MAX_SIZE = 10000000000;
- if (size > MAX_SIZE) {
- fail(FileError.QUOTA_EXCEEDED_ERR);
- return;
- }
-
- var fs;
- switch (type) {
- case LocalFileSystem.TEMPORARY:
- fs = getFS('temporary');
- break;
- case LocalFileSystem.PERSISTENT:
- fs = getFS('persistent');
- break;
- }
- if (fs)
- win(fs);
- else
- fail(FileError.NOT_FOUND_ERR);
- },
-
- resolveLocalFileSystemURI: function (success, fail, args) {
-
- var uri = args[0];
- var inputURL;
-
- var path = pathFromURL(uri);
- var fs = getFilesystemFromURL(uri);
- if (!fs || !validName(path)) {
- fail(FileError.ENCODING_ERR);
- return;
- }
- if (path.indexOf(fs.winpath) === 0)
- path=path.substr(fs.winpath.length);
- var abspath = cordovaPathToNative(fs.winpath+path);
-
- getFileFromPathAsync(abspath).done(
- function (storageFile) {
- success(new FileEntry(storageFile.name, path, fs.name, fs.makeNativeURL(path)));
- }, function () {
- getFolderFromPathAsync(abspath).done(
- function (storageFolder) {
- success(new DirectoryEntry(storageFolder.name, path, fs.name,fs.makeNativeURL(path)));
- }, function () {
- fail(FileError.NOT_FOUND_ERR);
- }
- );
- }
- );
- }
-
-
-};
-
-require("cordova/exec/proxy").add("File",module.exports);
diff --git a/plugins/cordova-plugin-file/src/wp/File.cs b/plugins/cordova-plugin-file/src/wp/File.cs
deleted file mode 100644
index 203d8d42..00000000
--- a/plugins/cordova-plugin-file/src/wp/File.cs
+++ /dev/null
@@ -1,1800 +0,0 @@
-/*
- Licensed 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.
-*/
-
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.IO;
-using System.IO.IsolatedStorage;
-using System.Runtime.Serialization;
-using System.Security;
-using System.Text;
-using System.Windows;
-using System.Windows.Resources;
-using WPCordovaClassLib.Cordova.JSON;
-
-namespace WPCordovaClassLib.Cordova.Commands
-{
- /// <summary>
- /// Provides access to isolated storage
- /// </summary>
- public class File : BaseCommand
- {
- // Error codes
- public const int NOT_FOUND_ERR = 1;
- public const int SECURITY_ERR = 2;
- public const int ABORT_ERR = 3;
- public const int NOT_READABLE_ERR = 4;
- public const int ENCODING_ERR = 5;
- public const int NO_MODIFICATION_ALLOWED_ERR = 6;
- public const int INVALID_STATE_ERR = 7;
- public const int SYNTAX_ERR = 8;
- public const int INVALID_MODIFICATION_ERR = 9;
- public const int QUOTA_EXCEEDED_ERR = 10;
- public const int TYPE_MISMATCH_ERR = 11;
- public const int PATH_EXISTS_ERR = 12;
-
- // File system options
- public const int TEMPORARY = 0;
- public const int PERSISTENT = 1;
- public const int RESOURCE = 2;
- public const int APPLICATION = 3;
-
- /// <summary>
- /// Temporary directory name
- /// </summary>
- private readonly string TMP_DIRECTORY_NAME = "tmp";
-
- /// <summary>
- /// Represents error code for callback
- /// </summary>
- [DataContract]
- public class ErrorCode
- {
- /// <summary>
- /// Error code
- /// </summary>
- [DataMember(IsRequired = true, Name = "code")]
- public int Code { get; set; }
-
- /// <summary>
- /// Creates ErrorCode object
- /// </summary>
- public ErrorCode(int code)
- {
- this.Code = code;
- }
- }
-
- /// <summary>
- /// Represents File action options.
- /// </summary>
- [DataContract]
- public class FileOptions
- {
- /// <summary>
- /// File path
- /// </summary>
- ///
- private string _fileName;
- [DataMember(Name = "fileName")]
- public string FilePath
- {
- get
- {
- return this._fileName;
- }
-
- set
- {
- int index = value.IndexOfAny(new char[] { '#', '?' });
- this._fileName = index > -1 ? value.Substring(0, index) : value;
- }
- }
-
- /// <summary>
- /// Full entryPath
- /// </summary>
- [DataMember(Name = "fullPath")]
- public string FullPath { get; set; }
-
- /// <summary>
- /// Directory name
- /// </summary>
- [DataMember(Name = "dirName")]
- public string DirectoryName { get; set; }
-
- /// <summary>
- /// Path to create file/directory
- /// </summary>
- [DataMember(Name = "path")]
- public string Path { get; set; }
-
- /// <summary>
- /// The encoding to use to encode the file's content. Default is UTF8.
- /// </summary>
- [DataMember(Name = "encoding")]
- public string Encoding { get; set; }
-
- /// <summary>
- /// Uri to get file
- /// </summary>
- ///
- private string _uri;
- [DataMember(Name = "uri")]
- public string Uri
- {
- get
- {
- return this._uri;
- }
-
- set
- {
- int index = value.IndexOfAny(new char[] { '#', '?' });
- this._uri = index > -1 ? value.Substring(0, index) : value;
- }
- }
-
- /// <summary>
- /// Size to truncate file
- /// </summary>
- [DataMember(Name = "size")]
- public long Size { get; set; }
-
- /// <summary>
- /// Data to write in file
- /// </summary>
- [DataMember(Name = "data")]
- public string Data { get; set; }
-
- /// <summary>
- /// Position the writing starts with
- /// </summary>
- [DataMember(Name = "position")]
- public int Position { get; set; }
-
- /// <summary>
- /// Type of file system requested
- /// </summary>
- [DataMember(Name = "type")]
- public int FileSystemType { get; set; }
-
- /// <summary>
- /// New file/directory name
- /// </summary>
- [DataMember(Name = "newName")]
- public string NewName { get; set; }
-
- /// <summary>
- /// Destination directory to copy/move file/directory
- /// </summary>
- [DataMember(Name = "parent")]
- public string Parent { get; set; }
-
- /// <summary>
- /// Options for getFile/getDirectory methods
- /// </summary>
- [DataMember(Name = "options")]
- public CreatingOptions CreatingOpt { get; set; }
-
- /// <summary>
- /// Creates options object with default parameters
- /// </summary>
- public FileOptions()
- {
- this.SetDefaultValues(new StreamingContext());
- }
-
- /// <summary>
- /// Initializes default values for class fields.
- /// Implemented in separate method because default constructor is not invoked during deserialization.
- /// </summary>
- /// <param name="context"></param>
- [OnDeserializing()]
- public void SetDefaultValues(StreamingContext context)
- {
- this.Encoding = "UTF-8";
- this.FilePath = "";
- this.FileSystemType = -1;
- }
- }
-
- /// <summary>
- /// Stores image info
- /// </summary>
- [DataContract]
- public class FileMetadata
- {
- [DataMember(Name = "fileName")]
- public string FileName { get; set; }
-
- [DataMember(Name = "fullPath")]
- public string FullPath { get; set; }
-
- [DataMember(Name = "type")]
- public string Type { get; set; }
-
- [DataMember(Name = "lastModifiedDate")]
- public string LastModifiedDate { get; set; }
-
- [DataMember(Name = "size")]
- public long Size { get; set; }
-
- public FileMetadata(string filePath)
- {
- if (string.IsNullOrEmpty(filePath))
- {
- throw new FileNotFoundException("File doesn't exist");
- }
-
- this.FullPath = filePath;
- this.Size = 0;
- this.FileName = string.Empty;
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- bool IsFile = isoFile.FileExists(filePath);
- bool IsDirectory = isoFile.DirectoryExists(filePath);
-
- if (!IsDirectory)
- {
- if (!IsFile) // special case, if isoFile cannot find it, it might still be part of the app-package
- {
- // attempt to get it from the resources
-
- Uri fileUri = new Uri(filePath, UriKind.Relative);
- StreamResourceInfo streamInfo = Application.GetResourceStream(fileUri);
- if (streamInfo != null)
- {
- this.Size = streamInfo.Stream.Length;
- this.FileName = filePath.Substring(filePath.LastIndexOf("/") + 1);
- }
- else
- {
- throw new FileNotFoundException("File doesn't exist");
- }
- }
- else
- {
- using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, isoFile))
- {
- this.Size = stream.Length;
- }
-
- this.FileName = System.IO.Path.GetFileName(filePath);
- this.LastModifiedDate = isoFile.GetLastWriteTime(filePath).DateTime.ToString();
- }
- }
-
- this.Type = MimeTypeMapper.GetMimeType(this.FileName);
- }
- }
- }
-
- /// <summary>
- /// Represents file or directory modification metadata
- /// </summary>
- [DataContract]
- public class ModificationMetadata
- {
- /// <summary>
- /// Modification time
- /// </summary>
- [DataMember]
- public string modificationTime { get; set; }
- }
-
- /// <summary>
- /// Represents file or directory entry
- /// </summary>
- [DataContract]
- public class FileEntry
- {
-
- /// <summary>
- /// File type
- /// </summary>
- [DataMember(Name = "isFile")]
- public bool IsFile { get; set; }
-
- /// <summary>
- /// Directory type
- /// </summary>
- [DataMember(Name = "isDirectory")]
- public bool IsDirectory { get; set; }
-
- /// <summary>
- /// File/directory name
- /// </summary>
- [DataMember(Name = "name")]
- public string Name { get; set; }
-
- /// <summary>
- /// Full path to file/directory
- /// </summary>
- [DataMember(Name = "fullPath")]
- public string FullPath { get; set; }
-
- /// <summary>
- /// URI encoded fullpath
- /// </summary>
- [DataMember(Name = "nativeURL")]
- public string NativeURL
- {
- set { }
- get
- {
- string escaped = Uri.EscapeUriString(this.FullPath);
- escaped = escaped.Replace("//", "/");
- if (escaped.StartsWith("/"))
- {
- escaped = escaped.Insert(0, "/");
- }
- return escaped;
- }
- }
-
- public bool IsResource { get; set; }
-
- public static FileEntry GetEntry(string filePath, bool bIsRes=false)
- {
- FileEntry entry = null;
- try
- {
- entry = new FileEntry(filePath, bIsRes);
-
- }
- catch (Exception ex)
- {
- Debug.WriteLine("Exception in GetEntry for filePath :: " + filePath + " " + ex.Message);
- }
- return entry;
- }
-
- /// <summary>
- /// Creates object and sets necessary properties
- /// </summary>
- /// <param name="filePath"></param>
- public FileEntry(string filePath, bool bIsRes = false)
- {
- if (string.IsNullOrEmpty(filePath))
- {
- throw new ArgumentException();
- }
-
- if(filePath.Contains(" "))
- {
- Debug.WriteLine("FilePath with spaces :: " + filePath);
- }
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- IsResource = bIsRes;
- IsFile = isoFile.FileExists(filePath);
- IsDirectory = isoFile.DirectoryExists(filePath);
- if (IsFile)
- {
- this.Name = Path.GetFileName(filePath);
- }
- else if (IsDirectory)
- {
- this.Name = this.GetDirectoryName(filePath);
- if (string.IsNullOrEmpty(Name))
- {
- this.Name = "/";
- }
- }
- else
- {
- if (IsResource)
- {
- this.Name = Path.GetFileName(filePath);
- }
- else
- {
- throw new FileNotFoundException();
- }
- }
-
- try
- {
- this.FullPath = filePath.Replace('\\', '/'); // new Uri(filePath).LocalPath;
- }
- catch (Exception)
- {
- this.FullPath = filePath;
- }
- }
- }
-
- /// <summary>
- /// Extracts directory name from path string
- /// Path should refer to a directory, for example \foo\ or /foo.
- /// </summary>
- /// <param name="path"></param>
- /// <returns></returns>
- private string GetDirectoryName(string path)
- {
- if (String.IsNullOrEmpty(path))
- {
- return path;
- }
-
- string[] split = path.Split(new char[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
- if (split.Length < 1)
- {
- return null;
- }
- else
- {
- return split[split.Length - 1];
- }
- }
- }
-
-
- /// <summary>
- /// Represents info about requested file system
- /// </summary>
- [DataContract]
- public class FileSystemInfo
- {
- /// <summary>
- /// file system type
- /// </summary>
- [DataMember(Name = "name", IsRequired = true)]
- public string Name { get; set; }
-
- /// <summary>
- /// Root directory entry
- /// </summary>
- [DataMember(Name = "root", EmitDefaultValue = false)]
- public FileEntry Root { get; set; }
-
- /// <summary>
- /// Creates class instance
- /// </summary>
- /// <param name="name"></param>
- /// <param name="rootEntry"> Root directory</param>
- public FileSystemInfo(string name, FileEntry rootEntry = null)
- {
- Name = name;
- Root = rootEntry;
- }
- }
-
- [DataContract]
- public class CreatingOptions
- {
- /// <summary>
- /// Create file/directory if is doesn't exist
- /// </summary>
- [DataMember(Name = "create")]
- public bool Create { get; set; }
-
- /// <summary>
- /// Generate an exception if create=true and file/directory already exists
- /// </summary>
- [DataMember(Name = "exclusive")]
- public bool Exclusive { get; set; }
-
-
- }
-
- // returns null value if it fails.
- private string[] getOptionStrings(string options)
- {
- string[] optStings = null;
- try
- {
- optStings = JSON.JsonHelper.Deserialize<string[]>(options);
- }
- catch (Exception)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), CurrentCommandCallbackId);
- }
- return optStings;
- }
-
- /// <summary>
- /// Gets amount of free space available for Isolated Storage
- /// </summary>
- /// <param name="options">No options is needed for this method</param>
- public void getFreeDiskSpace(string options)
- {
- string callbackId = getOptionStrings(options)[0];
-
- try
- {
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isoFile.AvailableFreeSpace), callbackId);
- }
- }
- catch (IsolatedStorageException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- /// <summary>
- /// Check if file exists
- /// </summary>
- /// <param name="options">File path</param>
- public void testFileExists(string options)
- {
- IsDirectoryOrFileExist(options, false);
- }
-
- /// <summary>
- /// Check if directory exists
- /// </summary>
- /// <param name="options">directory name</param>
- public void testDirectoryExists(string options)
- {
- IsDirectoryOrFileExist(options, true);
- }
-
- /// <summary>
- /// Check if file or directory exist
- /// </summary>
- /// <param name="options">File path/Directory name</param>
- /// <param name="isDirectory">Flag to recognize what we should check</param>
- public void IsDirectoryOrFileExist(string options, bool isDirectory)
- {
- string[] args = getOptionStrings(options);
- string callbackId = args[1];
- FileOptions fileOptions = JSON.JsonHelper.Deserialize<FileOptions>(args[0]);
- string filePath = args[0];
-
- if (fileOptions == null)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
- }
-
- try
- {
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- bool isExist;
- if (isDirectory)
- {
- isExist = isoFile.DirectoryExists(fileOptions.DirectoryName);
- }
- else
- {
- isExist = isoFile.FileExists(fileOptions.FilePath);
- }
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, isExist), callbackId);
- }
- }
- catch (IsolatedStorageException) // default handler throws INVALID_MODIFICATION_ERR
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
- }
-
- }
-
- public void readAsDataURL(string options)
- {
- string[] optStrings = getOptionStrings(options);
- string filePath = optStrings[0];
- int startPos = int.Parse(optStrings[1]);
- int endPos = int.Parse(optStrings[2]);
- string callbackId = optStrings[3];
-
- if (filePath != null)
- {
- try
- {
- string base64URL = null;
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (!isoFile.FileExists(filePath))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
- string mimeType = MimeTypeMapper.GetMimeType(filePath);
-
- using (IsolatedStorageFileStream stream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
- {
- string base64String = GetFileContent(stream);
- base64URL = "data:" + mimeType + ";base64," + base64String;
- }
- }
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, base64URL), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
- }
-
- private byte[] readFileBytes(string filePath,int startPos,int endPos, IsolatedStorageFile isoFile)
- {
- byte[] buffer;
- using (IsolatedStorageFileStream reader = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
- {
- if (startPos < 0)
- {
- startPos = Math.Max((int)reader.Length + startPos, 0);
- }
- else if (startPos > 0)
- {
- startPos = Math.Min((int)reader.Length, startPos);
- }
- if (endPos > 0)
- {
- endPos = Math.Min((int)reader.Length, endPos);
- }
- else if (endPos < 0)
- {
- endPos = Math.Max(endPos + (int)reader.Length, 0);
- }
-
- buffer = new byte[endPos - startPos];
- reader.Seek(startPos, SeekOrigin.Begin);
- reader.Read(buffer, 0, buffer.Length);
- }
-
- return buffer;
- }
-
- public void readAsArrayBuffer(string options)
- {
- string[] optStrings = getOptionStrings(options);
- string filePath = optStrings[0];
- int startPos = int.Parse(optStrings[1]);
- int endPos = int.Parse(optStrings[2]);
- string callbackId = optStrings[3];
-
- try
- {
- byte[] buffer;
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (!isoFile.FileExists(filePath))
- {
- readResourceAsText(options);
- return;
- }
- buffer = readFileBytes(filePath, startPos, endPos, isoFile);
- }
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, buffer), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- public void readAsBinaryString(string options)
- {
- string[] optStrings = getOptionStrings(options);
- string filePath = optStrings[0];
- int startPos = int.Parse(optStrings[1]);
- int endPos = int.Parse(optStrings[2]);
- string callbackId = optStrings[3];
-
- try
- {
- string result;
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (!isoFile.FileExists(filePath))
- {
- readResourceAsText(options);
- return;
- }
-
- byte[] buffer = readFileBytes(filePath, startPos, endPos, isoFile);
- result = System.Text.Encoding.GetEncoding("iso-8859-1").GetString(buffer, 0, buffer.Length);
-
- }
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, result), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- public void readAsText(string options)
- {
- string[] optStrings = getOptionStrings(options);
- string filePath = optStrings[0];
- string encStr = optStrings[1];
- int startPos = int.Parse(optStrings[2]);
- int endPos = int.Parse(optStrings[3]);
- string callbackId = optStrings[4];
-
- try
- {
- string text = "";
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (!isoFile.FileExists(filePath))
- {
- readResourceAsText(options);
- return;
- }
- Encoding encoding = Encoding.GetEncoding(encStr);
-
- byte[] buffer = this.readFileBytes(filePath, startPos, endPos, isoFile);
- text = encoding.GetString(buffer, 0, buffer.Length);
- }
-
- // JIRA: https://issues.apache.org/jira/browse/CB-8792
- // Need to perform additional serialization here because NativeExecution is always trying
- // to do JSON.parse() on command result. This leads to issue when trying to read JSON files
- var resultText = JsonHelper.Serialize(text);
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, resultText), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- /// <summary>
- /// Reads application resource as a text
- /// </summary>
- /// <param name="options">Path to a resource</param>
- public void readResourceAsText(string options)
- {
- string[] optStrings = getOptionStrings(options);
- string pathToResource = optStrings[0];
- string encStr = optStrings[1];
- int start = int.Parse(optStrings[2]);
- int endMarker = int.Parse(optStrings[3]);
- string callbackId = optStrings[4];
-
- try
- {
- if (pathToResource.StartsWith("/"))
- {
- pathToResource = pathToResource.Remove(0, 1);
- }
-
- var resource = Application.GetResourceStream(new Uri(pathToResource, UriKind.Relative));
-
- if (resource == null)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
-
- string text;
- StreamReader streamReader = new StreamReader(resource.Stream);
- text = streamReader.ReadToEnd();
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, text), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- public void truncate(string options)
- {
- string[] optStrings = getOptionStrings(options);
-
- string filePath = optStrings[0];
- int size = int.Parse(optStrings[1]);
- string callbackId = optStrings[2];
-
- try
- {
- long streamLength = 0;
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (!isoFile.FileExists(filePath))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
-
- using (FileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.ReadWrite, isoFile))
- {
- if (0 <= size && size <= stream.Length)
- {
- stream.SetLength(size);
- }
- streamLength = stream.Length;
- }
- }
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, streamLength), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- //write:[filePath,data,position,isBinary,callbackId]
- public void write(string options)
- {
- string[] optStrings = getOptionStrings(options);
-
- string filePath = optStrings[0];
- string data = optStrings[1];
- int position = int.Parse(optStrings[2]);
- bool isBinary = bool.Parse(optStrings[3]);
- string callbackId = optStrings[4];
-
- try
- {
- if (string.IsNullOrEmpty(data))
- {
- Debug.WriteLine("Expected some data to be send in the write command to {0}", filePath);
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
- return;
- }
-
- byte[] dataToWrite = isBinary ? JSON.JsonHelper.Deserialize<byte[]>(data) :
- System.Text.Encoding.UTF8.GetBytes(data);
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- // create the file if not exists
- if (!isoFile.FileExists(filePath))
- {
- var file = isoFile.CreateFile(filePath);
- file.Close();
- }
-
- using (FileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.ReadWrite, isoFile))
- {
- if (0 <= position && position <= stream.Length)
- {
- stream.SetLength(position);
- }
- using (BinaryWriter writer = new BinaryWriter(stream))
- {
- writer.Seek(0, SeekOrigin.End);
- writer.Write(dataToWrite);
- }
- }
- }
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, dataToWrite.Length), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- /// <summary>
- /// Look up metadata about this entry.
- /// </summary>
- /// <param name="options">filePath to entry</param>
- public void getMetadata(string options)
- {
- string[] optStings = getOptionStrings(options);
- string filePath = optStings[0];
- string callbackId = optStings[1];
-
- if (filePath != null)
- {
- try
- {
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (isoFile.FileExists(filePath))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK,
- new ModificationMetadata() { modificationTime = isoFile.GetLastWriteTime(filePath).DateTime.ToString() }), callbackId);
- }
- else if (isoFile.DirectoryExists(filePath))
- {
- string modTime = isoFile.GetLastWriteTime(filePath).DateTime.ToString();
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new ModificationMetadata() { modificationTime = modTime }), callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
-
- }
- }
- catch (IsolatedStorageException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
-
- }
-
-
- /// <summary>
- /// Returns a File that represents the current state of the file that this FileEntry represents.
- /// </summary>
- /// <param name="filePath">filePath to entry</param>
- /// <returns></returns>
- public void getFileMetadata(string options)
- {
- string[] optStings = getOptionStrings(options);
- string filePath = optStings[0];
- string callbackId = optStings[1];
-
- if (!string.IsNullOrEmpty(filePath))
- {
- try
- {
- FileMetadata metaData = new FileMetadata(filePath);
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, metaData), callbackId);
- }
- catch (IsolatedStorageException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_READABLE_ERR), callbackId);
- }
- }
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
- }
-
- /// <summary>
- /// Look up the parent DirectoryEntry containing this Entry.
- /// If this Entry is the root of IsolatedStorage, its parent is itself.
- /// </summary>
- /// <param name="options"></param>
- public void getParent(string options)
- {
- string[] optStings = getOptionStrings(options);
- string filePath = optStings[0];
- string callbackId = optStings[1];
-
- if (filePath != null)
- {
- try
- {
- if (string.IsNullOrEmpty(filePath))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
- return;
- }
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- FileEntry entry;
-
- if (isoFile.FileExists(filePath) || isoFile.DirectoryExists(filePath))
- {
-
-
- string path = this.GetParentDirectory(filePath);
- entry = FileEntry.GetEntry(path);
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry),callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
- }
-
- }
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
- }
- }
- }
- }
-
- public void remove(string options)
- {
- string[] args = getOptionStrings(options);
- string filePath = args[0];
- string callbackId = args[1];
-
- if (filePath != null)
- {
- try
- {
- if (filePath == "/" || filePath == "" || filePath == @"\")
- {
- throw new Exception("Cannot delete root file system") ;
- }
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (isoFile.FileExists(filePath))
- {
- isoFile.DeleteFile(filePath);
- }
- else
- {
- if (isoFile.DirectoryExists(filePath))
- {
- isoFile.DeleteDirectory(filePath);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
- return;
- }
- }
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK),callbackId);
- }
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
- }
- }
- }
- }
-
- public void removeRecursively(string options)
- {
- string[] args = getOptionStrings(options);
- string filePath = args[0];
- string callbackId = args[1];
-
- if (filePath != null)
- {
- if (string.IsNullOrEmpty(filePath))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
- }
- else
- {
- if (removeDirRecursively(filePath, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK), callbackId);
- }
- }
- }
- }
-
- public void readEntries(string options)
- {
- string[] args = getOptionStrings(options);
- string filePath = args[0];
- string callbackId = args[1];
-
- if (filePath != null)
- {
- try
- {
- if (string.IsNullOrEmpty(filePath))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION),callbackId);
- return;
- }
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (isoFile.DirectoryExists(filePath))
- {
- string path = File.AddSlashToDirectory(filePath);
- List<FileEntry> entries = new List<FileEntry>();
- string[] files = isoFile.GetFileNames(path + "*");
- string[] dirs = isoFile.GetDirectoryNames(path + "*");
- foreach (string file in files)
- {
- entries.Add(FileEntry.GetEntry(path + file));
- }
- foreach (string dir in dirs)
- {
- entries.Add(FileEntry.GetEntry(path + dir + "/"));
- }
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entries),callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
- }
- }
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
- }
- }
- }
- }
-
- public void requestFileSystem(string options)
- {
- // TODO: try/catch
- string[] optVals = getOptionStrings(options);
- //FileOptions fileOptions = new FileOptions();
- int fileSystemType = int.Parse(optVals[0]);
- double size = double.Parse(optVals[1]);
- string callbackId = optVals[2];
-
-
- IsolatedStorageFile.GetUserStoreForApplication();
-
- if (size > (10 * 1024 * 1024)) // 10 MB, compier will clean this up!
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR), callbackId);
- return;
- }
-
- try
- {
- if (size != 0)
- {
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- long availableSize = isoFile.AvailableFreeSpace;
- if (size > availableSize)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, QUOTA_EXCEEDED_ERR), callbackId);
- return;
- }
- }
- }
-
- if (fileSystemType == PERSISTENT)
- {
- // TODO: this should be in it's own folder to prevent overwriting of the app assets, which are also in ISO
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("persistent", FileEntry.GetEntry("/"))), callbackId);
- }
- else if (fileSystemType == TEMPORARY)
- {
- using (IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (!isoStorage.FileExists(TMP_DIRECTORY_NAME))
- {
- isoStorage.CreateDirectory(TMP_DIRECTORY_NAME);
- }
- }
-
- string tmpFolder = "/" + TMP_DIRECTORY_NAME + "/";
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("temporary", FileEntry.GetEntry(tmpFolder))), callbackId);
- }
- else if (fileSystemType == RESOURCE)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("resource")), callbackId);
- }
- else if (fileSystemType == APPLICATION)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, new FileSystemInfo("application")), callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
- }
-
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
- }
- }
- }
-
- public void resolveLocalFileSystemURI(string options)
- {
-
- string[] optVals = getOptionStrings(options);
- string uri = optVals[0].Split('?')[0];
- string callbackId = optVals[1];
-
- if (uri != null)
- {
- // a single '/' is valid, however, '/someDir' is not, but '/tmp//somedir' and '///someDir' are valid
- if (uri.StartsWith("/") && uri.IndexOf("//") < 0 && uri != "/")
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
- return;
- }
- try
- {
- // fix encoded spaces
- string path = Uri.UnescapeDataString(uri);
-
- FileEntry uriEntry = FileEntry.GetEntry(path);
- if (uriEntry != null)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, uriEntry), callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
- }
- }
- }
- }
-
- public void copyTo(string options)
- {
- TransferTo(options, false);
- }
-
- public void moveTo(string options)
- {
- TransferTo(options, true);
- }
-
- public void getFile(string options)
- {
- GetFileOrDirectory(options, false);
- }
-
- public void getDirectory(string options)
- {
- GetFileOrDirectory(options, true);
- }
-
- #region internal functionality
-
- /// <summary>
- /// Retrieves the parent directory name of the specified path,
- /// </summary>
- /// <param name="path">Path</param>
- /// <returns>Parent directory name</returns>
- private string GetParentDirectory(string path)
- {
- if (String.IsNullOrEmpty(path) || path == "/")
- {
- return "/";
- }
-
- if (path.EndsWith(@"/") || path.EndsWith(@"\"))
- {
- return this.GetParentDirectory(Path.GetDirectoryName(path));
- }
-
- string result = Path.GetDirectoryName(path);
- if (result == null)
- {
- result = "/";
- }
-
- return result;
- }
-
- private bool removeDirRecursively(string fullPath,string callbackId)
- {
- try
- {
- if (fullPath == "/")
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
- return false;
- }
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- if (isoFile.DirectoryExists(fullPath))
- {
- string tempPath = File.AddSlashToDirectory(fullPath);
- string[] files = isoFile.GetFileNames(tempPath + "*");
- if (files.Length > 0)
- {
- foreach (string file in files)
- {
- isoFile.DeleteFile(tempPath + file);
- }
- }
- string[] dirs = isoFile.GetDirectoryNames(tempPath + "*");
- if (dirs.Length > 0)
- {
- foreach (string dir in dirs)
- {
- if (!removeDirRecursively(tempPath + dir, callbackId))
- {
- return false;
- }
- }
- }
- isoFile.DeleteDirectory(fullPath);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR),callbackId);
- }
- }
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR),callbackId);
- return false;
- }
- }
- return true;
- }
-
- private bool CanonicalCompare(string pathA, string pathB)
- {
- string a = pathA.Replace("//", "/");
- string b = pathB.Replace("//", "/");
-
- return a.Equals(b, StringComparison.OrdinalIgnoreCase);
- }
-
- /*
- * copyTo:["fullPath","parent", "newName"],
- * moveTo:["fullPath","parent", "newName"],
- */
- private void TransferTo(string options, bool move)
- {
- // TODO: try/catch
- string[] optStrings = getOptionStrings(options);
- string fullPath = optStrings[0];
- string parent = optStrings[1];
- string newFileName = optStrings[2];
- string callbackId = optStrings[3];
-
- char[] invalids = Path.GetInvalidPathChars();
-
- if (newFileName.IndexOfAny(invalids) > -1 || newFileName.IndexOf(":") > -1 )
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
- return;
- }
-
- try
- {
- if ((parent == null) || (string.IsNullOrEmpty(parent)) || (string.IsNullOrEmpty(fullPath)))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
-
- string parentPath = File.AddSlashToDirectory(parent);
- string currentPath = fullPath;
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- bool isFileExist = isoFile.FileExists(currentPath);
- bool isDirectoryExist = isoFile.DirectoryExists(currentPath);
- bool isParentExist = isoFile.DirectoryExists(parentPath);
-
- if ( ( !isFileExist && !isDirectoryExist ) || !isParentExist )
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
- string newName;
- string newPath;
- if (isFileExist)
- {
- newName = (string.IsNullOrEmpty(newFileName))
- ? Path.GetFileName(currentPath)
- : newFileName;
-
- newPath = Path.Combine(parentPath, newName);
-
- // sanity check ..
- // cannot copy file onto itself
- if (CanonicalCompare(newPath,currentPath)) //(parent + newFileName))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR), callbackId);
- return;
- }
- else if (isoFile.DirectoryExists(newPath))
- {
- // there is already a folder with the same name, operation is not allowed
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR), callbackId);
- return;
- }
- else if (isoFile.FileExists(newPath))
- { // remove destination file if exists, in other case there will be exception
- isoFile.DeleteFile(newPath);
- }
-
- if (move)
- {
- isoFile.MoveFile(currentPath, newPath);
- }
- else
- {
- isoFile.CopyFile(currentPath, newPath, true);
- }
- }
- else
- {
- newName = (string.IsNullOrEmpty(newFileName))
- ? currentPath
- : newFileName;
-
- newPath = Path.Combine(parentPath, newName);
-
- if (move)
- {
- // remove destination directory if exists, in other case there will be exception
- // target directory should be empty
- if (!newPath.Equals(currentPath) && isoFile.DirectoryExists(newPath))
- {
- isoFile.DeleteDirectory(newPath);
- }
-
- isoFile.MoveDirectory(currentPath, newPath);
- }
- else
- {
- CopyDirectory(currentPath, newPath, isoFile);
- }
- }
- FileEntry entry = FileEntry.GetEntry(newPath);
- if (entry != null)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry), callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
- }
-
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex, callbackId))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
- }
- }
- }
-
- private bool HandleException(Exception ex, string cbId="")
- {
- bool handled = false;
- string callbackId = String.IsNullOrEmpty(cbId) ? this.CurrentCommandCallbackId : cbId;
- if (ex is SecurityException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, SECURITY_ERR), callbackId);
- handled = true;
- }
- else if (ex is FileNotFoundException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- handled = true;
- }
- else if (ex is ArgumentException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
- handled = true;
- }
- else if (ex is IsolatedStorageException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_MODIFICATION_ERR), callbackId);
- handled = true;
- }
- else if (ex is DirectoryNotFoundException)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- handled = true;
- }
- return handled;
- }
-
- private void CopyDirectory(string sourceDir, string destDir, IsolatedStorageFile isoFile)
- {
- string path = File.AddSlashToDirectory(sourceDir);
-
- bool bExists = isoFile.DirectoryExists(destDir);
-
- if (!bExists)
- {
- isoFile.CreateDirectory(destDir);
- }
-
- destDir = File.AddSlashToDirectory(destDir);
-
- string[] files = isoFile.GetFileNames(path + "*");
-
- if (files.Length > 0)
- {
- foreach (string file in files)
- {
- isoFile.CopyFile(path + file, destDir + file,true);
- }
- }
- string[] dirs = isoFile.GetDirectoryNames(path + "*");
- if (dirs.Length > 0)
- {
- foreach (string dir in dirs)
- {
- CopyDirectory(path + dir, destDir + dir, isoFile);
- }
- }
- }
-
- private string RemoveExtraSlash(string path) {
- if (path.StartsWith("//")) {
- path = path.Remove(0, 1);
- path = RemoveExtraSlash(path);
- }
- return path;
- }
-
- private string ResolvePath(string parentPath, string path)
- {
- string absolutePath = null;
-
- if (path.Contains(".."))
- {
- if (parentPath.Length > 1 && parentPath.StartsWith("/") && parentPath !="/")
- {
- parentPath = RemoveExtraSlash(parentPath);
- }
-
- string fullPath = Path.GetFullPath(Path.Combine(parentPath, path));
- absolutePath = fullPath.Replace(Path.GetPathRoot(fullPath), @"//");
- }
- else
- {
- absolutePath = Path.Combine(parentPath + "/", path);
- }
- return absolutePath;
- }
-
- private void GetFileOrDirectory(string options, bool getDirectory)
- {
- FileOptions fOptions = new FileOptions();
- string[] args = getOptionStrings(options);
-
- fOptions.FullPath = args[0];
- fOptions.Path = args[1];
-
- string callbackId = args[3];
-
- try
- {
- fOptions.CreatingOpt = JSON.JsonHelper.Deserialize<CreatingOptions>(args[2]);
- }
- catch (Exception)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.JSON_EXCEPTION), callbackId);
- return;
- }
-
- try
- {
- if ((string.IsNullOrEmpty(fOptions.Path)) || (string.IsNullOrEmpty(fOptions.FullPath)))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
-
- string path;
-
- if (fOptions.Path.Split(':').Length > 2)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
- return;
- }
-
- try
- {
- path = ResolvePath(fOptions.FullPath, fOptions.Path);
- }
- catch (Exception)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, ENCODING_ERR), callbackId);
- return;
- }
-
- using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication())
- {
- bool isFile = isoFile.FileExists(path);
- bool isDirectory = isoFile.DirectoryExists(path);
- bool create = (fOptions.CreatingOpt == null) ? false : fOptions.CreatingOpt.Create;
- bool exclusive = (fOptions.CreatingOpt == null) ? false : fOptions.CreatingOpt.Exclusive;
- if (create)
- {
- if (exclusive && (isoFile.FileExists(path) || isoFile.DirectoryExists(path)))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, PATH_EXISTS_ERR), callbackId);
- return;
- }
-
- // need to make sure the parent exists
- // it is an error to create a directory whose immediate parent does not yet exist
- // see issue: https://issues.apache.org/jira/browse/CB-339
- string[] pathParts = path.Split('/');
- string builtPath = pathParts[0];
- for (int n = 1; n < pathParts.Length - 1; n++)
- {
- builtPath += "/" + pathParts[n];
- if (!isoFile.DirectoryExists(builtPath))
- {
- Debug.WriteLine(String.Format("Error :: Parent folder \"{0}\" does not exist, when attempting to create \"{1}\"",builtPath,path));
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- return;
- }
- }
-
- if ((getDirectory) && (!isDirectory))
- {
- isoFile.CreateDirectory(path);
- }
- else
- {
- if ((!getDirectory) && (!isFile))
- {
-
- IsolatedStorageFileStream fileStream = isoFile.CreateFile(path);
- fileStream.Close();
- }
- }
- }
- else // (not create)
- {
- if ((!isFile) && (!isDirectory))
- {
- if (path.IndexOf("//www") == 0)
- {
- Uri fileUri = new Uri(path.Remove(0,2), UriKind.Relative);
- StreamResourceInfo streamInfo = Application.GetResourceStream(fileUri);
- if (streamInfo != null)
- {
- FileEntry _entry = FileEntry.GetEntry(fileUri.OriginalString,true);
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, _entry), callbackId);
-
- //using (BinaryReader br = new BinaryReader(streamInfo.Stream))
- //{
- // byte[] data = br.ReadBytes((int)streamInfo.Stream.Length);
-
- //}
-
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
-
-
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
- return;
- }
- if (((getDirectory) && (!isDirectory)) || ((!getDirectory) && (!isFile)))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, TYPE_MISMATCH_ERR), callbackId);
- return;
- }
- }
- FileEntry entry = FileEntry.GetEntry(path);
- if (entry != null)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, entry), callbackId);
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NOT_FOUND_ERR), callbackId);
- }
- }
- }
- catch (Exception ex)
- {
- if (!this.HandleException(ex))
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, NO_MODIFICATION_ALLOWED_ERR), callbackId);
- }
- }
- }
-
- private static string AddSlashToDirectory(string dirPath)
- {
- if (dirPath.EndsWith("/"))
- {
- return dirPath;
- }
- else
- {
- return dirPath + "/";
- }
- }
-
- /// <summary>
- /// Returns file content in a form of base64 string
- /// </summary>
- /// <param name="stream">File stream</param>
- /// <returns>Base64 representation of the file</returns>
- private string GetFileContent(Stream stream)
- {
- int streamLength = (int)stream.Length;
- byte[] fileData = new byte[streamLength + 1];
- stream.Read(fileData, 0, streamLength);
- stream.Close();
- return Convert.ToBase64String(fileData);
- }
-
- #endregion
-
- }
-}