2
0

AFURLResponseSerialization.m 26 KB

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