AFURLRequestSerialization.m 52 KB

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