diff options
Diffstat (limited to 'plugins/org.apache.cordova.file/src')
13 files changed, 0 insertions, 5684 deletions
diff --git a/plugins/org.apache.cordova.file/src/android/DirectoryManager.java b/plugins/org.apache.cordova.file/src/android/DirectoryManager.java deleted file mode 100644 index bcc005b2..00000000 --- a/plugins/org.apache.cordova.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/org.apache.cordova.file/src/android/EncodingException.java b/plugins/org.apache.cordova.file/src/android/EncodingException.java deleted file mode 100644 index e9e1653b..00000000 --- a/plugins/org.apache.cordova.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/org.apache.cordova.file/src/android/FileExistsException.java b/plugins/org.apache.cordova.file/src/android/FileExistsException.java deleted file mode 100644 index 5c4d83dc..00000000 --- a/plugins/org.apache.cordova.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/org.apache.cordova.file/src/android/FileHelper.java b/plugins/org.apache.cordova.file/src/android/FileHelper.java deleted file mode 100644 index 867f128c..00000000 --- a/plugins/org.apache.cordova.file/src/android/FileHelper.java +++ /dev/null @@ -1,158 +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.database.Cursor; -import android.net.Uri; -import android.webkit.MimeTypeMap; - -import org.apache.cordova.CordovaInterface; -import org.apache.cordova.LOG; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Locale; - -public class FileHelper { - private static final String LOG_TAG = "FileUtils"; - private static final String _DATA = "_data"; - - /** - * Returns the real path of the given URI string. - * If the given URI string represents a content:// URI, the real path is retrieved from the media store. - * - * @param uriString the URI string of the audio/image/video - * @param cordova the current application context - * @return the full path to the file - */ - @SuppressWarnings("deprecation") - public static String getRealPath(String uriString, CordovaInterface cordova) { - String realPath = null; - - if (uriString.startsWith("content://")) { - String[] proj = { _DATA }; - Cursor cursor = cordova.getActivity().managedQuery(Uri.parse(uriString), proj, null, null, null); - int column_index = cursor.getColumnIndexOrThrow(_DATA); - cursor.moveToFirst(); - realPath = cursor.getString(column_index); - if (realPath == null) { - LOG.e(LOG_TAG, "Could get real path for URI string %s", uriString); - } - } else if (uriString.startsWith("file://")) { - realPath = uriString.substring(7); - if (realPath.startsWith("/android_asset/")) { - LOG.e(LOG_TAG, "Cannot get real path for URI string %s because it is a file:///android_asset/ URI.", uriString); - realPath = null; - } - } else { - realPath = uriString; - } - - return realPath; - } - - /** - * Returns the real path of the given URI. - * If the given URI is a content:// URI, the real path is retrieved from the media store. - * - * @param uri the URI of the audio/image/video - * @param cordova the current application context - * @return the full path to the file - */ - public static String getRealPath(Uri uri, CordovaInterface cordova) { - return FileHelper.getRealPath(uri.toString(), cordova); - } - - /** - * Returns an input stream based on given URI string. - * - * @param uriString the URI string from which to obtain the input stream - * @param cordova the current application context - * @return an input stream into the data at the given URI or null if given an invalid URI string - * @throws IOException - */ - public static InputStream getInputStreamFromUriString(String uriString, CordovaInterface cordova) throws IOException { - if (uriString.startsWith("content")) { - Uri uri = Uri.parse(uriString); - return cordova.getActivity().getContentResolver().openInputStream(uri); - } else if (uriString.startsWith("file://")) { - int question = uriString.indexOf("?"); - if (question > -1) { - uriString = uriString.substring(0,question); - } - if (uriString.startsWith("file:///android_asset/")) { - Uri uri = Uri.parse(uriString); - String relativePath = uri.getPath().substring(15); - return cordova.getActivity().getAssets().open(relativePath); - } else { - return new FileInputStream(getRealPath(uriString, cordova)); - } - } else { - return new FileInputStream(getRealPath(uriString, cordova)); - } - } - - /** - * Removes the "file://" prefix from the given URI string, if applicable. - * If the given URI string doesn't have a "file://" prefix, it is returned unchanged. - * - * @param uriString the URI string to operate on - * @return a path without the "file://" prefix - */ - public static String stripFileProtocol(String uriString) { - if (uriString.startsWith("file://")) { - uriString = uriString.substring(7); - } - return uriString; - } - - public static String getMimeTypeForExtension(String path) { - String extension = path; - int lastDot = extension.lastIndexOf('.'); - if (lastDot != -1) { - extension = extension.substring(lastDot + 1); - } - // Convert the URI string to lower case to ensure compatibility with MimeTypeMap (see CB-2185). - extension = extension.toLowerCase(Locale.getDefault()); - if (extension.equals("3ga")) { - return "audio/3gpp"; - } - return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - } - - /** - * Returns the mime type of the data specified by the given URI string. - * - * @param uriString the URI string of the data - * @return the mime type of the specified data - */ - public static String getMimeType(String uriString, CordovaInterface cordova) { - String mimeType = null; - - Uri uri = Uri.parse(uriString); - if (uriString.startsWith("content://")) { - mimeType = cordova.getActivity().getContentResolver().getType(uri); - } else { - mimeType = getMimeTypeForExtension(uri.getPath()); - } - - return mimeType; - } -} diff --git a/plugins/org.apache.cordova.file/src/android/FileUtils.java b/plugins/org.apache.cordova.file/src/android/FileUtils.java deleted file mode 100755 index 9a9452fb..00000000 --- a/plugins/org.apache.cordova.file/src/android/FileUtils.java +++ /dev/null @@ -1,1191 +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.database.Cursor; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.util.Base64; -import android.util.Log; - -import org.apache.cordova.CallbackContext; -import org.apache.cordova.CordovaPlugin; -import org.apache.cordova.PluginResult; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -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.RandomAccessFile; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLDecoder; -import java.nio.channels.FileChannel; - -/** - * This class provides SD card file and directory services to JavaScript. - * Only files on the SD card can be accessed. - */ -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 TEMPORARY = 0; - public static int PERSISTENT = 1; - public static int RESOURCE = 2; - public static int APPLICATION = 3; - - private interface FileOp { - void run( ) throws Exception; - } - - /** - * Executes the request and returns whether the action was valid. - * - * @param action The action to execute. - * @param args JSONArray of arguments for the plugin. - * @param callbackContext The callback context used when calling back into JavaScript. - * @return True if the action was valid, false otherwise. - */ - public boolean execute(String action, final JSONArray args, final CallbackContext callbackContext) throws JSONException { - if (action.equals("testSaveLocationExists")) { - threadhelper( new FileOp( ){ - public void run() { - boolean b = DirectoryManager.testSaveLocationExists(); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b)); - } - },callbackContext); - } - else if (action.equals("getFreeDiskSpace")) { - threadhelper( new FileOp( ){ - public void run() { - long l = DirectoryManager.getFreeDiskSpace(false); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, l)); - } - },callbackContext); - } - else if (action.equals("testFileExists")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() { - boolean b = DirectoryManager.testFileExists(fname); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b)); - } - }, callbackContext); - } - else if (action.equals("testDirectoryExists")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() { - boolean b = DirectoryManager.testFileExists(fname); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, b)); - } - }, callbackContext); - } - else if (action.equals("readAsText")) { - final String encoding = args.getString(1); - final int start = args.getInt(2); - final int end = args.getInt(3); - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() { - readFileAs(fname, start, end, callbackContext, encoding, PluginResult.MESSAGE_TYPE_STRING); - } - }, callbackContext); - } - else if (action.equals("readAsDataURL")) { - final int start = args.getInt(1); - final int end = args.getInt(2); - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() { - readFileAs(fname, start, end, callbackContext, null, -1); - } - }, callbackContext); - } - else if (action.equals("readAsArrayBuffer")) { - final int start = args.getInt(1); - final int end = args.getInt(2); - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() { - readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_ARRAYBUFFER); - } - },callbackContext); - } - else if (action.equals("readAsBinaryString")) { - final int start = args.getInt(1); - final int end = args.getInt(2); - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() { - readFileAs(fname, start, end, callbackContext, null, PluginResult.MESSAGE_TYPE_BINARYSTRING); - } - }, callbackContext); - } - else if (action.equals("write")) { - final String fname=args.getString(0); - final String data=args.getString(1); - final int offset=args.getInt(2); - final Boolean isBinary=args.getBoolean(3); - threadhelper( new FileOp( ){ - public void run() throws FileNotFoundException, IOException, NoModificationAllowedException { - long fileSize = write(fname, data, offset, isBinary); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize)); - } - }, callbackContext); - } - else if (action.equals("truncate")) { - final String fname=args.getString(0); - final int offset=args.getInt(1); - threadhelper( new FileOp( ){ - public void run( ) throws FileNotFoundException, IOException, NoModificationAllowedException { - long fileSize = truncateFile(fname, offset); - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, fileSize)); - } - }, callbackContext); - } - else if (action.equals("requestFileSystem")) { - final int fstype=args.getInt(0); - final long size = args.optLong(1); - threadhelper( new FileOp( ){ - public void run() throws IOException, JSONException { - 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); - } - } - }, callbackContext); - } - else if (action.equals("resolveLocalFileSystemURI")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws IOException, JSONException { - JSONObject obj = resolveLocalFileSystemURI(fname); - callbackContext.success(obj); - } - },callbackContext); - } - else if (action.equals("getMetadata")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws FileNotFoundException, JSONException { - callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, getMetadata(fname))); - } - }, callbackContext); - } - else if (action.equals("getFileMetadata")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws FileNotFoundException, JSONException { - JSONObject obj = getFileMetadata(fname); - callbackContext.success(obj); - } - },callbackContext); - } - else if (action.equals("getParent")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws JSONException { - JSONObject obj = getParent(fname); - callbackContext.success(obj); - } - },callbackContext); - } - else if (action.equals("getDirectory")) { - final String dirname=args.getString(0); - final String fname=args.getString(1); - threadhelper( new FileOp( ){ - public void run() throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException { - JSONObject obj = getFile(dirname, fname, args.optJSONObject(2), true); - callbackContext.success(obj); - } - },callbackContext); - } - else if (action.equals("getFile")) { - final String dirname=args.getString(0); - final String fname=args.getString(1); - threadhelper( new FileOp( ){ - public void run() throws FileExistsException, IOException, TypeMismatchException, EncodingException, JSONException { - JSONObject obj = getFile(dirname, fname, args.optJSONObject(2), false); - callbackContext.success(obj); - } - },callbackContext); - } - else if (action.equals("remove")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws NoModificationAllowedException, InvalidModificationException { - boolean success= remove(fname); - if (success) { - notifyDelete(fname); - callbackContext.success(); - } else { - callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR); - } - } - },callbackContext); - } - else if (action.equals("removeRecursively")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws FileExistsException { - boolean success = removeRecursively(fname); - if (success) { - callbackContext.success(); - } else { - callbackContext.error(FileUtils.NO_MODIFICATION_ALLOWED_ERR); - } - } - },callbackContext); - } - else if (action.equals("moveTo")) { - final String fname=args.getString(0); - final String newParent=args.getString(1); - final String newName=args.getString(2); - threadhelper( new FileOp( ){ - public void run() throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException { - JSONObject entry = transferTo(fname, newParent, newName, true); - callbackContext.success(entry); - } - },callbackContext); - } - else if (action.equals("copyTo")) { - final String fname=args.getString(0); - final String newParent=args.getString(1); - final String newName=args.getString(2); - threadhelper( new FileOp( ){ - public void run() throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException { - JSONObject entry = transferTo(fname, newParent, newName, false); - callbackContext.success(entry); - } - },callbackContext); - } - else if (action.equals("readEntries")) { - final String fname=args.getString(0); - threadhelper( new FileOp( ){ - public void run() throws FileNotFoundException, JSONException { - JSONArray entries = readEntries(fname); - callbackContext.success(entries); - } - },callbackContext); - } - else { - return false; - } - return true; - } - - /* helper to execute functions async and handle the result codes - * - */ - private void threadhelper(final FileOp f, final CallbackContext callbackContext){ - cordova.getThreadPool().execute(new Runnable() { - public void run() { - try { - f.run(); - } catch ( Exception e) { - e.printStackTrace(); - 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); - } - } - } - }); - } - - /** - * Need to check to see if we need to clean up the content store - * - * @param filePath the path to check - */ - private void notifyDelete(String filePath) { - String newFilePath = FileHelper.getRealPath(filePath, cordova); - try { - this.cordova.getActivity().getContentResolver().delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - MediaStore.Images.Media.DATA + " = ?", - new String[] { newFilePath }); - } 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. - } - } - - /** - * Allows the user to look up the Entry for a file or directory referred to by a local URI. - * - * @param url 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 - */ - @SuppressWarnings("deprecation") - private JSONObject resolveLocalFileSystemURI(String url) throws IOException, JSONException { - String decoded = URLDecoder.decode(url, "UTF-8"); - - File fp = null; - - // Handle the special case where you get an Android content:// uri. - if (decoded.startsWith("content:")) { - Cursor cursor = this.cordova.getActivity().managedQuery(Uri.parse(decoded), new String[] { MediaStore.Images.Media.DATA }, null, null, null); - // Note: MediaStore.Images/Audio/Video.Media.DATA is always "_data" - int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); - cursor.moveToFirst(); - fp = new File(cursor.getString(column_index)); - } else { - // Test to see if this is a valid URL first - @SuppressWarnings("unused") - URL testUrl = new URL(decoded); - - if (decoded.startsWith("file://")) { - int questionMark = decoded.indexOf("?"); - if (questionMark < 0) { - fp = new File(decoded.substring(7, decoded.length())); - } else { - fp = new File(decoded.substring(7, questionMark)); - } - } else { - fp = new File(decoded); - } - } - - if (!fp.exists()) { - throw new FileNotFoundException(); - } - if (!fp.canRead()) { - throw new IOException(); - } - return getEntry(fp); - } - - /** - * Read the list of files from this directory. - * - * @param fileName the directory to read from - * @return a JSONArray containing JSONObjects that represent Entry objects. - * @throws FileNotFoundException if the directory is not found. - * @throws JSONException - */ - private JSONArray readEntries(String fileName) throws FileNotFoundException, JSONException { - File fp = createFileObject(fileName); - - if (!fp.exists()) { - // The directory we are listing doesn't exist so we should fail. - throw new FileNotFoundException(); - } - - JSONArray entries = new JSONArray(); - - if (fp.isDirectory()) { - File[] files = fp.listFiles(); - for (int i = 0; i < files.length; i++) { - if (files[i].canRead()) { - entries.put(getEntry(files[i])); - } - } - } - - return entries; - } - - /** - * A setup method that handles the move/copy of files/directories - * - * @param fileName to be copied/moved - * @param newParent is the location where the file will be copied/moved to - * @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 fileName, String newParent, String newName, boolean move) throws JSONException, NoModificationAllowedException, IOException, InvalidModificationException, EncodingException, FileExistsException { - String newFileName = FileHelper.getRealPath(fileName, cordova); - newParent = FileHelper.getRealPath(newParent, cordova); - - // Check for invalid file name - if (newName != null && newName.contains(":")) { - throw new EncodingException("Bad file name"); - } - - File source = new File(newFileName); - - if (!source.exists()) { - // The file/directory we are copying doesn't exist so we should fail. - throw new FileNotFoundException("The source does not exist"); - } - - 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 - File destination = createDestination(newName, source, destinationDir); - - //Log.d(LOG_TAG, "Source: " + source.getAbsolutePath()); - //Log.d(LOG_TAG, "Destin: " + destination.getAbsolutePath()); - - // Check to see if source and destination are the same file - if (source.getAbsolutePath().equals(destination.getAbsolutePath())) { - throw new InvalidModificationException("Can't copy a file onto itself"); - } - - if (source.isDirectory()) { - if (move) { - return moveDirectory(source, destination); - } else { - return copyDirectory(source, destination); - } - } else { - if (move) { - JSONObject newFileEntry = moveFile(source, destination); - - // If we've moved a file given its content URI, we need to clean up. - if (fileName.startsWith("content://")) { - notifyDelete(fileName); - } - - return newFileEntry; - } else { - return copyFile(source, destination); - } - } - } - - /** - * Creates the destination File object based on name passed in - * - * @param newName for the file directory to be called, if null use existing file name - * @param fp represents the source file - * @param destination represents the destination file - * @return a File object that represents the destination - */ - private File createDestination(String newName, File fp, File destination) { - File destFile = null; - - // I know this looks weird but it is to work around a JSON bug. - if ("null".equals(newName) || "".equals(newName)) { - newName = null; - } - - if (newName != null) { - destFile = new File(destination.getAbsolutePath() + File.separator + newName); - } else { - destFile = new File(destination.getAbsolutePath() + File.separator + fp.getName()); - } - return destFile; - } - - /** - * Copy a file - * - * @param srcFile file to be copied - * @param destFile destination to be copied to - * @return a FileEntry object - * @throws IOException - * @throws InvalidModificationException - * @throws JSONException - */ - private JSONObject copyFile(File srcFile, File destFile) throws IOException, InvalidModificationException, JSONException { - // Renaming a file to an existing directory should fail - if (destFile.exists() && destFile.isDirectory()) { - throw new InvalidModificationException("Can't rename a file to a directory"); - } - - copyAction(srcFile, destFile); - - return getEntry(destFile); - } - - /** - * Moved this code into it's own method so moveTo could use it when the move is across file systems - */ - private void copyAction(File srcFile, File destFile) - throws FileNotFoundException, IOException { - FileInputStream istream = new FileInputStream(srcFile); - FileOutputStream ostream = new FileOutputStream(destFile); - FileChannel input = istream.getChannel(); - FileChannel output = ostream.getChannel(); - - try { - input.transferTo(0, input.size(), output); - } finally { - istream.close(); - ostream.close(); - input.close(); - output.close(); - } - } - - /** - * Copy a directory - * - * @param srcDir directory to be copied - * @param destinationDir destination to be copied to - * @return a DirectoryEntry object - * @throws JSONException - * @throws IOException - * @throws NoModificationAllowedException - * @throws InvalidModificationException - */ - private JSONObject copyDirectory(File srcDir, File destinationDir) throws JSONException, IOException, NoModificationAllowedException, InvalidModificationException { - // Renaming a file to an existing directory should fail - if (destinationDir.exists() && destinationDir.isFile()) { - throw new InvalidModificationException("Can't rename a file to a directory"); - } - - // Check to make sure we are not copying the directory into itself - if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) { - throw new InvalidModificationException("Can't copy itself into itself"); - } - - // See if the destination directory exists. If not create it. - if (!destinationDir.exists()) { - if (!destinationDir.mkdir()) { - // If we can't create the directory then fail - throw new NoModificationAllowedException("Couldn't create the destination directory"); - } - } - - - for (File file : srcDir.listFiles()) { - File destination = new File(destinationDir.getAbsoluteFile() + File.separator + file.getName()); - if (file.isDirectory()) { - copyDirectory(file, destination); - } else { - copyFile(file, destination); - } - } - - return getEntry(destinationDir); - } - - /** - * 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. - * - * @param srcDir - * @param destinationDir - * @return - */ - private boolean isCopyOnItself(String src, String dest) { - - // This weird test is to determine if we are copying or moving a directory into itself. - // Copy /sdcard/myDir to /sdcard/myDir-backup is okay but - // Copy /sdcard/myDir to /sdcard/myDir/backup should throw an INVALID_MODIFICATION_ERR - if (dest.startsWith(src) && dest.indexOf(File.separator, src.length() - 1) != -1) { - return true; - } - - return false; - } - - /** - * Move a file - * - * @param srcFile file to be copied - * @param destFile destination to be copied to - * @return a FileEntry object - * @throws IOException - * @throws InvalidModificationException - * @throws JSONException - */ - private JSONObject moveFile(File srcFile, File destFile) throws IOException, JSONException, InvalidModificationException { - // Renaming a file to an existing directory should fail - if (destFile.exists() && destFile.isDirectory()) { - throw new InvalidModificationException("Can't rename a file to a directory"); - } - - // Try to rename the file - if (!srcFile.renameTo(destFile)) { - // Trying to rename the file failed. Possibly because we moved across file system on the device. - // Now we have to do things the hard way - // 1) Copy all the old file - // 2) delete the src file - copyAction(srcFile, destFile); - if (destFile.exists()) { - srcFile.delete(); - } else { - throw new IOException("moved failed"); - } - } - - return getEntry(destFile); - } - - /** - * Move a directory - * - * @param srcDir directory to be copied - * @param destinationDir destination to be copied to - * @return a DirectoryEntry object - * @throws JSONException - * @throws IOException - * @throws InvalidModificationException - * @throws NoModificationAllowedException - * @throws FileExistsException - */ - private JSONObject moveDirectory(File srcDir, File destinationDir) throws IOException, JSONException, InvalidModificationException, NoModificationAllowedException, FileExistsException { - // Renaming a file to an existing directory should fail - if (destinationDir.exists() && destinationDir.isFile()) { - throw new InvalidModificationException("Can't rename a file to a directory"); - } - - // Check to make sure we are not copying the directory into itself - if (isCopyOnItself(srcDir.getAbsolutePath(), destinationDir.getAbsolutePath())) { - throw new InvalidModificationException("Can't move itself into itself"); - } - - // If the destination directory already exists and is empty then delete it. This is according to spec. - if (destinationDir.exists()) { - if (destinationDir.list().length > 0) { - throw new InvalidModificationException("directory is not empty"); - } - } - - // Try to rename the directory - if (!srcDir.renameTo(destinationDir)) { - // Trying to rename the directory failed. Possibly because we moved across file system on the device. - // Now we have to do things the hard way - // 1) Copy all the old files - // 2) delete the src directory - copyDirectory(srcDir, destinationDir); - if (destinationDir.exists()) { - removeDirRecursively(srcDir); - } else { - throw new IOException("moved failed"); - } - } - - return getEntry(destinationDir); - } - - /** - * 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. - * - * @param filePath the directory to be removed - * @return a boolean representing success of failure - * @throws FileExistsException - */ - private boolean removeRecursively(String filePath) throws FileExistsException { - File fp = createFileObject(filePath); - - // You can't delete the root directory. - if (atRootDirectory(filePath)) { - return false; - } - - return removeDirRecursively(fp); - } - - /** - * Loops through a directory deleting all the files. - * - * @param directory to be removed - * @return a boolean representing success of failure - * @throws FileExistsException - */ - private 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; - } - } - - /** - * 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. - * - * @param filePath file or directory to be removed - * @return a boolean representing success of failure - * @throws NoModificationAllowedException - * @throws InvalidModificationException - */ - private boolean remove(String filePath) throws NoModificationAllowedException, InvalidModificationException { - File fp = createFileObject(filePath); - - // You can't delete the root directory. - if (atRootDirectory(filePath)) { - throw new NoModificationAllowedException("You can't delete the root directory"); - } - - // 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(); - } - - /** - * Creates or looks up a file. - * - * @param dirPath base directory - * @param fileName 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 dirPath, String fileName, 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 (fileName.contains(":")) { - throw new EncodingException("This file has a : in it's name"); - } - - File fp = createFileObject(dirPath, fileName); - - 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 getEntry(fp); - } - - /** - * If the path starts with a '/' just return that file object. If not construct the file - * object from the path passed in and the file name. - * - * @param dirPath root directory - * @param fileName new file name - * @return - */ - private File createFileObject(String dirPath, String fileName) { - File fp = null; - if (fileName.startsWith("/")) { - fp = new File(fileName); - } else { - dirPath = FileHelper.getRealPath(dirPath, cordova); - fp = new File(dirPath + File.separator + fileName); - } - return fp; - } - - /** - * Look up the parent DirectoryEntry containing this Entry. - * If this Entry is the root of its filesystem, its parent is itself. - * - * @param filePath - * @return - * @throws JSONException - */ - private JSONObject getParent(String filePath) throws JSONException { - filePath = FileHelper.getRealPath(filePath, cordova); - - if (atRootDirectory(filePath)) { - return getEntry(filePath); - } - return getEntry(new File(filePath).getParent()); - } - - /** - * Checks to see if we are at the root directory. Useful since we are - * not allow to delete this directory. - * - * @param filePath to directory - * @return true if we are at the root, false otherwise. - */ - private boolean atRootDirectory(String filePath) { - filePath = FileHelper.getRealPath(filePath, cordova); - - if (filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + cordova.getActivity().getPackageName() + "/cache") || - filePath.equals(Environment.getExternalStorageDirectory().getAbsolutePath()) || - filePath.equals("/data/data/" + cordova.getActivity().getPackageName())) { - return true; - } - return false; - } - - /** - * Create a File object from the passed in path - * - * @param filePath - * @return - */ - private File createFileObject(String filePath) { - filePath = FileHelper.getRealPath(filePath, cordova); - - File file = new File(filePath); - return file; - } - - /** - * Look up metadata about this entry. - * - * @param filePath to entry - * @return a long - * @throws FileNotFoundException - */ - private long getMetadata(String filePath) throws FileNotFoundException { - File file = createFileObject(filePath); - - if (!file.exists()) { - throw new FileNotFoundException("Failed to find file in getMetadata"); - } - - return file.lastModified(); - } - - /** - * Returns a File that represents the current state of the file that this FileEntry represents. - * - * @param filePath to entry - * @return returns a JSONObject represent a W3C File object - * @throws FileNotFoundException - * @throws JSONException - */ - private JSONObject getFileMetadata(String filePath) throws FileNotFoundException, JSONException { - File file = createFileObject(filePath); - - if (!file.exists()) { - throw new FileNotFoundException("File: " + filePath + " does not exist."); - } - - JSONObject metadata = new JSONObject(); - metadata.put("size", file.length()); - metadata.put("type", FileHelper.getMimeType(filePath, cordova)); - metadata.put("name", file.getName()); - metadata.put("fullPath", filePath); - metadata.put("lastModifiedDate", file.lastModified()); - - return metadata; - } - - /** - * 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(); - if (type == TEMPORARY) { - File fp; - fs.put("name", "temporary"); - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - fp = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + - "/Android/data/" + cordova.getActivity().getPackageName() + "/cache/"); - // Create the cache dir if it doesn't exist. - fp.mkdirs(); - fs.put("root", getEntry(Environment.getExternalStorageDirectory().getAbsolutePath() + - "/Android/data/" + cordova.getActivity().getPackageName() + "/cache/")); - } else { - fp = new File("/data/data/" + cordova.getActivity().getPackageName() + "/cache/"); - // Create the cache dir if it doesn't exist. - fp.mkdirs(); - fs.put("root", getEntry("/data/data/" + cordova.getActivity().getPackageName() + "/cache/")); - } - } - else if (type == PERSISTENT) { - fs.put("name", "persistent"); - if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { - fs.put("root", getEntry(Environment.getExternalStorageDirectory())); - } else { - fs.put("root", getEntry("/data/data/" + cordova.getActivity().getPackageName())); - } - } - else { - throw new IOException("No filesystem of type requested"); - } - - return fs; - } - - /** - * Returns a JSON object representing the given File. - * - * @param file the File to convert - * @return a JSON representation of the given File - * @throws JSONException - */ - public static JSONObject getEntry(File file) throws JSONException { - JSONObject entry = new JSONObject(); - - entry.put("isFile", file.isFile()); - entry.put("isDirectory", file.isDirectory()); - entry.put("name", file.getName()); - entry.put("fullPath", "file://" + file.getAbsolutePath()); - // The file system can't be specified, as it would lead to an infinite loop. - // entry.put("filesystem", null); - - return entry; - } - - /** - * Returns a JSON Object representing a directory on the device's file system - * - * @param path to the directory - * @return - * @throws JSONException - */ - private JSONObject getEntry(String path) throws JSONException { - return getEntry(new File(path)); - } - - /** - * Read the contents of a file. - * This is done in a background thread; the result is sent to the callback. - * - * @param filename The name of the file. - * @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 filename, final int start, final int end, final CallbackContext callbackContext, final String encoding, final int resultType) { - this.cordova.getThreadPool().execute(new Runnable() { - public void run() { - try { - byte[] bytes = readAsBinaryHelper(filename, start, end); - - PluginResult result; - switch (resultType) { - case PluginResult.MESSAGE_TYPE_STRING: - result = new PluginResult(PluginResult.Status.OK, new String(bytes, encoding)); - break; - case PluginResult.MESSAGE_TYPE_ARRAYBUFFER: - result = new PluginResult(PluginResult.Status.OK, bytes); - break; - case PluginResult.MESSAGE_TYPE_BINARYSTRING: - result = new PluginResult(PluginResult.Status.OK, bytes, true); - break; - default: // Base64. - String contentType = FileHelper.getMimeType(filename, cordova); - byte[] base64 = Base64.encode(bytes, Base64.NO_WRAP); - String s = "data:" + contentType + ";base64," + new String(base64, "US-ASCII"); - result = new PluginResult(PluginResult.Status.OK, s); - } - - callbackContext.sendPluginResult(result); - } 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)); - } - } - }); - } - - /** - * Read the contents of a file as binary. - * This is done synchronously; the result is returned. - * - * @param filename The name of the file. - * @param start Start position in the file. - * @param end End position to stop at (exclusive). - * @return Contents of the file as a byte[]. - * @throws IOException - */ - private byte[] readAsBinaryHelper(String filename, int start, int end) throws IOException { - int numBytesToRead = end - start; - byte[] bytes = new byte[numBytesToRead]; - InputStream inputStream = FileHelper.getInputStreamFromUriString(filename, cordova); - int numBytesRead = 0; - - if (start > 0) { - inputStream.skip(start); - } - - while (numBytesToRead > 0 && (numBytesRead = inputStream.read(bytes, numBytesRead, numBytesToRead)) >= 0) { - numBytesToRead -= numBytesRead; - } - - return bytes; - } - - /** - * Write contents of file. - * - * @param filename The name of the 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 - * @throws FileNotFoundException, IOException - * @throws NoModificationAllowedException - */ - /**/ - public long write(String filename, String data, int offset, boolean isBinary) throws FileNotFoundException, IOException, NoModificationAllowedException { - if (filename.startsWith("content://")) { - throw new NoModificationAllowedException("Couldn't write to file given its content URI"); - } - - filename = FileHelper.getRealPath(filename, cordova); - - boolean append = false; - if (offset > 0) { - this.truncateFile(filename, offset); - append = true; - } - - byte[] rawData; - if (isBinary) { - rawData = Base64.decode(data, Base64.DEFAULT); - } else { - rawData = data.getBytes(); - } - ByteArrayInputStream in = new ByteArrayInputStream(rawData); - try - { - FileOutputStream out = new FileOutputStream(filename, append); - byte buff[] = new byte[rawData.length]; - in.read(buff, 0, buff.length); - out.write(buff, 0, rawData.length); - out.flush(); - out.close(); - } - catch (NullPointerException e) - { - // This is a bug in the Android implementation of the Java Stack - NoModificationAllowedException realException = new NoModificationAllowedException(filename); - throw realException; - } - - return rawData.length; - } - - /** - * Truncate the file to size - * - * @param filename - * @param size - * @throws FileNotFoundException, IOException - * @throws NoModificationAllowedException - */ - private long truncateFile(String filename, long size) throws FileNotFoundException, IOException, NoModificationAllowedException { - if (filename.startsWith("content://")) { - throw new NoModificationAllowedException("Couldn't truncate file given its content URI"); - } - - filename = FileHelper.getRealPath(filename, cordova); - - RandomAccessFile raf = new RandomAccessFile(filename, "rw"); - try { - if (raf.length() >= size) { - FileChannel channel = raf.getChannel(); - channel.truncate(size); - return size; - } - - return raf.length(); - } finally { - raf.close(); - } - } -} diff --git a/plugins/org.apache.cordova.file/src/android/InvalidModificationException.java b/plugins/org.apache.cordova.file/src/android/InvalidModificationException.java deleted file mode 100644 index 8f6bec59..00000000 --- a/plugins/org.apache.cordova.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/org.apache.cordova.file/src/android/NoModificationAllowedException.java b/plugins/org.apache.cordova.file/src/android/NoModificationAllowedException.java deleted file mode 100644 index 627eafb5..00000000 --- a/plugins/org.apache.cordova.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/org.apache.cordova.file/src/android/TypeMismatchException.java b/plugins/org.apache.cordova.file/src/android/TypeMismatchException.java deleted file mode 100644 index 1315f9a9..00000000 --- a/plugins/org.apache.cordova.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/org.apache.cordova.file/src/blackberry10/index.js b/plugins/org.apache.cordova.file/src/blackberry10/index.js deleted file mode 100644 index 914d9663..00000000 --- a/plugins/org.apache.cordova.file/src/blackberry10/index.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - setSandbox : function (success, fail, args, env) { - require("lib/webview").setSandbox(JSON.parse(decodeURIComponent(args[0]))); - new PluginResult(args, env).noResult(false); - }, - - isSandboxed : function (success, fail, args, env) { - new PluginResult(args, env).ok(require("lib/webview").getSandbox() === "1"); - } -}; diff --git a/plugins/org.apache.cordova.file/src/ios/CDVFile.h b/plugins/org.apache.cordova.file/src/ios/CDVFile.h deleted file mode 100644 index 54d25f08..00000000 --- a/plugins/org.apache.cordova.file/src/ios/CDVFile.h +++ /dev/null @@ -1,107 +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> - -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; - -enum CDVFileSystemType { - TEMPORARY = 0, - PERSISTENT = 1 -}; -typedef int CDVFileSystemType; - -extern NSString* const kCDVAssetsLibraryPrefix; - -@interface CDVFile : CDVPlugin { - NSString* appDocsPath; - NSString* appLibraryPath; - NSString* appTempPath; - NSString* persistentPath; - NSString* temporaryPath; - - BOOL userHasAllowed; -} -- (NSNumber*)checkFreeDiskSpace:(NSString*)appPath; -- (NSString*)getAppPath:(NSString*)pathFragment; -// -(NSString*) getFullPath: (NSString*)pathFragment; -- (void)requestFileSystem:(CDVInvokedUrlCommand*)command; -- (NSDictionary*)getDirectoryEntry:(NSString*)fullPath isDirectory:(BOOL)isDir; -- (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command; -- (void)getDirectory:(CDVInvokedUrlCommand*)command; -- (void)getFile:(CDVInvokedUrlCommand*)command; -- (void)getParent:(CDVInvokedUrlCommand*)command; -- (void)getMetadata:(CDVInvokedUrlCommand*)command; -- (void)removeRecursively:(CDVInvokedUrlCommand*)command; -- (void)remove:(CDVInvokedUrlCommand*)command; -- (CDVPluginResult*)doRemove:(NSString*)fullPath; -- (void)copyTo:(CDVInvokedUrlCommand*)command; -- (void)moveTo:(CDVInvokedUrlCommand*)command; -- (BOOL)canCopyMoveSrc:(NSString*)src ToDestination:(NSString*)dest; -- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy; -// - (void) toURI:(CDVInvokedUrlCommand*)command; -- (void)getFileMetadata:(CDVInvokedUrlCommand*)command; -- (void)readEntries:(CDVInvokedUrlCommand*)command; - -- (void)readAsText:(CDVInvokedUrlCommand*)command; -- (void)readAsDataURL:(CDVInvokedUrlCommand*)command; -- (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command; -- (NSString*)getMimeTypeFromPath:(NSString*)fullPath; -- (void)write:(CDVInvokedUrlCommand*)command; -- (void)testFileExists:(CDVInvokedUrlCommand*)command; -- (void)testDirectoryExists:(CDVInvokedUrlCommand*)command; -// - (void) createDirectory:(CDVInvokedUrlCommand*)command; -// - (void) deleteDirectory:(CDVInvokedUrlCommand*)command; -// - (void) deleteFile:(CDVInvokedUrlCommand*)command; -- (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command; -- (void)truncate:(CDVInvokedUrlCommand*)command; - -// - (BOOL) fileExists:(NSString*)fileName; -// - (BOOL) directoryExists:(NSString*)dirName; -- (void)writeToFile:(NSString*)fileName withData:(NSData*)data append:(BOOL)shouldAppend callback:(NSString*)callbackId; -- (void)writeToFile:(NSString*)fileName withString:(NSString*)data encoding:(NSStringEncoding)encoding append:(BOOL)shouldAppend callback:(NSString*)callbackId; -- (unsigned long long)truncateFile:(NSString*)filePath atPosition:(unsigned long long)pos; - -@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 BOOL userHasAllowed; - -@end - -#define kW3FileTemporary @"temporary" -#define kW3FilePersistent @"persistent" diff --git a/plugins/org.apache.cordova.file/src/ios/CDVFile.m b/plugins/org.apache.cordova.file/src/ios/CDVFile.m deleted file mode 100644 index 6b2602d3..00000000 --- a/plugins/org.apache.cordova.file/src/ios/CDVFile.m +++ /dev/null @@ -1,1417 +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 <Cordova/CDV.h> -#import <AssetsLibrary/ALAsset.h> -#import <AssetsLibrary/ALAssetRepresentation.h> -#import <AssetsLibrary/ALAssetsLibrary.h> -#import <MobileCoreServices/MobileCoreServices.h> -#import <sys/xattr.h> - -extern NSString * const NSURLIsExcludedFromBackupKey __attribute__((weak_import)); - -#ifndef __IPHONE_5_1 - NSString* const NSURLIsExcludedFromBackupKey = @"NSURLIsExcludedFromBackupKey"; -#endif - -NSString* const kCDVAssetsLibraryPrefix = @"assets-library://"; - -@implementation CDVFile - -@synthesize appDocsPath, appLibraryPath, appTempPath, persistentPath, temporaryPath, userHasAllowed; - -- (id)initWithWebView:(UIWebView*)theWebView -{ - self = (CDVFile*)[super initWithWebView:theWebView]; - if (self) { - // get the documents directory path - NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - self.appDocsPath = [paths objectAtIndex:0]; - - paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); - self.appLibraryPath = [paths objectAtIndex:0]; - - self.appTempPath = [NSTemporaryDirectory()stringByStandardizingPath]; // remove trailing slash from NSTemporaryDirectory() - - self.persistentPath = [NSString stringWithFormat:@"/%@", [self.appDocsPath lastPathComponent]]; - self.temporaryPath = [NSString stringWithFormat:@"/%@", [self.appTempPath lastPathComponent]]; - // NSLog(@"docs: %@ - temp: %@", self.appDocsPath, self.appTempPath); - } - - return self; -} - -- (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; -} - -// figure out if the pathFragment represents a persistent of temporary directory and return the full application path. -// returns nil if path is not persistent or temporary -- (NSString*)getAppPath:(NSString*)pathFragment -{ - NSString* appPath = nil; - NSRange rangeP = [pathFragment rangeOfString:self.persistentPath]; - NSRange rangeT = [pathFragment rangeOfString:self.temporaryPath]; - - if ((rangeP.location != NSNotFound) && (rangeT.location != NSNotFound)) { - // we found both in the path, return whichever one is first - if (rangeP.length < rangeT.length) { - appPath = self.appDocsPath; - } else { - appPath = self.appTempPath; - } - } else if (rangeP.location != NSNotFound) { - appPath = self.appDocsPath; - } else if (rangeT.location != NSNotFound) { - appPath = self.appTempPath; - } - return appPath; -} - -/* get the full path to this resource - * IN - * NSString* pathFragment - full Path from File or Entry object (includes system path info) - * OUT - * NSString* fullPath - full iOS path to this resource, nil if not found - */ - -/* Was here in order to NOT have to return full path, but W3C synchronous DirectoryEntry.toURI() killed that idea since I can't call into iOS to - * resolve full URI. Leaving this code here in case W3C spec changes. --(NSString*) getFullPath: (NSString*)pathFragment -{ - return pathFragment; - NSString* fullPath = nil; - NSString *appPath = [ self getAppPath: pathFragment]; - if (appPath){ - - // remove last component from appPath - NSRange range = [appPath rangeOfString:@"/" options: NSBackwardsSearch]; - NSString* newPath = [appPath substringToIndex:range.location]; - // add pathFragment to get test Path - fullPath = [newPath stringByAppendingPathComponent:pathFragment]; - } - return fullPath; -} */ - -/* 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 -{ - NSArray* arguments = command.arguments; - - // arguments - NSString* strType = [arguments objectAtIndex:0]; - unsigned long long size = [[arguments objectAtIndex:1] longLongValue]; - - int type = [strType intValue]; - CDVPluginResult* result = nil; - - if (type > 1) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR]; - NSLog(@"iOS only supports TEMPORARY and PERSISTENT file systems"); - } else { - // NSString* fullPath = [NSString stringWithFormat:@"/%@", (type == 0 ? [self.appTempPath lastPathComponent] : [self.appDocsPath lastPathComponent])]; - NSString* fullPath = (type == 0 ? self.appTempPath : self.appDocsPath); - // check for avail space for size request - NSNumber* pNumAvail = [self checkFreeDiskSpace:fullPath]; - // NSLog(@"Free space: %@", [NSString stringWithFormat:@"%qu", [ pNumAvail unsignedLongLongValue ]]); - if (pNumAvail && ([pNumAvail unsignedLongLongValue] < size)) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:QUOTA_EXCEEDED_ERR]; - } else { - NSMutableDictionary* fileSystem = [NSMutableDictionary dictionaryWithCapacity:2]; - [fileSystem setObject:(type == TEMPORARY ? kW3FileTemporary : kW3FilePersistent) forKey:@"name"]; - NSDictionary* dirEntry = [self getDirectoryEntry:fullPath isDirectory:YES]; - [fileSystem setObject:dirEntry forKey:@"root"]; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileSystem]; - } - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* Creates a dictionary representing an Entry Object - * - * IN: - * NSString* fullPath of the entry - * 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 - * fileSystem = FileSystem object - !! ignored because creates circular reference FileSystem contains DirectoryEntry which contains FileSystem.....!! - */ -- (NSDictionary*)getDirectoryEntry:(NSString*)fullPath isDirectory:(BOOL)isDir -{ - NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:4]; - NSString* lastPart = [fullPath lastPathComponent]; - - [dirEntry setObject:[NSNumber numberWithBool:!isDir] forKey:@"isFile"]; - [dirEntry setObject:[NSNumber numberWithBool:isDir] forKey:@"isDirectory"]; - // NSURL* fileUrl = [NSURL fileURLWithPath:fullPath]; - // [dirEntry setObject: [fileUrl absoluteString] forKey: @"fullPath"]; - [dirEntry setObject:fullPath forKey:@"fullPath"]; - [dirEntry setObject:lastPart forKey:@"name"]; - - return dirEntry; -} - -/* - * Given a URI determine the File System information associated with it and return an appropriate W3C entry object - * IN - * NSString* fileURI - currently requires full file 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* inputUri = [command.arguments objectAtIndex:0]; - - // don't know if string is encoded or not so unescape - NSString* cleanUri = [inputUri stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - // now escape in order to create URL - NSString* strUri = [cleanUri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSURL* testUri = [NSURL URLWithString:strUri]; - CDVPluginResult* result = nil; - - if (!testUri) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR]; - } else if ([testUri isFileURL]) { - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - NSString* path = [testUri path]; - // NSLog(@"url path: %@", path); - BOOL isDir = NO; - // see if exists and is file or dir - BOOL bExists = [fileMgr fileExistsAtPath:path isDirectory:&isDir]; - if (bExists) { - // see if it contains docs path or temp path - NSString* foundFullPath = nil; - if ([path hasPrefix:self.appDocsPath]) { - foundFullPath = self.appDocsPath; - } else if ([path hasPrefix:self.appTempPath]) { - foundFullPath = self.appTempPath; - } - - if (foundFullPath == nil) { - // error SECURITY_ERR - not one of the two paths types supported - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:SECURITY_ERR]; - } else { - NSDictionary* fileSystem = [self getDirectoryEntry:path isDirectory:isDir]; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileSystem]; - } - } else { - // return NOT_FOUND_ERR - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - } - } else if ([strUri hasPrefix:@"assets-library://"]) { - NSDictionary* fileSystem = [self getDirectoryEntry:strUri isDirectory:NO]; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileSystem]; - } else { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR]; - } - - if (result != nil) { - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } -} - -/* Part of DirectoryEntry interface, creates or returns the specified directory - * IN: - * NSString* fullPath - full path 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 = [arguments objectAtIndex: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* fullPath - full path for this file - * NSString* path - file to be created/returned; may be full path or relative path - * NSDictionary* - 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 -{ - // arguments are URL encoded - NSString* fullPath = [command.arguments objectAtIndex:0]; - NSString* requestedPath = [command.arguments objectAtIndex:1]; - NSDictionary* options = [command.arguments objectAtIndex:2 withDefault:nil]; - - // return unsupported result for assets-library URLs - if ([fullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"getFile not supported for assets-library URLs."]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - CDVPluginResult* result = nil; - BOOL bDirRequest = NO; - BOOL create = NO; - BOOL exclusive = NO; - int errorCode = 0; // !!! risky - no error code currently defined for 0 - - if ([options valueForKeyIsNumber:@"create"]) { - create = [(NSNumber*)[options valueForKey:@"create"] boolValue]; - } - if ([options valueForKeyIsNumber:@"exclusive"]) { - exclusive = [(NSNumber*)[options valueForKey:@"exclusive"] boolValue]; - } - - if ([options valueForKeyIsNumber:@"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 { - // was full or relative path provided? - NSRange range = [requestedPath rangeOfString:fullPath]; - BOOL bIsFullPath = range.location != NSNotFound; - - NSString* reqFullPath = nil; - - if (!bIsFullPath) { - reqFullPath = [fullPath stringByAppendingPathComponent:requestedPath]; - } else { - reqFullPath = requestedPath; - } - - // NSLog(@"reqFullPath = %@", reqFullPath); - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - BOOL bIsDir; - BOOL bExists = [fileMgr fileExistsAtPath:reqFullPath isDirectory:&bIsDir]; - if (bExists && (create == NO) && (bIsDir == !bDirRequest)) { - // path exists and is 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:reqFullPath withIntermediateDirectories:NO attributes:nil error:&pError]; - } else { - // create the empty file - bSuccess = [fileMgr createFileAtPath:reqFullPath 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 getDirectoryEntry:reqFullPath isDirectory:bDirRequest]]; - } - } // are all possible conditions met? - } - - if (errorCode > 0) { - // create error callback - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode]; - } - - [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* fullPath - * NSMutableDictionary* options - * empty - */ -- (void)getParent:(CDVInvokedUrlCommand*)command -{ - // arguments are URL encoded - NSString* fullPath = [command.arguments objectAtIndex:0]; - - // we don't (yet?) support getting the parent of an asset - if ([fullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - CDVPluginResult* result = nil; - NSString* newPath = nil; - - if ([fullPath isEqualToString:self.appDocsPath] || [fullPath isEqualToString:self.appTempPath]) { - // return self - newPath = fullPath; - } else { - // since this call is made from an existing Entry object - the parent should already exist so no additional error checking - // remove last component and return Entry - NSRange range = [fullPath rangeOfString:@"/" options:NSBackwardsSearch]; - newPath = [fullPath substringToIndex:range.location]; - } - - if (newPath) { - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - BOOL bIsDir; - BOOL bExists = [fileMgr fileExistsAtPath:newPath isDirectory:&bIsDir]; - if (bExists) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getDirectoryEntry:newPath isDirectory:bIsDir]]; - } - } - if (!result) { - // invalid path or file does not exist - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* - * get MetaData of entry - * Currently MetaData only includes modificationTime. - */ -- (void)getMetadata:(CDVInvokedUrlCommand*)command -{ - // arguments - NSString* argPath = [command.arguments objectAtIndex:0]; - __block CDVPluginResult* result = nil; - - if ([argPath hasPrefix:kCDVAssetsLibraryPrefix]) { - // 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! Retrieve the metadata and send it off. - NSDate* date = [asset valueForProperty:ALAssetPropertyDate]; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:[date timeIntervalSince1970] * 1000]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } else { - // We couldn't find the asset. Send the appropriate error. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } - }; - // TODO(maxw): Consider making this a class variable since it's the same every time. - ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { - // Retrieving the asset failed for some reason. Send the appropriate error. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - }; - - ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; - [assetsLibrary assetForURL:[NSURL URLWithString:argPath] resultBlock:resultBlock failureBlock:failureBlock]; - return; - } - - NSString* testPath = argPath; // [self getFullPath: argPath]; - - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - NSError* __autoreleasing error = nil; - - NSDictionary* fileAttribs = [fileMgr attributesOfItemAtPath:testPath error:&error]; - - if (fileAttribs) { - NSDate* modDate = [fileAttribs fileModificationDate]; - if (modDate) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:[modDate timeIntervalSince1970] * 1000]; - } - } else { - // didn't get fileAttribs - CDVFileError errorCode = ABORT_ERR; - NSLog(@"error getting metadata: %@", [error localizedDescription]); - if ([error code] == NSFileNoSuchFileError) { - errorCode = NOT_FOUND_ERR; - } - // log [NSNumber numberWithDouble: theMessage] objCtype to see what it returns - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode]; - } - if (!result) { - // invalid path or file does not exist - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* - * set MetaData of entry - * Currently we only support "com.apple.MobileBackup" (boolean) - */ -- (void)setMetadata:(CDVInvokedUrlCommand*)command -{ - // arguments - NSString* filePath = [command.arguments objectAtIndex:0]; - NSDictionary* options = [command.arguments objectAtIndex:1 withDefault:nil]; - CDVPluginResult* result = nil; - BOOL ok = NO; - - // setMetadata doesn't make sense for asset library files - if (![filePath hasPrefix:kCDVAssetsLibraryPrefix]) { - // 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) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; - } else { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* removes the directory or file entry - * IN: - * NSArray* arguments - * 0 - NSString* fullPath - * - * 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 - NSString* fullPath = [command.arguments objectAtIndex:0]; - CDVPluginResult* result = nil; - CDVFileError errorCode = 0; // !! 0 not currently defined - - // return error for assets-library URLs - if ([fullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - errorCode = INVALID_MODIFICATION_ERR; - } else if ([fullPath isEqualToString:self.appDocsPath] || [fullPath isEqualToString:self.appTempPath]) { - // error if try to remove top level (documents or tmp) dir - errorCode = NO_MODIFICATION_ALLOWED_ERR; - } else { - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - BOOL bIsDir = NO; - BOOL bExists = [fileMgr fileExistsAtPath:fullPath isDirectory:&bIsDir]; - if (!bExists) { - errorCode = NOT_FOUND_ERR; - } - if (bIsDir && ([[fileMgr contentsOfDirectoryAtPath:fullPath error:nil] count] != 0)) { - // dir is not empty - errorCode = INVALID_MODIFICATION_ERR; - } - } - if (errorCode > 0) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode]; - } else { - // perform actual remove - result = [self doRemove:fullPath]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* recursively removes the directory - * IN: - * NSArray* arguments - * 0 - NSString* fullPath - * - * 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 - NSString* fullPath = [command.arguments objectAtIndex:0]; - - // return unsupported result for assets-library URLs - if ([fullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"removeRecursively not supported for assets-library URLs."]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - CDVPluginResult* result = nil; - - // error if try to remove top level (documents or tmp) dir - if ([fullPath isEqualToString:self.appDocsPath] || [fullPath isEqualToString:self.appTempPath]) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR]; - } else { - result = [self doRemove:fullPath]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* 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 getting metadata: %@", [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; -} - -- (void)copyTo:(CDVInvokedUrlCommand*)command -{ - [self doCopyMove:command isCopy:YES]; -} - -- (void)moveTo:(CDVInvokedUrlCommand*)command -{ - [self doCopyMove:command isCopy:NO]; -} - -/** - * 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; -} - -/* Copy/move a file or directory to a new location - * IN: - * NSArray* arguments - * 0 - NSString* fullPath of entry - * 1 - NSString* newName the new name of the entry, defaults to the current name - * NSMutableDictionary* options - DirectoryEntry to which to copy the entry - * BOOL - bCopy YES if copy, NO if move - * - */ -- (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy -{ - NSArray* arguments = command.arguments; - - // arguments - NSString* srcFullPath = [arguments objectAtIndex:0]; - NSString* destRootPath = [arguments objectAtIndex:1]; - // optional argument - NSString* newName = ([arguments count] > 2) ? [arguments objectAtIndex:2] : [srcFullPath lastPathComponent]; // use last component from appPath if new name not provided - - __block CDVPluginResult* result = nil; - CDVFileError errCode = 0; // !! Currently 0 is not defined, use this to signal error !! - - /*NSString* destRootPath = nil; - NSString* key = @"fullPath"; - if([options valueForKeyIsString:key]){ - destRootPath = [options objectForKey:@"fullPath"]; - }*/ - - if (!destRootPath) { - // no destination provided - errCode = NOT_FOUND_ERR; - } else if ([newName rangeOfString:@":"].location != NSNotFound) { - // invalid chars in new name - errCode = ENCODING_ERR; - } else { - NSString* newFullPath = [destRootPath stringByAppendingPathComponent:newName]; - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - if ([newFullPath isEqualToString:srcFullPath]) { - // source and destination can not be the same - errCode = INVALID_MODIFICATION_ERR; - } else if ([srcFullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - if (bCopy) { - // Copying (as opposed to moving) an assets library file is okay. - // 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! Get the data and try to copy it over. - if (![fileMgr fileExistsAtPath:destRootPath]) { - // The destination directory doesn't exist. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } else if ([fileMgr fileExistsAtPath:newFullPath]) { - // A file already exists at the destination path. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:PATH_EXISTS_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - // We're good to go! Write the file to the new destination. - ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation]; - Byte* buffer = (Byte*)malloc([assetRepresentation size]); - NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation size] error:nil]; - NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES]; - [data writeToFile:newFullPath atomically:YES]; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self getDirectoryEntry:newFullPath isDirectory:NO]]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } else { - // We couldn't find the asset. Send the appropriate error. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } - }; - ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { - // Retrieving the asset failed for some reason. Send the appropriate error. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - }; - - ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; - [assetsLibrary assetForURL:[NSURL URLWithString:srcFullPath] resultBlock:resultBlock failureBlock:failureBlock]; - return; - } else { - // Moving an assets library file is not doable, since we can't remove it. - errCode = INVALID_MODIFICATION_ERR; - } - } else { - BOOL bSrcIsDir = NO; - BOOL bDestIsDir = NO; - BOOL bNewIsDir = NO; - BOOL bSrcExists = [fileMgr fileExistsAtPath:srcFullPath isDirectory:&bSrcIsDir]; - BOOL bDestExists = [fileMgr fileExistsAtPath:destRootPath isDirectory:&bDestIsDir]; - BOOL bNewExists = [fileMgr fileExistsAtPath:newFullPath isDirectory:&bNewIsDir]; - if (!bSrcExists || !bDestExists) { - // the source or the destination root does not exist - errCode = NOT_FOUND_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:newFullPath] /*[newFullPath hasPrefix:srcFullPath]*/) { - // 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:newFullPath 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:newFullPath]) { // [newFullPath hasPrefix:srcFullPath]){ - // can't move a dir into itself - errCode = INVALID_MODIFICATION_ERR; - } else if (bNewExists) { - if (bNewIsDir && ([[fileMgr contentsOfDirectoryAtPath:newFullPath error:NULL] count] != 0)) { - // can't move dir to a dir that is not empty - errCode = INVALID_MODIFICATION_ERR; - newFullPath = nil; // so we won't try to move - } else { - // remove destination so can perform the moveItemAtPath - bSuccess = [fileMgr removeItemAtPath:newFullPath error:NULL]; - if (!bSuccess) { - errCode = INVALID_MODIFICATION_ERR; // is this the correct error? - newFullPath = nil; - } - } - } else if (bNewIsDir && [newFullPath hasPrefix:srcFullPath]) { - // can't move a directory inside itself or to any child at any depth; - errCode = INVALID_MODIFICATION_ERR; - newFullPath = nil; - } - - if (newFullPath != nil) { - bSuccess = [fileMgr moveItemAtPath:srcFullPath toPath:newFullPath error:&error]; - } - } - if (bSuccess) { - // should verify it is there and of the correct type??? - NSDictionary* newEntry = [self getDirectoryEntry:newFullPath isDirectory:bSrcIsDir]; // should be the same type as source - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newEntry]; - } else { - errCode = INVALID_MODIFICATION_ERR; // catch all - 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; - } - } - } - } - } - } - if (errCode > 0) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errCode]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -/* return the URI to the entry - * IN: - * NSArray* arguments - * 0 - NSString* fullPath of entry - * 1 - desired mime type of entry - ignored - always returns file:// - */ - -/* Not needed since W3C toURI is synchronous. Leaving code here for now in case W3C spec changes..... -- (void) toURI:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSString* argPath = [command.arguments objectAtIndex:0]; - PluginResult* result = nil; - NSString* jsString = nil; - - NSString* fullPath = [self getFullPath: argPath]; - if (fullPath) { - // do we need to make sure the file actually exists? - // create file uri - NSString* strUri = [fullPath stringByReplacingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; - NSURL* fileUrl = [NSURL fileURLWithPath:strUri]; - if (fileUrl) { - result = [PluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: [fileUrl absoluteString]]; - jsString = [result toSuccessCallbackString:callbackId]; - } // else NOT_FOUND_ERR - } - if(!jsString) { - // was error - result = [PluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt: NOT_FOUND_ERR cast: @"window.localFileSystem._castError"]; - jsString = [result toErrorCallbackString:callbackId]; - } - - [self writeJavascript:jsString]; -}*/ -- (void)getFileMetadata:(CDVInvokedUrlCommand*)command -{ - // arguments - NSString* argPath = [command.arguments objectAtIndex:0]; - - __block CDVPluginResult* result = nil; - - NSString* fullPath = argPath; // [self getFullPath: argPath]; - - if (fullPath) { - if ([fullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - // 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:argPath forKey:@"fullPath"]; - NSString* filename = [assetRepresentation filename]; - [fileInfo setObject:filename forKey:@"name"]; - [fileInfo setObject:[self getMimeTypeFromPath:filename] forKey:@"type"]; - NSDate* creationDate = [asset valueForProperty:ALAssetPropertyDate]; - NSNumber* msDate = [NSNumber numberWithDouble:[creationDate timeIntervalSince1970] * 1000]; - [fileInfo setObject:msDate forKey:@"lastModifiedDate"]; - - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } else { - // We couldn't find the asset. Send the appropriate error. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - } - }; - ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) { - // Retrieving the asset failed for some reason. Send the appropriate error. - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - }; - - ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init]; - [assetsLibrary assetForURL:[NSURL URLWithString:argPath] resultBlock:resultBlock failureBlock:failureBlock]; - return; - } else { - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - BOOL bIsDir = NO; - // make sure it exists and is not a directory - BOOL bExists = [fileMgr fileExistsAtPath:fullPath isDirectory:&bIsDir]; - if (!bExists || bIsDir) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - } else { - // create dictionary of file info - NSError* __autoreleasing error = nil; - NSDictionary* fileAttrs = [fileMgr attributesOfItemAtPath:fullPath error:&error]; - NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5]; - [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:[fileAttrs fileSize]] forKey:@"size"]; - [fileInfo setObject:argPath forKey:@"fullPath"]; - [fileInfo setObject:@"" forKey:@"type"]; // can't easily get the mimetype unless create URL, send request and read response so skipping - [fileInfo setObject:[argPath lastPathComponent] forKey:@"name"]; - NSDate* modDate = [fileAttrs fileModificationDate]; - NSNumber* msDate = [NSNumber numberWithDouble:[modDate timeIntervalSince1970] * 1000]; - [fileInfo setObject:msDate forKey:@"lastModifiedDate"]; - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]; - } - } - } - if (!result) { - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_INSTANTIATION_EXCEPTION]; - } - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -- (void)readEntries:(CDVInvokedUrlCommand*)command -{ - // arguments - NSString* fullPath = [command.arguments objectAtIndex:0]; - - // return unsupported result for assets-library URLs - if ([fullPath hasPrefix:kCDVAssetsLibraryPrefix]) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"readEntries not supported for assets-library URLs."]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - CDVPluginResult* result = nil; - - NSFileManager* fileMgr = [[NSFileManager alloc] init]; - NSError* __autoreleasing error = nil; - NSArray* contents = [fileMgr contentsOfDirectoryAtPath:fullPath 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 = [fullPath stringByAppendingPathComponent:name]; - BOOL bIsDir = NO; - [fileMgr fileExistsAtPath:entryPath isDirectory:&bIsDir]; - NSDictionary* entryDict = [self getDirectoryEntry:entryPath isDirectory:bIsDir]; - [entries addObject:entryDict]; - } - } - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:entries]; - } else { - // assume not found but could check error for more specific error conditions - result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]; - } - - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -- (void)readFileWithPath:(NSString*)path start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback -{ - if (path == nil) { - callback(nil, nil, SYNTAX_ERR); - } else { - [self.commandDelegate runInBackground:^ { - if ([path hasPrefix:kCDVAssetsLibraryPrefix]) { - // 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! Get the data and send it off. - ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation]; - Byte* buffer = (Byte*)malloc([assetRepresentation size]); - NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:0.0 length:[assetRepresentation 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:[NSURL URLWithString:path] resultBlock:resultBlock failureBlock:failureBlock]; - } else { - NSString* mimeType = [self 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); - } - }]; - } -} - -/* 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 - NSString* path = [command argumentAtIndex:0]; - NSString* encoding = [command argumentAtIndex:1]; - NSInteger start = [[command argumentAtIndex:2] integerValue]; - NSInteger end = [[command argumentAtIndex:3] integerValue]; - - // 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 readFileWithPath:path 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 -{ - NSString* path = [command argumentAtIndex:0]; - NSInteger start = [[command argumentAtIndex:1] integerValue]; - NSInteger end = [[command argumentAtIndex:2] integerValue]; - - [self readFileWithPath:path start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) { - CDVPluginResult* result = nil; - if (data != nil) { - // TODO: Would be faster to base64 encode directly to the final string. - NSString* output = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, [data base64EncodedString]]; - 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 -{ - NSString* path = [command argumentAtIndex:0]; - NSInteger start = [[command argumentAtIndex:1] integerValue]; - NSInteger end = [[command argumentAtIndex:2] integerValue]; - - [self readFileWithPath:path 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 -{ - NSString* path = [command argumentAtIndex:0]; - NSInteger start = [[command argumentAtIndex:1] integerValue]; - NSInteger end = [[command argumentAtIndex:2] integerValue]; - - [self readFileWithPath:path 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]; - }]; -} - -/* 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"; - } - } - CFRelease(typeId); - } - } - return mimeType; -} - -- (void)truncate:(CDVInvokedUrlCommand*)command -{ - // arguments - NSString* argPath = [command.arguments objectAtIndex:0]; - unsigned long long pos = (unsigned long long)[[command.arguments objectAtIndex:1] longLongValue]; - - // assets-library files can't be truncated - if ([argPath hasPrefix:kCDVAssetsLibraryPrefix]) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - NSString* appFile = argPath; // [self getFullPath:argPath]; - - unsigned long long newPos = [self truncateFile:appFile atPosition:pos]; - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:newPos]; - - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; -} - -- (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; -} - -/* write - * IN: - * NSArray* arguments - * 0 - NSString* file path to write to - * 1 - NSString* or NSData* data to write - * 2 - NSNumber* position to begin writing - */ -- (void)write:(CDVInvokedUrlCommand*)command -{ - NSString* callbackId = command.callbackId; - NSArray* arguments = command.arguments; - - // arguments - NSString* argPath = [arguments objectAtIndex:0]; - id argData = [arguments objectAtIndex:1]; - unsigned long long pos = (unsigned long long)[[arguments objectAtIndex:2] longLongValue]; - - // text can't be written into assets-library files - if ([argPath hasPrefix:kCDVAssetsLibraryPrefix]) { - CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR]; - [self.commandDelegate sendPluginResult:result callbackId:command.callbackId]; - return; - } - - NSString* fullPath = argPath; // [self getFullPath:argPath]; - - [self truncateFile:fullPath atPosition:pos]; - - if ([argData isKindOfClass:[NSString class]]) { - [self writeToFile:fullPath withString:argData encoding:NSUTF8StringEncoding append:YES callback:callbackId]; - } else if ([argData isKindOfClass:[NSData class]]) { - [self writeToFile:fullPath withData:argData append:YES callback:callbackId]; - } else { - CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid parameter type"]; - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; - } - -} - -- (void)writeToFile:(NSString*)filePath withData:(NSData*)encData append:(BOOL)shouldAppend callback:(NSString*)callbackId -{ - 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]; - [fileStream open]; - - bytesWritten = [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]; - } - [self.commandDelegate sendPluginResult:result callbackId:callbackId]; -} - -- (void)writeToFile:(NSString*)filePath withString:(NSString*)stringData encoding:(NSStringEncoding)encoding append:(BOOL)shouldAppend callback:(NSString*)callbackId -{ - [self writeToFile:filePath withData:[stringData dataUsingEncoding:encoding allowLossyConversion:YES] append:shouldAppend callback:callbackId]; -} - -- (void)testFileExists:(CDVInvokedUrlCommand*)command -{ - // arguments - NSString* argPath = [command.arguments objectAtIndex: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.arguments objectAtIndex: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]; -} - -@end diff --git a/plugins/org.apache.cordova.file/src/windows8/FileProxy.js b/plugins/org.apache.cordova.file/src/windows8/FileProxy.js deleted file mode 100644 index 1445ae70..00000000 --- a/plugins/org.apache.cordova.file/src/windows8/FileProxy.js +++ /dev/null @@ -1,845 +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 Entry = require('./Entry'), - File = require('./File'), - FileEntry = require('./FileEntry'), - FileError = require('./FileError'), - DirectoryEntry = require('./DirectoryEntry'), - Flags = require('./Flags'), - FileSystem = require('./FileSystem'), - LocalFileSystem = require('./LocalFileSystem'); - -module.exports = { - - getFileMetadata:function(win,fail,args) { - var fullPath = args[0]; - - Windows.Storage.StorageFile.getFileFromPathAsync(fullPath).done( - function (storageFile) { - storageFile.getBasicPropertiesAsync().then( - function (basicProperties) { - win(new File(storageFile.name, storageFile.path, storageFile.fileType, basicProperties.dateModified, basicProperties.size)); - }, function () { - fail && fail(FileError.NOT_READABLE_ERR); - } - ); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - }, - - getMetadata:function(success,fail,args) { - var fullPath = args[0]; - - var dealFile = function (sFile) { - Windows.Storage.StorageFile.getFileFromPathAsync(fullPath).then( - function (storageFile) { - return storageFile.getBasicPropertiesAsync(); - }, - function () { - fail && fail(FileError.NOT_READABLE_ERR); - } - // get the basic properties of the file. - ).then( - function (basicProperties) { - success(basicProperties.dateModified); - }, - function () { - fail && fail(FileError.NOT_READABLE_ERR); - } - ); - }; - - var dealFolder = function (sFolder) { - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).then( - function (storageFolder) { - return storageFolder.getBasicPropertiesAsync(); - }, - function () { - fail && fail(FileError.NOT_READABLE_ERR); - } - // get the basic properties of the folder. - ).then( - function (basicProperties) { - success(basicProperties.dateModified); - }, - function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - }; - - Windows.Storage.StorageFile.getFileFromPathAsync(fullPath).then( - // the path is file. - function (sFile) { - dealFile(sFile); - }, - // the path is folder - function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).then( - function (sFolder) { - dealFolder(sFolder); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - ); - }, - - getParent:function(win,fail,args) { // ["fullPath"] - var fullPath = args[0]; - - var storageFolderPer = Windows.Storage.ApplicationData.current.localFolder; - var storageFolderTem = Windows.Storage.ApplicationData.current.temporaryFolder; - - if (fullPath == storageFolderPer.path) { - win(new DirectoryEntry(storageFolderPer.name, storageFolderPer.path)); - return; - } else if (fullPath == storageFolderTem.path) { - win(new DirectoryEntry(storageFolderTem.name, storageFolderTem.path)); - return; - } - var splitArr = fullPath.split(new RegExp(/\/|\\/g)); - - var popItem = splitArr.pop(); - - var result = new DirectoryEntry(popItem, fullPath.substr(0, fullPath.length - popItem.length - 1)); - Windows.Storage.StorageFolder.getFolderFromPathAsync(result.fullPath).done( - function () { win(result); }, - function () { fail && fail(FileError.INVALID_STATE_ERR); } - ); - }, - - readAsText:function(win,fail,args) { - var fileName = args[0]; - var enc = args[1]; - - Windows.Storage.StorageFile.getFileFromPathAsync(fileName).done( - function (storageFile) { - var value = Windows.Storage.Streams.UnicodeEncoding.utf8; - if (enc == 'Utf16LE' || enc == 'utf16LE') { - value = Windows.Storage.Streams.UnicodeEncoding.utf16LE; - }else if (enc == 'Utf16BE' || enc == 'utf16BE') { - value = Windows.Storage.Streams.UnicodeEncoding.utf16BE; - } - Windows.Storage.FileIO.readTextAsync(storageFile, value).done( - function (fileContent) { - win(fileContent); - }, - function () { - fail && fail(FileError.ENCODING_ERR); - } - ); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - }, - - readAsDataURL:function(win,fail,args) { - var fileName = args[0]; - - - Windows.Storage.StorageFile.getFileFromPathAsync(fileName).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 && fail(FileError.NOT_FOUND_ERR); - } - ); - }, - - getDirectory:function(win,fail,args) { - var fullPath = args[0]; - var path = args[1]; - var options = args[2]; - - var flag = ""; - if (options !== null) { - flag = new Flags(options.create, options.exclusive); - } else { - flag = new Flags(false, false); - } - - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).then( - function (storageFolder) { - if (flag.create === true && flag.exclusive === true) { - storageFolder.createFolderAsync(path, Windows.Storage.CreationCollisionOption.failIfExists).done( - function (storageFolder) { - win(new DirectoryEntry(storageFolder.name, storageFolder.path)); - }, function () { - fail && fail(FileError.PATH_EXISTS_ERR); - } - ); - } else if (flag.create === true && flag.exclusive === false) { - storageFolder.createFolderAsync(path, Windows.Storage.CreationCollisionOption.openIfExists).done( - function (storageFolder) { - win(new DirectoryEntry(storageFolder.name, storageFolder.path)); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - } - ); - } else if (flag.create === false) { - if (/\?|\\|\*|\||\"|<|>|\:|\//g.test(path)) { - fail && fail(FileError.ENCODING_ERR); - return; - } - - storageFolder.getFolderAsync(path).done( - function (storageFolder) { - win(new DirectoryEntry(storageFolder.name, storageFolder.path)); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - }, - - remove:function(win,fail,args) { - var fullPath = args[0]; - - Windows.Storage.StorageFile.getFileFromPathAsync(fullPath).then( - function (sFile) { - Windows.Storage.StorageFile.getFileFromPathAsync(fullPath).done(function (storageFile) { - storageFile.deleteAsync().done(win, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - - }); - }); - }, - function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).then( - function (sFolder) { - var removeEntry = function () { - var storageFolderTop = null; - - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).then( - function (storageFolder) { - // FileSystem root can't be removed! - var storageFolderPer = Windows.Storage.ApplicationData.current.localFolder; - var storageFolderTem = Windows.Storage.ApplicationData.current.temporaryFolder; - if (fullPath == storageFolderPer.path || fullPath == storageFolderTem.path) { - fail && fail(FileError.NO_MODIFICATION_ALLOWED_ERR); - return; - } - storageFolderTop = storageFolder; - return storageFolder.createFileQuery().getFilesAsync(); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - - } - // check sub-files. - ).then(function (fileList) { - if (fileList) { - if (fileList.length === 0) { - return storageFolderTop.createFolderQuery().getFoldersAsync(); - } else { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - } - } - // check sub-folders. - }).then(function (folderList) { - if (folderList) { - if (folderList.length === 0) { - storageFolderTop.deleteAsync().done(win, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - - }); - } else { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - } - } - - }); - }; - removeEntry(); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - ); - }, - - removeRecursively:function(successCallback,fail,args) { - var fullPath = args[0]; - - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).done(function (storageFolder) { - var storageFolderPer = Windows.Storage.ApplicationData.current.localFolder; - var storageFolderTem = Windows.Storage.ApplicationData.current.temporaryFolder; - - if (storageFolder.path == storageFolderPer.path || storageFolder.path == storageFolderTem.path) { - fail && fail(FileError.NO_MODIFICATION_ALLOWED_ERR); - return; - } - - var removeFolders = function (path) { - return new WinJS.Promise(function (complete) { - var filePromiseArr = []; - var storageFolderTop = null; - Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then( - function (storageFolder) { - var fileListPromise = storageFolder.createFileQuery().getFilesAsync(); - - storageFolderTop = storageFolder; - return fileListPromise; - } - // remove all the files directly under the folder. - ).then(function (fileList) { - if (fileList !== null) { - for (var i = 0; i < fileList.length; i++) { - var filePromise = fileList[i].deleteAsync(); - filePromiseArr.push(filePromise); - } - } - WinJS.Promise.join(filePromiseArr).then(function () { - var folderListPromise = storageFolderTop.createFolderQuery().getFoldersAsync(); - return folderListPromise; - // remove empty folders. - }).then(function (folderList) { - var folderPromiseArr = []; - if (folderList.length !== 0) { - for (var j = 0; j < folderList.length; j++) { - - folderPromiseArr.push(removeFolders(folderList[j].path)); - } - WinJS.Promise.join(folderPromiseArr).then(function () { - storageFolderTop.deleteAsync().then(complete); - }); - } else { - storageFolderTop.deleteAsync().then(complete); - } - }, function () { }); - }, function () { }); - }); - }; - removeFolders(storageFolder.path).then(function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(storageFolder.path).then( - function () {}, - function () { - if (typeof successCallback !== 'undefined' && successCallback !== null) { successCallback(); } - }); - }); - }); - }, - - getFile:function(win,fail,args) { - var fullPath = args[0]; - var path = args[1]; - var options = args[2]; - - var flag = ""; - if (options !== null) { - flag = new Flags(options.create, options.exclusive); - } else { - flag = new Flags(false, false); - } - - Windows.Storage.StorageFolder.getFolderFromPathAsync(fullPath).then( - function (storageFolder) { - if (flag.create === true && flag.exclusive === true) { - storageFolder.createFileAsync(path, Windows.Storage.CreationCollisionOption.failIfExists).done( - function (storageFile) { - win(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - fail && fail(FileError.PATH_EXISTS_ERR); - } - ); - } else if (flag.create === true && flag.exclusive === false) { - storageFolder.createFileAsync(path, Windows.Storage.CreationCollisionOption.openIfExists).done( - function (storageFile) { - win(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - } - ); - } else if (flag.create === false) { - if (/\?|\\|\*|\||\"|<|>|\:|\//g.test(path)) { - fail && fail(FileError.ENCODING_ERR); - return; - } - storageFolder.getFileAsync(path).done( - function (storageFile) { - win(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - }, - - readEntries:function(win,fail,args) { // ["fullPath"] - var path = args[0]; - - var result = []; - - Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then(function (storageFolder) { - var promiseArr = []; - var index = 0; - promiseArr[index++] = storageFolder.createFileQuery().getFilesAsync().then(function (fileList) { - if (fileList !== null) { - for (var i = 0; i < fileList.length; i++) { - result.push(new FileEntry(fileList[i].name, fileList[i].path)); - } - } - }); - promiseArr[index++] = storageFolder.createFolderQuery().getFoldersAsync().then(function (folderList) { - if (folderList !== null) { - for (var j = 0; j < folderList.length; j++) { - result.push(new FileEntry(folderList[j].name, folderList[j].path)); - } - } - }); - WinJS.Promise.join(promiseArr).then(function () { - win(result); - }); - - }, function () { fail && fail(FileError.NOT_FOUND_ERR); }); - }, - - write:function(win,fail,args) { - var fileName = args[0]; - var text = args[1]; - var position = args[2]; - - Windows.Storage.StorageFile.getFileFromPathAsync(fileName).done( - function (storageFile) { - Windows.Storage.FileIO.writeTextAsync(storageFile,text,Windows.Storage.Streams.UnicodeEncoding.utf8).done( - function() { - win(String(text).length); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - } - ); - }, function() { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - }, - - truncate:function(win,fail,args) { // ["fileName","size"] - var fileName = args[0]; - var size = args[1]; - - Windows.Storage.StorageFile.getFileFromPathAsync(fileName).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; - var entry = new Entry(true, false, name, fullPath); - var parentPath = ""; - var successCallBack = function (entry) { - parentPath = entry.fullPath; - storageFile.deleteAsync().then(function () { - return Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath); - }).then(function (storageFolder) { - storageFolder.createFileAsync(name).then(function (newStorageFile) { - Windows.Storage.FileIO.writeTextAsync(newStorageFile, fileContent).done(function () { - win(String(fileContent).length); - }, function () { - fail && fail(FileError.NO_MODIFICATION_ALLOWED_ERR); - }); - }); - }); - }; - entry.getParent(successCallBack, null); - }, function () { fail && fail(FileError.NOT_FOUND_ERR); }); - } - }); - }, function () { fail && fail(FileError.NOT_FOUND_ERR); }); - }, - - copyTo:function(success,fail,args) { // ["fullPath","parent", "newName"] - var srcPath = args[0]; - var parentFullPath = args[1]; - var name = args[2]; - - //name can't be invalid - if (/\?|\\|\*|\||\"|<|>|\:|\//g.test(name)) { - fail && fail(FileError.ENCODING_ERR); - return; - } - // copy - var copyFiles = ""; - Windows.Storage.StorageFile.getFileFromPathAsync(srcPath).then( - function (sFile) { - copyFiles = function (srcPath, parentPath) { - var storageFileTop = null; - Windows.Storage.StorageFile.getFileFromPathAsync(srcPath).then(function (storageFile) { - storageFileTop = storageFile; - return Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath); - }, function () { - - fail && fail(FileError.NOT_FOUND_ERR); - }).then(function (storageFolder) { - storageFileTop.copyAsync(storageFolder, name, Windows.Storage.NameCollisionOption.failIfExists).then(function (storageFile) { - - success(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - - fail && fail(FileError.INVALID_MODIFICATION_ERR); - }); - }, function () { - - fail && fail(FileError.NOT_FOUND_ERR); - }); - }; - var copyFinish = function (srcPath, parentPath) { - copyFiles(srcPath, parentPath); - }; - copyFinish(srcPath, parentFullPath); - }, - function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(srcPath).then( - function (sFolder) { - copyFiles = function (srcPath, parentPath) { - var coreCopy = function (storageFolderTop, complete) { - storageFolderTop.createFolderQuery().getFoldersAsync().then(function (folderList) { - var folderPromiseArr = []; - if (folderList.length === 0) { complete(); } - else { - Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath).then(function (storageFolderTarget) { - var tempPromiseArr = []; - var index = 0; - for (var j = 0; j < folderList.length; j++) { - tempPromiseArr[index++] = storageFolderTarget.createFolderAsync(folderList[j].name).then(function (targetFolder) { - folderPromiseArr.push(copyFiles(folderList[j].path, targetFolder.path)); - }); - } - WinJS.Promise.join(tempPromiseArr).then(function () { - WinJS.Promise.join(folderPromiseArr).then(complete); - }); - }); - } - }); - }; - - return new WinJS.Promise(function (complete) { - var storageFolderTop = null; - var filePromiseArr = []; - var fileListTop = null; - Windows.Storage.StorageFolder.getFolderFromPathAsync(srcPath).then(function (storageFolder) { - storageFolderTop = storageFolder; - return storageFolder.createFileQuery().getFilesAsync(); - }).then(function (fileList) { - fileListTop = fileList; - if (fileList) { - return Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath); - } - }).then(function (targetStorageFolder) { - for (var i = 0; i < fileListTop.length; i++) { - filePromiseArr.push(fileListTop[i].copyAsync(targetStorageFolder)); - } - WinJS.Promise.join(filePromiseArr).then(function () { - coreCopy(storageFolderTop, complete); - }); - }); - }); - }; - var copyFinish = function (srcPath, parentPath) { - Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath).then(function (storageFolder) { - storageFolder.createFolderAsync(name, Windows.Storage.CreationCollisionOption.openIfExists).then(function (newStorageFolder) { - //can't copy onto itself - if (srcPath == newStorageFolder.path) { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - return; - } - //can't copy into itself - if (srcPath == parentPath) { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - return; - } - copyFiles(srcPath, newStorageFolder.path).then(function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(newStorageFolder.path).done( - function (storageFolder) { - success(new DirectoryEntry(storageFolder.name, storageFolder.path)); - }, - function () { fail && fail(FileError.NOT_FOUND_ERR); } - ); - }); - }, function () { fail && fail(FileError.INVALID_MODIFICATION_ERR); }); - }, function () { fail && fail(FileError.INVALID_MODIFICATION_ERR); }); - }; - copyFinish(srcPath, parentFullPath); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - ); - }, - - moveTo:function(success,fail,args) { - var srcPath = args[0]; - var parentFullPath = args[1]; - var name = args[2]; - - - //name can't be invalid - if (/\?|\\|\*|\||\"|<|>|\:|\//g.test(name)) { - fail && fail(FileError.ENCODING_ERR); - return; - } - - var moveFiles = ""; - Windows.Storage.StorageFile.getFileFromPathAsync(srcPath).then( - function (sFile) { - moveFiles = function (srcPath, parentPath) { - var storageFileTop = null; - Windows.Storage.StorageFile.getFileFromPathAsync(srcPath).then(function (storageFile) { - storageFileTop = storageFile; - return Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - }).then(function (storageFolder) { - storageFileTop.moveAsync(storageFolder, name, Windows.Storage.NameCollisionOption.replaceExisting).then(function () { - success(new FileEntry(name, storageFileTop.path)); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - }); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - }); - }; - var moveFinish = function (srcPath, parentPath) { - //can't copy onto itself - if (srcPath == parentPath + "\\" + name) { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - return; - } - moveFiles(srcPath, parentFullPath); - }; - moveFinish(srcPath, parentFullPath); - }, - function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(srcPath).then( - function (sFolder) { - moveFiles = function (srcPath, parentPath) { - var coreMove = function (storageFolderTop, complete) { - storageFolderTop.createFolderQuery().getFoldersAsync().then(function (folderList) { - var folderPromiseArr = []; - if (folderList.length === 0) { - // If failed, we must cancel the deletion of folders & files.So here wo can't delete the folder. - complete(); - } - else { - Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath).then(function (storageFolderTarget) { - var tempPromiseArr = []; - var index = 0; - for (var j = 0; j < folderList.length; j++) { - tempPromiseArr[index++] = storageFolderTarget.createFolderAsync(folderList[j].name).then(function (targetFolder) { - folderPromiseArr.push(moveFiles(folderList[j].path, targetFolder.path)); - }); - } - WinJS.Promise.join(tempPromiseArr).then(function () { - WinJS.Promise.join(folderPromiseArr).then(complete); - }); - }); - } - }); - }; - return new WinJS.Promise(function (complete) { - var storageFolderTop = null; - Windows.Storage.StorageFolder.getFolderFromPathAsync(srcPath).then(function (storageFolder) { - storageFolderTop = storageFolder; - return storageFolder.createFileQuery().getFilesAsync(); - }).then(function (fileList) { - var filePromiseArr = []; - Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath).then(function (dstStorageFolder) { - if (fileList) { - for (var i = 0; i < fileList.length; i++) { - filePromiseArr.push(fileList[i].moveAsync(dstStorageFolder)); - } - } - WinJS.Promise.join(filePromiseArr).then(function () { - coreMove(storageFolderTop, complete); - }, function () { }); - }); - }); - }); - }; - var moveFinish = function (srcPath, parentPath) { - var originFolderTop = null; - Windows.Storage.StorageFolder.getFolderFromPathAsync(srcPath).then(function (originFolder) { - originFolderTop = originFolder; - return Windows.Storage.StorageFolder.getFolderFromPathAsync(parentPath); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - }).then(function (storageFolder) { - return storageFolder.createFolderAsync(name, Windows.Storage.CreationCollisionOption.openIfExists); - }, function () { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - }).then(function (newStorageFolder) { - //can't move onto directory that is not empty - newStorageFolder.createFileQuery().getFilesAsync().then(function (fileList) { - newStorageFolder.createFolderQuery().getFoldersAsync().then(function (folderList) { - if (fileList.length !== 0 || folderList.length !== 0) { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - return; - } - //can't copy onto itself - if (srcPath == newStorageFolder.path) { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - return; - } - //can't copy into itself - if (srcPath == parentPath) { - fail && fail(FileError.INVALID_MODIFICATION_ERR); - return; - } - moveFiles(srcPath, newStorageFolder.path).then(function () { - var successCallback = function () { - success(new DirectoryEntry(name, newStorageFolder.path)); - }; - var temp = new DirectoryEntry(originFolderTop.name, originFolderTop.path).removeRecursively(successCallback, fail); - - }, function () { console.log("error!"); }); - }); - }); - }, function () { fail && fail(FileError.INVALID_MODIFICATION_ERR); }); - - }; - moveFinish(srcPath, parentFullPath); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - ); - }, - tempFileSystem:null, - - persistentFileSystem:null, - - requestFileSystem:function(win,fail,args) { - var type = args[0]; - var size = args[1]; - - var filePath = ""; - var result = null; - var fsTypeName = ""; - - switch (type) { - case LocalFileSystem.TEMPORARY: - filePath = Windows.Storage.ApplicationData.current.temporaryFolder.path; - fsTypeName = "temporary"; - break; - case LocalFileSystem.PERSISTENT: - filePath = Windows.Storage.ApplicationData.current.localFolder.path; - fsTypeName = "persistent"; - break; - } - - var MAX_SIZE = 10000000000; - if (size > MAX_SIZE) { - fail && fail(FileError.QUOTA_EXCEEDED_ERR); - return; - } - - var fileSystem = new FileSystem(fsTypeName, new DirectoryEntry(fsTypeName, filePath)); - result = fileSystem; - win(result); - }, - - resolveLocalFileSystemURI:function(success,fail,args) { - var uri = args[0]; - - var path = uri; - - // support for file name with parameters - if (/\?/g.test(path)) { - path = String(path).split("?")[0]; - } - - // support for encodeURI - if (/\%5/g.test(path)) { - path = decodeURI(path); - } - - // support for special path start with file:/// - if (path.substr(0, 8) == "file:///") { - path = Windows.Storage.ApplicationData.current.localFolder.path + "\\" + String(path).substr(8).split("/").join("\\"); - Windows.Storage.StorageFile.getFileFromPathAsync(path).then( - function (storageFile) { - success(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then( - function (storageFolder) { - success(new DirectoryEntry(storageFolder.name, storageFolder.path)); - }, function () { - fail && fail(FileError.NOT_FOUND_ERR); - } - ); - } - ); - } else { - Windows.Storage.StorageFile.getFileFromPathAsync(path).then( - function (storageFile) { - success(new FileEntry(storageFile.name, storageFile.path)); - }, function () { - Windows.Storage.StorageFolder.getFolderFromPathAsync(path).then( - function (storageFolder) { - success(new DirectoryEntry(storageFolder.name, storageFolder.path)); - }, function () { - fail && fail(FileError.ENCODING_ERR); - } - ); - } - ); - } - } - -}; - -require("cordova/windows8/commandProxy").add("File",module.exports); diff --git a/plugins/org.apache.cordova.file/src/wp/File.cs b/plugins/org.apache.cordova.file/src/wp/File.cs deleted file mode 100644 index 4fc61dde..00000000 --- a/plugins/org.apache.cordova.file/src/wp/File.cs +++ /dev/null @@ -1,1676 +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; - -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) - { - using (IsolatedStorageFile isoFile = IsolatedStorageFile.GetUserStoreForApplication()) - { - if (string.IsNullOrEmpty(filePath)) - { - throw new FileNotFoundException("File doesn't exist"); - } - else if (!isoFile.FileExists(filePath)) - { - // attempt to get it from the resources - if (filePath.IndexOf("www") == 0) - { - 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); - this.FullPath = filePath; - } - } - else - { - throw new FileNotFoundException("File doesn't exist"); - } - } - else - { - //TODO get file size the other way if possible - using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filePath, FileMode.Open, FileAccess.Read, isoFile)) - { - this.Size = stream.Length; - } - this.FullPath = filePath; - 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; } - - 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); - } - } - } - } - - 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]; - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR), 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]; - DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR), 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); - - using (TextReader reader = new StreamReader(isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read), encoding)) - { - text = reader.ReadToEnd(); - if (startPos < 0) - { - startPos = Math.Max(text.Length + startPos, 0); - } - else if (startPos > 0) - { - startPos = Math.Min(text.Length, startPos); - } - - if (endPos > 0) - { - endPos = Math.Min(text.Length, endPos); - } - else if (endPos < 0) - { - endPos = Math.Max(endPos + text.Length, 0); - } - - - text = text.Substring(startPos, endPos - startPos); - - } - } - - 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); - } - } - } - - /// <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; - } - - 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(data.ToCharArray()); - } - } - } - - DispatchCommandResult(new PluginResult(PluginResult.Status.OK, data.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 (filePath != null) - { - 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); - } - } - } - } - - /// <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 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 = Path.Combine(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 - - } -} |
