PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/front/plugins/cordova-plugin-file/src/ios/CDVFile.m

https://gitlab.com/boxnia/NFU_MOVIL
Objective C | 1117 lines | 729 code | 160 blank | 228 comment | 122 complexity | 0404677b00a0fac067f526a55858cd34 MD5 | raw file
  1. /*
  2. Licensed to the Apache Software Foundation (ASF) under one
  3. or more contributor license agreements. See the NOTICE file
  4. distributed with this work for additional information
  5. regarding copyright ownership. The ASF licenses this file
  6. to you under the Apache License, Version 2.0 (the
  7. "License"); you may not use this file except in compliance
  8. with the License. You may obtain a copy of the License at
  9. http://www.apache.org/licenses/LICENSE-2.0
  10. Unless required by applicable law or agreed to in writing,
  11. software distributed under the License is distributed on an
  12. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  13. KIND, either express or implied. See the License for the
  14. specific language governing permissions and limitations
  15. under the License.
  16. */
  17. #import <Cordova/CDV.h>
  18. #import "CDVFile.h"
  19. #import "CDVLocalFilesystem.h"
  20. #import "CDVAssetLibraryFilesystem.h"
  21. #import <objc/message.h>
  22. static NSString* toBase64(NSData* data) {
  23. SEL s1 = NSSelectorFromString(@"cdv_base64EncodedString");
  24. SEL s2 = NSSelectorFromString(@"base64EncodedString");
  25. SEL s3 = NSSelectorFromString(@"base64EncodedStringWithOptions:");
  26. if ([data respondsToSelector:s1]) {
  27. NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s1];
  28. return func(data, s1);
  29. } else if ([data respondsToSelector:s2]) {
  30. NSString* (*func)(id, SEL) = (void *)[data methodForSelector:s2];
  31. return func(data, s2);
  32. } else if ([data respondsToSelector:s3]) {
  33. NSString* (*func)(id, SEL, NSUInteger) = (void *)[data methodForSelector:s3];
  34. return func(data, s3, 0);
  35. } else {
  36. return nil;
  37. }
  38. }
  39. CDVFile *filePlugin = nil;
  40. extern NSString * const NSURLIsExcludedFromBackupKey __attribute__((weak_import));
  41. #ifndef __IPHONE_5_1
  42. NSString* const NSURLIsExcludedFromBackupKey = @"NSURLIsExcludedFromBackupKey";
  43. #endif
  44. NSString* const kCDVFilesystemURLPrefix = @"cdvfile";
  45. @implementation CDVFilesystemURL
  46. @synthesize url=_url;
  47. @synthesize fileSystemName=_fileSystemName;
  48. @synthesize fullPath=_fullPath;
  49. - (id) initWithString:(NSString *)strURL
  50. {
  51. if ( self = [super init] ) {
  52. NSURL *decodedURL = [NSURL URLWithString:strURL];
  53. return [self initWithURL:decodedURL];
  54. }
  55. return nil;
  56. }
  57. -(id) initWithURL:(NSURL *)URL
  58. {
  59. if ( self = [super init] ) {
  60. self.url = URL;
  61. self.fileSystemName = [self filesystemNameForLocalURI:URL];
  62. self.fullPath = [self fullPathForLocalURI:URL];
  63. }
  64. return self;
  65. }
  66. /*
  67. * IN
  68. * NSString localURI
  69. * OUT
  70. * NSString FileSystem Name for this URI, or nil if it is not recognized.
  71. */
  72. - (NSString *)filesystemNameForLocalURI:(NSURL *)uri
  73. {
  74. if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
  75. NSArray *pathComponents = [uri pathComponents];
  76. if (pathComponents != nil && pathComponents.count > 1) {
  77. return [pathComponents objectAtIndex:1];
  78. }
  79. } else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
  80. return @"assets-library";
  81. }
  82. return nil;
  83. }
  84. /*
  85. * IN
  86. * NSString localURI
  87. * OUT
  88. * NSString fullPath component suitable for an Entry object.
  89. * The incoming URI should be properly escaped. The returned fullPath is unescaped.
  90. */
  91. - (NSString *)fullPathForLocalURI:(NSURL *)uri
  92. {
  93. if ([[uri scheme] isEqualToString:kCDVFilesystemURLPrefix] && [[uri host] isEqualToString:@"localhost"]) {
  94. NSString *path = [uri path];
  95. if ([uri query]) {
  96. path = [NSString stringWithFormat:@"%@?%@", path, [uri query]];
  97. }
  98. NSRange slashRange = [path rangeOfString:@"/" options:0 range:NSMakeRange(1, path.length-1)];
  99. if (slashRange.location == NSNotFound) {
  100. return @"";
  101. }
  102. return [path substringFromIndex:slashRange.location];
  103. } else if ([[uri scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
  104. return [[uri absoluteString] substringFromIndex:[kCDVAssetsLibraryScheme length]+2];
  105. }
  106. return nil;
  107. }
  108. + (CDVFilesystemURL *)fileSystemURLWithString:(NSString *)strURL
  109. {
  110. return [[CDVFilesystemURL alloc] initWithString:strURL];
  111. }
  112. + (CDVFilesystemURL *)fileSystemURLWithURL:(NSURL *)URL
  113. {
  114. return [[CDVFilesystemURL alloc] initWithURL:URL];
  115. }
  116. - (NSString *)absoluteURL
  117. {
  118. return [NSString stringWithFormat:@"cdvfile://localhost/%@%@", self.fileSystemName, self.fullPath];
  119. }
  120. @end
  121. @implementation CDVFilesystemURLProtocol
  122. + (BOOL)canInitWithRequest:(NSURLRequest*)request
  123. {
  124. NSURL* url = [request URL];
  125. return [[url scheme] isEqualToString:kCDVFilesystemURLPrefix];
  126. }
  127. + (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest*)request
  128. {
  129. return request;
  130. }
  131. + (BOOL)requestIsCacheEquivalent:(NSURLRequest*)requestA toRequest:(NSURLRequest*)requestB
  132. {
  133. return [[[requestA URL] resourceSpecifier] isEqualToString:[[requestB URL] resourceSpecifier]];
  134. }
  135. - (void)startLoading
  136. {
  137. CDVFilesystemURL* url = [CDVFilesystemURL fileSystemURLWithURL:[[self request] URL]];
  138. NSObject<CDVFileSystem> *fs = [filePlugin filesystemForURL:url];
  139. __weak CDVFilesystemURLProtocol* weakSelf = self;
  140. [fs readFileAtURL:url start:0 end:-1 callback:^void(NSData *data, NSString *mimetype, CDVFileError error) {
  141. NSMutableDictionary* responseHeaders = [[NSMutableDictionary alloc] init];
  142. responseHeaders[@"Cache-Control"] = @"no-cache";
  143. if (!error) {
  144. responseHeaders[@"Content-Type"] = mimetype;
  145. NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url.url statusCode:200 HTTPVersion:@"HTTP/1.1"headerFields:responseHeaders];
  146. [[weakSelf client] URLProtocol:weakSelf didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
  147. [[weakSelf client] URLProtocol:weakSelf didLoadData:data];
  148. [[weakSelf client] URLProtocolDidFinishLoading:weakSelf];
  149. } else {
  150. NSURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url.url statusCode:404 HTTPVersion:@"HTTP/1.1"headerFields:responseHeaders];
  151. [[weakSelf client] URLProtocol:weakSelf didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
  152. [[weakSelf client] URLProtocolDidFinishLoading:weakSelf];
  153. }
  154. }];
  155. }
  156. - (void)stopLoading
  157. {}
  158. - (NSCachedURLResponse *)connection:(NSURLConnection *)connection
  159. willCacheResponse:(NSCachedURLResponse*)cachedResponse {
  160. return nil;
  161. }
  162. @end
  163. @implementation CDVFile
  164. @synthesize rootDocsPath, appDocsPath, appLibraryPath, appTempPath, userHasAllowed, fileSystems=fileSystems_;
  165. - (void)registerFilesystem:(NSObject<CDVFileSystem> *)fs {
  166. __weak CDVFile* weakSelf = self;
  167. SEL sel = NSSelectorFromString(@"urlTransformer");
  168. // for backwards compatibility - we check if this property is there
  169. // we create a wrapper block because the urlTransformer property
  170. // on the commandDelegate might be set dynamically at a future time
  171. // (and not dependent on plugin loading order)
  172. if ([self.commandDelegate respondsToSelector:sel]) {
  173. fs.urlTransformer = ^NSURL*(NSURL* urlToTransform) {
  174. // grab the block from the commandDelegate
  175. NSURL* (^urlTransformer)(NSURL*) = ((id(*)(id, SEL))objc_msgSend)(weakSelf.commandDelegate, sel);
  176. // if block is not null, we call it
  177. if (urlTransformer) {
  178. return urlTransformer(urlToTransform);
  179. } else { // else we return the same url
  180. return urlToTransform;
  181. }
  182. };
  183. }
  184. [fileSystems_ addObject:fs];
  185. }
  186. - (NSObject<CDVFileSystem> *)fileSystemByName:(NSString *)fsName
  187. {
  188. if (self.fileSystems != nil) {
  189. for (NSObject<CDVFileSystem> *fs in self.fileSystems) {
  190. if ([fs.name isEqualToString:fsName]) {
  191. return fs;
  192. }
  193. }
  194. }
  195. return nil;
  196. }
  197. - (NSObject<CDVFileSystem> *)filesystemForURL:(CDVFilesystemURL *)localURL {
  198. if (localURL.fileSystemName == nil) return nil;
  199. @try {
  200. return [self fileSystemByName:localURL.fileSystemName];
  201. }
  202. @catch (NSException *e) {
  203. return nil;
  204. }
  205. }
  206. - (NSArray *)getExtraFileSystemsPreference:(UIViewController *)vc
  207. {
  208. NSString *filesystemsStr = nil;
  209. if([self.viewController isKindOfClass:[CDVViewController class]]) {
  210. CDVViewController *vc = (CDVViewController *)self.viewController;
  211. NSDictionary *settings = [vc settings];
  212. filesystemsStr = [settings[@"iosextrafilesystems"] lowercaseString];
  213. }
  214. if (!filesystemsStr) {
  215. filesystemsStr = @"library,library-nosync,documents,documents-nosync,cache,bundle,root";
  216. }
  217. return [filesystemsStr componentsSeparatedByString:@","];
  218. }
  219. - (void)makeNonSyncable:(NSString*)path {
  220. [[NSFileManager defaultManager] createDirectoryAtPath:path
  221. withIntermediateDirectories:YES
  222. attributes:nil
  223. error:nil];
  224. NSURL* url = [NSURL fileURLWithPath:path];
  225. [url setResourceValue: [NSNumber numberWithBool: YES]
  226. forKey: NSURLIsExcludedFromBackupKey error:nil];
  227. }
  228. - (void)registerExtraFileSystems:(NSArray *)filesystems fromAvailableSet:(NSDictionary *)availableFileSystems
  229. {
  230. NSMutableSet *installedFilesystems = [[NSMutableSet alloc] initWithCapacity:7];
  231. /* Build non-syncable directories as necessary */
  232. for (NSString *nonSyncFS in @[@"library-nosync", @"documents-nosync"]) {
  233. if ([filesystems containsObject:nonSyncFS]) {
  234. [self makeNonSyncable:availableFileSystems[nonSyncFS]];
  235. }
  236. }
  237. /* Register filesystems in order */
  238. for (NSString *fsName in filesystems) {
  239. if (![installedFilesystems containsObject:fsName]) {
  240. NSString *fsRoot = availableFileSystems[fsName];
  241. if (fsRoot) {
  242. [filePlugin registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:fsName root:fsRoot]];
  243. [installedFilesystems addObject:fsName];
  244. } else {
  245. NSLog(@"Unrecognized extra filesystem identifier: %@", fsName);
  246. }
  247. }
  248. }
  249. }
  250. - (NSDictionary *)getAvailableFileSystems
  251. {
  252. NSString *libPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  253. NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
  254. return @{
  255. @"library": libPath,
  256. @"library-nosync": [libPath stringByAppendingPathComponent:@"NoCloud"],
  257. @"documents": docPath,
  258. @"documents-nosync": [docPath stringByAppendingPathComponent:@"NoCloud"],
  259. @"cache": [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) objectAtIndex:0],
  260. @"bundle": [[NSBundle mainBundle] bundlePath],
  261. @"root": @"/"
  262. };
  263. }
  264. - (void)pluginInitialize
  265. {
  266. filePlugin = self;
  267. [NSURLProtocol registerClass:[CDVFilesystemURLProtocol class]];
  268. fileSystems_ = [[NSMutableArray alloc] initWithCapacity:3];
  269. // Get the Library directory path
  270. NSArray* paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
  271. self.appLibraryPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"files"];
  272. // Get the Temporary directory path
  273. self.appTempPath = [NSTemporaryDirectory()stringByStandardizingPath]; // remove trailing slash from NSTemporaryDirectory()
  274. // Get the Documents directory path
  275. paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
  276. self.rootDocsPath = [paths objectAtIndex:0];
  277. self.appDocsPath = [self.rootDocsPath stringByAppendingPathComponent:@"files"];
  278. NSString *location = nil;
  279. if([self.viewController isKindOfClass:[CDVViewController class]]) {
  280. CDVViewController *vc = (CDVViewController *)self.viewController;
  281. NSMutableDictionary *settings = vc.settings;
  282. location = [[settings objectForKey:@"iospersistentfilelocation"] lowercaseString];
  283. }
  284. if (location == nil) {
  285. // Compatibilty by default (if the config preference is not set, or
  286. // if we're not embedded in a CDVViewController somehow.)
  287. location = @"compatibility";
  288. }
  289. NSError *error;
  290. if ([[NSFileManager defaultManager] createDirectoryAtPath:self.appTempPath
  291. withIntermediateDirectories:YES
  292. attributes:nil
  293. error:&error]) {
  294. [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"temporary" root:self.appTempPath]];
  295. } else {
  296. NSLog(@"Unable to create temporary directory: %@", error);
  297. }
  298. if ([location isEqualToString:@"library"]) {
  299. if ([[NSFileManager defaultManager] createDirectoryAtPath:self.appLibraryPath
  300. withIntermediateDirectories:YES
  301. attributes:nil
  302. error:&error]) {
  303. [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"persistent" root:self.appLibraryPath]];
  304. } else {
  305. NSLog(@"Unable to create library directory: %@", error);
  306. }
  307. } else if ([location isEqualToString:@"compatibility"]) {
  308. /*
  309. * Fall-back to compatibility mode -- this is the logic implemented in
  310. * earlier versions of this plugin, and should be maintained here so
  311. * that apps which were originally deployed with older versions of the
  312. * plugin can continue to provide access to files stored under those
  313. * versions.
  314. */
  315. [self registerFilesystem:[[CDVLocalFilesystem alloc] initWithName:@"persistent" root:self.rootDocsPath]];
  316. } else {
  317. NSAssert(false,
  318. @"File plugin configuration error: Please set iosPersistentFileLocation in config.xml to one of \"library\" (for new applications) or \"compatibility\" (for compatibility with previous versions)");
  319. }
  320. [self registerFilesystem:[[CDVAssetLibraryFilesystem alloc] initWithName:@"assets-library"]];
  321. [self registerExtraFileSystems:[self getExtraFileSystemsPreference:self.viewController]
  322. fromAvailableSet:[self getAvailableFileSystems]];
  323. }
  324. - (CDVFilesystemURL *)fileSystemURLforArg:(NSString *)urlArg
  325. {
  326. CDVFilesystemURL* ret = nil;
  327. if ([urlArg hasPrefix:@"file://"]) {
  328. /* This looks like a file url. Get the path, and see if any handlers recognize it. */
  329. NSURL *fileURL = [NSURL URLWithString:urlArg];
  330. NSURL *resolvedFileURL = [fileURL URLByResolvingSymlinksInPath];
  331. NSString *path = [resolvedFileURL path];
  332. ret = [self fileSystemURLforLocalPath:path];
  333. } else {
  334. ret = [CDVFilesystemURL fileSystemURLWithString:urlArg];
  335. }
  336. return ret;
  337. }
  338. - (CDVFilesystemURL *)fileSystemURLforLocalPath:(NSString *)localPath
  339. {
  340. CDVFilesystemURL *localURL = nil;
  341. NSUInteger shortestFullPath = 0;
  342. // Try all installed filesystems, in order. Return the most match url.
  343. for (id object in self.fileSystems) {
  344. if ([object respondsToSelector:@selector(URLforFilesystemPath:)]) {
  345. CDVFilesystemURL *url = [object URLforFilesystemPath:localPath];
  346. if (url){
  347. // A shorter fullPath would imply that the filesystem is a better match for the local path
  348. if (!localURL || ([[url fullPath] length] < shortestFullPath)) {
  349. localURL = url;
  350. shortestFullPath = [[url fullPath] length];
  351. }
  352. }
  353. }
  354. }
  355. return localURL;
  356. }
  357. - (NSNumber*)checkFreeDiskSpace:(NSString*)appPath
  358. {
  359. NSFileManager* fMgr = [[NSFileManager alloc] init];
  360. NSError* __autoreleasing pError = nil;
  361. NSDictionary* pDict = [fMgr attributesOfFileSystemForPath:appPath error:&pError];
  362. NSNumber* pNumAvail = (NSNumber*)[pDict objectForKey:NSFileSystemFreeSize];
  363. return pNumAvail;
  364. }
  365. /* Request the File System info
  366. *
  367. * IN:
  368. * arguments[0] - type (number as string)
  369. * TEMPORARY = 0, PERSISTENT = 1;
  370. * arguments[1] - size
  371. *
  372. * OUT:
  373. * Dictionary representing FileSystem object
  374. * name - the human readable directory name
  375. * root = DirectoryEntry object
  376. * bool isDirectory
  377. * bool isFile
  378. * string name
  379. * string fullPath
  380. * fileSystem = FileSystem object - !! ignored because creates circular reference !!
  381. */
  382. - (void)requestFileSystem:(CDVInvokedUrlCommand*)command
  383. {
  384. // arguments
  385. NSString* strType = [command argumentAtIndex:0];
  386. unsigned long long size = [[command argumentAtIndex:1] longLongValue];
  387. int type = [strType intValue];
  388. CDVPluginResult* result = nil;
  389. if (type >= self.fileSystems.count) {
  390. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR];
  391. NSLog(@"No filesystem of type requested");
  392. } else {
  393. NSString* fullPath = @"/";
  394. // check for avail space for size request
  395. NSNumber* pNumAvail = [self checkFreeDiskSpace:self.rootDocsPath];
  396. // NSLog(@"Free space: %@", [NSString stringWithFormat:@"%qu", [ pNumAvail unsignedLongLongValue ]]);
  397. if (pNumAvail && ([pNumAvail unsignedLongLongValue] < size)) {
  398. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:QUOTA_EXCEEDED_ERR];
  399. } else {
  400. NSObject<CDVFileSystem> *rootFs = [self.fileSystems objectAtIndex:type];
  401. if (rootFs == nil) {
  402. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:NOT_FOUND_ERR];
  403. NSLog(@"No filesystem of type requested");
  404. } else {
  405. NSMutableDictionary* fileSystem = [NSMutableDictionary dictionaryWithCapacity:2];
  406. [fileSystem setObject:rootFs.name forKey:@"name"];
  407. NSDictionary* dirEntry = [self makeEntryForPath:fullPath fileSystemName:rootFs.name isDirectory:YES];
  408. [fileSystem setObject:dirEntry forKey:@"root"];
  409. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileSystem];
  410. }
  411. }
  412. }
  413. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  414. }
  415. - (void)requestAllFileSystems:(CDVInvokedUrlCommand*)command
  416. {
  417. NSMutableArray* ret = [[NSMutableArray alloc] init];
  418. for (NSObject<CDVFileSystem>* root in fileSystems_) {
  419. [ret addObject:[self makeEntryForPath:@"/" fileSystemName:root.name isDirectory:YES]];
  420. }
  421. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:ret];
  422. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  423. }
  424. - (void)requestAllPaths:(CDVInvokedUrlCommand*)command
  425. {
  426. NSString* libPath = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES)[0];
  427. NSString* libPathSync = [libPath stringByAppendingPathComponent:@"Cloud"];
  428. NSString* libPathNoSync = [libPath stringByAppendingPathComponent:@"NoCloud"];
  429. NSString* docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
  430. NSString* storagePath = [libPath stringByDeletingLastPathComponent];
  431. NSString* cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
  432. // Create the directories if necessary.
  433. [[NSFileManager defaultManager] createDirectoryAtPath:libPathSync withIntermediateDirectories:YES attributes:nil error:nil];
  434. [[NSFileManager defaultManager] createDirectoryAtPath:libPathNoSync withIntermediateDirectories:YES attributes:nil error:nil];
  435. // Mark NoSync as non-iCloud.
  436. [[NSURL fileURLWithPath:libPathNoSync] setResourceValue: [NSNumber numberWithBool: YES]
  437. forKey: NSURLIsExcludedFromBackupKey error:nil];
  438. NSDictionary* ret = @{
  439. @"applicationDirectory": [[NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]] absoluteString],
  440. @"applicationStorageDirectory": [[NSURL fileURLWithPath:storagePath] absoluteString],
  441. @"dataDirectory": [[NSURL fileURLWithPath:libPathNoSync] absoluteString],
  442. @"syncedDataDirectory": [[NSURL fileURLWithPath:libPathSync] absoluteString],
  443. @"documentsDirectory": [[NSURL fileURLWithPath:docPath] absoluteString],
  444. @"cacheDirectory": [[NSURL fileURLWithPath:cachePath] absoluteString],
  445. @"tempDirectory": [[NSURL fileURLWithPath:NSTemporaryDirectory()] absoluteString]
  446. };
  447. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:ret];
  448. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  449. }
  450. /* Creates and returns a dictionary representing an Entry Object
  451. *
  452. * IN:
  453. * NSString* fullPath of the entry
  454. * int fsType - FileSystem type
  455. * BOOL isDirectory - YES if this is a directory, NO if is a file
  456. * OUT:
  457. * NSDictionary* Entry object
  458. * bool as NSNumber isDirectory
  459. * bool as NSNumber isFile
  460. * NSString* name - last part of path
  461. * NSString* fullPath
  462. * NSString* filesystemName - FileSystem name -- actual filesystem will be created on the JS side if necessary, to avoid
  463. * creating circular reference (FileSystem contains DirectoryEntry which contains FileSystem.....!!)
  464. */
  465. - (NSDictionary*)makeEntryForPath:(NSString*)fullPath fileSystemName:(NSString *)fsName isDirectory:(BOOL)isDir
  466. {
  467. NSObject<CDVFileSystem> *fs = [self fileSystemByName:fsName];
  468. return [fs makeEntryForPath:fullPath isDirectory:isDir];
  469. }
  470. - (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)localURL
  471. {
  472. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURL];
  473. return [fs makeEntryForLocalURL:localURL];
  474. }
  475. - (NSDictionary *)makeEntryForURL:(NSURL *)URL
  476. {
  477. CDVFilesystemURL* fsURL = [self fileSystemURLforArg:[URL absoluteString]];
  478. return [self makeEntryForLocalURL:fsURL];
  479. }
  480. /*
  481. * Given a URI determine the File System information associated with it and return an appropriate W3C entry object
  482. * IN
  483. * NSString* localURI: Should be an escaped local filesystem URI
  484. * OUT
  485. * Entry object
  486. * bool isDirectory
  487. * bool isFile
  488. * string name
  489. * string fullPath
  490. * fileSystem = FileSystem object - !! ignored because creates circular reference FileSystem contains DirectoryEntry which contains FileSystem.....!!
  491. */
  492. - (void)resolveLocalFileSystemURI:(CDVInvokedUrlCommand*)command
  493. {
  494. // arguments
  495. NSString* localURIstr = [command argumentAtIndex:0];
  496. CDVPluginResult* result;
  497. localURIstr = [self encodePath:localURIstr]; //encode path before resolving
  498. CDVFilesystemURL* inputURI = [self fileSystemURLforArg:localURIstr];
  499. if (inputURI == nil || inputURI.fileSystemName == nil) {
  500. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR];
  501. } else {
  502. NSObject<CDVFileSystem> *fs = [self filesystemForURL:inputURI];
  503. if (fs == nil) {
  504. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:ENCODING_ERR];
  505. } else {
  506. result = [fs entryForLocalURI:inputURI];
  507. }
  508. }
  509. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  510. }
  511. //encode path with percent escapes
  512. -(NSString *)encodePath:(NSString *)path
  513. {
  514. NSString *decodedPath = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; //decode incase it's already encoded to avoid encoding twice
  515. return [decodedPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
  516. }
  517. /* Part of DirectoryEntry interface, creates or returns the specified directory
  518. * IN:
  519. * NSString* localURI - local filesystem URI for this directory
  520. * NSString* path - directory to be created/returned; may be full path or relative path
  521. * NSDictionary* - Flags object
  522. * boolean as NSNumber create -
  523. * if create is true and directory does not exist, create dir and return directory entry
  524. * if create is true and exclusive is true and directory does exist, return error
  525. * if create is false and directory does not exist, return error
  526. * if create is false and the path represents a file, return error
  527. * boolean as NSNumber exclusive - used in conjunction with create
  528. * if exclusive is true and create is true - specifies failure if directory already exists
  529. *
  530. *
  531. */
  532. - (void)getDirectory:(CDVInvokedUrlCommand*)command
  533. {
  534. NSMutableArray* arguments = [NSMutableArray arrayWithArray:command.arguments];
  535. NSMutableDictionary* options = nil;
  536. if ([arguments count] >= 3) {
  537. options = [command argumentAtIndex:2 withDefault:nil];
  538. }
  539. // add getDir to options and call getFile()
  540. if (options != nil) {
  541. options = [NSMutableDictionary dictionaryWithDictionary:options];
  542. } else {
  543. options = [NSMutableDictionary dictionaryWithCapacity:1];
  544. }
  545. [options setObject:[NSNumber numberWithInt:1] forKey:@"getDir"];
  546. if ([arguments count] >= 3) {
  547. [arguments replaceObjectAtIndex:2 withObject:options];
  548. } else {
  549. [arguments addObject:options];
  550. }
  551. CDVInvokedUrlCommand* subCommand =
  552. [[CDVInvokedUrlCommand alloc] initWithArguments:arguments
  553. callbackId:command.callbackId
  554. className:command.className
  555. methodName:command.methodName];
  556. [self getFile:subCommand];
  557. }
  558. /* Part of DirectoryEntry interface, creates or returns the specified file
  559. * IN:
  560. * NSString* baseURI - local filesytem URI for the base directory to search
  561. * NSString* requestedPath - file to be created/returned; may be absolute path or relative path
  562. * NSDictionary* options - Flags object
  563. * boolean as NSNumber create -
  564. * if create is true and file does not exist, create file and return File entry
  565. * if create is true and exclusive is true and file does exist, return error
  566. * if create is false and file does not exist, return error
  567. * if create is false and the path represents a directory, return error
  568. * boolean as NSNumber exclusive - used in conjunction with create
  569. * if exclusive is true and create is true - specifies failure if file already exists
  570. */
  571. - (void)getFile:(CDVInvokedUrlCommand*)command
  572. {
  573. NSString* baseURIstr = [command argumentAtIndex:0];
  574. CDVFilesystemURL* baseURI = [self fileSystemURLforArg:baseURIstr];
  575. NSString* requestedPath = [command argumentAtIndex:1];
  576. NSDictionary* options = [command argumentAtIndex:2 withDefault:nil];
  577. NSObject<CDVFileSystem> *fs = [self filesystemForURL:baseURI];
  578. CDVPluginResult* result = [fs getFileForURL:baseURI requestedPath:requestedPath options:options];
  579. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  580. }
  581. /*
  582. * Look up the parent Entry containing this Entry.
  583. * If this Entry is the root of its filesystem, its parent is itself.
  584. * IN:
  585. * NSArray* arguments
  586. * 0 - NSString* localURI
  587. * NSMutableDictionary* options
  588. * empty
  589. */
  590. - (void)getParent:(CDVInvokedUrlCommand*)command
  591. {
  592. // arguments are URL encoded
  593. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  594. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  595. CDVPluginResult* result = [fs getParentForURL:localURI];
  596. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  597. }
  598. /*
  599. * set MetaData of entry
  600. * Currently we only support "com.apple.MobileBackup" (boolean)
  601. */
  602. - (void)setMetadata:(CDVInvokedUrlCommand*)command
  603. {
  604. // arguments
  605. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  606. NSDictionary* options = [command argumentAtIndex:1 withDefault:nil];
  607. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  608. CDVPluginResult* result = [fs setMetadataForURL:localURI withObject:options];
  609. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  610. }
  611. /* removes the directory or file entry
  612. * IN:
  613. * NSArray* arguments
  614. * 0 - NSString* localURI
  615. *
  616. * returns NO_MODIFICATION_ALLOWED_ERR if is top level directory or no permission to delete dir
  617. * returns INVALID_MODIFICATION_ERR if is non-empty dir or asset library file
  618. * returns NOT_FOUND_ERR if file or dir is not found
  619. */
  620. - (void)remove:(CDVInvokedUrlCommand*)command
  621. {
  622. // arguments
  623. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  624. CDVPluginResult* result = nil;
  625. if ([localURI.fullPath isEqualToString:@""]) {
  626. // error if try to remove top level (documents or tmp) dir
  627. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
  628. } else {
  629. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  630. result = [fs removeFileAtURL:localURI];
  631. }
  632. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  633. }
  634. /* recursively removes the directory
  635. * IN:
  636. * NSArray* arguments
  637. * 0 - NSString* localURI
  638. *
  639. * returns NO_MODIFICATION_ALLOWED_ERR if is top level directory or no permission to delete dir
  640. * returns NOT_FOUND_ERR if file or dir is not found
  641. */
  642. - (void)removeRecursively:(CDVInvokedUrlCommand*)command
  643. {
  644. // arguments
  645. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  646. CDVPluginResult* result = nil;
  647. if ([localURI.fullPath isEqualToString:@""]) {
  648. // error if try to remove top level (documents or tmp) dir
  649. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
  650. } else {
  651. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  652. result = [fs recursiveRemoveFileAtURL:localURI];
  653. }
  654. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  655. }
  656. - (void)copyTo:(CDVInvokedUrlCommand*)command
  657. {
  658. [self doCopyMove:command isCopy:YES];
  659. }
  660. - (void)moveTo:(CDVInvokedUrlCommand*)command
  661. {
  662. [self doCopyMove:command isCopy:NO];
  663. }
  664. /* Copy/move a file or directory to a new location
  665. * IN:
  666. * NSArray* arguments
  667. * 0 - NSString* URL of entry to copy
  668. * 1 - NSString* URL of the directory into which to copy/move the entry
  669. * 2 - Optionally, the new name of the entry, defaults to the current name
  670. * BOOL - bCopy YES if copy, NO if move
  671. */
  672. - (void)doCopyMove:(CDVInvokedUrlCommand*)command isCopy:(BOOL)bCopy
  673. {
  674. NSArray* arguments = command.arguments;
  675. // arguments
  676. NSString* srcURLstr = [command argumentAtIndex:0];
  677. NSString* destURLstr = [command argumentAtIndex:1];
  678. CDVPluginResult *result;
  679. if (!srcURLstr || !destURLstr) {
  680. // either no source or no destination provided
  681. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
  682. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  683. return;
  684. }
  685. CDVFilesystemURL* srcURL = [self fileSystemURLforArg:srcURLstr];
  686. CDVFilesystemURL* destURL = [self fileSystemURLforArg:destURLstr];
  687. NSObject<CDVFileSystem> *srcFs = [self filesystemForURL:srcURL];
  688. NSObject<CDVFileSystem> *destFs = [self filesystemForURL:destURL];
  689. // optional argument; use last component from srcFullPath if new name not provided
  690. NSString* newName = ([arguments count] > 2) ? [command argumentAtIndex:2] : [srcURL.url lastPathComponent];
  691. if ([newName rangeOfString:@":"].location != NSNotFound) {
  692. // invalid chars in new name
  693. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
  694. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  695. return;
  696. }
  697. __weak CDVFile* weakSelf = self;
  698. [destFs copyFileToURL:destURL withName:newName fromFileSystem:srcFs atURL:srcURL copy:bCopy callback:^(CDVPluginResult* result) {
  699. [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  700. }];
  701. }
  702. - (void)getFileMetadata:(CDVInvokedUrlCommand*)command
  703. {
  704. // arguments
  705. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  706. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  707. __weak CDVFile* weakSelf = self;
  708. [fs getFileMetadataForURL:localURI callback:^(CDVPluginResult* result) {
  709. [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  710. }];
  711. }
  712. - (void)readEntries:(CDVInvokedUrlCommand*)command
  713. {
  714. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  715. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  716. CDVPluginResult *result = [fs readEntriesAtURL:localURI];
  717. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  718. }
  719. /* read and return file data
  720. * IN:
  721. * NSArray* arguments
  722. * 0 - NSString* fullPath
  723. * 1 - NSString* encoding
  724. * 2 - NSString* start
  725. * 3 - NSString* end
  726. */
  727. - (void)readAsText:(CDVInvokedUrlCommand*)command
  728. {
  729. // arguments
  730. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  731. NSString* encoding = [command argumentAtIndex:1];
  732. NSInteger start = [[command argumentAtIndex:2] integerValue];
  733. NSInteger end = [[command argumentAtIndex:3] integerValue];
  734. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  735. if (fs == nil) {
  736. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR];
  737. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  738. return;
  739. }
  740. // TODO: implement
  741. if ([@"UTF-8" caseInsensitiveCompare : encoding] != NSOrderedSame) {
  742. NSLog(@"Only UTF-8 encodings are currently supported by readAsText");
  743. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:ENCODING_ERR];
  744. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  745. return;
  746. }
  747. __weak CDVFile* weakSelf = self;
  748. [self.commandDelegate runInBackground:^ {
  749. [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
  750. CDVPluginResult* result = nil;
  751. if (data != nil) {
  752. NSString* str = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSUTF8StringEncoding freeWhenDone:NO];
  753. // Check that UTF8 conversion did not fail.
  754. if (str != nil) {
  755. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:str];
  756. result.associatedObject = data;
  757. } else {
  758. errorCode = ENCODING_ERR;
  759. }
  760. }
  761. if (result == nil) {
  762. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
  763. }
  764. [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  765. }];
  766. }];
  767. }
  768. /* Read content of text file and return as base64 encoded data url.
  769. * IN:
  770. * NSArray* arguments
  771. * 0 - NSString* fullPath
  772. * 1 - NSString* start
  773. * 2 - NSString* end
  774. *
  775. * Determines the mime type from the file extension, returns ENCODING_ERR if mimetype can not be determined.
  776. */
  777. - (void)readAsDataURL:(CDVInvokedUrlCommand*)command
  778. {
  779. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  780. NSInteger start = [[command argumentAtIndex:1] integerValue];
  781. NSInteger end = [[command argumentAtIndex:2] integerValue];
  782. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  783. __weak CDVFile* weakSelf = self;
  784. [self.commandDelegate runInBackground:^ {
  785. [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
  786. CDVPluginResult* result = nil;
  787. if (data != nil) {
  788. NSString* b64Str = toBase64(data);
  789. NSString* output = [NSString stringWithFormat:@"data:%@;base64,%@", mimeType, b64Str];
  790. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:output];
  791. } else {
  792. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
  793. }
  794. [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  795. }];
  796. }];
  797. }
  798. /* Read content of text file and return as an arraybuffer
  799. * IN:
  800. * NSArray* arguments
  801. * 0 - NSString* fullPath
  802. * 1 - NSString* start
  803. * 2 - NSString* end
  804. */
  805. - (void)readAsArrayBuffer:(CDVInvokedUrlCommand*)command
  806. {
  807. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  808. NSInteger start = [[command argumentAtIndex:1] integerValue];
  809. NSInteger end = [[command argumentAtIndex:2] integerValue];
  810. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  811. __weak CDVFile* weakSelf = self;
  812. [self.commandDelegate runInBackground:^ {
  813. [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
  814. CDVPluginResult* result = nil;
  815. if (data != nil) {
  816. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArrayBuffer:data];
  817. } else {
  818. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
  819. }
  820. [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  821. }];
  822. }];
  823. }
  824. - (void)readAsBinaryString:(CDVInvokedUrlCommand*)command
  825. {
  826. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  827. NSInteger start = [[command argumentAtIndex:1] integerValue];
  828. NSInteger end = [[command argumentAtIndex:2] integerValue];
  829. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  830. __weak CDVFile* weakSelf = self;
  831. [self.commandDelegate runInBackground:^ {
  832. [fs readFileAtURL:localURI start:start end:end callback:^(NSData* data, NSString* mimeType, CDVFileError errorCode) {
  833. CDVPluginResult* result = nil;
  834. if (data != nil) {
  835. NSString* payload = [[NSString alloc] initWithBytesNoCopy:(void*)[data bytes] length:[data length] encoding:NSASCIIStringEncoding freeWhenDone:NO];
  836. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:payload];
  837. result.associatedObject = data;
  838. } else {
  839. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:errorCode];
  840. }
  841. [weakSelf.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  842. }];
  843. }];
  844. }
  845. - (void)truncate:(CDVInvokedUrlCommand*)command
  846. {
  847. // arguments
  848. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  849. unsigned long long pos = (unsigned long long)[[command argumentAtIndex:1] longLongValue];
  850. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  851. CDVPluginResult *result = [fs truncateFileAtURL:localURI atPosition:pos];
  852. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  853. }
  854. /* write
  855. * IN:
  856. * NSArray* arguments
  857. * 0 - NSString* localURI of file to write to
  858. * 1 - NSString* or NSData* data to write
  859. * 2 - NSNumber* position to begin writing
  860. */
  861. - (void)write:(CDVInvokedUrlCommand*)command
  862. {
  863. __weak CDVFile* weakSelf = self;
  864. [self.commandDelegate runInBackground:^ {
  865. NSString* callbackId = command.callbackId;
  866. // arguments
  867. CDVFilesystemURL* localURI = [self fileSystemURLforArg:command.arguments[0]];
  868. id argData = [command argumentAtIndex:1];
  869. unsigned long long pos = (unsigned long long)[[command argumentAtIndex:2] longLongValue];
  870. NSObject<CDVFileSystem> *fs = [self filesystemForURL:localURI];
  871. [fs truncateFileAtURL:localURI atPosition:pos];
  872. CDVPluginResult *result;
  873. if ([argData isKindOfClass:[NSString class]]) {
  874. NSData *encData = [argData dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES];
  875. result = [fs writeToFileAtURL:localURI withData:encData append:YES];
  876. } else if ([argData isKindOfClass:[NSData class]]) {
  877. result = [fs writeToFileAtURL:localURI withData:argData append:YES];
  878. } else {
  879. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Invalid parameter type"];
  880. }
  881. [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
  882. }];
  883. }
  884. #pragma mark Methods for converting between URLs and paths
  885. - (NSString *)filesystemPathForURL:(CDVFilesystemURL *)localURL
  886. {
  887. for (NSObject<CDVFileSystem> *fs in self.fileSystems) {
  888. if ([fs.name isEqualToString:localURL.fileSystemName]) {
  889. if ([fs respondsToSelector:@selector(filesystemPathForURL:)]) {
  890. return [fs filesystemPathForURL:localURL];
  891. }
  892. }
  893. }
  894. return nil;
  895. }
  896. #pragma mark Undocumented Filesystem API
  897. - (void)testFileExists:(CDVInvokedUrlCommand*)command
  898. {
  899. // arguments
  900. NSString* argPath = [command argumentAtIndex:0];
  901. // Get the file manager
  902. NSFileManager* fMgr = [NSFileManager defaultManager];
  903. NSString* appFile = argPath; // [ self getFullPath: argPath];
  904. BOOL bExists = [fMgr fileExistsAtPath:appFile];
  905. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:(bExists ? 1 : 0)];
  906. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  907. }
  908. - (void)testDirectoryExists:(CDVInvokedUrlCommand*)command
  909. {
  910. // arguments
  911. NSString* argPath = [command argumentAtIndex:0];
  912. // Get the file manager
  913. NSFileManager* fMgr = [[NSFileManager alloc] init];
  914. NSString* appFile = argPath; // [self getFullPath: argPath];
  915. BOOL bIsDir = NO;
  916. BOOL bExists = [fMgr fileExistsAtPath:appFile isDirectory:&bIsDir];
  917. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:((bExists && bIsDir) ? 1 : 0)];
  918. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  919. }
  920. // Returns number of bytes available via callback
  921. - (void)getFreeDiskSpace:(CDVInvokedUrlCommand*)command
  922. {
  923. // no arguments
  924. NSNumber* pNumAvail = [self checkFreeDiskSpace:self.rootDocsPath];
  925. NSString* strFreeSpace = [NSString stringWithFormat:@"%qu", [pNumAvail unsignedLongLongValue]];
  926. // NSLog(@"Free space is %@", strFreeSpace );
  927. CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:strFreeSpace];
  928. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  929. }
  930. #pragma mark Compatibility with older File API
  931. - (NSString*)getMimeTypeFromPath:(NSString*)fullPath
  932. {
  933. return [CDVLocalFilesystem getMimeTypeFromPath:fullPath];
  934. }
  935. - (NSDictionary *)getDirectoryEntry:(NSString *)localPath isDirectory:(BOOL)bDirRequest
  936. {
  937. CDVFilesystemURL *localURL = [self fileSystemURLforLocalPath:localPath];
  938. return [self makeEntryForPath:localURL.fullPath fileSystemName:localURL.fileSystemName isDirectory:bDirRequest];
  939. }
  940. #pragma mark Internal methods for testing
  941. // Internal methods for testing: Get the on-disk location of a local filesystem url.
  942. // [Currently used for testing file-transfer]
  943. - (void)_getLocalFilesystemPath:(CDVInvokedUrlCommand*)command
  944. {
  945. CDVFilesystemURL* localURL = [self fileSystemURLforArg:command.arguments[0]];
  946. NSString* fsPath = [self filesystemPathForURL:localURL];
  947. CDVPluginResult* result;
  948. if (fsPath) {
  949. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:fsPath];
  950. } else {
  951. result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot resolve URL to a file"];
  952. }
  953. [self.commandDelegate sendPluginResult:result callbackId:command.callbackId];
  954. }
  955. @end