aboutsummaryrefslogtreecommitdiffhomepage
path: root/Firebase/Storage/FIRStorageMetadata.m
diff options
context:
space:
mode:
Diffstat (limited to 'Firebase/Storage/FIRStorageMetadata.m')
-rw-r--r--Firebase/Storage/FIRStorageMetadata.m227
1 files changed, 227 insertions, 0 deletions
diff --git a/Firebase/Storage/FIRStorageMetadata.m b/Firebase/Storage/FIRStorageMetadata.m
new file mode 100644
index 0000000..6c85bbf
--- /dev/null
+++ b/Firebase/Storage/FIRStorageMetadata.m
@@ -0,0 +1,227 @@
+// Copyright 2017 Google
+//
+// 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.
+
+#import "FIRStorageMetadata.h"
+
+#import "FIRStorageConstants.h"
+#import "FIRStorageConstants_Private.h"
+#import "FIRStorageMetadata_Private.h"
+#import "FIRStorageUtils.h"
+
+// TODO: consider rewriting this using GTLR (GTLRStorageObjects.h)
+@implementation FIRStorageMetadata
+
+#pragma mark - Initializers
+
+- (instancetype)init {
+ return [self initWithDictionary:[NSDictionary dictionary]];
+}
+
+- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
+ self = [super init];
+ if (self) {
+ _bucket = dictionary[kFIRStorageMetadataBucket];
+ _cacheControl = dictionary[kFIRStorageMetadataCacheControl];
+ _contentDisposition = dictionary[kFIRStorageMetadataContentDisposition];
+ _contentEncoding = dictionary[kFIRStorageMetadataContentEncoding];
+ _contentLanguage = dictionary[kFIRStorageMetadataContentLanguage];
+ _contentType = dictionary[kFIRStorageMetadataContentType];
+ _customMetadata = dictionary[kFIRStorageMetadataCustomMetadata];
+ _size = [dictionary[kFIRStorageMetadataSize] longLongValue];
+ _downloadURLs = dictionary[kFIRStorageMetadataDownloadURLs];
+ _generation = [dictionary[kFIRStorageMetadataGeneration] longLongValue];
+ _metageneration = [dictionary[kFIRStorageMetadataMetageneration] longLongValue];
+ _timeCreated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataTimeCreated]];
+ _updated = [self dateFromRFC3339String:dictionary[kFIRStorageMetadataUpdated]];
+ // GCS "name" is our path, our "name" is just the last path component of the path
+ _path = dictionary[kFIRStorageMetadataName];
+ _name = [_path lastPathComponent];
+ NSString *downloadTokens = dictionary[kFIRStorageMetadataDownloadTokens];
+ if (downloadTokens) {
+ NSArray<NSString *> *downloadStringArray = [downloadTokens componentsSeparatedByString:@","];
+ NSMutableArray<NSURL *> *downloadURLArray =
+ [[NSMutableArray alloc] initWithCapacity:[downloadStringArray count]];
+ [downloadStringArray enumerateObjectsUsingBlock:^(NSString *_Nonnull token, NSUInteger idx,
+ BOOL *_Nonnull stop) {
+ NSURLComponents *components = [[NSURLComponents alloc] init];
+ components.scheme = kFIRStorageScheme;
+ components.host = kFIRStorageHost;
+ NSString *path = [FIRStorageUtils GCSEscapedString:_path];
+ NSString *fullPath = [NSString stringWithFormat:kFIRStorageFullPathFormat, _bucket, path];
+ components.percentEncodedPath = fullPath;
+ components.query = [NSString stringWithFormat:@"alt=media&token=%@", token];
+
+ [downloadURLArray insertObject:[components URL] atIndex:idx];
+ }];
+ _downloadURLs = downloadURLArray;
+ }
+ }
+ return self;
+}
+
+#pragma mark - NSObject overrides
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[[self class] allocWithZone:zone] initWithDictionary:[self dictionaryRepresentation]];
+}
+
+- (BOOL)isEqual:(id)object {
+ if (self == object) {
+ return YES;
+ }
+
+ if (![object isKindOfClass:[FIRStorageMetadata class]]) {
+ return NO;
+ }
+
+ BOOL isEqualObject = [self isEqualToFIRStorageMetadata:(FIRStorageMetadata *)object];
+ return isEqualObject;
+}
+
+- (BOOL)isEqualToFIRStorageMetadata:(FIRStorageMetadata *)metadata {
+ return [[self dictionaryRepresentation] isEqualToDictionary:[metadata dictionaryRepresentation]];
+}
+
+- (NSUInteger)hash {
+ NSUInteger hash = [[self dictionaryRepresentation] hash];
+ return hash;
+}
+
+- (NSString *)description {
+ NSDictionary *metadataDictionary = [self dictionaryRepresentation];
+ return [NSString stringWithFormat:@"%@ %p: %@", [self class], self, metadataDictionary];
+}
+
+#pragma mark - Public methods
+
+- (NSDictionary *)dictionaryRepresentation {
+ NSMutableDictionary *metadataDictionary = [[NSMutableDictionary alloc] initWithCapacity:13];
+
+ if (_bucket) {
+ metadataDictionary[kFIRStorageMetadataBucket] = _bucket;
+ }
+
+ if (_cacheControl) {
+ metadataDictionary[kFIRStorageMetadataCacheControl] = _cacheControl;
+ }
+
+ if (_contentDisposition) {
+ metadataDictionary[kFIRStorageMetadataContentDisposition] = _contentDisposition;
+ }
+
+ if (_contentEncoding) {
+ metadataDictionary[kFIRStorageMetadataContentEncoding] = _contentEncoding;
+ }
+
+ if (_contentLanguage) {
+ metadataDictionary[kFIRStorageMetadataContentLanguage] = _contentLanguage;
+ }
+
+ if (_contentType) {
+ metadataDictionary[kFIRStorageMetadataContentType] = _contentType;
+ }
+
+ if (_customMetadata) {
+ metadataDictionary[kFIRStorageMetadataCustomMetadata] = _customMetadata;
+ }
+
+ if (_downloadURLs) {
+ NSMutableArray *downloadTokens = [[NSMutableArray alloc] init];
+ [_downloadURLs
+ enumerateObjectsUsingBlock:^(NSURL *_Nonnull URL, NSUInteger idx, BOOL *_Nonnull stop) {
+ NSArray *queryItems = [URL.query componentsSeparatedByString:@"&"];
+ [queryItems enumerateObjectsUsingBlock:^(NSString *queryString, NSUInteger idx,
+ BOOL *_Nonnull stop) {
+ NSString *key;
+ NSString *value;
+ NSScanner *scanner = [NSScanner scannerWithString:queryString];
+ [scanner scanUpToString:@"=" intoString:&key];
+ [scanner scanString:@"=" intoString:NULL];
+ [scanner scanUpToString:@"\n" intoString:&value];
+ if ([key isEqual:@"token"]) {
+ [downloadTokens addObject:value];
+ *stop = YES;
+ }
+ }];
+ }];
+ NSString *downloadTokenString = [downloadTokens componentsJoinedByString:@","];
+ metadataDictionary[kFIRStorageMetadataDownloadTokens] = downloadTokenString;
+ }
+
+ if (_generation) {
+ NSString *generationString = [NSString stringWithFormat:@"%lld", _generation];
+ metadataDictionary[kFIRStorageMetadataGeneration] = generationString;
+ }
+
+ if (_metageneration) {
+ NSString *metagenerationString = [NSString stringWithFormat:@"%lld", _metageneration];
+ metadataDictionary[kFIRStorageMetadataMetageneration] = metagenerationString;
+ }
+
+ if (_timeCreated) {
+ metadataDictionary[kFIRStorageMetadataTimeCreated] = [self RFC3339StringFromDate:_timeCreated];
+ }
+
+ if (_updated) {
+ metadataDictionary[kFIRStorageMetadataUpdated] = [self RFC3339StringFromDate:_updated];
+ }
+
+ if (_path) {
+ metadataDictionary[kFIRStorageMetadataName] = _path;
+ }
+
+ return [metadataDictionary copy];
+}
+
+- (BOOL)isFile {
+ return _type == FIRStorageMetadataTypeFile;
+}
+
+- (BOOL)isFolder {
+ return _type == FIRStorageMetadataTypeFolder;
+}
+
+- (nullable NSURL *)downloadURL {
+ return [_downloadURLs firstObject];
+}
+
+#pragma mark - RFC 3339 conversions
+
+static NSDateFormatter *sRFC3339DateFormatter;
+
+static void setupDateFormatterOnce(void) {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ sRFC3339DateFormatter = [[NSDateFormatter alloc] init];
+ NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
+
+ [sRFC3339DateFormatter setLocale:enUSPOSIXLocale];
+ [sRFC3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss.SSSZZZZZ"];
+ [sRFC3339DateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0]];
+ });
+}
+
+- (nullable NSDate *)dateFromRFC3339String:(NSString *)dateString {
+ setupDateFormatterOnce();
+ NSDate *rfc3339Date = [sRFC3339DateFormatter dateFromString:dateString];
+ return rfc3339Date;
+}
+
+- (nullable NSString *)RFC3339StringFromDate:(NSDate *)date {
+ setupDateFormatterOnce();
+ NSString *rfc3339String = [sRFC3339DateFormatter stringFromDate:date];
+ return rfc3339String;
+}
+
+@end