FIRStorageUtils.m 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  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 || TARGET_OS_WATCH
  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. #if SWIFT_PACKAGE
  25. @import GTMSessionFetcherCore;
  26. #else
  27. #import <GTMSessionFetcher/GTMSessionFetcher.h>
  28. #endif
  29. // This is the list at https://cloud.google.com/storage/docs/json_api/ without &, ; and +.
  30. NSString *const kGCSObjectAllowedCharacterSet =
  31. @"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$'()*,=:@";
  32. @implementation FIRStorageUtils
  33. + (nullable NSString *)GCSEscapedString:(NSString *)string {
  34. NSCharacterSet *allowedCharacters =
  35. [NSCharacterSet characterSetWithCharactersInString:kGCSObjectAllowedCharacterSet];
  36. return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
  37. }
  38. + (nullable NSString *)MIMETypeForExtension:(NSString *)extension {
  39. if (extension == nil) {
  40. return nil;
  41. }
  42. CFStringRef pathExtension = (__bridge_retained CFStringRef)extension;
  43. CFStringRef type =
  44. UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension, NULL);
  45. NSString *mimeType =
  46. (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass(type, kUTTagClassMIMEType);
  47. CFRelease(pathExtension);
  48. if (type != NULL) {
  49. CFRelease(type);
  50. }
  51. return mimeType;
  52. }
  53. + (NSString *)queryStringForDictionary:(nullable NSDictionary *)dictionary {
  54. if (!dictionary) {
  55. return @"";
  56. }
  57. __block NSMutableArray *queryItems = [[NSMutableArray alloc] initWithCapacity:[dictionary count]];
  58. [dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *_Nonnull name, NSString *_Nonnull value,
  59. BOOL *_Nonnull stop) {
  60. NSString *item =
  61. [FIRStorageUtils GCSEscapedString:[NSString stringWithFormat:@"%@=%@", name, value]];
  62. [queryItems addObject:item];
  63. }];
  64. return [queryItems componentsJoinedByString:@"&"];
  65. }
  66. + (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path {
  67. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  68. NSURLComponents *components = [[NSURLComponents alloc] init];
  69. [components setScheme:kFIRStorageScheme];
  70. [components setHost:kFIRStorageHost];
  71. NSString *encodedPath = [self encodedURLForPath:path];
  72. [components setPercentEncodedPath:encodedPath];
  73. [request setURL:components.URL];
  74. return request;
  75. }
  76. + (NSURLRequest *)defaultRequestForPath:(FIRStoragePath *)path
  77. queryParams:(NSDictionary<NSString *, NSString *> *)queryParams {
  78. NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
  79. NSURLComponents *components = [[NSURLComponents alloc] init];
  80. [components setScheme:kFIRStorageScheme];
  81. [components setHost:kFIRStorageHost];
  82. NSMutableArray<NSURLQueryItem *> *queryItems = [NSMutableArray new];
  83. for (NSString *key in queryParams) {
  84. [queryItems addObject:[NSURLQueryItem queryItemWithName:key value:queryParams[key]]];
  85. }
  86. [components setQueryItems:queryItems];
  87. NSString *encodedPath = [self encodedURLForPath:path];
  88. [components setPercentEncodedPath:encodedPath];
  89. [request setURL:components.URL];
  90. return request;
  91. }
  92. + (NSString *)encodedURLForPath:(FIRStoragePath *)path {
  93. NSString *bucketName = [FIRStorageUtils GCSEscapedString:path.bucket];
  94. NSString *objectName = [FIRStorageUtils GCSEscapedString:path.object];
  95. NSString *bucketFormat = [NSString stringWithFormat:kFIRStorageBucketPathFormat, bucketName];
  96. NSString *urlPath = [@"/" stringByAppendingPathComponent:bucketFormat];
  97. if (objectName) {
  98. NSString *objectFormat = [NSString stringWithFormat:kFIRStorageObjectPathFormat, objectName];
  99. urlPath = [urlPath stringByAppendingFormat:@"/%@", objectFormat];
  100. } else {
  101. urlPath = [urlPath stringByAppendingString:@"/o"];
  102. }
  103. return [@"/" stringByAppendingString:[kFIRStorageVersionPath stringByAppendingString:urlPath]];
  104. }
  105. + (NSError *)storageErrorWithDescription:(NSString *)description code:(NSInteger)code {
  106. return [NSError errorWithDomain:FIRStorageErrorDomain
  107. code:code
  108. userInfo:@{NSLocalizedDescriptionKey : description}];
  109. }
  110. @end
  111. @implementation NSDictionary (FIRStorageNSDictionaryJSONHelpers)
  112. + (nullable instancetype)frs_dictionaryFromJSONData:(nullable NSData *)data {
  113. if (!data) {
  114. return nil;
  115. }
  116. return [NSJSONSerialization JSONObjectWithData:data
  117. options:NSJSONReadingMutableContainers
  118. error:nil];
  119. }
  120. @end
  121. @implementation NSData (FIRStorageNSDataJSONHelpers)
  122. + (nullable instancetype)frs_dataFromJSONDictionary:(nullable NSDictionary *)dictionary {
  123. if (!dictionary) {
  124. return nil;
  125. }
  126. return [NSJSONSerialization dataWithJSONObject:dictionary options:0 error:nil];
  127. }
  128. @end