You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by st...@apache.org on 2014/02/11 00:22:14 UTC

[02/17] git commit: CB-5466: Update to work with filesystem URLs

CB-5466: Update to work with filesystem URLs

This should be backwards compatible; raw filesystem paths are now submitted to
the File plugin to see if they can be handled first


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/commit/647dad7a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/tree/647dad7a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/diff/647dad7a

Branch: refs/heads/master
Commit: 647dad7aba71f6e69d8b35b3cb76328c26127c1f
Parents: 09b6718
Author: Ian Clelland <ic...@chromium.org>
Authored: Tue Dec 10 13:59:09 2013 -0500
Committer: Ian Clelland <ic...@chromium.org>
Committed: Tue Dec 10 21:58:36 2013 -0500

----------------------------------------------------------------------
 plugin.xml                |  2 +-
 src/ios/CDVFileTransfer.h |  1 +
 src/ios/CDVFileTransfer.m | 98 ++++++++++++++++++++++++------------------
 3 files changed, 57 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/647dad7a/plugin.xml
----------------------------------------------------------------------
diff --git a/plugin.xml b/plugin.xml
index 2e2549d..6094927 100644
--- a/plugin.xml
+++ b/plugin.xml
@@ -10,7 +10,7 @@
     <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer.git</repo>
     <issue>https://issues.apache.org/jira/browse/CB/component/12320650</issue>
 
-    <dependency id="org.apache.cordova.file" />
+    <dependency id="org.apache.cordova.file@1" />
 
     <js-module src="www/FileTransferError.js" name="FileTransferError">
         <clobbers target="window.FileTransferError" />

http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/647dad7a/src/ios/CDVFileTransfer.h
----------------------------------------------------------------------
diff --git a/src/ios/CDVFileTransfer.h b/src/ios/CDVFileTransfer.h
index 8e8211d..aa1cf9e 100644
--- a/src/ios/CDVFileTransfer.h
+++ b/src/ios/CDVFileTransfer.h
@@ -71,6 +71,7 @@ extern NSString* const kOptionsKeyCookie;
 @property (nonatomic, copy) NSString* objectId;
 @property (nonatomic, copy) NSString* source;
 @property (nonatomic, copy) NSString* target;
+@property (nonatomic, copy) NSURL* targetURL;
 @property (nonatomic, copy) NSString* mimeType;
 @property (assign) int responseCode; // atomic
 @property (nonatomic, assign) long long bytesTransfered;

http://git-wip-us.apache.org/repos/asf/cordova-plugin-file-transfer/blob/647dad7a/src/ios/CDVFileTransfer.m
----------------------------------------------------------------------
diff --git a/src/ios/CDVFileTransfer.m b/src/ios/CDVFileTransfer.m
index c50754f..de3a8bd 100644
--- a/src/ios/CDVFileTransfer.m
+++ b/src/ios/CDVFileTransfer.m
@@ -20,12 +20,15 @@
 #import <Cordova/CDV.h>
 #import "CDVFileTransfer.h"
 #import "CDVFile.h"
+#import "CDVLocalFilesystem.h"
 
 #import <AssetsLibrary/ALAsset.h>
 #import <AssetsLibrary/ALAssetRepresentation.h>
 #import <AssetsLibrary/ALAssetsLibrary.h>
 #import <CFNetwork/CFNetwork.h>
 
+extern CDVFile *filePlugin;
+
 @interface CDVFileTransfer ()
 // Sets the requests headers for the request.
 - (void)applyRequestHeaders:(NSDictionary*)headers toRequest:(NSMutableURLRequest*)req;
@@ -274,31 +277,23 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
     NSString* server = [command.arguments objectAtIndex:1];
     NSError* __autoreleasing err = nil;
 
-    // return unsupported result for assets-library URLs
-    if ([source hasPrefix:kCDVAssetsLibraryPrefix]) {
-        // 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* fileData = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
-                [self uploadData:fileData command:command];
-            } else {
+    CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:source];
+    NSObject<CDVFileSystem> *fs;
+    if (sourceURL) {
+        // Try to get a CDVFileSystem which will handle this file.
+        // This requires talking to the current CDVFile plugin.
+        fs = [filePlugin filesystemForURL:sourceURL];
+    }
+    if (fs) {
+        [fs readFileAtURL:sourceURL start:0 end:-1 callback:^(NSData *fileData, NSString *mimeType, CDVFileError err) {
+            if (err) {
                 // We couldn't find the asset.  Send the appropriate error.
                 CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
                 [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+            }  else {
+                [self uploadData:fileData command:command];
             }
-        };
-        ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
-            // Retrieving the asset failed for some reason.  Send the appropriate error.
-            CDVPluginResult* 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:source] resultBlock:resultBlock failureBlock:failureBlock];
+        }];
         return;
     } else {
         // Extract the path part out of a file: URL.
@@ -315,8 +310,11 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
 
         if (err != nil) {
             NSLog(@"Error opening file %@: %@", source, err);
+            CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[self createFileTransferError:NOT_FOUND_ERR AndSource:source AndTarget:server]];
+            [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
+        } else {
+            [self uploadData:fileData command:command];
         }
-        [self uploadData:fileData command:command];
     }
 }
 
@@ -366,32 +364,32 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
     NSString* objectId = [command.arguments objectAtIndex:3];
     NSDictionary* headers = [command.arguments objectAtIndex:4 withDefault:nil];
 
-    // return unsupported result for assets-library URLs
-    if ([target hasPrefix:kCDVAssetsLibraryPrefix]) {
-        CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"download not supported for assets-library URLs."];
-        [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
-        return;
-    }
-
     CDVPluginResult* result = nil;
     CDVFileTransferError errorCode = 0;
 
     NSURL* targetURL;
 
     if ([target hasPrefix:@"/"]) {
-        targetURL = [NSURL fileURLWithPath:target];
+        /* Backwards-compatibility:
+         * Check here to see if it looks like the user passed in a raw filesystem path. (Perhaps they had the path saved, and were previously using it with the old version of File). If so, normalize it by removing empty path segments, and check with File to see if any of the installed filesystems will handle it. If so, then we will end up with a filesystem url to use for the remainder of this operation.
+         */
+        target = [target stringByReplacingOccurrencesOfString:@"//" withString:@"/"];
+        targetURL = [filePlugin fileSystemURLforLocalPath:target].url;
     } else {
         targetURL = [NSURL URLWithString:target];
     }
 
-    NSURL* url = [NSURL URLWithString:source];
+    NSURL* sourceURL = [NSURL URLWithString:source];
 
-    if (!url) {
+    if (!sourceURL) {
         errorCode = INVALID_URL_ERR;
         NSLog(@"File Transfer Error: Invalid server URL %@", source);
     } else if (![targetURL isFileURL]) {
-        errorCode = FILE_NOT_FOUND_ERR;
-        NSLog(@"File Transfer Error: Invalid file path or URL %@", target);
+        CDVFilesystemURL *fsURL = [CDVFilesystemURL fileSystemURLWithString:target];
+        if (!fsURL) {
+           errorCode = FILE_NOT_FOUND_ERR;
+           NSLog(@"File Transfer Error: Invalid file path or URL %@", target);
+        }
     }
 
     if (errorCode > 0) {
@@ -400,7 +398,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
         return;
     }
 
-    NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:url];
+    NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL:sourceURL];
     [self applyRequestHeaders:headers toRequest:req];
 
     CDVFileTransferDelegate* delegate = [[CDVFileTransferDelegate alloc] init];
@@ -409,7 +407,8 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
     delegate.callbackId = command.callbackId;
     delegate.objectId = objectId;
     delegate.source = source;
-    delegate.target = target;
+    delegate.target = [targetURL absoluteString];
+    delegate.targetURL = targetURL;
     delegate.trustAllHosts = trustAllHosts;
 
     delegate.connection = [NSURLConnection connectionWithRequest:req delegate:delegate];
@@ -522,8 +521,6 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
     NSString* downloadResponse = nil;
     NSMutableDictionary* uploadResult;
     CDVPluginResult* result = nil;
-    BOOL bDirRequest = NO;
-    CDVFile* filePlugin;
 
     NSLog(@"File Transfer Finished with response code %d", self.responseCode);
 
@@ -549,8 +546,7 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
             self.targetFileHandle = nil;
             DLog(@"File Transfer Download success");
 
-            filePlugin = [[CDVFile alloc] init];
-            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[filePlugin getDirectoryEntry:target isDirectory:bDirRequest]];
+            result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[filePlugin makeEntryForURL:self.targetURL]];
         } else {
             downloadResponse = [[NSString alloc] initWithData:self.responseData encoding:NSUTF8StringEncoding];
             result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsDictionary:[command createFileTransferError:CONNECTION_ERR AndSource:source AndTarget:target AndHttpStatus:self.responseCode AndBody:downloadResponse]];
@@ -619,7 +615,23 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
     }
     if ((self.direction == CDV_TRANSFER_DOWNLOAD) && (self.responseCode >= 200) && (self.responseCode < 300)) {
         // Download response is okay; begin streaming output to file
-        NSString* parentPath = [self.target stringByDeletingLastPathComponent];
+        NSString *filePath = nil;
+        CDVFilesystemURL *sourceURL = [CDVFilesystemURL fileSystemURLWithString:self.target];
+        if (sourceURL && sourceURL.fileSystemType != -1) {
+            // This requires talking to the current CDVFile plugin
+            NSObject<CDVFileSystem> *fs = [filePlugin.fileSystems objectAtIndex:sourceURL.fileSystemType];
+            filePath = [fs filesystemPathForURL:sourceURL];
+        } else {
+            // Extract the path part out of a file: URL.
+            NSString* filePath = [self.target hasPrefix:@"/"] ? [self.target copy] : [[NSURL URLWithString:self.target] path];
+            if (filePath == nil) {
+                // We couldn't find the asset.  Send the appropriate error.
+                [self cancelTransferWithError:connection errorMessage:[NSString stringWithFormat:@"Could not create target file"]];
+                return;
+            }
+        }
+
+        NSString* parentPath = [filePath stringByDeletingLastPathComponent];
 
         // create parent directories if needed
         if ([[NSFileManager defaultManager] createDirectoryAtPath:parentPath withIntermediateDirectories:YES attributes:nil error:&error] == NO) {
@@ -631,12 +643,12 @@ static CFIndex WriteDataToStream(NSData* data, CFWriteStreamRef stream)
             return;
         }
         // create target file
-        if ([[NSFileManager defaultManager] createFileAtPath:self.target contents:nil attributes:nil] == NO) {
+        if ([[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil] == NO) {
             [self cancelTransferWithError:connection errorMessage:@"Could not create target file"];
             return;
         }
         // open target file for writing
-        self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:self.target];
+        self.targetFileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
         if (self.targetFileHandle == nil) {
             [self cancelTransferWithError:connection errorMessage:@"Could not open target file for writing"];
         }