FIRStorageUtils.m 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright 2017 Google
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #import <Foundation/Foundation.h>
  15. #if TARGET_OS_IOS || TARGET_OS_TV
  16. #import <MobileCoreServices/MobileCoreServices.h>
  17. #elif TARGET_OS_OSX
  18. #import <CoreServices/CoreServices.h>
  19. #endif
  20. #import "FirebaseStorage/Sources/FIRStorageUtils.h"
  21. #import "FirebaseStorage/Sources/FIRStorageConstants_Private.h"
  22. #import "FirebaseStorage/Sources/FIRStorageErrors.h"
  23. #import "FirebaseStorage/Sources/FIRStoragePath.h"
  24. #import <GTMSessionFetcher/GTMSessionFetcher.h>
  25. // This is the list at https://cloud.google.com/storage/docs/json_api/ without &, ; and +.
  26. NSString *const kGCSObjectAllowedCharacterSet =
  27. @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*,=:@";
  28. @implementation FIRStorageUtils
  29. + (nullable NSString *)GCSEscapedString:(NSString *)string {
  30. NSCharacterSet *allowedCharacters =
  31. [NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet];
  32. return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
  33. }
  34. + (nullable NSString *)MIMETypeForExtension:(NSString *)extension {
  35. if (extension == nil) {
  36. return nil;
  37. }
  38. CFStringRef pathExtension = (__bridge_retained CFStringRef)extension;
  39. CFStringRef type =
  40. UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL);
  41. NSString *mimeType =
  42. (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType);
  43. CFRelease(pathExtension);
  44. if (type != NULL) {
  45. CFRelease(type);
  46. }
  47. return mimeType;
  48. }
  49. + (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary {
  50. if (!dictionary) {
  51. return @"";
  52. }
  53. __block NSMutableArray *queryItems = [[NSMutableArray alloc] initWithCapacity:[dictionary count]];
  54. [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull name, NSString *_Nonnull value,
  55. BOOL *_Nonnull stop) {
  56. NSString *item =
  57. [FIRStorageUtils GCSEscapedString:[NSString stringWithFormat:@"%@=%@", name, value]];
  58. [queryItems addObject:item];
  59. }];
  60. return [queryItems componentsJoinedByString:@"&"];
  61. }
  62. + (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path {
  63. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  64. NSURLComponents *components = [[NSURLComponents alloc] init];
  65. [components setScheme:kFIRStorageScheme];
  66. [components setHost:kFIRStorageHost];
  67. NSString *encodedPath = [self encodedURLForPath:path];
  68. [components setPercentEncodedPath:encodedPath];
  69. [request setURL:components.URL];
  70. return request;
  71. }
  72. + (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path
  73. queryParams:(NSDictionary<NSString *, NSString *> *)queryParams {
  74. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  75. NSURLComponents *components = [[NSURLComponents alloc] init];
  76. [components setScheme:kFIRStorageScheme];
  77. [components setHost:kFIRStorageHost];
  78. NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray new];
  79. for (NSString *key in queryParams) {
  80. [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryParams[key]]];
  81. }
  82. [components setQueryItems:queryItems];
  83. NSString *encodedPath = [self encodedURLForPath:path];
  84. [components setPercentEncodedPath:encodedPath];
  85. [request setURL:components.URL];
  86. return request;
  87. }
  88. + (NSString *)encodedURLForPath:(FIRStoragePath *)path {
  89. NSString *bucketName = [FIRStorageUtils GCSEscapedString:path.bucket];
  90. NSString *objectName = [FIRStorageUtils GCSEscapedString:path.object];
  91. NSString *bucketFormat = [NSString stringWithFormat:kFIRStorageBucketPathFormat, bucketName];
  92. NSString *urlPath = [@"/" stringByAppendingPathComponent:bucketFormat];
  93. if (objectName) {
  94. NSString *objectFormat = [NSString stringWithFormat:kFIRStorageObjectPathFormat, objectName];
  95. urlPath = [urlPath stringByAppendingFormat:@"/%@", objectFormat];
  96. } else {
  97. urlPath = [urlPath stringByAppendingString:@"/o"];
  98. }
  99. return [@"/" stringByAppendingString:[kFIRStorageVersionPath stringByAppendingString:urlPath]];
  100. }
  101. + (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code {
  102. return [NSError errorWithDomain:FIRStorageErrorDomain
  103. code:code
  104. userInfo:@{NSLocalizedDescriptionKey : description}];
  105. }
  106. @end
  107. @implementation NSDictionary (FIRStorageNSDictionaryJSONHelpers)
  108. + (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data {
  109. if (!data) {
  110. return nil;
  111. }
  112. return [NSJSONSerialization JSONObjectWithData:data
  113. options:NSJSONReadingMutableContainers
  114. error:nil];
  115. }
  116. @end
  117. @implementation NSData (FIRStorageNSDataJSONHelpers)
  118. + (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary {
  119. if (!dictionary) {
  120. return nil;
  121. }
  122. return [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
  123. }
  124. @end