arnaucube
arnaucube/openEventsPlatformAppPublic Self-hosted repository
openEventsPlatformApp/plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.m
plugins/cordova-plugin-file/src/ios/CDVAssetLibraryFilesystem.mRaw
  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
 10 http://www.apache.org/licenses/LICENSE-2.0
 11
 12 Unless required by applicable law or agreed to in writing,
 13 software distributed under the License is distributed on an
 14 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 15 KIND, either express or implied.  See the License for the
 16 specific language governing permissions and limitations
 17 under the License.
 18 */
 19
 20#import "CDVFile.h"
 21#import "CDVAssetLibraryFilesystem.h"
 22#import <Cordova/CDV.h>
 23#import <AssetsLibrary/ALAsset.h>
 24#import <AssetsLibrary/ALAssetRepresentation.h>
 25#import <AssetsLibrary/ALAssetsLibrary.h>
 26#import <MobileCoreServices/MobileCoreServices.h>
 27
 28NSString* const kCDVAssetsLibraryPrefix = @"assets-library://";
 29NSString* const kCDVAssetsLibraryScheme = @"assets-library";
 30
 31@implementation CDVAssetLibraryFilesystem
 32@synthesize name=_name, urlTransformer;
 33
 34
 35/*
 36 The CDVAssetLibraryFilesystem works with resources which are identified
 37 by iOS as
 38   asset-library://<path>
 39 and represents them internally as URLs of the form
 40   cdvfile://localhost/assets-library/<path>
 41 */
 42
 43- (NSURL *)assetLibraryURLForLocalURL:(CDVFilesystemURL *)url
 44{
 45    if ([url.url.scheme isEqualToString:kCDVFilesystemURLPrefix]) {
 46        NSString *path = [[url.url absoluteString] substringFromIndex:[@"cdvfile://localhost/assets-library" length]];
 47        return [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@", path]];
 48    }
 49    return url.url;
 50}
 51
 52- (CDVPluginResult *)entryForLocalURI:(CDVFilesystemURL *)url
 53{
 54    NSDictionary* entry = [self makeEntryForLocalURL:url];
 55    return [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:entry];
 56}
 57
 58- (NSDictionary *)makeEntryForLocalURL:(CDVFilesystemURL *)url {
 59    return [self makeEntryForPath:url.fullPath isDirectory:NO];
 60}
 61
 62- (NSDictionary*)makeEntryForPath:(NSString*)fullPath isDirectory:(BOOL)isDir
 63{
 64    NSMutableDictionary* dirEntry = [NSMutableDictionary dictionaryWithCapacity:5];
 65    NSString* lastPart = [fullPath lastPathComponent];
 66    if (isDir && ![fullPath hasSuffix:@"/"]) {
 67        fullPath = [fullPath stringByAppendingString:@"/"];
 68    }
 69    [dirEntry setObject:[NSNumber numberWithBool:!isDir]  forKey:@"isFile"];
 70    [dirEntry setObject:[NSNumber numberWithBool:isDir]  forKey:@"isDirectory"];
 71    [dirEntry setObject:fullPath forKey:@"fullPath"];
 72    [dirEntry setObject:lastPart forKey:@"name"];
 73    [dirEntry setObject:self.name forKey: @"filesystemName"];
 74
 75    NSURL* nativeURL = [NSURL URLWithString:[NSString stringWithFormat:@"assets-library:/%@",fullPath]];
 76    if (self.urlTransformer) {
 77        nativeURL = self.urlTransformer(nativeURL);
 78    }
 79    dirEntry[@"nativeURL"] = [nativeURL absoluteString];
 80
 81    return dirEntry;
 82}
 83
 84/* helper function to get the mimeType from the file extension
 85 * IN:
 86 *	NSString* fullPath - filename (may include path)
 87 * OUT:
 88 *	NSString* the mime type as type/subtype.  nil if not able to determine
 89 */
 90+ (NSString*)getMimeTypeFromPath:(NSString*)fullPath
 91{
 92    NSString* mimeType = nil;
 93
 94    if (fullPath) {
 95        CFStringRef typeId = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fullPath pathExtension], NULL);
 96        if (typeId) {
 97            mimeType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass(typeId, kUTTagClassMIMEType);
 98            if (!mimeType) {
 99                // special case for m4a
100                if ([(__bridge NSString*)typeId rangeOfString : @"m4a-audio"].location != NSNotFound) {
101                    mimeType = @"audio/mp4";
102                } else if ([[fullPath pathExtension] rangeOfString:@"wav"].location != NSNotFound) {
103                    mimeType = @"audio/wav";
104                } else if ([[fullPath pathExtension] rangeOfString:@"css"].location != NSNotFound) {
105                    mimeType = @"text/css";
106                }
107            }
108            CFRelease(typeId);
109        }
110    }
111    return mimeType;
112}
113
114- (id)initWithName:(NSString *)name
115{
116    if (self) {
117        self.name = name;
118    }
119    return self;
120}
121
122- (CDVPluginResult *)getFileForURL:(CDVFilesystemURL *)baseURI requestedPath:(NSString *)requestedPath options:(NSDictionary *)options
123{
124    // return unsupported result for assets-library URLs
125   return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"getFile not supported for assets-library URLs."];
126}
127
128- (CDVPluginResult*)getParentForURL:(CDVFilesystemURL *)localURI
129{
130    // we don't (yet?) support getting the parent of an asset
131    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_READABLE_ERR];
132}
133
134- (CDVPluginResult*)setMetadataForURL:(CDVFilesystemURL *)localURI withObject:(NSDictionary *)options
135{
136    // setMetadata doesn't make sense for asset library files
137    return [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR];
138}
139
140- (CDVPluginResult *)removeFileAtURL:(CDVFilesystemURL *)localURI
141{
142    // return error for assets-library URLs
143    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
144}
145
146- (CDVPluginResult *)recursiveRemoveFileAtURL:(CDVFilesystemURL *)localURI
147{
148    // return error for assets-library URLs
149    return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"removeRecursively not supported for assets-library URLs."];
150}
151
152- (CDVPluginResult *)readEntriesAtURL:(CDVFilesystemURL *)localURI
153{
154    // return unsupported result for assets-library URLs
155    return [CDVPluginResult resultWithStatus:CDVCommandStatus_MALFORMED_URL_EXCEPTION messageAsString:@"readEntries not supported for assets-library URLs."];
156}
157
158- (CDVPluginResult *)truncateFileAtURL:(CDVFilesystemURL *)localURI atPosition:(unsigned long long)pos
159{
160    // assets-library files can't be truncated
161    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
162}
163
164- (CDVPluginResult *)writeToFileAtURL:(CDVFilesystemURL *)localURL withData:(NSData*)encData append:(BOOL)shouldAppend
165{
166    // text can't be written into assets-library files
167    return [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NO_MODIFICATION_ALLOWED_ERR];
168}
169
170- (void)copyFileToURL:(CDVFilesystemURL *)destURL withName:(NSString *)newName fromFileSystem:(NSObject<CDVFileSystem> *)srcFs atURL:(CDVFilesystemURL *)srcURL copy:(BOOL)bCopy callback:(void (^)(CDVPluginResult *))callback
171{
172    // Copying to an assets library file is not doable, since we can't write it.
173    CDVPluginResult *result = [CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:INVALID_MODIFICATION_ERR];
174    callback(result);
175}
176
177- (NSString *)filesystemPathForURL:(CDVFilesystemURL *)url
178{
179    NSString *path = nil;
180    if ([[url.url scheme] isEqualToString:kCDVAssetsLibraryScheme]) {
181        path = [url.url path];
182    } else {
183       path = url.fullPath;
184    }
185    if ([path hasSuffix:@"/"]) {
186      path = [path substringToIndex:([path length]-1)];
187    }
188    return path;
189}
190
191- (void)readFileAtURL:(CDVFilesystemURL *)localURL start:(NSInteger)start end:(NSInteger)end callback:(void (^)(NSData*, NSString* mimeType, CDVFileError))callback
192{
193    ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
194        if (asset) {
195            // We have the asset!  Get the data and send it off.
196            ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
197            NSUInteger size = (end > start) ? (end - start) : [assetRepresentation size];
198            Byte* buffer = (Byte*)malloc(size);
199            NSUInteger bufferSize = [assetRepresentation getBytes:buffer fromOffset:start length:size error:nil];
200            NSData* data = [NSData dataWithBytesNoCopy:buffer length:bufferSize freeWhenDone:YES];
201            NSString* MIMEType = (__bridge_transfer NSString*)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)[assetRepresentation UTI], kUTTagClassMIMEType);
202
203            callback(data, MIMEType, NO_ERROR);
204        } else {
205            callback(nil, nil, NOT_FOUND_ERR);
206        }
207    };
208
209    ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
210        // Retrieving the asset failed for some reason.  Send the appropriate error.
211        NSLog(@"Error: %@", error);
212        callback(nil, nil, SECURITY_ERR);
213    };
214
215    ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
216    [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
217}
218
219- (void)getFileMetadataForURL:(CDVFilesystemURL *)localURL callback:(void (^)(CDVPluginResult *))callback
220{
221    // In this case, we need to use an asynchronous method to retrieve the file.
222    // Because of this, we can't just assign to `result` and send it at the end of the method.
223    // Instead, we return after calling the asynchronous method and send `result` in each of the blocks.
224    ALAssetsLibraryAssetForURLResultBlock resultBlock = ^(ALAsset* asset) {
225        if (asset) {
226            // We have the asset!  Populate the dictionary and send it off.
227            NSMutableDictionary* fileInfo = [NSMutableDictionary dictionaryWithCapacity:5];
228            ALAssetRepresentation* assetRepresentation = [asset defaultRepresentation];
229            [fileInfo setObject:[NSNumber numberWithUnsignedLongLong:[assetRepresentation size]] forKey:@"size"];
230            [fileInfo setObject:localURL.fullPath forKey:@"fullPath"];
231            NSString* filename = [assetRepresentation filename];
232            [fileInfo setObject:filename forKey:@"name"];
233            [fileInfo setObject:[CDVAssetLibraryFilesystem getMimeTypeFromPath:filename] forKey:@"type"];
234            NSDate* creationDate = [asset valueForProperty:ALAssetPropertyDate];
235            NSNumber* msDate = [NSNumber numberWithDouble:[creationDate timeIntervalSince1970] * 1000];
236            [fileInfo setObject:msDate forKey:@"lastModifiedDate"];
237
238            callback([CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:fileInfo]);
239        } else {
240            // We couldn't find the asset.  Send the appropriate error.
241            callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsInt:NOT_FOUND_ERR]);
242        }
243    };
244    ALAssetsLibraryAccessFailureBlock failureBlock = ^(NSError* error) {
245        // Retrieving the asset failed for some reason.  Send the appropriate error.
246        callback([CDVPluginResult resultWithStatus:CDVCommandStatus_IO_EXCEPTION messageAsString:[error localizedDescription]]);
247    };
248
249    ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
250    [assetsLibrary assetForURL:[self assetLibraryURLForLocalURL:localURL] resultBlock:resultBlock failureBlock:failureBlock];
251    return;
252}
253@end