AFURLResponseSerialization.m 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. // AFURLResponseSerialization.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 "AFURLResponseSerialization.h"
  22. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  23. #import <UIKit/UIKit.h>
  24. #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
  25. #import <Cocoa/Cocoa.h>
  26. #endif
  27. NSString * const AFURLResponseSerializationErrorDomain = @"com.alamofire.error.serialization.response";
  28. NSString * const AFNetworkingOperationFailingURLResponseErrorKey = @"com.alamofire.serialization.response.error.response";
  29. NSString * const AFNetworkingOperationFailingURLResponseDataErrorKey = @"com.alamofire.serialization.response.error.data";
  30. static NSError * AFErrorWithUnderlyingError(NSError *error, NSError *underlyingError) {
  31. if (!error) {
  32. return underlyingError;
  33. }
  34. if (!underlyingError || error.userInfo[NSUnderlyingErrorKey]) {
  35. return error;
  36. }
  37. NSMutableDictionary *mutableUserInfo = [error.userInfo mutableCopy];
  38. mutableUserInfo[NSUnderlyingErrorKey] = underlyingError;
  39. return [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:mutableUserInfo];
  40. }
  41. static BOOL AFErrorOrUnderlyingErrorHasCodeInDomain(NSError *error, NSInteger code, NSString *domain) {
  42. if ([error.domain isEqualToString:domain] && error.code == code) {
  43. return YES;
  44. } else if (error.userInfo[NSUnderlyingErrorKey]) {
  45. return AFErrorOrUnderlyingErrorHasCodeInDomain(error.userInfo[NSUnderlyingErrorKey], code, domain);
  46. }
  47. return NO;
  48. }
  49. static id AFJSONObjectByRemovingKeysWithNullValues(id JSONObject, NSJSONReadingOptions readingOptions) {
  50. if ([JSONObject isKindOfClass:[NSArray class]]) {
  51. NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:[(NSArray *)JSONObject count]];
  52. for (id value in (NSArray *)JSONObject) {
  53. [mutableArray addObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions)];
  54. }
  55. return (readingOptions & NSJSONReadingMutableContainers) ? mutableArray : [NSArray arrayWithArray:mutableArray];
  56. } else if ([JSONObject isKindOfClass:[NSDictionary class]]) {
  57. NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithDictionary:JSONObject];
  58. for (id <NSCopying> key in [(NSDictionary *)JSONObject allKeys]) {
  59. id value = [(NSDictionary *)JSONObject objectForKey:key];
  60. if (!value || [value isEqual:[NSNull null]]) {
  61. [mutableDictionary removeObjectForKey:key];
  62. } else if ([value isKindOfClass:[NSArray class]] || [value isKindOfClass:[NSDictionary class]]) {
  63. [mutableDictionary setObject:AFJSONObjectByRemovingKeysWithNullValues(value, readingOptions) forKey:key];
  64. }
  65. }
  66. return (readingOptions & NSJSONReadingMutableContainers) ? mutableDictionary : [NSDictionary dictionaryWithDictionary:mutableDictionary];
  67. }
  68. return JSONObject;
  69. }
  70. @implementation AFHTTPResponseSerializer
  71. + (instancetype)serializer {
  72. return [[self alloc] init];
  73. }
  74. - (instancetype)init {
  75. self = [super init];
  76. if (!self) {
  77. return nil;
  78. }
  79. self.stringEncoding = NSUTF8StringEncoding;
  80. self.acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)];
  81. self.acceptableContentTypes = nil;
  82. return self;
  83. }
  84. #pragma mark -
  85. - (BOOL)validateResponse:(NSHTTPURLResponse *)response
  86. data:(NSData *)data
  87. error:(NSError * __autoreleasing *)error
  88. {
  89. BOOL responseIsValid = YES;
  90. NSError *validationError = nil;
  91. if (response && [response isKindOfClass:[NSHTTPURLResponse class]]) {
  92. if (self.acceptableContentTypes && ![self.acceptableContentTypes containsObject:[response MIMEType]]) {
  93. if ([data length] > 0 && [response URL]) {
  94. NSMutableDictionary *mutableUserInfo = [@{
  95. NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: unacceptable content-type: %@", @"AFNetworking", nil), [response MIMEType]],
  96. NSURLErrorFailingURLErrorKey:[response URL],
  97. AFNetworkingOperationFailingURLResponseErrorKey: response,
  98. } mutableCopy];
  99. if (data) {
  100. mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
  101. }
  102. validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:mutableUserInfo], validationError);
  103. }
  104. responseIsValid = NO;
  105. }
  106. if (self.acceptableStatusCodes && ![self.acceptableStatusCodes containsIndex:(NSUInteger)response.statusCode] && [response URL]) {
  107. NSMutableDictionary *mutableUserInfo = [@{
  108. NSLocalizedDescriptionKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Request failed: %@ (%ld)", @"AFNetworking", nil), [NSHTTPURLResponse localizedStringForStatusCode:response.statusCode], (long)response.statusCode],
  109. NSURLErrorFailingURLErrorKey:[response URL],
  110. AFNetworkingOperationFailingURLResponseErrorKey: response,
  111. } mutableCopy];
  112. if (data) {
  113. mutableUserInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] = data;
  114. }
  115. validationError = AFErrorWithUnderlyingError([NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:mutableUserInfo], validationError);
  116. responseIsValid = NO;
  117. }
  118. }
  119. if (error && !responseIsValid) {
  120. *error = validationError;
  121. }
  122. return responseIsValid;
  123. }
  124. #pragma mark - AFURLResponseSerialization
  125. - (id)responseObjectForResponse:(NSURLResponse *)response
  126. data:(NSData *)data
  127. error:(NSError *__autoreleasing *)error
  128. {
  129. [self validateResponse:(NSHTTPURLResponse *)response data:data error:error];
  130. return data;
  131. }
  132. #pragma mark - NSSecureCoding
  133. + (BOOL)supportsSecureCoding {
  134. return YES;
  135. }
  136. - (id)initWithCoder:(NSCoder *)decoder {
  137. self = [self init];
  138. if (!self) {
  139. return nil;
  140. }
  141. self.acceptableStatusCodes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
  142. self.acceptableContentTypes = [decoder decodeObjectOfClass:[NSIndexSet class] forKey:NSStringFromSelector(@selector(acceptableContentTypes))];
  143. return self;
  144. }
  145. - (void)encodeWithCoder:(NSCoder *)coder {
  146. [coder encodeObject:self.acceptableStatusCodes forKey:NSStringFromSelector(@selector(acceptableStatusCodes))];
  147. [coder encodeObject:self.acceptableContentTypes forKey:NSStringFromSelector(@selector(acceptableContentTypes))];
  148. }
  149. #pragma mark - NSCopying
  150. - (id)copyWithZone:(NSZone *)zone {
  151. AFHTTPResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
  152. serializer.acceptableStatusCodes = [self.acceptableStatusCodes copyWithZone:zone];
  153. serializer.acceptableContentTypes = [self.acceptableContentTypes copyWithZone:zone];
  154. return serializer;
  155. }
  156. @end
  157. #pragma mark -
  158. @implementation AFJSONResponseSerializer
  159. + (instancetype)serializer {
  160. return [self serializerWithReadingOptions:(NSJSONReadingOptions)0];
  161. }
  162. + (instancetype)serializerWithReadingOptions:(NSJSONReadingOptions)readingOptions {
  163. AFJSONResponseSerializer *serializer = [[self alloc] init];
  164. serializer.readingOptions = readingOptions;
  165. return serializer;
  166. }
  167. - (instancetype)init {
  168. self = [super init];
  169. if (!self) {
  170. return nil;
  171. }
  172. self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
  173. return self;
  174. }
  175. #pragma mark - AFURLResponseSerialization
  176. - (id)responseObjectForResponse:(NSURLResponse *)response
  177. data:(NSData *)data
  178. error:(NSError *__autoreleasing *)error
  179. {
  180. if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
  181. if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
  182. return nil;
  183. }
  184. }
  185. // Workaround for behavior of Rails to return a single space for `head :ok` (a workaround for a bug in Safari), which is not interpreted as valid input by NSJSONSerialization.
  186. // See https://github.com/rails/rails/issues/1742
  187. NSStringEncoding stringEncoding = self.stringEncoding;
  188. if (response.textEncodingName) {
  189. CFStringEncoding encoding = CFStringConvertIANACharSetNameToEncoding((CFStringRef)response.textEncodingName);
  190. if (encoding != kCFStringEncodingInvalidId) {
  191. stringEncoding = CFStringConvertEncodingToNSStringEncoding(encoding);
  192. }
  193. }
  194. id responseObject = nil;
  195. NSError *serializationError = nil;
  196. @autoreleasepool {
  197. NSString *responseString = [[NSString alloc] initWithData:data encoding:stringEncoding];
  198. if (responseString && ![responseString isEqualToString:@" "]) {
  199. // Workaround for a bug in NSJSONSerialization when Unicode character escape codes are used instead of the actual character
  200. // See http://stackoverflow.com/a/12843465/157142
  201. data = [responseString dataUsingEncoding:NSUTF8StringEncoding];
  202. if (data) {
  203. if ([data length] > 0) {
  204. responseObject = [NSJSONSerialization JSONObjectWithData:data options:self.readingOptions error:&serializationError];
  205. } else {
  206. return nil;
  207. }
  208. } else {
  209. NSDictionary *userInfo = @{
  210. NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"Data failed decoding as a UTF-8 string", @"AFNetworking", nil),
  211. NSLocalizedFailureReasonErrorKey: [NSString stringWithFormat:NSLocalizedStringFromTable(@"Could not decode string: %@", @"AFNetworking", nil), responseString]
  212. };
  213. serializationError = [NSError errorWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorCannotDecodeContentData userInfo:userInfo];
  214. }
  215. }
  216. }
  217. if (self.removesKeysWithNullValues && responseObject) {
  218. responseObject = AFJSONObjectByRemovingKeysWithNullValues(responseObject, self.readingOptions);
  219. }
  220. if (error) {
  221. *error = AFErrorWithUnderlyingError(serializationError, *error);
  222. }
  223. return responseObject;
  224. }
  225. #pragma mark - NSSecureCoding
  226. - (id)initWithCoder:(NSCoder *)decoder {
  227. self = [super initWithCoder:decoder];
  228. if (!self) {
  229. return nil;
  230. }
  231. self.readingOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readingOptions))] unsignedIntegerValue];
  232. self.removesKeysWithNullValues = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))] boolValue];
  233. return self;
  234. }
  235. - (void)encodeWithCoder:(NSCoder *)coder {
  236. [super encodeWithCoder:coder];
  237. [coder encodeObject:@(self.readingOptions) forKey:NSStringFromSelector(@selector(readingOptions))];
  238. [coder encodeObject:@(self.removesKeysWithNullValues) forKey:NSStringFromSelector(@selector(removesKeysWithNullValues))];
  239. }
  240. #pragma mark - NSCopying
  241. - (id)copyWithZone:(NSZone *)zone {
  242. AFJSONResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
  243. serializer.readingOptions = self.readingOptions;
  244. serializer.removesKeysWithNullValues = self.removesKeysWithNullValues;
  245. return serializer;
  246. }
  247. @end
  248. #pragma mark -
  249. @implementation AFXMLParserResponseSerializer
  250. + (instancetype)serializer {
  251. AFXMLParserResponseSerializer *serializer = [[self alloc] init];
  252. return serializer;
  253. }
  254. - (instancetype)init {
  255. self = [super init];
  256. if (!self) {
  257. return nil;
  258. }
  259. self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml", nil];
  260. return self;
  261. }
  262. #pragma mark - AFURLResponseSerialization
  263. - (id)responseObjectForResponse:(NSHTTPURLResponse *)response
  264. data:(NSData *)data
  265. error:(NSError *__autoreleasing *)error
  266. {
  267. if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
  268. if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
  269. return nil;
  270. }
  271. }
  272. return [[NSXMLParser alloc] initWithData:data];
  273. }
  274. @end
  275. #pragma mark -
  276. #ifdef __MAC_OS_X_VERSION_MIN_REQUIRED
  277. @implementation AFXMLDocumentResponseSerializer
  278. + (instancetype)serializer {
  279. return [self serializerWithXMLDocumentOptions:0];
  280. }
  281. + (instancetype)serializerWithXMLDocumentOptions:(NSUInteger)mask {
  282. AFXMLDocumentResponseSerializer *serializer = [[self alloc] init];
  283. serializer.options = mask;
  284. return serializer;
  285. }
  286. - (instancetype)init {
  287. self = [super init];
  288. if (!self) {
  289. return nil;
  290. }
  291. self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml", nil];
  292. return self;
  293. }
  294. #pragma mark - AFURLResponseSerialization
  295. - (id)responseObjectForResponse:(NSURLResponse *)response
  296. data:(NSData *)data
  297. error:(NSError *__autoreleasing *)error
  298. {
  299. if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
  300. if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
  301. return nil;
  302. }
  303. }
  304. NSError *serializationError = nil;
  305. NSXMLDocument *document = [[NSXMLDocument alloc] initWithData:data options:self.options error:&serializationError];
  306. if (error) {
  307. *error = AFErrorWithUnderlyingError(serializationError, *error);
  308. }
  309. return document;
  310. }
  311. #pragma mark - NSSecureCoding
  312. - (id)initWithCoder:(NSCoder *)decoder {
  313. self = [super initWithCoder:decoder];
  314. if (!self) {
  315. return nil;
  316. }
  317. self.options = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(options))] unsignedIntegerValue];
  318. return self;
  319. }
  320. - (void)encodeWithCoder:(NSCoder *)coder {
  321. [super encodeWithCoder:coder];
  322. [coder encodeObject:@(self.options) forKey:NSStringFromSelector(@selector(options))];
  323. }
  324. #pragma mark - NSCopying
  325. - (id)copyWithZone:(NSZone *)zone {
  326. AFXMLDocumentResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
  327. serializer.options = self.options;
  328. return serializer;
  329. }
  330. @end
  331. #endif
  332. #pragma mark -
  333. @implementation AFPropertyListResponseSerializer
  334. + (instancetype)serializer {
  335. return [self serializerWithFormat:NSPropertyListXMLFormat_v1_0 readOptions:0];
  336. }
  337. + (instancetype)serializerWithFormat:(NSPropertyListFormat)format
  338. readOptions:(NSPropertyListReadOptions)readOptions
  339. {
  340. AFPropertyListResponseSerializer *serializer = [[self alloc] init];
  341. serializer.format = format;
  342. serializer.readOptions = readOptions;
  343. return serializer;
  344. }
  345. - (instancetype)init {
  346. self = [super init];
  347. if (!self) {
  348. return nil;
  349. }
  350. self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/x-plist", nil];
  351. return self;
  352. }
  353. #pragma mark - AFURLResponseSerialization
  354. - (id)responseObjectForResponse:(NSURLResponse *)response
  355. data:(NSData *)data
  356. error:(NSError *__autoreleasing *)error
  357. {
  358. if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
  359. if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
  360. return nil;
  361. }
  362. }
  363. id responseObject;
  364. NSError *serializationError = nil;
  365. if (data) {
  366. responseObject = [NSPropertyListSerialization propertyListWithData:data options:self.readOptions format:NULL error:&serializationError];
  367. }
  368. if (error) {
  369. *error = AFErrorWithUnderlyingError(serializationError, *error);
  370. }
  371. return responseObject;
  372. }
  373. #pragma mark - NSSecureCoding
  374. - (id)initWithCoder:(NSCoder *)decoder {
  375. self = [super initWithCoder:decoder];
  376. if (!self) {
  377. return nil;
  378. }
  379. self.format = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(format))] unsignedIntegerValue];
  380. self.readOptions = [[decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(readOptions))] unsignedIntegerValue];
  381. return self;
  382. }
  383. - (void)encodeWithCoder:(NSCoder *)coder {
  384. [super encodeWithCoder:coder];
  385. [coder encodeObject:@(self.format) forKey:NSStringFromSelector(@selector(format))];
  386. [coder encodeObject:@(self.readOptions) forKey:NSStringFromSelector(@selector(readOptions))];
  387. }
  388. #pragma mark - NSCopying
  389. - (id)copyWithZone:(NSZone *)zone {
  390. AFPropertyListResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
  391. serializer.format = self.format;
  392. serializer.readOptions = self.readOptions;
  393. return serializer;
  394. }
  395. @end
  396. #pragma mark -
  397. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  398. #import <CoreGraphics/CoreGraphics.h>
  399. static UIImage * AFImageWithDataAtScale(NSData *data, CGFloat scale) {
  400. UIImage *image = [[UIImage alloc] initWithData:data];
  401. if (image.images) {
  402. return image;
  403. }
  404. return [[UIImage alloc] initWithCGImage:[image CGImage] scale:scale orientation:image.imageOrientation];
  405. }
  406. static UIImage * AFInflatedImageFromResponseWithDataAtScale(NSHTTPURLResponse *response, NSData *data, CGFloat scale) {
  407. if (!data || [data length] == 0) {
  408. return nil;
  409. }
  410. CGImageRef imageRef = NULL;
  411. CGDataProviderRef dataProvider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
  412. if ([response.MIMEType isEqualToString:@"image/png"]) {
  413. imageRef = CGImageCreateWithPNGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault);
  414. } else if ([response.MIMEType isEqualToString:@"image/jpeg"]) {
  415. imageRef = CGImageCreateWithJPEGDataProvider(dataProvider, NULL, true, kCGRenderingIntentDefault);
  416. if (imageRef) {
  417. CGColorSpaceRef imageColorSpace = CGImageGetColorSpace(imageRef);
  418. CGColorSpaceModel imageColorSpaceModel = CGColorSpaceGetModel(imageColorSpace);
  419. // CGImageCreateWithJPEGDataProvider does not properly handle CMKY, so fall back to AFImageWithDataAtScale
  420. if (imageColorSpaceModel == kCGColorSpaceModelCMYK) {
  421. CGImageRelease(imageRef);
  422. imageRef = NULL;
  423. }
  424. }
  425. }
  426. CGDataProviderRelease(dataProvider);
  427. UIImage *image = AFImageWithDataAtScale(data, scale);
  428. if (!imageRef) {
  429. if (image.images || !image) {
  430. return image;
  431. }
  432. imageRef = CGImageCreateCopy([image CGImage]);
  433. if (!imageRef) {
  434. return nil;
  435. }
  436. }
  437. size_t width = CGImageGetWidth(imageRef);
  438. size_t height = CGImageGetHeight(imageRef);
  439. size_t bitsPerComponent = CGImageGetBitsPerComponent(imageRef);
  440. if (width * height > 1024 * 1024 || bitsPerComponent > 8) {
  441. CGImageRelease(imageRef);
  442. return image;
  443. }
  444. // CGImageGetBytesPerRow() calculates incorrectly in iOS 5.0, so defer to CGBitmapContextCreate
  445. size_t bytesPerRow = 0;
  446. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  447. CGColorSpaceModel colorSpaceModel = CGColorSpaceGetModel(colorSpace);
  448. CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
  449. if (colorSpaceModel == kCGColorSpaceModelRGB) {
  450. uint32_t alpha = (bitmapInfo & kCGBitmapAlphaInfoMask);
  451. #pragma clang diagnostic push
  452. #pragma clang diagnostic ignored "-Wassign-enum"
  453. if (alpha == kCGImageAlphaNone) {
  454. bitmapInfo &= ~kCGBitmapAlphaInfoMask;
  455. bitmapInfo |= kCGImageAlphaNoneSkipFirst;
  456. } else if (!(alpha == kCGImageAlphaNoneSkipFirst || alpha == kCGImageAlphaNoneSkipLast)) {
  457. bitmapInfo &= ~kCGBitmapAlphaInfoMask;
  458. bitmapInfo |= kCGImageAlphaPremultipliedFirst;
  459. }
  460. #pragma clang diagnostic pop
  461. }
  462. CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, colorSpace, bitmapInfo);
  463. CGColorSpaceRelease(colorSpace);
  464. if (!context) {
  465. CGImageRelease(imageRef);
  466. return image;
  467. }
  468. CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, width, height), imageRef);
  469. CGImageRef inflatedImageRef = CGBitmapContextCreateImage(context);
  470. CGContextRelease(context);
  471. UIImage *inflatedImage = [[UIImage alloc] initWithCGImage:inflatedImageRef scale:scale orientation:image.imageOrientation];
  472. CGImageRelease(inflatedImageRef);
  473. CGImageRelease(imageRef);
  474. return inflatedImage;
  475. }
  476. #endif
  477. @implementation AFImageResponseSerializer
  478. - (instancetype)init {
  479. self = [super init];
  480. if (!self) {
  481. return nil;
  482. }
  483. self.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"image/tiff", @"image/jpeg", @"image/gif", @"image/png", @"image/ico", @"image/x-icon", @"image/bmp", @"image/x-bmp", @"image/x-xbitmap", @"image/x-win-bitmap", nil];
  484. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  485. self.imageScale = [[UIScreen mainScreen] scale];
  486. self.automaticallyInflatesResponseImage = YES;
  487. #endif
  488. return self;
  489. }
  490. #pragma mark - AFURLResponseSerializer
  491. - (id)responseObjectForResponse:(NSURLResponse *)response
  492. data:(NSData *)data
  493. error:(NSError *__autoreleasing *)error
  494. {
  495. if (![self validateResponse:(NSHTTPURLResponse *)response data:data error:error]) {
  496. if (!error || AFErrorOrUnderlyingErrorHasCodeInDomain(*error, NSURLErrorCannotDecodeContentData, AFURLResponseSerializationErrorDomain)) {
  497. return nil;
  498. }
  499. }
  500. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  501. if (self.automaticallyInflatesResponseImage) {
  502. return AFInflatedImageFromResponseWithDataAtScale((NSHTTPURLResponse *)response, data, self.imageScale);
  503. } else {
  504. return AFImageWithDataAtScale(data, self.imageScale);
  505. }
  506. #elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
  507. // Ensure that the image is set to it's correct pixel width and height
  508. NSBitmapImageRep *bitimage = [[NSBitmapImageRep alloc] initWithData:data];
  509. NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize([bitimage pixelsWide], [bitimage pixelsHigh])];
  510. [image addRepresentation:bitimage];
  511. return image;
  512. #endif
  513. return nil;
  514. }
  515. #pragma mark - NSSecureCoding
  516. - (id)initWithCoder:(NSCoder *)decoder {
  517. self = [super initWithCoder:decoder];
  518. if (!self) {
  519. return nil;
  520. }
  521. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  522. NSNumber *imageScale = [decoder decodeObjectOfClass:[NSNumber class] forKey:NSStringFromSelector(@selector(imageScale))];
  523. #if CGFLOAT_IS_DOUBLE
  524. self.imageScale = [imageScale doubleValue];
  525. #else
  526. self.imageScale = [imageScale floatValue];
  527. #endif
  528. self.automaticallyInflatesResponseImage = [decoder decodeBoolForKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))];
  529. #endif
  530. return self;
  531. }
  532. - (void)encodeWithCoder:(NSCoder *)coder {
  533. [super encodeWithCoder:coder];
  534. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  535. [coder encodeObject:@(self.imageScale) forKey:NSStringFromSelector(@selector(imageScale))];
  536. [coder encodeBool:self.automaticallyInflatesResponseImage forKey:NSStringFromSelector(@selector(automaticallyInflatesResponseImage))];
  537. #endif
  538. }
  539. #pragma mark - NSCopying
  540. - (id)copyWithZone:(NSZone *)zone {
  541. AFImageResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
  542. #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
  543. serializer.imageScale = self.imageScale;
  544. serializer.automaticallyInflatesResponseImage = self.automaticallyInflatesResponseImage;
  545. #endif
  546. return serializer;
  547. }
  548. @end
  549. #pragma mark -
  550. @interface AFCompoundResponseSerializer ()
  551. @property (readwrite, nonatomic, copy) NSArray *responseSerializers;
  552. @end
  553. @implementation AFCompoundResponseSerializer
  554. + (instancetype)compoundSerializerWithResponseSerializers:(NSArray *)responseSerializers {
  555. AFCompoundResponseSerializer *serializer = [[self alloc] init];
  556. serializer.responseSerializers = responseSerializers;
  557. return serializer;
  558. }
  559. #pragma mark - AFURLResponseSerialization
  560. - (id)responseObjectForResponse:(NSURLResponse *)response
  561. data:(NSData *)data
  562. error:(NSError *__autoreleasing *)error
  563. {
  564. for (id <AFURLResponseSerialization> serializer in self.responseSerializers) {
  565. if (![serializer isKindOfClass:[AFHTTPResponseSerializer class]]) {
  566. continue;
  567. }
  568. NSError *serializerError = nil;
  569. id responseObject = [serializer responseObjectForResponse:response data:data error:&serializerError];
  570. if (responseObject) {
  571. if (error) {
  572. *error = AFErrorWithUnderlyingError(serializerError, *error);
  573. }
  574. return responseObject;
  575. }
  576. }
  577. return [super responseObjectForResponse:response data:data error:error];
  578. }
  579. #pragma mark - NSSecureCoding
  580. - (id)initWithCoder:(NSCoder *)decoder {
  581. self = [super initWithCoder:decoder];
  582. if (!self) {
  583. return nil;
  584. }
  585. self.responseSerializers = [decoder decodeObjectOfClass:[NSArray class] forKey:NSStringFromSelector(@selector(responseSerializers))];
  586. return self;
  587. }
  588. - (void)encodeWithCoder:(NSCoder *)coder {
  589. [super encodeWithCoder:coder];
  590. [coder encodeObject:self.responseSerializers forKey:NSStringFromSelector(@selector(responseSerializers))];
  591. }
  592. #pragma mark - NSCopying
  593. - (id)copyWithZone:(NSZone *)zone {
  594. AFCompoundResponseSerializer *serializer = [[[self class] allocWithZone:zone] init];
  595. serializer.responseSerializers = self.responseSerializers;
  596. return serializer;
  597. }
  598. @end