diff --git a/AFNetworking b/AFNetworking index 60bd422..8ccc3f6 160000 --- a/AFNetworking +++ b/AFNetworking @@ -1 +1 @@ -Subproject commit 60bd422401112537fa6d6f008d4843e83f0d35bc +Subproject commit 8ccc3f6d6c1e7ab5062de75ad43d10dba24177e7 diff --git a/AFOAuth1Client.podspec b/AFOAuth1Client.podspec index ee30a53..7b31936 100644 --- a/AFOAuth1Client.podspec +++ b/AFOAuth1Client.podspec @@ -1,22 +1,22 @@ Pod::Spec.new do |s| s.name = "AFOAuth1Client" - s.version = "0.3.3" + s.version = "0.4.0" s.summary = "AFNetworking Extension for OAuth 1.0a Authentication." s.homepage = "https://github.com/AFNetworking/AFOAuth1Client" s.social_media_url = "https://twitter.com/AFNetworking" s.license = 'MIT' s.author = { 'Mattt Thompson' => 'm@mattt.me' } - s.source = { :git => "https://github.com/AFNetworking/AFOAuth1Client.git", :tag => '0.3.3' } + s.source = { :git => "https://github.com/lxcid/AFOAuth1Client.git", :tag => '0.4.0' } s.source_files = 'AFOAuth1Client' s.requires_arc = true - s.ios.deployment_target = '5.0' + s.ios.deployment_target = '7.0' s.ios.frameworks = 'MobileCoreServices', 'SystemConfiguration', 'Security', 'CoreGraphics' - s.osx.deployment_target = '10.7' + s.osx.deployment_target = '10.9' s.osx.frameworks = 'CoreServices', 'SystemConfiguration', 'Security' - s.dependency 'AFNetworking', '~> 1.3' + s.dependency 'AFNetworking', '~> 2.5' s.prefix_header_contents = <<-EOS #import diff --git a/AFOAuth1Client.xcworkspace/contents.xcworkspacedata b/AFOAuth1Client.xcworkspace/contents.xcworkspacedata index c00612b..19bf732 100644 --- a/AFOAuth1Client.xcworkspace/contents.xcworkspacedata +++ b/AFOAuth1Client.xcworkspace/contents.xcworkspacedata @@ -10,6 +10,24 @@ + + + + + + + + + + + + diff --git a/AFOAuth1Client.xcworkspace/xcshareddata/AFOAuth1Client.xccheckout b/AFOAuth1Client.xcworkspace/xcshareddata/AFOAuth1Client.xccheckout new file mode 100644 index 0000000..60a6148 --- /dev/null +++ b/AFOAuth1Client.xcworkspace/xcshareddata/AFOAuth1Client.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 4CC50E2E-E38D-4E80-9B02-0E8C1EAA3050 + IDESourceControlProjectName + AFOAuth1Client + IDESourceControlProjectOriginsDictionary + + AD8BFDC8297514A63E246839A285AD2407EFF65D + https://github.com/johndpope/AFOAuth1Client + + IDESourceControlProjectPath + AFOAuth1Client.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + AD8BFDC8297514A63E246839A285AD2407EFF65D + .. + + IDESourceControlProjectURL + https://github.com/johndpope/AFOAuth1Client + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + AD8BFDC8297514A63E246839A285AD2407EFF65D + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + AD8BFDC8297514A63E246839A285AD2407EFF65D + IDESourceControlWCCName + AFOAuth1Client + + + + diff --git a/AFOAuth1Client/AFOAuth1Client.h b/AFOAuth1Client/AFOAuth1Client.h index a83ecca..1568e63 100644 --- a/AFOAuth1Client/AFOAuth1Client.h +++ b/AFOAuth1Client/AFOAuth1Client.h @@ -1,6 +1,6 @@ // AFOAuth1Client.m // -// Copyright (c) 2011 Mattt Thompson (http://mattt.me/) +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -20,219 +20,127 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -#import "AFHTTPClient.h" +#import "AFHTTPSessionManager.h" -typedef NS_ENUM(NSUInteger, AFOAuthSignatureMethod) { - AFPlainTextSignatureMethod = 1, - AFHMACSHA1SignatureMethod = 2, -}; +///--------------------------- +/// @name Forward Declarations +///--------------------------- @class AFOAuth1Token; -/** - - */ -@interface AFOAuth1Client : AFHTTPClient - -///----------------------------------- -/// @name Managing OAuth Configuration -///----------------------------------- - -/** - - */ -@property (nonatomic, assign) AFOAuthSignatureMethod signatureMethod; - -/** - - */ -@property (nonatomic, copy) NSString *realm; - -/** - - */ -@property (nonatomic, strong) AFOAuth1Token *accessToken; - -/** - - */ -@property (nonatomic, strong) NSString *oauthAccessMethod; - -///--------------------- -/// @name Initialization -///--------------------- - -/** - - */ -- (id)initWithBaseURL:(NSURL *)url - key:(NSString *)key - secret:(NSString *)secret; - -///--------------------- -/// @name Authenticating -///--------------------- - -/** +///----------------------- +/// @name Type Definitions +///----------------------- - */ -- (void)authorizeUsingOAuthWithRequestTokenPath:(NSString *)requestTokenPath - userAuthorizationPath:(NSString *)userAuthorizationPath - callbackURL:(NSURL *)callbackURL - accessTokenPath:(NSString *)accessTokenPath - accessMethod:(NSString *)accessMethod - scope:(NSString *)scope - success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success - failure:(void (^)(NSError *error))failure; - -/** - - */ -- (void)acquireOAuthRequestTokenWithPath:(NSString *)path - callbackURL:(NSURL *)url - accessMethod:(NSString *)accessMethod - scope:(NSString *)scope - success:(void (^)(AFOAuth1Token *requestToken, id responseObject))success - failure:(void (^)(NSError *error))failure; - -/** - - */ -- (void)acquireOAuthAccessTokenWithPath:(NSString *)path - requestToken:(AFOAuth1Token *)requestToken - accessMethod:(NSString *)accessMethod - success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success - failure:(void (^)(NSError *error))failure; - -///---------------------------------------------------- -/// @name Configuring Service Provider Request Handling -///---------------------------------------------------- - -/** - - */ -- (void)setServiceProviderRequestHandler:(void (^)(NSURLRequest *request))block - completion:(void (^)())completion; - -@end +typedef void (^AFServiceProviderRequestHandlerBlock)(NSURLRequest *request); +typedef void (^AFServiceProviderRequestCompletionBlock)(); ///---------------- /// @name Constants ///---------------- /** - + */ extern NSString * const kAFApplicationLaunchedWithURLNotification; /** - + */ extern NSString * const kAFApplicationLaunchOptionsURLKey; -#pragma mark - - -/** - - */ -@interface AFOAuth1Token : NSObject - -/** - - */ -@property (readonly, nonatomic, copy) NSString *key; - -/** - - */ -@property (readonly, nonatomic, copy) NSString *secret; - -/** - - */ -@property (readonly, nonatomic, copy) NSString *session; - -/** - - */ -@property (nonatomic, copy) NSString *verifier; - -/** - - */ -@property (readonly, nonatomic, assign, getter = canBeRenewed) BOOL renewable; - -/** - - */ -@property (readonly, nonatomic, assign, getter = isExpired) BOOL expired; - /** + `AFOAuth1Client` encapsulates common patterns to authenticate against a resource server conforming to the behavior outlined in the OAuth 1.0a specification. + @see RFC 5849 The OAuth 1.0 Protocol: https://tools.ietf.org/html/rfc5849 */ -@property (nonatomic, strong) NSDictionary *userInfo; - -/** +@interface AFOAuth1Client : AFHTTPSessionManager - */ -- (id)initWithQueryString:(NSString *)queryString; +///--------------------- +/// @name Initialization +///--------------------- /** - + Initializes an `AFOAuth1Client` object with the specified base URL, key, and secret. + + @param url The base URL for the HTTP client. This argument must not be `nil`. + @param key The client key. + @param secret The client secret. */ -- (id)initWithKey:(NSString *)key - secret:(NSString *)secret - session:(NSString *)session - expiration:(NSDate *)expiration - renewable:(BOOL)canBeRenewed; +- (instancetype)initWithBaseURL:(NSURL *)url + key:(NSString *)key + secret:(NSString *)secret; -#ifdef _SECURITY_SECITEM_H_ ///--------------------- /// @name Authenticating ///--------------------- /** - Stores the specified OAuth token for a given web service identifier in the Keychain - with the default Keychain Accessibilty of kSecAttrAccessibleWhenUnlocked. + Perform some `NSURLSessionDataTask`s objects to make the necessary request token and access token requests using the specified parameters. - @param token The OAuth credential to be stored. - @param identifier The service identifier associated with the specified token. + @discussion This is a convenience for doing `acquireOAuthRequestTokenWithURLString:callbackURL:accessMethod:scope:success:failure` and then `acquireOAuthAccessTokenWithURLString:requestToken:accessMethod:success:failure:`. - @return Whether or not the credential was stored in the keychain. - */ -+ (BOOL)storeCredential:(AFOAuth1Token *)credential - withIdentifier:(NSString *)identifier; - -/** - Stores the specified OAuth token for a given web service identifier in the Keychain. - - @param token The OAuth credential to be stored. - @param identifier The service identifier associated with the specified token. - @param securityAccessibility The Keychain security accessibility to store the credential with. - - @return Whether or not the credential was stored in the keychain. - */ -+ (BOOL)storeCredential:(AFOAuth1Token *)credential - withIdentifier:(NSString *)identifier - withAccessibility:(id)securityAccessibility; - -/** - Retrieves the OAuth credential stored with the specified service identifier from the Keychain. + @param requestTokenURLString The request token URL string. + @param userAuthorizationURLString The user authorization URL string. + @param callbackURL The callback URL. + @param accessTokenURLString The URL string for requesting an access token. + @param accessMethod The HTTP method for requesting an access token. + @param scope The requested authorization scope. + @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the OAuth credential returned by the server, and the response object sent from the server. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error returned from the server. + */ +- (void)authorizeUsingOAuthWithRequestTokenURLString:(NSString *)requestTokenURLString + userAuthorizationURLString:(NSString *)userAuthorizationURLString + callbackURL:(NSURL *)callbackURL + accessTokenURLString:(NSString *)accessTokenURLString + accessMethod:(NSString *)accessMethod + scope:(NSString *)scope + success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success + failure:(void (^)(NSError *error))failure; + +/** + Performs a `NSURLSessionDataTask` to acquire an OAuth request token with the specified URL string, callback URL, access method, and scope. - @param identifier The service identifier associated with the specified credential. + @param URLString The URL string. + @param callbackURL The URL to be set for `oauth_callback`. If `nil`, "oob" (out-of-band) is specified. + @param accessMethod The HTTP method. + @param scope The requested authorization scope. + @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the OAuth credential returned by the server, and the response object sent from the server. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error returned from the server. + */ +- (NSURLSessionDataTask *)acquireOAuthRequestTokenWithURLString:(NSString *)URLString + callbackURL:(NSURL *)callbackURL + accessMethod:(NSString *)accessMethod + scope:(NSString *)scope + success:(void (^)(AFOAuth1Token *requestToken, id responseObject))success + failure:(void (^)(NSError *error))failure; + +/** + Performs a `NSURLSessionDataTask` to acquire an OAuth access token with the specified URL string, request token and access method. - @return The retrieved OAuth token. - */ -+ (AFOAuth1Token *)retrieveCredentialWithIdentifier:(NSString *)identifier; + @param URLString The URL string. + @param requestToken The request token. + @param accessMethod The HTTP method. + @param success A block object to be executed when the request operation finishes successfully. This block has no return value and takes two arguments: the OAuth credential returned by the server, and the response object sent from the server. + @param failure A block object to be executed when the request operation finishes unsuccessfully, or that finishes successfully, but encountered an error while parsing the response data. This block has no return value and takes a single argument: the error returned from the server. + */ +- (NSURLSessionDataTask *)acquireOAuthAccessTokenWithURLString:(NSString *)URLString + requestToken:(AFOAuth1Token *)requestToken + accessMethod:(NSString *)accessMethod + success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success + failure:(void (^)(NSError *error))failure; + +///---------------------------------------------------- +/// @name Configuring Service Provider Request Handling +///---------------------------------------------------- /** - Deletes the OAuth token stored with the specified service identifier from the Keychain. - - @param identifier The service identifier associated with the specified token. + Sets the service provider request handler and completion handler blocks. - @return Whether or not the token was deleted from the keychain. + @param block A block to be executed when the request is made to the service provider. This block has no return value and takes a single argument: the request made to the service provider. + @param completion A block to be executed when the request is finished. This block has no return value and takes no arguments. */ -+ (BOOL)deleteCredentialWithIdentifier:(NSString *)identifier; -#endif +- (void)setServiceProviderRequestHandler:(AFServiceProviderRequestHandlerBlock)block + completion:(AFServiceProviderRequestCompletionBlock)completion; @end diff --git a/AFOAuth1Client/AFOAuth1Client.m b/AFOAuth1Client/AFOAuth1Client.m index 886e9fc..24a99d3 100644 --- a/AFOAuth1Client/AFOAuth1Client.m +++ b/AFOAuth1Client/AFOAuth1Client.m @@ -1,6 +1,6 @@ // AFOAuth1Client.m // -// Copyright (c) 2011 Mattt Thompson (http://mattt.me/) +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -21,14 +21,12 @@ // THE SOFTWARE. #import "AFOAuth1Client.h" -#import "AFHTTPRequestOperation.h" -#import +#import "AFOAuth1RequestSerializer.h" +#import "AFOAuth1Token.h" +#import "AFOAuth1Utils.h" +#import "AFURLResponseSerialization.h" -typedef void (^AFServiceProviderRequestHandlerBlock)(NSURLRequest *request); -typedef void (^AFServiceProviderRequestCompletionBlock)(); - -static NSString * const kAFOAuth1Version = @"1.0"; NSString * const kAFApplicationLaunchedWithURLNotification = @"kAFApplicationLaunchedWithURLNotification"; #if __IPHONE_OS_VERSION_MIN_REQUIRED NSString * const kAFApplicationLaunchOptionsURLKey = @"UIApplicationLaunchOptionsURLKey"; @@ -36,285 +34,98 @@ NSString * const kAFApplicationLaunchOptionsURLKey = @"NSApplicationLaunchOptionsURLKey"; #endif -static NSString * AFEncodeBase64WithData(NSData *data) { - NSUInteger length = [data length]; - NSMutableData *mutableData = [NSMutableData dataWithLength:((length + 2) / 3) * 4]; - - uint8_t *input = (uint8_t *)[data bytes]; - uint8_t *output = (uint8_t *)[mutableData mutableBytes]; - - for (NSUInteger i = 0; i < length; i += 3) { - NSUInteger value = 0; - for (NSUInteger j = i; j < (i + 3); j++) { - value <<= 8; - if (j < length) { - value |= (0xFF & input[j]); - } - } - - static uint8_t const kAFBase64EncodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - NSUInteger idx = (i / 3) * 4; - output[idx + 0] = kAFBase64EncodingTable[(value >> 18) & 0x3F]; - output[idx + 1] = kAFBase64EncodingTable[(value >> 12) & 0x3F]; - output[idx + 2] = (i + 1) < length ? kAFBase64EncodingTable[(value >> 6) & 0x3F] : '='; - output[idx + 3] = (i + 2) < length ? kAFBase64EncodingTable[(value >> 0) & 0x3F] : '='; - } - - return [[NSString alloc] initWithData:mutableData encoding:NSASCIIStringEncoding]; -} - -static NSString * AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(NSString *string, NSStringEncoding encoding) { - static NSString * const kAFCharactersToBeEscaped = @":/?&=;+!@#$()',*"; - static NSString * const kAFCharactersToLeaveUnescaped = @"[]."; - - return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFCharactersToLeaveUnescaped, (__bridge CFStringRef)kAFCharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)); -} - -static NSDictionary * AFParametersFromQueryString(NSString *queryString) { - NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; - if (queryString) { - NSScanner *parameterScanner = [[NSScanner alloc] initWithString:queryString]; - NSString *name = nil; - NSString *value = nil; - - while (![parameterScanner isAtEnd]) { - name = nil; - [parameterScanner scanUpToString:@"=" intoString:&name]; - [parameterScanner scanString:@"=" intoString:NULL]; - - value = nil; - [parameterScanner scanUpToString:@"&" intoString:&value]; - [parameterScanner scanString:@"&" intoString:NULL]; - - if (name && value) { - parameters[[name stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]] = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - } - } - } - - return parameters; -} - -static inline BOOL AFQueryStringValueIsTrue(NSString *value) { - return value && [[value lowercaseString] hasPrefix:@"t"]; -} - -static inline NSString * AFNounce() { - CFUUIDRef uuid = CFUUIDCreate(NULL); - CFStringRef string = CFUUIDCreateString(NULL, uuid); - CFRelease(uuid); - - return (NSString *)CFBridgingRelease(string); -} - -static inline NSString * NSStringFromAFOAuthSignatureMethod(AFOAuthSignatureMethod signatureMethod) { - switch (signatureMethod) { - case AFPlainTextSignatureMethod: - return @"PLAINTEXT"; - case AFHMACSHA1SignatureMethod: - return @"HMAC-SHA1"; - default: - return nil; - } -} - -static inline NSString * AFPlainTextSignature(NSURLRequest *request, NSString *consumerSecret, NSString *tokenSecret, NSStringEncoding stringEncoding) { - NSString *secret = tokenSecret ? tokenSecret : @""; - NSString *signature = [NSString stringWithFormat:@"%@&%@", consumerSecret, secret]; - return signature; -} - -static inline NSString * AFHMACSHA1Signature(NSURLRequest *request, NSString *consumerSecret, NSString *tokenSecret, NSStringEncoding stringEncoding) { - NSString *secret = tokenSecret ? tokenSecret : @""; - NSString *secretString = [NSString stringWithFormat:@"%@&%@", AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(consumerSecret, stringEncoding), AFPercentEscapedQueryStringPairMemberFromStringWithEncoding(secret, stringEncoding)]; - NSData *secretStringData = [secretString dataUsingEncoding:stringEncoding]; - - NSString *queryString = AFPercentEscapedQueryStringPairMemberFromStringWithEncoding([[[[[request URL] query] componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(compare:)] componentsJoinedByString:@"&"], stringEncoding); - NSString *requestString = [NSString stringWithFormat:@"%@&%@&%@", [request HTTPMethod], AFPercentEscapedQueryStringPairMemberFromStringWithEncoding([[[request URL] absoluteString] componentsSeparatedByString:@"?"][0], stringEncoding), queryString]; - NSData *requestStringData = [requestString dataUsingEncoding:stringEncoding]; - - uint8_t digest[CC_SHA1_DIGEST_LENGTH]; - CCHmacContext cx; - CCHmacInit(&cx, kCCHmacAlgSHA1, [secretStringData bytes], [secretStringData length]); - CCHmacUpdate(&cx, [requestStringData bytes], [requestStringData length]); - CCHmacFinal(&cx, digest); - - return AFEncodeBase64WithData([NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH]); -} - -NSString * const kAFOAuth1CredentialServiceName = @"AFOAuthCredentialService"; - -static NSDictionary * AFKeychainQueryDictionaryWithIdentifier(NSString *identifier) { - return @{(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, - (__bridge id)kSecAttrAccount: identifier, - (__bridge id)kSecAttrService: kAFOAuth1CredentialServiceName - }; -} - #pragma mark - @interface AFOAuth1Client () -@property (readwrite, nonatomic, copy) NSString *key; -@property (readwrite, nonatomic, copy) NSString *secret; -@property (readwrite, nonatomic, strong) id applicationLaunchNotificationObserver; -@property (readwrite, nonatomic, copy) AFServiceProviderRequestHandlerBlock serviceProviderRequestHandler; -@property (readwrite, nonatomic, copy) AFServiceProviderRequestCompletionBlock serviceProviderRequestCompletion; - -- (NSDictionary *)OAuthParameters; -- (NSString *)OAuthSignatureForMethod:(NSString *)method - path:(NSString *)path - parameters:(NSDictionary *)parameters - token:(AFOAuth1Token *)requestToken; -- (NSString *)authorizationHeaderForMethod:(NSString*)method - path:(NSString*)path - parameters:(NSDictionary *)parameters; +@property (nonatomic, strong) id applicationLaunchNotificationObserver; +@property (nonatomic, copy) AFServiceProviderRequestHandlerBlock serviceProviderRequestHandler; +@property (nonatomic, copy) AFServiceProviderRequestCompletionBlock serviceProviderRequestCompletion; @end @implementation AFOAuth1Client -- (id)initWithBaseURL:(NSURL *)url - key:(NSString *)clientID - secret:(NSString *)secret -{ - NSParameterAssert(clientID); - NSParameterAssert(secret); - - self = [super initWithBaseURL:url]; - if (!self) { - return nil; - } - - self.key = clientID; - self.secret = secret; - - self.signatureMethod = AFHMACSHA1SignatureMethod; - - self.oauthAccessMethod = @"GET"; +#pragma mark - Properties - return self; -} - -- (void)dealloc { - self.applicationLaunchNotificationObserver = nil; ++ (BOOL)automaticallyNotifiesObserversOfApplicationLaunchNotificationObserver { + return NO; } - (void)setApplicationLaunchNotificationObserver:(id)applicationLaunchNotificationObserver { if (_applicationLaunchNotificationObserver) { [[NSNotificationCenter defaultCenter] removeObserver:_applicationLaunchNotificationObserver]; } - + [self willChangeValueForKey:@"applicationLaunchNotificationObserver"]; _applicationLaunchNotificationObserver = applicationLaunchNotificationObserver; [self didChangeValueForKey:@"applicationLaunchNotificationObserver"]; } -- (NSDictionary *)OAuthParameters { - NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; - parameters[@"oauth_version"] = kAFOAuth1Version; - parameters[@"oauth_signature_method"] = NSStringFromAFOAuthSignatureMethod(self.signatureMethod); - parameters[@"oauth_consumer_key"] = self.key; - parameters[@"oauth_timestamp"] = [@(floor([[NSDate date] timeIntervalSince1970])) stringValue]; - parameters[@"oauth_nonce"] = AFNounce(); - - if (self.realm) { - parameters[@"realm"] = self.realm; - } - - return parameters; -} - -- (NSString *)OAuthSignatureForMethod:(NSString *)method - path:(NSString *)path - parameters:(NSDictionary *)parameters - token:(AFOAuth1Token *)token -{ - NSMutableURLRequest *request = [super requestWithMethod:@"GET" path:path parameters:parameters]; - [request setHTTPMethod:method]; - - NSString *tokenSecret = token ? token.secret : nil; - - switch (self.signatureMethod) { - case AFPlainTextSignatureMethod: - return AFPlainTextSignature(request, self.secret, tokenSecret, self.stringEncoding); - case AFHMACSHA1SignatureMethod: - return AFHMACSHA1Signature(request, self.secret, tokenSecret, self.stringEncoding); - default: - return nil; - } -} - -- (NSString *)authorizationHeaderForMethod:(NSString *)method - path:(NSString *)path - parameters:(NSDictionary *)parameters -{ - static NSString * const kAFOAuth1AuthorizationFormatString = @"OAuth %@"; - - NSMutableDictionary *mutableParameters = parameters ? [parameters mutableCopy] : [NSMutableDictionary dictionary]; - NSMutableDictionary *mutableAuthorizationParameters = [NSMutableDictionary dictionary]; - - if (self.key && self.secret) { - [mutableAuthorizationParameters addEntriesFromDictionary:[self OAuthParameters]]; - if (self.accessToken) { - mutableAuthorizationParameters[@"oauth_token"] = self.accessToken.key; - } - } +#pragma mark - Object Life Cycle - [mutableParameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - if ([key isKindOfClass:[NSString class]] && [key hasPrefix:@"oauth_"]) { - mutableAuthorizationParameters[key] = obj; - } - }]; - - [mutableParameters addEntriesFromDictionary:mutableAuthorizationParameters]; - mutableAuthorizationParameters[@"oauth_signature"] = [self OAuthSignatureForMethod:method path:path parameters:mutableParameters token:self.accessToken]; +- (instancetype)initWithBaseURL:(NSURL *)URL + key:(NSString *)key + secret:(NSString *)secret { + NSParameterAssert(key); + NSParameterAssert(secret); - NSArray *sortedComponents = [[AFQueryStringFromParametersWithEncoding(mutableAuthorizationParameters, self.stringEncoding) componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)]; - NSMutableArray *mutableComponents = [NSMutableArray array]; - for (NSString *component in sortedComponents) { - NSArray *subcomponents = [component componentsSeparatedByString:@"="]; - if ([subcomponents count] == 2) { - [mutableComponents addObject:[NSString stringWithFormat:@"%@=\"%@\"", subcomponents[0], subcomponents[1]]]; - } + self = [super initWithBaseURL:URL]; + if (!self) { + return nil; } + + self.requestSerializer = [AFOAuth1RequestSerializer serializerWithKey:key secret:secret]; + self.responseSerializer = [AFHTTPResponseSerializer serializer]; // FIXME: (me@lxcid.com) Review to see whether we should introduce our own response serializer? + + return self; +} - return [NSString stringWithFormat:kAFOAuth1AuthorizationFormatString, [mutableComponents componentsJoinedByString:@", "]]; +- (void)dealloc { + self.applicationLaunchNotificationObserver = nil; } -#pragma mark - +#pragma mark - OAuth 1.0a -- (void)authorizeUsingOAuthWithRequestTokenPath:(NSString *)requestTokenPath - userAuthorizationPath:(NSString *)userAuthorizationPath - callbackURL:(NSURL *)callbackURL - accessTokenPath:(NSString *)accessTokenPath - accessMethod:(NSString *)accessMethod - scope:(NSString *)scope - success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success - failure:(void (^)(NSError *error))failure -{ - [self acquireOAuthRequestTokenWithPath:requestTokenPath callbackURL:callbackURL accessMethod:(NSString *)accessMethod scope:scope success:^(AFOAuth1Token *requestToken, id responseObject) { +- (void)authorizeUsingOAuthWithRequestTokenURLString:(NSString *)requestTokenURLString + userAuthorizationURLString:(NSString *)userAuthorizationURLString + callbackURL:(NSURL *)callbackURL + accessTokenURLString:(NSString *)accessTokenURLString + accessMethod:(NSString *)accessMethod + scope:(NSString *)scope + success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success + failure:(void (^)(NSError *error))failure { + NSURLSessionDataTask * __unused acquireOAuthRequestTokenTask = [self acquireOAuthRequestTokenWithURLString:requestTokenURLString callbackURL:callbackURL accessMethod:(NSString *)accessMethod scope:scope success:^(AFOAuth1Token *requestToken, id responseObject) { __block AFOAuth1Token *currentRequestToken = requestToken; - - self.applicationLaunchNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAFApplicationLaunchedWithURLNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { - NSURL *url = [[notification userInfo] valueForKey:kAFApplicationLaunchOptionsURLKey]; - - currentRequestToken.verifier = [AFParametersFromQueryString([url query]) valueForKey:@"oauth_verifier"]; - - [self acquireOAuthAccessTokenWithPath:accessTokenPath requestToken:currentRequestToken accessMethod:accessMethod success:^(AFOAuth1Token * accessToken, id responseObject) { + + NSNotificationCenter *defaultNotificationCenter = [NSNotificationCenter defaultCenter]; + self.applicationLaunchNotificationObserver = [defaultNotificationCenter addObserverForName:kAFApplicationLaunchedWithURLNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) { + NSURL *URL = [notification.userInfo valueForKey:kAFApplicationLaunchOptionsURLKey]; + + currentRequestToken.verifier = [[AFOAuth1Utils parametersFromQueryString:URL.query] valueForKey:@"oauth_verifier"]; + + NSURLSessionDataTask * __unused acquireOAuthAccessTokenTask = [self acquireOAuthAccessTokenWithURLString:accessTokenURLString requestToken:currentRequestToken accessMethod:accessMethod success:^(AFOAuth1Token * accessToken, id responseObject) { if (self.serviceProviderRequestCompletion) { self.serviceProviderRequestCompletion(); } self.applicationLaunchNotificationObserver = nil; if (accessToken) { - self.accessToken = accessToken; + if (![self.requestSerializer isKindOfClass:[AFOAuth1RequestSerializer class]]) { + if (failure) { + NSError *error = nil; // FIXME: (me@lxcid.com) Provides error info. + failure(error); + } + return; + } + AFOAuth1RequestSerializer *oauth1RequestSerializer = (AFOAuth1RequestSerializer *)self.requestSerializer; + oauth1RequestSerializer.accessToken = accessToken; if (success) { success(accessToken, responseObject); } } else { if (failure) { - failure(nil); + NSError *error = nil; // FIXME: (me@lxcid.com) Provides error info. + failure(error); } } } failure:^(NSError *error) { @@ -324,12 +135,19 @@ - (void)authorizeUsingOAuthWithRequestTokenPath:(NSString *)requestTokenPath } }]; }]; - - NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; - parameters[@"oauth_token"] = requestToken.key; - NSMutableURLRequest *request = [super requestWithMethod:@"GET" path:userAuthorizationPath parameters:parameters]; + + NSMutableDictionary *mutableParameters = [NSMutableDictionary dictionary]; + mutableParameters[@"oauth_token"] = requestToken.key; + NSError *error = nil; + NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] requestWithMethod:@"GET" URLString:[[NSURL URLWithString:userAuthorizationURLString relativeToURL:self.baseURL] absoluteString] parameters:mutableParameters error:&error]; + if (!request) { + if (failure) { + failure(error); + } + return; + } [request setHTTPShouldHandleCookies:NO]; - + if (self.serviceProviderRequestHandler) { self.serviceProviderRequestHandler(request); } else { @@ -347,365 +165,139 @@ - (void)authorizeUsingOAuthWithRequestTokenPath:(NSString *)requestTokenPath }]; } -- (void)acquireOAuthRequestTokenWithPath:(NSString *)path - callbackURL:(NSURL *)callbackURL - accessMethod:(NSString *)accessMethod - scope:(NSString *)scope - success:(void (^)(AFOAuth1Token *requestToken, id responseObject))success - failure:(void (^)(NSError *error))failure -{ - NSMutableDictionary *parameters = [[self OAuthParameters] mutableCopy]; - parameters[@"oauth_callback"] = [callbackURL absoluteString]; - if (scope && !self.accessToken) { - parameters[@"scope"] = scope; - } - - NSMutableURLRequest *request = [self requestWithMethod:accessMethod path:path parameters:parameters]; - [request setHTTPBody:nil]; - - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if (success) { - AFOAuth1Token *accessToken = [[AFOAuth1Token alloc] initWithQueryString:operation.responseString]; - success(accessToken, responseObject); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { +- (NSURLSessionDataTask *)acquireOAuthRequestTokenWithURLString:(NSString *)URLString + callbackURL:(NSURL *)callbackURL + accessMethod:(NSString *)accessMethod + scope:(NSString *)scope + success:(void (^)(AFOAuth1Token *requestToken, id responseObject))success + failure:(void (^)(NSError *error))failure { + if (![self.requestSerializer isKindOfClass:[AFOAuth1RequestSerializer class]]) { if (failure) { + NSError *error = nil; // FIXME: (me@lxcid.com) Provides error info. failure(error); } - }]; - - [self enqueueHTTPRequestOperation:operation]; -} - -- (void)acquireOAuthAccessTokenWithPath:(NSString *)path - requestToken:(AFOAuth1Token *)requestToken - accessMethod:(NSString *)accessMethod - success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success - failure:(void (^)(NSError *error))failure -{ - if (requestToken.key && requestToken.verifier) { - self.accessToken = requestToken; - - NSMutableDictionary *parameters = [[self OAuthParameters] mutableCopy]; - parameters[@"oauth_token"] = requestToken.key; - parameters[@"oauth_verifier"] = requestToken.verifier; - - NSMutableURLRequest *request = [self requestWithMethod:accessMethod path:path parameters:parameters]; - - AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if (success) { - AFOAuth1Token *accessToken = [[AFOAuth1Token alloc] initWithQueryString:operation.responseString]; - success(accessToken, responseObject); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) { - failure(error); - } - }]; - - [self enqueueHTTPRequestOperation:operation]; - } else { - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Bad OAuth response received from the server.", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey]; - NSError *error = [[NSError alloc] initWithDomain:AFNetworkingErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo]; - failure(error); + return nil; } -} - -#pragma mark - - -- (void)setServiceProviderRequestHandler:(void (^)(NSURLRequest *request))block - completion:(void (^)())completion -{ - self.serviceProviderRequestHandler = block; - self.serviceProviderRequestCompletion = completion; -} - -#pragma mark - AFHTTPClient - -- (NSMutableURLRequest *)requestWithMethod:(NSString *)method - path:(NSString *)path - parameters:(NSDictionary *)parameters -{ - NSMutableDictionary *mutableParameters = [parameters mutableCopy]; - for (NSString *key in parameters) { - if ([key hasPrefix:@"oauth_"]) { - [mutableParameters removeObjectForKey:key]; - } + AFOAuth1RequestSerializer *oauth1RequestSerializer = (AFOAuth1RequestSerializer *)self.requestSerializer; + + NSMutableDictionary *mutableParameters = [oauth1RequestSerializer.oauthParameters mutableCopy]; + if (callbackURL) { + mutableParameters[@"oauth_callback"] = [callbackURL absoluteString]; + } else { + mutableParameters[@"oauth_callback"] = @"oob"; } - - NSMutableURLRequest *request = [super requestWithMethod:method path:path parameters:mutableParameters]; - - // Only use parameters in the request entity body (with a content-type of `application/x-www-form-urlencoded`). - // See RFC 5849, Section 3.4.1.3.1 http://tools.ietf.org/html/rfc5849#section-3.4 - NSDictionary *authorizationParameters = parameters; - if (!([method isEqualToString:@"GET"] || [method isEqualToString:@"HEAD"] || [method isEqualToString:@"DELETE"])) { - authorizationParameters = ([[request valueForHTTPHeaderField:@"Content-Type"] hasPrefix:@"application/x-www-form-urlencoded"] ? parameters : nil); + if (scope && scope.length > 0 && !oauth1RequestSerializer.accessToken) { + mutableParameters[@"scope"] = scope; } - [request setValue:[self authorizationHeaderForMethod:method path:path parameters:authorizationParameters] forHTTPHeaderField:@"Authorization"]; - [request setHTTPShouldHandleCookies:NO]; - - return request; -} - -- (NSMutableURLRequest *)multipartFormRequestWithMethod:(NSString *)method - path:(NSString *)path - parameters:(NSDictionary *)parameters - constructingBodyWithBlock:(void (^)(id formData))block -{ - NSMutableURLRequest *request = [super multipartFormRequestWithMethod:method path:path parameters:parameters constructingBodyWithBlock:block]; - - // Only use parameters in the HTTP POST request body (with a content-type of `application/x-www-form-urlencoded`). - // See RFC 5849, Section 3.4.1.3.1 http://tools.ietf.org/html/rfc5849#section-3.4 - NSDictionary *authorizationParameters = ([[request valueForHTTPHeaderField:@"Content-Type"] hasPrefix:@"application/x-www-form-urlencoded"] ? parameters : nil); - [request setValue:[self authorizationHeaderForMethod:method path:path parameters:authorizationParameters] forHTTPHeaderField:@"Authorization"]; - [request setHTTPShouldHandleCookies:NO]; - - return request; -} - -#pragma mark - NSCoding - -- (id)initWithCoder:(NSCoder *)decoder { - self = [super initWithCoder:decoder]; - if (!self) { + NSDictionary *parameters = [mutableParameters copy]; + NSError *error = nil; + NSMutableURLRequest *request = [oauth1RequestSerializer requestWithMethod:accessMethod URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&error]; + if (error) { + if (failure) { + failure(error); + } return nil; } - - self.key = [decoder decodeObjectForKey:NSStringFromSelector(@selector(key))]; - self.secret = [decoder decodeObjectForKey:NSStringFromSelector(@selector(secret))]; - self.signatureMethod = (AFOAuthSignatureMethod)[decoder decodeIntegerForKey:NSStringFromSelector(@selector(signatureMethod))]; - self.realm = [decoder decodeObjectForKey:NSStringFromSelector(@selector(realm))]; - self.accessToken = [decoder decodeObjectForKey:NSStringFromSelector(@selector(accessToken))]; - self.oauthAccessMethod = [decoder decodeObjectForKey:NSStringFromSelector(@selector(oauthAccessMethod))]; - - return self; -} - -- (void)encodeWithCoder:(NSCoder *)coder { - [super encodeWithCoder:coder]; - [coder encodeObject:self.key forKey:NSStringFromSelector(@selector(key))]; - [coder encodeObject:self.secret forKey:NSStringFromSelector(@selector(secret))]; - [coder encodeInteger:self.signatureMethod forKey:NSStringFromSelector(@selector(signatureMethod))]; - [coder encodeObject:self.realm forKey:NSStringFromSelector(@selector(realm))]; - [coder encodeObject:self.accessToken forKey:NSStringFromSelector(@selector(accessToken))]; - [coder encodeObject:self.oauthAccessMethod forKey:NSStringFromSelector(@selector(oauthAccessMethod))]; -} - -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone { - AFOAuth1Client *copy = [[[self class] allocWithZone:zone] initWithBaseURL:self.baseURL key:self.key secret:self.secret]; - copy.signatureMethod = self.signatureMethod; - copy.realm = self.realm; - copy.accessToken = self.accessToken; - copy.oauthAccessMethod = self.oauthAccessMethod; - - return copy; + NSURLSessionDataTask *dataTask = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { + if (error) { + if (failure) { + failure(error); + } + return; + } + + if (success) { + NSStringEncoding stringEncoding = NSUTF8StringEncoding; + if (response.textEncodingName) { + CFStringRef cfTextEncodingName = (__bridge CFStringRef)response.textEncodingName; + CFStringEncoding cfStringEncoding = CFStringConvertIANACharSetNameToEncoding(cfTextEncodingName); + if (cfStringEncoding != kCFStringEncodingInvalidId) { + stringEncoding = CFStringConvertEncodingToNSStringEncoding(cfStringEncoding); + } + } + NSString *queryString = [[NSString alloc] initWithData:responseObject encoding:stringEncoding]; + AFOAuth1Token *accessToken = [[AFOAuth1Token alloc] initWithQueryString:queryString]; + success(accessToken, responseObject); + } + }]; + [dataTask resume]; + return dataTask; } -@end - -#pragma mark - - -@interface AFOAuth1Token () -@property (readwrite, nonatomic, copy) NSString *key; -@property (readwrite, nonatomic, copy) NSString *secret; -@property (readwrite, nonatomic, copy) NSString *session; -@property (readwrite, nonatomic, strong) NSDate *expiration; -@property (readwrite, nonatomic, assign, getter = canBeRenewed) BOOL renewable; -@end - -@implementation AFOAuth1Token - -- (id)initWithQueryString:(NSString *)queryString { - if (!queryString || [queryString length] == 0) { +- (NSURLSessionDataTask *)acquireOAuthAccessTokenWithURLString:(NSString *)URLString + requestToken:(AFOAuth1Token *)requestToken + accessMethod:(NSString *)accessMethod + success:(void (^)(AFOAuth1Token *accessToken, id responseObject))success + failure:(void (^)(NSError *error))failure { + if (![self.requestSerializer isKindOfClass:[AFOAuth1RequestSerializer class]]) { + if (failure) { + NSError *error = nil; // FIXME: (me@lxcid.com) Provides error info. + failure(error); + } return nil; } - - NSDictionary *attributes = AFParametersFromQueryString(queryString); - if ([attributes count] == 0) { + AFOAuth1RequestSerializer *oauth1RequestSerializer = (AFOAuth1RequestSerializer *)self.requestSerializer; + if (!requestToken.key) { + NSDictionary *userInfo = [NSDictionary dictionaryWithObject:NSLocalizedStringFromTable(@"Bad OAuth response received from the server.", @"AFNetworking", nil) forKey:NSLocalizedFailureReasonErrorKey]; + NSError *error = [[NSError alloc] initWithDomain:AFURLResponseSerializationErrorDomain code:NSURLErrorBadServerResponse userInfo:userInfo]; + if (failure) { + failure(error); + } return nil; } - - NSString *key = attributes[@"oauth_token"]; - NSString *secret = attributes[@"oauth_token_secret"]; - NSString *session = attributes[@"oauth_session_handle"]; - NSDate *expiration = nil; - if (attributes[@"oauth_token_duration"]) { - expiration = [NSDate dateWithTimeIntervalSinceNow:[attributes[@"oauth_token_duration"] doubleValue]]; - } - - BOOL canBeRenewed = NO; - if (attributes[@"oauth_token_renewable"]) { - canBeRenewed = AFQueryStringValueIsTrue(attributes[@"oauth_token_renewable"]); - } - - self = [self initWithKey:key secret:secret session:session expiration:expiration renewable:canBeRenewed]; - if (!self) { - return nil; - } - - NSMutableDictionary *mutableUserInfo = [attributes mutableCopy]; - [mutableUserInfo removeObjectsForKeys:@[@"oauth_token", @"oauth_token_secret", @"oauth_session_handle", @"oauth_token_duration", @"oauth_token_renewable"]]; - - if ([mutableUserInfo count] > 0) { - self.userInfo = [NSDictionary dictionaryWithDictionary:mutableUserInfo]; - } - - return self; -} - -- (id)initWithKey:(NSString *)key - secret:(NSString *)secret - session:(NSString *)session - expiration:(NSDate *)expiration - renewable:(BOOL)canBeRenewed -{ - NSParameterAssert(key); - NSParameterAssert(secret); - - self = [super init]; - if (!self) { - return nil; - } - - self.key = key; - self.secret = secret; - self.session = session; - self.expiration = expiration; - self.renewable = canBeRenewed; + oauth1RequestSerializer.accessToken = requestToken; - return self; -} - -- (BOOL)isExpired{ - return [self.expiration compare:[NSDate date]] == NSOrderedAscending; -} - -#pragma mark - - -+ (AFOAuth1Token *)retrieveCredentialWithIdentifier:(NSString *)identifier { - NSMutableDictionary *mutableQueryDictionary = [AFKeychainQueryDictionaryWithIdentifier(identifier) mutableCopy]; - mutableQueryDictionary[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; - mutableQueryDictionary[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; - - CFDataRef result = nil; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)mutableQueryDictionary, (CFTypeRef *)&result); - - if (status != errSecSuccess) { - NSLog(@"Unable to fetch credential with identifier \"%@\" (Error %li)", identifier, (long int)status); - return nil; + NSMutableDictionary *mutableParameters = [oauth1RequestSerializer.oauthParameters mutableCopy]; + mutableParameters[@"oauth_token"] = requestToken.key; + if (requestToken.verifier) { + mutableParameters[@"oauth_verifier"] = requestToken.verifier; } - - NSData *data = (__bridge_transfer NSData *)result; - AFOAuth1Token *credential = [NSKeyedUnarchiver unarchiveObjectWithData:data]; - - return credential; -} - -+ (BOOL)deleteCredentialWithIdentifier:(NSString *)identifier { - NSMutableDictionary *mutableQueryDictionary = [AFKeychainQueryDictionaryWithIdentifier(identifier) mutableCopy]; - - OSStatus status = SecItemDelete((__bridge CFDictionaryRef)mutableQueryDictionary); - - if (status != errSecSuccess) { - NSLog(@"Unable to delete credential with identifier \"%@\" (Error %li)", identifier, (long int)status); - } - - return (status == errSecSuccess); -} - -+ (BOOL)storeCredential:(AFOAuth1Token *)credential - withIdentifier:(NSString *)identifier -{ - id securityAccessibility = nil; -#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 43000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) - securityAccessibility = (__bridge id)kSecAttrAccessibleWhenUnlocked; -#endif - return [[self class] storeCredential:credential withIdentifier:identifier withAccessibility:securityAccessibility]; -} - -+ (BOOL)storeCredential:(AFOAuth1Token *)credential - withIdentifier:(NSString *)identifier - withAccessibility:(id)securityAccessibility -{ - NSMutableDictionary *mutableQueryDictionary = [AFKeychainQueryDictionaryWithIdentifier(identifier) mutableCopy]; - - if (!credential) { - return [self deleteCredentialWithIdentifier:identifier]; - } - - NSMutableDictionary *mutableUpdateDictionary = [NSMutableDictionary dictionary]; - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:credential]; - mutableUpdateDictionary[(__bridge id)kSecValueData] = data; - if (securityAccessibility) { - [mutableUpdateDictionary setObject:securityAccessibility forKey:(__bridge id)kSecAttrAccessible]; - } - - OSStatus status; - BOOL exists = !![self retrieveCredentialWithIdentifier:identifier]; - - if (exists) { - status = SecItemUpdate((__bridge CFDictionaryRef)mutableQueryDictionary, (__bridge CFDictionaryRef)mutableUpdateDictionary); - } else { - [mutableQueryDictionary addEntriesFromDictionary:mutableUpdateDictionary]; - status = SecItemAdd((__bridge CFDictionaryRef)mutableQueryDictionary, NULL); - } - - if (status != errSecSuccess) { - NSLog(@"Unable to %@ credential with identifier \"%@\" (Error %li)", exists ? @"update" : @"add", identifier, (long int)status); - } - - return (status == errSecSuccess); -} - -#pragma mark - NSCoding - -- (id)initWithCoder:(NSCoder *)decoder { - self = [super init]; - if (!self) { + NSDictionary *parameters = [mutableParameters copy]; + NSError *error = nil; + NSMutableURLRequest *request = [oauth1RequestSerializer requestWithMethod:accessMethod URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&error]; + if (error) { + if (failure) { + failure(error); + } return nil; } - - self.key = [decoder decodeObjectForKey:NSStringFromSelector(@selector(key))]; - self.secret = [decoder decodeObjectForKey:NSStringFromSelector(@selector(secret))]; - self.session = [decoder decodeObjectForKey:NSStringFromSelector(@selector(session))]; - self.verifier = [decoder decodeObjectForKey:NSStringFromSelector(@selector(verifier))]; - self.expiration = [decoder decodeObjectForKey:NSStringFromSelector(@selector(expiration))]; - self.renewable = [decoder decodeBoolForKey:NSStringFromSelector(@selector(renewable))]; - self.userInfo = [decoder decodeObjectForKey:NSStringFromSelector(@selector(userInfo))]; - - return self; -} - -- (void)encodeWithCoder:(NSCoder *)coder { - [coder encodeObject:self.key forKey:NSStringFromSelector(@selector(key))]; - [coder encodeObject:self.secret forKey:NSStringFromSelector(@selector(secret))]; - [coder encodeObject:self.session forKey:NSStringFromSelector(@selector(session))]; - [coder encodeObject:self.verifier forKey:NSStringFromSelector(@selector(verifier))]; - [coder encodeObject:self.expiration forKey:NSStringFromSelector(@selector(expiration))]; - [coder encodeBool:self.renewable forKey:NSStringFromSelector(@selector(renewable))]; - [coder encodeObject:self.userInfo forKey:NSStringFromSelector(@selector(userInfo))]; + NSURLSessionDataTask *dataTask = [self dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { + if (error) { + if (failure) { + failure(error); + } + return; + } + + if (success) { + NSStringEncoding stringEncoding = NSUTF8StringEncoding; + if (response.textEncodingName) { + CFStringRef cfTextEncodingName = (__bridge CFStringRef)response.textEncodingName; + CFStringEncoding cfStringEncoding = CFStringConvertIANACharSetNameToEncoding(cfTextEncodingName); + if (cfStringEncoding != kCFStringEncodingInvalidId) { + stringEncoding = CFStringConvertEncodingToNSStringEncoding(cfStringEncoding); + } + } + NSString *queryString = [[NSString alloc] initWithData:responseObject encoding:stringEncoding]; + AFOAuth1Token *accessToken = [[AFOAuth1Token alloc] initWithQueryString:queryString]; + success(accessToken, responseObject); + } + }]; + [dataTask resume]; + return dataTask; } -#pragma mark - NSCopying - -- (id)copyWithZone:(NSZone *)zone { - AFOAuth1Token *copy = [[[self class] allocWithZone:zone] init]; - copy.key = self.key; - copy.secret = self.secret; - copy.session = self.session; - copy.verifier = self.verifier; - copy.expiration = self.expiration; - copy.renewable = self.renewable; - copy.userInfo = self.userInfo; +#pragma mark - Configuring Service Provider Request Handling - return copy; +- (void)setServiceProviderRequestHandler:(AFServiceProviderRequestHandlerBlock)block + completion:(AFServiceProviderRequestCompletionBlock)completion { + self.serviceProviderRequestHandler = block; + self.serviceProviderRequestCompletion = completion; } @end diff --git a/AFOAuth1Client/AFOAuth1RequestSerializer.h b/AFOAuth1Client/AFOAuth1RequestSerializer.h new file mode 100644 index 0000000..cd38920 --- /dev/null +++ b/AFOAuth1Client/AFOAuth1RequestSerializer.h @@ -0,0 +1,66 @@ +// AFOAuth1RequestSerializer.h +// +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "AFURLRequestSerialization.h" + +@class AFOAuth1Token; + +typedef NS_ENUM(NSUInteger, AFOAuth1SignatureMethod) { + AFOAuth1PlainTextSignatureMethod = 1, + AFOAuth1HMACSHA1SignatureMethod = 2, +}; + +@interface AFOAuth1RequestSerializer : AFHTTPRequestSerializer + +///----------------------------------- +/// @name Managing OAuth Configuration +///----------------------------------- + +/** + The method used to create an OAuth signature. `AFPlainTextSignatureMethod` by default. + */ +@property (nonatomic, assign) AFOAuth1SignatureMethod signatureMethod; + +/** + The authentication realm. + */ +@property (nonatomic, copy) NSString *realm; + +/** + The client's access token. + */ +@property (nonatomic, strong) AFOAuth1Token *accessToken; + +/** + + */ +@property (nonatomic, copy, readonly) NSDictionary *oauthParameters; + +/** + Instantiates an `AFOAuth1RequestSerializer` object with the specified key, and secret. + + @param key The client key. + @param secret The client secret. + */ ++ (instancetype)serializerWithKey:(NSString *)key secret:(NSString *)secret; + +@end diff --git a/AFOAuth1Client/AFOAuth1RequestSerializer.m b/AFOAuth1Client/AFOAuth1RequestSerializer.m new file mode 100644 index 0000000..86c8a56 --- /dev/null +++ b/AFOAuth1Client/AFOAuth1RequestSerializer.m @@ -0,0 +1,243 @@ +// AFOAuth1RequestSerializer.m +// +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "AFOAuth1RequestSerializer.h" + +#import + +#import "AFOAuth1Token.h" +#import "AFOAuth1Utils.h" + +static NSString * const kAFOAuth1Version = @"1.0"; + +static inline NSString * AFOAuth1Nounce() { + CFUUIDRef uuid = CFUUIDCreate(NULL); + CFStringRef string = CFUUIDCreateString(NULL, uuid); + CFRelease(uuid); + return (NSString *)CFBridgingRelease(string); +} + +static inline NSString * NSStringFromAFOAuth1SignatureMethod(AFOAuth1SignatureMethod signatureMethod) { + switch (signatureMethod) { + case AFOAuth1PlainTextSignatureMethod: { + return @"PLAINTEXT"; + } break; + case AFOAuth1HMACSHA1SignatureMethod: { + return @"HMAC-SHA1"; + } break; + default: { + [NSException raise:NSInternalInconsistencyException format:@"Unknown OAuth 1.0a Signature Method: %lu", (unsigned long)signatureMethod]; + return nil; + } break; + } +} + +static inline NSString * AFOAuth1PlainTextSignature(NSURLRequest *request, NSString *consumerSecret, NSString *tokenSecret, NSStringEncoding stringEncoding) { + NSString *secret = tokenSecret ? tokenSecret : @""; + NSString *signature = [NSString stringWithFormat:@"%@&%@", consumerSecret, secret]; + return signature; +} + +static inline NSString * AFOAuth1HMACSHA1Signature(NSURLRequest *request, NSString *consumerSecret, NSString *tokenSecret, NSStringEncoding stringEncoding) { + NSString *secret = tokenSecret ? tokenSecret : @""; + NSString *secretString = [NSString stringWithFormat:@"%@&%@", [AFOAuth1Utils percentEscapedQueryStringPairMemberFromString:consumerSecret withEncoding:stringEncoding], [AFOAuth1Utils percentEscapedQueryStringPairMemberFromString:secret withEncoding:stringEncoding]]; + NSData *secretStringData = [secretString dataUsingEncoding:stringEncoding]; + + NSString *queryString = [AFOAuth1Utils percentEscapedQueryStringPairMemberFromString:[AFOAuth1Utils sortedQueryString:request.URL.query] withEncoding:stringEncoding]; + NSString *urlWithoutQueryString = [AFOAuth1Utils percentEscapedQueryStringPairMemberFromString:[request.URL.absoluteString componentsSeparatedByString:@"?"][0] withEncoding:stringEncoding]; + NSString *requestString = [NSString stringWithFormat:@"%@&%@&%@", request.HTTPMethod, urlWithoutQueryString, queryString]; + NSData *requestStringData = [requestString dataUsingEncoding:stringEncoding]; + + uint8_t digest[CC_SHA1_DIGEST_LENGTH]; + CCHmacContext cx; + CCHmacInit(&cx, kCCHmacAlgSHA1, secretStringData.bytes, secretStringData.length); + CCHmacUpdate(&cx, requestStringData.bytes, requestStringData.length); + CCHmacFinal(&cx, digest); + + return [[NSData dataWithBytes:digest length:CC_SHA1_DIGEST_LENGTH] base64EncodedStringWithOptions:0]; +} + +@interface AFOAuth1RequestSerializer () + +@property (nonatomic, copy) NSString *key; +@property (nonatomic, copy) NSString *secret; + +@end + +@implementation AFOAuth1RequestSerializer + ++ (instancetype)serializerWithKey:(NSString *)key secret:(NSString *)secret { + NSParameterAssert(key); + NSParameterAssert(secret); + + AFOAuth1RequestSerializer *serializer = [self serializer]; + serializer.key = key; + serializer.secret = secret; + serializer.signatureMethod = AFOAuth1HMACSHA1SignatureMethod; + + return serializer; +} + +- (NSDictionary *)oauthParameters { + NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init]; + parameters[@"oauth_version"] = kAFOAuth1Version; + parameters[@"oauth_signature_method"] = NSStringFromAFOAuth1SignatureMethod(self.signatureMethod); + parameters[@"oauth_consumer_key"] = self.key; + parameters[@"oauth_timestamp"] = [NSString stringWithFormat:@"%.0f", [[NSDate date] timeIntervalSince1970]]; + parameters[@"oauth_nonce"] = AFOAuth1Nounce(); + if (self.realm) { + parameters[@"realm"] = self.realm; + } + return [parameters copy]; +} + +- (NSString *)oauthSignatureForMethod:(NSString *)method URLString:(NSString *)URLString parameters:(NSDictionary *)parameters token:(AFOAuth1Token *)token error:(NSError * __autoreleasing *)error { + NSMutableURLRequest *request = [super requestWithMethod:@"GET" URLString:URLString parameters:parameters error:error]; + if (!request) { + return nil; + } + [request setHTTPMethod:method]; + + NSString *tokenSecret = token ? token.secret : nil; + + switch (self.signatureMethod) { + case AFOAuth1PlainTextSignatureMethod: { + return AFOAuth1PlainTextSignature(request, self.secret, tokenSecret, self.stringEncoding); + } break; + case AFOAuth1HMACSHA1SignatureMethod: { + return AFOAuth1HMACSHA1Signature(request, self.secret, tokenSecret, self.stringEncoding); + } break; + default: { + [NSException raise:NSInternalInconsistencyException format:@"Unknown OAuth 1.0a Signature Method: %lu", (unsigned long)self.signatureMethod]; + return nil; + } break; + } +} + +- (NSString *)authorizationHeaderForMethod:(NSString *)method URLString:(NSString *)URLString parameters:(NSDictionary *)parameters error:(NSError * __autoreleasing *)error { + NSMutableDictionary *mutableParameters = parameters ? [parameters mutableCopy] : [NSMutableDictionary dictionary]; + NSMutableDictionary *mutableAuthorizationParameters = [NSMutableDictionary dictionary]; + + if (self.key && self.secret) { + [mutableAuthorizationParameters addEntriesFromDictionary:self.oauthParameters]; + if (self.accessToken) { + mutableAuthorizationParameters[@"oauth_token"] = self.accessToken.key; + } + } + + [mutableParameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + if ([key isKindOfClass:[NSString class]] && [key hasPrefix:@"oauth_"]) { + mutableAuthorizationParameters[key] = obj; + } + }]; + + [mutableParameters addEntriesFromDictionary:mutableAuthorizationParameters]; + NSString *oauthSignature = [self oauthSignatureForMethod:method URLString:URLString parameters:mutableParameters token:self.accessToken error:error]; + if (!oauthSignature) { + return nil; + } + mutableAuthorizationParameters[@"oauth_signature"] = oauthSignature; + + NSArray *sortedQueryItems = [AFOAuth1Utils sortedQueryItemsFromParameters:mutableAuthorizationParameters]; + NSMutableArray *mutableComponents = [NSMutableArray array]; + for (NSArray *queryItem in sortedQueryItems) { + if (queryItem.count == 2) { + NSString *key = [AFOAuth1Utils percentEscapedQueryStringPairMemberFromString:queryItem[0] withEncoding:self.stringEncoding]; + NSString *value = [AFOAuth1Utils percentEscapedQueryStringPairMemberFromString:queryItem[1] withEncoding:self.stringEncoding]; + NSString *component = [NSString stringWithFormat:@"%@=\"%@\"", key, value]; + [mutableComponents addObject:component]; + } + } + + return [NSString stringWithFormat:@"OAuth %@", [mutableComponents componentsJoinedByString:@", "]]; +} + +#pragma mark - + +- (NSMutableURLRequest *)requestWithMethod:(NSString *)method URLString:(NSString *)URLString parameters:(id)parameters error:(NSError *__autoreleasing *)error { + NSMutableDictionary *mutableParameters = [parameters mutableCopy]; + for (NSString *key in parameters) { + if ([key hasPrefix:@"oauth_"]) { + [mutableParameters removeObjectForKey:key]; + } + } + + NSMutableURLRequest *request = [super requestWithMethod:method URLString:URLString parameters:mutableParameters error:error]; + if (!request) { + return nil; + } + + // Only use parameters in the request entity body (with a content-type of `application/x-www-form-urlencoded`). + // See RFC 5849, Section 3.4.1.3.1 http://tools.ietf.org/html/rfc5849#section-3.4 + NSDictionary *authorizationParameters = parameters; + if (!([method isEqualToString:@"GET"] || [method isEqualToString:@"HEAD"] || [method isEqualToString:@"DELETE"])) { + authorizationParameters = ([[request valueForHTTPHeaderField:@"Content-Type"] hasPrefix:@"application/x-www-form-urlencoded"] ? parameters : nil); + } + + NSString *authorizationHeader = [self authorizationHeaderForMethod:method URLString:URLString parameters:authorizationParameters error:error]; + if (!authorizationHeader) { + return nil; + } + [request setValue:authorizationHeader forHTTPHeaderField:@"Authorization"]; + [request setHTTPShouldHandleCookies:NO]; + + return request; +} + +#pragma mark - NSCoding + +- (instancetype)initWithCoder:(NSCoder *)decoder { + self = [super init]; + if (!self) { + return nil; + } + + _key = [decoder decodeObjectForKey:NSStringFromSelector(@selector(key))]; + _secret = [decoder decodeObjectForKey:NSStringFromSelector(@selector(secret))]; + _signatureMethod = [[decoder decodeObjectForKey:NSStringFromSelector(@selector(signatureMethod))] unsignedIntegerValue]; + _realm = [decoder decodeObjectForKey:NSStringFromSelector(@selector(realm))]; + _accessToken = [decoder decodeObjectForKey:NSStringFromSelector(@selector(accessToken))]; + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.key forKey:NSStringFromSelector(@selector(key))]; + [coder encodeObject:self.secret forKey:NSStringFromSelector(@selector(secret))]; + [coder encodeObject:@(self.signatureMethod) forKey:NSStringFromSelector(@selector(signatureMethod))]; + [coder encodeObject:self.realm forKey:NSStringFromSelector(@selector(realm))]; + [coder encodeObject:self.accessToken forKey:NSStringFromSelector(@selector(accessToken))]; +} + +#pragma mark - NSCopying + +- (instancetype)copyWithZone:(NSZone *)zone { + AFOAuth1RequestSerializer *copy = [[[self class] allocWithZone:zone] init]; + copy->_key = [self.key copyWithZone:zone]; + copy->_secret = [self.secret copyWithZone:zone]; + copy->_signatureMethod = self.signatureMethod; + copy->_realm = [self.realm copyWithZone:zone]; + copy->_accessToken = [self.accessToken copyWithZone:zone]; + return copy; +} + +@end diff --git a/AFOAuth1Client/AFOAuth1Token.h b/AFOAuth1Client/AFOAuth1Token.h new file mode 100644 index 0000000..8737479 --- /dev/null +++ b/AFOAuth1Client/AFOAuth1Token.h @@ -0,0 +1,136 @@ +// AFOAuth1Token.h +// +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +/** + `AFOAuth1Token` models the credentials returned from an OAuth server, storing the key, secret, session, verifier, and whether the token is expired and can be renewed. + + OAuth credentials can be stored in the user's keychain, and retrieved on subsequent launches. + */ +@interface AFOAuth1Token : NSObject + +/** + The OAuth token key. + */ +@property (readonly, nonatomic, copy) NSString *key; + +/** + The OAuth token secret. + */ +@property (readonly, nonatomic, copy) NSString *secret; + +/** + The OAuth token session. + */ +@property (readonly, nonatomic, copy) NSString *session; + +/** + The OAuth token verifier. + */ +@property (nonatomic, copy) NSString *verifier; + +/** + Whether the OAuth token can be renewed. + */ +@property (readonly, nonatomic, assign, getter = canBeRenewed) BOOL renewable; + +/** + Whether the OAuth token is expired. + */ +@property (readonly, nonatomic, assign, getter = isExpired) BOOL expired; + +/** + Any additional information associated with the OAuth token. + */ +@property (nonatomic, strong) NSDictionary *userInfo; + +/** + Initialize an OAuth token from a URL query string. + + @param queryString The query of a URL containing the OAuth token credentials. + */ +- (instancetype)initWithQueryString:(NSString *)queryString; + +/** + Initializes an OAuth token with the specified key, secret, session, and expiration date. + + @param key The OAuth token key. + @param secret The OAuth token secret. + @param session The OAuth token session. + @param expiration The OAuth token expiration date + @param renewable Whether the OAuth token can be renewed. + */ +- (instancetype)initWithKey:(NSString *)key + secret:(NSString *)secret + session:(NSString *)session + expiration:(NSDate *)expiration + renewable:(BOOL)canBeRenewed; + +///--------------------- +/// @name Authenticating +///--------------------- + +/** + Stores the specified OAuth token for a given web service identifier in the Keychain + with the default Keychain Accessibilty of kSecAttrAccessibleWhenUnlocked. + + @param token The OAuth credential to be stored. + @param identifier The service identifier associated with the specified token. + + @return Whether or not the credential was stored in the keychain. + */ ++ (BOOL)storeCredential:(AFOAuth1Token *)credential + withIdentifier:(NSString *)identifier; + +/** + Stores the specified OAuth token for a given web service identifier in the Keychain. + + @param token The OAuth credential to be stored. + @param identifier The service identifier associated with the specified token. + @param securityAccessibility The Keychain security accessibility to store the credential with. + + @return Whether or not the credential was stored in the keychain. + */ ++ (BOOL)storeCredential:(AFOAuth1Token *)credential + withIdentifier:(NSString *)identifier + withAccessibility:(id)securityAccessibility; + +/** + Retrieves the OAuth credential stored with the specified service identifier from the Keychain. + + @param identifier The service identifier associated with the specified credential. + + @return The retrieved OAuth token. + */ ++ (AFOAuth1Token *)retrieveCredentialWithIdentifier:(NSString *)identifier; + +/** + Deletes the OAuth token stored with the specified service identifier from the Keychain. + + @param identifier The service identifier associated with the specified token. + + @return Whether or not the token was deleted from the keychain. + */ ++ (BOOL)deleteCredentialWithIdentifier:(NSString *)identifier; + +@end diff --git a/AFOAuth1Client/AFOAuth1Token.m b/AFOAuth1Client/AFOAuth1Token.m new file mode 100644 index 0000000..c76d4f6 --- /dev/null +++ b/AFOAuth1Client/AFOAuth1Token.m @@ -0,0 +1,231 @@ +// AFOAuth1Token.m +// +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "AFOAuth1Token.h" + +#import + +#import "AFOAuth1Utils.h" + +static NSString * const kAFOAuth1CredentialServiceName = @"AFOAuth1CredentialService"; + +@interface AFOAuth1Token () +@property (nonatomic, copy) NSString *key; +@property (nonatomic, copy) NSString *secret; +@property (nonatomic, copy) NSString *session; +@property (nonatomic, strong) NSDate *expiration; +@property (nonatomic, assign, getter = canBeRenewed) BOOL renewable; +@end + +@implementation AFOAuth1Token + +- (instancetype)initWithQueryString:(NSString *)queryString { + if (!queryString || queryString.length == 0) { + return nil; + } + + NSDictionary *parameters = [AFOAuth1Utils parametersFromQueryString:queryString]; + + if (parameters.count == 0) { + return nil; + } + + NSString *key = parameters[@"oauth_token"]; + NSString *secret = parameters[@"oauth_token_secret"]; + NSString *session = parameters[@"oauth_session_handle"]; + + NSDate *expiration = nil; + NSString *tokenDuration = parameters[@"oauth_token_duration"]; + if (tokenDuration) { + expiration = [NSDate dateWithTimeIntervalSinceNow:[tokenDuration doubleValue]]; + } + + BOOL canBeRenewed = NO; + NSString *tokenRenewable = parameters[@"oauth_token_renewable"]; + if (tokenDuration) { + canBeRenewed = [AFOAuth1Utils isQueryStringValueTrue:tokenRenewable]; + } + + self = [self initWithKey:key secret:secret session:session expiration:expiration renewable:canBeRenewed]; + if (!self) { + return nil; + } + + NSMutableDictionary *mutableUserInfo = [parameters mutableCopy]; + [mutableUserInfo removeObjectsForKeys:@[ @"oauth_token", @"oauth_token_secret", @"oauth_session_handle", @"oauth_token_duration", @"oauth_token_renewable" ]]; + + if (mutableUserInfo.count > 0) { + self.userInfo = [mutableUserInfo copy]; + } + + return self; +} + +- (instancetype)initWithKey:(NSString *)key + secret:(NSString *)secret + session:(NSString *)session + expiration:(NSDate *)expiration + renewable:(BOOL)canBeRenewed { + NSParameterAssert(key); + NSParameterAssert(secret); + + self = [super init]; + if (!self) { + return nil; + } + + _key = key; + _secret = secret; + _session = session; + _expiration = expiration; + _renewable = canBeRenewed; + + return self; +} + +- (BOOL)isExpired { + return [self.expiration compare:[NSDate date]] == NSOrderedAscending; +} + +#pragma mark - NSCoding + +- (id)initWithCoder:(NSCoder *)decoder { + self = [super init]; + if (!self) { + return nil; + } + + _key = [decoder decodeObjectForKey:NSStringFromSelector(@selector(key))]; + _secret = [decoder decodeObjectForKey:NSStringFromSelector(@selector(secret))]; + _session = [decoder decodeObjectForKey:NSStringFromSelector(@selector(session))]; + _verifier = [decoder decodeObjectForKey:NSStringFromSelector(@selector(verifier))]; + _renewable = [decoder decodeBoolForKey:NSStringFromSelector(@selector(renewable))]; + _expiration = [decoder decodeObjectForKey:NSStringFromSelector(@selector(expiration))]; + _userInfo = [decoder decodeObjectForKey:NSStringFromSelector(@selector(userInfo))]; + + return self; +} + +- (void)encodeWithCoder:(NSCoder *)coder { + [coder encodeObject:self.key forKey:NSStringFromSelector(@selector(key))]; + [coder encodeObject:self.secret forKey:NSStringFromSelector(@selector(secret))]; + [coder encodeObject:self.session forKey:NSStringFromSelector(@selector(session))]; + [coder encodeObject:self.expiration forKey:NSStringFromSelector(@selector(expiration))]; + [coder encodeBool:self.renewable forKey:NSStringFromSelector(@selector(renewable))]; + [coder encodeObject:self.verifier forKey:NSStringFromSelector(@selector(verifier))]; + [coder encodeObject:self.userInfo forKey:NSStringFromSelector(@selector(userInfo))]; +} + +#pragma mark - NSCopying + +- (id)copyWithZone:(NSZone *)zone { + AFOAuth1Token *copy = [[[self class] allocWithZone:zone] initWithKey:[self.key copyWithZone:zone] secret:[self.secret copyWithZone:zone] session:[self.session copyWithZone:zone] expiration:[self.expiration copyWithZone:zone] renewable:self.renewable]; + copy->_verifier = [self.verifier copyWithZone:zone]; + copy->_userInfo = [self.userInfo copyWithZone:zone]; + return copy; +} + +#pragma mark - + ++ (NSDictionary *)keychainQueryDictionaryWithIdentifier:(NSString *)identifier { + return @{ + (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword, + (__bridge id)kSecAttrAccount : identifier, + (__bridge id)kSecAttrService : kAFOAuth1CredentialServiceName + }; +} + ++ (AFOAuth1Token *)retrieveCredentialWithIdentifier:(NSString *)identifier { + NSMutableDictionary *mutableQueryDictionary = [[self keychainQueryDictionaryWithIdentifier:identifier] mutableCopy]; + mutableQueryDictionary[(__bridge id)kSecReturnData] = (__bridge id)kCFBooleanTrue; + mutableQueryDictionary[(__bridge id)kSecMatchLimit] = (__bridge id)kSecMatchLimitOne; + + CFDataRef result = nil; + OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)mutableQueryDictionary, (CFTypeRef *)&result); + + if (status != errSecSuccess) { + NSLog(@"Unable to fetch credential with identifier \"%@\" (Error %li)", identifier, (long int)status); + return nil; + } + + NSData *data = (__bridge_transfer NSData *)result; + AFOAuth1Token *credential = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + + return credential; +} + ++ (BOOL)deleteCredentialWithIdentifier:(NSString *)identifier { + NSMutableDictionary *mutableQueryDictionary = [[self keychainQueryDictionaryWithIdentifier:identifier] mutableCopy]; + + OSStatus status = SecItemDelete((__bridge CFDictionaryRef)mutableQueryDictionary); + + if (status != errSecSuccess) { + NSLog(@"Unable to delete credential with identifier \"%@\" (Error %li)", identifier, (long int)status); + } + + return (status == errSecSuccess); +} + ++ (BOOL)storeCredential:(AFOAuth1Token *)credential + withIdentifier:(NSString *)identifier { + id securityAccessibility = nil; +#if (defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 43000) || (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1090) + securityAccessibility = (__bridge id)kSecAttrAccessibleWhenUnlocked; +#endif + + return [[self class] storeCredential:credential withIdentifier:identifier withAccessibility:securityAccessibility]; +} + ++ (BOOL)storeCredential:(AFOAuth1Token *)credential + withIdentifier:(NSString *)identifier + withAccessibility:(id)securityAccessibility { + NSMutableDictionary *mutableQueryDictionary = [[self keychainQueryDictionaryWithIdentifier:identifier] mutableCopy]; + + if (!credential) { + return [self deleteCredentialWithIdentifier:identifier]; + } + + NSMutableDictionary *mutableUpdateDictionary = [[NSMutableDictionary alloc] init]; + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:credential]; + mutableUpdateDictionary[(__bridge id)kSecValueData] = data; + if (securityAccessibility) { + [mutableUpdateDictionary setObject:securityAccessibility forKey:(__bridge id)kSecAttrAccessible]; + } + + OSStatus status; + BOOL exists = !![self retrieveCredentialWithIdentifier:identifier]; + + if (exists) { + status = SecItemUpdate((__bridge CFDictionaryRef)mutableQueryDictionary, (__bridge CFDictionaryRef)mutableUpdateDictionary); + } else { + [mutableQueryDictionary addEntriesFromDictionary:mutableUpdateDictionary]; + status = SecItemAdd((__bridge CFDictionaryRef)mutableQueryDictionary, NULL); + } + + if (status != errSecSuccess) { + NSLog(@"Unable to %@ credential with identifier \"%@\" (Error %li)", exists ? @"update" : @"add", identifier, (long int)status); + } + + return (status == errSecSuccess); +} + +@end diff --git a/AFOAuth1Client/AFOAuth1Utils.h b/AFOAuth1Client/AFOAuth1Utils.h new file mode 100644 index 0000000..b454c29 --- /dev/null +++ b/AFOAuth1Client/AFOAuth1Utils.h @@ -0,0 +1,60 @@ +// AFOAuth1Utils.h +// +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +/** + + */ +@interface AFOAuth1Utils : NSObject + +/** + + */ ++ (NSString *)percentEscapedQueryStringPairMemberFromString:(NSString *)string withEncoding:(NSStringEncoding)encoding; + +/** + + */ ++ (NSString *)sortedQueryString:(NSString *)queryString; + +/** + + */ ++ (NSArray *)sortedQueryItemsFromQueryString:(NSString *)queryString; + +/** + + */ ++ (NSDictionary *)parametersFromQueryString:(NSString *)queryString; + +/** + + */ ++ (NSArray *)sortedQueryItemsFromParameters:(NSDictionary *)parameters; + +/** + + */ ++ (BOOL)isQueryStringValueTrue:(NSString *)value; + +@end diff --git a/AFOAuth1Client/AFOAuth1Utils.m b/AFOAuth1Client/AFOAuth1Utils.m new file mode 100644 index 0000000..07c1225 --- /dev/null +++ b/AFOAuth1Client/AFOAuth1Utils.m @@ -0,0 +1,87 @@ +// AFOAuth1Utils.m +// +// Copyright (c) 2011-2014 AFNetworking (http://afnetworking.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "AFOAuth1Utils.h" + +@implementation AFOAuth1Utils + ++ (NSString *)percentEscapedQueryStringPairMemberFromString:(NSString *)string withEncoding:(NSStringEncoding)encoding { + static NSString * const kAFOAuth1CharactersToBeEscaped = @":/?&=;+!@#$()',*"; + static NSString * const kAFOAuth1CharactersToLeaveUnescaped = @"[]."; + return (__bridge_transfer NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (__bridge CFStringRef)string, (__bridge CFStringRef)kAFOAuth1CharactersToLeaveUnescaped, (__bridge CFStringRef)kAFOAuth1CharactersToBeEscaped, CFStringConvertNSStringEncodingToEncoding(encoding)); +} + ++ (NSString *)sortedQueryString:(NSString *)queryString { + return [[[queryString componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(compare:)] componentsJoinedByString:@"&"]; +} + ++ (NSArray *)sortedQueryItemsFromQueryString:(NSString *)queryString { + NSArray *sortedQueryPairs = [[queryString componentsSeparatedByString:@"&"] sortedArrayUsingSelector:@selector(compare:)]; + NSMutableArray *sortedQueryItems = [[NSMutableArray alloc] init]; + for (NSString *queryPair in sortedQueryPairs) { + NSArray *queryItem = [queryPair componentsSeparatedByString:@"="]; + [sortedQueryItems addObject:queryItem]; + } + return sortedQueryItems; +} + ++ (NSDictionary *)parametersFromQueryString:(NSString *)queryString { + NSArray *sortedQueryItems = [self sortedQueryItemsFromQueryString:queryString]; + NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init]; + for (NSArray *queryItem in sortedQueryItems) { + switch (queryItem.count) { + case 1: { + NSString *key = queryItem[0]; + parameters[key] = [NSNull null]; + } break; + case 2: { + NSString *key = queryItem[0]; + NSString *value = queryItem[1]; + parameters[key] = value; + } break; + default: { + NSLog(@"Ignoring query item:\n%@", queryItem); + } break; + } + } + return parameters; +} + +// FIXME: (me@lxcid.com) No support for nested parameters. ++ (NSArray *)sortedQueryItemsFromParameters:(NSDictionary *)parameters { + NSMutableArray *queryItems = [NSMutableArray array]; + [parameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { + [queryItems addObject:@[ key, obj ]]; + }]; + [queryItems sortUsingComparator:^NSComparisonResult(NSArray *queryItem1, NSArray *queryItem2) { + id key1 = queryItem1.firstObject; + id key2 = queryItem2.firstObject; + return [key1 compare:key2]; + }]; + return [queryItems copy]; +} + ++ (BOOL)isQueryStringValueTrue:(NSString *)value { + return value && [value.lowercaseString hasPrefix:@"t"]; +} + +@end diff --git a/Twitter OSX Example Client/Twitter OSX Example Client.xcodeproj/project.pbxproj b/Twitter OSX Example Client/Twitter OSX Example Client.xcodeproj/project.pbxproj index a20df6b..551622d 100644 --- a/Twitter OSX Example Client/Twitter OSX Example Client.xcodeproj/project.pbxproj +++ b/Twitter OSX Example Client/Twitter OSX Example Client.xcodeproj/project.pbxproj @@ -11,17 +11,20 @@ 3B95200016944D5B00BAF7F8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B951FFF16944D5B00BAF7F8 /* main.m */; }; 3B95200716944D5B00BAF7F8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95200616944D5B00BAF7F8 /* AppDelegate.m */; }; 3B95200A16944D5B00BAF7F8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3B95200816944D5B00BAF7F8 /* MainMenu.xib */; }; - 3B95202716944D7900BAF7F8 /* AFHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95201516944D7900BAF7F8 /* AFHTTPClient.m */; }; - 3B95202816944D7900BAF7F8 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95201716944D7900BAF7F8 /* AFHTTPRequestOperation.m */; }; - 3B95202916944D7900BAF7F8 /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95201916944D7900BAF7F8 /* AFImageRequestOperation.m */; }; - 3B95202A16944D7900BAF7F8 /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95201B16944D7900BAF7F8 /* AFJSONRequestOperation.m */; }; - 3B95202B16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95201D16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.m */; }; - 3B95202C16944D7900BAF7F8 /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95202016944D7900BAF7F8 /* AFPropertyListRequestOperation.m */; }; - 3B95202D16944D7900BAF7F8 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95202216944D7900BAF7F8 /* AFURLConnectionOperation.m */; }; - 3B95202E16944D7900BAF7F8 /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95202416944D7900BAF7F8 /* AFXMLRequestOperation.m */; }; - 3B95202F16944D7900BAF7F8 /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B95202616944D7900BAF7F8 /* UIImageView+AFNetworking.m */; }; + 5DF7787E1B3E2621003AE3C7 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7786C1B3E2621003AE3C7 /* AFHTTPRequestOperation.m */; }; + 5DF7787F1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7786E1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.m */; }; + 5DF778801B3E2621003AE3C7 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778701B3E2621003AE3C7 /* AFHTTPSessionManager.m */; }; + 5DF778811B3E2621003AE3C7 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778731B3E2621003AE3C7 /* AFNetworkReachabilityManager.m */; }; + 5DF778821B3E2621003AE3C7 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778751B3E2621003AE3C7 /* AFSecurityPolicy.m */; }; + 5DF778831B3E2621003AE3C7 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778771B3E2621003AE3C7 /* AFURLConnectionOperation.m */; }; + 5DF778841B3E2621003AE3C7 /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778791B3E2621003AE3C7 /* AFURLRequestSerialization.m */; }; + 5DF778851B3E2621003AE3C7 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7787B1B3E2621003AE3C7 /* AFURLResponseSerialization.m */; }; + 5DF778861B3E2621003AE3C7 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7787D1B3E2621003AE3C7 /* AFURLSessionManager.m */; }; + 5DF778AD1B3E272B003AE3C7 /* AFOAuth1Client.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778A61B3E272A003AE3C7 /* AFOAuth1Client.m */; }; + 5DF778AE1B3E272B003AE3C7 /* AFOAuth1RequestSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778A81B3E272A003AE3C7 /* AFOAuth1RequestSerializer.m */; }; + 5DF778AF1B3E272B003AE3C7 /* AFOAuth1Token.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778AA1B3E272A003AE3C7 /* AFOAuth1Token.m */; }; + 5DF778B01B3E272B003AE3C7 /* AFOAuth1Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778AC1B3E272B003AE3C7 /* AFOAuth1Utils.m */; }; F83DA16317C579A4006C3DB5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F83DA16217C579A4006C3DB5 /* Security.framework */; }; - F8E8694C16ADDA2800CD328E /* AFOAuth1Client.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E8694B16ADDA2800CD328E /* AFOAuth1Client.m */; }; F8E8695F16ADDE1D00CD328E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E8695E16ADDE1D00CD328E /* SystemConfiguration.framework */; }; /* End PBXBuildFile section */ @@ -37,28 +40,34 @@ 3B95200516944D5B00BAF7F8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 3B95200616944D5B00BAF7F8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 3B95200916944D5B00BAF7F8 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; - 3B95201416944D7900BAF7F8 /* AFHTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPClient.h; sourceTree = ""; }; - 3B95201516944D7900BAF7F8 /* AFHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPClient.m; sourceTree = ""; }; - 3B95201616944D7900BAF7F8 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = ""; }; - 3B95201716944D7900BAF7F8 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = ""; }; - 3B95201816944D7900BAF7F8 /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageRequestOperation.h; sourceTree = ""; }; - 3B95201916944D7900BAF7F8 /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageRequestOperation.m; sourceTree = ""; }; - 3B95201A16944D7900BAF7F8 /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONRequestOperation.h; sourceTree = ""; }; - 3B95201B16944D7900BAF7F8 /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFJSONRequestOperation.m; sourceTree = ""; }; - 3B95201C16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkActivityIndicatorManager.h; sourceTree = ""; }; - 3B95201D16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkActivityIndicatorManager.m; sourceTree = ""; }; - 3B95201E16944D7900BAF7F8 /* AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworking.h; sourceTree = ""; }; - 3B95201F16944D7900BAF7F8 /* AFPropertyListRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFPropertyListRequestOperation.h; sourceTree = ""; }; - 3B95202016944D7900BAF7F8 /* AFPropertyListRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFPropertyListRequestOperation.m; sourceTree = ""; }; - 3B95202116944D7900BAF7F8 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = ""; }; - 3B95202216944D7900BAF7F8 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = ""; }; - 3B95202316944D7900BAF7F8 /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFXMLRequestOperation.h; sourceTree = ""; }; - 3B95202416944D7900BAF7F8 /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFXMLRequestOperation.m; sourceTree = ""; }; - 3B95202516944D7900BAF7F8 /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+AFNetworking.h"; sourceTree = ""; }; - 3B95202616944D7900BAF7F8 /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+AFNetworking.m"; sourceTree = ""; }; + 5DF7786B1B3E2620003AE3C7 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = ""; }; + 5DF7786C1B3E2621003AE3C7 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = ""; }; + 5DF7786D1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperationManager.h; sourceTree = ""; }; + 5DF7786E1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationManager.m; sourceTree = ""; }; + 5DF7786F1B3E2621003AE3C7 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPSessionManager.h; sourceTree = ""; }; + 5DF778701B3E2621003AE3C7 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPSessionManager.m; sourceTree = ""; }; + 5DF778711B3E2621003AE3C7 /* AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworking.h; sourceTree = ""; }; + 5DF778721B3E2621003AE3C7 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkReachabilityManager.h; sourceTree = ""; }; + 5DF778731B3E2621003AE3C7 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkReachabilityManager.m; sourceTree = ""; }; + 5DF778741B3E2621003AE3C7 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFSecurityPolicy.h; sourceTree = ""; }; + 5DF778751B3E2621003AE3C7 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityPolicy.m; sourceTree = ""; }; + 5DF778761B3E2621003AE3C7 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = ""; }; + 5DF778771B3E2621003AE3C7 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = ""; }; + 5DF778781B3E2621003AE3C7 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLRequestSerialization.h; sourceTree = ""; }; + 5DF778791B3E2621003AE3C7 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLRequestSerialization.m; sourceTree = ""; }; + 5DF7787A1B3E2621003AE3C7 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLResponseSerialization.h; sourceTree = ""; }; + 5DF7787B1B3E2621003AE3C7 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLResponseSerialization.m; sourceTree = ""; }; + 5DF7787C1B3E2621003AE3C7 /* AFURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLSessionManager.h; sourceTree = ""; }; + 5DF7787D1B3E2621003AE3C7 /* AFURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLSessionManager.m; sourceTree = ""; }; + 5DF778A51B3E272A003AE3C7 /* AFOAuth1Client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Client.h; sourceTree = ""; }; + 5DF778A61B3E272A003AE3C7 /* AFOAuth1Client.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Client.m; sourceTree = ""; }; + 5DF778A71B3E272A003AE3C7 /* AFOAuth1RequestSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1RequestSerializer.h; sourceTree = ""; }; + 5DF778A81B3E272A003AE3C7 /* AFOAuth1RequestSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1RequestSerializer.m; sourceTree = ""; }; + 5DF778A91B3E272A003AE3C7 /* AFOAuth1Token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Token.h; sourceTree = ""; }; + 5DF778AA1B3E272A003AE3C7 /* AFOAuth1Token.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Token.m; sourceTree = ""; }; + 5DF778AB1B3E272B003AE3C7 /* AFOAuth1Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Utils.h; sourceTree = ""; }; + 5DF778AC1B3E272B003AE3C7 /* AFOAuth1Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Utils.m; sourceTree = ""; }; F83DA16217C579A4006C3DB5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - F8E8694A16ADDA2800CD328E /* AFOAuth1Client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Client.h; sourceTree = ""; }; - F8E8694B16ADDA2800CD328E /* AFOAuth1Client.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Client.m; sourceTree = ""; }; F8E8695E16ADDE1D00CD328E /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -136,50 +145,56 @@ name = "Supporting Files"; sourceTree = ""; }; - 3B95201316944D7900BAF7F8 /* AFNetworking */ = { + 5DF7786A1B3E2620003AE3C7 /* AFNetworking */ = { isa = PBXGroup; children = ( - 3B95201416944D7900BAF7F8 /* AFHTTPClient.h */, - 3B95201516944D7900BAF7F8 /* AFHTTPClient.m */, - 3B95201616944D7900BAF7F8 /* AFHTTPRequestOperation.h */, - 3B95201716944D7900BAF7F8 /* AFHTTPRequestOperation.m */, - 3B95201816944D7900BAF7F8 /* AFImageRequestOperation.h */, - 3B95201916944D7900BAF7F8 /* AFImageRequestOperation.m */, - 3B95201A16944D7900BAF7F8 /* AFJSONRequestOperation.h */, - 3B95201B16944D7900BAF7F8 /* AFJSONRequestOperation.m */, - 3B95201C16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.h */, - 3B95201D16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.m */, - 3B95201E16944D7900BAF7F8 /* AFNetworking.h */, - 3B95201F16944D7900BAF7F8 /* AFPropertyListRequestOperation.h */, - 3B95202016944D7900BAF7F8 /* AFPropertyListRequestOperation.m */, - 3B95202116944D7900BAF7F8 /* AFURLConnectionOperation.h */, - 3B95202216944D7900BAF7F8 /* AFURLConnectionOperation.m */, - 3B95202316944D7900BAF7F8 /* AFXMLRequestOperation.h */, - 3B95202416944D7900BAF7F8 /* AFXMLRequestOperation.m */, - 3B95202516944D7900BAF7F8 /* UIImageView+AFNetworking.h */, - 3B95202616944D7900BAF7F8 /* UIImageView+AFNetworking.m */, + 5DF7786B1B3E2620003AE3C7 /* AFHTTPRequestOperation.h */, + 5DF7786C1B3E2621003AE3C7 /* AFHTTPRequestOperation.m */, + 5DF7786D1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.h */, + 5DF7786E1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.m */, + 5DF7786F1B3E2621003AE3C7 /* AFHTTPSessionManager.h */, + 5DF778701B3E2621003AE3C7 /* AFHTTPSessionManager.m */, + 5DF778711B3E2621003AE3C7 /* AFNetworking.h */, + 5DF778721B3E2621003AE3C7 /* AFNetworkReachabilityManager.h */, + 5DF778731B3E2621003AE3C7 /* AFNetworkReachabilityManager.m */, + 5DF778741B3E2621003AE3C7 /* AFSecurityPolicy.h */, + 5DF778751B3E2621003AE3C7 /* AFSecurityPolicy.m */, + 5DF778761B3E2621003AE3C7 /* AFURLConnectionOperation.h */, + 5DF778771B3E2621003AE3C7 /* AFURLConnectionOperation.m */, + 5DF778781B3E2621003AE3C7 /* AFURLRequestSerialization.h */, + 5DF778791B3E2621003AE3C7 /* AFURLRequestSerialization.m */, + 5DF7787A1B3E2621003AE3C7 /* AFURLResponseSerialization.h */, + 5DF7787B1B3E2621003AE3C7 /* AFURLResponseSerialization.m */, + 5DF7787C1B3E2621003AE3C7 /* AFURLSessionManager.h */, + 5DF7787D1B3E2621003AE3C7 /* AFURLSessionManager.m */, ); name = AFNetworking; - path = ../AFNetworking/AFNetworking; + path = ../AFNetworking; sourceTree = ""; }; - F86035CE16ADCCC60027FDE8 /* Vendor */ = { + 5DF778A41B3E272A003AE3C7 /* AFOAuth1Client */ = { isa = PBXGroup; children = ( - F8E8694916ADDA2800CD328E /* AFOAuth1Client */, - 3B95201316944D7900BAF7F8 /* AFNetworking */, + 5DF778A51B3E272A003AE3C7 /* AFOAuth1Client.h */, + 5DF778A61B3E272A003AE3C7 /* AFOAuth1Client.m */, + 5DF778A71B3E272A003AE3C7 /* AFOAuth1RequestSerializer.h */, + 5DF778A81B3E272A003AE3C7 /* AFOAuth1RequestSerializer.m */, + 5DF778A91B3E272A003AE3C7 /* AFOAuth1Token.h */, + 5DF778AA1B3E272A003AE3C7 /* AFOAuth1Token.m */, + 5DF778AB1B3E272B003AE3C7 /* AFOAuth1Utils.h */, + 5DF778AC1B3E272B003AE3C7 /* AFOAuth1Utils.m */, ); - name = Vendor; + name = AFOAuth1Client; + path = ../AFOAuth1Client; sourceTree = ""; }; - F8E8694916ADDA2800CD328E /* AFOAuth1Client */ = { + F86035CE16ADCCC60027FDE8 /* Vendor */ = { isa = PBXGroup; children = ( - F8E8694A16ADDA2800CD328E /* AFOAuth1Client.h */, - F8E8694B16ADDA2800CD328E /* AFOAuth1Client.m */, + 5DF778A41B3E272A003AE3C7 /* AFOAuth1Client */, + 5DF7786A1B3E2620003AE3C7 /* AFNetworking */, ); - name = AFOAuth1Client; - path = ../AFOAuth1Client; + name = Vendor; sourceTree = ""; }; /* End PBXGroup section */ @@ -244,18 +259,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5DF778AE1B3E272B003AE3C7 /* AFOAuth1RequestSerializer.m in Sources */, + 5DF7787E1B3E2621003AE3C7 /* AFHTTPRequestOperation.m in Sources */, 3B95200016944D5B00BAF7F8 /* main.m in Sources */, + 5DF7787F1B3E2621003AE3C7 /* AFHTTPRequestOperationManager.m in Sources */, + 5DF778B01B3E272B003AE3C7 /* AFOAuth1Utils.m in Sources */, + 5DF778811B3E2621003AE3C7 /* AFNetworkReachabilityManager.m in Sources */, + 5DF778851B3E2621003AE3C7 /* AFURLResponseSerialization.m in Sources */, + 5DF778831B3E2621003AE3C7 /* AFURLConnectionOperation.m in Sources */, + 5DF778821B3E2621003AE3C7 /* AFSecurityPolicy.m in Sources */, + 5DF778AD1B3E272B003AE3C7 /* AFOAuth1Client.m in Sources */, + 5DF778801B3E2621003AE3C7 /* AFHTTPSessionManager.m in Sources */, + 5DF778841B3E2621003AE3C7 /* AFURLRequestSerialization.m in Sources */, + 5DF778861B3E2621003AE3C7 /* AFURLSessionManager.m in Sources */, 3B95200716944D5B00BAF7F8 /* AppDelegate.m in Sources */, - 3B95202716944D7900BAF7F8 /* AFHTTPClient.m in Sources */, - 3B95202816944D7900BAF7F8 /* AFHTTPRequestOperation.m in Sources */, - 3B95202916944D7900BAF7F8 /* AFImageRequestOperation.m in Sources */, - 3B95202A16944D7900BAF7F8 /* AFJSONRequestOperation.m in Sources */, - 3B95202B16944D7900BAF7F8 /* AFNetworkActivityIndicatorManager.m in Sources */, - 3B95202C16944D7900BAF7F8 /* AFPropertyListRequestOperation.m in Sources */, - 3B95202D16944D7900BAF7F8 /* AFURLConnectionOperation.m in Sources */, - 3B95202E16944D7900BAF7F8 /* AFXMLRequestOperation.m in Sources */, - 3B95202F16944D7900BAF7F8 /* UIImageView+AFNetworking.m in Sources */, - F8E8694C16ADDA2800CD328E /* AFOAuth1Client.m in Sources */, + 5DF778AF1B3E272B003AE3C7 /* AFOAuth1Token.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.h b/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.h index 482ae18..a4aaa71 100644 --- a/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.h +++ b/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.h @@ -24,7 +24,7 @@ #import #import "AFOAuth1Client.h" -#import "AFJSONRequestOperation.h" +//#import "AFJSONRequestOperation.h" @interface AppDelegate : NSObject diff --git a/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.m b/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.m index ae6e195..89f3d6f 100644 --- a/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.m +++ b/Twitter OSX Example Client/Twitter OSX Example Client/AppDelegate.m @@ -31,23 +31,20 @@ - (void)applicationDidFinishLaunching:(NSNotification *)notification { [[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL]; LSSetDefaultHandlerForURLScheme((__bridge CFStringRef)@"af-twitter", (__bridge CFStringRef)[[NSBundle mainBundle] bundleIdentifier]); + self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.twitter.com/1.1/"] key:@"4oFCF0AjP4PQDUaCh5RQ" secret:@"NxAihESVsdUXSUxtHrml2VBHA0xKofYKmmGS01KaSs"]; - [self.twitterClient registerHTTPOperationClass:[AFJSONRequestOperation class]]; - - [self.twitterClient authorizeUsingOAuthWithRequestTokenPath:@"/oauth/request_token" userAuthorizationPath:@"/oauth/authorize" callbackURL:[NSURL URLWithString:@"af-twitter://success"] accessTokenPath:@"/oauth/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) { - NSLog(@"Success: %@", accessToken); - - [self.twitterClient getPath:@"statuses/user_timeline.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSArray *responseArray = (NSArray *)responseObject; - [responseArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - NSLog(@"Success: %@", obj); - }]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + + [self.twitterClient authorizeUsingOAuthWithRequestTokenURLString:@"/oauth/request_token" userAuthorizationURLString:@"/oauth/authorize" callbackURL:[NSURL URLWithString:@"af-twitter://success"] accessTokenURLString:@"/oauth/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) { + self.twitterClient.responseSerializer = [AFJSONResponseSerializer serializer]; + [self.twitterClient GET:@"statuses/user_timeline.json" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) { + NSLog(@"%@", responseObject); + } failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"Error: %@", error); }]; } failure:^(NSError *error) { NSLog(@"Error: %@", error); }]; + } #pragma mark - NSAppleEventManager diff --git a/Twitter iOS Example Client/Twitter iOS Example Client.xcodeproj/project.pbxproj b/Twitter iOS Example Client/Twitter iOS Example Client.xcodeproj/project.pbxproj index 1bf8215..53f0914 100644 --- a/Twitter iOS Example Client/Twitter iOS Example Client.xcodeproj/project.pbxproj +++ b/Twitter iOS Example Client/Twitter iOS Example Client.xcodeproj/project.pbxproj @@ -15,15 +15,18 @@ 3B3A8B5D1693A877005B1AAC /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B3A8B5C1693A877005B1AAC /* Default.png */; }; 3B3A8B5F1693A877005B1AAC /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B3A8B5E1693A877005B1AAC /* Default@2x.png */; }; 3B3A8B611693A877005B1AAC /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 3B3A8B601693A877005B1AAC /* Default-568h@2x.png */; }; - 3B3A8B7E1693A8F5005B1AAC /* AFHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B6C1693A8F5005B1AAC /* AFHTTPClient.m */; }; - 3B3A8B7F1693A8F5005B1AAC /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B6E1693A8F5005B1AAC /* AFHTTPRequestOperation.m */; }; - 3B3A8B801693A8F5005B1AAC /* AFImageRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B701693A8F5005B1AAC /* AFImageRequestOperation.m */; }; - 3B3A8B811693A8F5005B1AAC /* AFJSONRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B721693A8F5005B1AAC /* AFJSONRequestOperation.m */; }; - 3B3A8B821693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B741693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.m */; }; - 3B3A8B831693A8F5005B1AAC /* AFPropertyListRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B771693A8F5005B1AAC /* AFPropertyListRequestOperation.m */; }; - 3B3A8B841693A8F5005B1AAC /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B791693A8F5005B1AAC /* AFURLConnectionOperation.m */; }; - 3B3A8B851693A8F5005B1AAC /* AFXMLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B7B1693A8F5005B1AAC /* AFXMLRequestOperation.m */; }; - 3B3A8B861693A8F5005B1AAC /* UIImageView+AFNetworking.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B3A8B7D1693A8F5005B1AAC /* UIImageView+AFNetworking.m */; }; + 5DF7789B1B3E262D003AE3C7 /* AFHTTPRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778891B3E262D003AE3C7 /* AFHTTPRequestOperation.m */; }; + 5DF7789C1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7788B1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.m */; }; + 5DF7789D1B3E262D003AE3C7 /* AFHTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7788D1B3E262D003AE3C7 /* AFHTTPSessionManager.m */; }; + 5DF7789E1B3E262D003AE3C7 /* AFNetworkReachabilityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778901B3E262D003AE3C7 /* AFNetworkReachabilityManager.m */; }; + 5DF7789F1B3E262D003AE3C7 /* AFSecurityPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778921B3E262D003AE3C7 /* AFSecurityPolicy.m */; }; + 5DF778A01B3E262D003AE3C7 /* AFURLConnectionOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778941B3E262D003AE3C7 /* AFURLConnectionOperation.m */; }; + 5DF778A11B3E262D003AE3C7 /* AFURLRequestSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778961B3E262D003AE3C7 /* AFURLRequestSerialization.m */; }; + 5DF778A21B3E262D003AE3C7 /* AFURLResponseSerialization.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF778981B3E262D003AE3C7 /* AFURLResponseSerialization.m */; }; + 5DF778A31B3E262D003AE3C7 /* AFURLSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 5DF7789A1B3E262D003AE3C7 /* AFURLSessionManager.m */; }; + ABB1C7AB1A1D47BD004D07FA /* AFOAuth1RequestSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = ABB1C7A61A1D47BD004D07FA /* AFOAuth1RequestSerializer.m */; }; + ABB1C7AC1A1D47BD004D07FA /* AFOAuth1Token.m in Sources */ = {isa = PBXBuildFile; fileRef = ABB1C7A81A1D47BD004D07FA /* AFOAuth1Token.m */; }; + ABB1C7AD1A1D47BD004D07FA /* AFOAuth1Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = ABB1C7AA1A1D47BD004D07FA /* AFOAuth1Utils.m */; }; F83DA16117C5799C006C3DB5 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F83DA16017C5799C006C3DB5 /* Security.framework */; }; F8E8694716ADDA1900CD328E /* AFOAuth1Client.m in Sources */ = {isa = PBXBuildFile; fileRef = F8E8694616ADDA1900CD328E /* AFOAuth1Client.m */; }; F8E8694E16ADDA3700CD328E /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E8694D16ADDA3700CD328E /* SystemConfiguration.framework */; }; @@ -43,25 +46,31 @@ 3B3A8B5C1693A877005B1AAC /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 3B3A8B5E1693A877005B1AAC /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 3B3A8B601693A877005B1AAC /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; - 3B3A8B6B1693A8F5005B1AAC /* AFHTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPClient.h; sourceTree = ""; }; - 3B3A8B6C1693A8F5005B1AAC /* AFHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPClient.m; sourceTree = ""; }; - 3B3A8B6D1693A8F5005B1AAC /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = ""; }; - 3B3A8B6E1693A8F5005B1AAC /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = ""; }; - 3B3A8B6F1693A8F5005B1AAC /* AFImageRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFImageRequestOperation.h; sourceTree = ""; }; - 3B3A8B701693A8F5005B1AAC /* AFImageRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageRequestOperation.m; sourceTree = ""; }; - 3B3A8B711693A8F5005B1AAC /* AFJSONRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFJSONRequestOperation.h; sourceTree = ""; }; - 3B3A8B721693A8F5005B1AAC /* AFJSONRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFJSONRequestOperation.m; sourceTree = ""; }; - 3B3A8B731693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkActivityIndicatorManager.h; sourceTree = ""; }; - 3B3A8B741693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkActivityIndicatorManager.m; sourceTree = ""; }; - 3B3A8B751693A8F5005B1AAC /* AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworking.h; sourceTree = ""; }; - 3B3A8B761693A8F5005B1AAC /* AFPropertyListRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFPropertyListRequestOperation.h; sourceTree = ""; }; - 3B3A8B771693A8F5005B1AAC /* AFPropertyListRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFPropertyListRequestOperation.m; sourceTree = ""; }; - 3B3A8B781693A8F5005B1AAC /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = ""; }; - 3B3A8B791693A8F5005B1AAC /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = ""; }; - 3B3A8B7A1693A8F5005B1AAC /* AFXMLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFXMLRequestOperation.h; sourceTree = ""; }; - 3B3A8B7B1693A8F5005B1AAC /* AFXMLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFXMLRequestOperation.m; sourceTree = ""; }; - 3B3A8B7C1693A8F5005B1AAC /* UIImageView+AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+AFNetworking.h"; sourceTree = ""; }; - 3B3A8B7D1693A8F5005B1AAC /* UIImageView+AFNetworking.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+AFNetworking.m"; sourceTree = ""; }; + 5DF778881B3E262D003AE3C7 /* AFHTTPRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperation.h; sourceTree = ""; }; + 5DF778891B3E262D003AE3C7 /* AFHTTPRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperation.m; sourceTree = ""; }; + 5DF7788A1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPRequestOperationManager.h; sourceTree = ""; }; + 5DF7788B1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPRequestOperationManager.m; sourceTree = ""; }; + 5DF7788C1B3E262D003AE3C7 /* AFHTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFHTTPSessionManager.h; sourceTree = ""; }; + 5DF7788D1B3E262D003AE3C7 /* AFHTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFHTTPSessionManager.m; sourceTree = ""; }; + 5DF7788E1B3E262D003AE3C7 /* AFNetworking.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworking.h; sourceTree = ""; }; + 5DF7788F1B3E262D003AE3C7 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkReachabilityManager.h; sourceTree = ""; }; + 5DF778901B3E262D003AE3C7 /* AFNetworkReachabilityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFNetworkReachabilityManager.m; sourceTree = ""; }; + 5DF778911B3E262D003AE3C7 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFSecurityPolicy.h; sourceTree = ""; }; + 5DF778921B3E262D003AE3C7 /* AFSecurityPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFSecurityPolicy.m; sourceTree = ""; }; + 5DF778931B3E262D003AE3C7 /* AFURLConnectionOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLConnectionOperation.h; sourceTree = ""; }; + 5DF778941B3E262D003AE3C7 /* AFURLConnectionOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperation.m; sourceTree = ""; }; + 5DF778951B3E262D003AE3C7 /* AFURLRequestSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLRequestSerialization.h; sourceTree = ""; }; + 5DF778961B3E262D003AE3C7 /* AFURLRequestSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLRequestSerialization.m; sourceTree = ""; }; + 5DF778971B3E262D003AE3C7 /* AFURLResponseSerialization.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLResponseSerialization.h; sourceTree = ""; }; + 5DF778981B3E262D003AE3C7 /* AFURLResponseSerialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLResponseSerialization.m; sourceTree = ""; }; + 5DF778991B3E262D003AE3C7 /* AFURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLSessionManager.h; sourceTree = ""; }; + 5DF7789A1B3E262D003AE3C7 /* AFURLSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLSessionManager.m; sourceTree = ""; }; + ABB1C7A51A1D47BD004D07FA /* AFOAuth1RequestSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1RequestSerializer.h; sourceTree = ""; }; + ABB1C7A61A1D47BD004D07FA /* AFOAuth1RequestSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1RequestSerializer.m; sourceTree = ""; }; + ABB1C7A71A1D47BD004D07FA /* AFOAuth1Token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Token.h; sourceTree = ""; }; + ABB1C7A81A1D47BD004D07FA /* AFOAuth1Token.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Token.m; sourceTree = ""; }; + ABB1C7A91A1D47BD004D07FA /* AFOAuth1Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Utils.h; sourceTree = ""; }; + ABB1C7AA1A1D47BD004D07FA /* AFOAuth1Utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Utils.m; sourceTree = ""; }; F83DA16017C5799C006C3DB5 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; F8E8694516ADDA1900CD328E /* AFOAuth1Client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFOAuth1Client.h; sourceTree = ""; }; F8E8694616ADDA1900CD328E /* AFOAuth1Client.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFOAuth1Client.m; sourceTree = ""; }; @@ -140,38 +149,38 @@ name = "Supporting Files"; sourceTree = ""; }; - 3B3A8B6A1693A8F5005B1AAC /* AFNetworking */ = { + 5DF778871B3E262D003AE3C7 /* AFNetworking */ = { isa = PBXGroup; children = ( - 3B3A8B6B1693A8F5005B1AAC /* AFHTTPClient.h */, - 3B3A8B6C1693A8F5005B1AAC /* AFHTTPClient.m */, - 3B3A8B6D1693A8F5005B1AAC /* AFHTTPRequestOperation.h */, - 3B3A8B6E1693A8F5005B1AAC /* AFHTTPRequestOperation.m */, - 3B3A8B6F1693A8F5005B1AAC /* AFImageRequestOperation.h */, - 3B3A8B701693A8F5005B1AAC /* AFImageRequestOperation.m */, - 3B3A8B711693A8F5005B1AAC /* AFJSONRequestOperation.h */, - 3B3A8B721693A8F5005B1AAC /* AFJSONRequestOperation.m */, - 3B3A8B731693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.h */, - 3B3A8B741693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.m */, - 3B3A8B751693A8F5005B1AAC /* AFNetworking.h */, - 3B3A8B761693A8F5005B1AAC /* AFPropertyListRequestOperation.h */, - 3B3A8B771693A8F5005B1AAC /* AFPropertyListRequestOperation.m */, - 3B3A8B781693A8F5005B1AAC /* AFURLConnectionOperation.h */, - 3B3A8B791693A8F5005B1AAC /* AFURLConnectionOperation.m */, - 3B3A8B7A1693A8F5005B1AAC /* AFXMLRequestOperation.h */, - 3B3A8B7B1693A8F5005B1AAC /* AFXMLRequestOperation.m */, - 3B3A8B7C1693A8F5005B1AAC /* UIImageView+AFNetworking.h */, - 3B3A8B7D1693A8F5005B1AAC /* UIImageView+AFNetworking.m */, + 5DF778881B3E262D003AE3C7 /* AFHTTPRequestOperation.h */, + 5DF778891B3E262D003AE3C7 /* AFHTTPRequestOperation.m */, + 5DF7788A1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.h */, + 5DF7788B1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.m */, + 5DF7788C1B3E262D003AE3C7 /* AFHTTPSessionManager.h */, + 5DF7788D1B3E262D003AE3C7 /* AFHTTPSessionManager.m */, + 5DF7788E1B3E262D003AE3C7 /* AFNetworking.h */, + 5DF7788F1B3E262D003AE3C7 /* AFNetworkReachabilityManager.h */, + 5DF778901B3E262D003AE3C7 /* AFNetworkReachabilityManager.m */, + 5DF778911B3E262D003AE3C7 /* AFSecurityPolicy.h */, + 5DF778921B3E262D003AE3C7 /* AFSecurityPolicy.m */, + 5DF778931B3E262D003AE3C7 /* AFURLConnectionOperation.h */, + 5DF778941B3E262D003AE3C7 /* AFURLConnectionOperation.m */, + 5DF778951B3E262D003AE3C7 /* AFURLRequestSerialization.h */, + 5DF778961B3E262D003AE3C7 /* AFURLRequestSerialization.m */, + 5DF778971B3E262D003AE3C7 /* AFURLResponseSerialization.h */, + 5DF778981B3E262D003AE3C7 /* AFURLResponseSerialization.m */, + 5DF778991B3E262D003AE3C7 /* AFURLSessionManager.h */, + 5DF7789A1B3E262D003AE3C7 /* AFURLSessionManager.m */, ); name = AFNetworking; - path = ../AFNetworking/AFNetworking; + path = ../AFNetworking; sourceTree = ""; }; F8E8694316ADDA0F00CD328E /* Vendor */ = { isa = PBXGroup; children = ( + 5DF778871B3E262D003AE3C7 /* AFNetworking */, F8E8694416ADDA1900CD328E /* AFOAuth1Client */, - 3B3A8B6A1693A8F5005B1AAC /* AFNetworking */, ); name = Vendor; sourceTree = ""; @@ -181,6 +190,12 @@ children = ( F8E8694516ADDA1900CD328E /* AFOAuth1Client.h */, F8E8694616ADDA1900CD328E /* AFOAuth1Client.m */, + ABB1C7A51A1D47BD004D07FA /* AFOAuth1RequestSerializer.h */, + ABB1C7A61A1D47BD004D07FA /* AFOAuth1RequestSerializer.m */, + ABB1C7A71A1D47BD004D07FA /* AFOAuth1Token.h */, + ABB1C7A81A1D47BD004D07FA /* AFOAuth1Token.m */, + ABB1C7A91A1D47BD004D07FA /* AFOAuth1Utils.h */, + ABB1C7AA1A1D47BD004D07FA /* AFOAuth1Utils.m */, ); name = AFOAuth1Client; path = ../AFOAuth1Client; @@ -250,18 +265,21 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 5DF778A31B3E262D003AE3C7 /* AFURLSessionManager.m in Sources */, 3B3A8B571693A877005B1AAC /* main.m in Sources */, + ABB1C7AB1A1D47BD004D07FA /* AFOAuth1RequestSerializer.m in Sources */, + 5DF7789E1B3E262D003AE3C7 /* AFNetworkReachabilityManager.m in Sources */, + ABB1C7AD1A1D47BD004D07FA /* AFOAuth1Utils.m in Sources */, + 5DF778A01B3E262D003AE3C7 /* AFURLConnectionOperation.m in Sources */, + 5DF7789D1B3E262D003AE3C7 /* AFHTTPSessionManager.m in Sources */, + 5DF778A11B3E262D003AE3C7 /* AFURLRequestSerialization.m in Sources */, 3B3A8B5B1693A877005B1AAC /* AppDelegate.m in Sources */, - 3B3A8B7E1693A8F5005B1AAC /* AFHTTPClient.m in Sources */, - 3B3A8B7F1693A8F5005B1AAC /* AFHTTPRequestOperation.m in Sources */, - 3B3A8B801693A8F5005B1AAC /* AFImageRequestOperation.m in Sources */, - 3B3A8B811693A8F5005B1AAC /* AFJSONRequestOperation.m in Sources */, - 3B3A8B821693A8F5005B1AAC /* AFNetworkActivityIndicatorManager.m in Sources */, - 3B3A8B831693A8F5005B1AAC /* AFPropertyListRequestOperation.m in Sources */, - 3B3A8B841693A8F5005B1AAC /* AFURLConnectionOperation.m in Sources */, - 3B3A8B851693A8F5005B1AAC /* AFXMLRequestOperation.m in Sources */, - 3B3A8B861693A8F5005B1AAC /* UIImageView+AFNetworking.m in Sources */, + ABB1C7AC1A1D47BD004D07FA /* AFOAuth1Token.m in Sources */, F8E8694716ADDA1900CD328E /* AFOAuth1Client.m in Sources */, + 5DF7789C1B3E262D003AE3C7 /* AFHTTPRequestOperationManager.m in Sources */, + 5DF7789F1B3E262D003AE3C7 /* AFSecurityPolicy.m in Sources */, + 5DF778A21B3E262D003AE3C7 /* AFURLResponseSerialization.m in Sources */, + 5DF7789B1B3E262D003AE3C7 /* AFHTTPRequestOperation.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.h b/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.h index 2972456..41d7e91 100644 --- a/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.h +++ b/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.h @@ -24,7 +24,6 @@ #import #import "AFOAuth1Client.h" -#import "AFJSONRequestOperation.h" @interface AppDelegate : UIResponder diff --git a/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.m b/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.m index cfead7c..11a4aff 100644 --- a/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.m +++ b/Twitter iOS Example Client/Twitter iOS Example Client/AppDelegate.m @@ -36,15 +36,12 @@ - (BOOL)application:(UIApplication *)application [self.window makeKeyAndVisible]; self.twitterClient = [[AFOAuth1Client alloc] initWithBaseURL:[NSURL URLWithString:@"https://api.twitter.com/1.1/"] key:@"4oFCF0AjP4PQDUaCh5RQ" secret:@"NxAihESVsdUXSUxtHrml2VBHA0xKofYKmmGS01KaSs"]; - - [self.twitterClient authorizeUsingOAuthWithRequestTokenPath:@"/oauth/request_token" userAuthorizationPath:@"/oauth/authorize" callbackURL:[NSURL URLWithString:@"af-twitter://success"] accessTokenPath:@"/oauth/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) { - [self.twitterClient registerHTTPOperationClass:[AFJSONRequestOperation class]]; - [self.twitterClient getPath:@"statuses/user_timeline.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSArray *responseArray = (NSArray *)responseObject; - [responseArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - NSLog(@"Success: %@", obj); - }]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + + [self.twitterClient authorizeUsingOAuthWithRequestTokenURLString:@"/oauth/request_token" userAuthorizationURLString:@"/oauth/authorize" callbackURL:[NSURL URLWithString:@"af-twitter://success"] accessTokenURLString:@"/oauth/access_token" accessMethod:@"POST" scope:nil success:^(AFOAuth1Token *accessToken, id responseObject) { + self.twitterClient.responseSerializer = [AFJSONResponseSerializer serializer]; + [self.twitterClient GET:@"statuses/user_timeline.json" parameters:nil success:^(NSURLSessionDataTask *task, id responseObject) { + NSLog(@"%@", responseObject); + } failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"Error: %@", error); }]; } failure:^(NSError *error) {