Github user tripodsan commented on a diff in the pull request:
https://github.com/apache/cordova-plugin-file/pull/42#discussion_r12163564
--- Diff: src/osx/CDVLocalFilesystem.m ---
@@ -0,0 +1,719 @@
+/*
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+ */
+
+#import "CDVFile.h"
+#import "CDVLocalFilesystem.h"
+#import <Cordova/CDV.h>
+#import <sys/xattr.h>
+
+@implementation CDVLocalFilesystem
+@synthesize name=_name, fsRoot=_fsRoot;
+
+- (id) initWithName:(NSString *)name root:(NSString *)fsRoot
+{
+ if (self) {
+ _name = name;
+ _fsRoot = fsRoot;
+ }
+ return self;
+}
+
+/*
+ * IN
+ * NSString localURI
+ * OUT
+ * CDVPluginResult result containing a file or directoryEntry for the
localURI, or an error if the
+ * URI represents a non-existent path, or is unrecognized or otherwise
malformed.
+ */
+- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
+{
+ CDVPluginResult* result = nil;
+ NSDictionary* entry = [self makeEntryForLocalURL:url];
+ if (entry) {
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:entry];
+ } else {
+ // return NOT_FOUND_ERR
+ result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+ }
+ return result;
+}
+- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
+ NSString *path = [self filesystemPathForURL:url];
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ BOOL isDir = NO;
+ // see if exists and is file or dir
+ BOOL bExists = [fileMgr fileExistsAtPath:path isDirectory:&isDir];
+ if (bExists) {
+ return [self makeEntryForPath:url.fullPath
fileSystemName:url.fileSystemName isDirectory:isDir];
+ } else {
+ return nil;
+ }
+}
+- (NSDictionary*)makeEntryForPath:(NSString*)fullPath
fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir
+{
+ NSMutableDictionary* dirEntry = [NSMutableDictionary
dictionaryWithCapacity:5];
+ NSString* lastPart = [[self stripQueryParametersFromPath:fullPath]
lastPathComponent];
+ if (isDir && ![fullPath hasSuffix:@"/"]) {
+ fullPath = [fullPath stringByAppendingString:@"/"];
+ }
+ [dirEntry setObject:[NSNumber numberWithBool:!isDir]
forKey:@"isFile"];
+ [dirEntry setObject:[NSNumber numberWithBool:isDir]
forKey:@"isDirectory"];
+ [dirEntry setObject:fullPath forKey:@"fullPath"];
+ [dirEntry setObject:lastPart forKey:@"name"];
+ [dirEntry setObject: [NSNumber numberWithInt:([fsName
isEqualToString:@"temporary"] ? 0 : 1)] forKey: @"filesystem"];
+ [dirEntry setObject:fsName forKey: @"filesystemName"];
+ dirEntry[@"nativeURL"] = [[NSURL fileURLWithPath:[self
filesystemPathForFullPath:fullPath]] absoluteString];
+
+
+ return dirEntry;
+}
+
+- (NSString *)stripQueryParametersFromPath:(NSString *)fullPath
+{
+ NSRange questionMark = [fullPath rangeOfString:@"?"];
+ if (questionMark.location != NSNotFound) {
+ return [fullPath
substringWithRange:NSMakeRange(0,questionMark.location)];
+ }
+ return fullPath;
+}
+
+- (NSString *)filesystemPathForFullPath:(NSString *)fullPath
+{
+ NSString *path = nil;
+ NSString *strippedFullPath = [self
stripQueryParametersFromPath:fullPath];
+ path = [NSString stringWithFormat:@"%@%@", self.fsRoot,
strippedFullPath];
+ if ([path length] > 1 && [path hasSuffix:@"/"]) {
+ path = [path substringToIndex:([path length]-1)];
+ }
+ return path;
+}
+/*
+ * IN
+ * NSString localURI
+ * OUT
+ * NSString full local filesystem path for the represented file or
directory, or nil if no such path is possible
+ * The file or directory does not necessarily have to exist. nil is
returned if the filesystem type is not recognized,
+ * or if the URL is malformed.
+ * The incoming URI should be properly escaped (no raw spaces, etc. URI
percent-encoding is expected).
+ */
+- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
+{
+ return [self filesystemPathForFullPath:url.fullPath];
+}
+
+- (CDVFilesystemURL *)URLforFullPath:(NSString *)fullPath
+{
+ if (fullPath) {
+ if ([fullPath hasPrefix:@"/"]) {
+ return [CDVFilesystemURL fileSystemURLWithString:[NSString
stringWithFormat:@"%@://localhost/%@%@", kCDVFilesystemURLPrefix, self.name,
fullPath]];
+ }
+ return [CDVFilesystemURL fileSystemURLWithString:[NSString
stringWithFormat:@"%@://localhost/%@/%@", kCDVFilesystemURLPrefix, self.name,
fullPath]];
+ }
+ return nil;
+}
+
+- (CDVFilesystemURL *)URLforFilesystemPath:(NSString *)path
+{
+ return [self URLforFullPath:[[self fullPathForFileSystemPath:path]
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+
+}
+
+- (NSString *)normalizePath:(NSString *)rawPath
+{
+ // If this is an absolute path, the first path component will be '/'.
Skip it if that's the case
+ BOOL isAbsolutePath = [rawPath hasPrefix:@"/"];
+ if (isAbsolutePath) {
+ rawPath = [rawPath substringFromIndex:1];
+ }
+ NSMutableArray *components = [NSMutableArray arrayWithArray:[rawPath
pathComponents]];
+ for (int index = 0; index < [components count]; ++index) {
+ if ([[components objectAtIndex:index] isEqualToString:@".."]) {
+ [components removeObjectAtIndex:index];
+ if (index > 0) {
+ [components removeObjectAtIndex:index-1];
+ --index;
+ }
+ }
+ }
+
+ if (isAbsolutePath) {
+ return [NSString stringWithFormat:@"/%@", [components
componentsJoinedByString:@"/"]];
+ } else {
+ return [components componentsJoinedByString:@"/"];
+ }
+
+
+}
+
+- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI
requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
+{
+ CDVPluginResult* result = nil;
+ BOOL bDirRequest = NO;
+ BOOL create = NO;
+ BOOL exclusive = NO;
+ int errorCode = 0; // !!! risky - no error code currently defined for 0
+
+ if ([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 {
+ // Build new fullPath for the requested resource.
+ // We concatenate the two paths together, and then scan the
resulting string to remove
+ // parent ("..") references. Any parent references at the
beginning of the string are
+ // silently removed.
+ NSString *combinedPath = [baseURI.fullPath
stringByAppendingPathComponent:[requestedPath
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
+ combinedPath = [self normalizePath:combinedPath];
+ CDVFilesystemURL* requestedURL = [self
URLforFullPath:combinedPath];
+
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ BOOL bIsDir;
+ BOOL bExists = [fileMgr fileExistsAtPath:[self
filesystemPathForURL:requestedURL] isDirectory:&bIsDir];
+ if (bExists && (create == NO) && (bIsDir == !bDirRequest)) {
+ // path exists and is not of requested type - return
TYPE_MISMATCH_ERR
+ errorCode = TYPE_MISMATCH_ERR;
+ } else if (!bExists && (create == NO)) {
+ // path does not exist and create is false - return
NOT_FOUND_ERR
+ errorCode = NOT_FOUND_ERR;
+ } else if (bExists && (create == YES) && (exclusive == YES)) {
+ // file/dir already exists and exclusive and create are both
true - return PATH_EXISTS_ERR
+ errorCode = PATH_EXISTS_ERR;
+ } else {
+ // if bExists and create == YES - just return data
+ // if bExists and create == NO - just return data
+ // if !bExists and create == YES - create and return data
+ BOOL bSuccess = YES;
+ NSError __autoreleasing* pError = nil;
+ if (!bExists && (create == YES)) {
+ if (bDirRequest) {
+ // create the dir
+ bSuccess = [fileMgr createDirectoryAtPath:[self
filesystemPathForURL:requestedURL] withIntermediateDirectories:NO
attributes:nil error:&pError];
+ } else {
+ // create the empty file
+ bSuccess = [fileMgr createFileAtPath:[self
filesystemPathForURL:requestedURL] contents:nil attributes:nil];
+ }
+ }
+ if (!bSuccess) {
+ errorCode = ABORT_ERR;
+ if (pError) {
+ NSLog(@"error creating directory: %@", [pError
localizedDescription]);
+ }
+ } else {
+ // NSLog(@"newly created file/dir (%@) exists: %d",
reqFullPath, [fileMgr fileExistsAtPath:reqFullPath]);
+ // file existed or was created
+ result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK messageAsDictionary:[self
makeEntryForPath:requestedURL.fullPath fileSystemName:baseURI.fileSystemName
isDirectory:bDirRequest]];
+ }
+ } // are all possible conditions met?
+ }
+
+ if (errorCode > 0) {
+ // create error callback
+ result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
+ }
+ return result;
+
+}
+
+- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
+{
+ CDVPluginResult* result = nil;
+ CDVFilesystemURL *newURI = nil;
+ if ([localURI.fullPath isEqualToString:@""]) {
+ // return self
+ newURI = localURI;
+ } else {
+ newURI = [CDVFilesystemURL fileSystemURLWithURL:[localURI.url
URLByDeletingLastPathComponent]]; /* TODO: UGLY - FIX */
+ }
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ BOOL bIsDir;
+ BOOL bExists = [fileMgr fileExistsAtPath:[self
filesystemPathForURL:newURI] isDirectory:&bIsDir];
+ if (bExists) {
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:[self makeEntryForPath:newURI.fullPath
fileSystemName:newURI.fileSystemName isDirectory:bIsDir]];
+ } else {
+ // invalid path or file does not exist
+ result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
+ }
+ return result;
+}
+
+- (void)getMetadataForURL:(CDVFilesystemURL *)url callback:(void
(^)(CDVPluginResult *))callback
+{
+
+ NSFileManager* fileMgr = [[NSFileManager alloc] init];
+ NSError* __autoreleasing error = nil;
+
+ CDVPluginResult *result;
+ NSDictionary* fileAttribs = [fileMgr attributesOfItemAtPath:[self
filesystemPathForURL:url] error:&error];
+
+ if (fileAttribs) {
+ // Ensure that directories (and other non-regular files) report
size of 0
+ unsigned long long size = ([fileAttribs fileType] ==
NSFileTypeRegular ? [fileAttribs fileSize] : 0);
+ NSDate* modDate = [fileAttribs fileModificationDate];
+ if (modDate) {
+ result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:@{@"modificationTime": @([modDate timeIntervalSince1970] *
1000), @"size": @(size)}];
+ }
+ } 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];
+ }
+ callback(result);
+}
+
+- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI
withObject:(NSDictionary *)options
+{
+ BOOL ok = NO;
+
+ NSString* filePath = [self filesystemPathForURL:localURI];
+ // we only care about this iCloud key for now.
+ // set to 1/true to skip backup, set to 0/false to back it up
(effectively removing the attribute)
+ NSString* iCloudBackupExtendedAttributeKey = @"com.apple.MobileBackup";
+ id iCloudBackupExtendedAttributeValue = [options
objectForKey:iCloudBackupExtendedAttributeKey];
+
+ if ((iCloudBackupExtendedAttributeValue != nil) &&
[iCloudBackupExtendedAttributeValue isKindOfClass:[NSNumber class]]) {
+ NSURL* url = [NSURL fileURLWithPath:filePath];
--- End diff --
wrong indentation.
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---