소스 검색

协议调试完成

南鑫林 6 년 전
부모
커밋
b0164ff6b4
100개의 변경된 파일14240개의 추가작업 그리고 44개의 파일을 삭제
  1. BIN
      .DS_Store
  2. BIN
      RainbowPlanet/.DS_Store
  3. 3 3
      RainbowPlanet/Podfile
  4. 1 41
      RainbowPlanet/Podfile.lock
  5. BIN
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/AMapFoundationKit
  6. 18 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapFoundationKit.h
  7. 19 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapFoundationVersion.h
  8. 31 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapServices.h
  9. 41 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapURLSearch.h
  10. 79 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapURLSearchConfig.h
  11. 44 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapURLSearchType.h
  12. 50 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapUtility.h
  13. 15 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/NSMutableArray+AMapSafe.h
  14. 15 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/NSMutableDictionary+AMapSafe.h
  15. 48 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/NSObject+AMapJsonSerialization.h
  16. 6 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Modules/module.modulemap
  17. 1 0
      RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/version.txt
  18. BIN
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/AMapLocationKit
  19. 26 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapGeoFenceError.h
  20. 211 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapGeoFenceManager.h
  21. 120 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapGeoFenceRegionObj.h
  22. 194 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationCommonObj.h
  23. 17 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationKit.h
  24. 208 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationManager.h
  25. 90 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationRegionObj.h
  26. 26 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationVersion.h
  27. 6 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Modules/module.modulemap
  28. 1 0
      RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/version.txt
  29. 19 0
      RainbowPlanet/Pods/Alamofire/LICENSE
  30. 243 0
      RainbowPlanet/Pods/Alamofire/README.md
  31. 460 0
      RainbowPlanet/Pods/Alamofire/Source/AFError.swift
  32. 465 0
      RainbowPlanet/Pods/Alamofire/Source/Alamofire.swift
  33. 37 0
      RainbowPlanet/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift
  34. 580 0
      RainbowPlanet/Pods/Alamofire/Source/MultipartFormData.swift
  35. 235 0
      RainbowPlanet/Pods/Alamofire/Source/NetworkReachabilityManager.swift
  36. 55 0
      RainbowPlanet/Pods/Alamofire/Source/Notifications.swift
  37. 483 0
      RainbowPlanet/Pods/Alamofire/Source/ParameterEncoding.swift
  38. 649 0
      RainbowPlanet/Pods/Alamofire/Source/Request.swift
  39. 567 0
      RainbowPlanet/Pods/Alamofire/Source/Response.swift
  40. 715 0
      RainbowPlanet/Pods/Alamofire/Source/ResponseSerialization.swift
  41. 300 0
      RainbowPlanet/Pods/Alamofire/Source/Result.swift
  42. 307 0
      RainbowPlanet/Pods/Alamofire/Source/ServerTrustPolicy.swift
  43. 725 0
      RainbowPlanet/Pods/Alamofire/Source/SessionDelegate.swift
  44. 899 0
      RainbowPlanet/Pods/Alamofire/Source/SessionManager.swift
  45. 466 0
      RainbowPlanet/Pods/Alamofire/Source/TaskDelegate.swift
  46. 136 0
      RainbowPlanet/Pods/Alamofire/Source/Timeline.swift
  47. 315 0
      RainbowPlanet/Pods/Alamofire/Source/Validation.swift
  48. 21 0
      RainbowPlanet/Pods/BMKLocationKit/LICENSE
  49. 2 0
      RainbowPlanet/Pods/BMKLocationKit/README.md
  50. BIN
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/BMKLocationKit
  51. 134 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKGeoFenceManager.h
  52. 114 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKGeoFenceRegion.h
  53. 97 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocation.h
  54. 56 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationAuth.h
  55. 16 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationComponent.h
  56. 30 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationKitVersion.h
  57. 247 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationManager.h
  58. 36 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationPoi.h
  59. 60 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationReGeocode.h
  60. 11 0
      RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/readme.txt
  61. 11 0
      RainbowPlanet/Pods/CryptoSwift/LICENSE
  62. 528 0
      RainbowPlanet/Pods/CryptoSwift/README.md
  63. 40 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AEAD/AEAD.swift
  64. 59 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AEAD/AEADChaCha20Poly1305.swift
  65. 35 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AES.Cryptors.swift
  66. 539 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AES.swift
  67. 148 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Array+Extension.swift
  68. 20 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Authenticator.swift
  69. 63 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BatchedCollection.swift
  70. 25 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Bit.swift
  71. 18 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockCipher.swift
  72. 85 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockDecryptor.swift
  73. 57 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockEncryptor.swift
  74. 24 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockMode.swift
  75. 27 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockModeOptions.swift
  76. 70 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CBC.swift
  77. 359 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CCM.swift
  78. 70 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CFB.swift
  79. 134 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CTR.swift
  80. 61 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CipherModeWorker.swift
  81. 51 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/ECB.swift
  82. 370 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/GCM.swift
  83. 70 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/OFB.swift
  84. 70 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/PCBC.swift
  85. 537 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Blowfish.swift
  86. 104 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/CBCMAC.swift
  87. 20 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/CMAC.swift
  88. 347 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/ChaCha20.swift
  89. 193 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Checksum.swift
  90. 47 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Cipher.swift
  91. 45 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Collection+Extension.swift
  92. 23 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/CompactMap.swift
  93. 22 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Cryptor.swift
  94. 44 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Cryptors.swift
  95. 78 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Digest.swift
  96. 18 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/DigestType.swift
  97. 23 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/AES+Foundation.swift
  98. 32 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Array+Foundation.swift
  99. 23 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift
  100. 0 0
      RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift

BIN
.DS_Store


BIN
RainbowPlanet/.DS_Store


+ 3 - 3
RainbowPlanet/Podfile

@@ -16,9 +16,9 @@ target 'RainbowPlanet' do
   pod 'ObjectMapper'
   # 图片加载
   pod 'Kingfisher'
-  pod 'Nuke'
-  pod 'Nuke-WebP-Plugin'
-  pod 'Gifu'
+#  pod 'Nuke'
+#  pod 'Nuke-WebP-Plugin'
+#  pod 'Gifu'
   # 自动布局
   pod 'SnapKit'
   # 键盘

+ 1 - 41
RainbowPlanet/Podfile.lock

@@ -12,35 +12,10 @@ PODS:
   - FSPagerView (0.8.2)
   - FWPopupView (4.0.1):
     - SnapKit
-  - Gifu (3.2.0)
   - IQKeyboardManagerSwift (6.2.0)
   - JXCategoryView (1.3.0)
   - KeychainAccess (3.1.2)
   - Kingfisher (4.10.1)
-  - libwebp (1.0.0):
-    - libwebp/core (= 1.0.0)
-    - libwebp/dec (= 1.0.0)
-    - libwebp/demux (= 1.0.0)
-    - libwebp/dsp (= 1.0.0)
-    - libwebp/enc (= 1.0.0)
-    - libwebp/mux (= 1.0.0)
-    - libwebp/utils (= 1.0.0)
-    - libwebp/webp (= 1.0.0)
-  - libwebp/core (1.0.0):
-    - libwebp/webp
-  - libwebp/dec (1.0.0):
-    - libwebp/core
-  - libwebp/demux (1.0.0):
-    - libwebp/core
-  - libwebp/dsp (1.0.0):
-    - libwebp/core
-  - libwebp/enc (1.0.0):
-    - libwebp/core
-  - libwebp/mux (1.0.0):
-    - libwebp/core
-  - libwebp/utils (1.0.0):
-    - libwebp/core
-  - libwebp/webp (1.0.0)
   - LYEmptyView (1.2.3)
   - MBProgressHUD (1.1.0)
   - MJRefresh (3.1.16)
@@ -52,10 +27,6 @@ PODS:
   - Moya/RxSwift (12.0.1):
     - Moya/Core
     - RxSwift (~> 4.0)
-  - Nuke (7.5.2)
-  - Nuke-WebP-Plugin (3.0.0):
-    - libwebp (= 1.0.0)
-    - Nuke (~> 7.0)
   - ObjectMapper (3.4.2)
   - PPBadgeViewSwift (2.2.2)
   - Result (4.1.0)
@@ -99,7 +70,6 @@ DEPENDENCIES:
   - EFQRCode
   - FSPagerView
   - FWPopupView
-  - Gifu
   - IQKeyboardManagerSwift
   - JXCategoryView
   - KeychainAccess
@@ -109,8 +79,6 @@ DEPENDENCIES:
   - MJRefresh
   - MLeaksFinder
   - Moya/RxSwift
-  - Nuke
-  - Nuke-WebP-Plugin
   - ObjectMapper
   - PPBadgeViewSwift
   - RxCocoa
@@ -140,19 +108,15 @@ SPEC REPOS:
     - FBRetainCycleDetector
     - FSPagerView
     - FWPopupView
-    - Gifu
     - IQKeyboardManagerSwift
     - JXCategoryView
     - KeychainAccess
     - Kingfisher
-    - libwebp
     - LYEmptyView
     - MBProgressHUD
     - MJRefresh
     - MLeaksFinder
     - Moya
-    - Nuke
-    - Nuke-WebP-Plugin
     - ObjectMapper
     - PPBadgeViewSwift
     - Result
@@ -181,19 +145,15 @@ SPEC CHECKSUMS:
   FBRetainCycleDetector: 46f8179bbb1c587deee3ea838a1a3ee02acf5015
   FSPagerView: 816a18842306973cc7cc6df8a5332272f7815c30
   FWPopupView: a463a17aab606b0ef222a68784dbf32accba4711
-  Gifu: 7bcb6427457d85e0b4dff5a84ec5947ac19a93ea
   IQKeyboardManagerSwift: b07ccf9d8cafe993dcd6cb794eb4ba34611a0c4e
   JXCategoryView: b3bf1bedb51b5f98b63d51f0e31007a2ef80de14
   KeychainAccess: b3816fddcf28aa29d94b10ec305cd52be14c472b
   Kingfisher: c148cd7b47ebde9989f6bc7c27dcaa79d81279a0
-  libwebp: e0c2a5daf37e99aeccd78bcdfe5587c70cb98572
   LYEmptyView: ea5827f3f81fcbec427f990005501991477bdae8
   MBProgressHUD: e7baa36a220447d8aeb12769bf0585582f3866d9
   MJRefresh: 7798e16e53a5ef7f332dd05b27664db4e29530fd
   MLeaksFinder: 8c435bd2f6d070af18cff082b503b21adc130fc0
   Moya: cf730b3cd9e005401ef37a85143aa141a12fd38f
-  Nuke: 0350d346a688426e8f2331253ef28dc2fc4f6178
-  Nuke-WebP-Plugin: 7dcbb669d736a7d6d3f3a44742e825c18ff982da
   ObjectMapper: 0d4402610f4e468903ae64629eec4784531e5c51
   PPBadgeViewSwift: 96a41852df7437e9d948565a1bc894f757c29933
   Result: bd966fac789cc6c1563440b348ab2598cc24d5c7
@@ -211,6 +171,6 @@ SPEC CHECKSUMS:
   UMCSecurityPlugins: 0831a08f3988f3cea9f1d3a7626cd9bee4fef150
   UMCShare: 552b29753f1b4da87b51d96545ed19e6263df397
 
-PODFILE CHECKSUM: 84cd3ee56591b3f6e142ff210f711b4531001b2c
+PODFILE CHECKSUM: f05eb443e8bd560c9fbf7cdfad37835958e0c336
 
 COCOAPODS: 1.5.3

BIN
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/AMapFoundationKit


+ 18 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapFoundationKit.h

@@ -0,0 +1,18 @@
+//
+//  AMapFoundationKit.h
+//  AMapFoundationKit
+//
+//  Created by xiaoming han on 15/10/28.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import <AMapFoundationKit/AMapFoundationVersion.h>
+#import <AMapFoundationKit/AMapServices.h>
+#import <AMapFoundationKit/AMapURLSearchConfig.h>
+#import <AMapFoundationKit/AMapURLSearchType.h>
+#import <AMapFoundationKit/AMapURLSearch.h>
+
+#import <AMapFoundationKit/AMapUtility.h>
+#import <AMapFoundationKit/NSMutableArray+AMapSafe.h>
+#import <AMapFoundationKit/NSMutableDictionary+AMapSafe.h>
+#import <AMapFoundationKit/NSObject+AMapJsonSerialization.h>

+ 19 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapFoundationVersion.h

@@ -0,0 +1,19 @@
+//
+//  AMapFoundationVersion.h
+//  AMapFoundation
+//
+//  Created by xiaoming han on 15/10/26.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#ifndef AMapFoundationVersion_h
+#define AMapFoundationVersion_h
+
+#define AMapFoundationVersionNumber    10506
+
+FOUNDATION_EXTERN NSString * const AMapFoundationVersion;
+FOUNDATION_EXTERN NSString * const AMapFoundationName;
+
+#endif /* AMapFoundationVersion_h */

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 31 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapServices.h


+ 41 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapURLSearch.h

@@ -0,0 +1,41 @@
+//
+//  AMapURLSearch.h
+//  AMapFoundation
+//
+//  Created by xiaoming han on 15/10/28.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "AMapURLSearchConfig.h"
+
+///调起高德地图URL进行搜索,若是调起失败,可使用`+ (void)getLatestAMapApp;`方法获取最新版高德地图app.
+@interface AMapURLSearch : NSObject
+
+/**
+ * @brief 打开高德地图AppStore页面
+ */
++ (void)getLatestAMapApp;
+
+/**
+ * @brief 调起高德地图app驾车导航.
+ * @param config 配置参数.
+ * @return 是否成功.若为YES则成功调起,若为NO则无法调起.
+ */
++ (BOOL)openAMapNavigation:(AMapNaviConfig *)config;
+
+/**
+ * @brief 调起高德地图app进行路径规划.
+ * @param config 配置参数.
+ * @return 是否成功.
+ */
++ (BOOL)openAMapRouteSearch:(AMapRouteConfig *)config;
+
+/**
+ * @brief 调起高德地图app进行POI搜索.
+ * @param config 配置参数.
+ * @return 是否成功.
+ */
++ (BOOL)openAMapPOISearch:(AMapPOIConfig *)config;
+
+@end

+ 79 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapURLSearchConfig.h

@@ -0,0 +1,79 @@
+//
+//  MAMapURLSearchConfig.h
+//  MAMapKitNew
+//
+//  Created by xiaoming han on 15/5/25.
+//  Copyright (c) 2015年 xiaoming han. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+#import "AMapURLSearchType.h"
+
+///导航配置信息
+@interface AMapNaviConfig : NSObject
+
+///应用返回的Scheme
+@property (nonatomic, copy) NSString *appScheme;
+
+///应用名称
+@property (nonatomic, copy) NSString *appName;
+
+///终点
+@property (nonatomic, assign) CLLocationCoordinate2D destination;
+
+///导航策略
+@property (nonatomic, assign) AMapDrivingStrategy strategy;
+
+@end
+
+#pragma mark - 
+
+///路径搜索配置信息
+@interface AMapRouteConfig : NSObject
+
+///应用返回的Scheme
+@property (nonatomic, copy) NSString *appScheme;
+
+///应用名称
+@property (nonatomic, copy) NSString *appName;
+
+///起点坐标
+@property (nonatomic, assign) CLLocationCoordinate2D startCoordinate;
+
+///终点坐标
+@property (nonatomic, assign) CLLocationCoordinate2D destinationCoordinate;
+
+///驾车策略
+@property (nonatomic, assign) AMapDrivingStrategy drivingStrategy;
+
+///公交策略
+@property (nonatomic, assign) AMapTransitStrategy transitStrategy;
+
+///路径规划类型
+@property (nonatomic, assign) AMapRouteSearchType routeType;
+
+@end
+
+#pragma mark -
+
+///POI搜索配置信息
+@interface AMapPOIConfig : NSObject
+
+///应用返回的Scheme
+@property (nonatomic, copy) NSString *appScheme;
+
+///应用名称
+@property (nonatomic, copy) NSString *appName;
+
+///搜索关键字
+@property (nonatomic, copy) NSString *keywords;
+
+///左上角坐标
+@property (nonatomic, assign) CLLocationCoordinate2D leftTopCoordinate;
+
+///右下角坐标
+@property (nonatomic, assign) CLLocationCoordinate2D rightBottomCoordinate;
+
+@end
+

+ 44 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapURLSearchType.h

@@ -0,0 +1,44 @@
+//
+//  MAMapURLSearchType.h
+//  MAMapKitNew
+//
+//  Created by xiaoming han on 15/5/25.
+//  Copyright (c) 2015年 xiaoming han. All rights reserved.
+//
+
+///驾车策略
+typedef NS_ENUM(NSInteger, AMapDrivingStrategy)
+{
+    AMapDrivingStrategyFastest  = 0, ///<速度最快
+    AMapDrivingStrategyMinFare  = 1, ///<避免收费
+    AMapDrivingStrategyShortest = 2, ///<距离最短
+    
+    AMapDrivingStrategyNoHighways   = 3, ///<不走高速
+    AMapDrivingStrategyAvoidCongestion = 4, ///<躲避拥堵
+    
+    AMapDrivingStrategyAvoidHighwaysAndFare    = 5, ///<不走高速且避免收费
+    AMapDrivingStrategyAvoidHighwaysAndCongestion = 6, ///<不走高速且躲避拥堵
+    AMapDrivingStrategyAvoidFareAndCongestion  = 7, ///<躲避收费和拥堵
+    AMapDrivingStrategyAvoidHighwaysAndFareAndCongestion = 8 ///<不走高速躲避收费和拥堵
+};
+
+///公交策略
+typedef NS_ENUM(NSInteger, AMapTransitStrategy)
+{
+    AMapTransitStrategyFastest = 0,///<最快捷
+    AMapTransitStrategyMinFare = 1,///<最经济
+    AMapTransitStrategyMinTransfer = 2,///<最少换乘
+    AMapTransitStrategyMinWalk = 3,///<最少步行
+    AMapTransitStrategyMostComfortable = 4,///<最舒适
+    AMapTransitStrategyAvoidSubway = 5,///<不乘地铁
+};
+
+///路径规划类型
+typedef NS_ENUM(NSInteger, AMapRouteSearchType)
+{
+    AMapRouteSearchTypeDriving = 0, ///<驾车
+    AMapRouteSearchTypeTransit = 1, ///<公交
+    AMapRouteSearchTypeWalking = 2, ///<步行
+};
+
+

+ 50 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/AMapUtility.h

@@ -0,0 +1,50 @@
+//
+//  AMapUtility.h
+//  AMapFoundation
+//
+//  Created by xiaoming han on 15/10/27.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+
+//工具方法
+
+/**
+ * @brief 如果字符串为nil则返回空字符串
+ */
+FOUNDATION_STATIC_INLINE NSString * AMapEmptyStringIfNil(NSString *s)
+{
+    return s ? s : @"";
+}
+
+///坐标类型枚举
+typedef NS_ENUM(NSInteger, AMapCoordinateType)
+{
+    AMapCoordinateTypeAMap = -1,    ///<AMap
+    AMapCoordinateTypeBaidu = 0,    ///<Baidu
+    AMapCoordinateTypeMapBar,       ///<MapBar
+    AMapCoordinateTypeMapABC,       ///<MapABC
+    AMapCoordinateTypeSoSoMap,      ///<SoSoMap
+    AMapCoordinateTypeAliYun,       ///<AliYun
+    AMapCoordinateTypeGoogle,       ///<Google
+    AMapCoordinateTypeGPS,          ///<GPS
+};
+
+/**
+ * @brief 转换目标经纬度为高德坐标系,不在枚举范围内的经纬度将直接返回。
+ * @param coordinate 待转换的经纬度
+ * @param type       坐标系类型
+ * @return 高德坐标系经纬度
+ */
+FOUNDATION_EXTERN CLLocationCoordinate2D AMapCoordinateConvert(CLLocationCoordinate2D coordinate, AMapCoordinateType type);
+
+/**
+ * @brief 判断目标经纬度处是否有高德数据。输入参数为高德坐标系。此方法为粗略判断,在边界地区可能会不准确。
+ * @param coordinate 待判断的目标经纬度
+ * @return 布尔值。YES:有数据,NO:没数据
+ */
+FOUNDATION_EXTERN BOOL AMapDataAvailableForCoordinate(CLLocationCoordinate2D coordinate);
+
+

+ 15 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/NSMutableArray+AMapSafe.h

@@ -0,0 +1,15 @@
+//
+//  NSArray(AMapSave).h
+//  AMapFoundationKit
+//
+//  Created by zhou on 2018/2/23.
+//  Copyright © 2018年 Amap.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSMutableArray<ObjectType> (AMapSafe)
+
+- (BOOL)amf_addObjectSafe:(ObjectType)anObject;
+
+@end

+ 15 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/NSMutableDictionary+AMapSafe.h

@@ -0,0 +1,15 @@
+//
+//  NSMutableDictionary+AMapSave.h
+//  AMapFoundationKit
+//
+//  Created by zhou on 2018/2/23.
+//  Copyright © 2018年 Amap.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface NSMutableDictionary <KeyType, ObjectType> (AMapSafe)
+
+- (BOOL)amf_setObjectSafe:(ObjectType)anObject forKey:(KeyType <NSCopying>)aKey;
+
+@end

+ 48 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Headers/NSObject+AMapJsonSerialization.h

@@ -0,0 +1,48 @@
+//
+//  NSObject+JsonAutoSerialize.h
+//  AMapFoundation
+//
+//  Created by zhou on 2018/2/1.
+//  Copyright © 2018年 Amap.com. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+// 网络自动化解析数组定义宏
+#define AMapJsonArray(key,type)  NSArray <type *> *key;     \
+@property (nonatomic, strong, readonly) type *__Array__##key
+
+#define AMapJsonMutableArray(key,type)  NSMutableArray <type *> *key;     \
+@property (nonatomic, strong, readonly) type *__Array__##key
+
+#define AMapNestedArray(key,type)   NSArray *key;     \
+@property (nonatomic, strong, readonly) type *__Array__##key
+
+#define AMapNestedMutableArray(key,type)    NSMutableArray *key;     \
+@property (nonatomic, strong, readonly) type *__Array__##key
+
+//#define AMapBind(key,propertyName,type)    *key;     \
+//@property (nonatomic, strong, readonly) type *__Bind__##propertyName##__##key
+
+@protocol AMapJsonManualSerialization <NSObject>
+
+@optional
+
+- (void)manualDeserializationJsonData:(NSDictionary *)jsonDictionary forInfo:(id)customInfo;
+
+- (NSMutableDictionary *)manualSerializeObjectForInfo:(id)customInfo;
+
+@end
+
+@interface NSObject (AMapJsonSerialization)
+
+// 反序列化自动解析Json数据,并根据和dictionaryJson的key匹配的属性名进行自动赋值,注意dictionaryJson需要和对象对应,注意只有非基础类型属性的解析才会回调手动解析(需实现AMapManuallParseJson协议)
+- (void)amf_deserializationJsonData:(NSDictionary *)dictionaryJson forInfo:(id)customInfo;
+
+// 将Module数据对象序列化成Json数据对象的Dictionary,对于NSString、NSMutableArray、NSNumber、NSNull、NSArray和NSMutableArray会返回nil
+- (NSMutableDictionary *)amf_serializeJsonObjectForInfo:(id)customInfo;
+
+// 将NSArray或NSMutableArray序列化成Json数据对象的数组,仅适用于是NSArray和NSMutableArray类型的对象调用,否则会返回nil
+- (NSMutableArray *)amf_serializeJsonArrayForInfo:(id)customInfo;
+
+@end

+ 6 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/Modules/module.modulemap

@@ -0,0 +1,6 @@
+framework module AMapFoundationKit {
+  umbrella header "AMapFoundationKit.h"
+
+  export *
+  module * { export * }
+}

+ 1 - 0
RainbowPlanet/Pods/AMapFoundation/AMapFoundationKit.framework/version.txt

@@ -0,0 +1 @@
+1.5.6+foundation.1d90b58

BIN
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/AMapLocationKit


+ 26 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapGeoFenceError.h

@@ -0,0 +1,26 @@
+//
+//  AMapGeoFenceError.h
+//  AMapLocationKit
+//
+//  Created by eidan on 16/12/15.
+//  Copyright © 2016年 Amap. All rights reserved.
+//
+
+#ifndef AMapGeoFenceError_h
+#define AMapGeoFenceError_h
+
+
+///AMapGeoFence errorDomain
+extern NSString * const AMapGeoFenceErrorDomain;
+
+///地理围栏错误码
+typedef NS_ENUM(NSInteger, AMapGeoFenceErrorCode) {
+    AMapGeoFenceErrorUnknown = 1,                    ///< 未知错误
+    AMapGeoFenceErrorInvalidParameter = 2,           ///< 参数错误
+    AMapGeoFenceErrorFailureConnection = 3,          ///< 网络连接异常
+    AMapGeoFenceErrorFailureAuth  = 4,               ///< 鉴权失败
+    AMapGeoFenceErrorNoValidFence = 5,               ///< 无可用围栏
+    AMapGeoFenceErroFailureLocating = 6,             ///< 定位错误
+};
+
+#endif /* AMapGeoFenceError_h */

+ 211 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapGeoFenceManager.h

@@ -0,0 +1,211 @@
+//
+//  AMapGeoFenceManager.h
+//  AMapLocationKit
+//
+//  Created by hanxiaoming on 16/12/5.
+//  Copyright © 2016年 Amap. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "AMapGeoFenceRegionObj.h"
+
+// 以下类涉及的坐标需要使用高德坐标系坐标(GCJ02)
+
+@protocol AMapGeoFenceManagerDelegate;
+
+///地理围栏监听状态类型
+typedef NS_OPTIONS(NSUInteger, AMapGeoFenceActiveAction)
+{
+    AMapGeoFenceActiveActionNone     = 0,       ///< 不进行监听
+    AMapGeoFenceActiveActionInside   = 1 << 0,  ///< 在范围内
+    AMapGeoFenceActiveActionOutside  = 1 << 1,  ///< 在范围外
+    AMapGeoFenceActiveActionStayed   = 1 << 2,  ///< 停留(在范围内超过10分钟)
+};
+
+///地理围栏任务状态类型
+typedef NS_OPTIONS(NSUInteger, AMapGeoFenceRegionActiveStatus)
+{
+    AMapGeoFenceRegionActiveUNMonitor   = 0,       ///< 未注册
+    AMapGeoFenceRegionActiveMonitoring  = 1 << 0,  ///< 正在监控
+    AMapGeoFenceRegionActivePaused      = 1 << 1,  ///< 暂停监控
+};
+
+///地理围栏管理类(since 2.3.0)
+@interface AMapGeoFenceManager : NSObject
+
+
+///实现了 AMapGeoFenceManagerDelegate 协议的类指针。
+@property (nonatomic, weak) id<AMapGeoFenceManagerDelegate> delegate;
+
+
+///需要进行通知的行为,默认为AMapGeoFenceActiveActionInside。
+@property (nonatomic, assign) AMapGeoFenceActiveAction activeAction;
+
+
+///指定定位是否会被系统自动暂停。默认为NO。
+@property (nonatomic, assign) BOOL pausesLocationUpdatesAutomatically;
+
+
+///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
+@property (nonatomic, assign) BOOL allowsBackgroundLocationUpdates;
+
+///检测是否存在虚拟定位风险,默认为NO,即不检测。 \n如果设置为YES,检测到风险后,会通过amapGeoFenceManager:didGeoFencesStatusChangedForRegion:customID:error: 的error给出风险提示,error的格式为error.domain==AMapGeoFenceErrorDomain; error.code==AMapGeoFenceErroFailureLocating; 
+@property (nonatomic, assign) BOOL detectRiskOfFakeLocation;
+
+
+/**
+ * @brief 添加一个圆形围栏
+ * @param center 围栏的中心点经纬度坐标
+ * @param radius 围栏的半径,单位:米,要求大于0
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addCircleRegionForMonitoringWithCenter:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius customID:(NSString *)customID;
+
+
+/**
+ * @brief 根据经纬度坐标数据添加一个闭合的多边形围栏,点与点之间按顺序尾部相连, 第一个点与最后一个点相连
+ * @param coordinates 经纬度坐标点数据,coordinates对应的内存会拷贝,调用者负责该内存的释放
+ * @param count 经纬度坐标点的个数,不可小于3个
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addPolygonRegionForMonitoringWithCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSInteger)count customID:(NSString *)customID;
+
+
+/**
+ * @brief 根据要查询的关键字,类型,城市等信息,添加一个或者多个POI地理围栏
+ * @param keyword 要查询的关键字,多个关键字用“|”分割,必填,keyword和type两者至少必选其一
+ * @param type 要查询的POI类型,多个类型用“|”分割,必填,keyword和type两者至少必选其一,具体分类编码和规则详见: http://lbs.amap.com/api/webservice/guide/api/search/#text
+ * @param city 要查询的城市
+ * @param size 要查询的数据的条数,(0,25],传入<=0的值为10,传入大于25的值为25,默认10
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addKeywordPOIRegionForMonitoringWithKeyword:(NSString *)keyword POIType:(NSString *)type city:(NSString *)city size:(NSInteger)size customID:(NSString *)customID;
+
+
+/**
+ * @brief 根据要查询的点的经纬度,搜索半径等信息,添加一个或者多个POI围栏
+ * @param locationPoint 点的经纬度坐标,必填
+ * @param aroundRadius 查询半径,单位:米,(0,50000],超出范围取3000,默认3000
+ * @param keyword 要查询的关键字,多个关键字用“|”分割,可选
+ * @param type 要查询的POI类型,多个类型用“|”分割,可选
+ * @param size 要查询的数据的条数,(0,25],传入<=0的值为10,传入大于25的值为25,默认10
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addAroundPOIRegionForMonitoringWithLocationPoint:(CLLocationCoordinate2D)locationPoint aroundRadius:(NSInteger)aroundRadius keyword:(NSString *)keyword POIType:(NSString *)type size:(NSInteger)size customID:(NSString *)customID;
+
+
+/**
+ * @brief 根据要查询的行政区域关键字,添加一个或者多个行政区域围栏
+ * @param districtName 行政区域关键字,必填,只支持单个关键词语:行政区名称、citycode、adcode,规则详见: http://lbs.amap.com/api/webservice/guide/api/district/#district
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addDistrictRegionForMonitoringWithDistrictName:(NSString *)districtName customID:(NSString *)customID;
+
+/**
+ * @brief 获取指定围栏的运行状态
+ * @param region 要获取运行状态的围栏
+ * @return 返回指定围栏的运行状态
+ */
+- (AMapGeoFenceRegionActiveStatus)statusWithGeoFenceRegion:(AMapGeoFenceRegion *)region;
+
+/**
+ * @brief 根据customID获得所有已经注册的围栏,如果customID传nil,则返回全部已注册围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @return 获得的围栏构成的数组,如果没有结果,返回nil
+ */
+- (NSArray *)geoFenceRegionsWithCustomID:(NSString *)customID;
+
+/**
+ * @brief 根据customID获得所有正在监控的围栏,如果customID传nil,则返回全部正在监控的围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @return 获得的围栏构成的数组,如果没有结果,返回nil
+ */
+- (NSArray *)monitoringGeoFenceRegionsWithCustomID:(NSString *)customID;
+
+/**
+ * @brief 根据customID获得所有已经暂停的围栏,如果customID传nil,则返回全部已经暂停的围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @return 获得的围栏构成的数组,如果没有结果,返回nil
+ */
+- (NSArray *)pausedGeoFenceRegionsWithCustomID:(NSString *)customID;
+
+
+/**
+ * @brief 暂停指定customID的围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @return 返回被暂停围栏的数组,如果没有围栏被暂停,返回nil
+ */
+- (NSArray *)pauseGeoFenceRegionsWithCustomID:(NSString *)customID;
+
+
+/**
+ * @brief 暂停指定围栏
+ * @param region 要暂停监控的围栏
+ * @return 返回指定围栏是否被暂停,如果指定围栏没有注册,则返回NO
+ */
+- (BOOL)pauseTheGeoFenceRegion:(AMapGeoFenceRegion *)region;
+
+/**
+ * @brief 根据customID开始监控已经暂停的围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @return 返回开始监控的围栏构成的数组
+ */
+- (NSArray *)startGeoFenceRegionsWithCustomID:(NSString *)customID;
+
+/**
+ * @brief 开始监控指定围栏
+ * @param region 要开始监控的围栏
+ * @return 返回指定围栏是否开始监控,如果指定围栏没有注册,则返回NO
+ */
+- (BOOL)startTheGeoFenceRegion:(AMapGeoFenceRegion *)region;
+
+/**
+ * @brief 移除指定围栏
+ * @param region 要停止监控的围栏
+ */
+- (void)removeTheGeoFenceRegion:(AMapGeoFenceRegion *)region;
+
+
+/**
+ * @brief 移除指定customID的围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ */
+- (void)removeGeoFenceRegionsWithCustomID:(NSString *)customID;
+
+
+/**
+ * @brief 移除所有围栏
+ */
+- (void)removeAllGeoFenceRegions;
+
+
+@end
+
+
+
+///地理围栏代理协议(since 2.3.0),该协议定义了获取地理围栏相关回调方法,包括添加、状态改变等。
+@protocol AMapGeoFenceManagerDelegate <NSObject>
+
+@optional
+
+
+/**
+ * @brief 添加地理围栏完成后的回调,成功与失败都会调用
+ * @param manager 地理围栏管理类
+ * @param regions 成功添加的一个或多个地理围栏构成的数组
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @param error 添加失败的错误信息
+ */
+- (void)amapGeoFenceManager:(AMapGeoFenceManager *)manager didAddRegionForMonitoringFinished:(NSArray <AMapGeoFenceRegion *> *)regions customID:(NSString *)customID error:(NSError *)error;
+
+
+/**
+ * @brief 地理围栏状态改变时回调,当围栏状态的值发生改变,定位失败都会调用
+ * @param manager 地理围栏管理类
+ * @param region 状态改变的地理围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @param error 错误信息,如定位相关的错误
+ */
+- (void)amapGeoFenceManager:(AMapGeoFenceManager *)manager didGeoFencesStatusChangedForRegion:(AMapGeoFenceRegion *)region customID:(NSString *)customID error:(NSError *)error;
+
+@end

+ 120 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapGeoFenceRegionObj.h

@@ -0,0 +1,120 @@
+//
+//  AMapGeoFenceRegionObj.h
+//  AMapLocationKit
+//
+//  Created by hanxiaoming on 16/12/5.
+//  Copyright © 2016年 Amap. All rights reserved.
+//
+
+#import "AMapLocationCommonObj.h"
+
+
+///AMapGeoFence Region State
+typedef NS_ENUM(NSInteger, AMapGeoFenceRegionStatus)
+{
+    AMapGeoFenceRegionStatusUnknown  = 0,       ///< 未知
+    AMapGeoFenceRegionStatusInside   = 1,       ///< 在范围内
+    AMapGeoFenceRegionStatusOutside  = 2,       ///< 在范围外
+    AMapGeoFenceRegionStatusStayed   = 3,       ///< 停留(在范围内超过10分钟)
+};
+
+typedef NS_ENUM(NSInteger, AMapGeoFenceRegionType)
+{
+    AMapGeoFenceRegionTypeCircle     = 0,       /// 圆形地理围栏
+    AMapGeoFenceRegionTypePolygon    = 1,       /// 多边形地理围栏
+    AMapGeoFenceRegionTypePOI        = 2,       /// 兴趣点(POI)地理围栏
+    AMapGeoFenceRegionTypeDistrict   = 3,       /// 行政区划地理围栏
+};
+
+#pragma mark - AMapGeoFenceRegion
+
+
+///地理围栏基类,不可直接使用。(since 2.3.0)
+@interface AMapGeoFenceRegion : NSObject<NSCopying>
+
+
+///AMapGeoFenceRegion的唯一标识符
+@property (nonatomic, copy, readonly) NSString *identifier;
+
+
+///用户自定义ID,可为nil。
+@property (nonatomic, copy, readonly) NSString *customID;
+
+
+///坐标点和围栏的关系,比如用户的位置和围栏的关系
+@property (nonatomic, assign) AMapGeoFenceRegionStatus fenceStatus;
+
+///用户自定义ID,可为nil。
+@property (nonatomic, assign) AMapGeoFenceRegionType regionType;
+
+///缓存最近获取的定位信息,可能会存在延时,可为nil,会在获取定位时更新
+@property (nonatomic, copy) CLLocation *currentLocation;
+
+@end
+
+
+#pragma mark - AMapLocationCircleRegion
+
+
+///圆形地理围栏(since 2.3.0)
+@interface AMapGeoFenceCircleRegion : AMapGeoFenceRegion
+
+
+///中心点的经纬度坐标
+@property (nonatomic, readonly) CLLocationCoordinate2D center;
+
+
+///半径,单位:米
+@property (nonatomic, readonly) CLLocationDistance radius;
+
+@end
+
+
+#pragma mark -AMapGeoFencePolygonRegion
+
+
+///多边形地理围栏(since 2.3.0)
+@interface AMapGeoFencePolygonRegion : AMapGeoFenceRegion
+
+
+///经纬度坐标点数据
+@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates;
+
+
+///经纬度坐标点的个数
+@property (nonatomic, readonly) NSInteger count;
+
+
+@end
+
+
+#pragma mark -AMapGeoFencePOIRegion
+
+
+///兴趣点(POI)地理围栏(since 2.3.0)
+@interface AMapGeoFencePOIRegion : AMapGeoFenceCircleRegion
+
+
+///POI信息
+@property (nonatomic, strong, readonly) AMapLocationPOIItem *POIItem;
+
+
+@end
+
+
+#pragma mark -AMapGeoFenceDistrictRegion
+
+
+///行政区划地理围栏(since 2.3.0)
+@interface AMapGeoFenceDistrictRegion : AMapGeoFenceRegion
+
+
+///行政区域信息
+@property (nonatomic, strong, readonly) AMapLocationDistrictItem *districtItem;
+
+
+///行政区域轮廓坐标点,每个行政区可能有多个模块,每个模块的坐标点数组由AMapLocationPoint构成
+@property (nonatomic, copy, readonly) NSArray <NSArray<AMapLocationPoint *> *> *polylinePoints;
+
+
+@end

+ 194 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationCommonObj.h

@@ -0,0 +1,194 @@
+//
+//  AMapLocationCommonObj.h
+//  AMapLocationKit
+//
+//  Created by AutoNavi on 15/10/22.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+#import <UIKit/UIKit.h>
+
+
+///AMapLocation errorDomain
+extern NSString * const AMapLocationErrorDomain;
+
+///AMapLocation errorCode
+typedef NS_ENUM(NSInteger, AMapLocationErrorCode)
+{
+    AMapLocationErrorUnknown = 1,               ///<未知错误
+    AMapLocationErrorLocateFailed = 2,          ///<定位错误
+    AMapLocationErrorReGeocodeFailed  = 3,      ///<逆地理错误
+    AMapLocationErrorTimeOut = 4,               ///<超时
+    AMapLocationErrorCanceled = 5,              ///<取消
+    AMapLocationErrorCannotFindHost = 6,        ///<找不到主机
+    AMapLocationErrorBadURL = 7,                ///<URL异常
+    AMapLocationErrorNotConnectedToInternet = 8,///<连接异常
+    AMapLocationErrorCannotConnectToHost = 9,   ///<服务器连接失败
+    AMapLocationErrorRegionMonitoringFailure=10,///<地理围栏错误
+    AMapLocationErrorRiskOfFakeLocation = 11,   ///<存在虚拟定位风险
+};
+
+///AMapLocation Region State
+typedef NS_ENUM(NSInteger, AMapLocationRegionState)
+{
+    AMapLocationRegionStateUnknow = 0,          ///<未知
+    AMapLocationRegionStateInside = 1,          ///<在范围内
+    AMapLocationRegionStateOutside = 2,         ///<在范围外
+};
+
+///AMapLocation Region Language
+typedef NS_ENUM(NSInteger, AMapLocationReGeocodeLanguage)
+{
+    AMapLocationReGeocodeLanguageDefault = 0,          ///<默认,根据地区选择语言
+    AMapLocationReGeocodeLanguageChinse = 1,           ///<中文
+    AMapLocationReGeocodeLanguageEnglish = 2,          ///<英文
+};
+
+///逆地理信息
+@interface AMapLocationReGeocode : NSObject<NSCopying,NSCoding>
+
+///格式化地址
+@property (nonatomic, copy) NSString *formattedAddress;
+
+///国家
+@property (nonatomic, copy) NSString *country;
+
+///省/直辖市
+@property (nonatomic, copy) NSString *province;
+
+///市
+@property (nonatomic, copy) NSString *city;
+
+///区
+@property (nonatomic, copy) NSString *district;
+
+///乡镇
+@property (nonatomic, copy) NSString *township __attribute__((deprecated("该字段从v2.2.0版本起不再返回数据,建议您使用AMapSearchKit的逆地理功能获取.")));
+
+///社区
+@property (nonatomic, copy) NSString *neighborhood __attribute__((deprecated("该字段从v2.2.0版本起不再返回数据,建议您使用AMapSearchKit的逆地理功能获取.")));
+
+///建筑
+@property (nonatomic, copy) NSString *building __attribute__((deprecated("该字段从v2.2.0版本起不再返回数据,建议您使用AMapSearchKit的逆地理功能获取.")));
+
+///城市编码
+@property (nonatomic, copy) NSString *citycode;
+
+///区域编码
+@property (nonatomic, copy) NSString *adcode;
+
+///街道名称
+@property (nonatomic, copy) NSString *street;
+
+///门牌号
+@property (nonatomic, copy) NSString *number;
+
+///兴趣点名称
+@property (nonatomic, copy) NSString *POIName;
+
+///所属兴趣点名称
+@property (nonatomic, copy) NSString *AOIName;
+
+@end
+
+#pragma mark - AMapLocationPoint
+
+///经纬度坐标点对象
+@interface AMapLocationPoint : NSObject<NSCopying,NSCoding>
+
+///纬度
+@property (nonatomic, assign) CGFloat latitude;
+
+///经度
+@property (nonatomic, assign) CGFloat longitude;
+
+/**
+ *  @brief AMapNaviPoint类对象的初始化函数
+ *  @param lat 纬度
+ *  @param lon 经度
+ *  @return AMapNaviPoint类对象id
+ */
++ (AMapLocationPoint *)locationWithLatitude:(CGFloat)lat longitude:(CGFloat)lon;
+
+@end
+
+///POI信息
+@interface AMapLocationPOIItem : NSObject <NSCopying, NSCoding>
+
+///id
+@property (nonatomic, copy) NSString *pId;
+
+///名称
+@property (nonatomic, copy) NSString *name;
+
+///类型
+@property (nonatomic, copy) NSString *type;
+
+///类型编码
+@property (nonatomic, copy) NSString *typeCode;
+
+///地址信息
+@property (nonatomic, copy) NSString *address;
+
+///经纬度
+@property (nonatomic, strong) AMapLocationPoint *location;
+
+///电话号码
+@property (nonatomic, copy) NSString *tel;
+
+///省份
+@property (nonatomic, copy) NSString *province;
+
+///城市
+@property (nonatomic, copy) NSString *city;
+
+///区
+@property (nonatomic, copy) NSString *district;
+
+@end
+
+///行政区域信息
+@interface AMapLocationDistrictItem : NSObject <NSCopying, NSCoding>
+
+///城市编码
+@property (nonatomic, copy) NSString *cityCode;
+
+///区域编码
+@property (nonatomic, copy) NSString *districtCode;
+
+///区名
+@property (nonatomic, copy) NSString *district;
+
+///行政区域轮廓坐标点,每个行政区可能有多个模块,每个模块的坐标点数组由AMapLocationPoint构成
+@property (nonatomic, copy) NSArray <NSArray<AMapLocationPoint *> *> *polylinePoints;
+
+@end
+
+///AMapLocation CoordinateType
+typedef NS_ENUM(NSUInteger, AMapLocationCoordinateType)
+{
+    AMapLocationCoordinateTypeBaidu = 0,        ///<Baidu
+    AMapLocationCoordinateTypeMapBar,           ///<MapBar
+    AMapLocationCoordinateTypeMapABC,           ///<MapABC
+    AMapLocationCoordinateTypeSoSoMap,          ///<SoSoMap
+    AMapLocationCoordinateTypeAliYun,           ///<AliYun
+    AMapLocationCoordinateTypeGoogle,           ///<Google
+    AMapLocationCoordinateTypeGPS,              ///<GPS
+};
+
+/**
+ *  @brief 转换目标经纬度为高德坐标系
+ *  @param coordinate 待转换的经纬度
+ *  @param type       坐标系类型
+ *  @return 高德坐标系经纬度
+ */
+FOUNDATION_EXTERN CLLocationCoordinate2D AMapLocationCoordinateConvert(CLLocationCoordinate2D coordinate, AMapLocationCoordinateType type);
+
+/**
+ *  @brief 判断目标经纬度是否在大陆以及港、澳地区。输入参数为高德坐标系。
+ *  @param coordinate 待判断的目标经纬度
+ *  @return 是否在大陆以及港、澳地区
+ */
+FOUNDATION_EXTERN BOOL AMapLocationDataAvailableForCoordinate(CLLocationCoordinate2D coordinate);

+ 17 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationKit.h

@@ -0,0 +1,17 @@
+//
+//  AMapLocationKit.h
+//  AMapLocationKit
+//
+//  Created by AutoNavi on 15/10/22.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import <AMapLocationKit/AMapLocationVersion.h>
+
+#import <AMapLocationKit/AMapLocationManager.h>
+#import <AMapLocationKit/AMapLocationCommonObj.h>
+#import <AMapLocationKit/AMapLocationRegionObj.h>
+
+#import <AMapLocationKit/AMapGeoFenceRegionObj.h>
+#import <AMapLocationKit/AMapGeoFenceManager.h>
+#import <AMapLocationKit/AMapGeoFenceError.h>

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 208 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationManager.h


+ 90 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationRegionObj.h

@@ -0,0 +1,90 @@
+//
+//  AMapLocationRegionObj.h
+//  AMapLocationKit
+//
+//  Created by AutoNavi on 15/11/27.
+//  Copyright © 2015年 Amap. All rights reserved.
+//
+
+#import "AMapLocationCommonObj.h"
+
+// 以下类涉及的坐标需要使用高德坐标系坐标(GCJ02)
+
+#pragma mark - AMapLocationRegion
+
+
+///AMapLocationRegion类,该类提供范围类的基本信息,并无具体实现,不要直接使用。
+@interface AMapLocationRegion : NSObject<NSCopying>
+
+///AMapLocationRegion的identifier
+@property (nonatomic, copy, readonly) NSString *identifier;
+
+///当进入region范围时是否通知,默认YES
+@property (nonatomic, assign) BOOL notifyOnEntry;
+
+///当离开region范围时是否通知,默认YES
+@property (nonatomic, assign) BOOL notifyOnExit;
+
+/**
+ *  @brief 初始化方法
+ *  @param identifier 唯一标识符,必填,不可为nil
+ */
+- (instancetype)initWithIdentifier:(NSString *)identifier;
+
+/**
+ *  @brief 坐标点是否在范围内
+ *  @param coordinate 要判断的坐标点
+ *  @return 是否在范围内
+ */
+- (BOOL)containsCoordinate:(CLLocationCoordinate2D)coordinate;
+
+@end
+
+#pragma mark - AMapLocationCircleRegion
+
+
+///AMapLocationCircleRegion类,定义一个圆形范围。
+@interface AMapLocationCircleRegion : AMapLocationRegion
+
+///中心点的经纬度坐标
+@property (nonatomic, readonly) CLLocationCoordinate2D center;
+
+///半径,单位:米
+@property (nonatomic, readonly) CLLocationDistance radius;
+
+/**
+ *  @brief 根据中心点和半径生成圆形范围
+ *  @param center 中心点的经纬度坐标
+ *  @param radius 半径,单位:米
+ *  @param identifier 唯一标识符,必填,不可为nil
+ *  @return AMapLocationCircleRegion类实例
+ */
+- (instancetype)initWithCenter:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius identifier:(NSString *)identifier;
+
+
+@end
+
+#pragma mark - AMapLocationPolygonRegion
+
+
+///AMapLocationCircleRegion类,定义一个闭合多边形范围,点与点之间按顺序尾部相连, 第一个点与最后一个点相连。
+@interface AMapLocationPolygonRegion : AMapLocationRegion
+
+///经纬度坐标点数据
+@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates;
+
+///经纬度坐标点的个数
+@property (nonatomic, readonly) NSInteger count;
+
+/**
+ *  @brief 根据经纬度坐标数据生成闭合多边形范围
+ *  @param coordinates 经纬度坐标点数据,coordinates对应的内存会拷贝,调用者负责该内存的释放
+ *  @param count 经纬度坐标点的个数,不可小于3个
+ *  @param identifier 唯一标识符,必填,不可为nil
+ *  @return AMapLocationCircleRegion类实例
+ */
+- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSInteger)count identifier:(NSString *)identifier;
+
+
+
+@end

+ 26 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Headers/AMapLocationVersion.h

@@ -0,0 +1,26 @@
+//
+//  AMapLoctionVersion.h
+//  AMapLocationKit
+//
+//  Created by AutoNavi on 16/1/22.
+//  Copyright © 2016年 Amap. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <AMapFoundationKit/AMapFoundationVersion.h>
+
+#ifndef AMapLoctionVersion_h
+#define AMapLoctionVersion_h
+
+#define AMapLocationVersionNumber                   20601
+#define AMapLocationFoundationVersionMinRequired    10400
+
+// 依赖库版本检测
+#if AMapFoundationVersionNumber < AMapLocationFoundationVersionMinRequired
+#error "The AMapFoundationKit version is less than minimum required, please update! Any questions please to visit http://lbs.amap.com"
+#endif
+
+FOUNDATION_EXTERN NSString * const AMapLocationVersion;
+FOUNDATION_EXTERN NSString * const AMapLocationName;
+
+#endif /* AMapLoctionVersion_h */

+ 6 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/Modules/module.modulemap

@@ -0,0 +1,6 @@
+framework module AMapLocationKit {
+  umbrella header "AMapLocationKit.h"
+
+  export *
+  module * { export * }
+}

+ 1 - 0
RainbowPlanet/Pods/AMapLocation/AMapLocationKit.framework/version.txt

@@ -0,0 +1 @@
+2.6.1+loc.b8da0f6

+ 19 - 0
RainbowPlanet/Pods/Alamofire/LICENSE

@@ -0,0 +1,19 @@
+Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 243 - 0
RainbowPlanet/Pods/Alamofire/README.md

@@ -0,0 +1,243 @@
+![Alamofire: Elegant Networking in Swift](https://raw.githubusercontent.com/Alamofire/Alamofire/master/alamofire.png)
+
+[![Build Status](https://travis-ci.org/Alamofire/Alamofire.svg?branch=master)](https://travis-ci.org/Alamofire/Alamofire)
+[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Alamofire.svg)](https://img.shields.io/cocoapods/v/Alamofire.svg)
+[![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
+[![Platform](https://img.shields.io/cocoapods/p/Alamofire.svg?style=flat)](https://alamofire.github.io/Alamofire)
+[![Twitter](https://img.shields.io/badge/twitter-@AlamofireSF-blue.svg?style=flat)](https://twitter.com/AlamofireSF)
+[![Gitter](https://badges.gitter.im/Alamofire/Alamofire.svg)](https://gitter.im/Alamofire/Alamofire?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
+
+Alamofire is an HTTP networking library written in Swift.
+
+- [Features](#features)
+- [Component Libraries](#component-libraries)
+- [Requirements](#requirements)
+- [Migration Guides](#migration-guides)
+- [Communication](#communication)
+- [Installation](#installation)
+- [Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md)
+    - **Intro -** [Making a Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#making-a-request), [Response Handling](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-handling), [Response Validation](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-validation), [Response Caching](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#response-caching)
+	- **HTTP -** [HTTP Methods](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-methods), [Parameter Encoding](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#parameter-encoding), [HTTP Headers](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#http-headers), [Authentication](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#authentication)
+	- **Large Data -** [Downloading Data to a File](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#downloading-data-to-a-file), [Uploading Data to a Server](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#uploading-data-to-a-server)
+	- **Tools -** [Statistical Metrics](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#statistical-metrics), [cURL Command Output](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md#curl-command-output)
+- [Advanced Usage](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md)
+	- **URL Session -** [Session Manager](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-manager), [Session Delegate](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#session-delegate), [Request](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#request)
+	- **Routing -** [Routing Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#routing-requests), [Adapting and Retrying Requests](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#adapting-and-retrying-requests)
+	- **Model Objects -** [Custom Response Serialization](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#custom-response-serialization)
+	- **Connection -** [Security](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#security), [Network Reachability](https://github.com/Alamofire/Alamofire/blob/master/Documentation/AdvancedUsage.md#network-reachability)
+- [Open Radars](#open-radars)
+- [FAQ](#faq)
+- [Credits](#credits)
+- [Donations](#donations)
+- [License](#license)
+
+## Features
+
+- [x] Chainable Request / Response Methods
+- [x] URL / JSON / plist Parameter Encoding
+- [x] Upload File / Data / Stream / MultipartFormData
+- [x] Download File using Request or Resume Data
+- [x] Authentication with URLCredential
+- [x] HTTP Response Validation
+- [x] Upload and Download Progress Closures with Progress
+- [x] cURL Command Output
+- [x] Dynamically Adapt and Retry Requests
+- [x] TLS Certificate and Public Key Pinning
+- [x] Network Reachability
+- [x] Comprehensive Unit and Integration Test Coverage
+- [x] [Complete Documentation](https://alamofire.github.io/Alamofire)
+
+## Component Libraries
+
+In order to keep Alamofire focused specifically on core networking implementations, additional component libraries have been created by the [Alamofire Software Foundation](https://github.com/Alamofire/Foundation) to bring additional functionality to the Alamofire ecosystem.
+
+- [AlamofireImage](https://github.com/Alamofire/AlamofireImage) - An image library including image response serializers, `UIImage` and `UIImageView` extensions, custom image filters, an auto-purging in-memory cache and a priority-based image downloading system.
+- [AlamofireNetworkActivityIndicator](https://github.com/Alamofire/AlamofireNetworkActivityIndicator) - Controls the visibility of the network activity indicator on iOS using Alamofire. It contains configurable delay timers to help mitigate flicker and can support `URLSession` instances not managed by Alamofire.
+
+## Requirements
+
+- iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+
+- Xcode 8.3+
+- Swift 3.1+
+
+## Migration Guides
+
+- [Alamofire 4.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%204.0%20Migration%20Guide.md)
+- [Alamofire 3.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%203.0%20Migration%20Guide.md)
+- [Alamofire 2.0 Migration Guide](https://github.com/Alamofire/Alamofire/blob/master/Documentation/Alamofire%202.0%20Migration%20Guide.md)
+
+## Communication
+- If you **need help with making network requests**, use [Stack Overflow](https://stackoverflow.com/questions/tagged/alamofire) and tag `alamofire`.
+- If you need to **find or understand an API**, check [our documentation](http://alamofire.github.io/Alamofire/) or [Apple's documentation for `URLSession`](https://developer.apple.com/documentation/foundation/url_loading_system), on top of which Alamofire is built.
+- If you need **help with an Alamofire feature**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
+- If you'd like to **discuss Alamofire best practices**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire).
+- If you'd like to **discuss a feature request**, use [our forum on swift.org](https://forums.swift.org/c/related-projects/alamofire). 
+- If you **found a bug**, open an issue and follow the guide. The more detail the better!
+- If you **want to contribute**, submit a pull request.
+
+## Installation
+
+### CocoaPods
+
+[CocoaPods](https://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command:
+
+```bash
+$ gem install cocoapods
+```
+
+> CocoaPods 1.1+ is required to build Alamofire 4.0+.
+
+To integrate Alamofire into your Xcode project using CocoaPods, specify it in your `Podfile`:
+
+```ruby
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '10.0'
+use_frameworks!
+
+target '<Your Target Name>' do
+    pod 'Alamofire', '~> 4.7'
+end
+```
+
+Then, run the following command:
+
+```bash
+$ pod install
+```
+
+### Carthage
+
+[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
+
+You can install Carthage with [Homebrew](https://brew.sh/) using the following command:
+
+```bash
+$ brew update
+$ brew install carthage
+```
+
+To integrate Alamofire into your Xcode project using Carthage, specify it in your `Cartfile`:
+
+```ogdl
+github "Alamofire/Alamofire" ~> 4.7
+```
+
+Run `carthage update` to build the framework and drag the built `Alamofire.framework` into your Xcode project.
+
+### Swift Package Manager
+
+The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Alamofire does support its use on supported platforms. 
+
+Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`.
+
+#### Swift 3
+
+```swift
+dependencies: [
+    .Package(url: "https://github.com/Alamofire/Alamofire.git", majorVersion: 4)
+]
+```
+
+#### Swift 4
+
+```swift
+dependencies: [
+    .package(url: "https://github.com/Alamofire/Alamofire.git", from: "4.0.0")
+]
+```
+
+### Manually
+
+If you prefer not to use any of the aforementioned dependency managers, you can integrate Alamofire into your project manually.
+
+#### Embedded Framework
+
+- Open up Terminal, `cd` into your top-level project directory, and run the following command "if" your project is not initialized as a git repository:
+
+  ```bash
+  $ git init
+  ```
+
+- Add Alamofire as a git [submodule](https://git-scm.com/docs/git-submodule) by running the following command:
+
+  ```bash
+  $ git submodule add https://github.com/Alamofire/Alamofire.git
+  ```
+
+- Open the new `Alamofire` folder, and drag the `Alamofire.xcodeproj` into the Project Navigator of your application's Xcode project.
+
+    > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter.
+
+- Select the `Alamofire.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target.
+- Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar.
+- In the tab bar at the top of that window, open the "General" panel.
+- Click on the `+` button under the "Embedded Binaries" section.
+- You will see two different `Alamofire.xcodeproj` folders each with two different versions of the `Alamofire.framework` nested inside a `Products` folder.
+
+    > It does not matter which `Products` folder you choose from, but it does matter whether you choose the top or bottom `Alamofire.framework`.
+
+- Select the top `Alamofire.framework` for iOS and the bottom one for OS X.
+
+    > You can verify which one you selected by inspecting the build log for your project. The build target for `Alamofire` will be listed as either `Alamofire iOS`, `Alamofire macOS`, `Alamofire tvOS` or `Alamofire watchOS`.
+
+- And that's it!
+
+  > The `Alamofire.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device.
+
+## Open Radars
+
+The following radars have some effect on the current implementation of Alamofire.
+
+- [`rdar://21349340`](http://www.openradar.me/radar?id=5517037090635776) - Compiler throwing warning due to toll-free bridging issue in test case
+- `rdar://26870455` - Background URL Session Configurations do not work in the simulator
+- `rdar://26849668` - Some URLProtocol APIs do not properly handle `URLRequest`
+- [`rdar://36082113`](http://openradar.appspot.com/radar?id=4942308441063424) - `URLSessionTaskMetrics` failing to link on watchOS 3.0+
+
+## Resolved Radars
+
+The following radars have been resolved over time after being filed against the Alamofire project.
+
+- [`rdar://26761490`](http://www.openradar.me/radar?id=5010235949318144) - Swift string interpolation causing memory leak with common usage (Resolved on 9/1/17 in Xcode 9 beta 6).
+
+## FAQ
+
+### What's the origin of the name Alamofire?
+
+Alamofire is named after the [Alamo Fire flower](https://aggie-horticulture.tamu.edu/wildseed/alamofire.html), a hybrid variant of the Bluebonnet, the official state flower of Texas.
+
+### What logic belongs in a Router vs. a Request Adapter?
+
+Simple, static data such as paths, parameters and common headers belong in the `Router`. Dynamic data such as an `Authorization` header whose value can changed based on an authentication system belongs in a `RequestAdapter`.
+
+The reason the dynamic data MUST be placed into the `RequestAdapter` is to support retry operations. When a `Request` is retried, the original request is not rebuilt meaning the `Router` will not be called again. The `RequestAdapter` is called again allowing the dynamic data to be updated on the original request before retrying the `Request`.
+
+## Credits
+
+Alamofire is owned and maintained by the [Alamofire Software Foundation](http://alamofire.org). You can follow them on Twitter at [@AlamofireSF](https://twitter.com/AlamofireSF) for project updates and releases.
+
+### Security Disclosure
+
+If you believe you have identified a security vulnerability with Alamofire, you should report it as soon as possible via email to security@alamofire.org. Please do not post it to a public issue tracker.
+
+## Donations
+
+The [ASF](https://github.com/Alamofire/Foundation#members) is looking to raise money to officially stay registered as a federal non-profit organization.
+Registering will allow us members to gain some legal protections and also allow us to put donations to use, tax free.
+Donating to the ASF will enable us to:
+
+- Pay our yearly legal fees to keep the non-profit in good status
+- Pay for our mail servers to help us stay on top of all questions and security issues
+- Potentially fund test servers to make it easier for us to test the edge cases
+- Potentially fund developers to work on one of our projects full-time
+
+The community adoption of the ASF libraries has been amazing.
+We are greatly humbled by your enthusiasm around the projects, and want to continue to do everything we can to move the needle forward.
+With your continued support, the ASF will be able to improve its reach and also provide better legal safety for the core members.
+If you use any of our libraries for work, see if your employers would be interested in donating.
+Any amount you can donate today to help us reach our goal would be greatly appreciated.
+
+[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=W34WPEE74APJQ)
+
+## License
+
+Alamofire is released under the MIT license. [See LICENSE](https://github.com/Alamofire/Alamofire/blob/master/LICENSE) for details.

+ 460 - 0
RainbowPlanet/Pods/Alamofire/Source/AFError.swift

@@ -0,0 +1,460 @@
+//
+//  AFError.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// `AFError` is the error type returned by Alamofire. It encompasses a few different types of errors, each with
+/// their own associated reasons.
+///
+/// - invalidURL:                  Returned when a `URLConvertible` type fails to create a valid `URL`.
+/// - parameterEncodingFailed:     Returned when a parameter encoding object throws an error during the encoding process.
+/// - multipartEncodingFailed:     Returned when some step in the multipart encoding process fails.
+/// - responseValidationFailed:    Returned when a `validate()` call fails.
+/// - responseSerializationFailed: Returned when a response serializer encounters an error in the serialization process.
+public enum AFError: Error {
+    /// The underlying reason the parameter encoding error occurred.
+    ///
+    /// - missingURL:                 The URL request did not have a URL to encode.
+    /// - jsonEncodingFailed:         JSON serialization failed with an underlying system error during the
+    ///                               encoding process.
+    /// - propertyListEncodingFailed: Property list serialization failed with an underlying system error during
+    ///                               encoding process.
+    public enum ParameterEncodingFailureReason {
+        case missingURL
+        case jsonEncodingFailed(error: Error)
+        case propertyListEncodingFailed(error: Error)
+    }
+
+    /// The underlying reason the multipart encoding error occurred.
+    ///
+    /// - bodyPartURLInvalid:                   The `fileURL` provided for reading an encodable body part isn't a
+    ///                                         file URL.
+    /// - bodyPartFilenameInvalid:              The filename of the `fileURL` provided has either an empty
+    ///                                         `lastPathComponent` or `pathExtension.
+    /// - bodyPartFileNotReachable:             The file at the `fileURL` provided was not reachable.
+    /// - bodyPartFileNotReachableWithError:    Attempting to check the reachability of the `fileURL` provided threw
+    ///                                         an error.
+    /// - bodyPartFileIsDirectory:              The file at the `fileURL` provided is actually a directory.
+    /// - bodyPartFileSizeNotAvailable:         The size of the file at the `fileURL` provided was not returned by
+    ///                                         the system.
+    /// - bodyPartFileSizeQueryFailedWithError: The attempt to find the size of the file at the `fileURL` provided
+    ///                                         threw an error.
+    /// - bodyPartInputStreamCreationFailed:    An `InputStream` could not be created for the provided `fileURL`.
+    /// - outputStreamCreationFailed:           An `OutputStream` could not be created when attempting to write the
+    ///                                         encoded data to disk.
+    /// - outputStreamFileAlreadyExists:        The encoded body data could not be writtent disk because a file
+    ///                                         already exists at the provided `fileURL`.
+    /// - outputStreamURLInvalid:               The `fileURL` provided for writing the encoded body data to disk is
+    ///                                         not a file URL.
+    /// - outputStreamWriteFailed:              The attempt to write the encoded body data to disk failed with an
+    ///                                         underlying error.
+    /// - inputStreamReadFailed:                The attempt to read an encoded body part `InputStream` failed with
+    ///                                         underlying system error.
+    public enum MultipartEncodingFailureReason {
+        case bodyPartURLInvalid(url: URL)
+        case bodyPartFilenameInvalid(in: URL)
+        case bodyPartFileNotReachable(at: URL)
+        case bodyPartFileNotReachableWithError(atURL: URL, error: Error)
+        case bodyPartFileIsDirectory(at: URL)
+        case bodyPartFileSizeNotAvailable(at: URL)
+        case bodyPartFileSizeQueryFailedWithError(forURL: URL, error: Error)
+        case bodyPartInputStreamCreationFailed(for: URL)
+
+        case outputStreamCreationFailed(for: URL)
+        case outputStreamFileAlreadyExists(at: URL)
+        case outputStreamURLInvalid(url: URL)
+        case outputStreamWriteFailed(error: Error)
+
+        case inputStreamReadFailed(error: Error)
+    }
+
+    /// The underlying reason the response validation error occurred.
+    ///
+    /// - dataFileNil:             The data file containing the server response did not exist.
+    /// - dataFileReadFailed:      The data file containing the server response could not be read.
+    /// - missingContentType:      The response did not contain a `Content-Type` and the `acceptableContentTypes`
+    ///                            provided did not contain wildcard type.
+    /// - unacceptableContentType: The response `Content-Type` did not match any type in the provided
+    ///                            `acceptableContentTypes`.
+    /// - unacceptableStatusCode:  The response status code was not acceptable.
+    public enum ResponseValidationFailureReason {
+        case dataFileNil
+        case dataFileReadFailed(at: URL)
+        case missingContentType(acceptableContentTypes: [String])
+        case unacceptableContentType(acceptableContentTypes: [String], responseContentType: String)
+        case unacceptableStatusCode(code: Int)
+    }
+
+    /// The underlying reason the response serialization error occurred.
+    ///
+    /// - inputDataNil:                    The server response contained no data.
+    /// - inputDataNilOrZeroLength:        The server response contained no data or the data was zero length.
+    /// - inputFileNil:                    The file containing the server response did not exist.
+    /// - inputFileReadFailed:             The file containing the server response could not be read.
+    /// - stringSerializationFailed:       String serialization failed using the provided `String.Encoding`.
+    /// - jsonSerializationFailed:         JSON serialization failed with an underlying system error.
+    /// - propertyListSerializationFailed: Property list serialization failed with an underlying system error.
+    public enum ResponseSerializationFailureReason {
+        case inputDataNil
+        case inputDataNilOrZeroLength
+        case inputFileNil
+        case inputFileReadFailed(at: URL)
+        case stringSerializationFailed(encoding: String.Encoding)
+        case jsonSerializationFailed(error: Error)
+        case propertyListSerializationFailed(error: Error)
+    }
+
+    case invalidURL(url: URLConvertible)
+    case parameterEncodingFailed(reason: ParameterEncodingFailureReason)
+    case multipartEncodingFailed(reason: MultipartEncodingFailureReason)
+    case responseValidationFailed(reason: ResponseValidationFailureReason)
+    case responseSerializationFailed(reason: ResponseSerializationFailureReason)
+}
+
+// MARK: - Adapt Error
+
+struct AdaptError: Error {
+    let error: Error
+}
+
+extension Error {
+    var underlyingAdaptError: Error? { return (self as? AdaptError)?.error }
+}
+
+// MARK: - Error Booleans
+
+extension AFError {
+    /// Returns whether the AFError is an invalid URL error.
+    public var isInvalidURLError: Bool {
+        if case .invalidURL = self { return true }
+        return false
+    }
+
+    /// Returns whether the AFError is a parameter encoding error. When `true`, the `underlyingError` property will
+    /// contain the associated value.
+    public var isParameterEncodingError: Bool {
+        if case .parameterEncodingFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the AFError is a multipart encoding error. When `true`, the `url` and `underlyingError` properties
+    /// will contain the associated values.
+    public var isMultipartEncodingError: Bool {
+        if case .multipartEncodingFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the `AFError` is a response validation error. When `true`, the `acceptableContentTypes`,
+    /// `responseContentType`, and `responseCode` properties will contain the associated values.
+    public var isResponseValidationError: Bool {
+        if case .responseValidationFailed = self { return true }
+        return false
+    }
+
+    /// Returns whether the `AFError` is a response serialization error. When `true`, the `failedStringEncoding` and
+    /// `underlyingError` properties will contain the associated values.
+    public var isResponseSerializationError: Bool {
+        if case .responseSerializationFailed = self { return true }
+        return false
+    }
+}
+
+// MARK: - Convenience Properties
+
+extension AFError {
+    /// The `URLConvertible` associated with the error.
+    public var urlConvertible: URLConvertible? {
+        switch self {
+        case .invalidURL(let url):
+            return url
+        default:
+            return nil
+        }
+    }
+
+    /// The `URL` associated with the error.
+    public var url: URL? {
+        switch self {
+        case .multipartEncodingFailed(let reason):
+            return reason.url
+        default:
+            return nil
+        }
+    }
+
+    /// The `Error` returned by a system framework associated with a `.parameterEncodingFailed`,
+    /// `.multipartEncodingFailed` or `.responseSerializationFailed` error.
+    public var underlyingError: Error? {
+        switch self {
+        case .parameterEncodingFailed(let reason):
+            return reason.underlyingError
+        case .multipartEncodingFailed(let reason):
+            return reason.underlyingError
+        case .responseSerializationFailed(let reason):
+            return reason.underlyingError
+        default:
+            return nil
+        }
+    }
+
+    /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.
+    public var acceptableContentTypes: [String]? {
+        switch self {
+        case .responseValidationFailed(let reason):
+            return reason.acceptableContentTypes
+        default:
+            return nil
+        }
+    }
+
+    /// The response `Content-Type` of a `.responseValidationFailed` error.
+    public var responseContentType: String? {
+        switch self {
+        case .responseValidationFailed(let reason):
+            return reason.responseContentType
+        default:
+            return nil
+        }
+    }
+
+    /// The response code of a `.responseValidationFailed` error.
+    public var responseCode: Int? {
+        switch self {
+        case .responseValidationFailed(let reason):
+            return reason.responseCode
+        default:
+            return nil
+        }
+    }
+
+    /// The `String.Encoding` associated with a failed `.stringResponse()` call.
+    public var failedStringEncoding: String.Encoding? {
+        switch self {
+        case .responseSerializationFailed(let reason):
+            return reason.failedStringEncoding
+        default:
+            return nil
+        }
+    }
+}
+
+extension AFError.ParameterEncodingFailureReason {
+    var underlyingError: Error? {
+        switch self {
+        case .jsonEncodingFailed(let error), .propertyListEncodingFailed(let error):
+            return error
+        default:
+            return nil
+        }
+    }
+}
+
+extension AFError.MultipartEncodingFailureReason {
+    var url: URL? {
+        switch self {
+        case .bodyPartURLInvalid(let url), .bodyPartFilenameInvalid(let url), .bodyPartFileNotReachable(let url),
+             .bodyPartFileIsDirectory(let url), .bodyPartFileSizeNotAvailable(let url),
+             .bodyPartInputStreamCreationFailed(let url), .outputStreamCreationFailed(let url),
+             .outputStreamFileAlreadyExists(let url), .outputStreamURLInvalid(let url),
+             .bodyPartFileNotReachableWithError(let url, _), .bodyPartFileSizeQueryFailedWithError(let url, _):
+            return url
+        default:
+            return nil
+        }
+    }
+
+    var underlyingError: Error? {
+        switch self {
+        case .bodyPartFileNotReachableWithError(_, let error), .bodyPartFileSizeQueryFailedWithError(_, let error),
+             .outputStreamWriteFailed(let error), .inputStreamReadFailed(let error):
+            return error
+        default:
+            return nil
+        }
+    }
+}
+
+extension AFError.ResponseValidationFailureReason {
+    var acceptableContentTypes: [String]? {
+        switch self {
+        case .missingContentType(let types), .unacceptableContentType(let types, _):
+            return types
+        default:
+            return nil
+        }
+    }
+
+    var responseContentType: String? {
+        switch self {
+        case .unacceptableContentType(_, let responseType):
+            return responseType
+        default:
+            return nil
+        }
+    }
+
+    var responseCode: Int? {
+        switch self {
+        case .unacceptableStatusCode(let code):
+            return code
+        default:
+            return nil
+        }
+    }
+}
+
+extension AFError.ResponseSerializationFailureReason {
+    var failedStringEncoding: String.Encoding? {
+        switch self {
+        case .stringSerializationFailed(let encoding):
+            return encoding
+        default:
+            return nil
+        }
+    }
+
+    var underlyingError: Error? {
+        switch self {
+        case .jsonSerializationFailed(let error), .propertyListSerializationFailed(let error):
+            return error
+        default:
+            return nil
+        }
+    }
+}
+
+// MARK: - Error Descriptions
+
+extension AFError: LocalizedError {
+    public var errorDescription: String? {
+        switch self {
+        case .invalidURL(let url):
+            return "URL is not valid: \(url)"
+        case .parameterEncodingFailed(let reason):
+            return reason.localizedDescription
+        case .multipartEncodingFailed(let reason):
+            return reason.localizedDescription
+        case .responseValidationFailed(let reason):
+            return reason.localizedDescription
+        case .responseSerializationFailed(let reason):
+            return reason.localizedDescription
+        }
+    }
+}
+
+extension AFError.ParameterEncodingFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .missingURL:
+            return "URL request to encode was missing a URL"
+        case .jsonEncodingFailed(let error):
+            return "JSON could not be encoded because of error:\n\(error.localizedDescription)"
+        case .propertyListEncodingFailed(let error):
+            return "PropertyList could not be encoded because of error:\n\(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.MultipartEncodingFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .bodyPartURLInvalid(let url):
+            return "The URL provided is not a file URL: \(url)"
+        case .bodyPartFilenameInvalid(let url):
+            return "The URL provided does not have a valid filename: \(url)"
+        case .bodyPartFileNotReachable(let url):
+            return "The URL provided is not reachable: \(url)"
+        case .bodyPartFileNotReachableWithError(let url, let error):
+            return (
+                "The system returned an error while checking the provided URL for " +
+                "reachability.\nURL: \(url)\nError: \(error)"
+            )
+        case .bodyPartFileIsDirectory(let url):
+            return "The URL provided is a directory: \(url)"
+        case .bodyPartFileSizeNotAvailable(let url):
+            return "Could not fetch the file size from the provided URL: \(url)"
+        case .bodyPartFileSizeQueryFailedWithError(let url, let error):
+            return (
+                "The system returned an error while attempting to fetch the file size from the " +
+                "provided URL.\nURL: \(url)\nError: \(error)"
+            )
+        case .bodyPartInputStreamCreationFailed(let url):
+            return "Failed to create an InputStream for the provided URL: \(url)"
+        case .outputStreamCreationFailed(let url):
+            return "Failed to create an OutputStream for URL: \(url)"
+        case .outputStreamFileAlreadyExists(let url):
+            return "A file already exists at the provided URL: \(url)"
+        case .outputStreamURLInvalid(let url):
+            return "The provided OutputStream URL is invalid: \(url)"
+        case .outputStreamWriteFailed(let error):
+            return "OutputStream write failed with error: \(error)"
+        case .inputStreamReadFailed(let error):
+            return "InputStream read failed with error: \(error)"
+        }
+    }
+}
+
+extension AFError.ResponseSerializationFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .inputDataNil:
+            return "Response could not be serialized, input data was nil."
+        case .inputDataNilOrZeroLength:
+            return "Response could not be serialized, input data was nil or zero length."
+        case .inputFileNil:
+            return "Response could not be serialized, input file was nil."
+        case .inputFileReadFailed(let url):
+            return "Response could not be serialized, input file could not be read: \(url)."
+        case .stringSerializationFailed(let encoding):
+            return "String could not be serialized with encoding: \(encoding)."
+        case .jsonSerializationFailed(let error):
+            return "JSON could not be serialized because of error:\n\(error.localizedDescription)"
+        case .propertyListSerializationFailed(let error):
+            return "PropertyList could not be serialized because of error:\n\(error.localizedDescription)"
+        }
+    }
+}
+
+extension AFError.ResponseValidationFailureReason {
+    var localizedDescription: String {
+        switch self {
+        case .dataFileNil:
+            return "Response could not be validated, data file was nil."
+        case .dataFileReadFailed(let url):
+            return "Response could not be validated, data file could not be read: \(url)."
+        case .missingContentType(let types):
+            return (
+                "Response Content-Type was missing and acceptable content types " +
+                "(\(types.joined(separator: ","))) do not match \"*/*\"."
+            )
+        case .unacceptableContentType(let acceptableTypes, let responseType):
+            return (
+                "Response Content-Type \"\(responseType)\" does not match any acceptable types: " +
+                "\(acceptableTypes.joined(separator: ","))."
+            )
+        case .unacceptableStatusCode(let code):
+            return "Response status code was unacceptable: \(code)."
+        }
+    }
+}

+ 465 - 0
RainbowPlanet/Pods/Alamofire/Source/Alamofire.swift

@@ -0,0 +1,465 @@
+//
+//  Alamofire.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Types adopting the `URLConvertible` protocol can be used to construct URLs, which are then used to construct
+/// URL requests.
+public protocol URLConvertible {
+    /// Returns a URL that conforms to RFC 2396 or throws an `Error`.
+    ///
+    /// - throws: An `Error` if the type cannot be converted to a `URL`.
+    ///
+    /// - returns: A URL or throws an `Error`.
+    func asURL() throws -> URL
+}
+
+extension String: URLConvertible {
+    /// Returns a URL if `self` represents a valid URL string that conforms to RFC 2396 or throws an `AFError`.
+    ///
+    /// - throws: An `AFError.invalidURL` if `self` is not a valid URL string.
+    ///
+    /// - returns: A URL or throws an `AFError`.
+    public func asURL() throws -> URL {
+        guard let url = URL(string: self) else { throw AFError.invalidURL(url: self) }
+        return url
+    }
+}
+
+extension URL: URLConvertible {
+    /// Returns self.
+    public func asURL() throws -> URL { return self }
+}
+
+extension URLComponents: URLConvertible {
+    /// Returns a URL if `url` is not nil, otherwise throws an `Error`.
+    ///
+    /// - throws: An `AFError.invalidURL` if `url` is `nil`.
+    ///
+    /// - returns: A URL or throws an `AFError`.
+    public func asURL() throws -> URL {
+        guard let url = url else { throw AFError.invalidURL(url: self) }
+        return url
+    }
+}
+
+// MARK: -
+
+/// Types adopting the `URLRequestConvertible` protocol can be used to construct URL requests.
+public protocol URLRequestConvertible {
+    /// Returns a URL request or throws if an `Error` was encountered.
+    ///
+    /// - throws: An `Error` if the underlying `URLRequest` is `nil`.
+    ///
+    /// - returns: A URL request.
+    func asURLRequest() throws -> URLRequest
+}
+
+extension URLRequestConvertible {
+    /// The URL request.
+    public var urlRequest: URLRequest? { return try? asURLRequest() }
+}
+
+extension URLRequest: URLRequestConvertible {
+    /// Returns a URL request or throws if an `Error` was encountered.
+    public func asURLRequest() throws -> URLRequest { return self }
+}
+
+// MARK: -
+
+extension URLRequest {
+    /// Creates an instance with the specified `method`, `urlString` and `headers`.
+    ///
+    /// - parameter url:     The URL.
+    /// - parameter method:  The HTTP method.
+    /// - parameter headers: The HTTP headers. `nil` by default.
+    ///
+    /// - returns: The new `URLRequest` instance.
+    public init(url: URLConvertible, method: HTTPMethod, headers: HTTPHeaders? = nil) throws {
+        let url = try url.asURL()
+
+        self.init(url: url)
+
+        httpMethod = method.rawValue
+
+        if let headers = headers {
+            for (headerField, headerValue) in headers {
+                setValue(headerValue, forHTTPHeaderField: headerField)
+            }
+        }
+    }
+
+    func adapt(using adapter: RequestAdapter?) throws -> URLRequest {
+        guard let adapter = adapter else { return self }
+        return try adapter.adapt(self)
+    }
+}
+
+// MARK: - Data Request
+
+/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of the specified `url`,
+/// `method`, `parameters`, `encoding` and `headers`.
+///
+/// - parameter url:        The URL.
+/// - parameter method:     The HTTP method. `.get` by default.
+/// - parameter parameters: The parameters. `nil` by default.
+/// - parameter encoding:   The parameter encoding. `URLEncoding.default` by default.
+/// - parameter headers:    The HTTP headers. `nil` by default.
+///
+/// - returns: The created `DataRequest`.
+@discardableResult
+public func request(
+    _ url: URLConvertible,
+    method: HTTPMethod = .get,
+    parameters: Parameters? = nil,
+    encoding: ParameterEncoding = URLEncoding.default,
+    headers: HTTPHeaders? = nil)
+    -> DataRequest
+{
+    return SessionManager.default.request(
+        url,
+        method: method,
+        parameters: parameters,
+        encoding: encoding,
+        headers: headers
+    )
+}
+
+/// Creates a `DataRequest` using the default `SessionManager` to retrieve the contents of a URL based on the
+/// specified `urlRequest`.
+///
+/// - parameter urlRequest: The URL request
+///
+/// - returns: The created `DataRequest`.
+@discardableResult
+public func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
+    return SessionManager.default.request(urlRequest)
+}
+
+// MARK: - Download Request
+
+// MARK: URL Request
+
+/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of the specified `url`,
+/// `method`, `parameters`, `encoding`, `headers` and save them to the `destination`.
+///
+/// If `destination` is not specified, the contents will remain in the temporary location determined by the
+/// underlying URL session.
+///
+/// - parameter url:         The URL.
+/// - parameter method:      The HTTP method. `.get` by default.
+/// - parameter parameters:  The parameters. `nil` by default.
+/// - parameter encoding:    The parameter encoding. `URLEncoding.default` by default.
+/// - parameter headers:     The HTTP headers. `nil` by default.
+/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
+///
+/// - returns: The created `DownloadRequest`.
+@discardableResult
+public func download(
+    _ url: URLConvertible,
+    method: HTTPMethod = .get,
+    parameters: Parameters? = nil,
+    encoding: ParameterEncoding = URLEncoding.default,
+    headers: HTTPHeaders? = nil,
+    to destination: DownloadRequest.DownloadFileDestination? = nil)
+    -> DownloadRequest
+{
+    return SessionManager.default.download(
+        url,
+        method: method,
+        parameters: parameters,
+        encoding: encoding,
+        headers: headers,
+        to: destination
+    )
+}
+
+/// Creates a `DownloadRequest` using the default `SessionManager` to retrieve the contents of a URL based on the
+/// specified `urlRequest` and save them to the `destination`.
+///
+/// If `destination` is not specified, the contents will remain in the temporary location determined by the
+/// underlying URL session.
+///
+/// - parameter urlRequest:  The URL request.
+/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
+///
+/// - returns: The created `DownloadRequest`.
+@discardableResult
+public func download(
+    _ urlRequest: URLRequestConvertible,
+    to destination: DownloadRequest.DownloadFileDestination? = nil)
+    -> DownloadRequest
+{
+    return SessionManager.default.download(urlRequest, to: destination)
+}
+
+// MARK: Resume Data
+
+/// Creates a `DownloadRequest` using the default `SessionManager` from the `resumeData` produced from a
+/// previous request cancellation to retrieve the contents of the original request and save them to the `destination`.
+///
+/// If `destination` is not specified, the contents will remain in the temporary location determined by the
+/// underlying URL session.
+///
+/// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken
+/// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the
+/// data is written incorrectly and will always fail to resume the download. For more information about the bug and
+/// possible workarounds, please refer to the following Stack Overflow post:
+///
+///    - http://stackoverflow.com/a/39347461/1342462
+///
+/// - parameter resumeData:  The resume data. This is an opaque data blob produced by `URLSessionDownloadTask`
+///                          when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for additional
+///                          information.
+/// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
+///
+/// - returns: The created `DownloadRequest`.
+@discardableResult
+public func download(
+    resumingWith resumeData: Data,
+    to destination: DownloadRequest.DownloadFileDestination? = nil)
+    -> DownloadRequest
+{
+    return SessionManager.default.download(resumingWith: resumeData, to: destination)
+}
+
+// MARK: - Upload Request
+
+// MARK: File
+
+/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers`
+/// for uploading the `file`.
+///
+/// - parameter file:    The file to upload.
+/// - parameter url:     The URL.
+/// - parameter method:  The HTTP method. `.post` by default.
+/// - parameter headers: The HTTP headers. `nil` by default.
+///
+/// - returns: The created `UploadRequest`.
+@discardableResult
+public func upload(
+    _ fileURL: URL,
+    to url: URLConvertible,
+    method: HTTPMethod = .post,
+    headers: HTTPHeaders? = nil)
+    -> UploadRequest
+{
+    return SessionManager.default.upload(fileURL, to: url, method: method, headers: headers)
+}
+
+/// Creates a `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for
+/// uploading the `file`.
+///
+/// - parameter file:       The file to upload.
+/// - parameter urlRequest: The URL request.
+///
+/// - returns: The created `UploadRequest`.
+@discardableResult
+public func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest {
+    return SessionManager.default.upload(fileURL, with: urlRequest)
+}
+
+// MARK: Data
+
+/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers`
+/// for uploading the `data`.
+///
+/// - parameter data:    The data to upload.
+/// - parameter url:     The URL.
+/// - parameter method:  The HTTP method. `.post` by default.
+/// - parameter headers: The HTTP headers. `nil` by default.
+///
+/// - returns: The created `UploadRequest`.
+@discardableResult
+public func upload(
+    _ data: Data,
+    to url: URLConvertible,
+    method: HTTPMethod = .post,
+    headers: HTTPHeaders? = nil)
+    -> UploadRequest
+{
+    return SessionManager.default.upload(data, to: url, method: method, headers: headers)
+}
+
+/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for
+/// uploading the `data`.
+///
+/// - parameter data:       The data to upload.
+/// - parameter urlRequest: The URL request.
+///
+/// - returns: The created `UploadRequest`.
+@discardableResult
+public func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
+    return SessionManager.default.upload(data, with: urlRequest)
+}
+
+// MARK: InputStream
+
+/// Creates an `UploadRequest` using the default `SessionManager` from the specified `url`, `method` and `headers`
+/// for uploading the `stream`.
+///
+/// - parameter stream:  The stream to upload.
+/// - parameter url:     The URL.
+/// - parameter method:  The HTTP method. `.post` by default.
+/// - parameter headers: The HTTP headers. `nil` by default.
+///
+/// - returns: The created `UploadRequest`.
+@discardableResult
+public func upload(
+    _ stream: InputStream,
+    to url: URLConvertible,
+    method: HTTPMethod = .post,
+    headers: HTTPHeaders? = nil)
+    -> UploadRequest
+{
+    return SessionManager.default.upload(stream, to: url, method: method, headers: headers)
+}
+
+/// Creates an `UploadRequest` using the default `SessionManager` from the specified `urlRequest` for
+/// uploading the `stream`.
+///
+/// - parameter urlRequest: The URL request.
+/// - parameter stream:     The stream to upload.
+///
+/// - returns: The created `UploadRequest`.
+@discardableResult
+public func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest {
+    return SessionManager.default.upload(stream, with: urlRequest)
+}
+
+// MARK: MultipartFormData
+
+/// Encodes `multipartFormData` using `encodingMemoryThreshold` with the default `SessionManager` and calls
+/// `encodingCompletion` with new `UploadRequest` using the `url`, `method` and `headers`.
+///
+/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
+/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
+/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
+/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
+/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
+/// used for larger payloads such as video content.
+///
+/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
+/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
+/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
+/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
+/// technique was used.
+///
+/// - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+///                                      `multipartFormDataEncodingMemoryThreshold` by default.
+/// - parameter url:                     The URL.
+/// - parameter method:                  The HTTP method. `.post` by default.
+/// - parameter headers:                 The HTTP headers. `nil` by default.
+/// - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+public func upload(
+    multipartFormData: @escaping (MultipartFormData) -> Void,
+    usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
+    to url: URLConvertible,
+    method: HTTPMethod = .post,
+    headers: HTTPHeaders? = nil,
+    encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?)
+{
+    return SessionManager.default.upload(
+        multipartFormData: multipartFormData,
+        usingThreshold: encodingMemoryThreshold,
+        to: url,
+        method: method,
+        headers: headers,
+        encodingCompletion: encodingCompletion
+    )
+}
+
+/// Encodes `multipartFormData` using `encodingMemoryThreshold` and the default `SessionManager` and
+/// calls `encodingCompletion` with new `UploadRequest` using the `urlRequest`.
+///
+/// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
+/// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
+/// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
+/// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
+/// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
+/// used for larger payloads such as video content.
+///
+/// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
+/// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
+/// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
+/// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
+/// technique was used.
+///
+/// - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+/// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+///                                      `multipartFormDataEncodingMemoryThreshold` by default.
+/// - parameter urlRequest:              The URL request.
+/// - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+public func upload(
+    multipartFormData: @escaping (MultipartFormData) -> Void,
+    usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
+    with urlRequest: URLRequestConvertible,
+    encodingCompletion: ((SessionManager.MultipartFormDataEncodingResult) -> Void)?)
+{
+    return SessionManager.default.upload(
+        multipartFormData: multipartFormData,
+        usingThreshold: encodingMemoryThreshold,
+        with: urlRequest,
+        encodingCompletion: encodingCompletion
+    )
+}
+
+#if !os(watchOS)
+
+// MARK: - Stream Request
+
+// MARK: Hostname and Port
+
+/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `hostname`
+/// and `port`.
+///
+/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+///
+/// - parameter hostName: The hostname of the server to connect to.
+/// - parameter port:     The port of the server to connect to.
+///
+/// - returns: The created `StreamRequest`.
+@discardableResult
+@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+public func stream(withHostName hostName: String, port: Int) -> StreamRequest {
+    return SessionManager.default.stream(withHostName: hostName, port: port)
+}
+
+// MARK: NetService
+
+/// Creates a `StreamRequest` using the default `SessionManager` for bidirectional streaming with the `netService`.
+///
+/// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+///
+/// - parameter netService: The net service used to identify the endpoint.
+///
+/// - returns: The created `StreamRequest`.
+@discardableResult
+@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+public func stream(with netService: NetService) -> StreamRequest {
+    return SessionManager.default.stream(with: netService)
+}
+
+#endif

+ 37 - 0
RainbowPlanet/Pods/Alamofire/Source/DispatchQueue+Alamofire.swift

@@ -0,0 +1,37 @@
+//
+//  DispatchQueue+Alamofire.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Dispatch
+import Foundation
+
+extension DispatchQueue {
+    static var userInteractive: DispatchQueue { return DispatchQueue.global(qos: .userInteractive) }
+    static var userInitiated: DispatchQueue { return DispatchQueue.global(qos: .userInitiated) }
+    static var utility: DispatchQueue { return DispatchQueue.global(qos: .utility) }
+    static var background: DispatchQueue { return DispatchQueue.global(qos: .background) }
+
+    func after(_ delay: TimeInterval, execute closure: @escaping () -> Void) {
+        asyncAfter(deadline: .now() + delay, execute: closure)
+    }
+}

+ 580 - 0
RainbowPlanet/Pods/Alamofire/Source/MultipartFormData.swift

@@ -0,0 +1,580 @@
+//
+//  MultipartFormData.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+#if os(iOS) || os(watchOS) || os(tvOS)
+import MobileCoreServices
+#elseif os(macOS)
+import CoreServices
+#endif
+
+/// Constructs `multipart/form-data` for uploads within an HTTP or HTTPS body. There are currently two ways to encode
+/// multipart form data. The first way is to encode the data directly in memory. This is very efficient, but can lead
+/// to memory issues if the dataset is too large. The second way is designed for larger datasets and will write all the
+/// data to a single file on disk with all the proper boundary segmentation. The second approach MUST be used for
+/// larger datasets such as video content, otherwise your app may run out of memory when trying to encode the dataset.
+///
+/// For more information on `multipart/form-data` in general, please refer to the RFC-2388 and RFC-2045 specs as well
+/// and the w3 form documentation.
+///
+/// - https://www.ietf.org/rfc/rfc2388.txt
+/// - https://www.ietf.org/rfc/rfc2045.txt
+/// - https://www.w3.org/TR/html401/interact/forms.html#h-17.13
+open class MultipartFormData {
+
+    // MARK: - Helper Types
+
+    struct EncodingCharacters {
+        static let crlf = "\r\n"
+    }
+
+    struct BoundaryGenerator {
+        enum BoundaryType {
+            case initial, encapsulated, final
+        }
+
+        static func randomBoundary() -> String {
+            return String(format: "alamofire.boundary.%08x%08x", arc4random(), arc4random())
+        }
+
+        static func boundaryData(forBoundaryType boundaryType: BoundaryType, boundary: String) -> Data {
+            let boundaryText: String
+
+            switch boundaryType {
+            case .initial:
+                boundaryText = "--\(boundary)\(EncodingCharacters.crlf)"
+            case .encapsulated:
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)\(EncodingCharacters.crlf)"
+            case .final:
+                boundaryText = "\(EncodingCharacters.crlf)--\(boundary)--\(EncodingCharacters.crlf)"
+            }
+
+            return boundaryText.data(using: String.Encoding.utf8, allowLossyConversion: false)!
+        }
+    }
+
+    class BodyPart {
+        let headers: HTTPHeaders
+        let bodyStream: InputStream
+        let bodyContentLength: UInt64
+        var hasInitialBoundary = false
+        var hasFinalBoundary = false
+
+        init(headers: HTTPHeaders, bodyStream: InputStream, bodyContentLength: UInt64) {
+            self.headers = headers
+            self.bodyStream = bodyStream
+            self.bodyContentLength = bodyContentLength
+        }
+    }
+
+    // MARK: - Properties
+
+    /// The `Content-Type` header value containing the boundary used to generate the `multipart/form-data`.
+    open lazy var contentType: String = "multipart/form-data; boundary=\(self.boundary)"
+
+    /// The content length of all body parts used to generate the `multipart/form-data` not including the boundaries.
+    public var contentLength: UInt64 { return bodyParts.reduce(0) { $0 + $1.bodyContentLength } }
+
+    /// The boundary used to separate the body parts in the encoded form data.
+    public let boundary: String
+
+    private var bodyParts: [BodyPart]
+    private var bodyPartError: AFError?
+    private let streamBufferSize: Int
+
+    // MARK: - Lifecycle
+
+    /// Creates a multipart form data object.
+    ///
+    /// - returns: The multipart form data object.
+    public init() {
+        self.boundary = BoundaryGenerator.randomBoundary()
+        self.bodyParts = []
+
+        ///
+        /// The optimal read/write buffer size in bytes for input and output streams is 1024 (1KB). For more
+        /// information, please refer to the following article:
+        ///   - https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html
+        ///
+
+        self.streamBufferSize = 1024
+    }
+
+    // MARK: - Body Parts
+
+    /// Creates a body part from the data and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}` (HTTP Header)
+    /// - Encoded data
+    /// - Multipart form boundary
+    ///
+    /// - parameter data: The data to encode into the multipart form data.
+    /// - parameter name: The name to associate with the data in the `Content-Disposition` HTTP header.
+    public func append(_ data: Data, withName name: String) {
+        let headers = contentHeaders(withName: name)
+        let stream = InputStream(data: data)
+        let length = UInt64(data.count)
+
+        append(stream, withLength: length, headers: headers)
+    }
+
+    /// Creates a body part from the data and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}` (HTTP Header)
+    /// - `Content-Type: #{generated mimeType}` (HTTP Header)
+    /// - Encoded data
+    /// - Multipart form boundary
+    ///
+    /// - parameter data:     The data to encode into the multipart form data.
+    /// - parameter name:     The name to associate with the data in the `Content-Disposition` HTTP header.
+    /// - parameter mimeType: The MIME type to associate with the data content type in the `Content-Type` HTTP header.
+    public func append(_ data: Data, withName name: String, mimeType: String) {
+        let headers = contentHeaders(withName: name, mimeType: mimeType)
+        let stream = InputStream(data: data)
+        let length = UInt64(data.count)
+
+        append(stream, withLength: length, headers: headers)
+    }
+
+    /// Creates a body part from the data and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
+    /// - Encoded file data
+    /// - Multipart form boundary
+    ///
+    /// - parameter data:     The data to encode into the multipart form data.
+    /// - parameter name:     The name to associate with the data in the `Content-Disposition` HTTP header.
+    /// - parameter fileName: The filename to associate with the data in the `Content-Disposition` HTTP header.
+    /// - parameter mimeType: The MIME type to associate with the data in the `Content-Type` HTTP header.
+    public func append(_ data: Data, withName name: String, fileName: String, mimeType: String) {
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
+        let stream = InputStream(data: data)
+        let length = UInt64(data.count)
+
+        append(stream, withLength: length, headers: headers)
+    }
+
+    /// Creates a body part from the file and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{generated filename}` (HTTP Header)
+    /// - `Content-Type: #{generated mimeType}` (HTTP Header)
+    /// - Encoded file data
+    /// - Multipart form boundary
+    ///
+    /// The filename in the `Content-Disposition` HTTP header is generated from the last path component of the
+    /// `fileURL`. The `Content-Type` HTTP header MIME type is generated by mapping the `fileURL` extension to the
+    /// system associated MIME type.
+    ///
+    /// - parameter fileURL: The URL of the file whose content will be encoded into the multipart form data.
+    /// - parameter name:    The name to associate with the file content in the `Content-Disposition` HTTP header.
+    public func append(_ fileURL: URL, withName name: String) {
+        let fileName = fileURL.lastPathComponent
+        let pathExtension = fileURL.pathExtension
+
+        if !fileName.isEmpty && !pathExtension.isEmpty {
+            let mime = mimeType(forPathExtension: pathExtension)
+            append(fileURL, withName: name, fileName: fileName, mimeType: mime)
+        } else {
+            setBodyPartError(withReason: .bodyPartFilenameInvalid(in: fileURL))
+        }
+    }
+
+    /// Creates a body part from the file and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - Content-Disposition: form-data; name=#{name}; filename=#{filename} (HTTP Header)
+    /// - Content-Type: #{mimeType} (HTTP Header)
+    /// - Encoded file data
+    /// - Multipart form boundary
+    ///
+    /// - parameter fileURL:  The URL of the file whose content will be encoded into the multipart form data.
+    /// - parameter name:     The name to associate with the file content in the `Content-Disposition` HTTP header.
+    /// - parameter fileName: The filename to associate with the file content in the `Content-Disposition` HTTP header.
+    /// - parameter mimeType: The MIME type to associate with the file content in the `Content-Type` HTTP header.
+    public func append(_ fileURL: URL, withName name: String, fileName: String, mimeType: String) {
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
+
+        //============================================================
+        //                 Check 1 - is file URL?
+        //============================================================
+
+        guard fileURL.isFileURL else {
+            setBodyPartError(withReason: .bodyPartURLInvalid(url: fileURL))
+            return
+        }
+
+        //============================================================
+        //              Check 2 - is file URL reachable?
+        //============================================================
+
+        do {
+            let isReachable = try fileURL.checkPromisedItemIsReachable()
+            guard isReachable else {
+                setBodyPartError(withReason: .bodyPartFileNotReachable(at: fileURL))
+                return
+            }
+        } catch {
+            setBodyPartError(withReason: .bodyPartFileNotReachableWithError(atURL: fileURL, error: error))
+            return
+        }
+
+        //============================================================
+        //            Check 3 - is file URL a directory?
+        //============================================================
+
+        var isDirectory: ObjCBool = false
+        let path = fileURL.path
+
+        guard FileManager.default.fileExists(atPath: path, isDirectory: &isDirectory) && !isDirectory.boolValue else {
+            setBodyPartError(withReason: .bodyPartFileIsDirectory(at: fileURL))
+            return
+        }
+
+        //============================================================
+        //          Check 4 - can the file size be extracted?
+        //============================================================
+
+        let bodyContentLength: UInt64
+
+        do {
+            guard let fileSize = try FileManager.default.attributesOfItem(atPath: path)[.size] as? NSNumber else {
+                setBodyPartError(withReason: .bodyPartFileSizeNotAvailable(at: fileURL))
+                return
+            }
+
+            bodyContentLength = fileSize.uint64Value
+        }
+        catch {
+            setBodyPartError(withReason: .bodyPartFileSizeQueryFailedWithError(forURL: fileURL, error: error))
+            return
+        }
+
+        //============================================================
+        //       Check 5 - can a stream be created from file URL?
+        //============================================================
+
+        guard let stream = InputStream(url: fileURL) else {
+            setBodyPartError(withReason: .bodyPartInputStreamCreationFailed(for: fileURL))
+            return
+        }
+
+        append(stream, withLength: bodyContentLength, headers: headers)
+    }
+
+    /// Creates a body part from the stream and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - `Content-Disposition: form-data; name=#{name}; filename=#{filename}` (HTTP Header)
+    /// - `Content-Type: #{mimeType}` (HTTP Header)
+    /// - Encoded stream data
+    /// - Multipart form boundary
+    ///
+    /// - parameter stream:   The input stream to encode in the multipart form data.
+    /// - parameter length:   The content length of the stream.
+    /// - parameter name:     The name to associate with the stream content in the `Content-Disposition` HTTP header.
+    /// - parameter fileName: The filename to associate with the stream content in the `Content-Disposition` HTTP header.
+    /// - parameter mimeType: The MIME type to associate with the stream content in the `Content-Type` HTTP header.
+    public func append(
+        _ stream: InputStream,
+        withLength length: UInt64,
+        name: String,
+        fileName: String,
+        mimeType: String)
+    {
+        let headers = contentHeaders(withName: name, fileName: fileName, mimeType: mimeType)
+        append(stream, withLength: length, headers: headers)
+    }
+
+    /// Creates a body part with the headers, stream and length and appends it to the multipart form data object.
+    ///
+    /// The body part data will be encoded using the following format:
+    ///
+    /// - HTTP headers
+    /// - Encoded stream data
+    /// - Multipart form boundary
+    ///
+    /// - parameter stream:  The input stream to encode in the multipart form data.
+    /// - parameter length:  The content length of the stream.
+    /// - parameter headers: The HTTP headers for the body part.
+    public func append(_ stream: InputStream, withLength length: UInt64, headers: HTTPHeaders) {
+        let bodyPart = BodyPart(headers: headers, bodyStream: stream, bodyContentLength: length)
+        bodyParts.append(bodyPart)
+    }
+
+    // MARK: - Data Encoding
+
+    /// Encodes all the appended body parts into a single `Data` value.
+    ///
+    /// It is important to note that this method will load all the appended body parts into memory all at the same
+    /// time. This method should only be used when the encoded data will have a small memory footprint. For large data
+    /// cases, please use the `writeEncodedDataToDisk(fileURL:completionHandler:)` method.
+    ///
+    /// - throws: An `AFError` if encoding encounters an error.
+    ///
+    /// - returns: The encoded `Data` if encoding is successful.
+    public func encode() throws -> Data {
+        if let bodyPartError = bodyPartError {
+            throw bodyPartError
+        }
+
+        var encoded = Data()
+
+        bodyParts.first?.hasInitialBoundary = true
+        bodyParts.last?.hasFinalBoundary = true
+
+        for bodyPart in bodyParts {
+            let encodedData = try encode(bodyPart)
+            encoded.append(encodedData)
+        }
+
+        return encoded
+    }
+
+    /// Writes the appended body parts into the given file URL.
+    ///
+    /// This process is facilitated by reading and writing with input and output streams, respectively. Thus,
+    /// this approach is very memory efficient and should be used for large body part data.
+    ///
+    /// - parameter fileURL: The file URL to write the multipart form data into.
+    ///
+    /// - throws: An `AFError` if encoding encounters an error.
+    public func writeEncodedData(to fileURL: URL) throws {
+        if let bodyPartError = bodyPartError {
+            throw bodyPartError
+        }
+
+        if FileManager.default.fileExists(atPath: fileURL.path) {
+            throw AFError.multipartEncodingFailed(reason: .outputStreamFileAlreadyExists(at: fileURL))
+        } else if !fileURL.isFileURL {
+            throw AFError.multipartEncodingFailed(reason: .outputStreamURLInvalid(url: fileURL))
+        }
+
+        guard let outputStream = OutputStream(url: fileURL, append: false) else {
+            throw AFError.multipartEncodingFailed(reason: .outputStreamCreationFailed(for: fileURL))
+        }
+
+        outputStream.open()
+        defer { outputStream.close() }
+
+        self.bodyParts.first?.hasInitialBoundary = true
+        self.bodyParts.last?.hasFinalBoundary = true
+
+        for bodyPart in self.bodyParts {
+            try write(bodyPart, to: outputStream)
+        }
+    }
+
+    // MARK: - Private - Body Part Encoding
+
+    private func encode(_ bodyPart: BodyPart) throws -> Data {
+        var encoded = Data()
+
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
+        encoded.append(initialData)
+
+        let headerData = encodeHeaders(for: bodyPart)
+        encoded.append(headerData)
+
+        let bodyStreamData = try encodeBodyStream(for: bodyPart)
+        encoded.append(bodyStreamData)
+
+        if bodyPart.hasFinalBoundary {
+            encoded.append(finalBoundaryData())
+        }
+
+        return encoded
+    }
+
+    private func encodeHeaders(for bodyPart: BodyPart) -> Data {
+        var headerText = ""
+
+        for (key, value) in bodyPart.headers {
+            headerText += "\(key): \(value)\(EncodingCharacters.crlf)"
+        }
+        headerText += EncodingCharacters.crlf
+
+        return headerText.data(using: String.Encoding.utf8, allowLossyConversion: false)!
+    }
+
+    private func encodeBodyStream(for bodyPart: BodyPart) throws -> Data {
+        let inputStream = bodyPart.bodyStream
+        inputStream.open()
+        defer { inputStream.close() }
+
+        var encoded = Data()
+
+        while inputStream.hasBytesAvailable {
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
+
+            if let error = inputStream.streamError {
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: error))
+            }
+
+            if bytesRead > 0 {
+                encoded.append(buffer, count: bytesRead)
+            } else {
+                break
+            }
+        }
+
+        return encoded
+    }
+
+    // MARK: - Private - Writing Body Part to Output Stream
+
+    private func write(_ bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        try writeInitialBoundaryData(for: bodyPart, to: outputStream)
+        try writeHeaderData(for: bodyPart, to: outputStream)
+        try writeBodyStream(for: bodyPart, to: outputStream)
+        try writeFinalBoundaryData(for: bodyPart, to: outputStream)
+    }
+
+    private func writeInitialBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        let initialData = bodyPart.hasInitialBoundary ? initialBoundaryData() : encapsulatedBoundaryData()
+        return try write(initialData, to: outputStream)
+    }
+
+    private func writeHeaderData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        let headerData = encodeHeaders(for: bodyPart)
+        return try write(headerData, to: outputStream)
+    }
+
+    private func writeBodyStream(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        let inputStream = bodyPart.bodyStream
+
+        inputStream.open()
+        defer { inputStream.close() }
+
+        while inputStream.hasBytesAvailable {
+            var buffer = [UInt8](repeating: 0, count: streamBufferSize)
+            let bytesRead = inputStream.read(&buffer, maxLength: streamBufferSize)
+
+            if let streamError = inputStream.streamError {
+                throw AFError.multipartEncodingFailed(reason: .inputStreamReadFailed(error: streamError))
+            }
+
+            if bytesRead > 0 {
+                if buffer.count != bytesRead {
+                    buffer = Array(buffer[0..<bytesRead])
+                }
+
+                try write(&buffer, to: outputStream)
+            } else {
+                break
+            }
+        }
+    }
+
+    private func writeFinalBoundaryData(for bodyPart: BodyPart, to outputStream: OutputStream) throws {
+        if bodyPart.hasFinalBoundary {
+            return try write(finalBoundaryData(), to: outputStream)
+        }
+    }
+
+    // MARK: - Private - Writing Buffered Data to Output Stream
+
+    private func write(_ data: Data, to outputStream: OutputStream) throws {
+        var buffer = [UInt8](repeating: 0, count: data.count)
+        data.copyBytes(to: &buffer, count: data.count)
+
+        return try write(&buffer, to: outputStream)
+    }
+
+    private func write(_ buffer: inout [UInt8], to outputStream: OutputStream) throws {
+        var bytesToWrite = buffer.count
+
+        while bytesToWrite > 0, outputStream.hasSpaceAvailable {
+            let bytesWritten = outputStream.write(buffer, maxLength: bytesToWrite)
+
+            if let error = outputStream.streamError {
+                throw AFError.multipartEncodingFailed(reason: .outputStreamWriteFailed(error: error))
+            }
+
+            bytesToWrite -= bytesWritten
+
+            if bytesToWrite > 0 {
+                buffer = Array(buffer[bytesWritten..<buffer.count])
+            }
+        }
+    }
+
+    // MARK: - Private - Mime Type
+
+    private func mimeType(forPathExtension pathExtension: String) -> String {
+        if
+            let id = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue(),
+            let contentType = UTTypeCopyPreferredTagWithClass(id, kUTTagClassMIMEType)?.takeRetainedValue()
+        {
+            return contentType as String
+        }
+
+        return "application/octet-stream"
+    }
+
+    // MARK: - Private - Content Headers
+
+    private func contentHeaders(withName name: String, fileName: String? = nil, mimeType: String? = nil) -> [String: String] {
+        var disposition = "form-data; name=\"\(name)\""
+        if let fileName = fileName { disposition += "; filename=\"\(fileName)\"" }
+
+        var headers = ["Content-Disposition": disposition]
+        if let mimeType = mimeType { headers["Content-Type"] = mimeType }
+
+        return headers
+    }
+
+    // MARK: - Private - Boundary Encoding
+
+    private func initialBoundaryData() -> Data {
+        return BoundaryGenerator.boundaryData(forBoundaryType: .initial, boundary: boundary)
+    }
+
+    private func encapsulatedBoundaryData() -> Data {
+        return BoundaryGenerator.boundaryData(forBoundaryType: .encapsulated, boundary: boundary)
+    }
+
+    private func finalBoundaryData() -> Data {
+        return BoundaryGenerator.boundaryData(forBoundaryType: .final, boundary: boundary)
+    }
+
+    // MARK: - Private - Errors
+
+    private func setBodyPartError(withReason reason: AFError.MultipartEncodingFailureReason) {
+        guard bodyPartError == nil else { return }
+        bodyPartError = AFError.multipartEncodingFailed(reason: reason)
+    }
+}

+ 235 - 0
RainbowPlanet/Pods/Alamofire/Source/NetworkReachabilityManager.swift

@@ -0,0 +1,235 @@
+//
+//  NetworkReachabilityManager.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+#if !os(watchOS)
+
+import Foundation
+import SystemConfiguration
+
+/// The `NetworkReachabilityManager` class listens for reachability changes of hosts and addresses for both WWAN and
+/// WiFi network interfaces.
+///
+/// Reachability can be used to determine background information about why a network operation failed, or to retry
+/// network requests when a connection is established. It should not be used to prevent a user from initiating a network
+/// request, as it's possible that an initial request may be required to establish reachability.
+open class NetworkReachabilityManager {
+    /// Defines the various states of network reachability.
+    ///
+    /// - unknown:      It is unknown whether the network is reachable.
+    /// - notReachable: The network is not reachable.
+    /// - reachable:    The network is reachable.
+    public enum NetworkReachabilityStatus {
+        case unknown
+        case notReachable
+        case reachable(ConnectionType)
+    }
+
+    /// Defines the various connection types detected by reachability flags.
+    ///
+    /// - ethernetOrWiFi: The connection type is either over Ethernet or WiFi.
+    /// - wwan:           The connection type is a WWAN connection.
+    public enum ConnectionType {
+        case ethernetOrWiFi
+        case wwan
+    }
+
+    /// A closure executed when the network reachability status changes. The closure takes a single argument: the
+    /// network reachability status.
+    public typealias Listener = (NetworkReachabilityStatus) -> Void
+
+    // MARK: - Properties
+
+    /// Whether the network is currently reachable.
+    open var isReachable: Bool { return isReachableOnWWAN || isReachableOnEthernetOrWiFi }
+
+    /// Whether the network is currently reachable over the WWAN interface.
+    open var isReachableOnWWAN: Bool { return networkReachabilityStatus == .reachable(.wwan) }
+
+    /// Whether the network is currently reachable over Ethernet or WiFi interface.
+    open var isReachableOnEthernetOrWiFi: Bool { return networkReachabilityStatus == .reachable(.ethernetOrWiFi) }
+
+    /// The current network reachability status.
+    open var networkReachabilityStatus: NetworkReachabilityStatus {
+        guard let flags = self.flags else { return .unknown }
+        return networkReachabilityStatusForFlags(flags)
+    }
+
+    /// The dispatch queue to execute the `listener` closure on.
+    open var listenerQueue: DispatchQueue = DispatchQueue.main
+
+    /// A closure executed when the network reachability status changes.
+    open var listener: Listener?
+
+    open var flags: SCNetworkReachabilityFlags? {
+        var flags = SCNetworkReachabilityFlags()
+
+        if SCNetworkReachabilityGetFlags(reachability, &flags) {
+            return flags
+        }
+
+        return nil
+    }
+
+    private let reachability: SCNetworkReachability
+    open var previousFlags: SCNetworkReachabilityFlags
+
+    // MARK: - Initialization
+
+    /// Creates a `NetworkReachabilityManager` instance with the specified host.
+    ///
+    /// - parameter host: The host used to evaluate network reachability.
+    ///
+    /// - returns: The new `NetworkReachabilityManager` instance.
+    public convenience init?(host: String) {
+        guard let reachability = SCNetworkReachabilityCreateWithName(nil, host) else { return nil }
+        self.init(reachability: reachability)
+    }
+
+    /// Creates a `NetworkReachabilityManager` instance that monitors the address 0.0.0.0.
+    ///
+    /// Reachability treats the 0.0.0.0 address as a special token that causes it to monitor the general routing
+    /// status of the device, both IPv4 and IPv6.
+    ///
+    /// - returns: The new `NetworkReachabilityManager` instance.
+    public convenience init?() {
+        var address = sockaddr_in()
+        address.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
+        address.sin_family = sa_family_t(AF_INET)
+
+        guard let reachability = withUnsafePointer(to: &address, { pointer in
+            return pointer.withMemoryRebound(to: sockaddr.self, capacity: MemoryLayout<sockaddr>.size) {
+                return SCNetworkReachabilityCreateWithAddress(nil, $0)
+            }
+        }) else { return nil }
+
+        self.init(reachability: reachability)
+    }
+
+    private init(reachability: SCNetworkReachability) {
+        self.reachability = reachability
+
+        // Set the previous flags to an unreserved value to represent unknown status
+        self.previousFlags = SCNetworkReachabilityFlags(rawValue: 1 << 30)
+    }
+
+    deinit {
+        stopListening()
+    }
+
+    // MARK: - Listening
+
+    /// Starts listening for changes in network reachability status.
+    ///
+    /// - returns: `true` if listening was started successfully, `false` otherwise.
+    @discardableResult
+    open func startListening() -> Bool {
+        var context = SCNetworkReachabilityContext(version: 0, info: nil, retain: nil, release: nil, copyDescription: nil)
+        context.info = Unmanaged.passUnretained(self).toOpaque()
+
+        let callbackEnabled = SCNetworkReachabilitySetCallback(
+            reachability,
+            { (_, flags, info) in
+                let reachability = Unmanaged<NetworkReachabilityManager>.fromOpaque(info!).takeUnretainedValue()
+                reachability.notifyListener(flags)
+            },
+            &context
+        )
+
+        let queueEnabled = SCNetworkReachabilitySetDispatchQueue(reachability, listenerQueue)
+
+        listenerQueue.async {
+            guard let flags = self.flags else { return }
+            self.notifyListener(flags)
+        }
+
+        return callbackEnabled && queueEnabled
+    }
+
+    /// Stops listening for changes in network reachability status.
+    open func stopListening() {
+        SCNetworkReachabilitySetCallback(reachability, nil, nil)
+        SCNetworkReachabilitySetDispatchQueue(reachability, nil)
+    }
+
+    // MARK: - Internal - Listener Notification
+
+    func notifyListener(_ flags: SCNetworkReachabilityFlags) {
+        guard previousFlags != flags else { return }
+        previousFlags = flags
+
+        listener?(networkReachabilityStatusForFlags(flags))
+    }
+
+    // MARK: - Internal - Network Reachability Status
+
+    func networkReachabilityStatusForFlags(_ flags: SCNetworkReachabilityFlags) -> NetworkReachabilityStatus {
+        guard isNetworkReachable(with: flags) else { return .notReachable }
+
+        var networkStatus: NetworkReachabilityStatus = .reachable(.ethernetOrWiFi)
+
+    #if os(iOS)
+        if flags.contains(.isWWAN) { networkStatus = .reachable(.wwan) }
+    #endif
+
+        return networkStatus
+    }
+
+    func isNetworkReachable(with flags: SCNetworkReachabilityFlags) -> Bool {
+        let isReachable = flags.contains(.reachable)
+        let needsConnection = flags.contains(.connectionRequired)
+        let canConnectAutomatically = flags.contains(.connectionOnDemand) || flags.contains(.connectionOnTraffic)
+        let canConnectWithoutUserInteraction = canConnectAutomatically && !flags.contains(.interventionRequired)
+
+        return isReachable && (!needsConnection || canConnectWithoutUserInteraction)
+    }
+}
+
+// MARK: -
+
+extension NetworkReachabilityManager.NetworkReachabilityStatus: Equatable {}
+
+/// Returns whether the two network reachability status values are equal.
+///
+/// - parameter lhs: The left-hand side value to compare.
+/// - parameter rhs: The right-hand side value to compare.
+///
+/// - returns: `true` if the two values are equal, `false` otherwise.
+public func ==(
+    lhs: NetworkReachabilityManager.NetworkReachabilityStatus,
+    rhs: NetworkReachabilityManager.NetworkReachabilityStatus)
+    -> Bool
+{
+    switch (lhs, rhs) {
+    case (.unknown, .unknown):
+        return true
+    case (.notReachable, .notReachable):
+        return true
+    case let (.reachable(lhsConnectionType), .reachable(rhsConnectionType)):
+        return lhsConnectionType == rhsConnectionType
+    default:
+        return false
+    }
+}
+
+#endif

+ 55 - 0
RainbowPlanet/Pods/Alamofire/Source/Notifications.swift

@@ -0,0 +1,55 @@
+//
+//  Notifications.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+extension Notification.Name {
+    /// Used as a namespace for all `URLSessionTask` related notifications.
+    public struct Task {
+        /// Posted when a `URLSessionTask` is resumed. The notification `object` contains the resumed `URLSessionTask`.
+        public static let DidResume = Notification.Name(rawValue: "org.alamofire.notification.name.task.didResume")
+
+        /// Posted when a `URLSessionTask` is suspended. The notification `object` contains the suspended `URLSessionTask`.
+        public static let DidSuspend = Notification.Name(rawValue: "org.alamofire.notification.name.task.didSuspend")
+
+        /// Posted when a `URLSessionTask` is cancelled. The notification `object` contains the cancelled `URLSessionTask`.
+        public static let DidCancel = Notification.Name(rawValue: "org.alamofire.notification.name.task.didCancel")
+
+        /// Posted when a `URLSessionTask` is completed. The notification `object` contains the completed `URLSessionTask`.
+        public static let DidComplete = Notification.Name(rawValue: "org.alamofire.notification.name.task.didComplete")
+    }
+}
+
+// MARK: -
+
+extension Notification {
+    /// Used as a namespace for all `Notification` user info dictionary keys.
+    public struct Key {
+        /// User info dictionary key representing the `URLSessionTask` associated with the notification.
+        public static let Task = "org.alamofire.notification.key.task"
+
+        /// User info dictionary key representing the responseData associated with the notification.
+        public static let ResponseData = "org.alamofire.notification.key.responseData"
+    }
+}

+ 483 - 0
RainbowPlanet/Pods/Alamofire/Source/ParameterEncoding.swift

@@ -0,0 +1,483 @@
+//
+//  ParameterEncoding.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// HTTP method definitions.
+///
+/// See https://tools.ietf.org/html/rfc7231#section-4.3
+public enum HTTPMethod: String {
+    case options = "OPTIONS"
+    case get     = "GET"
+    case head    = "HEAD"
+    case post    = "POST"
+    case put     = "PUT"
+    case patch   = "PATCH"
+    case delete  = "DELETE"
+    case trace   = "TRACE"
+    case connect = "CONNECT"
+}
+
+// MARK: -
+
+/// A dictionary of parameters to apply to a `URLRequest`.
+public typealias Parameters = [String: Any]
+
+/// A type used to define how a set of parameters are applied to a `URLRequest`.
+public protocol ParameterEncoding {
+    /// Creates a URL request by encoding parameters and applying them onto an existing request.
+    ///
+    /// - parameter urlRequest: The request to have parameters applied.
+    /// - parameter parameters: The parameters to apply.
+    ///
+    /// - throws: An `AFError.parameterEncodingFailed` error if encoding fails.
+    ///
+    /// - returns: The encoded request.
+    func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest
+}
+
+// MARK: -
+
+/// Creates a url-encoded query string to be set as or appended to any existing URL query string or set as the HTTP
+/// body of the URL request. Whether the query string is set or appended to any existing URL query string or set as
+/// the HTTP body depends on the destination of the encoding.
+///
+/// The `Content-Type` HTTP header field of an encoded request with HTTP body is set to
+/// `application/x-www-form-urlencoded; charset=utf-8`.
+///
+/// There is no published specification for how to encode collection types. By default the convention of appending
+/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for
+/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the
+/// square brackets appended to array keys.
+///
+/// `BoolEncoding` can be used to configure how boolean values are encoded. The default behavior is to encode
+/// `true` as 1 and `false` as 0.
+public struct URLEncoding: ParameterEncoding {
+
+    // MARK: Helper Types
+
+    /// Defines whether the url-encoded query string is applied to the existing query string or HTTP body of the
+    /// resulting URL request.
+    ///
+    /// - methodDependent: Applies encoded query string result to existing query string for `GET`, `HEAD` and `DELETE`
+    ///                    requests and sets as the HTTP body for requests with any other HTTP method.
+    /// - queryString:     Sets or appends encoded query string result to existing query string.
+    /// - httpBody:        Sets encoded query string result as the HTTP body of the URL request.
+    public enum Destination {
+        case methodDependent, queryString, httpBody
+    }
+
+    /// Configures how `Array` parameters are encoded.
+    ///
+    /// - brackets:        An empty set of square brackets is appended to the key for every value.
+    ///                    This is the default behavior.
+    /// - noBrackets:      No brackets are appended. The key is encoded as is.
+    public enum ArrayEncoding {
+        case brackets, noBrackets
+
+        func encode(key: String) -> String {
+            switch self {
+            case .brackets:
+                return "\(key)[]"
+            case .noBrackets:
+                return key
+            }
+        }
+    }
+
+    /// Configures how `Bool` parameters are encoded.
+    ///
+    /// - numeric:         Encode `true` as `1` and `false` as `0`. This is the default behavior.
+    /// - literal:         Encode `true` and `false` as string literals.
+    public enum BoolEncoding {
+        case numeric, literal
+
+        func encode(value: Bool) -> String {
+            switch self {
+            case .numeric:
+                return value ? "1" : "0"
+            case .literal:
+                return value ? "true" : "false"
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    /// Returns a default `URLEncoding` instance.
+    public static var `default`: URLEncoding { return URLEncoding() }
+
+    /// Returns a `URLEncoding` instance with a `.methodDependent` destination.
+    public static var methodDependent: URLEncoding { return URLEncoding() }
+
+    /// Returns a `URLEncoding` instance with a `.queryString` destination.
+    public static var queryString: URLEncoding { return URLEncoding(destination: .queryString) }
+
+    /// Returns a `URLEncoding` instance with an `.httpBody` destination.
+    public static var httpBody: URLEncoding { return URLEncoding(destination: .httpBody) }
+
+    /// The destination defining where the encoded query string is to be applied to the URL request.
+    public let destination: Destination
+
+    /// The encoding to use for `Array` parameters.
+    public let arrayEncoding: ArrayEncoding
+
+    /// The encoding to use for `Bool` parameters.
+    public let boolEncoding: BoolEncoding
+
+    // MARK: Initialization
+
+    /// Creates a `URLEncoding` instance using the specified destination.
+    ///
+    /// - parameter destination: The destination defining where the encoded query string is to be applied.
+    /// - parameter arrayEncoding: The encoding to use for `Array` parameters.
+    /// - parameter boolEncoding: The encoding to use for `Bool` parameters.
+    ///
+    /// - returns: The new `URLEncoding` instance.
+    public init(destination: Destination = .methodDependent, arrayEncoding: ArrayEncoding = .brackets, boolEncoding: BoolEncoding = .numeric) {
+        self.destination = destination
+        self.arrayEncoding = arrayEncoding
+        self.boolEncoding = boolEncoding
+    }
+
+    // MARK: Encoding
+
+    /// Creates a URL request by encoding parameters and applying them onto an existing request.
+    ///
+    /// - parameter urlRequest: The request to have parameters applied.
+    /// - parameter parameters: The parameters to apply.
+    ///
+    /// - throws: An `Error` if the encoding process encounters an error.
+    ///
+    /// - returns: The encoded request.
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let parameters = parameters else { return urlRequest }
+
+        if let method = HTTPMethod(rawValue: urlRequest.httpMethod ?? "GET"), encodesParametersInURL(with: method) {
+            guard let url = urlRequest.url else {
+                throw AFError.parameterEncodingFailed(reason: .missingURL)
+            }
+
+            if var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false), !parameters.isEmpty {
+                let percentEncodedQuery = (urlComponents.percentEncodedQuery.map { $0 + "&" } ?? "") + query(parameters)
+                urlComponents.percentEncodedQuery = percentEncodedQuery
+                urlRequest.url = urlComponents.url
+            }
+        } else {
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/x-www-form-urlencoded; charset=utf-8", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = query(parameters).data(using: .utf8, allowLossyConversion: false)
+        }
+
+        return urlRequest
+    }
+
+    /// Creates percent-escaped, URL encoded query string components from the given key-value pair using recursion.
+    ///
+    /// - parameter key:   The key of the query component.
+    /// - parameter value: The value of the query component.
+    ///
+    /// - returns: The percent-escaped, URL encoded query string components.
+    public func queryComponents(fromKey key: String, value: Any) -> [(String, String)] {
+        var components: [(String, String)] = []
+
+        if let dictionary = value as? [String: Any] {
+            for (nestedKey, value) in dictionary {
+                components += queryComponents(fromKey: "\(key)[\(nestedKey)]", value: value)
+            }
+        } else if let array = value as? [Any] {
+            for value in array {
+                components += queryComponents(fromKey: arrayEncoding.encode(key: key), value: value)
+            }
+        } else if let value = value as? NSNumber {
+            if value.isBool {
+                components.append((escape(key), escape(boolEncoding.encode(value: value.boolValue))))
+            } else {
+                components.append((escape(key), escape("\(value)")))
+            }
+        } else if let bool = value as? Bool {
+            components.append((escape(key), escape(boolEncoding.encode(value: bool))))
+        } else {
+            components.append((escape(key), escape("\(value)")))
+        }
+
+        return components
+    }
+
+    /// Returns a percent-escaped string following RFC 3986 for a query string key or value.
+    ///
+    /// RFC 3986 states that the following characters are "reserved" characters.
+    ///
+    /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"
+    /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="
+    ///
+    /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow
+    /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"
+    /// should be percent-escaped in the query string.
+    ///
+    /// - parameter string: The string to be percent-escaped.
+    ///
+    /// - returns: The percent-escaped string.
+    public func escape(_ string: String) -> String {
+        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4
+        let subDelimitersToEncode = "!$&'()*+,;="
+
+        var allowedCharacterSet = CharacterSet.urlQueryAllowed
+        allowedCharacterSet.remove(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")
+
+        var escaped = ""
+
+        //==========================================================================================================
+        //
+        //  Batching is required for escaping due to an internal bug in iOS 8.1 and 8.2. Encoding more than a few
+        //  hundred Chinese characters causes various malloc error crashes. To avoid this issue until iOS 8 is no
+        //  longer supported, batching MUST be used for encoding. This introduces roughly a 20% overhead. For more
+        //  info, please refer to:
+        //
+        //      - https://github.com/Alamofire/Alamofire/issues/206
+        //
+        //==========================================================================================================
+
+        if #available(iOS 8.3, *) {
+            escaped = string.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? string
+        } else {
+            let batchSize = 50
+            var index = string.startIndex
+
+            while index != string.endIndex {
+                let startIndex = index
+                let endIndex = string.index(index, offsetBy: batchSize, limitedBy: string.endIndex) ?? string.endIndex
+                let range = startIndex..<endIndex
+
+                let substring = string[range]
+
+                escaped += substring.addingPercentEncoding(withAllowedCharacters: allowedCharacterSet) ?? String(substring)
+
+                index = endIndex
+            }
+        }
+
+        return escaped
+    }
+
+    private func query(_ parameters: [String: Any]) -> String {
+        var components: [(String, String)] = []
+
+        for key in parameters.keys.sorted(by: <) {
+            let value = parameters[key]!
+            components += queryComponents(fromKey: key, value: value)
+        }
+        return components.map { "\($0)=\($1)" }.joined(separator: "&")
+    }
+
+    private func encodesParametersInURL(with method: HTTPMethod) -> Bool {
+        switch destination {
+        case .queryString:
+            return true
+        case .httpBody:
+            return false
+        default:
+            break
+        }
+
+        switch method {
+        case .get, .head, .delete:
+            return true
+        default:
+            return false
+        }
+    }
+}
+
+// MARK: -
+
+/// Uses `JSONSerialization` to create a JSON representation of the parameters object, which is set as the body of the
+/// request. The `Content-Type` HTTP header field of an encoded request is set to `application/json`.
+public struct JSONEncoding: ParameterEncoding {
+
+    // MARK: Properties
+
+    /// Returns a `JSONEncoding` instance with default writing options.
+    public static var `default`: JSONEncoding { return JSONEncoding() }
+
+    /// Returns a `JSONEncoding` instance with `.prettyPrinted` writing options.
+    public static var prettyPrinted: JSONEncoding { return JSONEncoding(options: .prettyPrinted) }
+
+    /// The options for writing the parameters as JSON data.
+    public let options: JSONSerialization.WritingOptions
+
+    // MARK: Initialization
+
+    /// Creates a `JSONEncoding` instance using the specified options.
+    ///
+    /// - parameter options: The options for writing the parameters as JSON data.
+    ///
+    /// - returns: The new `JSONEncoding` instance.
+    public init(options: JSONSerialization.WritingOptions = []) {
+        self.options = options
+    }
+
+    // MARK: Encoding
+
+    /// Creates a URL request by encoding parameters and applying them onto an existing request.
+    ///
+    /// - parameter urlRequest: The request to have parameters applied.
+    /// - parameter parameters: The parameters to apply.
+    ///
+    /// - throws: An `Error` if the encoding process encounters an error.
+    ///
+    /// - returns: The encoded request.
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let parameters = parameters else { return urlRequest }
+
+        do {
+            let data = try JSONSerialization.data(withJSONObject: parameters, options: options)
+
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = data
+        } catch {
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+        }
+
+        return urlRequest
+    }
+
+    /// Creates a URL request by encoding the JSON object and setting the resulting data on the HTTP body.
+    ///
+    /// - parameter urlRequest: The request to apply the JSON object to.
+    /// - parameter jsonObject: The JSON object to apply to the request.
+    ///
+    /// - throws: An `Error` if the encoding process encounters an error.
+    ///
+    /// - returns: The encoded request.
+    public func encode(_ urlRequest: URLRequestConvertible, withJSONObject jsonObject: Any? = nil) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let jsonObject = jsonObject else { return urlRequest }
+
+        do {
+            let data = try JSONSerialization.data(withJSONObject: jsonObject, options: options)
+
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = data
+        } catch {
+            throw AFError.parameterEncodingFailed(reason: .jsonEncodingFailed(error: error))
+        }
+
+        return urlRequest
+    }
+}
+
+// MARK: -
+
+/// Uses `PropertyListSerialization` to create a plist representation of the parameters object, according to the
+/// associated format and write options values, which is set as the body of the request. The `Content-Type` HTTP header
+/// field of an encoded request is set to `application/x-plist`.
+public struct PropertyListEncoding: ParameterEncoding {
+
+    // MARK: Properties
+
+    /// Returns a default `PropertyListEncoding` instance.
+    public static var `default`: PropertyListEncoding { return PropertyListEncoding() }
+
+    /// Returns a `PropertyListEncoding` instance with xml formatting and default writing options.
+    public static var xml: PropertyListEncoding { return PropertyListEncoding(format: .xml) }
+
+    /// Returns a `PropertyListEncoding` instance with binary formatting and default writing options.
+    public static var binary: PropertyListEncoding { return PropertyListEncoding(format: .binary) }
+
+    /// The property list serialization format.
+    public let format: PropertyListSerialization.PropertyListFormat
+
+    /// The options for writing the parameters as plist data.
+    public let options: PropertyListSerialization.WriteOptions
+
+    // MARK: Initialization
+
+    /// Creates a `PropertyListEncoding` instance using the specified format and options.
+    ///
+    /// - parameter format:  The property list serialization format.
+    /// - parameter options: The options for writing the parameters as plist data.
+    ///
+    /// - returns: The new `PropertyListEncoding` instance.
+    public init(
+        format: PropertyListSerialization.PropertyListFormat = .xml,
+        options: PropertyListSerialization.WriteOptions = 0)
+    {
+        self.format = format
+        self.options = options
+    }
+
+    // MARK: Encoding
+
+    /// Creates a URL request by encoding parameters and applying them onto an existing request.
+    ///
+    /// - parameter urlRequest: The request to have parameters applied.
+    /// - parameter parameters: The parameters to apply.
+    ///
+    /// - throws: An `Error` if the encoding process encounters an error.
+    ///
+    /// - returns: The encoded request.
+    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
+        var urlRequest = try urlRequest.asURLRequest()
+
+        guard let parameters = parameters else { return urlRequest }
+
+        do {
+            let data = try PropertyListSerialization.data(
+                fromPropertyList: parameters,
+                format: format,
+                options: options
+            )
+
+            if urlRequest.value(forHTTPHeaderField: "Content-Type") == nil {
+                urlRequest.setValue("application/x-plist", forHTTPHeaderField: "Content-Type")
+            }
+
+            urlRequest.httpBody = data
+        } catch {
+            throw AFError.parameterEncodingFailed(reason: .propertyListEncodingFailed(error: error))
+        }
+
+        return urlRequest
+    }
+}
+
+// MARK: -
+
+extension NSNumber {
+    fileprivate var isBool: Bool { return CFBooleanGetTypeID() == CFGetTypeID(self) }
+}

+ 649 - 0
RainbowPlanet/Pods/Alamofire/Source/Request.swift

@@ -0,0 +1,649 @@
+//
+//  Request.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary.
+public protocol RequestAdapter {
+    /// Inspects and adapts the specified `URLRequest` in some manner if necessary and returns the result.
+    ///
+    /// - parameter urlRequest: The URL request to adapt.
+    ///
+    /// - throws: An `Error` if the adaptation encounters an error.
+    ///
+    /// - returns: The adapted `URLRequest`.
+    func adapt(_ urlRequest: URLRequest) throws -> URLRequest
+}
+
+// MARK: -
+
+/// A closure executed when the `RequestRetrier` determines whether a `Request` should be retried or not.
+public typealias RequestRetryCompletion = (_ shouldRetry: Bool, _ timeDelay: TimeInterval) -> Void
+
+/// A type that determines whether a request should be retried after being executed by the specified session manager
+/// and encountering an error.
+public protocol RequestRetrier {
+    /// Determines whether the `Request` should be retried by calling the `completion` closure.
+    ///
+    /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs
+    /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
+    /// cleaned up after.
+    ///
+    /// - parameter manager:    The session manager the request was executed on.
+    /// - parameter request:    The request that failed due to the encountered error.
+    /// - parameter error:      The error encountered when executing the request.
+    /// - parameter completion: The completion closure to be executed when retry decision has been determined.
+    func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion)
+}
+
+// MARK: -
+
+protocol TaskConvertible {
+    func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask
+}
+
+/// A dictionary of headers to apply to a `URLRequest`.
+public typealias HTTPHeaders = [String: String]
+
+// MARK: -
+
+/// Responsible for sending a request and receiving the response and associated data from the server, as well as
+/// managing its underlying `URLSessionTask`.
+open class Request {
+
+    // MARK: Helper Types
+
+    /// A closure executed when monitoring upload or download progress of a request.
+    public typealias ProgressHandler = (Progress) -> Void
+
+    enum RequestTask {
+        case data(TaskConvertible?, URLSessionTask?)
+        case download(TaskConvertible?, URLSessionTask?)
+        case upload(TaskConvertible?, URLSessionTask?)
+        case stream(TaskConvertible?, URLSessionTask?)
+    }
+
+    // MARK: Properties
+
+    /// The delegate for the underlying task.
+    open internal(set) var delegate: TaskDelegate {
+        get {
+            taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() }
+            return taskDelegate
+        }
+        set {
+            taskDelegateLock.lock() ; defer { taskDelegateLock.unlock() }
+            taskDelegate = newValue
+        }
+    }
+
+    /// The underlying task.
+    open var task: URLSessionTask? { return delegate.task }
+
+    /// The session belonging to the underlying task.
+    public let session: URLSession
+
+    /// The request sent or to be sent to the server.
+    open var request: URLRequest? { return task?.originalRequest }
+
+    /// The response received from the server, if any.
+    open var response: HTTPURLResponse? { return task?.response as? HTTPURLResponse }
+
+    /// The number of times the request has been retried.
+    open internal(set) var retryCount: UInt = 0
+
+    let originalTask: TaskConvertible?
+
+    var startTime: CFAbsoluteTime?
+    var endTime: CFAbsoluteTime?
+
+    var validations: [() -> Void] = []
+
+    private var taskDelegate: TaskDelegate
+    private var taskDelegateLock = NSLock()
+
+    // MARK: Lifecycle
+
+    init(session: URLSession, requestTask: RequestTask, error: Error? = nil) {
+        self.session = session
+
+        switch requestTask {
+        case .data(let originalTask, let task):
+            taskDelegate = DataTaskDelegate(task: task)
+            self.originalTask = originalTask
+        case .download(let originalTask, let task):
+            taskDelegate = DownloadTaskDelegate(task: task)
+            self.originalTask = originalTask
+        case .upload(let originalTask, let task):
+            taskDelegate = UploadTaskDelegate(task: task)
+            self.originalTask = originalTask
+        case .stream(let originalTask, let task):
+            taskDelegate = TaskDelegate(task: task)
+            self.originalTask = originalTask
+        }
+
+        delegate.error = error
+        delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() }
+    }
+
+    // MARK: Authentication
+
+    /// Associates an HTTP Basic credential with the request.
+    ///
+    /// - parameter user:        The user.
+    /// - parameter password:    The password.
+    /// - parameter persistence: The URL credential persistence. `.ForSession` by default.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    open func authenticate(
+        user: String,
+        password: String,
+        persistence: URLCredential.Persistence = .forSession)
+        -> Self
+    {
+        let credential = URLCredential(user: user, password: password, persistence: persistence)
+        return authenticate(usingCredential: credential)
+    }
+
+    /// Associates a specified credential with the request.
+    ///
+    /// - parameter credential: The credential.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    open func authenticate(usingCredential credential: URLCredential) -> Self {
+        delegate.credential = credential
+        return self
+    }
+
+    /// Returns a base64 encoded basic authentication credential as an authorization header tuple.
+    ///
+    /// - parameter user:     The user.
+    /// - parameter password: The password.
+    ///
+    /// - returns: A tuple with Authorization header and credential value if encoding succeeds, `nil` otherwise.
+    open class func authorizationHeader(user: String, password: String) -> (key: String, value: String)? {
+        guard let data = "\(user):\(password)".data(using: .utf8) else { return nil }
+
+        let credential = data.base64EncodedString(options: [])
+
+        return (key: "Authorization", value: "Basic \(credential)")
+    }
+
+    // MARK: State
+
+    /// Resumes the request.
+    open func resume() {
+        guard let task = task else { delegate.queue.isSuspended = false ; return }
+
+        if startTime == nil { startTime = CFAbsoluteTimeGetCurrent() }
+
+        task.resume()
+
+        NotificationCenter.default.post(
+            name: Notification.Name.Task.DidResume,
+            object: self,
+            userInfo: [Notification.Key.Task: task]
+        )
+    }
+
+    /// Suspends the request.
+    open func suspend() {
+        guard let task = task else { return }
+
+        task.suspend()
+
+        NotificationCenter.default.post(
+            name: Notification.Name.Task.DidSuspend,
+            object: self,
+            userInfo: [Notification.Key.Task: task]
+        )
+    }
+
+    /// Cancels the request.
+    open func cancel() {
+        guard let task = task else { return }
+
+        task.cancel()
+
+        NotificationCenter.default.post(
+            name: Notification.Name.Task.DidCancel,
+            object: self,
+            userInfo: [Notification.Key.Task: task]
+        )
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Request: CustomStringConvertible {
+    /// The textual representation used when written to an output stream, which includes the HTTP method and URL, as
+    /// well as the response status code if a response has been received.
+    open var description: String {
+        var components: [String] = []
+
+        if let HTTPMethod = request?.httpMethod {
+            components.append(HTTPMethod)
+        }
+
+        if let urlString = request?.url?.absoluteString {
+            components.append(urlString)
+        }
+
+        if let response = response {
+            components.append("(\(response.statusCode))")
+        }
+
+        return components.joined(separator: " ")
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Request: CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, in the form of a cURL command.
+    open var debugDescription: String {
+        return cURLRepresentation()
+    }
+
+    func cURLRepresentation() -> String {
+        var components = ["$ curl -v"]
+
+        guard let request = self.request,
+              let url = request.url,
+              let host = url.host
+        else {
+            return "$ curl command could not be created"
+        }
+
+        if let httpMethod = request.httpMethod, httpMethod != "GET" {
+            components.append("-X \(httpMethod)")
+        }
+
+        if let credentialStorage = self.session.configuration.urlCredentialStorage {
+            let protectionSpace = URLProtectionSpace(
+                host: host,
+                port: url.port ?? 0,
+                protocol: url.scheme,
+                realm: host,
+                authenticationMethod: NSURLAuthenticationMethodHTTPBasic
+            )
+
+            if let credentials = credentialStorage.credentials(for: protectionSpace)?.values {
+                for credential in credentials {
+                    guard let user = credential.user, let password = credential.password else { continue }
+                    components.append("-u \(user):\(password)")
+                }
+            } else {
+                if let credential = delegate.credential, let user = credential.user, let password = credential.password {
+                    components.append("-u \(user):\(password)")
+                }
+            }
+        }
+
+        if session.configuration.httpShouldSetCookies {
+            if
+                let cookieStorage = session.configuration.httpCookieStorage,
+                let cookies = cookieStorage.cookies(for: url), !cookies.isEmpty
+            {
+                let string = cookies.reduce("") { $0 + "\($1.name)=\($1.value);" }
+
+            #if swift(>=3.2)
+                components.append("-b \"\(string[..<string.index(before: string.endIndex)])\"")
+            #else
+                components.append("-b \"\(string.substring(to: string.characters.index(before: string.endIndex)))\"")
+            #endif
+            }
+        }
+
+        var headers: [AnyHashable: Any] = [:]
+
+        session.configuration.httpAdditionalHeaders?.filter {  $0.0 != AnyHashable("Cookie") }
+                                                    .forEach { headers[$0.0] = $0.1 }
+
+        request.allHTTPHeaderFields?.filter { $0.0 != "Cookie" }
+                                    .forEach { headers[$0.0] = $0.1 }
+
+        components += headers.map {
+            let escapedValue = String(describing: $0.value).replacingOccurrences(of: "\"", with: "\\\"")
+
+            return "-H \"\($0.key): \(escapedValue)\""
+        }
+
+        if let httpBodyData = request.httpBody, let httpBody = String(data: httpBodyData, encoding: .utf8) {
+            var escapedBody = httpBody.replacingOccurrences(of: "\\\"", with: "\\\\\"")
+            escapedBody = escapedBody.replacingOccurrences(of: "\"", with: "\\\"")
+
+            components.append("-d \"\(escapedBody)\"")
+        }
+
+        components.append("\"\(url.absoluteString)\"")
+
+        return components.joined(separator: " \\\n\t")
+    }
+}
+
+// MARK: -
+
+/// Specific type of `Request` that manages an underlying `URLSessionDataTask`.
+open class DataRequest: Request {
+
+    // MARK: Helper Types
+
+    struct Requestable: TaskConvertible {
+        let urlRequest: URLRequest
+
+        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
+            do {
+                let urlRequest = try self.urlRequest.adapt(using: adapter)
+                return queue.sync { session.dataTask(with: urlRequest) }
+            } catch {
+                throw AdaptError(error: error)
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    /// The request sent or to be sent to the server.
+    open override var request: URLRequest? {
+        if let request = super.request { return request }
+        if let requestable = originalTask as? Requestable { return requestable.urlRequest }
+
+        return nil
+    }
+
+    /// The progress of fetching the response data from the server for the request.
+    open var progress: Progress { return dataDelegate.progress }
+
+    var dataDelegate: DataTaskDelegate { return delegate as! DataTaskDelegate }
+
+    // MARK: Stream
+
+    /// Sets a closure to be called periodically during the lifecycle of the request as data is read from the server.
+    ///
+    /// This closure returns the bytes most recently received from the server, not including data from previous calls.
+    /// If this closure is set, data will only be available within this closure, and will not be saved elsewhere. It is
+    /// also important to note that the server data in any `Response` object will be `nil`.
+    ///
+    /// - parameter closure: The code to be executed periodically during the lifecycle of the request.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    open func stream(closure: ((Data) -> Void)? = nil) -> Self {
+        dataDelegate.dataStream = closure
+        return self
+    }
+
+    // MARK: Progress
+
+    /// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server.
+    ///
+    /// - parameter queue:   The dispatch queue to execute the closure on.
+    /// - parameter closure: The code to be executed periodically as data is read from the server.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self {
+        dataDelegate.progressHandler = (closure, queue)
+        return self
+    }
+}
+
+// MARK: -
+
+/// Specific type of `Request` that manages an underlying `URLSessionDownloadTask`.
+open class DownloadRequest: Request {
+
+    // MARK: Helper Types
+
+    /// A collection of options to be executed prior to moving a downloaded file from the temporary URL to the
+    /// destination URL.
+    public struct DownloadOptions: OptionSet {
+        /// Returns the raw bitmask value of the option and satisfies the `RawRepresentable` protocol.
+        public let rawValue: UInt
+
+        /// A `DownloadOptions` flag that creates intermediate directories for the destination URL if specified.
+        public static let createIntermediateDirectories = DownloadOptions(rawValue: 1 << 0)
+
+        /// A `DownloadOptions` flag that removes a previous file from the destination URL if specified.
+        public static let removePreviousFile = DownloadOptions(rawValue: 1 << 1)
+
+        /// Creates a `DownloadFileDestinationOptions` instance with the specified raw value.
+        ///
+        /// - parameter rawValue: The raw bitmask value for the option.
+        ///
+        /// - returns: A new log level instance.
+        public init(rawValue: UInt) {
+            self.rawValue = rawValue
+        }
+    }
+
+    /// A closure executed once a download request has successfully completed in order to determine where to move the
+    /// temporary file written to during the download process. The closure takes two arguments: the temporary file URL
+    /// and the URL response, and returns a two arguments: the file URL where the temporary file should be moved and
+    /// the options defining how the file should be moved.
+    public typealias DownloadFileDestination = (
+        _ temporaryURL: URL,
+        _ response: HTTPURLResponse)
+        -> (destinationURL: URL, options: DownloadOptions)
+
+    enum Downloadable: TaskConvertible {
+        case request(URLRequest)
+        case resumeData(Data)
+
+        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
+            do {
+                let task: URLSessionTask
+
+                switch self {
+                case let .request(urlRequest):
+                    let urlRequest = try urlRequest.adapt(using: adapter)
+                    task = queue.sync { session.downloadTask(with: urlRequest) }
+                case let .resumeData(resumeData):
+                    task = queue.sync { session.downloadTask(withResumeData: resumeData) }
+                }
+
+                return task
+            } catch {
+                throw AdaptError(error: error)
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    /// The request sent or to be sent to the server.
+    open override var request: URLRequest? {
+        if let request = super.request { return request }
+
+        if let downloadable = originalTask as? Downloadable, case let .request(urlRequest) = downloadable {
+            return urlRequest
+        }
+
+        return nil
+    }
+
+    /// The resume data of the underlying download task if available after a failure.
+    open var resumeData: Data? { return downloadDelegate.resumeData }
+
+    /// The progress of downloading the response data from the server for the request.
+    open var progress: Progress { return downloadDelegate.progress }
+
+    var downloadDelegate: DownloadTaskDelegate { return delegate as! DownloadTaskDelegate }
+
+    // MARK: State
+
+    /// Cancels the request.
+    open override func cancel() {
+        downloadDelegate.downloadTask.cancel { self.downloadDelegate.resumeData = $0 }
+
+        NotificationCenter.default.post(
+            name: Notification.Name.Task.DidCancel,
+            object: self,
+            userInfo: [Notification.Key.Task: task as Any]
+        )
+    }
+
+    // MARK: Progress
+
+    /// Sets a closure to be called periodically during the lifecycle of the `Request` as data is read from the server.
+    ///
+    /// - parameter queue:   The dispatch queue to execute the closure on.
+    /// - parameter closure: The code to be executed periodically as data is read from the server.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    open func downloadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self {
+        downloadDelegate.progressHandler = (closure, queue)
+        return self
+    }
+
+    // MARK: Destination
+
+    /// Creates a download file destination closure which uses the default file manager to move the temporary file to a
+    /// file URL in the first available directory with the specified search path directory and search path domain mask.
+    ///
+    /// - parameter directory: The search path directory. `.DocumentDirectory` by default.
+    /// - parameter domain:    The search path domain mask. `.UserDomainMask` by default.
+    ///
+    /// - returns: A download file destination closure.
+    open class func suggestedDownloadDestination(
+        for directory: FileManager.SearchPathDirectory = .documentDirectory,
+        in domain: FileManager.SearchPathDomainMask = .userDomainMask)
+        -> DownloadFileDestination
+    {
+        return { temporaryURL, response in
+            let directoryURLs = FileManager.default.urls(for: directory, in: domain)
+
+            if !directoryURLs.isEmpty {
+                return (directoryURLs[0].appendingPathComponent(response.suggestedFilename!), [])
+            }
+
+            return (temporaryURL, [])
+        }
+    }
+}
+
+// MARK: -
+
+/// Specific type of `Request` that manages an underlying `URLSessionUploadTask`.
+open class UploadRequest: DataRequest {
+
+    // MARK: Helper Types
+
+    enum Uploadable: TaskConvertible {
+        case data(Data, URLRequest)
+        case file(URL, URLRequest)
+        case stream(InputStream, URLRequest)
+
+        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
+            do {
+                let task: URLSessionTask
+
+                switch self {
+                case let .data(data, urlRequest):
+                    let urlRequest = try urlRequest.adapt(using: adapter)
+                    task = queue.sync { session.uploadTask(with: urlRequest, from: data) }
+                case let .file(url, urlRequest):
+                    let urlRequest = try urlRequest.adapt(using: adapter)
+                    task = queue.sync { session.uploadTask(with: urlRequest, fromFile: url) }
+                case let .stream(_, urlRequest):
+                    let urlRequest = try urlRequest.adapt(using: adapter)
+                    task = queue.sync { session.uploadTask(withStreamedRequest: urlRequest) }
+                }
+
+                return task
+            } catch {
+                throw AdaptError(error: error)
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    /// The request sent or to be sent to the server.
+    open override var request: URLRequest? {
+        if let request = super.request { return request }
+
+        guard let uploadable = originalTask as? Uploadable else { return nil }
+
+        switch uploadable {
+        case .data(_, let urlRequest), .file(_, let urlRequest), .stream(_, let urlRequest):
+            return urlRequest
+        }
+    }
+
+    /// The progress of uploading the payload to the server for the upload request.
+    open var uploadProgress: Progress { return uploadDelegate.uploadProgress }
+
+    var uploadDelegate: UploadTaskDelegate { return delegate as! UploadTaskDelegate }
+
+    // MARK: Upload Progress
+
+    /// Sets a closure to be called periodically during the lifecycle of the `UploadRequest` as data is sent to
+    /// the server.
+    ///
+    /// After the data is sent to the server, the `progress(queue:closure:)` APIs can be used to monitor the progress
+    /// of data being read from the server.
+    ///
+    /// - parameter queue:   The dispatch queue to execute the closure on.
+    /// - parameter closure: The code to be executed periodically as data is sent to the server.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    open func uploadProgress(queue: DispatchQueue = DispatchQueue.main, closure: @escaping ProgressHandler) -> Self {
+        uploadDelegate.uploadProgressHandler = (closure, queue)
+        return self
+    }
+}
+
+// MARK: -
+
+#if !os(watchOS)
+
+/// Specific type of `Request` that manages an underlying `URLSessionStreamTask`.
+@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+open class StreamRequest: Request {
+    enum Streamable: TaskConvertible {
+        case stream(hostName: String, port: Int)
+        case netService(NetService)
+
+        func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
+            let task: URLSessionTask
+
+            switch self {
+            case let .stream(hostName, port):
+                task = queue.sync { session.streamTask(withHostName: hostName, port: port) }
+            case let .netService(netService):
+                task = queue.sync { session.streamTask(with: netService) }
+            }
+
+            return task
+        }
+    }
+}
+
+#endif

+ 567 - 0
RainbowPlanet/Pods/Alamofire/Source/Response.swift

@@ -0,0 +1,567 @@
+//
+//  Response.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Used to store all data associated with an non-serialized response of a data or upload request.
+public struct DefaultDataResponse {
+    /// The URL request sent to the server.
+    public let request: URLRequest?
+
+    /// The server's response to the URL request.
+    public let response: HTTPURLResponse?
+
+    /// The data returned by the server.
+    public let data: Data?
+
+    /// The error encountered while executing or validating the request.
+    public let error: Error?
+
+    /// The timeline of the complete lifecycle of the request.
+    public let timeline: Timeline
+
+    var _metrics: AnyObject?
+
+    /// Creates a `DefaultDataResponse` instance from the specified parameters.
+    ///
+    /// - Parameters:
+    ///   - request:  The URL request sent to the server.
+    ///   - response: The server's response to the URL request.
+    ///   - data:     The data returned by the server.
+    ///   - error:    The error encountered while executing or validating the request.
+    ///   - timeline: The timeline of the complete lifecycle of the request. `Timeline()` by default.
+    ///   - metrics:  The task metrics containing the request / response statistics. `nil` by default.
+    public init(
+        request: URLRequest?,
+        response: HTTPURLResponse?,
+        data: Data?,
+        error: Error?,
+        timeline: Timeline = Timeline(),
+        metrics: AnyObject? = nil)
+    {
+        self.request = request
+        self.response = response
+        self.data = data
+        self.error = error
+        self.timeline = timeline
+    }
+}
+
+// MARK: -
+
+/// Used to store all data associated with a serialized response of a data or upload request.
+public struct DataResponse<Value> {
+    /// The URL request sent to the server.
+    public let request: URLRequest?
+
+    /// The server's response to the URL request.
+    public let response: HTTPURLResponse?
+
+    /// The data returned by the server.
+    public let data: Data?
+
+    /// The result of response serialization.
+    public let result: Result<Value>
+
+    /// The timeline of the complete lifecycle of the request.
+    public let timeline: Timeline
+
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
+    public var value: Value? { return result.value }
+
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
+    public var error: Error? { return result.error }
+
+    var _metrics: AnyObject?
+
+    /// Creates a `DataResponse` instance with the specified parameters derived from response serialization.
+    ///
+    /// - parameter request:  The URL request sent to the server.
+    /// - parameter response: The server's response to the URL request.
+    /// - parameter data:     The data returned by the server.
+    /// - parameter result:   The result of response serialization.
+    /// - parameter timeline: The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
+    ///
+    /// - returns: The new `DataResponse` instance.
+    public init(
+        request: URLRequest?,
+        response: HTTPURLResponse?,
+        data: Data?,
+        result: Result<Value>,
+        timeline: Timeline = Timeline())
+    {
+        self.request = request
+        self.response = response
+        self.data = data
+        self.result = result
+        self.timeline = timeline
+    }
+}
+
+// MARK: -
+
+extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure.
+    public var description: String {
+        return result.debugDescription
+    }
+
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
+    /// response, the server data, the response serialization result and the timeline.
+    public var debugDescription: String {
+        var output: [String] = []
+
+        output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil")
+        output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
+        output.append("[Data]: \(data?.count ?? 0) bytes")
+        output.append("[Result]: \(result.debugDescription)")
+        output.append("[Timeline]: \(timeline.debugDescription)")
+
+        return output.joined(separator: "\n")
+    }
+}
+
+// MARK: -
+
+extension DataResponse {
+    /// Evaluates the specified closure when the result of this `DataResponse` is a success, passing the unwrapped
+    /// result value as a parameter.
+    ///
+    /// Use the `map` method with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let possibleInt = possibleData.map { $0.count }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A `DataResponse` whose result wraps the value returned by the given closure. If this instance's
+    ///            result is a failure, returns a response wrapping the same failure.
+    public func map<T>(_ transform: (Value) -> T) -> DataResponse<T> {
+        var response = DataResponse<T>(
+            request: request,
+            response: self.response,
+            data: data,
+            result: result.map(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+
+    /// Evaluates the given closure when the result of this `DataResponse` is a success, passing the unwrapped result
+    /// value as a parameter.
+    ///
+    /// Use the `flatMap` method with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let possibleObject = possibleData.flatMap {
+    ///         try JSONSerialization.jsonObject(with: $0)
+    ///     }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A success or failure `DataResponse` depending on the result of the given closure. If this instance's
+    ///            result is a failure, returns the same failure.
+    public func flatMap<T>(_ transform: (Value) throws -> T) -> DataResponse<T> {
+        var response = DataResponse<T>(
+            request: request,
+            response: self.response,
+            data: data,
+            result: result.flatMap(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `mapError` function with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
+    ///
+    /// - Parameter transform: A closure that takes the error of the instance.
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
+    public func mapError<E: Error>(_ transform: (Error) -> E) -> DataResponse {
+        var response = DataResponse(
+            request: request,
+            response: self.response,
+            data: data,
+            result: result.mapError(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+
+    /// Evaluates the specified closure when the `DataResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `flatMapError` function with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DataResponse<Data> = ...
+    ///     let possibleObject = possibleData.flatMapError {
+    ///         try someFailableFunction(taking: $0)
+    ///     }
+    ///
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
+    ///
+    /// - Returns: A `DataResponse` instance containing the result of the transform.
+    public func flatMapError<E: Error>(_ transform: (Error) throws -> E) -> DataResponse {
+        var response = DataResponse(
+            request: request,
+            response: self.response,
+            data: data,
+            result: result.flatMapError(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+}
+
+// MARK: -
+
+/// Used to store all data associated with an non-serialized response of a download request.
+public struct DefaultDownloadResponse {
+    /// The URL request sent to the server.
+    public let request: URLRequest?
+
+    /// The server's response to the URL request.
+    public let response: HTTPURLResponse?
+
+    /// The temporary destination URL of the data returned from the server.
+    public let temporaryURL: URL?
+
+    /// The final destination URL of the data returned from the server if it was moved.
+    public let destinationURL: URL?
+
+    /// The resume data generated if the request was cancelled.
+    public let resumeData: Data?
+
+    /// The error encountered while executing or validating the request.
+    public let error: Error?
+
+    /// The timeline of the complete lifecycle of the request.
+    public let timeline: Timeline
+
+    var _metrics: AnyObject?
+
+    /// Creates a `DefaultDownloadResponse` instance from the specified parameters.
+    ///
+    /// - Parameters:
+    ///   - request:        The URL request sent to the server.
+    ///   - response:       The server's response to the URL request.
+    ///   - temporaryURL:   The temporary destination URL of the data returned from the server.
+    ///   - destinationURL: The final destination URL of the data returned from the server if it was moved.
+    ///   - resumeData:     The resume data generated if the request was cancelled.
+    ///   - error:          The error encountered while executing or validating the request.
+    ///   - timeline:       The timeline of the complete lifecycle of the request. `Timeline()` by default.
+    ///   - metrics:        The task metrics containing the request / response statistics. `nil` by default.
+    public init(
+        request: URLRequest?,
+        response: HTTPURLResponse?,
+        temporaryURL: URL?,
+        destinationURL: URL?,
+        resumeData: Data?,
+        error: Error?,
+        timeline: Timeline = Timeline(),
+        metrics: AnyObject? = nil)
+    {
+        self.request = request
+        self.response = response
+        self.temporaryURL = temporaryURL
+        self.destinationURL = destinationURL
+        self.resumeData = resumeData
+        self.error = error
+        self.timeline = timeline
+    }
+}
+
+// MARK: -
+
+/// Used to store all data associated with a serialized response of a download request.
+public struct DownloadResponse<Value> {
+    /// The URL request sent to the server.
+    public let request: URLRequest?
+
+    /// The server's response to the URL request.
+    public let response: HTTPURLResponse?
+
+    /// The temporary destination URL of the data returned from the server.
+    public let temporaryURL: URL?
+
+    /// The final destination URL of the data returned from the server if it was moved.
+    public let destinationURL: URL?
+
+    /// The resume data generated if the request was cancelled.
+    public let resumeData: Data?
+
+    /// The result of response serialization.
+    public let result: Result<Value>
+
+    /// The timeline of the complete lifecycle of the request.
+    public let timeline: Timeline
+
+    /// Returns the associated value of the result if it is a success, `nil` otherwise.
+    public var value: Value? { return result.value }
+
+    /// Returns the associated error value if the result if it is a failure, `nil` otherwise.
+    public var error: Error? { return result.error }
+
+    var _metrics: AnyObject?
+
+    /// Creates a `DownloadResponse` instance with the specified parameters derived from response serialization.
+    ///
+    /// - parameter request:        The URL request sent to the server.
+    /// - parameter response:       The server's response to the URL request.
+    /// - parameter temporaryURL:   The temporary destination URL of the data returned from the server.
+    /// - parameter destinationURL: The final destination URL of the data returned from the server if it was moved.
+    /// - parameter resumeData:     The resume data generated if the request was cancelled.
+    /// - parameter result:         The result of response serialization.
+    /// - parameter timeline:       The timeline of the complete lifecycle of the `Request`. Defaults to `Timeline()`.
+    ///
+    /// - returns: The new `DownloadResponse` instance.
+    public init(
+        request: URLRequest?,
+        response: HTTPURLResponse?,
+        temporaryURL: URL?,
+        destinationURL: URL?,
+        resumeData: Data?,
+        result: Result<Value>,
+        timeline: Timeline = Timeline())
+    {
+        self.request = request
+        self.response = response
+        self.temporaryURL = temporaryURL
+        self.destinationURL = destinationURL
+        self.resumeData = resumeData
+        self.result = result
+        self.timeline = timeline
+    }
+}
+
+// MARK: -
+
+extension DownloadResponse: CustomStringConvertible, CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure.
+    public var description: String {
+        return result.debugDescription
+    }
+
+    /// The debug textual representation used when written to an output stream, which includes the URL request, the URL
+    /// response, the temporary and destination URLs, the resume data, the response serialization result and the
+    /// timeline.
+    public var debugDescription: String {
+        var output: [String] = []
+
+        output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil")
+        output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
+        output.append("[TemporaryURL]: \(temporaryURL?.path ?? "nil")")
+        output.append("[DestinationURL]: \(destinationURL?.path ?? "nil")")
+        output.append("[ResumeData]: \(resumeData?.count ?? 0) bytes")
+        output.append("[Result]: \(result.debugDescription)")
+        output.append("[Timeline]: \(timeline.debugDescription)")
+
+        return output.joined(separator: "\n")
+    }
+}
+
+// MARK: -
+
+extension DownloadResponse {
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
+    /// result value as a parameter.
+    ///
+    /// Use the `map` method with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let possibleInt = possibleData.map { $0.count }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A `DownloadResponse` whose result wraps the value returned by the given closure. If this instance's
+    ///            result is a failure, returns a response wrapping the same failure.
+    public func map<T>(_ transform: (Value) -> T) -> DownloadResponse<T> {
+        var response = DownloadResponse<T>(
+            request: request,
+            response: self.response,
+            temporaryURL: temporaryURL,
+            destinationURL: destinationURL,
+            resumeData: resumeData,
+            result: result.map(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+
+    /// Evaluates the given closure when the result of this `DownloadResponse` is a success, passing the unwrapped
+    /// result value as a parameter.
+    ///
+    /// Use the `flatMap` method with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let possibleObject = possibleData.flatMap {
+    ///         try JSONSerialization.jsonObject(with: $0)
+    ///     }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance's result.
+    ///
+    /// - returns: A success or failure `DownloadResponse` depending on the result of the given closure. If this
+    /// instance's result is a failure, returns the same failure.
+    public func flatMap<T>(_ transform: (Value) throws -> T) -> DownloadResponse<T> {
+        var response = DownloadResponse<T>(
+            request: request,
+            response: self.response,
+            temporaryURL: temporaryURL,
+            destinationURL: destinationURL,
+            resumeData: resumeData,
+            result: result.flatMap(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `mapError` function with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let withMyError = possibleData.mapError { MyError.error($0) }
+    ///
+    /// - Parameter transform: A closure that takes the error of the instance.
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
+    public func mapError<E: Error>(_ transform: (Error) -> E) -> DownloadResponse {
+        var response = DownloadResponse(
+            request: request,
+            response: self.response,
+            temporaryURL: temporaryURL,
+            destinationURL: destinationURL,
+            resumeData: resumeData,
+            result: result.mapError(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+
+    /// Evaluates the specified closure when the `DownloadResponse` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `flatMapError` function with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: DownloadResponse<Data> = ...
+    ///     let possibleObject = possibleData.flatMapError {
+    ///         try someFailableFunction(taking: $0)
+    ///     }
+    ///
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
+    ///
+    /// - Returns: A `DownloadResponse` instance containing the result of the transform.
+    public func flatMapError<E: Error>(_ transform: (Error) throws -> E) -> DownloadResponse {
+        var response = DownloadResponse(
+            request: request,
+            response: self.response,
+            temporaryURL: temporaryURL,
+            destinationURL: destinationURL,
+            resumeData: resumeData,
+            result: result.flatMapError(transform),
+            timeline: timeline
+        )
+
+        response._metrics = _metrics
+
+        return response
+    }
+}
+
+// MARK: -
+
+protocol Response {
+    /// The task metrics containing the request / response statistics.
+    var _metrics: AnyObject? { get set }
+    mutating func add(_ metrics: AnyObject?)
+}
+
+extension Response {
+    mutating func add(_ metrics: AnyObject?) {
+        #if !os(watchOS)
+            guard #available(iOS 10.0, macOS 10.12, tvOS 10.0, *) else { return }
+            guard let metrics = metrics as? URLSessionTaskMetrics else { return }
+
+            _metrics = metrics
+        #endif
+    }
+}
+
+// MARK: -
+
+@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
+extension DefaultDataResponse: Response {
+#if !os(watchOS)
+    /// The task metrics containing the request / response statistics.
+    public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
+#endif
+}
+
+@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
+extension DataResponse: Response {
+#if !os(watchOS)
+    /// The task metrics containing the request / response statistics.
+    public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
+#endif
+}
+
+@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
+extension DefaultDownloadResponse: Response {
+#if !os(watchOS)
+    /// The task metrics containing the request / response statistics.
+    public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
+#endif
+}
+
+@available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
+extension DownloadResponse: Response {
+#if !os(watchOS)
+    /// The task metrics containing the request / response statistics.
+    public var metrics: URLSessionTaskMetrics? { return _metrics as? URLSessionTaskMetrics }
+#endif
+}

+ 715 - 0
RainbowPlanet/Pods/Alamofire/Source/ResponseSerialization.swift

@@ -0,0 +1,715 @@
+//
+//  ResponseSerialization.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// The type in which all data response serializers must conform to in order to serialize a response.
+public protocol DataResponseSerializerProtocol {
+    /// The type of serialized object to be created by this `DataResponseSerializerType`.
+    associatedtype SerializedObject
+
+    /// A closure used by response handlers that takes a request, response, data and error and returns a result.
+    var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<SerializedObject> { get }
+}
+
+// MARK: -
+
+/// A generic `DataResponseSerializerType` used to serialize a request, response, and data into a serialized object.
+public struct DataResponseSerializer<Value>: DataResponseSerializerProtocol {
+    /// The type of serialized object to be created by this `DataResponseSerializer`.
+    public typealias SerializedObject = Value
+
+    /// A closure used by response handlers that takes a request, response, data and error and returns a result.
+    public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>
+
+    /// Initializes the `ResponseSerializer` instance with the given serialize response closure.
+    ///
+    /// - parameter serializeResponse: The closure used to serialize the response.
+    ///
+    /// - returns: The new generic response serializer instance.
+    public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>) {
+        self.serializeResponse = serializeResponse
+    }
+}
+
+// MARK: -
+
+/// The type in which all download response serializers must conform to in order to serialize a response.
+public protocol DownloadResponseSerializerProtocol {
+    /// The type of serialized object to be created by this `DownloadResponseSerializerType`.
+    associatedtype SerializedObject
+
+    /// A closure used by response handlers that takes a request, response, url and error and returns a result.
+    var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<SerializedObject> { get }
+}
+
+// MARK: -
+
+/// A generic `DownloadResponseSerializerType` used to serialize a request, response, and data into a serialized object.
+public struct DownloadResponseSerializer<Value>: DownloadResponseSerializerProtocol {
+    /// The type of serialized object to be created by this `DownloadResponseSerializer`.
+    public typealias SerializedObject = Value
+
+    /// A closure used by response handlers that takes a request, response, url and error and returns a result.
+    public var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>
+
+    /// Initializes the `ResponseSerializer` instance with the given serialize response closure.
+    ///
+    /// - parameter serializeResponse: The closure used to serialize the response.
+    ///
+    /// - returns: The new generic response serializer instance.
+    public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>) {
+        self.serializeResponse = serializeResponse
+    }
+}
+
+// MARK: - Timeline
+
+extension Request {
+    var timeline: Timeline {
+        let requestStartTime = self.startTime ?? CFAbsoluteTimeGetCurrent()
+        let requestCompletedTime = self.endTime ?? CFAbsoluteTimeGetCurrent()
+        let initialResponseTime = self.delegate.initialResponseTime ?? requestCompletedTime
+
+        return Timeline(
+            requestStartTime: requestStartTime,
+            initialResponseTime: initialResponseTime,
+            requestCompletedTime: requestCompletedTime,
+            serializationCompletedTime: CFAbsoluteTimeGetCurrent()
+        )
+    }
+}
+
+// MARK: - Default
+
+extension DataRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter queue:             The queue on which the completion handler is dispatched.
+    /// - parameter completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
+        delegate.queue.addOperation {
+            (queue ?? DispatchQueue.main).async {
+                var dataResponse = DefaultDataResponse(
+                    request: self.request,
+                    response: self.response,
+                    data: self.delegate.data,
+                    error: self.delegate.error,
+                    timeline: self.timeline
+                )
+
+                dataResponse.add(self.delegate.metrics)
+
+                completionHandler(dataResponse)
+            }
+        }
+
+        return self
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter queue:              The queue on which the completion handler is dispatched.
+    /// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
+    ///                                 and data.
+    /// - parameter completionHandler:  The code to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func response<T: DataResponseSerializerProtocol>(
+        queue: DispatchQueue? = nil,
+        responseSerializer: T,
+        completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
+        -> Self
+    {
+        delegate.queue.addOperation {
+            let result = responseSerializer.serializeResponse(
+                self.request,
+                self.response,
+                self.delegate.data,
+                self.delegate.error
+            )
+
+            var dataResponse = DataResponse<T.SerializedObject>(
+                request: self.request,
+                response: self.response,
+                data: self.delegate.data,
+                result: result,
+                timeline: self.timeline
+            )
+
+            dataResponse.add(self.delegate.metrics)
+
+            (queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
+        }
+
+        return self
+    }
+}
+
+extension DownloadRequest {
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter queue:             The queue on which the completion handler is dispatched.
+    /// - parameter completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func response(
+        queue: DispatchQueue? = nil,
+        completionHandler: @escaping (DefaultDownloadResponse) -> Void)
+        -> Self
+    {
+        delegate.queue.addOperation {
+            (queue ?? DispatchQueue.main).async {
+                var downloadResponse = DefaultDownloadResponse(
+                    request: self.request,
+                    response: self.response,
+                    temporaryURL: self.downloadDelegate.temporaryURL,
+                    destinationURL: self.downloadDelegate.destinationURL,
+                    resumeData: self.downloadDelegate.resumeData,
+                    error: self.downloadDelegate.error,
+                    timeline: self.timeline
+                )
+
+                downloadResponse.add(self.delegate.metrics)
+
+                completionHandler(downloadResponse)
+            }
+        }
+
+        return self
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter queue:              The queue on which the completion handler is dispatched.
+    /// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
+    ///                                 and data contained in the destination url.
+    /// - parameter completionHandler:  The code to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func response<T: DownloadResponseSerializerProtocol>(
+        queue: DispatchQueue? = nil,
+        responseSerializer: T,
+        completionHandler: @escaping (DownloadResponse<T.SerializedObject>) -> Void)
+        -> Self
+    {
+        delegate.queue.addOperation {
+            let result = responseSerializer.serializeResponse(
+                self.request,
+                self.response,
+                self.downloadDelegate.fileURL,
+                self.downloadDelegate.error
+            )
+
+            var downloadResponse = DownloadResponse<T.SerializedObject>(
+                request: self.request,
+                response: self.response,
+                temporaryURL: self.downloadDelegate.temporaryURL,
+                destinationURL: self.downloadDelegate.destinationURL,
+                resumeData: self.downloadDelegate.resumeData,
+                result: result,
+                timeline: self.timeline
+            )
+
+            downloadResponse.add(self.delegate.metrics)
+
+            (queue ?? DispatchQueue.main).async { completionHandler(downloadResponse) }
+        }
+
+        return self
+    }
+}
+
+// MARK: - Data
+
+extension Request {
+    /// Returns a result data type that contains the response data as-is.
+    ///
+    /// - parameter response: The response from the server.
+    /// - parameter data:     The data returned from the server.
+    /// - parameter error:    The error already encountered if it exists.
+    ///
+    /// - returns: The result data type.
+    public static func serializeResponseData(response: HTTPURLResponse?, data: Data?, error: Error?) -> Result<Data> {
+        guard error == nil else { return .failure(error!) }
+
+        if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(Data()) }
+
+        guard let validData = data else {
+            return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
+        }
+
+        return .success(validData)
+    }
+}
+
+extension DataRequest {
+    /// Creates a response serializer that returns the associated data as-is.
+    ///
+    /// - returns: A data response serializer.
+    public static func dataResponseSerializer() -> DataResponseSerializer<Data> {
+        return DataResponseSerializer { _, response, data, error in
+            return Request.serializeResponseData(response: response, data: data, error: error)
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responseData(
+        queue: DispatchQueue? = nil,
+        completionHandler: @escaping (DataResponse<Data>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DataRequest.dataResponseSerializer(),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+extension DownloadRequest {
+    /// Creates a response serializer that returns the associated data as-is.
+    ///
+    /// - returns: A data response serializer.
+    public static func dataResponseSerializer() -> DownloadResponseSerializer<Data> {
+        return DownloadResponseSerializer { _, response, fileURL, error in
+            guard error == nil else { return .failure(error!) }
+
+            guard let fileURL = fileURL else {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
+            }
+
+            do {
+                let data = try Data(contentsOf: fileURL)
+                return Request.serializeResponseData(response: response, data: data, error: error)
+            } catch {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
+            }
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter completionHandler: The code to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responseData(
+        queue: DispatchQueue? = nil,
+        completionHandler: @escaping (DownloadResponse<Data>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DownloadRequest.dataResponseSerializer(),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+// MARK: - String
+
+extension Request {
+    /// Returns a result string type initialized from the response data with the specified string encoding.
+    ///
+    /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
+    ///                       response, falling back to the default HTTP default character set, ISO-8859-1.
+    /// - parameter response: The response from the server.
+    /// - parameter data:     The data returned from the server.
+    /// - parameter error:    The error already encountered if it exists.
+    ///
+    /// - returns: The result data type.
+    public static func serializeResponseString(
+        encoding: String.Encoding?,
+        response: HTTPURLResponse?,
+        data: Data?,
+        error: Error?)
+        -> Result<String>
+    {
+        guard error == nil else { return .failure(error!) }
+
+        if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success("") }
+
+        guard let validData = data else {
+            return .failure(AFError.responseSerializationFailed(reason: .inputDataNil))
+        }
+
+        var convertedEncoding = encoding
+
+        if let encodingName = response?.textEncodingName as CFString?, convertedEncoding == nil {
+            convertedEncoding = String.Encoding(rawValue: CFStringConvertEncodingToNSStringEncoding(
+                CFStringConvertIANACharSetNameToEncoding(encodingName))
+            )
+        }
+
+        let actualEncoding = convertedEncoding ?? .isoLatin1
+
+        if let string = String(data: validData, encoding: actualEncoding) {
+            return .success(string)
+        } else {
+            return .failure(AFError.responseSerializationFailed(reason: .stringSerializationFailed(encoding: actualEncoding)))
+        }
+    }
+}
+
+extension DataRequest {
+    /// Creates a response serializer that returns a result string type initialized from the response data with
+    /// the specified string encoding.
+    ///
+    /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
+    ///                       response, falling back to the default HTTP default character set, ISO-8859-1.
+    ///
+    /// - returns: A string response serializer.
+    public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DataResponseSerializer<String> {
+        return DataResponseSerializer { _, response, data, error in
+            return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter encoding:          The string encoding. If `nil`, the string encoding will be determined from the
+    ///                                server response, falling back to the default HTTP default character set,
+    ///                                ISO-8859-1.
+    /// - parameter completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responseString(
+        queue: DispatchQueue? = nil,
+        encoding: String.Encoding? = nil,
+        completionHandler: @escaping (DataResponse<String>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DataRequest.stringResponseSerializer(encoding: encoding),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+extension DownloadRequest {
+    /// Creates a response serializer that returns a result string type initialized from the response data with
+    /// the specified string encoding.
+    ///
+    /// - parameter encoding: The string encoding. If `nil`, the string encoding will be determined from the server
+    ///                       response, falling back to the default HTTP default character set, ISO-8859-1.
+    ///
+    /// - returns: A string response serializer.
+    public static func stringResponseSerializer(encoding: String.Encoding? = nil) -> DownloadResponseSerializer<String> {
+        return DownloadResponseSerializer { _, response, fileURL, error in
+            guard error == nil else { return .failure(error!) }
+
+            guard let fileURL = fileURL else {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
+            }
+
+            do {
+                let data = try Data(contentsOf: fileURL)
+                return Request.serializeResponseString(encoding: encoding, response: response, data: data, error: error)
+            } catch {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
+            }
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter encoding:          The string encoding. If `nil`, the string encoding will be determined from the
+    ///                                server response, falling back to the default HTTP default character set,
+    ///                                ISO-8859-1.
+    /// - parameter completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responseString(
+        queue: DispatchQueue? = nil,
+        encoding: String.Encoding? = nil,
+        completionHandler: @escaping (DownloadResponse<String>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DownloadRequest.stringResponseSerializer(encoding: encoding),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+// MARK: - JSON
+
+extension Request {
+    /// Returns a JSON object contained in a result type constructed from the response data using `JSONSerialization`
+    /// with the specified reading options.
+    ///
+    /// - parameter options:  The JSON serialization reading options. Defaults to `.allowFragments`.
+    /// - parameter response: The response from the server.
+    /// - parameter data:     The data returned from the server.
+    /// - parameter error:    The error already encountered if it exists.
+    ///
+    /// - returns: The result data type.
+    public static func serializeResponseJSON(
+        options: JSONSerialization.ReadingOptions,
+        response: HTTPURLResponse?,
+        data: Data?,
+        error: Error?)
+        -> Result<Any>
+    {
+        guard error == nil else { return .failure(error!) }
+
+        if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
+
+        guard let validData = data, validData.count > 0 else {
+            return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
+        }
+
+        do {
+            let json = try JSONSerialization.jsonObject(with: validData, options: options)
+            return .success(json)
+        } catch {
+            return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
+        }
+    }
+}
+
+extension DataRequest {
+    /// Creates a response serializer that returns a JSON object result type constructed from the response data using
+    /// `JSONSerialization` with the specified reading options.
+    ///
+    /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
+    ///
+    /// - returns: A JSON object response serializer.
+    public static func jsonResponseSerializer(
+        options: JSONSerialization.ReadingOptions = .allowFragments)
+        -> DataResponseSerializer<Any>
+    {
+        return DataResponseSerializer { _, response, data, error in
+            return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter options:           The JSON serialization reading options. Defaults to `.allowFragments`.
+    /// - parameter completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responseJSON(
+        queue: DispatchQueue? = nil,
+        options: JSONSerialization.ReadingOptions = .allowFragments,
+        completionHandler: @escaping (DataResponse<Any>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DataRequest.jsonResponseSerializer(options: options),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+extension DownloadRequest {
+    /// Creates a response serializer that returns a JSON object result type constructed from the response data using
+    /// `JSONSerialization` with the specified reading options.
+    ///
+    /// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
+    ///
+    /// - returns: A JSON object response serializer.
+    public static func jsonResponseSerializer(
+        options: JSONSerialization.ReadingOptions = .allowFragments)
+        -> DownloadResponseSerializer<Any>
+    {
+        return DownloadResponseSerializer { _, response, fileURL, error in
+            guard error == nil else { return .failure(error!) }
+
+            guard let fileURL = fileURL else {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
+            }
+
+            do {
+                let data = try Data(contentsOf: fileURL)
+                return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
+            } catch {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
+            }
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter options:           The JSON serialization reading options. Defaults to `.allowFragments`.
+    /// - parameter completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responseJSON(
+        queue: DispatchQueue? = nil,
+        options: JSONSerialization.ReadingOptions = .allowFragments,
+        completionHandler: @escaping (DownloadResponse<Any>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DownloadRequest.jsonResponseSerializer(options: options),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+// MARK: - Property List
+
+extension Request {
+    /// Returns a plist object contained in a result type constructed from the response data using
+    /// `PropertyListSerialization` with the specified reading options.
+    ///
+    /// - parameter options:  The property list reading options. Defaults to `[]`.
+    /// - parameter response: The response from the server.
+    /// - parameter data:     The data returned from the server.
+    /// - parameter error:    The error already encountered if it exists.
+    ///
+    /// - returns: The result data type.
+    public static func serializeResponsePropertyList(
+        options: PropertyListSerialization.ReadOptions,
+        response: HTTPURLResponse?,
+        data: Data?,
+        error: Error?)
+        -> Result<Any>
+    {
+        guard error == nil else { return .failure(error!) }
+
+        if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
+
+        guard let validData = data, validData.count > 0 else {
+            return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
+        }
+
+        do {
+            let plist = try PropertyListSerialization.propertyList(from: validData, options: options, format: nil)
+            return .success(plist)
+        } catch {
+            return .failure(AFError.responseSerializationFailed(reason: .propertyListSerializationFailed(error: error)))
+        }
+    }
+}
+
+extension DataRequest {
+    /// Creates a response serializer that returns an object constructed from the response data using
+    /// `PropertyListSerialization` with the specified reading options.
+    ///
+    /// - parameter options: The property list reading options. Defaults to `[]`.
+    ///
+    /// - returns: A property list object response serializer.
+    public static func propertyListResponseSerializer(
+        options: PropertyListSerialization.ReadOptions = [])
+        -> DataResponseSerializer<Any>
+    {
+        return DataResponseSerializer { _, response, data, error in
+            return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error)
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter options:           The property list reading options. Defaults to `[]`.
+    /// - parameter completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responsePropertyList(
+        queue: DispatchQueue? = nil,
+        options: PropertyListSerialization.ReadOptions = [],
+        completionHandler: @escaping (DataResponse<Any>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DataRequest.propertyListResponseSerializer(options: options),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+extension DownloadRequest {
+    /// Creates a response serializer that returns an object constructed from the response data using
+    /// `PropertyListSerialization` with the specified reading options.
+    ///
+    /// - parameter options: The property list reading options. Defaults to `[]`.
+    ///
+    /// - returns: A property list object response serializer.
+    public static func propertyListResponseSerializer(
+        options: PropertyListSerialization.ReadOptions = [])
+        -> DownloadResponseSerializer<Any>
+    {
+        return DownloadResponseSerializer { _, response, fileURL, error in
+            guard error == nil else { return .failure(error!) }
+
+            guard let fileURL = fileURL else {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileNil))
+            }
+
+            do {
+                let data = try Data(contentsOf: fileURL)
+                return Request.serializeResponsePropertyList(options: options, response: response, data: data, error: error)
+            } catch {
+                return .failure(AFError.responseSerializationFailed(reason: .inputFileReadFailed(at: fileURL)))
+            }
+        }
+    }
+
+    /// Adds a handler to be called once the request has finished.
+    ///
+    /// - parameter options:           The property list reading options. Defaults to `[]`.
+    /// - parameter completionHandler: A closure to be executed once the request has finished.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func responsePropertyList(
+        queue: DispatchQueue? = nil,
+        options: PropertyListSerialization.ReadOptions = [],
+        completionHandler: @escaping (DownloadResponse<Any>) -> Void)
+        -> Self
+    {
+        return response(
+            queue: queue,
+            responseSerializer: DownloadRequest.propertyListResponseSerializer(options: options),
+            completionHandler: completionHandler
+        )
+    }
+}
+
+/// A set of HTTP response status code that do not contain response data.
+private let emptyDataStatusCodes: Set<Int> = [204, 205]

+ 300 - 0
RainbowPlanet/Pods/Alamofire/Source/Result.swift

@@ -0,0 +1,300 @@
+//
+//  Result.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Used to represent whether a request was successful or encountered an error.
+///
+/// - success: The request and all post processing operations were successful resulting in the serialization of the
+///            provided associated value.
+///
+/// - failure: The request encountered an error resulting in a failure. The associated values are the original data
+///            provided by the server as well as the error that caused the failure.
+public enum Result<Value> {
+    case success(Value)
+    case failure(Error)
+
+    /// Returns `true` if the result is a success, `false` otherwise.
+    public var isSuccess: Bool {
+        switch self {
+        case .success:
+            return true
+        case .failure:
+            return false
+        }
+    }
+
+    /// Returns `true` if the result is a failure, `false` otherwise.
+    public var isFailure: Bool {
+        return !isSuccess
+    }
+
+    /// Returns the associated value if the result is a success, `nil` otherwise.
+    public var value: Value? {
+        switch self {
+        case .success(let value):
+            return value
+        case .failure:
+            return nil
+        }
+    }
+
+    /// Returns the associated error value if the result is a failure, `nil` otherwise.
+    public var error: Error? {
+        switch self {
+        case .success:
+            return nil
+        case .failure(let error):
+            return error
+        }
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Result: CustomStringConvertible {
+    /// The textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure.
+    public var description: String {
+        switch self {
+        case .success:
+            return "SUCCESS"
+        case .failure:
+            return "FAILURE"
+        }
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Result: CustomDebugStringConvertible {
+    /// The debug textual representation used when written to an output stream, which includes whether the result was a
+    /// success or failure in addition to the value or error.
+    public var debugDescription: String {
+        switch self {
+        case .success(let value):
+            return "SUCCESS: \(value)"
+        case .failure(let error):
+            return "FAILURE: \(error)"
+        }
+    }
+}
+
+// MARK: - Functional APIs
+
+extension Result {
+    /// Creates a `Result` instance from the result of a closure.
+    ///
+    /// A failure result is created when the closure throws, and a success result is created when the closure
+    /// succeeds without throwing an error.
+    ///
+    ///     func someString() throws -> String { ... }
+    ///
+    ///     let result = Result(value: {
+    ///         return try someString()
+    ///     })
+    ///
+    ///     // The type of result is Result<String>
+    ///
+    /// The trailing closure syntax is also supported:
+    ///
+    ///     let result = Result { try someString() }
+    ///
+    /// - parameter value: The closure to execute and create the result for.
+    public init(value: () throws -> Value) {
+        do {
+            self = try .success(value())
+        } catch {
+            self = .failure(error)
+        }
+    }
+
+    /// Returns the success value, or throws the failure error.
+    ///
+    ///     let possibleString: Result<String> = .success("success")
+    ///     try print(possibleString.unwrap())
+    ///     // Prints "success"
+    ///
+    ///     let noString: Result<String> = .failure(error)
+    ///     try print(noString.unwrap())
+    ///     // Throws error
+    public func unwrap() throws -> Value {
+        switch self {
+        case .success(let value):
+            return value
+        case .failure(let error):
+            throw error
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
+    ///
+    /// Use the `map` method with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: Result<Data> = .success(Data())
+    ///     let possibleInt = possibleData.map { $0.count }
+    ///     try print(possibleInt.unwrap())
+    ///     // Prints "0"
+    ///
+    ///     let noData: Result<Data> = .failure(error)
+    ///     let noInt = noData.map { $0.count }
+    ///     try print(noInt.unwrap())
+    ///     // Throws error
+    ///
+    /// - parameter transform: A closure that takes the success value of the `Result` instance.
+    ///
+    /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
+    ///            same failure.
+    public func map<T>(_ transform: (Value) -> T) -> Result<T> {
+        switch self {
+        case .success(let value):
+            return .success(transform(value))
+        case .failure(let error):
+            return .failure(error)
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
+    ///
+    /// Use the `flatMap` method with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: Result<Data> = .success(Data(...))
+    ///     let possibleObject = possibleData.flatMap {
+    ///         try JSONSerialization.jsonObject(with: $0)
+    ///     }
+    ///
+    /// - parameter transform: A closure that takes the success value of the instance.
+    ///
+    /// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
+    ///            same failure.
+    public func flatMap<T>(_ transform: (Value) throws -> T) -> Result<T> {
+        switch self {
+        case .success(let value):
+            do {
+                return try .success(transform(value))
+            } catch {
+                return .failure(error)
+            }
+        case .failure(let error):
+            return .failure(error)
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `mapError` function with a closure that does not throw. For example:
+    ///
+    ///     let possibleData: Result<Data> = .failure(someError)
+    ///     let withMyError: Result<Data> = possibleData.mapError { MyError.error($0) }
+    ///
+    /// - Parameter transform: A closure that takes the error of the instance.
+    /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
+    ///            the same instance.
+    public func mapError<T: Error>(_ transform: (Error) -> T) -> Result {
+        switch self {
+        case .failure(let error):
+            return .failure(transform(error))
+        case .success:
+            return self
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `flatMapError` function with a closure that may throw an error. For example:
+    ///
+    ///     let possibleData: Result<Data> = .success(Data(...))
+    ///     let possibleObject = possibleData.flatMapError {
+    ///         try someFailableFunction(taking: $0)
+    ///     }
+    ///
+    /// - Parameter transform: A throwing closure that takes the error of the instance.
+    ///
+    /// - Returns: A `Result` instance containing the result of the transform. If this instance is a success, returns
+    ///            the same instance.
+    public func flatMapError<T: Error>(_ transform: (Error) throws -> T) -> Result {
+        switch self {
+        case .failure(let error):
+            do {
+                return try .failure(transform(error))
+            } catch {
+                return .failure(error)
+            }
+        case .success:
+            return self
+        }
+    }
+
+    /// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
+    ///
+    /// Use the `withValue` function to evaluate the passed closure without modifying the `Result` instance.
+    ///
+    /// - Parameter closure: A closure that takes the success value of this instance.
+    /// - Returns: This `Result` instance, unmodified.
+    @discardableResult
+    public func withValue(_ closure: (Value) throws -> Void) rethrows -> Result {
+        if case let .success(value) = self { try closure(value) }
+
+        return self
+    }
+
+    /// Evaluates the specified closure when the `Result` is a failure, passing the unwrapped error as a parameter.
+    ///
+    /// Use the `withError` function to evaluate the passed closure without modifying the `Result` instance.
+    ///
+    /// - Parameter closure: A closure that takes the success value of this instance.
+    /// - Returns: This `Result` instance, unmodified.
+    @discardableResult
+    public func withError(_ closure: (Error) throws -> Void) rethrows -> Result {
+        if case let .failure(error) = self { try closure(error) }
+
+        return self
+    }
+
+    /// Evaluates the specified closure when the `Result` is a success.
+    ///
+    /// Use the `ifSuccess` function to evaluate the passed closure without modifying the `Result` instance.
+    ///
+    /// - Parameter closure: A `Void` closure.
+    /// - Returns: This `Result` instance, unmodified.
+    @discardableResult
+    public func ifSuccess(_ closure: () throws -> Void) rethrows -> Result {
+        if isSuccess { try closure() }
+
+        return self
+    }
+
+    /// Evaluates the specified closure when the `Result` is a failure.
+    ///
+    /// Use the `ifFailure` function to evaluate the passed closure without modifying the `Result` instance.
+    ///
+    /// - Parameter closure: A `Void` closure.
+    /// - Returns: This `Result` instance, unmodified.
+    @discardableResult
+    public func ifFailure(_ closure: () throws -> Void) rethrows -> Result {
+        if isFailure { try closure() }
+
+        return self
+    }
+}

+ 307 - 0
RainbowPlanet/Pods/Alamofire/Source/ServerTrustPolicy.swift

@@ -0,0 +1,307 @@
+//
+//  ServerTrustPolicy.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Responsible for managing the mapping of `ServerTrustPolicy` objects to a given host.
+open class ServerTrustPolicyManager {
+    /// The dictionary of policies mapped to a particular host.
+    public let policies: [String: ServerTrustPolicy]
+
+    /// Initializes the `ServerTrustPolicyManager` instance with the given policies.
+    ///
+    /// Since different servers and web services can have different leaf certificates, intermediate and even root
+    /// certficates, it is important to have the flexibility to specify evaluation policies on a per host basis. This
+    /// allows for scenarios such as using default evaluation for host1, certificate pinning for host2, public key
+    /// pinning for host3 and disabling evaluation for host4.
+    ///
+    /// - parameter policies: A dictionary of all policies mapped to a particular host.
+    ///
+    /// - returns: The new `ServerTrustPolicyManager` instance.
+    public init(policies: [String: ServerTrustPolicy]) {
+        self.policies = policies
+    }
+
+    /// Returns the `ServerTrustPolicy` for the given host if applicable.
+    ///
+    /// By default, this method will return the policy that perfectly matches the given host. Subclasses could override
+    /// this method and implement more complex mapping implementations such as wildcards.
+    ///
+    /// - parameter host: The host to use when searching for a matching policy.
+    ///
+    /// - returns: The server trust policy for the given host if found.
+    open func serverTrustPolicy(forHost host: String) -> ServerTrustPolicy? {
+        return policies[host]
+    }
+}
+
+// MARK: -
+
+extension URLSession {
+    private struct AssociatedKeys {
+        static var managerKey = "URLSession.ServerTrustPolicyManager"
+    }
+
+    var serverTrustPolicyManager: ServerTrustPolicyManager? {
+        get {
+            return objc_getAssociatedObject(self, &AssociatedKeys.managerKey) as? ServerTrustPolicyManager
+        }
+        set (manager) {
+            objc_setAssociatedObject(self, &AssociatedKeys.managerKey, manager, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
+        }
+    }
+}
+
+// MARK: - ServerTrustPolicy
+
+/// The `ServerTrustPolicy` evaluates the server trust generally provided by an `NSURLAuthenticationChallenge` when
+/// connecting to a server over a secure HTTPS connection. The policy configuration then evaluates the server trust
+/// with a given set of criteria to determine whether the server trust is valid and the connection should be made.
+///
+/// Using pinned certificates or public keys for evaluation helps prevent man-in-the-middle (MITM) attacks and other
+/// vulnerabilities. Applications dealing with sensitive customer data or financial information are strongly encouraged
+/// to route all communication over an HTTPS connection with pinning enabled.
+///
+/// - performDefaultEvaluation: Uses the default server trust evaluation while allowing you to control whether to
+///                             validate the host provided by the challenge. Applications are encouraged to always
+///                             validate the host in production environments to guarantee the validity of the server's
+///                             certificate chain.
+///
+/// - performRevokedEvaluation: Uses the default and revoked server trust evaluations allowing you to control whether to
+///                             validate the host provided by the challenge as well as specify the revocation flags for
+///                             testing for revoked certificates. Apple platforms did not start testing for revoked
+///                             certificates automatically until iOS 10.1, macOS 10.12 and tvOS 10.1 which is
+///                             demonstrated in our TLS tests. Applications are encouraged to always validate the host
+///                             in production environments to guarantee the validity of the server's certificate chain.
+///
+/// - pinCertificates:          Uses the pinned certificates to validate the server trust. The server trust is
+///                             considered valid if one of the pinned certificates match one of the server certificates.
+///                             By validating both the certificate chain and host, certificate pinning provides a very
+///                             secure form of server trust validation mitigating most, if not all, MITM attacks.
+///                             Applications are encouraged to always validate the host and require a valid certificate
+///                             chain in production environments.
+///
+/// - pinPublicKeys:            Uses the pinned public keys to validate the server trust. The server trust is considered
+///                             valid if one of the pinned public keys match one of the server certificate public keys.
+///                             By validating both the certificate chain and host, public key pinning provides a very
+///                             secure form of server trust validation mitigating most, if not all, MITM attacks.
+///                             Applications are encouraged to always validate the host and require a valid certificate
+///                             chain in production environments.
+///
+/// - disableEvaluation:        Disables all evaluation which in turn will always consider any server trust as valid.
+///
+/// - customEvaluation:         Uses the associated closure to evaluate the validity of the server trust.
+public enum ServerTrustPolicy {
+    case performDefaultEvaluation(validateHost: Bool)
+    case performRevokedEvaluation(validateHost: Bool, revocationFlags: CFOptionFlags)
+    case pinCertificates(certificates: [SecCertificate], validateCertificateChain: Bool, validateHost: Bool)
+    case pinPublicKeys(publicKeys: [SecKey], validateCertificateChain: Bool, validateHost: Bool)
+    case disableEvaluation
+    case customEvaluation((_ serverTrust: SecTrust, _ host: String) -> Bool)
+
+    // MARK: - Bundle Location
+
+    /// Returns all certificates within the given bundle with a `.cer` file extension.
+    ///
+    /// - parameter bundle: The bundle to search for all `.cer` files.
+    ///
+    /// - returns: All certificates within the given bundle.
+    public static func certificates(in bundle: Bundle = Bundle.main) -> [SecCertificate] {
+        var certificates: [SecCertificate] = []
+
+        let paths = Set([".cer", ".CER", ".crt", ".CRT", ".der", ".DER"].map { fileExtension in
+            bundle.paths(forResourcesOfType: fileExtension, inDirectory: nil)
+        }.joined())
+
+        for path in paths {
+            if
+                let certificateData = try? Data(contentsOf: URL(fileURLWithPath: path)) as CFData,
+                let certificate = SecCertificateCreateWithData(nil, certificateData)
+            {
+                certificates.append(certificate)
+            }
+        }
+
+        return certificates
+    }
+
+    /// Returns all public keys within the given bundle with a `.cer` file extension.
+    ///
+    /// - parameter bundle: The bundle to search for all `*.cer` files.
+    ///
+    /// - returns: All public keys within the given bundle.
+    public static func publicKeys(in bundle: Bundle = Bundle.main) -> [SecKey] {
+        var publicKeys: [SecKey] = []
+
+        for certificate in certificates(in: bundle) {
+            if let publicKey = publicKey(for: certificate) {
+                publicKeys.append(publicKey)
+            }
+        }
+
+        return publicKeys
+    }
+
+    // MARK: - Evaluation
+
+    /// Evaluates whether the server trust is valid for the given host.
+    ///
+    /// - parameter serverTrust: The server trust to evaluate.
+    /// - parameter host:        The host of the challenge protection space.
+    ///
+    /// - returns: Whether the server trust is valid.
+    public func evaluate(_ serverTrust: SecTrust, forHost host: String) -> Bool {
+        var serverTrustIsValid = false
+
+        switch self {
+        case let .performDefaultEvaluation(validateHost):
+            let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+            SecTrustSetPolicies(serverTrust, policy)
+
+            serverTrustIsValid = trustIsValid(serverTrust)
+        case let .performRevokedEvaluation(validateHost, revocationFlags):
+            let defaultPolicy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+            let revokedPolicy = SecPolicyCreateRevocation(revocationFlags)
+            SecTrustSetPolicies(serverTrust, [defaultPolicy, revokedPolicy] as CFTypeRef)
+
+            serverTrustIsValid = trustIsValid(serverTrust)
+        case let .pinCertificates(pinnedCertificates, validateCertificateChain, validateHost):
+            if validateCertificateChain {
+                let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+                SecTrustSetPolicies(serverTrust, policy)
+
+                SecTrustSetAnchorCertificates(serverTrust, pinnedCertificates as CFArray)
+                SecTrustSetAnchorCertificatesOnly(serverTrust, true)
+
+                serverTrustIsValid = trustIsValid(serverTrust)
+            } else {
+                let serverCertificatesDataArray = certificateData(for: serverTrust)
+                let pinnedCertificatesDataArray = certificateData(for: pinnedCertificates)
+
+                outerLoop: for serverCertificateData in serverCertificatesDataArray {
+                    for pinnedCertificateData in pinnedCertificatesDataArray {
+                        if serverCertificateData == pinnedCertificateData {
+                            serverTrustIsValid = true
+                            break outerLoop
+                        }
+                    }
+                }
+            }
+        case let .pinPublicKeys(pinnedPublicKeys, validateCertificateChain, validateHost):
+            var certificateChainEvaluationPassed = true
+
+            if validateCertificateChain {
+                let policy = SecPolicyCreateSSL(true, validateHost ? host as CFString : nil)
+                SecTrustSetPolicies(serverTrust, policy)
+
+                certificateChainEvaluationPassed = trustIsValid(serverTrust)
+            }
+
+            if certificateChainEvaluationPassed {
+                outerLoop: for serverPublicKey in ServerTrustPolicy.publicKeys(for: serverTrust) as [AnyObject] {
+                    for pinnedPublicKey in pinnedPublicKeys as [AnyObject] {
+                        if serverPublicKey.isEqual(pinnedPublicKey) {
+                            serverTrustIsValid = true
+                            break outerLoop
+                        }
+                    }
+                }
+            }
+        case .disableEvaluation:
+            serverTrustIsValid = true
+        case let .customEvaluation(closure):
+            serverTrustIsValid = closure(serverTrust, host)
+        }
+
+        return serverTrustIsValid
+    }
+
+    // MARK: - Private - Trust Validation
+
+    private func trustIsValid(_ trust: SecTrust) -> Bool {
+        var isValid = false
+
+        var result = SecTrustResultType.invalid
+        let status = SecTrustEvaluate(trust, &result)
+
+        if status == errSecSuccess {
+            let unspecified = SecTrustResultType.unspecified
+            let proceed = SecTrustResultType.proceed
+
+
+            isValid = result == unspecified || result == proceed
+        }
+
+        return isValid
+    }
+
+    // MARK: - Private - Certificate Data
+
+    private func certificateData(for trust: SecTrust) -> [Data] {
+        var certificates: [SecCertificate] = []
+
+        for index in 0..<SecTrustGetCertificateCount(trust) {
+            if let certificate = SecTrustGetCertificateAtIndex(trust, index) {
+                certificates.append(certificate)
+            }
+        }
+
+        return certificateData(for: certificates)
+    }
+
+    private func certificateData(for certificates: [SecCertificate]) -> [Data] {
+        return certificates.map { SecCertificateCopyData($0) as Data }
+    }
+
+    // MARK: - Private - Public Key Extraction
+
+    private static func publicKeys(for trust: SecTrust) -> [SecKey] {
+        var publicKeys: [SecKey] = []
+
+        for index in 0..<SecTrustGetCertificateCount(trust) {
+            if
+                let certificate = SecTrustGetCertificateAtIndex(trust, index),
+                let publicKey = publicKey(for: certificate)
+            {
+                publicKeys.append(publicKey)
+            }
+        }
+
+        return publicKeys
+    }
+
+    private static func publicKey(for certificate: SecCertificate) -> SecKey? {
+        var publicKey: SecKey?
+
+        let policy = SecPolicyCreateBasicX509()
+        var trust: SecTrust?
+        let trustCreationStatus = SecTrustCreateWithCertificates(certificate, policy, &trust)
+
+        if let trust = trust, trustCreationStatus == errSecSuccess {
+            publicKey = SecTrustCopyPublicKey(trust)
+        }
+
+        return publicKey
+    }
+}

+ 725 - 0
RainbowPlanet/Pods/Alamofire/Source/SessionDelegate.swift

@@ -0,0 +1,725 @@
+//
+//  SessionDelegate.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Responsible for handling all delegate callbacks for the underlying session.
+open class SessionDelegate: NSObject {
+
+    // MARK: URLSessionDelegate Overrides
+
+    /// Overrides default behavior for URLSessionDelegate method `urlSession(_:didBecomeInvalidWithError:)`.
+    open var sessionDidBecomeInvalidWithError: ((URLSession, Error?) -> Void)?
+
+    /// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`.
+    open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
+
+    /// Overrides all behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)` and requires the caller to call the `completionHandler`.
+    open var sessionDidReceiveChallengeWithCompletion: ((URLSession, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)?
+
+    /// Overrides default behavior for URLSessionDelegate method `urlSessionDidFinishEvents(forBackgroundURLSession:)`.
+    open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)?
+
+    // MARK: URLSessionTaskDelegate Overrides
+
+    /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`.
+    open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)?
+
+    /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)` and
+    /// requires the caller to call the `completionHandler`.
+    open var taskWillPerformHTTPRedirectionWithCompletion: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest, @escaping (URLRequest?) -> Void) -> Void)?
+
+    /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)`.
+    open var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
+
+    /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:didReceive:completionHandler:)` and
+    /// requires the caller to call the `completionHandler`.
+    open var taskDidReceiveChallengeWithCompletion: ((URLSession, URLSessionTask, URLAuthenticationChallenge, @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) -> Void)?
+
+    /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)`.
+    open var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)?
+
+    /// Overrides all behavior for URLSessionTaskDelegate method `urlSession(_:task:needNewBodyStream:)` and
+    /// requires the caller to call the `completionHandler`.
+    open var taskNeedNewBodyStreamWithCompletion: ((URLSession, URLSessionTask, @escaping (InputStream?) -> Void) -> Void)?
+
+    /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)`.
+    open var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
+
+    /// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:didCompleteWithError:)`.
+    open var taskDidComplete: ((URLSession, URLSessionTask, Error?) -> Void)?
+
+    // MARK: URLSessionDataDelegate Overrides
+
+    /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)`.
+    open var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)?
+
+    /// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:completionHandler:)` and
+    /// requires caller to call the `completionHandler`.
+    open var dataTaskDidReceiveResponseWithCompletion: ((URLSession, URLSessionDataTask, URLResponse, @escaping (URLSession.ResponseDisposition) -> Void) -> Void)?
+
+    /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didBecome:)`.
+    open var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)?
+
+    /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:didReceive:)`.
+    open var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
+
+    /// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)`.
+    open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)?
+
+    /// Overrides all behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)` and
+    /// requires caller to call the `completionHandler`.
+    open var dataTaskWillCacheResponseWithCompletion: ((URLSession, URLSessionDataTask, CachedURLResponse, @escaping (CachedURLResponse?) -> Void) -> Void)?
+
+    // MARK: URLSessionDownloadDelegate Overrides
+
+    /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didFinishDownloadingTo:)`.
+    open var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> Void)?
+
+    /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)`.
+    open var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
+
+    /// Overrides default behavior for URLSessionDownloadDelegate method `urlSession(_:downloadTask:didResumeAtOffset:expectedTotalBytes:)`.
+    open var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
+
+    // MARK: URLSessionStreamDelegate Overrides
+
+#if !os(watchOS)
+
+    /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:readClosedFor:)`.
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    open var streamTaskReadClosed: ((URLSession, URLSessionStreamTask) -> Void)? {
+        get {
+            return _streamTaskReadClosed as? (URLSession, URLSessionStreamTask) -> Void
+        }
+        set {
+            _streamTaskReadClosed = newValue
+        }
+    }
+
+    /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:writeClosedFor:)`.
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    open var streamTaskWriteClosed: ((URLSession, URLSessionStreamTask) -> Void)? {
+        get {
+            return _streamTaskWriteClosed as? (URLSession, URLSessionStreamTask) -> Void
+        }
+        set {
+            _streamTaskWriteClosed = newValue
+        }
+    }
+
+    /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:betterRouteDiscoveredFor:)`.
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    open var streamTaskBetterRouteDiscovered: ((URLSession, URLSessionStreamTask) -> Void)? {
+        get {
+            return _streamTaskBetterRouteDiscovered as? (URLSession, URLSessionStreamTask) -> Void
+        }
+        set {
+            _streamTaskBetterRouteDiscovered = newValue
+        }
+    }
+
+    /// Overrides default behavior for URLSessionStreamDelegate method `urlSession(_:streamTask:didBecome:outputStream:)`.
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    open var streamTaskDidBecomeInputAndOutputStreams: ((URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void)? {
+        get {
+            return _streamTaskDidBecomeInputStream as? (URLSession, URLSessionStreamTask, InputStream, OutputStream) -> Void
+        }
+        set {
+            _streamTaskDidBecomeInputStream = newValue
+        }
+    }
+
+    var _streamTaskReadClosed: Any?
+    var _streamTaskWriteClosed: Any?
+    var _streamTaskBetterRouteDiscovered: Any?
+    var _streamTaskDidBecomeInputStream: Any?
+
+#endif
+
+    // MARK: Properties
+
+    var retrier: RequestRetrier?
+    weak var sessionManager: SessionManager?
+
+    var requests: [Int: Request] = [:]
+    private let lock = NSLock()
+
+    /// Access the task delegate for the specified task in a thread-safe manner.
+    open subscript(task: URLSessionTask) -> Request? {
+        get {
+            lock.lock() ; defer { lock.unlock() }
+            return requests[task.taskIdentifier]
+        }
+        set {
+            lock.lock() ; defer { lock.unlock() }
+            requests[task.taskIdentifier] = newValue
+        }
+    }
+
+    // MARK: Lifecycle
+
+    /// Initializes the `SessionDelegate` instance.
+    ///
+    /// - returns: The new `SessionDelegate` instance.
+    public override init() {
+        super.init()
+    }
+
+    // MARK: NSObject Overrides
+
+    /// Returns a `Bool` indicating whether the `SessionDelegate` implements or inherits a method that can respond
+    /// to a specified message.
+    ///
+    /// - parameter selector: A selector that identifies a message.
+    ///
+    /// - returns: `true` if the receiver implements or inherits a method that can respond to selector, otherwise `false`.
+    open override func responds(to selector: Selector) -> Bool {
+        #if !os(macOS)
+            if selector == #selector(URLSessionDelegate.urlSessionDidFinishEvents(forBackgroundURLSession:)) {
+                return sessionDidFinishEventsForBackgroundURLSession != nil
+            }
+        #endif
+
+        #if !os(watchOS)
+            if #available(iOS 9.0, macOS 10.11, tvOS 9.0, *) {
+                switch selector {
+                case #selector(URLSessionStreamDelegate.urlSession(_:readClosedFor:)):
+                    return streamTaskReadClosed != nil
+                case #selector(URLSessionStreamDelegate.urlSession(_:writeClosedFor:)):
+                    return streamTaskWriteClosed != nil
+                case #selector(URLSessionStreamDelegate.urlSession(_:betterRouteDiscoveredFor:)):
+                    return streamTaskBetterRouteDiscovered != nil
+                case #selector(URLSessionStreamDelegate.urlSession(_:streamTask:didBecome:outputStream:)):
+                    return streamTaskDidBecomeInputAndOutputStreams != nil
+                default:
+                    break
+                }
+            }
+        #endif
+
+        switch selector {
+        case #selector(URLSessionDelegate.urlSession(_:didBecomeInvalidWithError:)):
+            return sessionDidBecomeInvalidWithError != nil
+        case #selector(URLSessionDelegate.urlSession(_:didReceive:completionHandler:)):
+            return (sessionDidReceiveChallenge != nil  || sessionDidReceiveChallengeWithCompletion != nil)
+        case #selector(URLSessionTaskDelegate.urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)):
+            return (taskWillPerformHTTPRedirection != nil || taskWillPerformHTTPRedirectionWithCompletion != nil)
+        case #selector(URLSessionDataDelegate.urlSession(_:dataTask:didReceive:completionHandler:)):
+            return (dataTaskDidReceiveResponse != nil || dataTaskDidReceiveResponseWithCompletion != nil)
+        default:
+            return type(of: self).instancesRespond(to: selector)
+        }
+    }
+}
+
+// MARK: - URLSessionDelegate
+
+extension SessionDelegate: URLSessionDelegate {
+    /// Tells the delegate that the session has been invalidated.
+    ///
+    /// - parameter session: The session object that was invalidated.
+    /// - parameter error:   The error that caused invalidation, or nil if the invalidation was explicit.
+    open func urlSession(_ session: URLSession, didBecomeInvalidWithError error: Error?) {
+        sessionDidBecomeInvalidWithError?(session, error)
+    }
+
+    /// Requests credentials from the delegate in response to a session-level authentication request from the
+    /// remote server.
+    ///
+    /// - parameter session:           The session containing the task that requested authentication.
+    /// - parameter challenge:         An object that contains the request for authentication.
+    /// - parameter completionHandler: A handler that your delegate method must call providing the disposition
+    ///                                and credential.
+    open func urlSession(
+        _ session: URLSession,
+        didReceive challenge: URLAuthenticationChallenge,
+        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
+    {
+        guard sessionDidReceiveChallengeWithCompletion == nil else {
+            sessionDidReceiveChallengeWithCompletion?(session, challenge, completionHandler)
+            return
+        }
+
+        var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
+        var credential: URLCredential?
+
+        if let sessionDidReceiveChallenge = sessionDidReceiveChallenge {
+            (disposition, credential) = sessionDidReceiveChallenge(session, challenge)
+        } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
+            let host = challenge.protectionSpace.host
+
+            if
+                let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
+                let serverTrust = challenge.protectionSpace.serverTrust
+            {
+                if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
+                    disposition = .useCredential
+                    credential = URLCredential(trust: serverTrust)
+                } else {
+                    disposition = .cancelAuthenticationChallenge
+                }
+            }
+        }
+
+        completionHandler(disposition, credential)
+    }
+
+#if !os(macOS)
+
+    /// Tells the delegate that all messages enqueued for a session have been delivered.
+    ///
+    /// - parameter session: The session that no longer has any outstanding requests.
+    open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
+        sessionDidFinishEventsForBackgroundURLSession?(session)
+    }
+
+#endif
+}
+
+// MARK: - URLSessionTaskDelegate
+
+extension SessionDelegate: URLSessionTaskDelegate {
+    /// Tells the delegate that the remote server requested an HTTP redirect.
+    ///
+    /// - parameter session:           The session containing the task whose request resulted in a redirect.
+    /// - parameter task:              The task whose request resulted in a redirect.
+    /// - parameter response:          An object containing the server’s response to the original request.
+    /// - parameter request:           A URL request object filled out with the new location.
+    /// - parameter completionHandler: A closure that your handler should call with either the value of the request
+    ///                                parameter, a modified URL request object, or NULL to refuse the redirect and
+    ///                                return the body of the redirect response.
+    open func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        willPerformHTTPRedirection response: HTTPURLResponse,
+        newRequest request: URLRequest,
+        completionHandler: @escaping (URLRequest?) -> Void)
+    {
+        guard taskWillPerformHTTPRedirectionWithCompletion == nil else {
+            taskWillPerformHTTPRedirectionWithCompletion?(session, task, response, request, completionHandler)
+            return
+        }
+
+        var redirectRequest: URLRequest? = request
+
+        if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection {
+            redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request)
+        }
+
+        completionHandler(redirectRequest)
+    }
+
+    /// Requests credentials from the delegate in response to an authentication request from the remote server.
+    ///
+    /// - parameter session:           The session containing the task whose request requires authentication.
+    /// - parameter task:              The task whose request requires authentication.
+    /// - parameter challenge:         An object that contains the request for authentication.
+    /// - parameter completionHandler: A handler that your delegate method must call providing the disposition
+    ///                                and credential.
+    open func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        didReceive challenge: URLAuthenticationChallenge,
+        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
+    {
+        guard taskDidReceiveChallengeWithCompletion == nil else {
+            taskDidReceiveChallengeWithCompletion?(session, task, challenge, completionHandler)
+            return
+        }
+
+        if let taskDidReceiveChallenge = taskDidReceiveChallenge {
+            let result = taskDidReceiveChallenge(session, task, challenge)
+            completionHandler(result.0, result.1)
+        } else if let delegate = self[task]?.delegate {
+            delegate.urlSession(
+                session,
+                task: task,
+                didReceive: challenge,
+                completionHandler: completionHandler
+            )
+        } else {
+            urlSession(session, didReceive: challenge, completionHandler: completionHandler)
+        }
+    }
+
+    /// Tells the delegate when a task requires a new request body stream to send to the remote server.
+    ///
+    /// - parameter session:           The session containing the task that needs a new body stream.
+    /// - parameter task:              The task that needs a new body stream.
+    /// - parameter completionHandler: A completion handler that your delegate method should call with the new body stream.
+    open func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
+    {
+        guard taskNeedNewBodyStreamWithCompletion == nil else {
+            taskNeedNewBodyStreamWithCompletion?(session, task, completionHandler)
+            return
+        }
+
+        if let taskNeedNewBodyStream = taskNeedNewBodyStream {
+            completionHandler(taskNeedNewBodyStream(session, task))
+        } else if let delegate = self[task]?.delegate {
+            delegate.urlSession(session, task: task, needNewBodyStream: completionHandler)
+        }
+    }
+
+    /// Periodically informs the delegate of the progress of sending body content to the server.
+    ///
+    /// - parameter session:                  The session containing the data task.
+    /// - parameter task:                     The data task.
+    /// - parameter bytesSent:                The number of bytes sent since the last time this delegate method was called.
+    /// - parameter totalBytesSent:           The total number of bytes sent so far.
+    /// - parameter totalBytesExpectedToSend: The expected length of the body data.
+    open func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        didSendBodyData bytesSent: Int64,
+        totalBytesSent: Int64,
+        totalBytesExpectedToSend: Int64)
+    {
+        if let taskDidSendBodyData = taskDidSendBodyData {
+            taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
+        } else if let delegate = self[task]?.delegate as? UploadTaskDelegate {
+            delegate.URLSession(
+                session,
+                task: task,
+                didSendBodyData: bytesSent,
+                totalBytesSent: totalBytesSent,
+                totalBytesExpectedToSend: totalBytesExpectedToSend
+            )
+        }
+    }
+
+#if !os(watchOS)
+
+    /// Tells the delegate that the session finished collecting metrics for the task.
+    ///
+    /// - parameter session: The session collecting the metrics.
+    /// - parameter task:    The task whose metrics have been collected.
+    /// - parameter metrics: The collected metrics.
+    @available(iOS 10.0, macOS 10.12, tvOS 10.0, *)
+    @objc(URLSession:task:didFinishCollectingMetrics:)
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didFinishCollecting metrics: URLSessionTaskMetrics) {
+        self[task]?.delegate.metrics = metrics
+    }
+
+#endif
+
+    /// Tells the delegate that the task finished transferring data.
+    ///
+    /// - parameter session: The session containing the task whose request finished transferring data.
+    /// - parameter task:    The task whose request finished transferring data.
+    /// - parameter error:   If an error occurred, an error object indicating how the transfer failed, otherwise nil.
+    open func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+        /// Executed after it is determined that the request is not going to be retried
+        let completeTask: (URLSession, URLSessionTask, Error?) -> Void = { [weak self] session, task, error in
+            guard let strongSelf = self else { return }
+
+            strongSelf.taskDidComplete?(session, task, error)
+
+            strongSelf[task]?.delegate.urlSession(session, task: task, didCompleteWithError: error)
+
+            var userInfo: [String: Any] = [Notification.Key.Task: task]
+
+            if let data = (strongSelf[task]?.delegate as? DataTaskDelegate)?.data {
+                userInfo[Notification.Key.ResponseData] = data
+            }
+
+            NotificationCenter.default.post(
+                name: Notification.Name.Task.DidComplete,
+                object: strongSelf,
+                userInfo: userInfo
+            )
+
+            strongSelf[task] = nil
+        }
+
+        guard let request = self[task], let sessionManager = sessionManager else {
+            completeTask(session, task, error)
+            return
+        }
+
+        // Run all validations on the request before checking if an error occurred
+        request.validations.forEach { $0() }
+
+        // Determine whether an error has occurred
+        var error: Error? = error
+
+        if request.delegate.error != nil {
+            error = request.delegate.error
+        }
+
+        /// If an error occurred and the retrier is set, asynchronously ask the retrier if the request
+        /// should be retried. Otherwise, complete the task by notifying the task delegate.
+        if let retrier = retrier, let error = error {
+            retrier.should(sessionManager, retry: request, with: error) { [weak self] shouldRetry, timeDelay in
+                guard shouldRetry else { completeTask(session, task, error) ; return }
+
+                DispatchQueue.utility.after(timeDelay) { [weak self] in
+                    guard let strongSelf = self else { return }
+
+                    let retrySucceeded = strongSelf.sessionManager?.retry(request) ?? false
+
+                    if retrySucceeded, let task = request.task {
+                        strongSelf[task] = request
+                        return
+                    } else {
+                        completeTask(session, task, error)
+                    }
+                }
+            }
+        } else {
+            completeTask(session, task, error)
+        }
+    }
+}
+
+// MARK: - URLSessionDataDelegate
+
+extension SessionDelegate: URLSessionDataDelegate {
+    /// Tells the delegate that the data task received the initial reply (headers) from the server.
+    ///
+    /// - parameter session:           The session containing the data task that received an initial reply.
+    /// - parameter dataTask:          The data task that received an initial reply.
+    /// - parameter response:          A URL response object populated with headers.
+    /// - parameter completionHandler: A completion handler that your code calls to continue the transfer, passing a
+    ///                                constant to indicate whether the transfer should continue as a data task or
+    ///                                should become a download task.
+    open func urlSession(
+        _ session: URLSession,
+        dataTask: URLSessionDataTask,
+        didReceive response: URLResponse,
+        completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
+    {
+        guard dataTaskDidReceiveResponseWithCompletion == nil else {
+            dataTaskDidReceiveResponseWithCompletion?(session, dataTask, response, completionHandler)
+            return
+        }
+
+        var disposition: URLSession.ResponseDisposition = .allow
+
+        if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse {
+            disposition = dataTaskDidReceiveResponse(session, dataTask, response)
+        }
+
+        completionHandler(disposition)
+    }
+
+    /// Tells the delegate that the data task was changed to a download task.
+    ///
+    /// - parameter session:      The session containing the task that was replaced by a download task.
+    /// - parameter dataTask:     The data task that was replaced by a download task.
+    /// - parameter downloadTask: The new download task that replaced the data task.
+    open func urlSession(
+        _ session: URLSession,
+        dataTask: URLSessionDataTask,
+        didBecome downloadTask: URLSessionDownloadTask)
+    {
+        if let dataTaskDidBecomeDownloadTask = dataTaskDidBecomeDownloadTask {
+            dataTaskDidBecomeDownloadTask(session, dataTask, downloadTask)
+        } else {
+            self[downloadTask]?.delegate = DownloadTaskDelegate(task: downloadTask)
+        }
+    }
+
+    /// Tells the delegate that the data task has received some of the expected data.
+    ///
+    /// - parameter session:  The session containing the data task that provided data.
+    /// - parameter dataTask: The data task that provided data.
+    /// - parameter data:     A data object containing the transferred data.
+    open func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        if let dataTaskDidReceiveData = dataTaskDidReceiveData {
+            dataTaskDidReceiveData(session, dataTask, data)
+        } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate {
+            delegate.urlSession(session, dataTask: dataTask, didReceive: data)
+        }
+    }
+
+    /// Asks the delegate whether the data (or upload) task should store the response in the cache.
+    ///
+    /// - parameter session:           The session containing the data (or upload) task.
+    /// - parameter dataTask:          The data (or upload) task.
+    /// - parameter proposedResponse:  The default caching behavior. This behavior is determined based on the current
+    ///                                caching policy and the values of certain received headers, such as the Pragma
+    ///                                and Cache-Control headers.
+    /// - parameter completionHandler: A block that your handler must call, providing either the original proposed
+    ///                                response, a modified version of that response, or NULL to prevent caching the
+    ///                                response. If your delegate implements this method, it must call this completion
+    ///                                handler; otherwise, your app leaks memory.
+    open func urlSession(
+        _ session: URLSession,
+        dataTask: URLSessionDataTask,
+        willCacheResponse proposedResponse: CachedURLResponse,
+        completionHandler: @escaping (CachedURLResponse?) -> Void)
+    {
+        guard dataTaskWillCacheResponseWithCompletion == nil else {
+            dataTaskWillCacheResponseWithCompletion?(session, dataTask, proposedResponse, completionHandler)
+            return
+        }
+
+        if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
+            completionHandler(dataTaskWillCacheResponse(session, dataTask, proposedResponse))
+        } else if let delegate = self[dataTask]?.delegate as? DataTaskDelegate {
+            delegate.urlSession(
+                session,
+                dataTask: dataTask,
+                willCacheResponse: proposedResponse,
+                completionHandler: completionHandler
+            )
+        } else {
+            completionHandler(proposedResponse)
+        }
+    }
+}
+
+// MARK: - URLSessionDownloadDelegate
+
+extension SessionDelegate: URLSessionDownloadDelegate {
+    /// Tells the delegate that a download task has finished downloading.
+    ///
+    /// - parameter session:      The session containing the download task that finished.
+    /// - parameter downloadTask: The download task that finished.
+    /// - parameter location:     A file URL for the temporary file. Because the file is temporary, you must either
+    ///                           open the file for reading or move it to a permanent location in your app’s sandbox
+    ///                           container directory before returning from this delegate method.
+    open func urlSession(
+        _ session: URLSession,
+        downloadTask: URLSessionDownloadTask,
+        didFinishDownloadingTo location: URL)
+    {
+        if let downloadTaskDidFinishDownloadingToURL = downloadTaskDidFinishDownloadingToURL {
+            downloadTaskDidFinishDownloadingToURL(session, downloadTask, location)
+        } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
+            delegate.urlSession(session, downloadTask: downloadTask, didFinishDownloadingTo: location)
+        }
+    }
+
+    /// Periodically informs the delegate about the download’s progress.
+    ///
+    /// - parameter session:                   The session containing the download task.
+    /// - parameter downloadTask:              The download task.
+    /// - parameter bytesWritten:              The number of bytes transferred since the last time this delegate
+    ///                                        method was called.
+    /// - parameter totalBytesWritten:         The total number of bytes transferred so far.
+    /// - parameter totalBytesExpectedToWrite: The expected length of the file, as provided by the Content-Length
+    ///                                        header. If this header was not provided, the value is
+    ///                                        `NSURLSessionTransferSizeUnknown`.
+    open func urlSession(
+        _ session: URLSession,
+        downloadTask: URLSessionDownloadTask,
+        didWriteData bytesWritten: Int64,
+        totalBytesWritten: Int64,
+        totalBytesExpectedToWrite: Int64)
+    {
+        if let downloadTaskDidWriteData = downloadTaskDidWriteData {
+            downloadTaskDidWriteData(session, downloadTask, bytesWritten, totalBytesWritten, totalBytesExpectedToWrite)
+        } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
+            delegate.urlSession(
+                session,
+                downloadTask: downloadTask,
+                didWriteData: bytesWritten,
+                totalBytesWritten: totalBytesWritten,
+                totalBytesExpectedToWrite: totalBytesExpectedToWrite
+            )
+        }
+    }
+
+    /// Tells the delegate that the download task has resumed downloading.
+    ///
+    /// - parameter session:            The session containing the download task that finished.
+    /// - parameter downloadTask:       The download task that resumed. See explanation in the discussion.
+    /// - parameter fileOffset:         If the file's cache policy or last modified date prevents reuse of the
+    ///                                 existing content, then this value is zero. Otherwise, this value is an
+    ///                                 integer representing the number of bytes on disk that do not need to be
+    ///                                 retrieved again.
+    /// - parameter expectedTotalBytes: The expected length of the file, as provided by the Content-Length header.
+    ///                                 If this header was not provided, the value is NSURLSessionTransferSizeUnknown.
+    open func urlSession(
+        _ session: URLSession,
+        downloadTask: URLSessionDownloadTask,
+        didResumeAtOffset fileOffset: Int64,
+        expectedTotalBytes: Int64)
+    {
+        if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
+            downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
+        } else if let delegate = self[downloadTask]?.delegate as? DownloadTaskDelegate {
+            delegate.urlSession(
+                session,
+                downloadTask: downloadTask,
+                didResumeAtOffset: fileOffset,
+                expectedTotalBytes: expectedTotalBytes
+            )
+        }
+    }
+}
+
+// MARK: - URLSessionStreamDelegate
+
+#if !os(watchOS)
+
+@available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+extension SessionDelegate: URLSessionStreamDelegate {
+    /// Tells the delegate that the read side of the connection has been closed.
+    ///
+    /// - parameter session:    The session.
+    /// - parameter streamTask: The stream task.
+    open func urlSession(_ session: URLSession, readClosedFor streamTask: URLSessionStreamTask) {
+        streamTaskReadClosed?(session, streamTask)
+    }
+
+    /// Tells the delegate that the write side of the connection has been closed.
+    ///
+    /// - parameter session:    The session.
+    /// - parameter streamTask: The stream task.
+    open func urlSession(_ session: URLSession, writeClosedFor streamTask: URLSessionStreamTask) {
+        streamTaskWriteClosed?(session, streamTask)
+    }
+
+    /// Tells the delegate that the system has determined that a better route to the host is available.
+    ///
+    /// - parameter session:    The session.
+    /// - parameter streamTask: The stream task.
+    open func urlSession(_ session: URLSession, betterRouteDiscoveredFor streamTask: URLSessionStreamTask) {
+        streamTaskBetterRouteDiscovered?(session, streamTask)
+    }
+
+    /// Tells the delegate that the stream task has been completed and provides the unopened stream objects.
+    ///
+    /// - parameter session:      The session.
+    /// - parameter streamTask:   The stream task.
+    /// - parameter inputStream:  The new input stream.
+    /// - parameter outputStream: The new output stream.
+    open func urlSession(
+        _ session: URLSession,
+        streamTask: URLSessionStreamTask,
+        didBecome inputStream: InputStream,
+        outputStream: OutputStream)
+    {
+        streamTaskDidBecomeInputAndOutputStreams?(session, streamTask, inputStream, outputStream)
+    }
+}
+
+#endif

+ 899 - 0
RainbowPlanet/Pods/Alamofire/Source/SessionManager.swift

@@ -0,0 +1,899 @@
+//
+//  SessionManager.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Responsible for creating and managing `Request` objects, as well as their underlying `NSURLSession`.
+open class SessionManager {
+
+    // MARK: - Helper Types
+
+    /// Defines whether the `MultipartFormData` encoding was successful and contains result of the encoding as
+    /// associated values.
+    ///
+    /// - Success: Represents a successful `MultipartFormData` encoding and contains the new `UploadRequest` along with
+    ///            streaming information.
+    /// - Failure: Used to represent a failure in the `MultipartFormData` encoding and also contains the encoding
+    ///            error.
+    public enum MultipartFormDataEncodingResult {
+        case success(request: UploadRequest, streamingFromDisk: Bool, streamFileURL: URL?)
+        case failure(Error)
+    }
+
+    // MARK: - Properties
+
+    /// A default instance of `SessionManager`, used by top-level Alamofire request methods, and suitable for use
+    /// directly for any ad hoc requests.
+    public static let `default`: SessionManager = {
+        let configuration = URLSessionConfiguration.default
+        configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
+
+        return SessionManager(configuration: configuration)
+    }()
+
+    /// Creates default values for the "Accept-Encoding", "Accept-Language" and "User-Agent" headers.
+    public static let defaultHTTPHeaders: HTTPHeaders = {
+        // Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3
+        let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5"
+
+        // Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5
+        let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in
+            let quality = 1.0 - (Double(index) * 0.1)
+            return "\(languageCode);q=\(quality)"
+        }.joined(separator: ", ")
+
+        // User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3
+        // Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0`
+        let userAgent: String = {
+            if let info = Bundle.main.infoDictionary {
+                let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
+                let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
+                let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
+                let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
+
+                let osNameVersion: String = {
+                    let version = ProcessInfo.processInfo.operatingSystemVersion
+                    let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
+
+                    let osName: String = {
+                        #if os(iOS)
+                            return "iOS"
+                        #elseif os(watchOS)
+                            return "watchOS"
+                        #elseif os(tvOS)
+                            return "tvOS"
+                        #elseif os(macOS)
+                            return "OS X"
+                        #elseif os(Linux)
+                            return "Linux"
+                        #else
+                            return "Unknown"
+                        #endif
+                    }()
+
+                    return "\(osName) \(versionString)"
+                }()
+
+                let alamofireVersion: String = {
+                    guard
+                        let afInfo = Bundle(for: SessionManager.self).infoDictionary,
+                        let build = afInfo["CFBundleShortVersionString"]
+                    else { return "Unknown" }
+
+                    return "Alamofire/\(build)"
+                }()
+
+                return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
+            }
+
+            return "Alamofire"
+        }()
+
+        return [
+            "Accept-Encoding": acceptEncoding,
+            "Accept-Language": acceptLanguage,
+            "User-Agent": userAgent
+        ]
+    }()
+
+    /// Default memory threshold used when encoding `MultipartFormData` in bytes.
+    public static let multipartFormDataEncodingMemoryThreshold: UInt64 = 10_000_000
+
+    /// The underlying session.
+    public let session: URLSession
+
+    /// The session delegate handling all the task and session delegate callbacks.
+    public let delegate: SessionDelegate
+
+    /// Whether to start requests immediately after being constructed. `true` by default.
+    open var startRequestsImmediately: Bool = true
+
+    /// The request adapter called each time a new request is created.
+    open var adapter: RequestAdapter?
+
+    /// The request retrier called each time a request encounters an error to determine whether to retry the request.
+    open var retrier: RequestRetrier? {
+        get { return delegate.retrier }
+        set { delegate.retrier = newValue }
+    }
+
+    /// The background completion handler closure provided by the UIApplicationDelegate
+    /// `application:handleEventsForBackgroundURLSession:completionHandler:` method. By setting the background
+    /// completion handler, the SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` closure implementation
+    /// will automatically call the handler.
+    ///
+    /// If you need to handle your own events before the handler is called, then you need to override the
+    /// SessionDelegate `sessionDidFinishEventsForBackgroundURLSession` and manually call the handler when finished.
+    ///
+    /// `nil` by default.
+    open var backgroundCompletionHandler: (() -> Void)?
+
+    let queue = DispatchQueue(label: "org.alamofire.session-manager." + UUID().uuidString)
+
+    // MARK: - Lifecycle
+
+    /// Creates an instance with the specified `configuration`, `delegate` and `serverTrustPolicyManager`.
+    ///
+    /// - parameter configuration:            The configuration used to construct the managed session.
+    ///                                       `URLSessionConfiguration.default` by default.
+    /// - parameter delegate:                 The delegate used when initializing the session. `SessionDelegate()` by
+    ///                                       default.
+    /// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
+    ///                                       challenges. `nil` by default.
+    ///
+    /// - returns: The new `SessionManager` instance.
+    public init(
+        configuration: URLSessionConfiguration = URLSessionConfiguration.default,
+        delegate: SessionDelegate = SessionDelegate(),
+        serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
+    {
+        self.delegate = delegate
+        self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
+
+        commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
+    }
+
+    /// Creates an instance with the specified `session`, `delegate` and `serverTrustPolicyManager`.
+    ///
+    /// - parameter session:                  The URL session.
+    /// - parameter delegate:                 The delegate of the URL session. Must equal the URL session's delegate.
+    /// - parameter serverTrustPolicyManager: The server trust policy manager to use for evaluating all server trust
+    ///                                       challenges. `nil` by default.
+    ///
+    /// - returns: The new `SessionManager` instance if the URL session's delegate matches; `nil` otherwise.
+    public init?(
+        session: URLSession,
+        delegate: SessionDelegate,
+        serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
+    {
+        guard delegate === session.delegate else { return nil }
+
+        self.delegate = delegate
+        self.session = session
+
+        commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
+    }
+
+    private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?) {
+        session.serverTrustPolicyManager = serverTrustPolicyManager
+
+        delegate.sessionManager = self
+
+        delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
+            guard let strongSelf = self else { return }
+            DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() }
+        }
+    }
+
+    deinit {
+        session.invalidateAndCancel()
+    }
+
+    // MARK: - Data Request
+
+    /// Creates a `DataRequest` to retrieve the contents of the specified `url`, `method`, `parameters`, `encoding`
+    /// and `headers`.
+    ///
+    /// - parameter url:        The URL.
+    /// - parameter method:     The HTTP method. `.get` by default.
+    /// - parameter parameters: The parameters. `nil` by default.
+    /// - parameter encoding:   The parameter encoding. `URLEncoding.default` by default.
+    /// - parameter headers:    The HTTP headers. `nil` by default.
+    ///
+    /// - returns: The created `DataRequest`.
+    @discardableResult
+    open func request(
+        _ url: URLConvertible,
+        method: HTTPMethod = .get,
+        parameters: Parameters? = nil,
+        encoding: ParameterEncoding = URLEncoding.default,
+        headers: HTTPHeaders? = nil)
+        -> DataRequest
+    {
+        var originalRequest: URLRequest?
+
+        do {
+            originalRequest = try URLRequest(url: url, method: method, headers: headers)
+            let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
+            return request(encodedURLRequest)
+        } catch {
+            return request(originalRequest, failedWith: error)
+        }
+    }
+
+    /// Creates a `DataRequest` to retrieve the contents of a URL based on the specified `urlRequest`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter urlRequest: The URL request.
+    ///
+    /// - returns: The created `DataRequest`.
+    @discardableResult
+    open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
+        var originalRequest: URLRequest?
+
+        do {
+            originalRequest = try urlRequest.asURLRequest()
+            let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
+
+            let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
+            let request = DataRequest(session: session, requestTask: .data(originalTask, task))
+
+            delegate[task] = request
+
+            if startRequestsImmediately { request.resume() }
+
+            return request
+        } catch {
+            return request(originalRequest, failedWith: error)
+        }
+    }
+
+    // MARK: Private - Request Implementation
+
+    private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest {
+        var requestTask: Request.RequestTask = .data(nil, nil)
+
+        if let urlRequest = urlRequest {
+            let originalTask = DataRequest.Requestable(urlRequest: urlRequest)
+            requestTask = .data(originalTask, nil)
+        }
+
+        let underlyingError = error.underlyingAdaptError ?? error
+        let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError)
+
+        if let retrier = retrier, error is AdaptError {
+            allowRetrier(retrier, toRetry: request, with: underlyingError)
+        } else {
+            if startRequestsImmediately { request.resume() }
+        }
+
+        return request
+    }
+
+    // MARK: - Download Request
+
+    // MARK: URL Request
+
+    /// Creates a `DownloadRequest` to retrieve the contents the specified `url`, `method`, `parameters`, `encoding`,
+    /// `headers` and save them to the `destination`.
+    ///
+    /// If `destination` is not specified, the contents will remain in the temporary location determined by the
+    /// underlying URL session.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter url:         The URL.
+    /// - parameter method:      The HTTP method. `.get` by default.
+    /// - parameter parameters:  The parameters. `nil` by default.
+    /// - parameter encoding:    The parameter encoding. `URLEncoding.default` by default.
+    /// - parameter headers:     The HTTP headers. `nil` by default.
+    /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
+    ///
+    /// - returns: The created `DownloadRequest`.
+    @discardableResult
+    open func download(
+        _ url: URLConvertible,
+        method: HTTPMethod = .get,
+        parameters: Parameters? = nil,
+        encoding: ParameterEncoding = URLEncoding.default,
+        headers: HTTPHeaders? = nil,
+        to destination: DownloadRequest.DownloadFileDestination? = nil)
+        -> DownloadRequest
+    {
+        do {
+            let urlRequest = try URLRequest(url: url, method: method, headers: headers)
+            let encodedURLRequest = try encoding.encode(urlRequest, with: parameters)
+            return download(encodedURLRequest, to: destination)
+        } catch {
+            return download(nil, to: destination, failedWith: error)
+        }
+    }
+
+    /// Creates a `DownloadRequest` to retrieve the contents of a URL based on the specified `urlRequest` and save
+    /// them to the `destination`.
+    ///
+    /// If `destination` is not specified, the contents will remain in the temporary location determined by the
+    /// underlying URL session.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter urlRequest:  The URL request
+    /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
+    ///
+    /// - returns: The created `DownloadRequest`.
+    @discardableResult
+    open func download(
+        _ urlRequest: URLRequestConvertible,
+        to destination: DownloadRequest.DownloadFileDestination? = nil)
+        -> DownloadRequest
+    {
+        do {
+            let urlRequest = try urlRequest.asURLRequest()
+            return download(.request(urlRequest), to: destination)
+        } catch {
+            return download(nil, to: destination, failedWith: error)
+        }
+    }
+
+    // MARK: Resume Data
+
+    /// Creates a `DownloadRequest` from the `resumeData` produced from a previous request cancellation to retrieve
+    /// the contents of the original request and save them to the `destination`.
+    ///
+    /// If `destination` is not specified, the contents will remain in the temporary location determined by the
+    /// underlying URL session.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// On the latest release of all the Apple platforms (iOS 10, macOS 10.12, tvOS 10, watchOS 3), `resumeData` is broken
+    /// on background URL session configurations. There's an underlying bug in the `resumeData` generation logic where the
+    /// data is written incorrectly and will always fail to resume the download. For more information about the bug and
+    /// possible workarounds, please refer to the following Stack Overflow post:
+    ///
+    ///    - http://stackoverflow.com/a/39347461/1342462
+    ///
+    /// - parameter resumeData:  The resume data. This is an opaque data blob produced by `URLSessionDownloadTask`
+    ///                          when a task is cancelled. See `URLSession -downloadTask(withResumeData:)` for
+    ///                          additional information.
+    /// - parameter destination: The closure used to determine the destination of the downloaded file. `nil` by default.
+    ///
+    /// - returns: The created `DownloadRequest`.
+    @discardableResult
+    open func download(
+        resumingWith resumeData: Data,
+        to destination: DownloadRequest.DownloadFileDestination? = nil)
+        -> DownloadRequest
+    {
+        return download(.resumeData(resumeData), to: destination)
+    }
+
+    // MARK: Private - Download Implementation
+
+    private func download(
+        _ downloadable: DownloadRequest.Downloadable,
+        to destination: DownloadRequest.DownloadFileDestination?)
+        -> DownloadRequest
+    {
+        do {
+            let task = try downloadable.task(session: session, adapter: adapter, queue: queue)
+            let download = DownloadRequest(session: session, requestTask: .download(downloadable, task))
+
+            download.downloadDelegate.destination = destination
+
+            delegate[task] = download
+
+            if startRequestsImmediately { download.resume() }
+
+            return download
+        } catch {
+            return download(downloadable, to: destination, failedWith: error)
+        }
+    }
+
+    private func download(
+        _ downloadable: DownloadRequest.Downloadable?,
+        to destination: DownloadRequest.DownloadFileDestination?,
+        failedWith error: Error)
+        -> DownloadRequest
+    {
+        var downloadTask: Request.RequestTask = .download(nil, nil)
+
+        if let downloadable = downloadable {
+            downloadTask = .download(downloadable, nil)
+        }
+
+        let underlyingError = error.underlyingAdaptError ?? error
+
+        let download = DownloadRequest(session: session, requestTask: downloadTask, error: underlyingError)
+        download.downloadDelegate.destination = destination
+
+        if let retrier = retrier, error is AdaptError {
+            allowRetrier(retrier, toRetry: download, with: underlyingError)
+        } else {
+            if startRequestsImmediately { download.resume() }
+        }
+
+        return download
+    }
+
+    // MARK: - Upload Request
+
+    // MARK: File
+
+    /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `file`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter file:    The file to upload.
+    /// - parameter url:     The URL.
+    /// - parameter method:  The HTTP method. `.post` by default.
+    /// - parameter headers: The HTTP headers. `nil` by default.
+    ///
+    /// - returns: The created `UploadRequest`.
+    @discardableResult
+    open func upload(
+        _ fileURL: URL,
+        to url: URLConvertible,
+        method: HTTPMethod = .post,
+        headers: HTTPHeaders? = nil)
+        -> UploadRequest
+    {
+        do {
+            let urlRequest = try URLRequest(url: url, method: method, headers: headers)
+            return upload(fileURL, with: urlRequest)
+        } catch {
+            return upload(nil, failedWith: error)
+        }
+    }
+
+    /// Creates a `UploadRequest` from the specified `urlRequest` for uploading the `file`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter file:       The file to upload.
+    /// - parameter urlRequest: The URL request.
+    ///
+    /// - returns: The created `UploadRequest`.
+    @discardableResult
+    open func upload(_ fileURL: URL, with urlRequest: URLRequestConvertible) -> UploadRequest {
+        do {
+            let urlRequest = try urlRequest.asURLRequest()
+            return upload(.file(fileURL, urlRequest))
+        } catch {
+            return upload(nil, failedWith: error)
+        }
+    }
+
+    // MARK: Data
+
+    /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `data`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter data:    The data to upload.
+    /// - parameter url:     The URL.
+    /// - parameter method:  The HTTP method. `.post` by default.
+    /// - parameter headers: The HTTP headers. `nil` by default.
+    ///
+    /// - returns: The created `UploadRequest`.
+    @discardableResult
+    open func upload(
+        _ data: Data,
+        to url: URLConvertible,
+        method: HTTPMethod = .post,
+        headers: HTTPHeaders? = nil)
+        -> UploadRequest
+    {
+        do {
+            let urlRequest = try URLRequest(url: url, method: method, headers: headers)
+            return upload(data, with: urlRequest)
+        } catch {
+            return upload(nil, failedWith: error)
+        }
+    }
+
+    /// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `data`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter data:       The data to upload.
+    /// - parameter urlRequest: The URL request.
+    ///
+    /// - returns: The created `UploadRequest`.
+    @discardableResult
+    open func upload(_ data: Data, with urlRequest: URLRequestConvertible) -> UploadRequest {
+        do {
+            let urlRequest = try urlRequest.asURLRequest()
+            return upload(.data(data, urlRequest))
+        } catch {
+            return upload(nil, failedWith: error)
+        }
+    }
+
+    // MARK: InputStream
+
+    /// Creates an `UploadRequest` from the specified `url`, `method` and `headers` for uploading the `stream`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter stream:  The stream to upload.
+    /// - parameter url:     The URL.
+    /// - parameter method:  The HTTP method. `.post` by default.
+    /// - parameter headers: The HTTP headers. `nil` by default.
+    ///
+    /// - returns: The created `UploadRequest`.
+    @discardableResult
+    open func upload(
+        _ stream: InputStream,
+        to url: URLConvertible,
+        method: HTTPMethod = .post,
+        headers: HTTPHeaders? = nil)
+        -> UploadRequest
+    {
+        do {
+            let urlRequest = try URLRequest(url: url, method: method, headers: headers)
+            return upload(stream, with: urlRequest)
+        } catch {
+            return upload(nil, failedWith: error)
+        }
+    }
+
+    /// Creates an `UploadRequest` from the specified `urlRequest` for uploading the `stream`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter stream:     The stream to upload.
+    /// - parameter urlRequest: The URL request.
+    ///
+    /// - returns: The created `UploadRequest`.
+    @discardableResult
+    open func upload(_ stream: InputStream, with urlRequest: URLRequestConvertible) -> UploadRequest {
+        do {
+            let urlRequest = try urlRequest.asURLRequest()
+            return upload(.stream(stream, urlRequest))
+        } catch {
+            return upload(nil, failedWith: error)
+        }
+    }
+
+    // MARK: MultipartFormData
+
+    /// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new
+    /// `UploadRequest` using the `url`, `method` and `headers`.
+    ///
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
+    /// used for larger payloads such as video content.
+    ///
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
+    /// technique was used.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+    /// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+    ///                                      `multipartFormDataEncodingMemoryThreshold` by default.
+    /// - parameter url:                     The URL.
+    /// - parameter method:                  The HTTP method. `.post` by default.
+    /// - parameter headers:                 The HTTP headers. `nil` by default.
+    /// - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+    open func upload(
+        multipartFormData: @escaping (MultipartFormData) -> Void,
+        usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
+        to url: URLConvertible,
+        method: HTTPMethod = .post,
+        headers: HTTPHeaders? = nil,
+        queue: DispatchQueue? = nil,
+        encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
+    {
+        do {
+            let urlRequest = try URLRequest(url: url, method: method, headers: headers)
+
+            return upload(
+                multipartFormData: multipartFormData,
+                usingThreshold: encodingMemoryThreshold,
+                with: urlRequest,
+                queue: queue,
+                encodingCompletion: encodingCompletion
+            )
+        } catch {
+            (queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) }
+        }
+    }
+
+    /// Encodes `multipartFormData` using `encodingMemoryThreshold` and calls `encodingCompletion` with new
+    /// `UploadRequest` using the `urlRequest`.
+    ///
+    /// It is important to understand the memory implications of uploading `MultipartFormData`. If the cummulative
+    /// payload is small, encoding the data in-memory and directly uploading to a server is the by far the most
+    /// efficient approach. However, if the payload is too large, encoding the data in-memory could cause your app to
+    /// be terminated. Larger payloads must first be written to disk using input and output streams to keep the memory
+    /// footprint low, then the data can be uploaded as a stream from the resulting file. Streaming from disk MUST be
+    /// used for larger payloads such as video content.
+    ///
+    /// The `encodingMemoryThreshold` parameter allows Alamofire to automatically determine whether to encode in-memory
+    /// or stream from disk. If the content length of the `MultipartFormData` is below the `encodingMemoryThreshold`,
+    /// encoding takes place in-memory. If the content length exceeds the threshold, the data is streamed to disk
+    /// during the encoding process. Then the result is uploaded as data or as a stream depending on which encoding
+    /// technique was used.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter multipartFormData:       The closure used to append body parts to the `MultipartFormData`.
+    /// - parameter encodingMemoryThreshold: The encoding memory threshold in bytes.
+    ///                                      `multipartFormDataEncodingMemoryThreshold` by default.
+    /// - parameter urlRequest:              The URL request.
+    /// - parameter encodingCompletion:      The closure called when the `MultipartFormData` encoding is complete.
+    open func upload(
+        multipartFormData: @escaping (MultipartFormData) -> Void,
+        usingThreshold encodingMemoryThreshold: UInt64 = SessionManager.multipartFormDataEncodingMemoryThreshold,
+        with urlRequest: URLRequestConvertible,
+        queue: DispatchQueue? = nil,
+        encodingCompletion: ((MultipartFormDataEncodingResult) -> Void)?)
+    {
+        DispatchQueue.global(qos: .utility).async {
+            let formData = MultipartFormData()
+            multipartFormData(formData)
+
+            var tempFileURL: URL?
+
+            do {
+                var urlRequestWithContentType = try urlRequest.asURLRequest()
+                urlRequestWithContentType.setValue(formData.contentType, forHTTPHeaderField: "Content-Type")
+
+                let isBackgroundSession = self.session.configuration.identifier != nil
+
+                if formData.contentLength < encodingMemoryThreshold && !isBackgroundSession {
+                    let data = try formData.encode()
+
+                    let encodingResult = MultipartFormDataEncodingResult.success(
+                        request: self.upload(data, with: urlRequestWithContentType),
+                        streamingFromDisk: false,
+                        streamFileURL: nil
+                    )
+
+                    (queue ?? DispatchQueue.main).async { encodingCompletion?(encodingResult) }
+                } else {
+                    let fileManager = FileManager.default
+                    let tempDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory())
+                    let directoryURL = tempDirectoryURL.appendingPathComponent("org.alamofire.manager/multipart.form.data")
+                    let fileName = UUID().uuidString
+                    let fileURL = directoryURL.appendingPathComponent(fileName)
+
+                    tempFileURL = fileURL
+
+                    var directoryError: Error?
+
+                    // Create directory inside serial queue to ensure two threads don't do this in parallel
+                    self.queue.sync {
+                        do {
+                            try fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)
+                        } catch {
+                            directoryError = error
+                        }
+                    }
+
+                    if let directoryError = directoryError { throw directoryError }
+
+                    try formData.writeEncodedData(to: fileURL)
+
+                    let upload = self.upload(fileURL, with: urlRequestWithContentType)
+
+                    // Cleanup the temp file once the upload is complete
+                    upload.delegate.queue.addOperation {
+                        do {
+                            try FileManager.default.removeItem(at: fileURL)
+                        } catch {
+                            // No-op
+                        }
+                    }
+
+                    (queue ?? DispatchQueue.main).async {
+                        let encodingResult = MultipartFormDataEncodingResult.success(
+                            request: upload,
+                            streamingFromDisk: true,
+                            streamFileURL: fileURL
+                        )
+
+                        encodingCompletion?(encodingResult)
+                    }
+                }
+            } catch {
+                // Cleanup the temp file in the event that the multipart form data encoding failed
+                if let tempFileURL = tempFileURL {
+                    do {
+                        try FileManager.default.removeItem(at: tempFileURL)
+                    } catch {
+                        // No-op
+                    }
+                }
+
+                (queue ?? DispatchQueue.main).async { encodingCompletion?(.failure(error)) }
+            }
+        }
+    }
+
+    // MARK: Private - Upload Implementation
+
+    private func upload(_ uploadable: UploadRequest.Uploadable) -> UploadRequest {
+        do {
+            let task = try uploadable.task(session: session, adapter: adapter, queue: queue)
+            let upload = UploadRequest(session: session, requestTask: .upload(uploadable, task))
+
+            if case let .stream(inputStream, _) = uploadable {
+                upload.delegate.taskNeedNewBodyStream = { _, _ in inputStream }
+            }
+
+            delegate[task] = upload
+
+            if startRequestsImmediately { upload.resume() }
+
+            return upload
+        } catch {
+            return upload(uploadable, failedWith: error)
+        }
+    }
+
+    private func upload(_ uploadable: UploadRequest.Uploadable?, failedWith error: Error) -> UploadRequest {
+        var uploadTask: Request.RequestTask = .upload(nil, nil)
+
+        if let uploadable = uploadable {
+            uploadTask = .upload(uploadable, nil)
+        }
+
+        let underlyingError = error.underlyingAdaptError ?? error
+        let upload = UploadRequest(session: session, requestTask: uploadTask, error: underlyingError)
+
+        if let retrier = retrier, error is AdaptError {
+            allowRetrier(retrier, toRetry: upload, with: underlyingError)
+        } else {
+            if startRequestsImmediately { upload.resume() }
+        }
+
+        return upload
+    }
+
+#if !os(watchOS)
+
+    // MARK: - Stream Request
+
+    // MARK: Hostname and Port
+
+    /// Creates a `StreamRequest` for bidirectional streaming using the `hostname` and `port`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter hostName: The hostname of the server to connect to.
+    /// - parameter port:     The port of the server to connect to.
+    ///
+    /// - returns: The created `StreamRequest`.
+    @discardableResult
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    open func stream(withHostName hostName: String, port: Int) -> StreamRequest {
+        return stream(.stream(hostName: hostName, port: port))
+    }
+
+    // MARK: NetService
+
+    /// Creates a `StreamRequest` for bidirectional streaming using the `netService`.
+    ///
+    /// If `startRequestsImmediately` is `true`, the request will have `resume()` called before being returned.
+    ///
+    /// - parameter netService: The net service used to identify the endpoint.
+    ///
+    /// - returns: The created `StreamRequest`.
+    @discardableResult
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    open func stream(with netService: NetService) -> StreamRequest {
+        return stream(.netService(netService))
+    }
+
+    // MARK: Private - Stream Implementation
+
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    private func stream(_ streamable: StreamRequest.Streamable) -> StreamRequest {
+        do {
+            let task = try streamable.task(session: session, adapter: adapter, queue: queue)
+            let request = StreamRequest(session: session, requestTask: .stream(streamable, task))
+
+            delegate[task] = request
+
+            if startRequestsImmediately { request.resume() }
+
+            return request
+        } catch {
+            return stream(failedWith: error)
+        }
+    }
+
+    @available(iOS 9.0, macOS 10.11, tvOS 9.0, *)
+    private func stream(failedWith error: Error) -> StreamRequest {
+        let stream = StreamRequest(session: session, requestTask: .stream(nil, nil), error: error)
+        if startRequestsImmediately { stream.resume() }
+        return stream
+    }
+
+#endif
+
+    // MARK: - Internal - Retry Request
+
+    func retry(_ request: Request) -> Bool {
+        guard let originalTask = request.originalTask else { return false }
+
+        do {
+            let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
+
+            if let originalTask = request.task {
+                delegate[originalTask] = nil // removes the old request to avoid endless growth
+            }
+
+            request.delegate.task = task // resets all task delegate data
+
+            request.retryCount += 1
+            request.startTime = CFAbsoluteTimeGetCurrent()
+            request.endTime = nil
+
+            task.resume()
+
+            return true
+        } catch {
+            request.delegate.error = error.underlyingAdaptError ?? error
+            return false
+        }
+    }
+
+    private func allowRetrier(_ retrier: RequestRetrier, toRetry request: Request, with error: Error) {
+        DispatchQueue.utility.async { [weak self] in
+            guard let strongSelf = self else { return }
+
+            retrier.should(strongSelf, retry: request, with: error) { shouldRetry, timeDelay in
+                guard let strongSelf = self else { return }
+
+                guard shouldRetry else {
+                    if strongSelf.startRequestsImmediately { request.resume() }
+                    return
+                }
+
+                DispatchQueue.utility.after(timeDelay) {
+                    guard let strongSelf = self else { return }
+
+                    let retrySucceeded = strongSelf.retry(request)
+
+                    if retrySucceeded, let task = request.task {
+                        strongSelf.delegate[task] = request
+                    } else {
+                        if strongSelf.startRequestsImmediately { request.resume() }
+                    }
+                }
+            }
+        }
+    }
+}

+ 466 - 0
RainbowPlanet/Pods/Alamofire/Source/TaskDelegate.swift

@@ -0,0 +1,466 @@
+//
+//  TaskDelegate.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// The task delegate is responsible for handling all delegate callbacks for the underlying task as well as
+/// executing all operations attached to the serial operation queue upon task completion.
+open class TaskDelegate: NSObject {
+
+    // MARK: Properties
+
+    /// The serial operation queue used to execute all operations after the task completes.
+    public let queue: OperationQueue
+
+    /// The data returned by the server.
+    public var data: Data? { return nil }
+
+    /// The error generated throughout the lifecyle of the task.
+    public var error: Error?
+
+    var task: URLSessionTask? {
+        set {
+            taskLock.lock(); defer { taskLock.unlock() }
+            _task = newValue
+        }
+        get {
+            taskLock.lock(); defer { taskLock.unlock() }
+            return _task
+        }
+    }
+
+    var initialResponseTime: CFAbsoluteTime?
+    var credential: URLCredential?
+    var metrics: AnyObject? // URLSessionTaskMetrics
+
+    private var _task: URLSessionTask? {
+        didSet { reset() }
+    }
+
+    private let taskLock = NSLock()
+
+    // MARK: Lifecycle
+
+    init(task: URLSessionTask?) {
+        _task = task
+
+        self.queue = {
+            let operationQueue = OperationQueue()
+
+            operationQueue.maxConcurrentOperationCount = 1
+            operationQueue.isSuspended = true
+            operationQueue.qualityOfService = .utility
+
+            return operationQueue
+        }()
+    }
+
+    func reset() {
+        error = nil
+        initialResponseTime = nil
+    }
+
+    // MARK: URLSessionTaskDelegate
+
+    var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)?
+    var taskDidReceiveChallenge: ((URLSession, URLSessionTask, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?
+    var taskNeedNewBodyStream: ((URLSession, URLSessionTask) -> InputStream?)?
+    var taskDidCompleteWithError: ((URLSession, URLSessionTask, Error?) -> Void)?
+
+    @objc(URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:)
+    func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        willPerformHTTPRedirection response: HTTPURLResponse,
+        newRequest request: URLRequest,
+        completionHandler: @escaping (URLRequest?) -> Void)
+    {
+        var redirectRequest: URLRequest? = request
+
+        if let taskWillPerformHTTPRedirection = taskWillPerformHTTPRedirection {
+            redirectRequest = taskWillPerformHTTPRedirection(session, task, response, request)
+        }
+
+        completionHandler(redirectRequest)
+    }
+
+    @objc(URLSession:task:didReceiveChallenge:completionHandler:)
+    func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        didReceive challenge: URLAuthenticationChallenge,
+        completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
+    {
+        var disposition: URLSession.AuthChallengeDisposition = .performDefaultHandling
+        var credential: URLCredential?
+
+        if let taskDidReceiveChallenge = taskDidReceiveChallenge {
+            (disposition, credential) = taskDidReceiveChallenge(session, task, challenge)
+        } else if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
+            let host = challenge.protectionSpace.host
+
+            if
+                let serverTrustPolicy = session.serverTrustPolicyManager?.serverTrustPolicy(forHost: host),
+                let serverTrust = challenge.protectionSpace.serverTrust
+            {
+                if serverTrustPolicy.evaluate(serverTrust, forHost: host) {
+                    disposition = .useCredential
+                    credential = URLCredential(trust: serverTrust)
+                } else {
+                    disposition = .cancelAuthenticationChallenge
+                }
+            }
+        } else {
+            if challenge.previousFailureCount > 0 {
+                disposition = .rejectProtectionSpace
+            } else {
+                credential = self.credential ?? session.configuration.urlCredentialStorage?.defaultCredential(for: challenge.protectionSpace)
+
+                if credential != nil {
+                    disposition = .useCredential
+                }
+            }
+        }
+
+        completionHandler(disposition, credential)
+    }
+
+    @objc(URLSession:task:needNewBodyStream:)
+    func urlSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        needNewBodyStream completionHandler: @escaping (InputStream?) -> Void)
+    {
+        var bodyStream: InputStream?
+
+        if let taskNeedNewBodyStream = taskNeedNewBodyStream {
+            bodyStream = taskNeedNewBodyStream(session, task)
+        }
+
+        completionHandler(bodyStream)
+    }
+
+    @objc(URLSession:task:didCompleteWithError:)
+    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
+        if let taskDidCompleteWithError = taskDidCompleteWithError {
+            taskDidCompleteWithError(session, task, error)
+        } else {
+            if let error = error {
+                if self.error == nil { self.error = error }
+
+                if
+                    let downloadDelegate = self as? DownloadTaskDelegate,
+                    let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data
+                {
+                    downloadDelegate.resumeData = resumeData
+                }
+            }
+
+            queue.isSuspended = false
+        }
+    }
+}
+
+// MARK: -
+
+class DataTaskDelegate: TaskDelegate, URLSessionDataDelegate {
+
+    // MARK: Properties
+
+    var dataTask: URLSessionDataTask { return task as! URLSessionDataTask }
+
+    override var data: Data? {
+        if dataStream != nil {
+            return nil
+        } else {
+            return mutableData
+        }
+    }
+
+    var progress: Progress
+    var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)?
+
+    var dataStream: ((_ data: Data) -> Void)?
+
+    private var totalBytesReceived: Int64 = 0
+    private var mutableData: Data
+
+    private var expectedContentLength: Int64?
+
+    // MARK: Lifecycle
+
+    override init(task: URLSessionTask?) {
+        mutableData = Data()
+        progress = Progress(totalUnitCount: 0)
+
+        super.init(task: task)
+    }
+
+    override func reset() {
+        super.reset()
+
+        progress = Progress(totalUnitCount: 0)
+        totalBytesReceived = 0
+        mutableData = Data()
+        expectedContentLength = nil
+    }
+
+    // MARK: URLSessionDataDelegate
+
+    var dataTaskDidReceiveResponse: ((URLSession, URLSessionDataTask, URLResponse) -> URLSession.ResponseDisposition)?
+    var dataTaskDidBecomeDownloadTask: ((URLSession, URLSessionDataTask, URLSessionDownloadTask) -> Void)?
+    var dataTaskDidReceiveData: ((URLSession, URLSessionDataTask, Data) -> Void)?
+    var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)?
+
+    func urlSession(
+        _ session: URLSession,
+        dataTask: URLSessionDataTask,
+        didReceive response: URLResponse,
+        completionHandler: @escaping (URLSession.ResponseDisposition) -> Void)
+    {
+        var disposition: URLSession.ResponseDisposition = .allow
+
+        expectedContentLength = response.expectedContentLength
+
+        if let dataTaskDidReceiveResponse = dataTaskDidReceiveResponse {
+            disposition = dataTaskDidReceiveResponse(session, dataTask, response)
+        }
+
+        completionHandler(disposition)
+    }
+
+    func urlSession(
+        _ session: URLSession,
+        dataTask: URLSessionDataTask,
+        didBecome downloadTask: URLSessionDownloadTask)
+    {
+        dataTaskDidBecomeDownloadTask?(session, dataTask, downloadTask)
+    }
+
+    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
+        if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
+
+        if let dataTaskDidReceiveData = dataTaskDidReceiveData {
+            dataTaskDidReceiveData(session, dataTask, data)
+        } else {
+            if let dataStream = dataStream {
+                dataStream(data)
+            } else {
+                mutableData.append(data)
+            }
+
+            let bytesReceived = Int64(data.count)
+            totalBytesReceived += bytesReceived
+            let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
+
+            progress.totalUnitCount = totalBytesExpected
+            progress.completedUnitCount = totalBytesReceived
+
+            if let progressHandler = progressHandler {
+                progressHandler.queue.async { progressHandler.closure(self.progress) }
+            }
+        }
+    }
+
+    func urlSession(
+        _ session: URLSession,
+        dataTask: URLSessionDataTask,
+        willCacheResponse proposedResponse: CachedURLResponse,
+        completionHandler: @escaping (CachedURLResponse?) -> Void)
+    {
+        var cachedResponse: CachedURLResponse? = proposedResponse
+
+        if let dataTaskWillCacheResponse = dataTaskWillCacheResponse {
+            cachedResponse = dataTaskWillCacheResponse(session, dataTask, proposedResponse)
+        }
+
+        completionHandler(cachedResponse)
+    }
+}
+
+// MARK: -
+
+class DownloadTaskDelegate: TaskDelegate, URLSessionDownloadDelegate {
+
+    // MARK: Properties
+
+    var downloadTask: URLSessionDownloadTask { return task as! URLSessionDownloadTask }
+
+    var progress: Progress
+    var progressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)?
+
+    var resumeData: Data?
+    override var data: Data? { return resumeData }
+
+    var destination: DownloadRequest.DownloadFileDestination?
+
+    var temporaryURL: URL?
+    var destinationURL: URL?
+
+    var fileURL: URL? { return destination != nil ? destinationURL : temporaryURL }
+
+    // MARK: Lifecycle
+
+    override init(task: URLSessionTask?) {
+        progress = Progress(totalUnitCount: 0)
+        super.init(task: task)
+    }
+
+    override func reset() {
+        super.reset()
+
+        progress = Progress(totalUnitCount: 0)
+        resumeData = nil
+    }
+
+    // MARK: URLSessionDownloadDelegate
+
+    var downloadTaskDidFinishDownloadingToURL: ((URLSession, URLSessionDownloadTask, URL) -> URL)?
+    var downloadTaskDidWriteData: ((URLSession, URLSessionDownloadTask, Int64, Int64, Int64) -> Void)?
+    var downloadTaskDidResumeAtOffset: ((URLSession, URLSessionDownloadTask, Int64, Int64) -> Void)?
+
+    func urlSession(
+        _ session: URLSession,
+        downloadTask: URLSessionDownloadTask,
+        didFinishDownloadingTo location: URL)
+    {
+        temporaryURL = location
+
+        guard
+            let destination = destination,
+            let response = downloadTask.response as? HTTPURLResponse
+        else { return }
+
+        let result = destination(location, response)
+        let destinationURL = result.destinationURL
+        let options = result.options
+
+        self.destinationURL = destinationURL
+
+        do {
+            if options.contains(.removePreviousFile), FileManager.default.fileExists(atPath: destinationURL.path) {
+                try FileManager.default.removeItem(at: destinationURL)
+            }
+
+            if options.contains(.createIntermediateDirectories) {
+                let directory = destinationURL.deletingLastPathComponent()
+                try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
+            }
+
+            try FileManager.default.moveItem(at: location, to: destinationURL)
+        } catch {
+            self.error = error
+        }
+    }
+
+    func urlSession(
+        _ session: URLSession,
+        downloadTask: URLSessionDownloadTask,
+        didWriteData bytesWritten: Int64,
+        totalBytesWritten: Int64,
+        totalBytesExpectedToWrite: Int64)
+    {
+        if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
+
+        if let downloadTaskDidWriteData = downloadTaskDidWriteData {
+            downloadTaskDidWriteData(
+                session,
+                downloadTask,
+                bytesWritten,
+                totalBytesWritten,
+                totalBytesExpectedToWrite
+            )
+        } else {
+            progress.totalUnitCount = totalBytesExpectedToWrite
+            progress.completedUnitCount = totalBytesWritten
+
+            if let progressHandler = progressHandler {
+                progressHandler.queue.async { progressHandler.closure(self.progress) }
+            }
+        }
+    }
+
+    func urlSession(
+        _ session: URLSession,
+        downloadTask: URLSessionDownloadTask,
+        didResumeAtOffset fileOffset: Int64,
+        expectedTotalBytes: Int64)
+    {
+        if let downloadTaskDidResumeAtOffset = downloadTaskDidResumeAtOffset {
+            downloadTaskDidResumeAtOffset(session, downloadTask, fileOffset, expectedTotalBytes)
+        } else {
+            progress.totalUnitCount = expectedTotalBytes
+            progress.completedUnitCount = fileOffset
+        }
+    }
+}
+
+// MARK: -
+
+class UploadTaskDelegate: DataTaskDelegate {
+
+    // MARK: Properties
+
+    var uploadTask: URLSessionUploadTask { return task as! URLSessionUploadTask }
+
+    var uploadProgress: Progress
+    var uploadProgressHandler: (closure: Request.ProgressHandler, queue: DispatchQueue)?
+
+    // MARK: Lifecycle
+
+    override init(task: URLSessionTask?) {
+        uploadProgress = Progress(totalUnitCount: 0)
+        super.init(task: task)
+    }
+
+    override func reset() {
+        super.reset()
+        uploadProgress = Progress(totalUnitCount: 0)
+    }
+
+    // MARK: URLSessionTaskDelegate
+
+    var taskDidSendBodyData: ((URLSession, URLSessionTask, Int64, Int64, Int64) -> Void)?
+
+    func URLSession(
+        _ session: URLSession,
+        task: URLSessionTask,
+        didSendBodyData bytesSent: Int64,
+        totalBytesSent: Int64,
+        totalBytesExpectedToSend: Int64)
+    {
+        if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
+
+        if let taskDidSendBodyData = taskDidSendBodyData {
+            taskDidSendBodyData(session, task, bytesSent, totalBytesSent, totalBytesExpectedToSend)
+        } else {
+            uploadProgress.totalUnitCount = totalBytesExpectedToSend
+            uploadProgress.completedUnitCount = totalBytesSent
+
+            if let uploadProgressHandler = uploadProgressHandler {
+                uploadProgressHandler.queue.async { uploadProgressHandler.closure(self.uploadProgress) }
+            }
+        }
+    }
+}

+ 136 - 0
RainbowPlanet/Pods/Alamofire/Source/Timeline.swift

@@ -0,0 +1,136 @@
+//
+//  Timeline.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+/// Responsible for computing the timing metrics for the complete lifecycle of a `Request`.
+public struct Timeline {
+    /// The time the request was initialized.
+    public let requestStartTime: CFAbsoluteTime
+
+    /// The time the first bytes were received from or sent to the server.
+    public let initialResponseTime: CFAbsoluteTime
+
+    /// The time when the request was completed.
+    public let requestCompletedTime: CFAbsoluteTime
+
+    /// The time when the response serialization was completed.
+    public let serializationCompletedTime: CFAbsoluteTime
+
+    /// The time interval in seconds from the time the request started to the initial response from the server.
+    public let latency: TimeInterval
+
+    /// The time interval in seconds from the time the request started to the time the request completed.
+    public let requestDuration: TimeInterval
+
+    /// The time interval in seconds from the time the request completed to the time response serialization completed.
+    public let serializationDuration: TimeInterval
+
+    /// The time interval in seconds from the time the request started to the time response serialization completed.
+    public let totalDuration: TimeInterval
+
+    /// Creates a new `Timeline` instance with the specified request times.
+    ///
+    /// - parameter requestStartTime:           The time the request was initialized. Defaults to `0.0`.
+    /// - parameter initialResponseTime:        The time the first bytes were received from or sent to the server.
+    ///                                         Defaults to `0.0`.
+    /// - parameter requestCompletedTime:       The time when the request was completed. Defaults to `0.0`.
+    /// - parameter serializationCompletedTime: The time when the response serialization was completed. Defaults
+    ///                                         to `0.0`.
+    ///
+    /// - returns: The new `Timeline` instance.
+    public init(
+        requestStartTime: CFAbsoluteTime = 0.0,
+        initialResponseTime: CFAbsoluteTime = 0.0,
+        requestCompletedTime: CFAbsoluteTime = 0.0,
+        serializationCompletedTime: CFAbsoluteTime = 0.0)
+    {
+        self.requestStartTime = requestStartTime
+        self.initialResponseTime = initialResponseTime
+        self.requestCompletedTime = requestCompletedTime
+        self.serializationCompletedTime = serializationCompletedTime
+
+        self.latency = initialResponseTime - requestStartTime
+        self.requestDuration = requestCompletedTime - requestStartTime
+        self.serializationDuration = serializationCompletedTime - requestCompletedTime
+        self.totalDuration = serializationCompletedTime - requestStartTime
+    }
+}
+
+// MARK: - CustomStringConvertible
+
+extension Timeline: CustomStringConvertible {
+    /// The textual representation used when written to an output stream, which includes the latency, the request
+    /// duration and the total duration.
+    public var description: String {
+        let latency = String(format: "%.3f", self.latency)
+        let requestDuration = String(format: "%.3f", self.requestDuration)
+        let serializationDuration = String(format: "%.3f", self.serializationDuration)
+        let totalDuration = String(format: "%.3f", self.totalDuration)
+
+        // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is
+        // fixed, we should move back to string interpolation by reverting commit 7d4a43b1.
+        let timings = [
+            "\"Latency\": " + latency + " secs",
+            "\"Request Duration\": " + requestDuration + " secs",
+            "\"Serialization Duration\": " + serializationDuration + " secs",
+            "\"Total Duration\": " + totalDuration + " secs"
+        ]
+
+        return "Timeline: { " + timings.joined(separator: ", ") + " }"
+    }
+}
+
+// MARK: - CustomDebugStringConvertible
+
+extension Timeline: CustomDebugStringConvertible {
+    /// The textual representation used when written to an output stream, which includes the request start time, the
+    /// initial response time, the request completed time, the serialization completed time, the latency, the request
+    /// duration and the total duration.
+    public var debugDescription: String {
+        let requestStartTime = String(format: "%.3f", self.requestStartTime)
+        let initialResponseTime = String(format: "%.3f", self.initialResponseTime)
+        let requestCompletedTime = String(format: "%.3f", self.requestCompletedTime)
+        let serializationCompletedTime = String(format: "%.3f", self.serializationCompletedTime)
+        let latency = String(format: "%.3f", self.latency)
+        let requestDuration = String(format: "%.3f", self.requestDuration)
+        let serializationDuration = String(format: "%.3f", self.serializationDuration)
+        let totalDuration = String(format: "%.3f", self.totalDuration)
+
+        // NOTE: Had to move to string concatenation due to memory leak filed as rdar://26761490. Once memory leak is
+        // fixed, we should move back to string interpolation by reverting commit 7d4a43b1.
+        let timings = [
+            "\"Request Start Time\": " + requestStartTime,
+            "\"Initial Response Time\": " + initialResponseTime,
+            "\"Request Completed Time\": " + requestCompletedTime,
+            "\"Serialization Completed Time\": " + serializationCompletedTime,
+            "\"Latency\": " + latency + " secs",
+            "\"Request Duration\": " + requestDuration + " secs",
+            "\"Serialization Duration\": " + serializationDuration + " secs",
+            "\"Total Duration\": " + totalDuration + " secs"
+        ]
+
+        return "Timeline: { " + timings.joined(separator: ", ") + " }"
+    }
+}

+ 315 - 0
RainbowPlanet/Pods/Alamofire/Source/Validation.swift

@@ -0,0 +1,315 @@
+//
+//  Validation.swift
+//
+//  Copyright (c) 2014 Alamofire Software Foundation (http://alamofire.org/)
+//
+//  Permission is hereby granted, free of charge, to any person obtaining a copy
+//  of this software and associated documentation files (the "Software"), to deal
+//  in the Software without restriction, including without limitation the rights
+//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+//  copies of the Software, and to permit persons to whom the Software is
+//  furnished to do so, subject to the following conditions:
+//
+//  The above copyright notice and this permission notice shall be included in
+//  all copies or substantial portions of the Software.
+//
+//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+//  THE SOFTWARE.
+//
+
+import Foundation
+
+extension Request {
+
+    // MARK: Helper Types
+
+    fileprivate typealias ErrorReason = AFError.ResponseValidationFailureReason
+
+    /// Used to represent whether validation was successful or encountered an error resulting in a failure.
+    ///
+    /// - success: The validation was successful.
+    /// - failure: The validation failed encountering the provided error.
+    public enum ValidationResult {
+        case success
+        case failure(Error)
+    }
+
+    fileprivate struct MIMEType {
+        let type: String
+        let subtype: String
+
+        var isWildcard: Bool { return type == "*" && subtype == "*" }
+
+        init?(_ string: String) {
+            let components: [String] = {
+                let stripped = string.trimmingCharacters(in: .whitespacesAndNewlines)
+
+            #if swift(>=3.2)
+                let split = stripped[..<(stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)]
+            #else
+                let split = stripped.substring(to: stripped.range(of: ";")?.lowerBound ?? stripped.endIndex)
+            #endif
+
+                return split.components(separatedBy: "/")
+            }()
+
+            if let type = components.first, let subtype = components.last {
+                self.type = type
+                self.subtype = subtype
+            } else {
+                return nil
+            }
+        }
+
+        func matches(_ mime: MIMEType) -> Bool {
+            switch (type, subtype) {
+            case (mime.type, mime.subtype), (mime.type, "*"), ("*", mime.subtype), ("*", "*"):
+                return true
+            default:
+                return false
+            }
+        }
+    }
+
+    // MARK: Properties
+
+    fileprivate var acceptableStatusCodes: [Int] { return Array(200..<300) }
+
+    fileprivate var acceptableContentTypes: [String] {
+        if let accept = request?.value(forHTTPHeaderField: "Accept") {
+            return accept.components(separatedBy: ",")
+        }
+
+        return ["*/*"]
+    }
+
+    // MARK: Status Code
+
+    fileprivate func validate<S: Sequence>(
+        statusCode acceptableStatusCodes: S,
+        response: HTTPURLResponse)
+        -> ValidationResult
+        where S.Iterator.Element == Int
+    {
+        if acceptableStatusCodes.contains(response.statusCode) {
+            return .success
+        } else {
+            let reason: ErrorReason = .unacceptableStatusCode(code: response.statusCode)
+            return .failure(AFError.responseValidationFailed(reason: reason))
+        }
+    }
+
+    // MARK: Content Type
+
+    fileprivate func validate<S: Sequence>(
+        contentType acceptableContentTypes: S,
+        response: HTTPURLResponse,
+        data: Data?)
+        -> ValidationResult
+        where S.Iterator.Element == String
+    {
+        guard let data = data, data.count > 0 else { return .success }
+
+        guard
+            let responseContentType = response.mimeType,
+            let responseMIMEType = MIMEType(responseContentType)
+        else {
+            for contentType in acceptableContentTypes {
+                if let mimeType = MIMEType(contentType), mimeType.isWildcard {
+                    return .success
+                }
+            }
+
+            let error: AFError = {
+                let reason: ErrorReason = .missingContentType(acceptableContentTypes: Array(acceptableContentTypes))
+                return AFError.responseValidationFailed(reason: reason)
+            }()
+
+            return .failure(error)
+        }
+
+        for contentType in acceptableContentTypes {
+            if let acceptableMIMEType = MIMEType(contentType), acceptableMIMEType.matches(responseMIMEType) {
+                return .success
+            }
+        }
+
+        let error: AFError = {
+            let reason: ErrorReason = .unacceptableContentType(
+                acceptableContentTypes: Array(acceptableContentTypes),
+                responseContentType: responseContentType
+            )
+
+            return AFError.responseValidationFailed(reason: reason)
+        }()
+
+        return .failure(error)
+    }
+}
+
+// MARK: -
+
+extension DataRequest {
+    /// A closure used to validate a request that takes a URL request, a URL response and data, and returns whether the
+    /// request was valid.
+    public typealias Validation = (URLRequest?, HTTPURLResponse, Data?) -> ValidationResult
+
+    /// Validates the request, using the specified closure.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter validation: A closure to validate the request.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate(_ validation: @escaping Validation) -> Self {
+        let validationExecution: () -> Void = { [unowned self] in
+            if
+                let response = self.response,
+                self.delegate.error == nil,
+                case let .failure(error) = validation(self.request, response, self.delegate.data)
+            {
+                self.delegate.error = error
+            }
+        }
+
+        validations.append(validationExecution)
+
+        return self
+    }
+
+    /// Validates that the response has a status code in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter range: The range of acceptable status codes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
+        return validate { [unowned self] _, response, _ in
+            return self.validate(statusCode: acceptableStatusCodes, response: response)
+        }
+    }
+
+    /// Validates that the response has a content type in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String {
+        return validate { [unowned self] _, response, data in
+            return self.validate(contentType: acceptableContentTypes, response: response, data: data)
+        }
+    }
+
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
+    /// type matches any specified in the Accept HTTP header field.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate() -> Self {
+        return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes)
+    }
+}
+
+// MARK: -
+
+extension DownloadRequest {
+    /// A closure used to validate a request that takes a URL request, a URL response, a temporary URL and a
+    /// destination URL, and returns whether the request was valid.
+    public typealias Validation = (
+        _ request: URLRequest?,
+        _ response: HTTPURLResponse,
+        _ temporaryURL: URL?,
+        _ destinationURL: URL?)
+        -> ValidationResult
+
+    /// Validates the request, using the specified closure.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter validation: A closure to validate the request.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate(_ validation: @escaping Validation) -> Self {
+        let validationExecution: () -> Void = { [unowned self] in
+            let request = self.request
+            let temporaryURL = self.downloadDelegate.temporaryURL
+            let destinationURL = self.downloadDelegate.destinationURL
+
+            if
+                let response = self.response,
+                self.delegate.error == nil,
+                case let .failure(error) = validation(request, response, temporaryURL, destinationURL)
+            {
+                self.delegate.error = error
+            }
+        }
+
+        validations.append(validationExecution)
+
+        return self
+    }
+
+    /// Validates that the response has a status code in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter range: The range of acceptable status codes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(statusCode acceptableStatusCodes: S) -> Self where S.Iterator.Element == Int {
+        return validate { [unowned self] _, response, _, _ in
+            return self.validate(statusCode: acceptableStatusCodes, response: response)
+        }
+    }
+
+    /// Validates that the response has a content type in the specified sequence.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - parameter contentType: The acceptable content types, which may specify wildcard types and/or subtypes.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate<S: Sequence>(contentType acceptableContentTypes: S) -> Self where S.Iterator.Element == String {
+        return validate { [unowned self] _, response, _, _ in
+            let fileURL = self.downloadDelegate.fileURL
+
+            guard let validFileURL = fileURL else {
+                return .failure(AFError.responseValidationFailed(reason: .dataFileNil))
+            }
+
+            do {
+                let data = try Data(contentsOf: validFileURL)
+                return self.validate(contentType: acceptableContentTypes, response: response, data: data)
+            } catch {
+                return .failure(AFError.responseValidationFailed(reason: .dataFileReadFailed(at: validFileURL)))
+            }
+        }
+    }
+
+    /// Validates that the response has a status code in the default acceptable range of 200...299, and that the content
+    /// type matches any specified in the Accept HTTP header field.
+    ///
+    /// If validation fails, subsequent calls to response handlers will have an associated error.
+    ///
+    /// - returns: The request.
+    @discardableResult
+    public func validate() -> Self {
+        return validate(statusCode: self.acceptableStatusCodes).validate(contentType: self.acceptableContentTypes)
+    }
+}

+ 21 - 0
RainbowPlanet/Pods/BMKLocationKit/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 jiangfangsheng
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 2 - 0
RainbowPlanet/Pods/BMKLocationKit/README.md

@@ -0,0 +1,2 @@
+# BMKLocationKit
+Baidu IOS LOC Framework

BIN
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/BMKLocationKit


+ 134 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKGeoFenceManager.h

@@ -0,0 +1,134 @@
+//
+//  BMKGeoFenceManager.h
+//  BMKLocationKit
+//
+//  Created by baidu on 2017/3/2.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+#import "BMKGeoFenceRegion.h"
+
+@protocol BMKGeoFenceManagerDelegate;
+
+///地理围栏监听状态类型
+typedef NS_OPTIONS(NSUInteger, BMKGeoFenceActiveAction)
+{
+    BMKGeoFenceActiveActionNone     = 0,       ///< 不进行监听
+    BMKGeoFenceActiveActionInside   = 1 << 0,  ///< 在范围内
+    BMKGeoFenceActiveActionOutside  = 1 << 1,  ///< 在范围外
+    BMKGeoFenceActiveActionStayed   = 1 << 2,  ///< 停留(在范围内超过10分钟)
+};
+
+///BMKGeoFence errorDomain
+FOUNDATION_EXPORT NSErrorDomain const _Nonnull BMKGeoFenceErrorDomain;
+
+///地理围栏错误码
+typedef NS_ENUM(NSInteger, BMKGeoFenceErrorCode) {
+    BMKGeoFenceErrorUnknown = 1,                    ///< 未知错误
+    BMKGeoFenceErrorInvalidParameter = 2,           ///< 参数错误
+    BMKGeoFenceErrorFailureConnection = 3,          ///< 网络连接异常
+    BMKGeoFenceErrorFailureAuth  = 4,               ///< 鉴权失败
+    BMKGeoFenceErrorNoValidFence = 5,               ///< 无可用围栏
+    BMKGeoFenceErroFailureLocating = 6,             ///< 定位错误
+};
+
+
+///地理围栏管理类
+@interface BMKGeoFenceManager : NSObject
+
+
+///实现了 BMKGeoFenceManagerDelegate 协议的类指针。
+@property (nonatomic, weak, nullable) id<BMKGeoFenceManagerDelegate> delegate;
+
+
+///需要进行通知的行为,默认为BMKGeoFenceActiveActionInside。
+@property (nonatomic, assign) BMKGeoFenceActiveAction activeAction;
+
+
+///指定定位是否会被系统自动暂停。默认为NO。
+@property (nonatomic, assign) BOOL pausesLocationUpdatesAutomatically;
+
+
+///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
+@property (nonatomic, assign) BOOL allowsBackgroundLocationUpdates;
+
+
+/**
+ * @brief 添加一个圆形围栏
+ * @param center 围栏的中心点经纬度坐标
+ * @param radius 围栏的半径,单位:米,要求大于0
+ * @param type 围栏的坐标系类型
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addCircleRegionForMonitoringWithCenter:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius coorType:(BMKLocationCoordinateType)type customID:(NSString * _Nullable)customID;
+
+
+/**
+ * @brief 根据经纬度坐标数据添加一个闭合的多边形围栏,点与点之间按顺序尾部相连, 第一个点与最后一个点相连
+ * @param coordinates 经纬度坐标点数据,coordinates对应的内存会拷贝,调用者负责该内存的释放
+ * @param count 经纬度坐标点的个数,不可小于3个
+ * @param type 围栏的坐标系类型
+ * @param customID 用户自定义ID,可选,SDK原值返回
+ */
+- (void)addPolygonRegionForMonitoringWithCoordinates:(CLLocationCoordinate2D * _Nonnull)coordinates count:(NSInteger)count coorType:(BMKLocationCoordinateType)type customID:(NSString * _Nullable)customID;
+
+
+/**
+ * @brief 根据customID获得指定的围栏,如果customID传nil,则返回全部围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @return 获得的围栏构成的数组,如果没有结果,返回nil
+ */
+- (NSArray * _Nullable)geoFenceRegionsWithCustomID:(NSString * _Nullable)customID;
+
+
+/**
+ * @brief 移除指定围栏
+ * @param region 要停止监控的围栏
+ */
+- (void)removeTheGeoFenceRegion:(BMKGeoFenceRegion * _Nonnull)region;
+
+
+/**
+ * @brief 移除指定customID的围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ */
+- (void)removeGeoFenceRegionsWithCustomID:(NSString * _Nullable)customID;
+
+
+/**
+ * @brief 移除所有围栏
+ */
+- (void)removeAllGeoFenceRegions;
+
+
+@end
+
+
+
+///地理围栏代理协议,该协议定义了获取地理围栏相关回调方法,包括添加、状态改变等。
+@protocol BMKGeoFenceManagerDelegate <NSObject>
+
+@optional
+
+
+/**
+ * @brief 添加地理围栏完成后的回调,成功与失败都会调用
+ * @param manager 地理围栏管理类
+ * @param regions 成功添加的一个或多个地理围栏构成的数组
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @param error 添加失败的错误信息
+ */
+- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager didAddRegionForMonitoringFinished:(NSArray <BMKGeoFenceRegion *> * _Nullable)regions customID:(NSString * _Nullable)customID error:(NSError * _Nullable)error;
+
+
+/**
+ * @brief 地理围栏状态改变时回调,当围栏状态的值发生改变,定位失败都会调用
+ * @param manager 地理围栏管理类
+ * @param region 状态改变的地理围栏
+ * @param customID 用户执行添加围栏函数时传入的customID
+ * @param error 错误信息,如定位相关的错误
+ */
+- (void)BMKGeoFenceManager:(BMKGeoFenceManager * _Nonnull)manager didGeoFencesStatusChangedForRegion:(BMKGeoFenceRegion * _Nullable)region customID:(NSString * _Nullable)customID error:(NSError * _Nullable)error;
+
+@end
+

+ 114 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKGeoFenceRegion.h

@@ -0,0 +1,114 @@
+//
+//  BMKGeoFenceRegion.h
+//  BMKLocationKit
+//
+//  Created by baidu on 2017/3/2.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+#import "BMKLocationManager.h"
+
+///BMKGeoFence Region State
+typedef NS_ENUM(NSInteger, BMKGeoFenceRegionStatus)
+{
+    BMKGeoFenceRegionStatusUnknown  = 0,       ///< 未知
+    BMKGeoFenceRegionStatusInside   = 1,       ///< 在范围内
+    BMKGeoFenceRegionStatusOutside  = 1 << 1,       ///< 在范围外
+    BMKGeoFenceRegionStatusStayed   = 1 << 2,       ///< 停留(在范围内超过10分钟)
+};
+
+#pragma mark - BMKGeoFenceRegion
+
+
+///地理围栏基类,不可直接使用
+@interface BMKGeoFenceRegion : NSObject<NSCopying>
+
+
+///BMKGeoFenceRegion的唯一标识符
+@property (nonatomic, copy, readonly) NSString *identifier;
+
+
+///用户自定义ID,可为nil。
+@property (nonatomic, copy, readonly) NSString *customID;
+
+
+///坐标点和围栏的关系,比如用户的位置和围栏的关系
+@property (nonatomic, assign) BMKGeoFenceRegionStatus fenceStatus;
+
+///设定围栏坐标系类型。默认为 BMKLocationCoordinateTypeGCJ02。
+@property(nonatomic, readonly) BMKLocationCoordinateType coordinateType;
+
+///上次发生状态变化的时间
+@property(nonatomic, assign)NSTimeInterval lastEventTime;
+
+
+/**
+ *  @brief 判断位置与围栏状态
+ *  @param CLLocationCoordinate2D 坐标值
+ *  @return 返回BMKGeoFenceRegionStatus状态
+ */
+-(BMKGeoFenceRegionStatus)judgeStatusWithCoor:(CLLocationCoordinate2D)coor;
+
+@end
+
+
+#pragma mark - BMKLocationCircleRegion
+
+
+///圆形地理围栏
+@interface BMKGeoFenceCircleRegion : BMKGeoFenceRegion
+
+
+///中心点的经纬度坐标
+@property (nonatomic, readonly) CLLocationCoordinate2D center;
+
+
+///半径,单位:米
+@property (nonatomic, readonly) CLLocationDistance radius;
+
+/**
+ *  @brief 构造圆形围栏
+ *  @param customid 用户自定义ID
+ *  @param identityid 识别id
+ *  @param center 中心坐标
+ *  @param radius 围栏半径
+ *  @param type 坐标系类型
+ *  @return BMKGeoFenceCircleRegion id
+ */
+- (id)initWithCustomID:(NSString *)customid identityID:(NSString *)identityid center:(CLLocationCoordinate2D)center radius:(CLLocationDistance)radius coor:(BMKLocationCoordinateType)type;
+
+
+
+@end
+
+
+#pragma mark -BMKGeoFencePolygonRegion
+
+
+///多边形地理围栏
+@interface BMKGeoFencePolygonRegion : BMKGeoFenceRegion
+
+
+///经纬度坐标点数据
+@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates;
+
+
+///经纬度坐标点的个数
+@property (nonatomic, readonly) NSInteger count;
+
+
+/**
+ *  @brief 构造多边形围栏
+ *  @param customid 用户自定义ID
+ *  @param identityid 识别id
+ *  @param coor 多边形顶点
+ *  @param count 顶点个数
+ *  @param type 坐标系类型
+ *  @return BMKGeoFencePolygonRegion id
+ */
+- (id)initWithCustomID:(NSString *)customid identityID:(NSString *)identityid coor:(CLLocationCoordinate2D *)coor count:(NSInteger)count coor:(BMKLocationCoordinateType)type;
+
+@end
+

+ 97 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocation.h

@@ -0,0 +1,97 @@
+//
+//  BMKLocation.h
+//  LocationComponent
+//
+//  Created by baidu on 2017/8/16.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+#ifndef BMKLocation_h
+#define BMKLocation_h
+
+#import <CoreLocation/CoreLocation.h>
+#import "BMKLocationReGeocode.h"
+
+/** 
+ * BMKLocationProvider 位置数据来源,分iOS系统定位和其他定位服务结果两种,目前仅支持iOS系统定位服务
+ *
+ */
+typedef NS_ENUM(int, BMKLocationProvider) {
+    
+    BMKLocationProviderIOS = 0,           //!<位置来源于iOS本身定位
+    BMKLocationProviderOther          //!<位置来源于其他定位服务
+    
+};
+
+///描述百度iOS 定位数据
+@interface BMKLocation : NSObject
+
+///BMKLocation 位置数据
+@property(nonatomic, copy, readonly) CLLocation * _Nullable location;
+
+///BMKLocation 地址数据
+@property(nonatomic, copy) BMKLocationReGeocode * _Nullable rgcData;
+
+///BMKLocation 位置来源
+@property(nonatomic, assign) BMKLocationProvider provider;
+
+///BMKLocation 位置ID
+@property(nonatomic, retain) NSString * _Nullable locationID;
+
+/*
+ *  floorString
+ *
+ *  Discussion:
+ *    室内定位成功时返回的楼层信息,ex:f1
+ */
+@property(readonly, nonatomic, copy, nullable) NSString *floorString;
+
+/*
+ *  buildingID
+ *
+ *  Discussion:
+ *    室内定位成功时返回的百度建筑物ID
+ */
+@property(readonly, nonatomic, copy, nullable) NSString *buildingID;
+
+/*
+ *  buildingName
+ *
+ *  Discussion:
+ *    室内定位成功时返回的百度建筑物名称
+ */
+@property(readonly, nonatomic, copy, nullable) NSString *buildingName;
+
+
+/*
+ *  extraInfo
+ *
+ *  Discussion:
+ *    定位附加信息,如停车位code识别结果、停车位code示例、vdr推算结果置信度等
+ */
+@property(readonly, nonatomic, copy, nullable) NSDictionary * extraInfo;
+
+/**
+ *  @brief 初始化BMKLocation实例
+ *  @param loc CLLocation对象
+ *  @param rgc BMKLocationReGeocode对象
+ *  @return BMKLocation id
+ */
+- (id _Nonnull)initWithLocation:(CLLocation * _Nullable)loc withRgcData:(BMKLocationReGeocode * _Nullable)rgc;
+
+/**
+ *  @brief 构造BMKLocation
+ *  @param location CLLocation
+ *  @param floorString 楼层字符串
+ *  @param buildingID 建筑物ID
+ *  @param buildingName 建筑物名称
+ *  @param info 位置附加信息
+ *  @return BMKLocation id
+ */
+-(id _Nonnull)initWithLocation:(CLLocation * _Nullable)location floorString:(NSString * _Nullable)floorString buildingID:(NSString * _Nullable)buildingID
+                  buildingName:(NSString * _Nullable)buildingName extraInfo:(NSDictionary * _Nullable)info withRgcData:(BMKLocationReGeocode * _Nullable)rgc;
+
+
+@end
+
+#endif /* BMKLocation_h */

+ 56 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationAuth.h

@@ -0,0 +1,56 @@
+//
+//  BMKLocationAuth.h
+//  LocationComponent
+//
+//  Created by baidu on 2017/4/10.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+#ifndef BMKLocationAuth_h
+#define BMKLocationAuth_h
+
+///定位鉴权错误码
+typedef NS_ENUM(NSInteger, BMKLocationAuthErrorCode) {
+    BMKLocationAuthErrorUnknown = -1,                    ///< 未知错误
+    BMKLocationAuthErrorSuccess = 0,           ///< 鉴权成功
+    BMKLocationAuthErrorNetworkFailed = 1,          ///< 因网络鉴权失败
+    BMKLocationAuthErrorFailed  = 2,               ///< KEY非法鉴权失败
+
+};
+///通知Delegate
+@protocol BMKLocationAuthDelegate <NSObject>
+@optional
+
+/**
+ *@brief 返回授权验证错误
+ *@param iError 错误号 : 为0时验证通过,具体参加BMKLocationAuthErrorCode
+ */
+- (void)onCheckPermissionState:(BMKLocationAuthErrorCode)iError;
+@end
+
+
+///BMKLocationAuth类。用于鉴权
+@interface BMKLocationAuth : NSObject
+
+///鉴权状态0:成功; 1:网络错误; 2:授权失败
+@property(nonatomic, readonly, assign) BMKLocationAuthErrorCode permisionState;
+
+/**
+ * @brief 得到BMKLocationAuth的单例
+ */
++ (BMKLocationAuth*)sharedInstance;
+
+
+/**
+ *@brief 启动引擎
+ *@param key 申请的有效key
+ *@param delegate 回调是否鉴权成功
+ */
+-(void)checkPermisionWithKey:(NSString*)key authDelegate:(id<BMKLocationAuthDelegate>)delegate;
+
+
+@end
+
+
+
+#endif /* BMKLocationAuth_h */

+ 16 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationComponent.h

@@ -0,0 +1,16 @@
+//
+//  BMKLocationComponent.h
+//  LocationComponent
+//
+//  Created by Baidu on 3/31/14.
+//  Copyright (c) 2014 baidu. All rights reserved.
+//
+
+#import "BMKLocationManager.h"
+#import "BMKLocationKitVersion.h"
+#import "BMKLocationPoi.h"
+#import "BMKLocation.h"
+#import "BMKGeoFenceRegion.h"
+#import "BMKGeoFenceManager.h"
+#import "BMKLocationReGeocode.h"
+#import "BMKLocationAuth.h"

+ 30 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationKitVersion.h

@@ -0,0 +1,30 @@
+//
+//  BMKLocationKitVersion.h
+//  BMKLocationKit
+//
+//  Created by baidu on 17/9/9.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+#ifndef BMKLocationKitVersion_h
+#define BMKLocationKitVersion_h
+
+#import <UIKit/UIKit.h>
+
+/**
+ *获取当前定位sdk 的版本号
+ *当前定位sdk版本 : 1.5.0
+ *@return  返回当前定位sdk 的版本号
+ */
+UIKIT_EXTERN NSString* BMKLocationKitVersion();
+
+/**
+ *获取当前定位sdk 的float版本号
+ *当前定位sdk版本 : 1.5
+ *@return  返回当前定位sdk 的float版本号
+ */
+UIKIT_EXTERN float BMKLocationKitFloatVersion();
+
+
+
+#endif /* BMKLocationKitVersion_h */

+ 247 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationManager.h

@@ -0,0 +1,247 @@
+//
+//  BMKLocationManager.h
+//  BMKLocationKit
+//
+//  Created by baidu on 2017/3/2.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+
+#import <Foundation/Foundation.h>
+#import <CoreLocation/CoreLocation.h>
+#import "BMKLocationReGeocode.h"
+#import "BMKLocation.h"
+
+/** BMKLocationCoordinateType 枚举坐标系类型
+ *
+ */
+typedef NS_ENUM(NSUInteger, BMKLocationCoordinateType)
+{
+    BMKLocationCoordinateTypeBMK09LL = 0,        ///<BMK09LL
+    BMKLocationCoordinateTypeBMK09MC,           ///<BMK09MC
+    BMKLocationCoordinateTypeWGS84,        ///<WGS84
+    BMKLocationCoordinateTypeGCJ02          ///<GCJ02
+};
+
+/** BMKLocationNetworkState 枚举识别网络状态类型
+ *
+ */
+typedef NS_ENUM(int, BMKLocationNetworkState) {
+    BMKLocationNetworkStateUnknown = 0,    ///<网络状态未知
+    BMKLocationNetworkStateWifi,           ///<网络状态wifi
+    BMKLocationNetworkStateWifiHotSpot,          ///<网络状态连接WIFI移动热点
+    BMKLocationNetworkStateMobile2G,          ///<网络状态移动2G
+    BMKLocationNetworkStateMobile3G,          ///<网络状态移动3G
+    BMKLocationNetworkStateMobile4G        ///<网络状态移动4G
+    
+};
+
+
+///BMKLocation errorDomain
+
+FOUNDATION_EXPORT NSErrorDomain const _Nonnull BMKLocationErrorDomain;
+
+///BMKLocation errorCode
+typedef NS_ENUM(NSInteger, BMKLocationErrorCode)
+{
+    BMKLocationErrorUnKnown = 0,                   ///<未知异常
+    BMKLocationErrorLocFailed = 1,                 ///<位置未知,持续定位中
+    BMKLocationErrorDenied = 2,                    ///<手机不允许定位,请确认用户授予定位权限或者手机是否打开定位开关
+    BMKLocationErrorNetWork = 3,                   ///<因为网络原因导致系统定位失败
+    BMKLocationErrorHeadingFailed = 4,             ///<获取手机方向信息失败
+    BMKLocationErrorGetExtraNetworkFailed  = 5,    ///<网络原因导致获取额外信息(地址、网络状态等信息)失败
+    BMKLocationErrorGetExtraParseFailed  = 6,      ///<网络返回数据解析失败导致获取额外信息(地址、网络状态等信息)失败
+    BMKLocationErrorFailureAuth  = 7,              ///<鉴权失败导致无法返回定位、地址等信息
+};
+
+
+/**
+ *  @brief 单次定位返回Block
+ *  @param location 定位信息,数据包括CLLocation 位置数据,BMKLocationReGeocode 地址信息,参考BMKLocation。
+ *  @param state 移动热点状态
+ *  @param error 错误信息,参考 BMKLocationErrorCode
+ */
+typedef void (^BMKLocatingCompletionBlock)(BMKLocation * _Nullable location, BMKLocationNetworkState state , NSError * _Nullable error);
+
+
+
+@protocol BMKLocationManagerDelegate;
+
+#pragma mark - BMKLocationManager
+
+
+///BMKLocationManager类。初始化之前请设置 BMKLocationAuth 中的APIKey,否则将无法正常使用服务.
+@interface BMKLocationManager : NSObject
+
+///实现了 BMKLocationManagerDelegate 协议的类指针。
+@property (nonatomic, weak, nullable) id<BMKLocationManagerDelegate> delegate;
+
+///设定定位的最小更新距离。默认为 kCLDistanceFilterNone。
+@property(nonatomic, assign) CLLocationDistance distanceFilter;
+
+///设定定位精度。默认为 kCLLocationAccuracyBest。
+@property(nonatomic, assign) CLLocationAccuracy desiredAccuracy;
+
+///设定定位类型。默认为 CLActivityTypeAutomotiveNavigation。
+@property(nonatomic, assign) CLActivityType activityType;
+
+///设定定位坐标系类型。默认为 BMKLocationCoordinateTypeGCJ02。
+@property(nonatomic, assign) BMKLocationCoordinateType coordinateType;
+
+///指定定位是否会被系统自动暂停。默认为NO。
+@property(nonatomic, assign) BOOL pausesLocationUpdatesAutomatically;
+
+
+///是否允许后台定位。默认为NO。只在iOS 9.0及之后起作用。设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
+@property(nonatomic, assign) BOOL allowsBackgroundLocationUpdates;
+
+///指定单次定位超时时间,默认为10s。最小值是2s。注意单次定位请求前设置。注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)后开始计算。
+@property(nonatomic, assign) NSInteger locationTimeout;
+
+///指定单次定位逆地理超时时间,默认为10s。最小值是2s。注意单次定位请求前设置。
+@property(nonatomic, assign) NSInteger reGeocodeTimeout;
+
+///连续定位是否返回逆地理信息,默认YES。
+@property (nonatomic, assign) BOOL locatingWithReGeocode;
+
+///定位sdk-v1.3之后,开发者可以选择是否需要最新版本rgc数据,默认是不需要NO;YES的情况下,定位sdk会实时返回最新的rgc数据,如城市变更等数据都会实时更新
+@property (nonatomic, assign) BOOL isNeedNewVersionReGeocode;
+
+
+///开发者可以指定该用户的id,用于后续统一识别用户,便于查找问题
+@property(nonatomic, retain, nullable) NSString * userID;
+
+
+
+
+/**
+ *  @brief 单次定位。如果当前正在连续定位,调用此方法将会失败,返回NO。\n该方法将会根据设定的 desiredAccuracy 去获取定位信息。如果获取的定位信息精确度低于 desiredAccuracy ,将会持续的等待定位信息,直到超时后通过completionBlock返回精度最高的定位信息。\n可以通过 stopUpdatingLocation 方法去取消正在进行的单次定位请求。
+ *  @param withReGeocode 是否带有逆地理信息(获取逆地理信息需要联网)
+ *  @param withNetWorkState 是否带有移动热点识别状态(需要联网)
+ *  @param completionBlock 单次定位完成后的Block
+ *  @return 是否成功添加单次定位Request
+ */
+- (BOOL)requestLocationWithReGeocode:(BOOL)withReGeocode withNetworkState:(BOOL)withNetWorkState completionBlock:(BMKLocatingCompletionBlock _Nonnull)completionBlock;
+
+/**
+ *  @brief 开始连续定位。调用此方法会cancel掉所有的单次定位请求。
+ */
+- (void)startUpdatingLocation;
+
+/**
+ *  @brief 停止连续定位。调用此方法会cancel掉所有的单次定位请求,可以用来取消单次定位。
+ */
+- (void)stopUpdatingLocation;
+
+/**
+ * @brief 请求网络状态结果回调。
+ */
+- (void)requestNetworkState;
+
+
+/**
+ * @brief 该方法返回设备是否支持设备朝向事件回调。
+ * @return 是否支持设备朝向事件回调
+ */
++ (BOOL)headingAvailable;
+
+/**
+ * @brief 该方法为BMKLocationManager开始设备朝向事件回调。
+ */
+- (void)startUpdatingHeading;
+
+/**
+ * @brief 该方法为BMKLocationManager停止设备朝向事件回调。
+ */
+- (void)stopUpdatingHeading;
+
+/**
+ * @brief 该方法为BMKLocationManager尝试使用高精度室内定位。在特定的室内场景下会有更高精度的定位回调,只在室内定位版本生效。
+ */
+- (void)tryIndoorLocation;
+
+/**
+ * @brief 该方法为BMKLocationManager会关闭高精度室内定位,只在室内定位版本生效。
+ */
+- (void)stopIndoorLocation;
+
+
+/**
+ *  @brief 转换为百度经纬度的坐标
+ *  @param coordinate 待转换的经纬度
+ *  @param srctype    待转换坐标系类型
+ *  @param destype    目标百度坐标系类型(bd09ll,bd09mc)
+ *  @return 目标百度坐标系经纬度
+ */
++ (CLLocationCoordinate2D) BMKLocationCoordinateConvert:(CLLocationCoordinate2D) coordinate SrcType:(BMKLocationCoordinateType)srctype DesType:(BMKLocationCoordinateType)destype;
+
+/**
+ *  @brief 判断目标经纬度是否在大陆以及港、澳地区。
+ *  @param coordinate 待判断的目标经纬度
+ *  @param coortype 待判断经纬度的坐标系类型
+ *  @return 是否在大陆以及港、澳地区
+ */
++ (BOOL) BMKLocationDataAvailableForCoordinate:(CLLocationCoordinate2D)coordinate withCoorType:(BMKLocationCoordinateType)coortype;
+
+
+@end
+
+#pragma mark - BMKLocationManagerDelegate
+
+
+///BMKLocationManagerDelegate 协议定义了发生错误时的错误回调方法,连续定位的回调方法等。
+@protocol BMKLocationManagerDelegate <NSObject>
+
+@optional
+
+/**
+ *  @brief 当定位发生错误时,会调用代理的此方法。
+ *  @param manager 定位 BMKLocationManager 类。
+ *  @param error 返回的错误,参考 CLError 。
+ */
+- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didFailWithError:(NSError * _Nullable)error;
+
+
+/**
+ *  @brief 连续定位回调函数。
+ *  @param manager 定位 BMKLocationManager 类。
+ *  @param location 定位结果,参考BMKLocation。
+ *  @param error 错误信息。
+ */
+- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error;
+
+/**
+ *  @brief 定位权限状态改变时回调函数
+ *  @param manager 定位 BMKLocationManager 类。
+ *  @param status 定位权限状态。
+ */
+- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;
+
+
+/**
+ * @brief 该方法为BMKLocationManager提示需要设备校正回调方法。
+ * @param manager 提供该定位结果的BMKLocationManager类的实例。
+ */
+- (BOOL)BMKLocationManagerShouldDisplayHeadingCalibration:(BMKLocationManager * _Nonnull)manager;
+
+/**
+ * @brief 该方法为BMKLocationManager提供设备朝向的回调方法。
+ * @param manager 提供该定位结果的BMKLocationManager类的实例
+ * @param heading 设备的朝向结果
+ */
+- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager
+          didUpdateHeading:(CLHeading * _Nullable)heading;
+
+/**
+ * @brief 该方法为BMKLocationManager所在App系统网络状态改变的回调事件。
+ * @param manager 提供该定位结果的BMKLocationManager类的实例
+ * @param state 当前网络状态
+ * @param error 错误信息
+ */
+- (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager
+     didUpdateNetworkState:(BMKLocationNetworkState)state orError:(NSError * _Nullable)error;
+
+
+@end
+
+

+ 36 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationPoi.h

@@ -0,0 +1,36 @@
+//
+//  BMKLocationPoi.h
+//  BMKLocationKit
+//
+//  Created by baidu on 2017/3/2.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+
+
+///描述Poi各属性
+@interface BMKLocationPoi : NSObject
+
+///BMKLocationPoi的id属性
+@property(nonatomic, copy, readonly) NSString *uid;
+
+///BMKLocationPoi的名字属性
+@property(nonatomic, copy, readonly) NSString *name;
+
+///BMKLocationPoi的可信度
+@property(nonatomic, assign, readonly) float relaiability;
+
+
+/**
+ *  @brief 通过NSDictionary初始化方法一
+ */
+- (id)initWithDictionary:(NSDictionary *)dictionary;
+
+
+/**
+ *  @brief 通过NSDictionary初始化方法二
+ */
+- (id)initWithTwoDictionary:(NSDictionary *)dictionary;
+
+@end
+
+

+ 60 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/Headers/BMKLocationReGeocode.h

@@ -0,0 +1,60 @@
+//
+//  BMKLocationReGeocode.h
+//  BMKLocationKit
+//
+//  Created by baidu on 2017/3/2.
+//  Copyright © 2017年 baidu. All rights reserved.
+//
+#import <Foundation/Foundation.h>
+#import "BMKLocationPoi.h"
+
+///BMKLocationReGeocode类。描述跟地址有关的信息.
+@interface BMKLocationReGeocode : NSObject
+
+///国家名字属性
+@property(nonatomic, copy, readonly) NSString *country;
+
+///国家编码属性
+@property(nonatomic, copy, readonly) NSString *countryCode;
+
+///省份名字属性
+@property(nonatomic, copy, readonly) NSString *province;
+
+///城市名字属性
+@property(nonatomic, copy, readonly) NSString *city;
+
+///区名字属性
+@property(nonatomic, copy, readonly) NSString *district;
+
+///街道名字属性
+@property(nonatomic, copy, readonly) NSString *street;
+
+///街道号码属性
+@property(nonatomic, copy, readonly) NSString *streetNumber;
+
+///城市编码属性
+@property(nonatomic, copy, readonly) NSString *cityCode;
+
+///行政区划编码属性
+@property(nonatomic, copy, readonly) NSString *adCode;
+
+
+///位置语义化结果的定位点在什么地方周围的描述信息
+@property(nonatomic, copy, readonly) NSString *locationDescribe;
+
+
+///位置语义化结果的属性,该定位点周围的poi列表信息
+@property(nonatomic, retain, readonly) NSArray<BMKLocationPoi *> *poiList;
+
+/**
+ *  @brief 通过NSData初始化方法
+ */
+- (id)initWithReGeocodeString:(NSData *)reGeocodeString;
+
+
+/**
+ *  @brief 通过JSON初始化方法
+ */
+- (id)initWithJsonString:(NSData *)jsonString withHighAccuracy:(BOOL)highAcc;
+
+@end

+ 11 - 0
RainbowPlanet/Pods/BMKLocationKit/framework/BMKLocationKit.framework/readme.txt

@@ -0,0 +1,11 @@
+1、版本:
+    百度地图iOS定位SDK v1.5
+
+2、是否带IDFA:
+    是
+
+3、是否为Bitcode:
+    是
+
+4、集成方法:
+    http://lbsyun.baidu.com/index.php?title=ios-locsdk

+ 11 - 0
RainbowPlanet/Pods/CryptoSwift/LICENSE

@@ -0,0 +1,11 @@
+Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin.krzyzanowski@gmail.com>
+This software is provided 'as-is', without any express or implied warranty. 
+
+In no event will the authors be held liable for any damages arising from the use of this software. 
+
+Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+
+- The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+- Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+- This notice may not be removed or altered from any source or binary distribution.
+- Redistributions of any form whatsoever must retain the following acknowledgment: 'This product includes software developed by the "Marcin Krzyzanowski" (http://krzyzanowskim.com/).'

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 528 - 0
RainbowPlanet/Pods/CryptoSwift/README.md


+ 40 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AEAD/AEAD.swift

@@ -0,0 +1,40 @@
+//
+//  AEAD.swift
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+//
+
+// https://www.iana.org/assignments/aead-parameters/aead-parameters.xhtml
+
+/// Authenticated Encryption with Associated Data (AEAD)
+public protocol AEAD {
+    static var kLen: Int { get } // key length
+    static var ivRange: Range<Int> { get } // nonce length
+}
+
+extension AEAD {
+    static func calculateAuthenticationTag(authenticator: Authenticator, cipherText: Array<UInt8>, authenticationHeader: Array<UInt8>) throws -> Array<UInt8> {
+        let headerPadding = ((16 - (authenticationHeader.count & 0xf)) & 0xf)
+        let cipherPadding = ((16 - (cipherText.count & 0xf)) & 0xf)
+
+        var mac = authenticationHeader
+        mac += Array<UInt8>(repeating: 0, count: headerPadding)
+        mac += cipherText
+        mac += Array<UInt8>(repeating: 0, count: cipherPadding)
+        mac += UInt64(bigEndian: UInt64(authenticationHeader.count)).bytes()
+        mac += UInt64(bigEndian: UInt64(cipherText.count)).bytes()
+
+        return try authenticator.authenticate(mac)
+    }
+}

+ 59 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AEAD/AEADChaCha20Poly1305.swift

@@ -0,0 +1,59 @@
+//
+//  ChaCha20Poly1305.swift
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+//
+//  https://tools.ietf.org/html/rfc7539#section-2.8.1
+
+/// AEAD_CHACHA20_POLY1305
+public final class AEADChaCha20Poly1305: AEAD {
+    public static let kLen = 32 // key length
+    public static var ivRange = Range<Int>(12...12)
+
+    /// Authenticated encryption
+    public static func encrypt(_ plainText: Array<UInt8>, key: Array<UInt8>, iv: Array<UInt8>, authenticationHeader: Array<UInt8>) throws -> (cipherText: Array<UInt8>, authenticationTag: Array<UInt8>) {
+        let cipher = try ChaCha20(key: key, iv: iv)
+
+        var polykey = Array<UInt8>(repeating: 0, count: kLen)
+        var toEncrypt = polykey
+        polykey = try cipher.encrypt(polykey)
+        toEncrypt += polykey
+        toEncrypt += plainText
+
+        let fullCipherText = try cipher.encrypt(toEncrypt)
+        let cipherText = Array(fullCipherText.dropFirst(64))
+
+        let tag = try calculateAuthenticationTag(authenticator: Poly1305(key: polykey), cipherText: cipherText, authenticationHeader: authenticationHeader)
+        return (cipherText, tag)
+    }
+
+    /// Authenticated decryption
+    public static func decrypt(_ cipherText: Array<UInt8>, key: Array<UInt8>, iv: Array<UInt8>, authenticationHeader: Array<UInt8>, authenticationTag: Array<UInt8>) throws -> (plainText: Array<UInt8>, success: Bool) {
+        let chacha = try ChaCha20(key: key, iv: iv)
+
+        let polykey = try chacha.encrypt(Array<UInt8>(repeating: 0, count: kLen))
+        let mac = try calculateAuthenticationTag(authenticator: Poly1305(key: polykey), cipherText: cipherText, authenticationHeader: authenticationHeader)
+        guard mac == authenticationTag else {
+            return (cipherText, false)
+        }
+
+        var toDecrypt = Array<UInt8>(reserveCapacity: cipherText.count + 64)
+        toDecrypt += polykey
+        toDecrypt += polykey
+        toDecrypt += cipherText
+        let fullPlainText = try chacha.decrypt(toDecrypt)
+        let plainText = Array(fullPlainText.dropFirst(64))
+        return (plainText, true)
+    }
+}

+ 35 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AES.Cryptors.swift

@@ -0,0 +1,35 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+// MARK: Cryptors
+
+extension AES: Cryptors {
+    public func makeEncryptor() throws -> Cryptor & Updatable {
+        let worker = try blockMode.worker(blockSize: AES.blockSize, cipherOperation: encrypt)
+        if worker is StreamModeWorker {
+            return try StreamEncryptor(blockSize: AES.blockSize, padding: padding, worker)
+        }
+        return try BlockEncryptor(blockSize: AES.blockSize, padding: padding, worker)
+    }
+
+    public func makeDecryptor() throws -> Cryptor & Updatable {
+        let cipherOperation: CipherOperationOnBlock = blockMode.options.contains(.useEncryptToDecrypt) == true ? encrypt : decrypt
+        let worker = try blockMode.worker(blockSize: AES.blockSize, cipherOperation: cipherOperation)
+        if worker is StreamModeWorker {
+            return try StreamDecryptor(blockSize: AES.blockSize, padding: padding, worker)
+        }
+        return try BlockDecryptor(blockSize: AES.blockSize, padding: padding, worker)
+    }
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 539 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/AES.swift


+ 148 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Array+Extension.swift

@@ -0,0 +1,148 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+extension Array {
+    public init(reserveCapacity: Int) {
+        self = Array<Element>()
+        self.reserveCapacity(reserveCapacity)
+    }
+
+    var slice: ArraySlice<Element> {
+        return self[self.startIndex ..< self.endIndex]
+    }
+}
+
+extension Array where Element == UInt8 {
+    public init(hex: String) {
+        self.init(reserveCapacity: hex.unicodeScalars.lazy.underestimatedCount)
+        var buffer: UInt8?
+        var skip = hex.hasPrefix("0x") ? 2 : 0
+        for char in hex.unicodeScalars.lazy {
+            guard skip == 0 else {
+                skip -= 1
+                continue
+            }
+            guard char.value >= 48 && char.value <= 102 else {
+                removeAll()
+                return
+            }
+            let v: UInt8
+            let c: UInt8 = UInt8(char.value)
+            switch c {
+            case let c where c <= 57:
+                v = c - 48
+            case let c where c >= 65 && c <= 70:
+                v = c - 55
+            case let c where c >= 97:
+                v = c - 87
+            default:
+                removeAll()
+                return
+            }
+            if let b = buffer {
+                append(b << 4 | v)
+                buffer = nil
+            } else {
+                buffer = v
+            }
+        }
+        if let b = buffer {
+            append(b)
+        }
+    }
+
+    public func toHexString() -> String {
+        return `lazy`.reduce("") {
+            var s = String($1, radix: 16)
+            if s.count == 1 {
+                s = "0" + s
+            }
+            return $0 + s
+        }
+    }
+}
+
+extension Array where Element == UInt8 {
+    /// split in chunks with given chunk size
+    @available(*, deprecated)
+    public func chunks(size chunksize: Int) -> Array<Array<Element>> {
+        var words = Array<Array<Element>>()
+        words.reserveCapacity(count / chunksize)
+        for idx in stride(from: chunksize, through: count, by: chunksize) {
+            words.append(Array(self[idx - chunksize ..< idx])) // slow for large table
+        }
+        let remainder = suffix(count % chunksize)
+        if !remainder.isEmpty {
+            words.append(Array(remainder))
+        }
+        return words
+    }
+
+    public func md5() -> [Element] {
+        return Digest.md5(self)
+    }
+
+    public func sha1() -> [Element] {
+        return Digest.sha1(self)
+    }
+
+    public func sha224() -> [Element] {
+        return Digest.sha224(self)
+    }
+
+    public func sha256() -> [Element] {
+        return Digest.sha256(self)
+    }
+
+    public func sha384() -> [Element] {
+        return Digest.sha384(self)
+    }
+
+    public func sha512() -> [Element] {
+        return Digest.sha512(self)
+    }
+
+    public func sha2(_ variant: SHA2.Variant) -> [Element] {
+        return Digest.sha2(self, variant: variant)
+    }
+
+    public func sha3(_ variant: SHA3.Variant) -> [Element] {
+        return Digest.sha3(self, variant: variant)
+    }
+
+    public func crc32(seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
+        return Checksum.crc32(self, seed: seed, reflect: reflect)
+    }
+
+    public func crc32c(seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
+        return Checksum.crc32c(self, seed: seed, reflect: reflect)
+    }
+
+    public func crc16(seed: UInt16? = nil) -> UInt16 {
+        return Checksum.crc16(self, seed: seed)
+    }
+
+    public func encrypt(cipher: Cipher) throws -> [Element] {
+        return try cipher.encrypt(slice)
+    }
+
+    public func decrypt(cipher: Cipher) throws -> [Element] {
+        return try cipher.decrypt(slice)
+    }
+
+    public func authenticate<A: Authenticator>(with authenticator: A) throws -> [Element] {
+        return try authenticator.authenticate(self)
+    }
+}

+ 20 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Authenticator.swift

@@ -0,0 +1,20 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+/// Message authentication code.
+public protocol Authenticator {
+    /// Calculate Message Authentication Code (MAC) for message.
+    func authenticate(_ bytes: Array<UInt8>) throws -> Array<UInt8>
+}

+ 63 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BatchedCollection.swift

@@ -0,0 +1,63 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+struct BatchedCollectionIndex<Base: Collection> {
+    let range: Range<Base.Index>
+}
+
+extension BatchedCollectionIndex: Comparable {
+    static func == <Base>(lhs: BatchedCollectionIndex<Base>, rhs: BatchedCollectionIndex<Base>) -> Bool {
+        return lhs.range.lowerBound == rhs.range.lowerBound
+    }
+
+    static func < <Base>(lhs: BatchedCollectionIndex<Base>, rhs: BatchedCollectionIndex<Base>) -> Bool {
+        return lhs.range.lowerBound < rhs.range.lowerBound
+    }
+}
+
+protocol BatchedCollectionType: Collection {
+    associatedtype Base: Collection
+}
+
+struct BatchedCollection<Base: Collection>: Collection {
+    let base: Base
+    let size: Int
+    typealias Index = BatchedCollectionIndex<Base>
+    private func nextBreak(after idx: Base.Index) -> Base.Index {
+        return base.index(idx, offsetBy: size, limitedBy: base.endIndex) ?? base.endIndex
+    }
+
+    var startIndex: Index {
+        return Index(range: base.startIndex..<nextBreak(after: base.startIndex))
+    }
+
+    var endIndex: Index {
+        return Index(range: base.endIndex..<base.endIndex)
+    }
+
+    func index(after idx: Index) -> Index {
+        return Index(range: idx.range.upperBound..<nextBreak(after: idx.range.upperBound))
+    }
+
+    subscript(idx: Index) -> Base.SubSequence {
+        return base[idx.range]
+    }
+}
+
+extension Collection {
+    func batched(by size: Int) -> BatchedCollection<Self> {
+        return BatchedCollection(base: self, size: size)
+    }
+}

+ 25 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Bit.swift

@@ -0,0 +1,25 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public enum Bit: Int {
+    case zero
+    case one
+}
+
+extension Bit {
+    func inverted() -> Bit {
+        return self == .zero ? .one : .zero
+    }
+}

+ 18 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockCipher.swift

@@ -0,0 +1,18 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+protocol BlockCipher: Cipher {
+    static var blockSize: Int { get }
+}

+ 85 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockDecryptor.swift

@@ -0,0 +1,85 @@
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2018 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public class BlockDecryptor: Cryptor, Updatable {
+    private let blockSize: Int
+    private let padding: Padding
+    private var worker: CipherModeWorker
+    private var accumulated = Array<UInt8>()
+
+    init(blockSize: Int, padding: Padding, _ worker: CipherModeWorker) throws {
+        self.blockSize = blockSize
+        self.padding = padding
+        self.worker = worker
+    }
+
+    public func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
+        accumulated += bytes
+
+        // If a worker (eg GCM) can combine ciphertext + tag
+        // we need to remove tag from the ciphertext.
+        if !isLast && accumulated.count < blockSize + worker.additionalBufferSize {
+            return []
+        }
+
+        let accumulatedWithoutSuffix: Array<UInt8>
+        if worker.additionalBufferSize > 0 {
+            // FIXME: how slow is that?
+            accumulatedWithoutSuffix = Array(accumulated.prefix(accumulated.count - worker.additionalBufferSize))
+        } else {
+            accumulatedWithoutSuffix = accumulated
+        }
+
+        var processedBytesCount = 0
+        var plaintext = Array<UInt8>(reserveCapacity: accumulatedWithoutSuffix.count)
+        // Processing in a block-size manner. It's good for block modes, but bad for stream modes.
+        for var chunk in accumulatedWithoutSuffix.batched(by: blockSize) {
+            if isLast || (accumulatedWithoutSuffix.count - processedBytesCount) >= blockSize {
+                let isLastChunk = processedBytesCount + chunk.count == accumulatedWithoutSuffix.count
+                
+                if isLast, isLastChunk, var finalizingWorker = worker as? FinalizingDecryptModeWorker {
+                    chunk = try finalizingWorker.willDecryptLast(bytes: chunk + accumulated.suffix(worker.additionalBufferSize)) // tag size
+                }
+
+                if !chunk.isEmpty {
+                    plaintext += worker.decrypt(block: chunk)
+                }
+
+                if isLast, isLastChunk, var finalizingWorker = worker as? FinalizingDecryptModeWorker {
+                    plaintext = Array(try finalizingWorker.didDecryptLast(bytes: plaintext.slice))
+                }
+
+                processedBytesCount += chunk.count
+            }
+        }
+        accumulated.removeFirst(processedBytesCount) // super-slow
+
+        if isLast {
+            plaintext = padding.remove(from: plaintext, blockSize: blockSize)
+        }
+
+        return plaintext
+    }
+
+    public func seek(to position: Int) throws {
+        guard var worker = self.worker as? SeekableModeWorker else {
+            fatalError("Not supported")
+        }
+
+        try worker.seek(to: position)
+        self.worker = worker
+
+        accumulated = []
+    }
+}

+ 57 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockEncryptor.swift

@@ -0,0 +1,57 @@
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2018 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+final class BlockEncryptor: Cryptor, Updatable {
+    private let blockSize: Int
+    private var worker: CipherModeWorker
+    private let padding: Padding
+    // Accumulated bytes. Not all processed bytes.
+    private var accumulated = Array<UInt8>(reserveCapacity: 16)
+
+    private var lastBlockRemainder = 0
+
+    init(blockSize: Int, padding: Padding, _ worker: CipherModeWorker) throws {
+        self.blockSize = blockSize
+        self.padding = padding
+        self.worker = worker
+    }
+
+    // MARK: Updatable
+    public func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool) throws -> Array<UInt8> {
+        accumulated += bytes
+
+        if isLast {
+            accumulated = padding.add(to: accumulated, blockSize: blockSize)
+        }
+
+        var encrypted = Array<UInt8>(reserveCapacity: accumulated.count)
+        for chunk in accumulated.batched(by: blockSize) {
+            if isLast || chunk.count == blockSize {
+                encrypted += worker.encrypt(block: chunk)
+            }
+        }
+
+        // Stream encrypts all, so it removes all elements
+        accumulated.removeFirst(encrypted.count)
+
+        if var finalizingWorker = worker as? FinalizingEncryptModeWorker, isLast == true {
+            encrypted = Array(try finalizingWorker.finalize(encrypt: encrypted.slice))
+        }
+
+        return encrypted
+    }
+
+    func seek(to: Int) throws {
+        fatalError("Not supported")
+    }
+}

+ 24 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockMode.swift

@@ -0,0 +1,24 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public typealias CipherOperationOnBlock = (_ block: ArraySlice<UInt8>) -> Array<UInt8>?
+
+public protocol BlockMode {
+    var options: BlockModeOption { get }
+    //TODO: doesn't have to be public
+    func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker
+}
+
+typealias StreamMode = BlockMode

+ 27 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/BlockModeOptions.swift

@@ -0,0 +1,27 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public struct BlockModeOption: OptionSet {
+    public let rawValue: Int
+
+    public init(rawValue: Int) {
+        self.rawValue = rawValue
+    }
+
+    static let none = BlockModeOption(rawValue: 1 << 0)
+    static let initializationVectorRequired = BlockModeOption(rawValue: 1 << 1)
+    static let paddingRequired = BlockModeOption(rawValue: 1 << 2)
+    static let useEncryptToDecrypt = BlockModeOption(rawValue: 1 << 3)
+}

+ 70 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CBC.swift

@@ -0,0 +1,70 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  Cipher-block chaining (CBC)
+//
+
+public struct CBC: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .paddingRequired]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return CBCModeWorker(blockSize: blockSize, iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
+struct CBCModeWorker: BlockModeWorker {
+    let cipherOperation: CipherOperationOnBlock
+    var blockSize: Int
+    let additionalBufferSize: Int = 0
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
+
+    init(blockSize: Int, iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.blockSize = blockSize
+        self.iv = iv
+        self.cipherOperation = cipherOperation
+    }
+
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
+            return Array(plaintext)
+        }
+        prev = ciphertext.slice
+        return ciphertext
+    }
+
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let plaintext = cipherOperation(ciphertext) else {
+            return Array(ciphertext)
+        }
+        let result: Array<UInt8> = xor(prev ?? iv, plaintext)
+        prev = ciphertext
+        return result
+    }
+}

+ 359 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CCM.swift

@@ -0,0 +1,359 @@
+////  CryptoSwift
+//
+//  Copyright (C) 2014-2018 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+// CCM mode combines the well known CBC-MAC with the well known counter mode of encryption.
+// https://tools.ietf.org/html/rfc3610
+// https://csrc.nist.gov/publications/detail/sp/800-38c/final
+
+#if canImport(Darwin)
+import Darwin
+#else
+import Glibc
+#endif
+
+
+/// Counter with Cipher Block Chaining-Message Authentication Code
+public struct CCM: StreamMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+        case invalidParameter
+        case fail
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let nonce: Array<UInt8>
+    private let additionalAuthenticatedData: Array<UInt8>?
+    private let tagLength: Int
+    private let messageLength: Int // total message length. need to know in advance
+
+    // `authenticationTag` nil for encryption, known tag for decryption
+    /// For encryption, the value is set at the end of the encryption.
+    /// For decryption, this is a known Tag to validate against.
+    public var authenticationTag: Array<UInt8>?
+
+    /// Initialize CCM
+    ///
+    /// - Parameters:
+    ///   - iv: Initialization vector. Nonce. Valid length between 7 and 13 bytes.
+    ///   - tagLength: Authentication tag length, in bytes. Value of {4, 6, 8, 10, 12, 14, 16}.
+    ///   - messageLength: Plaintext message length (excluding tag if attached). Length have to be provided in advance.
+    ///   - additionalAuthenticatedData: Additional authenticated data.
+    public init(iv: Array<UInt8>, tagLength: Int, messageLength: Int, additionalAuthenticatedData: Array<UInt8>? = nil) {
+        self.nonce = iv
+        self.tagLength = tagLength
+        self.additionalAuthenticatedData = additionalAuthenticatedData
+        self.messageLength = messageLength // - tagLength
+    }
+
+    /// Initialize CCM
+    ///
+    /// - Parameters:
+    ///   - iv: Initialization vector. Nonce. Valid length between 7 and 13 bytes.
+    ///   - tagLength: Authentication tag length, in bytes. Value of {4, 6, 8, 10, 12, 14, 16}.
+    ///   - messageLength: Plaintext message length (excluding tag if attached). Length have to be provided in advance.
+    ///   - authenticationTag: Authentication Tag value if not concatenated to ciphertext.
+    ///   - additionalAuthenticatedData: Additional authenticated data.
+    public init(iv: Array<UInt8>, tagLength: Int, messageLength: Int, authenticationTag: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil) {
+        self.init(iv: iv, tagLength: tagLength, messageLength: messageLength, additionalAuthenticatedData: additionalAuthenticatedData)
+        self.authenticationTag = authenticationTag
+    }
+
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if nonce.isEmpty {
+            throw Error.invalidInitializationVector
+        }
+
+        return CCMModeWorker(blockSize: blockSize, nonce: nonce.slice, messageLength: messageLength, additionalAuthenticatedData: additionalAuthenticatedData, tagLength: tagLength, cipherOperation: cipherOperation)
+    }
+}
+
+class CCMModeWorker: StreamModeWorker, SeekableModeWorker, CounterModeWorker, FinalizingEncryptModeWorker, FinalizingDecryptModeWorker {
+    typealias Counter = Int
+    var counter = 0
+
+    let cipherOperation: CipherOperationOnBlock
+    let blockSize: Int
+    private let tagLength: Int
+    private let messageLength: Int // total message length. need to know in advance
+    private let q: UInt8
+
+    let additionalBufferSize: Int
+    private var keystreamPosIdx = 0
+    private let nonce: Array<UInt8>
+    private var last_y: ArraySlice<UInt8> = []
+    private var keystream: Array<UInt8> = []
+    // Known Tag used to validate during decryption
+    private var expectedTag: Array<UInt8>?
+
+    public enum Error: Swift.Error {
+        case invalidParameter
+    }
+
+    init(blockSize: Int, nonce: ArraySlice<UInt8>, messageLength: Int,  additionalAuthenticatedData: [UInt8]?, expectedTag: Array<UInt8>? = nil, tagLength: Int, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.blockSize = 16 // CCM is defined for 128 block size
+        self.tagLength = tagLength
+        self.additionalBufferSize = tagLength
+        self.messageLength = messageLength
+        self.expectedTag = expectedTag
+        self.cipherOperation = cipherOperation
+        self.nonce = Array(nonce)
+        self.q = UInt8(15 - nonce.count) // n = 15-q
+
+        let hasAssociatedData = additionalAuthenticatedData != nil && !additionalAuthenticatedData!.isEmpty
+        processControlInformation(nonce: self.nonce, tagLength: tagLength, hasAssociatedData: hasAssociatedData)
+
+        if let aad = additionalAuthenticatedData, hasAssociatedData {
+            process(aad: aad)
+        }
+    }
+
+    // For the very first time setup new IV (aka y0) from the block0
+    private func processControlInformation(nonce: [UInt8], tagLength: Int, hasAssociatedData: Bool) {
+        let block0 = try! format(nonce: nonce, Q: UInt32(messageLength), q: q, t: UInt8(tagLength), hasAssociatedData: hasAssociatedData).slice
+        let y0 = cipherOperation(block0)!.slice
+        last_y = y0
+    }
+
+    private func process(aad: [UInt8]) {
+        let encodedAAD = format(aad: aad)
+
+        for block_i in encodedAAD.batched(by: 16) {
+            let y_i = cipherOperation(xor(block_i, last_y))!.slice
+            last_y = y_i
+        }
+    }
+
+    private func S(i: Int) throws -> [UInt8] {
+        let ctr = try format(counter: i, nonce: nonce, q: q)
+        return cipherOperation(ctr.slice)!
+    }
+
+    func seek(to position: Int) throws {
+        self.counter = position
+        keystream = try S(i: position)
+        let offset = position % blockSize
+        keystreamPosIdx = offset
+    }
+
+    func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        var result = Array<UInt8>(reserveCapacity: plaintext.count)
+
+        var processed = 0
+        while processed < plaintext.count {
+            // Need a full block here to update keystream and do CBC
+            if keystream.isEmpty || keystreamPosIdx == blockSize {
+                // y[i], where i is the counter. Can encrypt 1 block at a time
+                counter += 1
+                guard let S = try? S(i: counter) else { return Array(plaintext) }
+                let plaintextP = addPadding(Array(plaintext), blockSize: blockSize)
+                guard let y = cipherOperation(xor(last_y, plaintextP)) else { return Array(plaintext) }
+                last_y = y.slice
+
+                keystream = S
+                keystreamPosIdx = 0
+            }
+
+            let xored: Array<UInt8> = xor(plaintext[plaintext.startIndex.advanced(by: processed)...], keystream[keystreamPosIdx...])
+            keystreamPosIdx += xored.count
+            processed += xored.count
+            result += xored
+        }
+        return result
+    }
+
+    func finalize(encrypt ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // concatenate T at the end
+        guard let S0 = try? S(i: 0) else { return ciphertext }
+
+        let computedTag = xor(last_y.prefix(tagLength), S0) as ArraySlice<UInt8>
+        return ciphertext + computedTag
+    }
+
+    // Decryption is stream
+    // CBC is block
+    private var accumulatedPlaintext: [UInt8] = []
+
+    func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        var output = Array<UInt8>(reserveCapacity: ciphertext.count)
+
+        do {
+            var currentCounter = counter
+            var processed = 0
+            while processed < ciphertext.count {
+                // Need a full block here to update keystream and do CBC
+                // New keystream for a new block
+                if keystream.isEmpty || keystreamPosIdx == blockSize {
+                    currentCounter += 1
+                    guard let S = try? S(i: currentCounter) else { return Array(ciphertext) }
+                    keystream = S
+                    keystreamPosIdx = 0
+                }
+
+                let xored: Array<UInt8> = xor(ciphertext[ciphertext.startIndex.advanced(by: processed)...], keystream[keystreamPosIdx...]) // plaintext
+                keystreamPosIdx += xored.count
+                processed += xored.count
+                output += xored
+                counter = currentCounter
+            }
+        }
+
+        // Accumulate plaintext for the MAC calculations at the end.
+        // It would be good to process it together though, here.
+        accumulatedPlaintext += output
+
+        // Shouldn't return plaintext until validate tag.
+        // With incremental update, can't validate tag until all block are processed.
+        return output
+    }
+
+    func finalize(decrypt plaintext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // concatenate T at the end
+        let computedTag = Array(last_y.prefix(tagLength))
+        guard let expectedTag = self.expectedTag, expectedTag == computedTag else {
+            throw CCM.Error.fail
+        }
+
+        return plaintext
+    }
+
+    @discardableResult
+    func willDecryptLast(bytes ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // get tag of additionalBufferSize size
+        // `ciphertext` contains at least additionalBufferSize bytes
+        // overwrite expectedTag property used later for verification
+        guard let S0 = try? S(i: 0) else { return ciphertext }
+        self.expectedTag = xor(ciphertext.suffix(tagLength), S0) as [UInt8]
+        return ciphertext[ciphertext.startIndex..<ciphertext.endIndex.advanced(by: -Swift.min(tagLength,ciphertext.count))]
+    }
+
+    func didDecryptLast(bytes plaintext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+
+        // Calculate Tag, from the last CBC block, for accumulated plaintext.
+        var processed = 0
+        for block in accumulatedPlaintext.batched(by: blockSize) {
+            let blockP = addPadding(Array(block), blockSize: blockSize)
+            guard let y = cipherOperation(xor(last_y, blockP)) else { return plaintext }
+            last_y = y.slice
+            processed += block.count
+        }
+        accumulatedPlaintext.removeFirst(processed)
+        return plaintext
+    }
+}
+
+// Q - octet length of P
+// q - octet length of Q. Maximum length (in octets) of payload. An element of {2,3,4,5,6,7,8}
+// t - octet length of T (MAC length). An element of {4,6,8,10,12,14,16}
+private func format(nonce N: [UInt8], Q: UInt32, q: UInt8, t: UInt8, hasAssociatedData: Bool) throws -> [UInt8] {
+    var flags0: UInt8 = 0
+
+    if hasAssociatedData {
+        // 7 bit
+        flags0 |= (1 << 6)
+    }
+
+    // 6,5,4 bit is t in 3 bits
+    flags0 |= (((t-2)/2) & 0x07) << 3
+
+    // 3,2,1 bit is q in 3 bits
+    flags0 |= ((q-1) & 0x07) << 0
+
+    var block0: [UInt8] = Array<UInt8>(repeating: 0, count: 16)
+    block0[0] = flags0
+
+    // N in 1...(15-q) octets, n = 15-q
+    // n is an element of {7,8,9,10,11,12,13}
+    let n = 15-Int(q)
+    guard (n + Int(q)) == 15 else {
+        // n+q == 15
+        throw CCMModeWorker.Error.invalidParameter
+    }
+    block0[1...n] = N[0...(n-1)]
+
+    // Q in (16-q)...15 octets
+    block0[(16-Int(q))...15] = Q.bytes(totalBytes: Int(q)).slice
+
+    return block0
+}
+
+/// Formatting of the Counter Blocks. Ctr[i]
+/// The counter generation function.
+/// Q - octet length of P
+/// q - octet length of Q. Maximum length (in octets) of payload. An element of {2,3,4,5,6,7,8}
+private func format(counter i: Int, nonce N: [UInt8], q: UInt8) throws -> [UInt8] {
+    var flags0: UInt8 = 0
+
+    // bit 8,7 is Reserved
+    // bit 4,5,6 shall be set to 0
+    // 3,2,1 bit is q in 3 bits
+    flags0 |= ((q-1) & 0x07) << 0
+
+    var block = Array<UInt8>(repeating: 0, count: 16) // block[0]
+    block[0] = flags0
+
+    // N in 1...(15-q) octets, n = 15-q
+    // n is an element of {7,8,9,10,11,12,13}
+    let n = 15-Int(q)
+    guard (n + Int(q)) == 15 else {
+        // n+q == 15
+        throw CCMModeWorker.Error.invalidParameter
+    }
+    block[1...n] = N[0...(n-1)]
+
+    // [i]8q in (16-q)...15 octets
+    block[(16-Int(q))...15] = i.bytes(totalBytes: Int(q)).slice
+
+    return block
+}
+
+/// Resulting can be partitioned into 16-octet blocks
+private func format(aad: [UInt8]) -> [UInt8] {
+    let a = aad.count
+
+    switch Double(a) {
+    case 0..<65280: // 2^16-2^8
+        // [a]16
+        return addPadding(a.bytes(totalBytes: 2) + aad, blockSize: 16)
+    case 65280..<4_294_967_296: // 2^32
+        // [a]32
+        return addPadding([0xFF, 0xFE] + a.bytes(totalBytes: 4) + aad, blockSize: 16)
+    case 4_294_967_296..<pow(2,64): // 2^64
+        // [a]64
+        return addPadding([0xFF, 0xFF] + a.bytes(totalBytes: 8) + aad, blockSize: 16)
+    default:
+        // Reserved
+        return addPadding(aad, blockSize: 16)
+    }
+}
+
+// If data is not a multiple of block size bytes long then the remainder is zero padded
+// Note: It's similar to ZeroPadding, but it's not the same.
+private func addPadding(_ bytes: Array<UInt8>, blockSize: Int) -> Array<UInt8> {
+    if bytes.isEmpty {
+        return Array<UInt8>(repeating: 0, count: blockSize)
+    }
+
+    let remainder = bytes.count % blockSize
+    if remainder == 0 {
+        return bytes
+    }
+
+    let paddingCount = blockSize - remainder
+    if paddingCount > 0 {
+        return bytes + Array<UInt8>(repeating: 0, count: paddingCount)
+    }
+    return bytes
+}

+ 70 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CFB.swift

@@ -0,0 +1,70 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  Cipher feedback (CFB)
+//
+
+public struct CFB: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return CFBModeWorker(blockSize: blockSize, iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
+struct CFBModeWorker: BlockModeWorker {
+    let cipherOperation: CipherOperationOnBlock
+    let blockSize: Int
+    let additionalBufferSize: Int = 0
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
+
+    init(blockSize: Int, iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.blockSize = blockSize
+        self.iv = iv
+        self.cipherOperation = cipherOperation
+    }
+
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let ciphertext = cipherOperation(prev ?? iv) else {
+            return Array(plaintext)
+        }
+        prev = xor(plaintext, ciphertext.slice)
+        return Array(prev ?? [])
+    }
+
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let plaintext = cipherOperation(prev ?? iv) else {
+            return Array(ciphertext)
+        }
+        let result: Array<UInt8> = xor(plaintext, ciphertext)
+        prev = ciphertext
+        return result
+    }
+}

+ 134 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CTR.swift

@@ -0,0 +1,134 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  Counter (CTR)
+
+public struct CTR: StreamMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let iv: Array<UInt8>
+    private let counter: Int
+
+    public init(iv: Array<UInt8>, counter: Int = 0) {
+        self.iv = iv
+        self.counter = counter
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return CTRModeWorker(blockSize: blockSize, iv: iv.slice, counter: counter, cipherOperation: cipherOperation)
+    }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct CTRModeWorker: StreamModeWorker, SeekableModeWorker, CounterModeWorker {
+    typealias Counter = CTRCounter
+
+    final class CTRCounter {
+        private let constPrefix: Array<UInt8>
+        private var value: UInt64
+        //TODO: make it an updatable value, computing is too slow
+        var bytes: Array<UInt8> {
+            return constPrefix + value.bytes()
+        }
+
+        init(_ initialValue: Array<UInt8>) {
+            let halfIndex = initialValue.startIndex.advanced(by: initialValue.count / 2)
+            constPrefix = Array(initialValue[initialValue.startIndex..<halfIndex])
+
+            let suffixBytes = Array(initialValue[halfIndex...])
+            value = UInt64(bytes: suffixBytes)
+        }
+
+        convenience init(nonce: Array<UInt8>, startAt index: Int) {
+            self.init(buildCounterValue(nonce, counter: UInt64(index)))
+        }
+
+        static func +=(lhs: CTRCounter, rhs: Int) {
+            lhs.value += UInt64(rhs)
+        }
+    }
+
+    let cipherOperation: CipherOperationOnBlock
+    let additionalBufferSize: Int = 0
+    let iv: Array<UInt8>
+    var counter: CTRCounter
+
+    private let blockSize: Int
+
+    // The same keystream is used for the block length plaintext
+    // As new data is added, keystream suffix is used to xor operation.
+    private var keystream: Array<UInt8>
+    private var keystreamPosIdx = 0
+
+    init(blockSize: Int, iv: ArraySlice<UInt8>, counter: Int, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.cipherOperation = cipherOperation
+        self.blockSize = blockSize
+        self.iv = Array(iv)
+
+        // the first keystream is calculated from the nonce = initial value of counter
+        self.counter = CTRCounter(nonce: Array(iv), startAt: counter)
+        self.keystream = Array(cipherOperation(self.counter.bytes.slice)!)
+    }
+
+    mutating func seek(to position: Int) throws {
+        let offset = position % blockSize
+        counter = CTRCounter(nonce: iv, startAt: position / blockSize)
+        keystream = Array(cipherOperation(counter.bytes.slice)!)
+        keystreamPosIdx = offset
+    }
+
+    // plaintext is at most blockSize long
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        var result = Array<UInt8>(reserveCapacity: plaintext.count)
+
+        var processed = 0
+        while processed < plaintext.count {
+            // Update keystream
+            if keystreamPosIdx == blockSize {
+                counter += 1
+                keystream = Array(cipherOperation(counter.bytes.slice)!)
+                keystreamPosIdx = 0
+            }
+
+            let xored: Array<UInt8> = xor(plaintext[plaintext.startIndex.advanced(by: processed)...], keystream[keystreamPosIdx...])
+            keystreamPosIdx += xored.count
+            processed += xored.count
+            result += xored
+        }
+
+        return result
+    }
+
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        return encrypt(block: ciphertext)
+    }
+}
+
+private func buildCounterValue(_ iv: Array<UInt8>, counter: UInt64) -> Array<UInt8> {
+    let noncePartLen = iv.count / 2
+    let noncePrefix = iv[iv.startIndex..<iv.startIndex.advanced(by: noncePartLen)]
+    let nonceSuffix = iv[iv.startIndex.advanced(by: noncePartLen)..<iv.startIndex.advanced(by: iv.count)]
+    let c = UInt64(bytes: nonceSuffix) + counter
+    return noncePrefix + c.bytes()
+}

+ 61 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/CipherModeWorker.swift

@@ -0,0 +1,61 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public protocol CipherModeWorker {
+    var cipherOperation: CipherOperationOnBlock { get }
+
+    // Additional space needed when incrementally process data
+    // eg. for GCM combined mode
+    var additionalBufferSize: Int { get }
+
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8>
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8>
+}
+
+/// Block workers use `BlockEncryptor`
+public protocol BlockModeWorker: CipherModeWorker {
+    var blockSize: Int { get }
+}
+
+public protocol CounterModeWorker: CipherModeWorker {
+    associatedtype Counter
+    var counter: Counter { get set }
+}
+
+public protocol SeekableModeWorker: CipherModeWorker {
+    mutating func seek(to position: Int) throws
+}
+
+/// Stream workers use `StreamEncryptor`
+public protocol StreamModeWorker: CipherModeWorker {
+}
+
+public protocol FinalizingEncryptModeWorker: CipherModeWorker {
+    // Any final calculations, eg. calculate tag
+    // Called after the last block is encrypted
+    mutating func finalize(encrypt ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8>
+}
+
+public protocol FinalizingDecryptModeWorker: CipherModeWorker {
+    // Called before decryption, hence input is ciphertext.
+    // ciphertext is either a last block, or a tag (for stream workers)
+    @discardableResult
+    mutating func willDecryptLast(bytes ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8>
+    // Called after decryption, hence input is ciphertext
+    mutating func didDecryptLast(bytes plaintext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8>
+    // Any final calculations, eg. calculate tag
+    // Called after the last block is encrypted
+    mutating func finalize(decrypt plaintext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8>
+}

+ 51 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/ECB.swift

@@ -0,0 +1,51 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  Electronic codebook (ECB)
+//
+
+public struct ECB: BlockMode {
+    public let options: BlockModeOption = .paddingRequired
+
+    public init() {
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        return ECBModeWorker(blockSize: blockSize, cipherOperation: cipherOperation)
+    }
+}
+
+struct ECBModeWorker: BlockModeWorker {
+    typealias Element = Array<UInt8>
+    let cipherOperation: CipherOperationOnBlock
+    let blockSize: Int
+    let additionalBufferSize: Int = 0
+
+    init(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.blockSize = blockSize
+        self.cipherOperation = cipherOperation
+    }
+
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let ciphertext = cipherOperation(plaintext) else {
+            return Array(plaintext)
+        }
+        return ciphertext
+    }
+
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        return encrypt(block: ciphertext)
+    }
+}

+ 370 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/GCM.swift

@@ -0,0 +1,370 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  Galois/Counter Mode (GCM)
+//  https://csrc.nist.gov/publications/detail/sp/800-38d/final
+//  ref: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.694.695&rep=rep1&type=pdf
+//
+
+public final class GCM: BlockMode {
+    public enum Mode {
+        /// In combined mode, the authentication tag is directly appended to the encrypted message. This is usually what you want.
+        case combined
+        /// Some applications may need to store the authentication tag and the encrypted message at different locations.
+        case detached
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .useEncryptToDecrypt]
+
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+        /// Special symbol FAIL that indicates that the inputs are not authentic.
+        case fail
+    }
+
+    private let iv: Array<UInt8>
+    private let additionalAuthenticatedData: Array<UInt8>?
+    private let mode: Mode
+    
+    /// Length of authentication tag, in bytes.
+    /// For encryption, the value is given as init parameter.
+    /// For decryption, the lenght of given authentication tag is used.
+    private let tagLength: Int
+
+    // `authenticationTag` nil for encryption, known tag for decryption
+    /// For encryption, the value is set at the end of the encryption.
+    /// For decryption, this is a known Tag to validate against.
+    public var authenticationTag: Array<UInt8>?
+
+    // encrypt
+    /// Possible tag lengths: 4,8,12,13,14,15,16
+    public init(iv: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil, tagLength: Int = 16, mode: Mode = .detached) {
+        self.iv = iv
+        self.additionalAuthenticatedData = additionalAuthenticatedData
+        self.mode = mode
+        self.tagLength = tagLength
+    }
+
+    // decrypt
+    public convenience init(iv: Array<UInt8>, authenticationTag: Array<UInt8>, additionalAuthenticatedData: Array<UInt8>? = nil, mode: Mode = .detached) {
+        self.init(iv: iv, additionalAuthenticatedData: additionalAuthenticatedData, tagLength: authenticationTag.count, mode: mode)
+        self.authenticationTag = authenticationTag
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if iv.isEmpty {
+            throw Error.invalidInitializationVector
+        }
+
+        let worker = GCMModeWorker(iv: iv.slice, aad: additionalAuthenticatedData?.slice, expectedTag: authenticationTag, tagLength: tagLength, mode: mode, cipherOperation: cipherOperation)
+        worker.didCalculateTag = { [weak self] tag in
+            self?.authenticationTag = tag
+        }
+        return worker
+    }
+}
+
+// MARK: - Worker
+
+final class GCMModeWorker: BlockModeWorker, FinalizingEncryptModeWorker, FinalizingDecryptModeWorker {
+    let cipherOperation: CipherOperationOnBlock
+
+    // Callback called when authenticationTag is ready
+    var didCalculateTag: ((Array<UInt8>) -> Void)?
+
+    private let tagLength: Int
+    // GCM nonce is 96-bits by default. It's the most effective length for the IV
+    private static let nonceSize = 12
+
+    // GCM is designed for 128-bit ciphers like AES (but not really for Blowfish). 64-bit mode is not implemented.
+    let blockSize = 16 // 128 bit
+    let additionalBufferSize: Int
+    private let iv: ArraySlice<UInt8>
+    private let mode: GCM.Mode
+    private var counter: UInt128
+    private let eky0: UInt128 // move to GF?
+    private let h: UInt128
+
+    // Additional authenticated data
+    private let aad: ArraySlice<UInt8>?
+    // Known Tag used to validate during decryption
+    private var expectedTag: Array<UInt8>?
+
+    // Note: need new worker to reset instance
+    // Use empty aad if not specified. AAD is optional.
+    private lazy var gf: GF = {
+        if let aad = aad {
+            return GF(aad: Array(aad), h: h, blockSize: blockSize)
+        }
+        return GF(aad: [UInt8](), h: h, blockSize: blockSize)
+    }()
+
+    init(iv: ArraySlice<UInt8>, aad: ArraySlice<UInt8>? = nil, expectedTag: Array<UInt8>? = nil, tagLength: Int, mode: GCM.Mode, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.cipherOperation = cipherOperation
+        self.iv = iv
+        self.mode = mode
+        self.aad = aad
+        self.expectedTag = expectedTag
+        self.tagLength = tagLength
+        h = UInt128(cipherOperation(Array<UInt8>(repeating: 0, count: blockSize).slice)!) // empty block
+
+        if mode == .combined {
+            self.additionalBufferSize = tagLength
+        } else {
+            self.additionalBufferSize = 0
+        }
+        
+        // Assume nonce is 12 bytes long, otherwise initial counter would be calulated from GHASH
+        // counter = GF.ghash(aad: [UInt8](), ciphertext: nonce)
+        if iv.count == GCMModeWorker.nonceSize {
+            counter = makeCounter(nonce: Array(self.iv))
+        } else {
+            counter = GF.ghash(h: h, aad: [UInt8](), ciphertext: Array(iv), blockSize: blockSize)
+        }
+
+        // Set constants
+        eky0 = UInt128(cipherOperation(counter.bytes.slice)!)
+    }
+
+    func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        counter = incrementCounter(counter)
+
+        guard let ekyN = cipherOperation(counter.bytes.slice) else {
+            return Array(plaintext)
+        }
+
+        // plaintext block ^ ek1
+        let ciphertext = xor(plaintext, ekyN) as Array<UInt8>
+
+        // update ghash incrementally
+        gf.ghashUpdate(block: ciphertext)
+
+        return Array(ciphertext)
+    }
+
+    func finalize(encrypt ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // Calculate MAC tag.
+        let ghash = gf.ghashFinish()
+        let tag = Array((ghash ^ eky0).bytes.prefix(tagLength))
+
+        // Notify handler
+        didCalculateTag?(tag)
+
+        switch mode {
+        case .combined:
+            return (ciphertext + tag).slice
+        case .detached:
+            return ciphertext
+        }
+    }
+
+    func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        counter = incrementCounter(counter)
+
+        // update ghash incrementally
+        gf.ghashUpdate(block: Array(ciphertext))
+
+        guard let ekN = cipherOperation(counter.bytes.slice) else {
+            return Array(ciphertext)
+        }
+
+        // ciphertext block ^ ek1
+        let plaintext = xor(ciphertext, ekN) as Array<UInt8>
+        return plaintext
+    }
+
+    // The authenticated decryption operation has five inputs: K, IV , C, A, and T. It has only a single
+    // output, either the plaintext value P or a special symbol FAIL that indicates that the inputs are not
+    // authentic.
+    @discardableResult
+    func willDecryptLast(bytes ciphertext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // Validate tag
+        switch mode {
+        case .combined:
+            // overwrite expectedTag property used later for verification
+            self.expectedTag = Array(ciphertext.suffix(tagLength))
+            return ciphertext[ciphertext.startIndex..<ciphertext.endIndex.advanced(by: -Swift.min(tagLength,ciphertext.count))]
+        case .detached:
+            return ciphertext
+        }
+    }
+
+    func didDecryptLast(bytes plaintext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // Calculate MAC tag.
+        let ghash = gf.ghashFinish()
+        let computedTag = Array((ghash ^ eky0).bytes.prefix(tagLength))
+
+        // Validate tag
+        guard let expectedTag = self.expectedTag, computedTag == expectedTag else {
+            throw GCM.Error.fail
+        }
+
+        return plaintext
+    }
+
+    func finalize(decrypt plaintext: ArraySlice<UInt8>) throws -> ArraySlice<UInt8> {
+        // do nothing
+        return plaintext
+    }
+}
+
+// MARK: - Local utils
+
+private func makeCounter(nonce: Array<UInt8>) -> UInt128 {
+    return UInt128(nonce + [0, 0, 0, 1])
+}
+
+// Successive counter values are generated using the function incr(), which treats the rightmost 32
+// bits of its argument as a nonnegative integer with the least significant bit on the right
+private func incrementCounter(_ counter: UInt128) -> UInt128 {
+    let b = counter.i.b + 1
+    let a = (b == 0 ? counter.i.a + 1 : counter.i.a)
+    return UInt128((a, b))
+}
+
+// If data is not a multiple of block size bytes long then the remainder is zero padded
+// Note: It's similar to ZeroPadding, but it's not the same.
+private func addPadding(_ bytes: Array<UInt8>, blockSize: Int) -> Array<UInt8> {
+    if bytes.isEmpty {
+        return Array<UInt8>(repeating: 0, count: blockSize)
+    }
+
+    let remainder = bytes.count % blockSize
+    if remainder == 0 {
+        return bytes
+    }
+
+    let paddingCount = blockSize - remainder
+    if paddingCount > 0 {
+        return bytes + Array<UInt8>(repeating: 0, count: paddingCount)
+    }
+    return bytes
+}
+
+// MARK: - GF
+
+/// The Field GF(2^128)
+private final class GF {
+    static let r = UInt128(a: 0xE100000000000000, b: 0)
+
+    let blockSize: Int
+    let h: UInt128
+
+    // AAD won't change
+    let aadLength: Int
+
+    // Updated for every consumed block
+    var ciphertextLength: Int
+
+    // Start with 0
+    var x: UInt128
+
+    init(aad: [UInt8], h: UInt128, blockSize: Int) {
+        self.blockSize = blockSize
+        aadLength = aad.count
+        ciphertextLength = 0
+        self.h = h
+        x = 0
+
+        // Calculate for AAD at the begining
+        x = GF.calculateX(aad: aad, x: x, h: h, blockSize: blockSize)
+    }
+
+    @discardableResult
+    func ghashUpdate(block ciphertextBlock: Array<UInt8>) -> UInt128 {
+        ciphertextLength += ciphertextBlock.count
+        x = GF.calculateX(block: addPadding(ciphertextBlock, blockSize: blockSize), x: x, h: h, blockSize: blockSize)
+        return x
+    }
+
+    func ghashFinish() -> UInt128 {
+        // len(A) || len(C)
+        let len = UInt128(a: UInt64(aadLength * 8), b: UInt64(ciphertextLength * 8))
+        x = GF.multiply((x ^ len), h)
+        return x
+    }
+
+    // GHASH. One-time calculation
+    static func ghash(x startx: UInt128 = 0, h: UInt128, aad: Array<UInt8>, ciphertext: Array<UInt8>, blockSize: Int) -> UInt128 {
+        var x = calculateX(aad: aad, x: startx, h: h, blockSize: blockSize)
+        x = calculateX(ciphertext: ciphertext, x: x, h: h, blockSize: blockSize)
+
+        // len(aad) || len(ciphertext)
+        let len = UInt128(a: UInt64(aad.count * 8), b: UInt64(ciphertext.count * 8))
+        x = multiply((x ^ len), h)
+
+        return x
+    }
+
+    // Calculate Ciphertext part, for all blocks
+    // Not used with incremental calculation.
+    private static func calculateX(ciphertext: [UInt8], x startx: UInt128, h: UInt128, blockSize: Int) -> UInt128 {
+        let pciphertext = addPadding(ciphertext, blockSize: blockSize)
+        let blocksCount = pciphertext.count / blockSize
+
+        var x = startx
+        for i in 0..<blocksCount {
+            let cpos = i * blockSize
+            let block = pciphertext[pciphertext.startIndex.advanced(by: cpos)..<pciphertext.startIndex.advanced(by: cpos + blockSize)]
+            x = calculateX(block: Array(block), x: x, h: h, blockSize: blockSize)
+        }
+        return x
+    }
+
+    // block is expected to be padded with addPadding
+    private static func calculateX(block ciphertextBlock: Array<UInt8>, x: UInt128, h: UInt128, blockSize: Int) -> UInt128 {
+        let k = x ^ UInt128(ciphertextBlock)
+        return multiply(k, h)
+    }
+
+    // Calculate AAD part, for all blocks
+    private static func calculateX(aad: [UInt8], x startx: UInt128, h: UInt128, blockSize: Int) -> UInt128 {
+        let paad = addPadding(aad, blockSize: blockSize)
+        let blocksCount = paad.count / blockSize
+
+        var x = startx
+        for i in 0..<blocksCount {
+            let apos = i * blockSize
+            let k = x ^ UInt128(paad[paad.startIndex.advanced(by: apos)..<paad.startIndex.advanced(by: apos + blockSize)])
+            x = multiply(k, h)
+        }
+
+        return x
+    }
+
+    // Multiplication GF(2^128).
+    private static func multiply(_ x: UInt128, _ y: UInt128) -> UInt128 {
+        var z: UInt128 = 0
+        var v = x
+        var k = UInt128(a: 1 << 63, b: 0)
+
+        for _ in 0..<128 {
+            if y & k == k {
+                z = z ^ v
+            }
+
+            if v & 1 != 1 {
+                v = v >> 1
+            } else {
+                v = (v >> 1) ^ r
+            }
+
+            k = k >> 1
+        }
+
+        return z
+    }
+}

+ 70 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/OFB.swift

@@ -0,0 +1,70 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+// Output Feedback (OFB)
+//
+
+public struct OFB: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .useEncryptToDecrypt]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return OFBModeWorker(blockSize: blockSize, iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
+struct OFBModeWorker: BlockModeWorker {
+    let cipherOperation: CipherOperationOnBlock
+    let blockSize: Int
+    let additionalBufferSize: Int = 0
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
+
+    init(blockSize: Int, iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.blockSize = blockSize
+        self.iv = iv
+        self.cipherOperation = cipherOperation
+    }
+
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let ciphertext = cipherOperation(prev ?? iv) else {
+            return Array(plaintext)
+        }
+        prev = ciphertext.slice
+        return xor(plaintext, ciphertext)
+    }
+
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let decrypted = cipherOperation(prev ?? iv) else {
+            return Array(ciphertext)
+        }
+        let plaintext: Array<UInt8> = xor(decrypted, ciphertext)
+        prev = decrypted.slice
+        return plaintext
+    }
+}

+ 70 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/BlockMode/PCBC.swift

@@ -0,0 +1,70 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  Propagating Cipher Block Chaining (PCBC)
+//
+
+public struct PCBC: BlockMode {
+    public enum Error: Swift.Error {
+        /// Invalid IV
+        case invalidInitializationVector
+    }
+
+    public let options: BlockModeOption = [.initializationVectorRequired, .paddingRequired]
+    private let iv: Array<UInt8>
+
+    public init(iv: Array<UInt8>) {
+        self.iv = iv
+    }
+
+    public func worker(blockSize: Int, cipherOperation: @escaping CipherOperationOnBlock) throws -> CipherModeWorker {
+        if iv.count != blockSize {
+            throw Error.invalidInitializationVector
+        }
+
+        return PCBCModeWorker(blockSize: blockSize, iv: iv.slice, cipherOperation: cipherOperation)
+    }
+}
+
+struct PCBCModeWorker: BlockModeWorker {
+    let cipherOperation: CipherOperationOnBlock
+    var blockSize: Int
+    let additionalBufferSize: Int = 0
+    private let iv: ArraySlice<UInt8>
+    private var prev: ArraySlice<UInt8>?
+
+    init(blockSize: Int, iv: ArraySlice<UInt8>, cipherOperation: @escaping CipherOperationOnBlock) {
+        self.blockSize = blockSize
+        self.iv = iv
+        self.cipherOperation = cipherOperation
+    }
+
+    mutating func encrypt(block plaintext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let ciphertext = cipherOperation(xor(prev ?? iv, plaintext)) else {
+            return Array(plaintext)
+        }
+        prev = xor(plaintext, ciphertext.slice)
+        return ciphertext
+    }
+
+    mutating func decrypt(block ciphertext: ArraySlice<UInt8>) -> Array<UInt8> {
+        guard let plaintext = cipherOperation(ciphertext) else {
+            return Array(ciphertext)
+        }
+        let result: Array<UInt8> = xor(prev ?? iv, plaintext)
+        prev = xor(plaintext.slice, ciphertext)
+        return result
+    }
+}

+ 537 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Blowfish.swift

@@ -0,0 +1,537 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  https://en.wikipedia.org/wiki/Blowfish_(cipher)
+//  Based on Paul Kocher implementation
+//
+
+public final class Blowfish {
+    public enum Error: Swift.Error {
+        /// Data padding is required
+        case dataPaddingRequired
+        /// Invalid key or IV
+        case invalidKeyOrInitializationVector
+        /// Invalid IV
+        case invalidInitializationVector
+        /// Invalid block mode
+        case invalidBlockMode
+    }
+
+    public static let blockSize: Int = 8 // 64 bit
+    public let keySize: Int
+
+    private let blockMode: BlockMode
+    private let padding: Padding
+    private var decryptWorker: CipherModeWorker!
+    private var encryptWorker: CipherModeWorker!
+
+    private let N = 16 // rounds
+    private var P: Array<UInt32>
+    private var S: Array<Array<UInt32>>
+    private let origP: Array<UInt32> = [
+        0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822,
+        0x299f31d0, 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377,
+        0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5,
+        0xb5470917, 0x9216d5d9, 0x8979fb1b,
+    ]
+
+    private let origS: Array<Array<UInt32>> = [
+        [
+            0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
+            0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
+            0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16,
+            0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e,
+            0x0d95748f, 0x728eb658, 0x718bcd58, 0x82154aee,
+            0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013,
+            0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef,
+            0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e,
+            0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60,
+            0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440,
+            0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce,
+            0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a,
+            0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e,
+            0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677,
+            0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193,
+            0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032,
+            0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88,
+            0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239,
+            0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e,
+            0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0,
+            0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3,
+            0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98,
+            0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88,
+            0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe,
+            0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6,
+            0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d,
+            0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b,
+            0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7,
+            0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x04c006ba,
+            0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463,
+            0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f,
+            0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09,
+            0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3,
+            0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb,
+            0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279,
+            0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8,
+            0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab,
+            0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82,
+            0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db,
+            0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573,
+            0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0,
+            0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b,
+            0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790,
+            0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8,
+            0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4,
+            0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0,
+            0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7,
+            0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c,
+            0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad,
+            0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1,
+            0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299,
+            0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9,
+            0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477,
+            0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf,
+            0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49,
+            0x00250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af,
+            0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa,
+            0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5,
+            0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41,
+            0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915,
+            0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
+            0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
+            0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
+            0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a,
+        ],
+        [
+            0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
+            0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
+            0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
+            0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e,
+            0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6,
+            0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1,
+            0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e,
+            0x09686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1,
+            0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737,
+            0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8,
+            0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x0200b3ff,
+            0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd,
+            0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701,
+            0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7,
+            0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41,
+            0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331,
+            0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf,
+            0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af,
+            0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e,
+            0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87,
+            0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c,
+            0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2,
+            0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16,
+            0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd,
+            0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b,
+            0x043556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509,
+            0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e,
+            0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3,
+            0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f,
+            0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a,
+            0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4,
+            0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960,
+            0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66,
+            0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28,
+            0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802,
+            0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84,
+            0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510,
+            0x13cca830, 0xeb61bd96, 0x0334fe1e, 0xaa0363cf,
+            0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14,
+            0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e,
+            0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50,
+            0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7,
+            0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8,
+            0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281,
+            0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99,
+            0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696,
+            0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128,
+            0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73,
+            0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0,
+            0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0,
+            0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105,
+            0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250,
+            0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3,
+            0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285,
+            0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00,
+            0x58428d2a, 0x0c55f5ea, 0x1dadf43e, 0x233f7061,
+            0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb,
+            0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e,
+            0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735,
+            0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc,
+            0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
+            0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
+            0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
+            0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7,
+        ],
+        [
+            0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
+            0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
+            0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
+            0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840,
+            0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45,
+            0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504,
+            0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a,
+            0x28507825, 0x530429f4, 0x0a2c86da, 0xe9b66dfb,
+            0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee,
+            0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6,
+            0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42,
+            0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b,
+            0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2,
+            0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb,
+            0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527,
+            0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b,
+            0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33,
+            0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c,
+            0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3,
+            0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc,
+            0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17,
+            0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564,
+            0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b,
+            0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115,
+            0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922,
+            0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728,
+            0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0,
+            0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e,
+            0x0a476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37,
+            0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d,
+            0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804,
+            0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b,
+            0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3,
+            0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb,
+            0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d,
+            0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c,
+            0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350,
+            0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9,
+            0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a,
+            0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe,
+            0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d,
+            0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc,
+            0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f,
+            0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61,
+            0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2,
+            0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9,
+            0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2,
+            0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c,
+            0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e,
+            0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633,
+            0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10,
+            0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169,
+            0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52,
+            0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027,
+            0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5,
+            0xf0177a28, 0xc0f586e0, 0x006058aa, 0x30dc7d62,
+            0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634,
+            0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76,
+            0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24,
+            0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc,
+            0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
+            0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
+            0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
+            0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0,
+        ],
+        [
+            0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
+            0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
+            0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
+            0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4,
+            0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8,
+            0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6,
+            0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304,
+            0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22,
+            0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4,
+            0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6,
+            0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9,
+            0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59,
+            0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593,
+            0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x022b8b51,
+            0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28,
+            0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c,
+            0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b,
+            0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28,
+            0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c,
+            0x15056dd4, 0x88f46dba, 0x03a16125, 0x0564f0bd,
+            0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a,
+            0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319,
+            0x7533d928, 0xb155fdf5, 0x03563482, 0x8aba3cbb,
+            0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f,
+            0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991,
+            0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32,
+            0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680,
+            0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166,
+            0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae,
+            0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb,
+            0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5,
+            0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47,
+            0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370,
+            0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d,
+            0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x0115af84,
+            0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048,
+            0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8,
+            0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd,
+            0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9,
+            0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7,
+            0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38,
+            0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f,
+            0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c,
+            0xbf97222c, 0x15e6fc2a, 0x0f91fc71, 0x9b941525,
+            0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1,
+            0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442,
+            0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964,
+            0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e,
+            0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8,
+            0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0x0fe3f11d,
+            0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f,
+            0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299,
+            0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02,
+            0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc,
+            0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614,
+            0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a,
+            0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6,
+            0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b,
+            0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0,
+            0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060,
+            0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
+            0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
+            0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
+            0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6,
+        ],
+    ]
+
+    public init(key: Array<UInt8>, blockMode: BlockMode = CBC(iv: Array<UInt8>(repeating: 0, count: Blowfish.blockSize)), padding: Padding) throws {
+        precondition(key.count >= 5 && key.count <= 56)
+
+        self.blockMode = blockMode
+        self.padding = padding
+        keySize = key.count
+
+        S = origS
+        P = origP
+
+        expandKey(key: key)
+        try setupBlockModeWorkers()
+    }
+
+    private func setupBlockModeWorkers() throws {
+        encryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
+
+        if blockMode.options.contains(.useEncryptToDecrypt) {
+            decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: encrypt)
+        } else {
+            decryptWorker = try blockMode.worker(blockSize: Blowfish.blockSize, cipherOperation: decrypt)
+        }
+    }
+
+    private func reset() {
+        S = origS
+        P = origP
+        // todo expand key
+    }
+
+    private func expandKey(key: Array<UInt8>) {
+        var j = 0
+        for i in 0..<(N + 2) {
+            var data: UInt32 = 0x0
+            for _ in 0..<4 {
+                data = (data << 8) | UInt32(key[j])
+                j += 1
+                if j >= key.count {
+                    j = 0
+                }
+            }
+            P[i] ^= data
+        }
+
+        var datal: UInt32 = 0
+        var datar: UInt32 = 0
+
+        for i in stride(from: 0, to: N + 2, by: 2) {
+            encryptBlowfishBlock(l: &datal, r: &datar)
+            P[i] = datal
+            P[i + 1] = datar
+        }
+
+        for i in 0..<4 {
+            for j in stride(from: 0, to: 256, by: 2) {
+                encryptBlowfishBlock(l: &datal, r: &datar)
+                S[i][j] = datal
+                S[i][j + 1] = datar
+            }
+        }
+    }
+
+    fileprivate func encrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
+        var result = Array<UInt8>()
+
+        var l = UInt32(bytes: block[block.startIndex..<block.startIndex.advanced(by: 4)])
+        var r = UInt32(bytes: block[block.startIndex.advanced(by: 4)..<block.startIndex.advanced(by: 8)])
+
+        encryptBlowfishBlock(l: &l, r: &r)
+
+        // because everything is too complex to be solved in reasonable time o_O
+        result += [
+            UInt8((l >> 24) & 0xff),
+            UInt8((l >> 16) & 0xff),
+        ]
+        result += [
+            UInt8((l >> 8) & 0xff),
+            UInt8((l >> 0) & 0xff),
+        ]
+        result += [
+            UInt8((r >> 24) & 0xff),
+            UInt8((r >> 16) & 0xff),
+        ]
+        result += [
+            UInt8((r >> 8) & 0xff),
+            UInt8((r >> 0) & 0xff),
+        ]
+
+        return result
+    }
+
+    fileprivate func decrypt(block: ArraySlice<UInt8>) -> Array<UInt8>? {
+        var result = Array<UInt8>()
+
+        var l = UInt32(bytes: block[block.startIndex..<block.startIndex.advanced(by: 4)])
+        var r = UInt32(bytes: block[block.startIndex.advanced(by: 4)..<block.startIndex.advanced(by: 8)])
+
+        decryptBlowfishBlock(l: &l, r: &r)
+
+        // because everything is too complex to be solved in reasonable time o_O
+        result += [
+            UInt8((l >> 24) & 0xff),
+            UInt8((l >> 16) & 0xff),
+        ]
+        result += [
+            UInt8((l >> 8) & 0xff),
+            UInt8((l >> 0) & 0xff),
+        ]
+        result += [
+            UInt8((r >> 24) & 0xff),
+            UInt8((r >> 16) & 0xff),
+        ]
+        result += [
+            UInt8((r >> 8) & 0xff),
+            UInt8((r >> 0) & 0xff),
+        ]
+        return result
+    }
+
+    /// Encrypts the 8-byte padded buffer
+    ///
+    /// - Parameters:
+    ///   - l: left half
+    ///   - r: right half
+    fileprivate func encryptBlowfishBlock(l: inout UInt32, r: inout UInt32) {
+        var Xl = l
+        var Xr = r
+
+        for i in 0..<N {
+            Xl = Xl ^ P[i]
+            Xr = F(x: Xl) ^ Xr
+
+            (Xl, Xr) = (Xr, Xl)
+        }
+
+        (Xl, Xr) = (Xr, Xl)
+
+        Xr = Xr ^ P[self.N]
+        Xl = Xl ^ P[self.N + 1]
+
+        l = Xl
+        r = Xr
+    }
+
+    /// Decrypts the 8-byte padded buffer
+    ///
+    /// - Parameters:
+    ///   - l: left half
+    ///   - r: right half
+    fileprivate func decryptBlowfishBlock(l: inout UInt32, r: inout UInt32) {
+        var Xl = l
+        var Xr = r
+
+        for i in (2...N + 1).reversed() {
+            Xl = Xl ^ P[i]
+            Xr = F(x: Xl) ^ Xr
+
+            (Xl, Xr) = (Xr, Xl)
+        }
+
+        (Xl, Xr) = (Xr, Xl)
+
+        Xr = Xr ^ P[1]
+        Xl = Xl ^ P[0]
+
+        l = Xl
+        r = Xr
+    }
+
+    private func F(x: UInt32) -> UInt32 {
+        let f1 = S[0][Int(x >> 24) & 0xff]
+        let f2 = S[1][Int(x >> 16) & 0xff]
+        let f3 = S[2][Int(x >> 8) & 0xff]
+        let f4 = S[3][Int(x & 0xff)]
+        return ((f1 &+ f2) ^ f3) &+ f4
+    }
+}
+
+extension Blowfish: Cipher {
+    /// Encrypt the 8-byte padded buffer, block by block. Note that for amounts of data larger than a block, it is not safe to just call encrypt() on successive blocks.
+    ///
+    /// - Parameter bytes: Plaintext data
+    /// - Returns: Encrypted data
+    public func encrypt<C: Collection>(_ bytes: C) throws -> Array<UInt8> where C.Element == UInt8, C.Index == Int {
+        let bytes = padding.add(to: Array(bytes), blockSize: Blowfish.blockSize) // FIXME: Array(bytes) copies
+
+        var out = Array<UInt8>()
+        out.reserveCapacity(bytes.count)
+
+        for chunk in bytes.batched(by: Blowfish.blockSize) {
+            out += encryptWorker.encrypt(block: chunk)
+        }
+
+        if blockMode.options.contains(.paddingRequired) && (out.count % Blowfish.blockSize != 0) {
+            throw Error.dataPaddingRequired
+        }
+
+        return out
+    }
+
+    /// Decrypt the 8-byte padded buffer
+    ///
+    /// - Parameter bytes: Ciphertext data
+    /// - Returns: Plaintext data
+    public func decrypt<C: Collection>(_ bytes: C) throws -> Array<UInt8> where C.Element == UInt8, C.Index == Int {
+        if blockMode.options.contains(.paddingRequired) && (bytes.count % Blowfish.blockSize != 0) {
+            throw Error.dataPaddingRequired
+        }
+
+        var out = Array<UInt8>()
+        out.reserveCapacity(bytes.count)
+
+        for chunk in Array(bytes).batched(by: Blowfish.blockSize) {
+            out += decryptWorker.decrypt(block: chunk) // FIXME: copying here is innefective
+        }
+
+        out = padding.remove(from: out, blockSize: Blowfish.blockSize)
+
+        return out
+    }
+}

+ 104 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/CBCMAC.swift

@@ -0,0 +1,104 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public class CBCMAC: Authenticator {
+    public enum Error: Swift.Error {
+        case wrongKeyLength
+    }
+
+    private let key: SecureBytes
+
+    private static let BlockSize: Int = 16
+    private static let Zero: Array<UInt8> = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+    private static let Rb: Array<UInt8> = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87]
+
+    public init(key: Array<UInt8>) throws {
+        if key.count != 16 {
+            throw Error.wrongKeyLength
+        }
+        self.key = SecureBytes(bytes: key)
+    }
+
+    // MARK: Authenticator
+
+    public func authenticate(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
+        let aes = try AES(key: Array(key), blockMode: CBC(iv: CBCMAC.Zero), padding: .noPadding)
+
+        let l = try aes.encrypt(CBCMAC.Zero)
+        var subKey1 = leftShiftOneBit(l)
+        if (l[0] & 0x80) != 0 {
+            subKey1 = xor(CBCMAC.Rb, subKey1)
+        }
+        var subKey2 = leftShiftOneBit(subKey1)
+        if (subKey1[0] & 0x80) != 0 {
+            subKey2 = xor(CBCMAC.Rb, subKey2)
+        }
+
+        let lastBlockComplete: Bool
+        let blockCount = (bytes.count + CBCMAC.BlockSize - 1) / CBCMAC.BlockSize
+        if blockCount == 0 {
+            lastBlockComplete = false
+        } else {
+            lastBlockComplete = bytes.count % CBCMAC.BlockSize == 0
+        }
+        var paddedBytes = bytes
+        if !lastBlockComplete {
+            bitPadding(to: &paddedBytes, blockSize: CBCMAC.BlockSize)
+        }
+
+        var blocks = Array(paddedBytes.batched(by: CBCMAC.BlockSize))
+        var lastBlock = blocks.popLast()!
+        if lastBlockComplete {
+            lastBlock = xor(lastBlock, subKey1)
+        } else {
+            lastBlock = xor(lastBlock, subKey2)
+        }
+
+        var x = Array<UInt8>(repeating: 0x00, count: CBCMAC.BlockSize)
+        var y = Array<UInt8>(repeating: 0x00, count: CBCMAC.BlockSize)
+        for block in blocks {
+            y = xor(block, x)
+            x = try aes.encrypt(y)
+        }
+        // the difference between CMAC and CBC-MAC is that CMAC xors the final block with a secret value
+        y = process(lastBlock: lastBlock, with: x)
+        return try aes.encrypt(y)
+    }
+
+    func process(lastBlock: ArraySlice<UInt8>, with x: [UInt8]) -> [UInt8] {
+        return Array(lastBlock)
+    }
+
+    // MARK: Helper methods
+
+    /**
+     Performs left shift by one bit to the bit string aquired after concatenating al bytes in the byte array
+     - parameters:
+     - bytes: byte array
+     - returns: bit shifted bit string split again in array of bytes
+     */
+    private func leftShiftOneBit(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        var shifted = Array<UInt8>(repeating: 0x00, count: bytes.count)
+        let last = bytes.count - 1
+        for index in 0..<last {
+            shifted[index] = bytes[index] << 1
+            if (bytes[index + 1] & 0x80) != 0 {
+                shifted[index] += 0x01
+            }
+        }
+        shifted[last] = bytes[last] << 1
+        return shifted
+    }
+}

+ 20 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/CMAC.swift

@@ -0,0 +1,20 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public final class CMAC: CBCMAC {
+    override func process(lastBlock: ArraySlice<UInt8>, with x: [UInt8]) -> [UInt8] {
+        return xor(lastBlock, x)
+    }
+}

+ 347 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/ChaCha20.swift

@@ -0,0 +1,347 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+//  https://tools.ietf.org/html/rfc7539
+//
+
+public final class ChaCha20: BlockCipher {
+    public enum Error: Swift.Error {
+        case invalidKeyOrInitializationVector
+        case notSupported
+    }
+
+    public static let blockSize = 64 // 512 / 8
+    public let keySize: Int
+
+    fileprivate let key: Key
+    fileprivate var counter: Array<UInt8>
+
+    public init(key: Array<UInt8>, iv nonce: Array<UInt8>) throws {
+        precondition(nonce.count == 12 || nonce.count == 8)
+
+        if key.count != 32 {
+            throw Error.invalidKeyOrInitializationVector
+        }
+
+        self.key = Key(bytes: key)
+        keySize = self.key.count
+
+        if nonce.count == 8 {
+            counter = [0, 0, 0, 0, 0, 0, 0, 0] + nonce
+        } else {
+            counter = [0, 0, 0, 0] + nonce
+        }
+
+        assert(counter.count == 16)
+    }
+
+    /// https://tools.ietf.org/html/rfc7539#section-2.3.
+    fileprivate func core(block: inout Array<UInt8>, counter: Array<UInt8>, key: Array<UInt8>) {
+        precondition(block.count == ChaCha20.blockSize)
+        precondition(counter.count == 16)
+        precondition(key.count == 32)
+
+        let j0: UInt32 = 0x61707865
+        let j1: UInt32 = 0x3320646e // 0x3620646e sigma/tau
+        let j2: UInt32 = 0x79622d32
+        let j3: UInt32 = 0x6b206574
+        let j4: UInt32 = UInt32(bytes: key[0..<4]).bigEndian
+        let j5: UInt32 = UInt32(bytes: key[4..<8]).bigEndian
+        let j6: UInt32 = UInt32(bytes: key[8..<12]).bigEndian
+        let j7: UInt32 = UInt32(bytes: key[12..<16]).bigEndian
+        let j8: UInt32 = UInt32(bytes: key[16..<20]).bigEndian
+        let j9: UInt32 = UInt32(bytes: key[20..<24]).bigEndian
+        let j10: UInt32 = UInt32(bytes: key[24..<28]).bigEndian
+        let j11: UInt32 = UInt32(bytes: key[28..<32]).bigEndian
+        let j12: UInt32 = UInt32(bytes: counter[0..<4]).bigEndian
+        let j13: UInt32 = UInt32(bytes: counter[4..<8]).bigEndian
+        let j14: UInt32 = UInt32(bytes: counter[8..<12]).bigEndian
+        let j15: UInt32 = UInt32(bytes: counter[12..<16]).bigEndian
+
+        var (x0, x1, x2, x3, x4, x5, x6, x7) = (j0, j1, j2, j3, j4, j5, j6, j7)
+        var (x8, x9, x10, x11, x12, x13, x14, x15) = (j8, j9, j10, j11, j12, j13, j14, j15)
+
+        for _ in 0..<10 { // 20 rounds
+            x0 = x0 &+ x4
+            x12 ^= x0
+            x12 = (x12 << 16) | (x12 >> 16)
+            x8 = x8 &+ x12
+            x4 ^= x8
+            x4 = (x4 << 12) | (x4 >> 20)
+            x0 = x0 &+ x4
+            x12 ^= x0
+            x12 = (x12 << 8) | (x12 >> 24)
+            x8 = x8 &+ x12
+            x4 ^= x8
+            x4 = (x4 << 7) | (x4 >> 25)
+            x1 = x1 &+ x5
+            x13 ^= x1
+            x13 = (x13 << 16) | (x13 >> 16)
+            x9 = x9 &+ x13
+            x5 ^= x9
+            x5 = (x5 << 12) | (x5 >> 20)
+            x1 = x1 &+ x5
+            x13 ^= x1
+            x13 = (x13 << 8) | (x13 >> 24)
+            x9 = x9 &+ x13
+            x5 ^= x9
+            x5 = (x5 << 7) | (x5 >> 25)
+            x2 = x2 &+ x6
+            x14 ^= x2
+            x14 = (x14 << 16) | (x14 >> 16)
+            x10 = x10 &+ x14
+            x6 ^= x10
+            x6 = (x6 << 12) | (x6 >> 20)
+            x2 = x2 &+ x6
+            x14 ^= x2
+            x14 = (x14 << 8) | (x14 >> 24)
+            x10 = x10 &+ x14
+            x6 ^= x10
+            x6 = (x6 << 7) | (x6 >> 25)
+            x3 = x3 &+ x7
+            x15 ^= x3
+            x15 = (x15 << 16) | (x15 >> 16)
+            x11 = x11 &+ x15
+            x7 ^= x11
+            x7 = (x7 << 12) | (x7 >> 20)
+            x3 = x3 &+ x7
+            x15 ^= x3
+            x15 = (x15 << 8) | (x15 >> 24)
+            x11 = x11 &+ x15
+            x7 ^= x11
+            x7 = (x7 << 7) | (x7 >> 25)
+            x0 = x0 &+ x5
+            x15 ^= x0
+            x15 = (x15 << 16) | (x15 >> 16)
+            x10 = x10 &+ x15
+            x5 ^= x10
+            x5 = (x5 << 12) | (x5 >> 20)
+            x0 = x0 &+ x5
+            x15 ^= x0
+            x15 = (x15 << 8) | (x15 >> 24)
+            x10 = x10 &+ x15
+            x5 ^= x10
+            x5 = (x5 << 7) | (x5 >> 25)
+            x1 = x1 &+ x6
+            x12 ^= x1
+            x12 = (x12 << 16) | (x12 >> 16)
+            x11 = x11 &+ x12
+            x6 ^= x11
+            x6 = (x6 << 12) | (x6 >> 20)
+            x1 = x1 &+ x6
+            x12 ^= x1
+            x12 = (x12 << 8) | (x12 >> 24)
+            x11 = x11 &+ x12
+            x6 ^= x11
+            x6 = (x6 << 7) | (x6 >> 25)
+            x2 = x2 &+ x7
+            x13 ^= x2
+            x13 = (x13 << 16) | (x13 >> 16)
+            x8 = x8 &+ x13
+            x7 ^= x8
+            x7 = (x7 << 12) | (x7 >> 20)
+            x2 = x2 &+ x7
+            x13 ^= x2
+            x13 = (x13 << 8) | (x13 >> 24)
+            x8 = x8 &+ x13
+            x7 ^= x8
+            x7 = (x7 << 7) | (x7 >> 25)
+            x3 = x3 &+ x4
+            x14 ^= x3
+            x14 = (x14 << 16) | (x14 >> 16)
+            x9 = x9 &+ x14
+            x4 ^= x9
+            x4 = (x4 << 12) | (x4 >> 20)
+            x3 = x3 &+ x4
+            x14 ^= x3
+            x14 = (x14 << 8) | (x14 >> 24)
+            x9 = x9 &+ x14
+            x4 ^= x9
+            x4 = (x4 << 7) | (x4 >> 25)
+        }
+
+        x0 = x0 &+ j0
+        x1 = x1 &+ j1
+        x2 = x2 &+ j2
+        x3 = x3 &+ j3
+        x4 = x4 &+ j4
+        x5 = x5 &+ j5
+        x6 = x6 &+ j6
+        x7 = x7 &+ j7
+        x8 = x8 &+ j8
+        x9 = x9 &+ j9
+        x10 = x10 &+ j10
+        x11 = x11 &+ j11
+        x12 = x12 &+ j12
+        x13 = x13 &+ j13
+        x14 = x14 &+ j14
+        x15 = x15 &+ j15
+
+        block.replaceSubrange(0..<4, with: x0.bigEndian.bytes())
+        block.replaceSubrange(4..<8, with: x1.bigEndian.bytes())
+        block.replaceSubrange(8..<12, with: x2.bigEndian.bytes())
+        block.replaceSubrange(12..<16, with: x3.bigEndian.bytes())
+        block.replaceSubrange(16..<20, with: x4.bigEndian.bytes())
+        block.replaceSubrange(20..<24, with: x5.bigEndian.bytes())
+        block.replaceSubrange(24..<28, with: x6.bigEndian.bytes())
+        block.replaceSubrange(28..<32, with: x7.bigEndian.bytes())
+        block.replaceSubrange(32..<36, with: x8.bigEndian.bytes())
+        block.replaceSubrange(36..<40, with: x9.bigEndian.bytes())
+        block.replaceSubrange(40..<44, with: x10.bigEndian.bytes())
+        block.replaceSubrange(44..<48, with: x11.bigEndian.bytes())
+        block.replaceSubrange(48..<52, with: x12.bigEndian.bytes())
+        block.replaceSubrange(52..<56, with: x13.bigEndian.bytes())
+        block.replaceSubrange(56..<60, with: x14.bigEndian.bytes())
+        block.replaceSubrange(60..<64, with: x15.bigEndian.bytes())
+    }
+
+    // XORKeyStream
+    func process(bytes: ArraySlice<UInt8>, counter: inout Array<UInt8>, key: Array<UInt8>) -> Array<UInt8> {
+        precondition(counter.count == 16)
+        precondition(key.count == 32)
+
+        var block = Array<UInt8>(repeating: 0, count: ChaCha20.blockSize)
+        var bytesSlice = bytes
+        var out = Array<UInt8>(reserveCapacity: bytesSlice.count)
+
+        while bytesSlice.count >= ChaCha20.blockSize {
+            core(block: &block, counter: counter, key: key)
+            for (i, x) in block.enumerated() {
+                out.append(bytesSlice[bytesSlice.startIndex + i] ^ x)
+            }
+            var u: UInt32 = 1
+            for i in 0..<4 {
+                u += UInt32(counter[i])
+                counter[i] = UInt8(u & 0xff)
+                u >>= 8
+            }
+            bytesSlice = bytesSlice[bytesSlice.startIndex + ChaCha20.blockSize..<bytesSlice.endIndex]
+        }
+
+        if bytesSlice.count > 0 {
+            core(block: &block, counter: counter, key: key)
+            for (i, v) in bytesSlice.enumerated() {
+                out.append(v ^ block[i])
+            }
+        }
+        return out
+    }
+}
+
+// MARK: Cipher
+
+extension ChaCha20: Cipher {
+    public func encrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
+        return process(bytes: bytes, counter: &counter, key: Array(key))
+    }
+
+    public func decrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8> {
+        return try encrypt(bytes)
+    }
+}
+
+// MARK: Encryptor
+
+extension ChaCha20 {
+    public struct ChaChaEncryptor: Cryptor, Updatable {
+        private var accumulated = Array<UInt8>()
+        private let chacha: ChaCha20
+
+        init(chacha: ChaCha20) {
+            self.chacha = chacha
+        }
+
+        public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = false) throws -> Array<UInt8> {
+            accumulated += bytes
+
+            var encrypted = Array<UInt8>()
+            encrypted.reserveCapacity(accumulated.count)
+            for chunk in accumulated.batched(by: ChaCha20.blockSize) {
+                if isLast || accumulated.count >= ChaCha20.blockSize {
+                    encrypted += try chacha.encrypt(chunk)
+                    accumulated.removeFirst(chunk.count) // TODO: improve performance
+                }
+            }
+            return encrypted
+        }
+
+        public func seek(to: Int) throws {
+            throw Error.notSupported
+        }
+    }
+}
+
+// MARK: Decryptor
+
+extension ChaCha20 {
+    public struct ChaChaDecryptor: Cryptor, Updatable {
+        private var accumulated = Array<UInt8>()
+
+        private var offset: Int = 0
+        private var offsetToRemove: Int = 0
+        private let chacha: ChaCha20
+
+        init(chacha: ChaCha20) {
+            self.chacha = chacha
+        }
+
+        public mutating func update(withBytes bytes: ArraySlice<UInt8>, isLast: Bool = true) throws -> Array<UInt8> {
+            // prepend "offset" number of bytes at the beginning
+            if offset > 0 {
+                accumulated += Array<UInt8>(repeating: 0, count: offset) + bytes
+                offsetToRemove = offset
+                offset = 0
+            } else {
+                accumulated += bytes
+            }
+
+            var plaintext = Array<UInt8>()
+            plaintext.reserveCapacity(accumulated.count)
+            for chunk in accumulated.batched(by: ChaCha20.blockSize) {
+                if isLast || accumulated.count >= ChaCha20.blockSize {
+                    plaintext += try chacha.decrypt(chunk)
+
+                    // remove "offset" from the beginning of first chunk
+                    if offsetToRemove > 0 {
+                        plaintext.removeFirst(offsetToRemove) // TODO: improve performance
+                        offsetToRemove = 0
+                    }
+
+                    accumulated.removeFirst(chunk.count)
+                }
+            }
+
+            return plaintext
+        }
+
+        public func seek(to: Int) throws {
+            throw Error.notSupported
+        }
+    }
+}
+
+// MARK: Cryptors
+
+extension ChaCha20: Cryptors {
+    //TODO: Use BlockEncryptor/BlockDecryptor
+    
+    public func makeEncryptor() -> Cryptor & Updatable {
+        return ChaCha20.ChaChaEncryptor(chacha: self)
+    }
+
+    public func makeDecryptor() -> Cryptor & Updatable {
+        return ChaCha20.ChaChaDecryptor(chacha: self)
+    }
+}

+ 193 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Checksum.swift

@@ -0,0 +1,193 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+/// CRC - cyclic redundancy check code.
+public final class Checksum {
+    private static let table32: Array<UInt32> = [
+        0x0000_0000, 0x7707_3096, 0xEE0E_612C, 0x9909_51BA, 0x076D_C419, 0x706A_F48F, 0xE963_A535, 0x9E64_95A3,
+        0x0EDB_8832, 0x79DC_B8A4, 0xE0D5_E91E, 0x97D2_D988, 0x09B6_4C2B, 0x7EB1_7CBD, 0xE7B8_2D07, 0x90BF_1D91,
+        0x1DB7_1064, 0x6AB0_20F2, 0xF3B9_7148, 0x84BE_41DE, 0x1ADA_D47D, 0x6DDD_E4EB, 0xF4D4_B551, 0x83D3_85C7,
+        0x136C_9856, 0x646B_A8C0, 0xFD62_F97A, 0x8A65_C9EC, 0x1401_5C4F, 0x6306_6CD9, 0xFA0F_3D63, 0x8D08_0DF5,
+        0x3B6E_20C8, 0x4C69_105E, 0xD560_41E4, 0xA267_7172, 0x3C03_E4D1, 0x4B04_D447, 0xD20D_85FD, 0xA50A_B56B,
+        0x35B5_A8FA, 0x42B2_986C, 0xDBBB_C9D6, 0xACBC_F940, 0x32D8_6CE3, 0x45DF_5C75, 0xDCD6_0DCF, 0xABD1_3D59,
+        0x26D9_30AC, 0x51DE_003A, 0xC8D7_5180, 0xBFD0_6116, 0x21B4_F4B5, 0x56B3_C423, 0xCFBA_9599, 0xB8BD_A50F,
+        0x2802_B89E, 0x5F05_8808, 0xC60C_D9B2, 0xB10B_E924, 0x2F6F_7C87, 0x5868_4C11, 0xC161_1DAB, 0xB666_2D3D,
+        0x76DC_4190, 0x01DB_7106, 0x98D2_20BC, 0xEFD5_102A, 0x71B1_8589, 0x06B6_B51F, 0x9FBF_E4A5, 0xE8B8_D433,
+        0x7807_C9A2, 0x0F00_F934, 0x9609_A88E, 0xE10E_9818, 0x7F6A_0DBB, 0x086D_3D2D, 0x9164_6C97, 0xE663_5C01,
+        0x6B6B_51F4, 0x1C6C_6162, 0x8565_30D8, 0xF262_004E, 0x6C06_95ED, 0x1B01_A57B, 0x8208_F4C1, 0xF50F_C457,
+        0x65B0_D9C6, 0x12B7_E950, 0x8BBE_B8EA, 0xFCB9_887C, 0x62DD_1DDF, 0x15DA_2D49, 0x8CD3_7CF3, 0xFBD4_4C65,
+        0x4DB2_6158, 0x3AB5_51CE, 0xA3BC_0074, 0xD4BB_30E2, 0x4ADF_A541, 0x3DD8_95D7, 0xA4D1_C46D, 0xD3D6_F4FB,
+        0x4369_E96A, 0x346E_D9FC, 0xAD67_8846, 0xDA60_B8D0, 0x4404_2D73, 0x3303_1DE5, 0xAA0A_4C5F, 0xDD0D_7CC9,
+        0x5005_713C, 0x2702_41AA, 0xBE0B_1010, 0xC90C_2086, 0x5768_B525, 0x206F_85B3, 0xB966_D409, 0xCE61_E49F,
+        0x5EDE_F90E, 0x29D9_C998, 0xB0D0_9822, 0xC7D7_A8B4, 0x59B3_3D17, 0x2EB4_0D81, 0xB7BD_5C3B, 0xC0BA_6CAD,
+        0xEDB8_8320, 0x9ABF_B3B6, 0x03B6_E20C, 0x74B1_D29A, 0xEAD5_4739, 0x9DD2_77AF, 0x04DB_2615, 0x73DC_1683,
+        0xE363_0B12, 0x9464_3B84, 0x0D6D_6A3E, 0x7A6A_5AA8, 0xE40E_CF0B, 0x9309_FF9D, 0x0A00_AE27, 0x7D07_9EB1,
+        0xF00F_9344, 0x8708_A3D2, 0x1E01_F268, 0x6906_C2FE, 0xF762_575D, 0x8065_67CB, 0x196C_3671, 0x6E6B_06E7,
+        0xFED4_1B76, 0x89D3_2BE0, 0x10DA_7A5A, 0x67DD_4ACC, 0xF9B9_DF6F, 0x8EBE_EFF9, 0x17B7_BE43, 0x60B0_8ED5,
+        0xD6D6_A3E8, 0xA1D1_937E, 0x38D8_C2C4, 0x4FDF_F252, 0xD1BB_67F1, 0xA6BC_5767, 0x3FB5_06DD, 0x48B2_364B,
+        0xD80D_2BDA, 0xAF0A_1B4C, 0x3603_4AF6, 0x4104_7A60, 0xDF60_EFC3, 0xA867_DF55, 0x316E_8EEF, 0x4669_BE79,
+        0xCB61_B38C, 0xBC66_831A, 0x256F_D2A0, 0x5268_E236, 0xCC0C_7795, 0xBB0B_4703, 0x2202_16B9, 0x5505_262F,
+        0xC5BA_3BBE, 0xB2BD_0B28, 0x2BB4_5A92, 0x5CB3_6A04, 0xC2D7_FFA7, 0xB5D0_CF31, 0x2CD9_9E8B, 0x5BDE_AE1D,
+        0x9B64_C2B0, 0xEC63_F226, 0x756A_A39C, 0x026D_930A, 0x9C09_06A9, 0xEB0E_363F, 0x7207_6785, 0x0500_5713,
+        0x95BF_4A82, 0xE2B8_7A14, 0x7BB1_2BAE, 0x0CB6_1B38, 0x92D2_8E9B, 0xE5D5_BE0D, 0x7CDC_EFB7, 0x0BDB_DF21,
+        0x86D3_D2D4, 0xF1D4_E242, 0x68DD_B3F8, 0x1FDA_836E, 0x81BE_16CD, 0xF6B9_265B, 0x6FB0_77E1, 0x18B7_4777,
+        0x8808_5AE6, 0xFF0F_6A70, 0x6606_3BCA, 0x1101_0B5C, 0x8F65_9EFF, 0xF862_AE69, 0x616B_FFD3, 0x166C_CF45,
+        0xA00A_E278, 0xD70D_D2EE, 0x4E04_8354, 0x3903_B3C2, 0xA767_2661, 0xD060_16F7, 0x4969_474D, 0x3E6E_77DB,
+        0xAED1_6A4A, 0xD9D6_5ADC, 0x40DF_0B66, 0x37D8_3BF0, 0xA9BC_AE53, 0xDEBB_9EC5, 0x47B2_CF7F, 0x30B5_FFE9,
+        0xBDBD_F21C, 0xCABA_C28A, 0x53B3_9330, 0x24B4_A3A6, 0xBAD0_3605, 0xCDD7_0693, 0x54DE_5729, 0x23D9_67BF,
+        0xB366_7A2E, 0xC461_4AB8, 0x5D68_1B02, 0x2A6F_2B94, 0xB40B_BE37, 0xC30C_8EA1, 0x5A05_DF1B, 0x2D02_EF8D,
+    ]
+
+    private static let table32c: Array<UInt32> = [
+        0x0000_0000, 0xF26B_8303, 0xE13B_70F7, 0x1350_F3F4, 0xC79A_971F, 0x35F1_141C, 0x26A1_E7E8, 0xD4CA_64EB,
+        0x8AD9_58CF, 0x78B2_DBCC, 0x6BE2_2838, 0x9989_AB3B, 0x4D43_CFD0, 0xBF28_4CD3, 0xAC78_BF27, 0x5E13_3C24,
+        0x105E_C76F, 0xE235_446C, 0xF165_B798, 0x030E_349B, 0xD7C4_5070, 0x25AF_D373, 0x36FF_2087, 0xC494_A384,
+        0x9A87_9FA0, 0x68EC_1CA3, 0x7BBC_EF57, 0x89D7_6C54, 0x5D1D_08BF, 0xAF76_8BBC, 0xBC26_7848, 0x4E4D_FB4B,
+        0x20BD_8EDE, 0xD2D6_0DDD, 0xC186_FE29, 0x33ED_7D2A, 0xE727_19C1, 0x154C_9AC2, 0x061C_6936, 0xF477_EA35,
+        0xAA64_D611, 0x580F_5512, 0x4B5F_A6E6, 0xB934_25E5, 0x6DFE_410E, 0x9F95_C20D, 0x8CC5_31F9, 0x7EAE_B2FA,
+        0x30E3_49B1, 0xC288_CAB2, 0xD1D8_3946, 0x23B3_BA45, 0xF779_DEAE, 0x0512_5DAD, 0x1642_AE59, 0xE429_2D5A,
+        0xBA3A_117E, 0x4851_927D, 0x5B01_6189, 0xA96A_E28A, 0x7DA0_8661, 0x8FCB_0562, 0x9C9B_F696, 0x6EF0_7595,
+        0x417B_1DBC, 0xB310_9EBF, 0xA040_6D4B, 0x522B_EE48, 0x86E1_8AA3, 0x748A_09A0, 0x67DA_FA54, 0x95B1_7957,
+        0xCBA2_4573, 0x39C9_C670, 0x2A99_3584, 0xD8F2_B687, 0x0C38_D26C, 0xFE53_516F, 0xED03_A29B, 0x1F68_2198,
+        0x5125_DAD3, 0xA34E_59D0, 0xB01E_AA24, 0x4275_2927, 0x96BF_4DCC, 0x64D4_CECF, 0x7784_3D3B, 0x85EF_BE38,
+        0xDBFC_821C, 0x2997_011F, 0x3AC7_F2EB, 0xC8AC_71E8, 0x1C66_1503, 0xEE0D_9600, 0xFD5D_65F4, 0x0F36_E6F7,
+        0x61C6_9362, 0x93AD_1061, 0x80FD_E395, 0x7296_6096, 0xA65C_047D, 0x5437_877E, 0x4767_748A, 0xB50C_F789,
+        0xEB1F_CBAD, 0x1974_48AE, 0x0A24_BB5A, 0xF84F_3859, 0x2C85_5CB2, 0xDEEE_DFB1, 0xCDBE_2C45, 0x3FD5_AF46,
+        0x7198_540D, 0x83F3_D70E, 0x90A3_24FA, 0x62C8_A7F9, 0xB602_C312, 0x4469_4011, 0x5739_B3E5, 0xA552_30E6,
+        0xFB41_0CC2, 0x092A_8FC1, 0x1A7A_7C35, 0xE811_FF36, 0x3CDB_9BDD, 0xCEB0_18DE, 0xDDE0_EB2A, 0x2F8B_6829,
+        0x82F6_3B78, 0x709D_B87B, 0x63CD_4B8F, 0x91A6_C88C, 0x456C_AC67, 0xB707_2F64, 0xA457_DC90, 0x563C_5F93,
+        0x082F_63B7, 0xFA44_E0B4, 0xE914_1340, 0x1B7F_9043, 0xCFB5_F4A8, 0x3DDE_77AB, 0x2E8E_845F, 0xDCE5_075C,
+        0x92A8_FC17, 0x60C3_7F14, 0x7393_8CE0, 0x81F8_0FE3, 0x5532_6B08, 0xA759_E80B, 0xB409_1BFF, 0x4662_98FC,
+        0x1871_A4D8, 0xEA1A_27DB, 0xF94A_D42F, 0x0B21_572C, 0xDFEB_33C7, 0x2D80_B0C4, 0x3ED0_4330, 0xCCBB_C033,
+        0xA24B_B5A6, 0x5020_36A5, 0x4370_C551, 0xB11B_4652, 0x65D1_22B9, 0x97BA_A1BA, 0x84EA_524E, 0x7681_D14D,
+        0x2892_ED69, 0xDAF9_6E6A, 0xC9A9_9D9E, 0x3BC2_1E9D, 0xEF08_7A76, 0x1D63_F975, 0x0E33_0A81, 0xFC58_8982,
+        0xB215_72C9, 0x407E_F1CA, 0x532E_023E, 0xA145_813D, 0x758F_E5D6, 0x87E4_66D5, 0x94B4_9521, 0x66DF_1622,
+        0x38CC_2A06, 0xCAA7_A905, 0xD9F7_5AF1, 0x2B9C_D9F2, 0xFF56_BD19, 0x0D3D_3E1A, 0x1E6D_CDEE, 0xEC06_4EED,
+        0xC38D_26C4, 0x31E6_A5C7, 0x22B6_5633, 0xD0DD_D530, 0x0417_B1DB, 0xF67C_32D8, 0xE52C_C12C, 0x1747_422F,
+        0x4954_7E0B, 0xBB3F_FD08, 0xA86F_0EFC, 0x5A04_8DFF, 0x8ECE_E914, 0x7CA5_6A17, 0x6FF5_99E3, 0x9D9E_1AE0,
+        0xD3D3_E1AB, 0x21B8_62A8, 0x32E8_915C, 0xC083_125F, 0x1449_76B4, 0xE622_F5B7, 0xF572_0643, 0x0719_8540,
+        0x590A_B964, 0xAB61_3A67, 0xB831_C993, 0x4A5A_4A90, 0x9E90_2E7B, 0x6CFB_AD78, 0x7FAB_5E8C, 0x8DC0_DD8F,
+        0xE330_A81A, 0x115B_2B19, 0x020B_D8ED, 0xF060_5BEE, 0x24AA_3F05, 0xD6C1_BC06, 0xC591_4FF2, 0x37FA_CCF1,
+        0x69E9_F0D5, 0x9B82_73D6, 0x88D2_8022, 0x7AB9_0321, 0xAE73_67CA, 0x5C18_E4C9, 0x4F48_173D, 0xBD23_943E,
+        0xF36E_6F75, 0x0105_EC76, 0x1255_1F82, 0xE03E_9C81, 0x34F4_F86A, 0xC69F_7B69, 0xD5CF_889D, 0x27A4_0B9E,
+        0x79B7_37BA, 0x8BDC_B4B9, 0x988C_474D, 0x6AE7_C44E, 0xBE2D_A0A5, 0x4C46_23A6, 0x5F16_D052, 0xAD7D_5351,
+    ]
+
+    private static let table16: Array<UInt16> = [
+        0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+        0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+        0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+        0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+        0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+        0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+        0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+        0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+        0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+        0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+        0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+        0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+        0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+        0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+        0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+        0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+        0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+        0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+        0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+        0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+        0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+        0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+        0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+        0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+        0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+        0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+        0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+        0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+        0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+        0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+        0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+        0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
+    ]
+
+    /// Polynomial: 0xEDB88320 (Reversed) - IEEE
+    func crc32(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
+        var crc: UInt32 = seed != nil ? seed! : 0xFFFF_FFFF
+        for chunk in message.batched(by: 256) {
+            for b in chunk {
+                let idx = Int((crc ^ UInt32(reflect ? b : reversed(b))) & 0xFF)
+                crc = (crc >> 8) ^ Checksum.table32[idx]
+            }
+        }
+        return (reflect ? crc : reversed(crc)) ^ 0xFFFF_FFFF
+    }
+
+    /// Polynomial: 0x82F63B78 (Reversed) - Castagnoli
+    func crc32c(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
+        var crc: UInt32 = seed != nil ? seed! : 0xFFFF_FFFF
+        for chunk in message.batched(by: 256) {
+            for b in chunk {
+                let idx = Int((crc ^ UInt32(reflect ? b : reversed(b))) & 0xFF)
+                crc = (crc >> 8) ^ Checksum.table32c[idx]
+            }
+        }
+        return (reflect ? crc : reversed(crc)) ^ 0xFFFF_FFFF
+    }
+
+    /// Polynomial: 0xA001 (Reversed) - IBM
+    func crc16(_ message: Array<UInt8>, seed: UInt16? = nil) -> UInt16 {
+        var crc: UInt16 = seed != nil ? seed! : 0x0000
+        for chunk in message.batched(by: 256) {
+            for b in chunk {
+                crc = (crc >> 8) ^ Checksum.table16[Int((crc ^ UInt16(b)) & 0xFF)]
+            }
+        }
+        return crc
+    }
+}
+
+// MARK: Public interface
+
+public extension Checksum {
+    /// Calculate CRC32.
+    ///
+    /// - parameter message: Message
+    /// - parameter seed:    Seed value (Optional)
+    /// - parameter reflect: is reflect (default true)
+    ///
+    /// - returns: Calculated code
+    static func crc32(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
+        return Checksum().crc32(message, seed: seed, reflect: reflect)
+    }
+
+    /// Calculate CRC32C
+    ///
+    /// - parameter message: Message
+    /// - parameter seed:    Seed value (Optional)
+    /// - parameter reflect: is reflect (default true)
+    ///
+    /// - returns: Calculated code
+    static func crc32c(_ message: Array<UInt8>, seed: UInt32? = nil, reflect: Bool = true) -> UInt32 {
+        return Checksum().crc32c(message, seed: seed, reflect: reflect)
+    }
+
+    /// Calculate CRC16
+    ///
+    /// - parameter message: Message
+    /// - parameter seed:    Seed value (Optional)
+    ///
+    /// - returns: Calculated code
+    static func crc16(_ message: Array<UInt8>, seed: UInt16? = nil) -> UInt16 {
+        return Checksum().crc16(message, seed: seed)
+    }
+}

+ 47 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Cipher.swift

@@ -0,0 +1,47 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+public enum CipherError: Error {
+    case encrypt
+    case decrypt
+}
+
+public protocol Cipher: class {
+    var keySize: Int { get }
+
+    /// Encrypt given bytes at once
+    ///
+    /// - parameter bytes: Plaintext data
+    /// - returns: Encrypted data
+    func encrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8>
+    func encrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8>
+
+    /// Decrypt given bytes at once
+    ///
+    /// - parameter bytes: Ciphertext data
+    /// - returns: Plaintext data
+    func decrypt(_ bytes: ArraySlice<UInt8>) throws -> Array<UInt8>
+    func decrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8>
+}
+
+extension Cipher {
+    public func encrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
+        return try encrypt(bytes.slice)
+    }
+
+    public func decrypt(_ bytes: Array<UInt8>) throws -> Array<UInt8> {
+        return try decrypt(bytes.slice)
+    }
+}

+ 45 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Collection+Extension.swift

@@ -0,0 +1,45 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+extension Collection where Self.Element == UInt8, Self.Index == Int {
+    // Big endian order
+    func toUInt32Array() -> Array<UInt32> {
+        if isEmpty {
+            return []
+        }
+
+        var result = Array<UInt32>(reserveCapacity: 16)
+        for idx in stride(from: startIndex, to: endIndex, by: 4) {
+            let val = UInt32(bytes: self, fromIndex: idx).bigEndian
+            result.append(val)
+        }
+
+        return result
+    }
+
+    // Big endian order
+    func toUInt64Array() -> Array<UInt64> {
+        if isEmpty {
+            return []
+        }
+
+        var result = Array<UInt64>(reserveCapacity: 32)
+        for idx in stride(from: startIndex, to: endIndex, by: 8) {
+            let val = UInt64(bytes: self, fromIndex: idx).bigEndian
+            result.append(val)
+        }
+
+        return result
+    }
+}

+ 23 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/CompactMap.swift

@@ -0,0 +1,23 @@
+////  CryptoSwift
+//
+//  Copyright (C) 2014-2018 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+#if swift(>=4.1)
+    // TODO: remove this file when Xcode 9.2 is no longer used
+#else
+    extension Sequence {
+        public func compactMap<ElementOfResult>(_ transform: (Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult] {
+            return try flatMap(transform)
+        }
+    }
+#endif

+ 22 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Cryptor.swift

@@ -0,0 +1,22 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+/// Cryptor (Encryptor or Decryptor)
+public protocol Cryptor {
+    /// Seek to position in file, if block mode allows random access.
+    ///
+    /// - parameter to: new value of counter
+    mutating func seek(to: Int) throws
+}

+ 44 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Cryptors.swift

@@ -0,0 +1,44 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+#if canImport(Darwin)
+import Darwin
+#else
+import Glibc
+#endif
+
+/// Worker cryptor/decryptor of `Updatable` types
+public protocol Cryptors: class {
+
+    /// Cryptor suitable for encryption
+    func makeEncryptor() throws -> Cryptor & Updatable
+
+    /// Cryptor suitable for decryption
+    func makeDecryptor() throws -> Cryptor & Updatable
+
+    /// Generate array of random bytes. Helper function.
+    static func randomIV(_ blockSize: Int) -> Array<UInt8>
+}
+
+extension Cryptors {
+    public static func randomIV(_ blockSize: Int) -> Array<UInt8> {
+        var randomIV: Array<UInt8> = Array<UInt8>()
+        randomIV.reserveCapacity(blockSize)
+        for randomByte in RandomBytesSequence(size: blockSize) {
+            randomIV.append(randomByte)
+        }
+        return randomIV
+    }
+}

+ 78 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Digest.swift

@@ -0,0 +1,78 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+@available(*, renamed: "Digest")
+public typealias Hash = Digest
+
+/// Hash functions to calculate Digest.
+public struct Digest {
+    /// Calculate MD5 Digest
+    /// - parameter bytes: input message
+    /// - returns: Digest bytes
+    public static func md5(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        return MD5().calculate(for: bytes)
+    }
+
+    /// Calculate SHA1 Digest
+    /// - parameter bytes: input message
+    /// - returns: Digest bytes
+    public static func sha1(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        return SHA1().calculate(for: bytes)
+    }
+
+    /// Calculate SHA2-224 Digest
+    /// - parameter bytes: input message
+    /// - returns: Digest bytes
+    public static func sha224(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        return sha2(bytes, variant: .sha224)
+    }
+
+    /// Calculate SHA2-256 Digest
+    /// - parameter bytes: input message
+    /// - returns: Digest bytes
+    public static func sha256(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        return sha2(bytes, variant: .sha256)
+    }
+
+    /// Calculate SHA2-384 Digest
+    /// - parameter bytes: input message
+    /// - returns: Digest bytes
+    public static func sha384(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        return sha2(bytes, variant: .sha384)
+    }
+
+    /// Calculate SHA2-512 Digest
+    /// - parameter bytes: input message
+    /// - returns: Digest bytes
+    public static func sha512(_ bytes: Array<UInt8>) -> Array<UInt8> {
+        return sha2(bytes, variant: .sha512)
+    }
+
+    /// Calculate SHA2 Digest
+    /// - parameter bytes: input message
+    /// - parameter variant: SHA-2 variant
+    /// - returns: Digest bytes
+    public static func sha2(_ bytes: Array<UInt8>, variant: SHA2.Variant) -> Array<UInt8> {
+        return SHA2(variant: variant).calculate(for: bytes)
+    }
+
+    /// Calculate SHA3 Digest
+    /// - parameter bytes: input message
+    /// - parameter variant: SHA-3 variant
+    /// - returns: Digest bytes
+    public static func sha3(_ bytes: Array<UInt8>, variant: SHA3.Variant) -> Array<UInt8> {
+        return SHA3(variant: variant).calculate(for: bytes)
+    }
+}

+ 18 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/DigestType.swift

@@ -0,0 +1,18 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+internal protocol DigestType {
+    func calculate(for bytes: Array<UInt8>) -> Array<UInt8>
+}

+ 23 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/AES+Foundation.swift

@@ -0,0 +1,23 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+import Foundation
+
+extension AES {
+    /// Initialize with CBC block mode.
+    public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws {
+        try self.init(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: padding)
+    }
+}

+ 32 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Array+Foundation.swift

@@ -0,0 +1,32 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+import Foundation
+
+public extension Array where Element == UInt8 {
+    func toBase64() -> String? {
+        return Data( self).base64EncodedString()
+    }
+
+    init(base64: String) {
+        self.init()
+
+        guard let decodedData = Data(base64Encoded: base64) else {
+            return
+        }
+
+        append(contentsOf: decodedData.bytes)
+    }
+}

+ 23 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/Blowfish+Foundation.swift

@@ -0,0 +1,23 @@
+//
+//  CryptoSwift
+//
+//  Copyright (C) 2014-2017 Marcin Krzyżanowski <marcin@krzyzanowskim.com>
+//  This software is provided 'as-is', without any express or implied warranty.
+//
+//  In no event will the authors be held liable for any damages arising from the use of this software.
+//
+//  Permission is granted to anyone to use this software for any purpose,including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
+//
+//  - The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation is required.
+//  - Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
+//  - This notice may not be removed or altered from any source or binary distribution.
+//
+
+import Foundation
+
+extension Blowfish {
+    /// Initialize with CBC block mode.
+    public convenience init(key: String, iv: String, padding: Padding = .pkcs7) throws {
+        try self.init(key: key.bytes, blockMode: CBC(iv: iv.bytes), padding: padding)
+    }
+}

+ 0 - 0
RainbowPlanet/Pods/CryptoSwift/Sources/CryptoSwift/Foundation/ChaCha20+Foundation.swift


이 변경점에서 너무 많은 파일들이 변경되어 몇몇 파일들은 표시되지 않았습니다.