PageRenderTime 35ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/Pods/AFNetworking/AFNetworking/AFURLRequestSerialization.m

https://gitlab.com/lisit1003/test
Objective C | 1272 lines | 965 code | 280 blank | 27 comment | 120 complexity | efc782cad77b193c134db0af0c321be0 MD5 | raw file
  1. // AFSerialization.h
  2. //
  3. // Copyright (c) 2013-2014 AFNetworking (http://afnetworking.com)
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. #import "AFURLRequestSerialization.h"
  23. #if __IPHONE_OS_VERSION_MIN_REQUIRED
  24. #import <MobileCoreServices/MobileCoreServices.h>
  25. #else
  26. #import <CoreServices/CoreServices.h>
  27. #endif
  28. extern NSString * const AFNetworkingErrorDomain;
  29. typedef NSString * (^AFQueryStringSerializationBlock)(NSURLRequest *request, NSDictionary *parameters, NSError *__autoreleasing *error);
  30. static NSString * AFBase64EncodedStringFromString(NSString *string) {
  31. NSData *data = [NSData dataWithBytes:[string UTF8String] length:[string lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];
  32. NSUInteger length = [data length];
  33. NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
  34. uint8_t *input = (uint8_t *)[data bytes];
  35. uint8_t *output = (uint8_t *)[mutableData mutableBytes];
  36. for (NSUInteger i = 0; i < length; i += 3) {
  37. NSUInteger value = 0;
  38. for (NSUInteger j = i; j < (i + 3); j++) {
  39. value <<= 8;
  40. if (j < length) {
  41. value |= (0xFF & input[j]);
  42. }
  43. }
  44. static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  45. NSUInteger idx = (i / 3) * 4;
  46. output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F];
  47. output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F];
  48. output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '=';
  49. output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '=';
  50. }
  51. return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding];
  52. }
  53. static NSString * const kAFCharactersToBeEscapedInQueryString = @":/?&=;+!@#$()',*";
  54. static NSString * AFPercentEscapedQueryStringKeyFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
  55. static NSString * const kAFCharactersToLeaveUnescapedInQueryStringPairKey = @"[].";
  56. return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescapedInQueryStringPairKey, (__bridge CFStringRef)kAFCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
  57. }
  58. static NSString * AFPercentEscapedQueryStringValueFromStringWithEncoding(NSString *string, NSStringEncoding encoding) {
  59. return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, NULL, (__bridge CFStringRef)kAFCharactersToBeEscapedInQueryString, CFStringConvertNSStringEncodingToEncoding(encoding));
  60. }
  61. #pragma mark -
  62. @interface AFQueryStringPair : NSObject
  63. @property (readwrite, nonatomic, strong) id field;
  64. @property (readwrite, nonatomic, strong) id value;
  65. - (id)initWithField:(id)field value:(id)value;
  66. - (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding;
  67. @end
  68. @implementation AFQueryStringPair
  69. - (id)initWithField:(id)field value:(id)value {
  70. self = [super init];
  71. if (!self) {
  72. return nil;
  73. }
  74. self.field = field;
  75. self.value = value;
  76. return self;
  77. }
  78. - (NSString *)URLEncodedStringValueWithEncoding:(NSStringEncoding)stringEncoding {
  79. if (!self.value || [self.value isEqual:[NSNull null]]) {
  80. return AFPercentEscapedQueryStringKeyFromStringWithEncoding([self.field description], stringEncoding);
  81. } else {
  82. return [NSString stringWithFormat:@"%@=%@", AFPercentEscapedQueryStringKeyFromStringWithEncoding([self.field description], stringEncoding), AFPercentEscapedQueryStringValueFromStringWithEncoding([self.value description], stringEncoding)];
  83. }
  84. }
  85. @end
  86. #pragma mark -
  87. extern NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary);
  88. extern NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value);
  89. static NSString * AFQueryStringFromParametersWithEncoding(NSDictionary *parameters, NSStringEncoding stringEncoding) {
  90. NSMutableArray *mutablePairs = [NSMutableArray array];
  91. for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
  92. [mutablePairs addObject:[pair URLEncodedStringValueWithEncoding:stringEncoding]];
  93. }
  94. return [mutablePairs componentsJoinedByString:@"&"];
  95. }
  96. NSArray * AFQueryStringPairsFromDictionary(NSDictionary *dictionary) {
  97. return AFQueryStringPairsFromKeyAndValue(nil, dictionary);
  98. }
  99. NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
  100. NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
  101. NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
  102. if ([value isKindOfClass:[NSDictionary class]]) {
  103. NSDictionary *dictionary = value;
  104. // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
  105. for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
  106. id nestedValue = [dictionary objectForKey:nestedKey];
  107. if (nestedValue) {
  108. [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
  109. }
  110. }
  111. } else if ([value isKindOfClass:[NSArray class]]) {
  112. NSArray *array = value;
  113. for (id nestedValue in array) {
  114. [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
  115. }
  116. } else if ([value isKindOfClass:[NSSet class]]) {
  117. NSSet *set = value;
  118. for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
  119. [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
  120. }
  121. } else {
  122. [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
  123. }
  124. return mutableQueryStringComponents;
  125. }
  126. #pragma mark -
  127. @interface AFStreamingMultipartFormData : NSObject <AFMultipartFormData>
  128. - (instancetype)initWithURLRequest:(NSMutableURLRequest *)urlRequest
  129. stringEncoding:(NSStringEncoding)encoding;
  130. - (NSMutableURLRequest *)requestByFinalizingMultipartFormData;
  131. @end
  132. #pragma mark -
  133. @interface AFHTTPRequestSerializer ()
  134. @property (readwrite, nonatomic, strong) NSMutableDictionary *mutableHTTPRequestHeaders;
  135. @property (readwrite, nonatomic, assign) AFHTTPRequestQueryStringSerializationStyle queryStringSerializationStyle;
  136. @property (readwrite, nonatomic, copy) AFQueryStringSerializationBlock queryStringSerialization;
  137. @end
  138. @implementation AFHTTPRequestSerializer
  139. + (instancetype)serializer {
  140. return [[self alloc] init];
  141. }
  142. - (instancetype)init {
  143. self = [super init];
  144. if (!self) {
  145. return nil;
  146. }
  147. self.stringEncoding = NSUTF8StringEncoding;
  148. self.allowsCellularAccess = YES;
  149. self.cachePolicy = NSURLRequestUseProtocolCachePolicy;
  150. self.HTTPShouldHandleCookies = YES;
  151. self.HTTPShouldUsePipelining = NO;
  152. self.networkServiceType = NSURLNetworkServiceTypeDefault;
  153. self.timeoutInterval = 60;
  154. self.mutableHTTPRequestHeaders = [NSMutableDictionary dictionary];
  155. // Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
  156. NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
  157. [[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
  158. float q = 1.0f - (idx * 0.1f);
  159. [acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
  160. *stop = q <= 0.5f;
  161. }];
  162. [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];
  163. NSString *userAgent = nil;
  164. #pragma clang diagnostic push
  165. #pragma clang diagnostic ignored "-Wgnu"
  166. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  167. // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43
  168. userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], (__bridge id)CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), kCFBundleVersionKey) ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
  169. #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
  170. userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleExecutableKey] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleIdentifierKey], [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"] ?: [[[NSBundle mainBundle] infoDictionary] objectForKey:(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]];
  171. #endif
  172. #pragma clang diagnostic pop
  173. if (userAgent) {
  174. if (![userAgent canBeConvertedToEncoding:NSASCIIStringEncoding]) {
  175. NSMutableString *mutableUserAgent = [userAgent mutableCopy];
  176. if (CFStringTransform((__bridge CFMutableStringRef)(mutableUserAgent), NULL, (__bridge CFStringRef)@"Any-Latin; Latin-ASCII; [:^ASCII:] Remove", false)) {
  177. userAgent = mutableUserAgent;
  178. }
  179. }
  180. [self setValue:userAgent forHTTPHeaderField:@"User-Agent"];
  181. }
  182. // HTTP Method Definitions; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
  183. self.HTTPMethodsEncodingParametersInURI = [NSSet setWithObjects:@"GET", @"HEAD", @"DELETE", nil];
  184. return self;
  185. }
  186. #pragma mark -
  187. - (NSDictionary *)HTTPRequestHeaders {
  188. return [NSDictionary dictionaryWithDictionary:self.mutableHTTPRequestHeaders];
  189. }
  190. - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
  191. [self.mutableHTTPRequestHeaders setValue:value forKey:field];
  192. }
  193. - (void)setAuthorizationHeaderFieldWithUsername:(NSString *)username password:(NSString *)password {
  194. NSString *basicAuthCredentials = [NSString stringWithFormat:@"%@:%@", username, password];
  195. [self setValue:[NSString stringWithFormat:@"Basic %@", AFBase64EncodedStringFromString(basicAuthCredentials)] forHTTPHeaderField:@"Authorization"];
  196. }
  197. - (void)setAuthorizationHeaderFieldWithToken:(NSString *)token {
  198. [self setValue:[NSString stringWithFormat:@"Token token=\"%@\"", token] forHTTPHeaderField:@"Authorization"];
  199. }
  200. - (void)clearAuthorizationHeader {
  201. [self.mutableHTTPRequestHeaders removeObjectForKey:@"Authorization"];
  202. }
  203. #pragma mark -
  204. - (void)setQueryStringSerializationWithStyle:(AFHTTPRequestQueryStringSerializationStyle)style {
  205. self.queryStringSerializationStyle = style;
  206. self.queryStringSerialization = nil;
  207. }
  208. - (void)setQueryStringSerializationWithBlock:(NSString *(^)(NSURLRequest *, NSDictionary *, NSError *__autoreleasing *))block {
  209. self.queryStringSerialization = block;
  210. }
  211. #pragma mark -
  212. - (NSMutableURLRequest *)requestWithMethod:(NSString *)method
  213. URLString:(NSString *)URLString
  214. parameters:(id)parameters
  215. {
  216. return [self requestWithMethod:method URLString:URLString parameters:parameters error:nil];
  217. }
  218. - (NSMutableURLRequest *)requestWithMethod:(NSString *)method
  219. URLString:(NSString *)URLString
  220. parameters:(id)parameters
  221. error:(NSError *__autoreleasing *)error
  222. {
  223. NSParameterAssert(method);
  224. NSParameterAssert(URLString);
  225. NSURL *url = [NSURL URLWithString:URLString];
  226. NSParameterAssert(url);
  227. NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
  228. mutableRequest.HTTPMethod = method;
  229. mutableRequest.allowsCellularAccess = self.allowsCellularAccess;
  230. mutableRequest.cachePolicy = self.cachePolicy;
  231. mutableRequest.HTTPShouldHandleCookies = self.HTTPShouldHandleCookies;
  232. mutableRequest.HTTPShouldUsePipelining = self.HTTPShouldUsePipelining;
  233. mutableRequest.networkServiceType = self.networkServiceType;
  234. mutableRequest.timeoutInterval = self.timeoutInterval;
  235. mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];
  236. return mutableRequest;
  237. }
  238. - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
  239. URLString:(NSString *)URLString
  240. parameters:(NSDictionary *)parameters
  241. constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
  242. {
  243. return [self multipartFormRequestWithMethod:method URLString:URLString parameters:parameters constructingBodyWithBlock:block error:nil];
  244. }
  245. - (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method
  246. URLString:(NSString *)URLString
  247. parameters:(NSDictionary *)parameters
  248. constructingBodyWithBlock:(void (^)(id <AFMultipartFormData> formData))block
  249. error:(NSError *__autoreleasing *)error
  250. {
  251. NSParameterAssert(method);
  252. NSParameterAssert(![method isEqualToString:@"GET"] && ![method isEqualToString:@"HEAD"]);
  253. NSMutableURLRequest *mutableRequest = [self requestWithMethod:method URLString:URLString parameters:nil error:error];
  254. __block AFStreamingMultipartFormData *formData = [[AFStreamingMultipartFormData alloc] initWithURLRequest:mutableRequest stringEncoding:NSUTF8StringEncoding];
  255. if (parameters) {
  256. for (AFQueryStringPair *pair in AFQueryStringPairsFromDictionary(parameters)) {
  257. NSData *data = nil;
  258. if ([pair.value isKindOfClass:[NSData class]]) {
  259. data = pair.value;
  260. } else if ([pair.value isEqual:[NSNull null]]) {
  261. data = [NSData data];
  262. } else {
  263. data = [[pair.value description] dataUsingEncoding:self.stringEncoding];
  264. }
  265. if (data) {
  266. [formData appendPartWithFormData:data name:[pair.field description]];
  267. }
  268. }
  269. }
  270. if (block) {
  271. block(formData);
  272. }
  273. return [formData requestByFinalizingMultipartFormData];
  274. }
  275. - (NSMutableURLRequest *)requestWithMultipartFormRequest:(NSURLRequest *)request
  276. writingStreamContentsToFile:(NSURL *)fileURL
  277. completionHandler:(void (^)(NSError *error))handler
  278. {
  279. if (!request.HTTPBodyStream) {
  280. return [request mutableCopy];
  281. }
  282. NSParameterAssert([fileURL isFileURL]);
  283. NSInputStream *inputStream = request.HTTPBodyStream;
  284. NSOutputStream *outputStream = [[NSOutputStream alloc] initWithURL:fileURL append:NO];
  285. __block NSError *error = nil;
  286. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  287. [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  288. [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  289. [inputStream open];
  290. [outputStream open];
  291. while ([inputStream hasBytesAvailable] && [outputStream hasSpaceAvailable]) {
  292. uint8_t buffer[1024];
  293. NSInteger bytesRead = [inputStream read:buffer maxLength:1024];
  294. if (inputStream.streamError || bytesRead < 0) {
  295. error = inputStream.streamError;
  296. break;
  297. }
  298. NSInteger bytesWritten = [outputStream write:buffer maxLength:(NSUInteger)bytesRead];
  299. if (outputStream.streamError || bytesWritten < 0) {
  300. error = outputStream.streamError;
  301. break;
  302. }
  303. if (bytesRead == 0 && bytesWritten == 0) {
  304. break;
  305. }
  306. }
  307. [outputStream close];
  308. [inputStream close];
  309. if (handler) {
  310. dispatch_async(dispatch_get_main_queue(), ^{
  311. handler(error);
  312. });
  313. }
  314. });
  315. NSMutableURLRequest *mutableRequest = [request mutableCopy];
  316. mutableRequest.HTTPBodyStream = nil;
  317. return mutableRequest;
  318. }
  319. #pragma mark - AFURLRequestSerialization
  320. - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
  321. withParameters:(id)parameters
  322. error:(NSError *__autoreleasing *)error
  323. {
  324. NSParameterAssert(request);
  325. NSMutableURLRequest *mutableRequest = [request mutableCopy];
  326. [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
  327. if (![request valueForHTTPHeaderField:field]) {
  328. [mutableRequest setValue:value forHTTPHeaderField:field];
  329. }
  330. }];
  331. if (parameters) {
  332. NSString *query = nil;
  333. if (self.queryStringSerialization) {
  334. query = self.queryStringSerialization(request, parameters, error);
  335. } else {
  336. switch (self.queryStringSerializationStyle) {
  337. case AFHTTPRequestQueryStringDefaultStyle:
  338. query = AFQueryStringFromParametersWithEncoding(parameters, self.stringEncoding);
  339. break;
  340. }
  341. }
  342. if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
  343. mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
  344. } else {
  345. if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
  346. NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(self.stringEncoding));
  347. [mutableRequest setValue:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
  348. }
  349. [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
  350. }
  351. }
  352. return mutableRequest;
  353. }
  354. #pragma mark - NSecureCoding
  355. + (BOOL)supportsSecureCoding {
  356. return YES;
  357. }
  358. - (id)initWithCoder:(NSCoder *)decoder {
  359. self = [self init];
  360. if (!self) {
  361. return nil;
  362. }
  363. self.mutableHTTPRequestHeaders = [[decoder decodeObjectOfClass:[NSDictionary class] forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))] mutableCopy];
  364. self.queryStringSerializationStyle = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))] unsignedIntegerValue];
  365. return self;
  366. }
  367. - (void)encodeWithCoder:(NSCoder *)coder {
  368. [coder encodeObject:self.mutableHTTPRequestHeaders forKey:NSStringFromSelector(@selector(mutableHTTPRequestHeaders))];
  369. [coder encodeInteger:self.queryStringSerializationStyle forKey:NSStringFromSelector(@selector(queryStringSerializationStyle))];
  370. }
  371. #pragma mark - NSCopying
  372. - (id)copyWithZone:(NSZone *)zone {
  373. AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
  374. serializer.mutableHTTPRequestHeaders = [self.mutableHTTPRequestHeaders mutableCopyWithZone:zone];
  375. serializer.queryStringSerializationStyle = self.queryStringSerializationStyle;
  376. serializer.queryStringSerialization = self.queryStringSerialization;
  377. return serializer;
  378. }
  379. @end
  380. #pragma mark -
  381. static NSString * AFCreateMultipartFormBoundary() {
  382. return [NSString stringWithFormat:@"Boundary+%08X%08X", arc4random(), arc4random()];
  383. }
  384. static NSString * const kAFMultipartFormCRLF = @"\r\n";
  385. static inline NSString * AFMultipartFormInitialBoundary(NSString *boundary) {
  386. return [NSString stringWithFormat:@"--%@%@", boundary, kAFMultipartFormCRLF];
  387. }
  388. static inline NSString * AFMultipartFormEncapsulationBoundary(NSString *boundary) {
  389. return [NSString stringWithFormat:@"%@--%@%@", kAFMultipartFormCRLF, boundary, kAFMultipartFormCRLF];
  390. }
  391. static inline NSString * AFMultipartFormFinalBoundary(NSString *boundary) {
  392. return [NSString stringWithFormat:@"%@--%@--%@", kAFMultipartFormCRLF, boundary, kAFMultipartFormCRLF];
  393. }
  394. static inline NSString * AFContentTypeForPathExtension(NSString *extension) {
  395. #ifdef __UTTYPE__
  396. NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL);
  397. NSString *contentType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
  398. if (!contentType) {
  399. return @"application/octet-stream";
  400. } else {
  401. return contentType;
  402. }
  403. #else
  404. #pragma unused (extension)
  405. return @"application/octet-stream";
  406. #endif
  407. }
  408. NSUInteger const kAFUploadStream3GSuggestedPacketSize = 1024 * 16;
  409. NSTimeInterval const kAFUploadStream3GSuggestedDelay = 0.2;
  410. @interface AFHTTPBodyPart : NSObject
  411. @property (nonatomic, assign) NSStringEncoding stringEncoding;
  412. @property (nonatomic, strong) NSDictionary *headers;
  413. @property (nonatomic, copy) NSString *boundary;
  414. @property (nonatomic, strong) id body;
  415. @property (nonatomic, assign) unsigned long long bodyContentLength;
  416. @property (nonatomic, strong) NSInputStream *inputStream;
  417. @property (nonatomic, assign) BOOL hasInitialBoundary;
  418. @property (nonatomic, assign) BOOL hasFinalBoundary;
  419. @property (readonly, nonatomic, assign, getter = hasBytesAvailable) BOOL bytesAvailable;
  420. @property (readonly, nonatomic, assign) unsigned long long contentLength;
  421. - (NSInteger)read:(uint8_t *)buffer
  422. maxLength:(NSUInteger)length;
  423. @end
  424. @interface AFMultipartBodyStream : NSInputStream <NSStreamDelegate>
  425. @property (nonatomic, assign) NSUInteger numberOfBytesInPacket;
  426. @property (nonatomic, assign) NSTimeInterval delay;
  427. @property (nonatomic, strong) NSInputStream *inputStream;
  428. @property (readonly, nonatomic, assign) unsigned long long contentLength;
  429. @property (readonly, nonatomic, assign, getter = isEmpty) BOOL empty;
  430. - (id)initWithStringEncoding:(NSStringEncoding)encoding;
  431. - (void)setInitialAndFinalBoundaries;
  432. - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart;
  433. @end
  434. #pragma mark -
  435. @interface AFStreamingMultipartFormData ()
  436. @property (readwrite, nonatomic, copy) NSMutableURLRequest *request;
  437. @property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
  438. @property (readwrite, nonatomic, copy) NSString *boundary;
  439. @property (readwrite, nonatomic, strong) AFMultipartBodyStream *bodyStream;
  440. @end
  441. @implementation AFStreamingMultipartFormData
  442. - (id)initWithURLRequest:(NSMutableURLRequest *)urlRequest
  443. stringEncoding:(NSStringEncoding)encoding
  444. {
  445. self = [super init];
  446. if (!self) {
  447. return nil;
  448. }
  449. self.request = urlRequest;
  450. self.stringEncoding = encoding;
  451. self.boundary = AFCreateMultipartFormBoundary();
  452. self.bodyStream = [[AFMultipartBodyStream alloc] initWithStringEncoding:encoding];
  453. return self;
  454. }
  455. - (BOOL)appendPartWithFileURL:(NSURL *)fileURL
  456. name:(NSString *)name
  457. error:(NSError * __autoreleasing *)error
  458. {
  459. NSParameterAssert(fileURL);
  460. NSParameterAssert(name);
  461. NSString *fileName = [fileURL lastPathComponent];
  462. NSString *mimeType = AFContentTypeForPathExtension([fileURL pathExtension]);
  463. return [self appendPartWithFileURL:fileURL name:name fileName:fileName mimeType:mimeType error:error];
  464. }
  465. - (BOOL)appendPartWithFileURL:(NSURL *)fileURL
  466. name:(NSString *)name
  467. fileName:(NSString *)fileName
  468. mimeType:(NSString *)mimeType
  469. error:(NSError * __autoreleasing *)error
  470. {
  471. NSParameterAssert(fileURL);
  472. NSParameterAssert(name);
  473. NSParameterAssert(fileName);
  474. NSParameterAssert(mimeType);
  475. if (![fileURL isFileURL]) {
  476. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Expected URL to be a file URL", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
  477. if (error) {
  478. *error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
  479. }
  480. return NO;
  481. } else if ([fileURL checkResourceIsReachableAndReturnError:error] == NO) {
  482. NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"File URL not reachable.", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey];
  483. if (error) {
  484. *error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadURL userInfo:userInfo];
  485. }
  486. return NO;
  487. }
  488. NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:[fileURL path] error:error];
  489. if (!fileAttributes) {
  490. return NO;
  491. }
  492. NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
  493. [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
  494. [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
  495. AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
  496. bodyPart.stringEncoding = self.stringEncoding;
  497. bodyPart.headers = mutableHeaders;
  498. bodyPart.boundary = self.boundary;
  499. bodyPart.body = fileURL;
  500. bodyPart.bodyContentLength = [[fileAttributes objectForKey:NSFileSize] unsignedLongLongValue];
  501. [self.bodyStream appendHTTPBodyPart:bodyPart];
  502. return YES;
  503. }
  504. - (void)appendPartWithInputStream:(NSInputStream *)inputStream
  505. name:(NSString *)name
  506. fileName:(NSString *)fileName
  507. length:(int64_t)length
  508. mimeType:(NSString *)mimeType
  509. {
  510. NSParameterAssert(name);
  511. NSParameterAssert(fileName);
  512. NSParameterAssert(mimeType);
  513. NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
  514. [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
  515. [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
  516. AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
  517. bodyPart.stringEncoding = self.stringEncoding;
  518. bodyPart.headers = mutableHeaders;
  519. bodyPart.boundary = self.boundary;
  520. bodyPart.body = inputStream;
  521. bodyPart.bodyContentLength = (unsigned long long)length;
  522. [self.bodyStream appendHTTPBodyPart:bodyPart];
  523. }
  524. - (void)appendPartWithFileData:(NSData *)data
  525. name:(NSString *)name
  526. fileName:(NSString *)fileName
  527. mimeType:(NSString *)mimeType
  528. {
  529. NSParameterAssert(name);
  530. NSParameterAssert(fileName);
  531. NSParameterAssert(mimeType);
  532. NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
  533. [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"; filename=\"%@\"", name, fileName] forKey:@"Content-Disposition"];
  534. [mutableHeaders setValue:mimeType forKey:@"Content-Type"];
  535. [self appendPartWithHeaders:mutableHeaders body:data];
  536. }
  537. - (void)appendPartWithFormData:(NSData *)data
  538. name:(NSString *)name
  539. {
  540. NSParameterAssert(name);
  541. NSMutableDictionary *mutableHeaders = [NSMutableDictionary dictionary];
  542. [mutableHeaders setValue:[NSString stringWithFormat:@"form-data; name=\"%@\"", name] forKey:@"Content-Disposition"];
  543. [self appendPartWithHeaders:mutableHeaders body:data];
  544. }
  545. - (void)appendPartWithHeaders:(NSDictionary *)headers
  546. body:(NSData *)body
  547. {
  548. NSParameterAssert(body);
  549. AFHTTPBodyPart *bodyPart = [[AFHTTPBodyPart alloc] init];
  550. bodyPart.stringEncoding = self.stringEncoding;
  551. bodyPart.headers = headers;
  552. bodyPart.boundary = self.boundary;
  553. bodyPart.bodyContentLength = [body length];
  554. bodyPart.body = body;
  555. [self.bodyStream appendHTTPBodyPart:bodyPart];
  556. }
  557. - (void)throttleBandwidthWithPacketSize:(NSUInteger)numberOfBytes
  558. delay:(NSTimeInterval)delay
  559. {
  560. self.bodyStream.numberOfBytesInPacket = numberOfBytes;
  561. self.bodyStream.delay = delay;
  562. }
  563. - (NSMutableURLRequest *)requestByFinalizingMultipartFormData {
  564. if ([self.bodyStream isEmpty]) {
  565. return self.request;
  566. }
  567. // Reset the initial and final boundaries to ensure correct Content-Length
  568. [self.bodyStream setInitialAndFinalBoundaries];
  569. [self.request setHTTPBodyStream:self.bodyStream];
  570. [self.request setValue:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", self.boundary] forHTTPHeaderField:@"Content-Type"];
  571. [self.request setValue:[NSString stringWithFormat:@"%llu", [self.bodyStream contentLength]] forHTTPHeaderField:@"Content-Length"];
  572. return self.request;
  573. }
  574. @end
  575. #pragma mark -
  576. @interface AFMultipartBodyStream () <NSCopying>
  577. @property (readwrite, nonatomic, assign) NSStreamStatus streamStatus;
  578. @property (readwrite, nonatomic, strong) NSError *streamError;
  579. @property (readwrite, nonatomic, assign) NSStringEncoding stringEncoding;
  580. @property (readwrite, nonatomic, strong) NSMutableArray *HTTPBodyParts;
  581. @property (readwrite, nonatomic, strong) NSEnumerator *HTTPBodyPartEnumerator;
  582. @property (readwrite, nonatomic, strong) AFHTTPBodyPart *currentHTTPBodyPart;
  583. @property (readwrite, nonatomic, strong) NSOutputStream *outputStream;
  584. @property (readwrite, nonatomic, strong) NSMutableData *buffer;
  585. @end
  586. @implementation AFMultipartBodyStream
  587. - (id)initWithStringEncoding:(NSStringEncoding)encoding {
  588. self = [super init];
  589. if (!self) {
  590. return nil;
  591. }
  592. self.stringEncoding = encoding;
  593. self.HTTPBodyParts = [NSMutableArray array];
  594. self.numberOfBytesInPacket = NSIntegerMax;
  595. return self;
  596. }
  597. - (void)setInitialAndFinalBoundaries {
  598. if ([self.HTTPBodyParts count] > 0) {
  599. for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
  600. bodyPart.hasInitialBoundary = NO;
  601. bodyPart.hasFinalBoundary = NO;
  602. }
  603. [[self.HTTPBodyParts objectAtIndex:0] setHasInitialBoundary:YES];
  604. [[self.HTTPBodyParts lastObject] setHasFinalBoundary:YES];
  605. }
  606. }
  607. - (void)appendHTTPBodyPart:(AFHTTPBodyPart *)bodyPart {
  608. [self.HTTPBodyParts addObject:bodyPart];
  609. }
  610. - (BOOL)isEmpty {
  611. return [self.HTTPBodyParts count] == 0;
  612. }
  613. #pragma mark - NSInputStream
  614. - (NSInteger)read:(uint8_t *)buffer
  615. maxLength:(NSUInteger)length
  616. {
  617. if ([self streamStatus] == NSStreamStatusClosed) {
  618. return 0;
  619. }
  620. NSInteger totalNumberOfBytesRead = 0;
  621. #pragma clang diagnostic push
  622. #pragma clang diagnostic ignored "-Wgnu"
  623. while ((NSUInteger)totalNumberOfBytesRead < MIN(length, self.numberOfBytesInPacket)) {
  624. if (!self.currentHTTPBodyPart || ![self.currentHTTPBodyPart hasBytesAvailable]) {
  625. if (!(self.currentHTTPBodyPart = [self.HTTPBodyPartEnumerator nextObject])) {
  626. break;
  627. }
  628. } else {
  629. NSUInteger maxLength = length - (NSUInteger)totalNumberOfBytesRead;
  630. NSInteger numberOfBytesRead = [self.currentHTTPBodyPart read:&buffer[totalNumberOfBytesRead] maxLength:maxLength];
  631. if (numberOfBytesRead == -1) {
  632. self.streamError = self.currentHTTPBodyPart.inputStream.streamError;
  633. break;
  634. } else {
  635. totalNumberOfBytesRead += numberOfBytesRead;
  636. if (self.delay > 0.0f) {
  637. [NSThread sleepForTimeInterval:self.delay];
  638. }
  639. }
  640. }
  641. }
  642. #pragma clang diagnostic pop
  643. return totalNumberOfBytesRead;
  644. }
  645. - (BOOL)getBuffer:(__unused uint8_t **)buffer
  646. length:(__unused NSUInteger *)len
  647. {
  648. return NO;
  649. }
  650. - (BOOL)hasBytesAvailable {
  651. return [self streamStatus] == NSStreamStatusOpen;
  652. }
  653. #pragma mark - NSStream
  654. - (void)open {
  655. if (self.streamStatus == NSStreamStatusOpen) {
  656. return;
  657. }
  658. self.streamStatus = NSStreamStatusOpen;
  659. [self setInitialAndFinalBoundaries];
  660. self.HTTPBodyPartEnumerator = [self.HTTPBodyParts objectEnumerator];
  661. }
  662. - (void)close {
  663. self.streamStatus = NSStreamStatusClosed;
  664. }
  665. - (id)propertyForKey:(__unused NSString *)key {
  666. return nil;
  667. }
  668. - (BOOL)setProperty:(__unused id)property
  669. forKey:(__unused NSString *)key
  670. {
  671. return NO;
  672. }
  673. - (void)scheduleInRunLoop:(__unused NSRunLoop *)aRunLoop
  674. forMode:(__unused NSString *)mode
  675. {}
  676. - (void)removeFromRunLoop:(__unused NSRunLoop *)aRunLoop
  677. forMode:(__unused NSString *)mode
  678. {}
  679. - (unsigned long long)contentLength {
  680. unsigned long long length = 0;
  681. for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
  682. length += [bodyPart contentLength];
  683. }
  684. return length;
  685. }
  686. #pragma mark - Undocumented CFReadStream Bridged Methods
  687. - (void)_scheduleInCFRunLoop:(__unused CFRunLoopRef)aRunLoop
  688. forMode:(__unused CFStringRef)aMode
  689. {}
  690. - (void)_unscheduleFromCFRunLoop:(__unused CFRunLoopRef)aRunLoop
  691. forMode:(__unused CFStringRef)aMode
  692. {}
  693. - (BOOL)_setCFClientFlags:(__unused CFOptionFlags)inFlags
  694. callback:(__unused CFReadStreamClientCallBack)inCallback
  695. context:(__unused CFStreamClientContext *)inContext {
  696. return NO;
  697. }
  698. #pragma mark - NSCopying
  699. -(id)copyWithZone:(NSZone *)zone {
  700. AFMultipartBodyStream *bodyStreamCopy = [[[self class] allocWithZone:zone] initWithStringEncoding:self.stringEncoding];
  701. for (AFHTTPBodyPart *bodyPart in self.HTTPBodyParts) {
  702. [bodyStreamCopy appendHTTPBodyPart:[bodyPart copy]];
  703. }
  704. [bodyStreamCopy setInitialAndFinalBoundaries];
  705. return bodyStreamCopy;
  706. }
  707. @end
  708. #pragma mark -
  709. typedef enum {
  710. AFEncapsulationBoundaryPhase = 1,
  711. AFHeaderPhase = 2,
  712. AFBodyPhase = 3,
  713. AFFinalBoundaryPhase = 4,
  714. } AFHTTPBodyPartReadPhase;
  715. @interface AFHTTPBodyPart () <NSCopying> {
  716. AFHTTPBodyPartReadPhase _phase;
  717. NSInputStream *_inputStream;
  718. unsigned long long _phaseReadOffset;
  719. }
  720. - (BOOL)transitionToNextPhase;
  721. - (NSInteger)readData:(NSData *)data
  722. intoBuffer:(uint8_t *)buffer
  723. maxLength:(NSUInteger)length;
  724. @end
  725. @implementation AFHTTPBodyPart
  726. - (id)init {
  727. self = [super init];
  728. if (!self) {
  729. return nil;
  730. }
  731. [self transitionToNextPhase];
  732. return self;
  733. }
  734. - (void)dealloc {
  735. if (_inputStream) {
  736. [_inputStream close];
  737. _inputStream = nil;
  738. }
  739. }
  740. - (NSInputStream *)inputStream {
  741. if (!_inputStream) {
  742. if ([self.body isKindOfClass:[NSData class]]) {
  743. _inputStream = [NSInputStream inputStreamWithData:self.body];
  744. } else if ([self.body isKindOfClass:[NSURL class]]) {
  745. _inputStream = [NSInputStream inputStreamWithURL:self.body];
  746. } else if ([self.body isKindOfClass:[NSInputStream class]]) {
  747. _inputStream = self.body;
  748. }
  749. }
  750. return _inputStream;
  751. }
  752. - (NSString *)stringForHeaders {
  753. NSMutableString *headerString = [NSMutableString string];
  754. for (NSString *field in [self.headers allKeys]) {
  755. [headerString appendString:[NSString stringWithFormat:@"%@: %@%@", field, [self.headers valueForKey:field], kAFMultipartFormCRLF]];
  756. }
  757. [headerString appendString:kAFMultipartFormCRLF];
  758. return [NSString stringWithString:headerString];
  759. }
  760. - (unsigned long long)contentLength {
  761. unsigned long long length = 0;
  762. NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding];
  763. length += [encapsulationBoundaryData length];
  764. NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding];
  765. length += [headersData length];
  766. length += _bodyContentLength;
  767. NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary(self.boundary) dataUsingEncoding:self.stringEncoding] : [NSData data]);
  768. length += [closingBoundaryData length];
  769. return length;
  770. }
  771. - (BOOL)hasBytesAvailable {
  772. // Allows `read:maxLength:` to be called again if `AFMultipartFormFinalBoundary` doesn't fit into the available buffer
  773. if (_phase == AFFinalBoundaryPhase) {
  774. return YES;
  775. }
  776. #pragma clang diagnostic push
  777. #pragma clang diagnostic ignored "-Wcovered-switch-default"
  778. switch (self.inputStream.streamStatus) {
  779. case NSStreamStatusNotOpen:
  780. case NSStreamStatusOpening:
  781. case NSStreamStatusOpen:
  782. case NSStreamStatusReading:
  783. case NSStreamStatusWriting:
  784. return YES;
  785. case NSStreamStatusAtEnd:
  786. case NSStreamStatusClosed:
  787. case NSStreamStatusError:
  788. default:
  789. return NO;
  790. }
  791. #pragma clang diagnostic pop
  792. }
  793. - (NSInteger)read:(uint8_t *)buffer
  794. maxLength:(NSUInteger)length
  795. {
  796. NSInteger totalNumberOfBytesRead = 0;
  797. if (_phase == AFEncapsulationBoundaryPhase) {
  798. NSData *encapsulationBoundaryData = [([self hasInitialBoundary] ? AFMultipartFormInitialBoundary(self.boundary) : AFMultipartFormEncapsulationBoundary(self.boundary)) dataUsingEncoding:self.stringEncoding];
  799. totalNumberOfBytesRead += [self readData:encapsulationBoundaryData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
  800. }
  801. if (_phase == AFHeaderPhase) {
  802. NSData *headersData = [[self stringForHeaders] dataUsingEncoding:self.stringEncoding];
  803. totalNumberOfBytesRead += [self readData:headersData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
  804. }
  805. if (_phase == AFBodyPhase) {
  806. NSInteger numberOfBytesRead = 0;
  807. numberOfBytesRead = [self.inputStream read:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
  808. if (numberOfBytesRead == -1) {
  809. return -1;
  810. } else {
  811. totalNumberOfBytesRead += numberOfBytesRead;
  812. if ([self.inputStream streamStatus] >= NSStreamStatusAtEnd) {
  813. [self transitionToNextPhase];
  814. }
  815. }
  816. }
  817. if (_phase == AFFinalBoundaryPhase) {
  818. NSData *closingBoundaryData = ([self hasFinalBoundary] ? [AFMultipartFormFinalBoundary(self.boundary) dataUsingEncoding:self.stringEncoding] : [NSData data]);
  819. totalNumberOfBytesRead += [self readData:closingBoundaryData intoBuffer:&buffer[totalNumberOfBytesRead] maxLength:(length - (NSUInteger)totalNumberOfBytesRead)];
  820. }
  821. return totalNumberOfBytesRead;
  822. }
  823. - (NSInteger)readData:(NSData *)data
  824. intoBuffer:(uint8_t *)buffer
  825. maxLength:(NSUInteger)length
  826. {
  827. #pragma clang diagnostic push
  828. #pragma clang diagnostic ignored "-Wgnu"
  829. NSRange range = NSMakeRange((NSUInteger)_phaseReadOffset, MIN([data length] - ((NSUInteger)_phaseReadOffset), length));
  830. [data getBytes:buffer range:range];
  831. #pragma clang diagnostic pop
  832. _phaseReadOffset += range.length;
  833. if (((NSUInteger)_phaseReadOffset) >= [data length]) {
  834. [self transitionToNextPhase];
  835. }
  836. return (NSInteger)range.length;
  837. }
  838. - (BOOL)transitionToNextPhase {
  839. if (![[NSThread currentThread] isMainThread]) {
  840. [self performSelectorOnMainThread:@selector(transitionToNextPhase) withObject:nil waitUntilDone:YES];
  841. return YES;
  842. }
  843. #pragma clang diagnostic push
  844. #pragma clang diagnostic ignored "-Wcovered-switch-default"
  845. switch (_phase) {
  846. case AFEncapsulationBoundaryPhase:
  847. _phase = AFHeaderPhase;
  848. break;
  849. case AFHeaderPhase:
  850. [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
  851. [self.inputStream open];
  852. _phase = AFBodyPhase;
  853. break;
  854. case AFBodyPhase:
  855. [self.inputStream close];
  856. _phase = AFFinalBoundaryPhase;
  857. break;
  858. case AFFinalBoundaryPhase:
  859. default:
  860. _phase = AFEncapsulationBoundaryPhase;
  861. break;
  862. }
  863. _phaseReadOffset = 0;
  864. #pragma clang diagnostic pop
  865. return YES;
  866. }
  867. #pragma mark - NSCopying
  868. - (id)copyWithZone:(NSZone *)zone {
  869. AFHTTPBodyPart *bodyPart = [[[self class] allocWithZone:zone] init];
  870. bodyPart.stringEncoding = self.stringEncoding;
  871. bodyPart.headers = self.headers;
  872. bodyPart.bodyContentLength = self.bodyContentLength;
  873. bodyPart.body = self.body;
  874. bodyPart.boundary = self.boundary;
  875. return bodyPart;
  876. }
  877. @end
  878. #pragma mark -
  879. @implementation AFJSONRequestSerializer
  880. + (instancetype)serializer {
  881. return [self serializerWithWritingOptions:0];
  882. }
  883. + (instancetype)serializerWithWritingOptions:(NSJSONWritingOptions)writingOptions
  884. {
  885. AFJSONRequestSerializer *serializer = [[self alloc] init];
  886. serializer.writingOptions = writingOptions;
  887. return serializer;
  888. }
  889. #pragma mark - AFURLRequestSerialization
  890. - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
  891. withParameters:(id)parameters
  892. error:(NSError *__autoreleasing *)error
  893. {
  894. NSParameterAssert(request);
  895. if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
  896. return [super requestBySerializingRequest:request withParameters:parameters error:error];
  897. }
  898. NSMutableURLRequest *mutableRequest = [request mutableCopy];
  899. [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
  900. if (![request valueForHTTPHeaderField:field]) {
  901. [mutableRequest setValue:value forHTTPHeaderField:field];
  902. }
  903. }];
  904. if (parameters) {
  905. if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
  906. NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
  907. [mutableRequest setValue:[NSString stringWithFormat:@"application/json; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
  908. }
  909. [mutableRequest setHTTPBody:[NSJSONSerialization dataWithJSONObject:parameters options:self.writingOptions error:error]];
  910. }
  911. return mutableRequest;
  912. }
  913. #pragma mark - NSecureCoding
  914. - (id)initWithCoder:(NSCoder *)decoder {
  915. self = [super initWithCoder:decoder];
  916. if (!self) {
  917. return nil;
  918. }
  919. self.writingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writingOptions))] unsignedIntegerValue];
  920. return self;
  921. }
  922. - (void)encodeWithCoder:(NSCoder *)coder {
  923. [super encodeWithCoder:coder];
  924. [coder encodeInteger:self.writingOptions forKey:NSStringFromSelector(@selector(writingOptions))];
  925. }
  926. #pragma mark - NSCopying
  927. - (id)copyWithZone:(NSZone *)zone {
  928. AFJSONRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
  929. serializer.writingOptions = self.writingOptions;
  930. return serializer;
  931. }
  932. @end
  933. #pragma mark -
  934. @implementation AFPropertyListRequestSerializer
  935. + (instancetype)serializer {
  936. return [self serializerWithFormat:NSPropertyListXMLFormat_v1_0 writeOptions:0];
  937. }
  938. + (instancetype)serializerWithFormat:(NSPropertyListFormat)format
  939. writeOptions:(NSPropertyListWriteOptions)writeOptions
  940. {
  941. AFPropertyListRequestSerializer *serializer = [[self alloc] init];
  942. serializer.format = format;
  943. serializer.writeOptions = writeOptions;
  944. return serializer;
  945. }
  946. #pragma mark - AFURLRequestSerializer
  947. - (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
  948. withParameters:(id)parameters
  949. error:(NSError *__autoreleasing *)error
  950. {
  951. NSParameterAssert(request);
  952. if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
  953. return [super requestBySerializingRequest:request withParameters:parameters error:error];
  954. }
  955. NSMutableURLRequest *mutableRequest = [request mutableCopy];
  956. [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
  957. if (![request valueForHTTPHeaderField:field]) {
  958. [mutableRequest setValue:value forHTTPHeaderField:field];
  959. }
  960. }];
  961. if (parameters) {
  962. if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
  963. NSString *charset = (__bridge NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding(NSUTF8StringEncoding));
  964. [mutableRequest setValue:[NSString stringWithFormat:@"application/x-plist; charset=%@", charset] forHTTPHeaderField:@"Content-Type"];
  965. }
  966. [mutableRequest setHTTPBody:[NSPropertyListSerialization dataWithPropertyList:parameters format:self.format options:self.writeOptions error:error]];
  967. }
  968. return mutableRequest;
  969. }
  970. #pragma mark - NSecureCoding
  971. - (id)initWithCoder:(NSCoder *)decoder {
  972. self = [super initWithCoder:decoder];
  973. if (!self) {
  974. return nil;
  975. }
  976. self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue];
  977. self.writeOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(writeOptions))] unsignedIntegerValue];
  978. return self;
  979. }
  980. - (void)encodeWithCoder:(NSCoder *)coder {
  981. [super encodeWithCoder:coder];
  982. [coder encodeInteger:self.format forKey:NSStringFromSelector(@selector(format))];
  983. [coder encodeObject:@(self.writeOptions) forKey:NSStringFromSelector(@selector(writeOptions))];
  984. }
  985. #pragma mark - NSCopying
  986. - (id)copyWithZone:(NSZone *)zone {
  987. AFPropertyListRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
  988. serializer.format = self.format;
  989. serializer.writeOptions = self.writeOptions;
  990. return serializer;
  991. }
  992. @end