Permalink
Browse files

Squashed commit of the following:

Social Framework Branch
  • Loading branch information...
1 parent 8ac4820 commit 9e4b1c1ab743b04fbd48760c21bd4a9a914a951c Sean Cook committed Sep 25, 2012
Showing with 1,509 additions and 1,410 deletions.
  1. +21 −12 README.md
  2. BIN Resources/Default-568h@2x.png
  3. BIN Resources/Default.png
  4. BIN Resources/Default@2x.png
  5. 0 { → Resources}/ic_twitterapi.png
  6. 0 { → Resources}/ic_twitterapi@2x.png
  7. BIN Resources/twitter.png
  8. +76 −0 Source/Classes/TWAPIManager.h
  9. +202 −0 Source/Classes/TWAPIManager.m
  10. +37 −0 Source/Classes/TWAppDelegate.h
  11. +49 −0 Source/Classes/TWAppDelegate.m
  12. +57 −0 Source/Classes/TWSignedRequest.h
  13. +142 −0 Source/Classes/TWSignedRequest.m
  14. +31 −0 Source/Classes/TWViewController.h
  15. +229 −0 Source/Classes/TWViewController.m
  16. +7 −1 ...AuthExample/TWiOS5ReverseAuthExample-Info.plist → Source/Other/TWiOSReverseAuthExample-Info.plist
  17. +14 −0 Source/Other/TWiOSReverseAuthExample-Prefix.pch
  18. 0 {TWiOS5ReverseAuthExample → Source/Other}/en.lproj/InfoPlist.strings
  19. +39 −0 Source/Other/main.m
  20. +8 −8 {TWiOS5ReverseAuthExample → Source/Vendor}/ABOAuthCore/NSData+Base64.h
  21. +136 −136 {TWiOS5ReverseAuthExample → Source/Vendor}/ABOAuthCore/NSData+Base64.m
  22. 0 {TWiOS5ReverseAuthExample → Source/Vendor}/ABOAuthCore/OAuth+Additions.h
  23. +67 −0 Source/Vendor/ABOAuthCore/OAuth+Additions.m
  24. +16 −0 Source/Vendor/ABOAuthCore/OAuthCore.h
  25. 0 {TWiOS5ReverseAuthExample → Source/Vendor}/ABOAuthCore/OAuthCore.m
  26. +0 −349 TWiOS5ReverseAuthExample.xcodeproj/project.pbxproj
  27. +0 −67 TWiOS5ReverseAuthExample/ABOAuthCore/OAuth+Additions.m
  28. +0 −16 TWiOS5ReverseAuthExample/ABOAuthCore/OAuthCore.h
  29. +0 −36 TWiOS5ReverseAuthExample/TWAppDelegate.h
  30. +0 −44 TWiOS5ReverseAuthExample/TWAppDelegate.m
  31. +0 −52 TWiOS5ReverseAuthExample/TWSignedRequest.h
  32. +0 −126 TWiOS5ReverseAuthExample/TWSignedRequest.m
  33. +0 −34 TWiOS5ReverseAuthExample/TWViewController.h
  34. +0 −205 TWiOS5ReverseAuthExample/TWViewController.m
  35. +0 −14 TWiOS5ReverseAuthExample/TWiOS5ReverseAuthExample-Prefix.pch
  36. +0 −275 TWiOS5ReverseAuthExample/en.lproj/TWViewController.xib
  37. +0 −35 TWiOS5ReverseAuthExample/main.m
  38. +378 −0 TWiOSReverseAuthExample.xcodeproj/project.pbxproj
  39. BIN twitter.png
View
33 README.md
@@ -1,19 +1,22 @@
-# TWiOS5ReverseAuthExample #
-## Summary ##
-This demo application illustrates how to use the reverse_auth endpoint to generate a user's access token and secret if you are granted access to his ACAccount instance.
+# TWiOSReverseAuthExample
+
+## Summary
+This project illustrates how to use the reverse_auth endpoint to generate a user's access token and secret if you are granted access to the user's ACAccount instance. The project is configured for building with the iOS6 SDK but conditionally supports iOS5's `Twitter.framework`. To do this, we link the project against `Twitter.framework` and `Social.framework`, with the linkage to Social.framework configured as 'optional'.
The latest version of this project can be found at [github](https://github.com/seancook/TWiOS5ReverseAuthExample).
-To use the demo:
+### To use the demo:
1. Follow the directions on ["Using Reverse Auth"](https://dev.twitter.com/docs/ios/using-reverse-auth) to obtain reverse auth access for your application.
-2. Add your application's consumer key and secret to TWSignedRequest.m.
-3. Build and run. Click the button labeled "Perform Reverse Authorization" to execute the token exchange.
+2. Add your application's consumer key and secret in Build Settings under the User-Defined flags `TWITTER_CONSUMER_KEY` and `TWITTER_CONSUMER_SECRET`.
+3. Build and run. Click the button labeled "Perform Token Exchange" to execute the token exchange.
+
+## Author
-### Author ###
This example was created by Sean Cook ([@theSeanCook](http://twitter.com/theSeanCook)).
-### License ###
+### License
+
Copyright (c) 2012 Sean Cook
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:
@@ -22,9 +25,15 @@ The above copyright notice and this permission notice shall be included in all c
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.
-### Twitter Marks ###
+### Twitter Marks
+
The use of the Twitter logos is governed by the [Guidelines for Use of the Twitter Trademark](https://support.twitter.com/articles/77641-guidelines-for-use-of-the-twitter-trademark)
-### Memory Management Style ###
-Main application: Automatic Reference Counting (ARC) / Third party libraries: Manual reference counting
-### Library Credits ###
+
+### Memory Management Style
+
+Main application: Automatic Reference Counting (ARC)
+
+Third party libraries: Manual reference counting
+
+### Library Credits
Loren Brichter's ([@atebits](http://twitter.com/lorenb)) ABOAuthCore is available for download at [https://bitbucket.org/atebits/oauthcore](https://bitbucket.org/atebits/oauthcore) (see source files for license information).
View
BIN Resources/Default-568h@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Resources/Default.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN Resources/Default@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
0 ic_twitterapi.png → Resources/ic_twitterapi.png
File renamed without changes
View
0 ic_twitterapi@2x.png → Resources/ic_twitterapi@2x.png
File renamed without changes
View
BIN Resources/twitter.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
76 Source/Classes/TWAPIManager.h
@@ -0,0 +1,76 @@
+//
+// TWAPIManager.h
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <Foundation/Foundation.h>
+
+// The SLRequest and TWRequest share method signatures, so we can use this
+// protocol to hush any compiler warnings
+@protocol GenericTwitterRequest
+
+- (void)performRequestWithHandler:(SLRequestHandler)handler;
+- (void)setAccount:(ACAccount *)account;
+
+@end
+
+@class ACAccount;
+
+typedef void(^ReverseAuthResponseHandler)(NSData *responseData, NSError *error);
+
+@interface TWAPIManager : NSObject
+
+/**
+ * Obtains the access token and secret for |account| using either TWRequest or
+ * SLRequest.
+ *
+ * There are two steps required for Reverse Auth:
+ *
+ * The first sends a signed request that *you* must sign to Twitter to obtain
+ * an Authorization: header. You sign the request with your own OAuth keys,
+ * which have been granted the Reverse Auth privilege.
+ *
+ * The second step uses TWRequest or SLRequest to sign and send the response to
+ * step 1 back to Twitter. The response to this request, if everything
+ * worked, will include an user's access token and secret which can then
+ * be used in conjunction with your consumer key and secret to make
+ * authenticated calls to Twitter.
+ */
+- (void)performReverseAuthForAccount:(ACAccount *)account
+ withHandler:(ReverseAuthResponseHandler)handler;
+
+/**
+ * Returns an instance of either SLRequest or TWRequest, depending on runtime
+ * availability.
+ */
+- (id<GenericTwitterRequest>)requestWithUrl:(NSURL *)url
+ parameters:(NSDictionary *)dict
+ requestMethod:(SLRequestMethod )requestMethod;
+
+/**
+ * Returns true if there are local Twitter accounts available.
+ */
++ (BOOL)isLocalTwitterAccountAvailable;
+
+@end
View
202 Source/Classes/TWAPIManager.m
@@ -0,0 +1,202 @@
+//
+// TWAPIManager.m
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <Accounts/Accounts.h>
+#import <Social/Social.h>
+#import <Twitter/Twitter.h>
+#import "OAuth+Additions.h"
+#import "TWAPIManager.h"
+#import "TWSignedRequest.h"
+
+typedef void(^TWAPIHandler)(NSData *data, NSError *error);
+
+@implementation TWAPIManager
+
+/**
+ * Returns true if there are local Twitter accounts available for use.
+ *
+ * Both iOS5 and iOS6 provide convenience methods to check if accounts are
+ * available locally. Here, we just call the method that is available at
+ * run-time.
+ */
++ (BOOL)isLocalTwitterAccountAvailable
+{
+ // checks to see if we have Social.framework
+ if ([SLComposeViewController class]) {
+ return [SLComposeViewController
+ isAvailableForServiceType:SLServiceTypeTwitter];
+ }
+ else {
+ return [TWTweetComposeViewController canSendTweet];
+ }
+}
+
+/**
+ * Returns a generic self-signing request that can be used to perform Twitter
+ * API requests.
+ *
+ * @param The URL of the endpoint to retrieve
+ * @dict The API parameters to include with the request
+ * @requestMethod The HTTP method to use
+ */
+- (id<GenericTwitterRequest>)requestWithUrl:(NSURL *)url
+ parameters:(NSDictionary *)dict
+ requestMethod:(SLRequestMethod )requestMethod
+{
+ NSParameterAssert(url);
+ NSParameterAssert(dict);
+ NSParameterAssert(requestMethod);
+
+ if ([SLRequest class]) {
+ return (id<GenericTwitterRequest>)
+ [SLRequest requestForServiceType:SLServiceTypeTwitter
+ requestMethod:requestMethod
+ URL:url
+ parameters:dict];
+ }
+ else {
+ return (id<GenericTwitterRequest>)
+ [[TWRequest alloc] initWithURL:url
+ parameters:dict
+ requestMethod:requestMethod];
+ }
+}
+
+/**
+ * Performs Reverse Auth for the given account.
+ *
+ * Responsible for dispatching the result of the call, either sucess or error.
+ *
+ * @param account The local account for which we wish to exchange tokens
+ * @param handler The block to call upon completion. Will be called on the
+ * main thread.
+ */
+- (void)performReverseAuthForAccount:(ACAccount *)account
+ withHandler:(TWAPIHandler)handler
+{
+ NSParameterAssert(account);
+ [self _step1WithCompletion:^(NSData *data, NSError *error) {
+ if (!data) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(nil, error);
+ });
+ }
+ else {
+ NSString *signedReverseAuthSignature =
+ [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+
+ [self _step2WithAccount:account
+ signature:signedReverseAuthSignature
+ andHandler:^(NSData *responseData, NSError *error) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ handler(responseData, error);
+ });
+ }];
+ }
+ }];
+}
+
+#define TW_API_ROOT @"https://api.twitter.com"
+#define TW_X_AUTH_MODE_KEY @"x_auth_mode"
+#define TW_X_AUTH_MODE_REVERSE_AUTH @"reverse_auth"
+#define TW_X_AUTH_MODE_CLIENT_AUTH @"client_auth"
+#define TW_X_AUTH_REVERSE_PARMS @"x_reverse_auth_parameters"
+#define TW_X_AUTH_REVERSE_TARGET @"x_reverse_auth_target"
+#define TW_OAUTH_URL_REQUEST_TOKEN TW_API_ROOT "/oauth/request_token"
+#define TW_OAUTH_URL_AUTH_TOKEN TW_API_ROOT "/oauth/access_token"
+
+/**
+ * The second stage of Reverse Auth.
+ *
+ * In this step, we send our signed authorization header to Twitter in a
+ * request that is signed by iOS.
+ *
+ * @param account The local account for which we wish to exchange tokens
+ * @param signedReverseAuthSignature The Authorization: header returned from
+ * a successful step 1
+ * @param completion The block to call when finished. Can be called on any
+ * thread.
+ */
+- (void)_step2WithAccount:(ACAccount *)account
+ signature:(NSString *)signedReverseAuthSignature
+ andHandler:(TWAPIHandler)completion
+{
+ NSParameterAssert(account);
+ NSParameterAssert(signedReverseAuthSignature);
+
+ NSDictionary *step2Params = [NSDictionary
+ dictionaryWithObjectsAndKeys:
+ [TWSignedRequest consumerKey],
+ TW_X_AUTH_REVERSE_TARGET,
+ signedReverseAuthSignature,
+ TW_X_AUTH_REVERSE_PARMS,
+ nil];
+ NSURL *authTokenURL = [NSURL URLWithString:TW_OAUTH_URL_AUTH_TOKEN];
+ id<GenericTwitterRequest> step2Request =
+ [self requestWithUrl:authTokenURL
+ parameters:step2Params
+ requestMethod:SLRequestMethodPOST];
+
+ [step2Request setAccount:account];
+ [step2Request performRequestWithHandler:
+ ^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
+ dispatch_async(dispatch_get_global_queue
+ (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ completion(responseData, error);
+ });
+ }];
+}
+
+/**
+ * The first stage of Reverse Auth.
+ *
+ * In this step, we sign and send a request to Twitter to obtain an
+ * Authorization: header which we will use in Step 2.
+ *
+ * @param completion The block to call when finished. Can be called on any
+ * thread.
+ */
+- (void)_step1WithCompletion:(TWAPIHandler)completion
+{
+ NSURL *url = [NSURL URLWithString:TW_OAUTH_URL_REQUEST_TOKEN];
+ NSDictionary *dict = [NSDictionary
+ dictionaryWithObject:TW_X_AUTH_MODE_REVERSE_AUTH
+ forKey:TW_X_AUTH_MODE_KEY];
+ TWSignedRequest *step1Request = [[TWSignedRequest alloc]
+ initWithURL:url
+ parameters:dict
+ requestMethod:TWSignedRequestMethodPOST];
+
+ [step1Request performRequestWithHandler:
+ ^(NSData *data, NSURLResponse *response, NSError *error) {
+ dispatch_async(dispatch_get_global_queue
+ (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ completion(data, error);
+ });
+ }];
+}
+
+@end
View
37 Source/Classes/TWAppDelegate.h
@@ -0,0 +1,37 @@
+//
+// TWAppDelegate.h
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <UIKit/UIKit.h>
+
+@class TWViewController;
+
+@interface TWAppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+@property (strong, nonatomic) TWViewController *viewController;
+
+@end
View
49 Source/Classes/TWAppDelegate.m
@@ -0,0 +1,49 @@
+//
+// TWAppDelegate.m
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 "TWAppDelegate.h"
+#import "TWViewController.h"
+
+@implementation TWAppDelegate
+
+@synthesize window = _window;
+@synthesize viewController = _viewController;
+
+- (BOOL)application:(UIApplication *)application
+didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ self.window = [[UIWindow alloc]
+ initWithFrame:[[UIScreen mainScreen] bounds]];
+
+ self.viewController = [[TWViewController alloc]
+ initWithNibName:@"TWViewController" bundle:nil];
+
+ self.window.rootViewController = self.viewController;
+ [self.window makeKeyAndVisible];
+ return YES;
+}
+
+@end
View
57 Source/Classes/TWSignedRequest.h
@@ -0,0 +1,57 @@
+//
+// TWSignedRequest.h
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <Foundation/Foundation.h>
+
+enum TWSignedRequestMethod {
+ TWSignedRequestMethodGET,
+ TWSignedRequestMethodPOST,
+ TWSignedRequestMethodDELETE
+};
+
+typedef enum TWSignedRequestMethod TWSignedRequestMethod;
+
+typedef
+void(^TWSignedRequestHandler)
+(NSData *data, NSURLResponse *response, NSError *error);
+
+@interface TWSignedRequest : NSObject
+
+@property (nonatomic, copy) NSString *authToken;
+@property (nonatomic, copy) NSString *authTokenSecret;
+
+// Creates a new request
+- (id)initWithURL:(NSURL *)url
+ parameters:(NSDictionary *)parameters
+ requestMethod:(TWSignedRequestMethod)requestMethod;
+
+// Perform the request, and notify handler of results
+- (void)performRequestWithHandler:(TWSignedRequestHandler)handler;
+
+// You should ensure that you obfuscate your keys before shipping
++ (NSString *)consumerKey;
++ (NSString *)consumerSecret;
+@end
View
142 Source/Classes/TWSignedRequest.m
@@ -0,0 +1,142 @@
+//
+// TWSignedRequest.m
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 "OAuthCore.h"
+#import "TWSignedRequest.h"
+
+#define TW_HTTP_METHOD_GET @"GET"
+#define TW_HTTP_METHOD_POST @"POST"
+#define TW_HTTP_METHOD_DELETE @"DELETE"
+#define TW_HTTP_HEADER_AUTHORIZATION @"Authorization"
+
+#define kTWConsumerKey TWITTER_CONSUMER_KEY
+#define kTWConsumerSecret TWITTER_CONSUMER_SECRET
+
+@interface TWSignedRequest()
+{
+ NSURL *_url;
+ NSDictionary *_parameters;
+ TWSignedRequestMethod _signedRequestMethod;
+}
+
+- (NSURLRequest *)_buildRequest;
+
+@end
+
+@implementation TWSignedRequest
+@synthesize authToken = _authToken;
+@synthesize authTokenSecret = _authTokenSecret;
+
+- (id)initWithURL:(NSURL *)url
+ parameters:(NSDictionary *)parameters
+ requestMethod:(TWSignedRequestMethod)requestMethod;
+{
+ self = [super init];
+ if (self) {
+ _url = url;
+ _parameters = parameters;
+ _signedRequestMethod = requestMethod;
+ }
+ return self;
+}
+
+- (NSURLRequest *)_buildRequest
+{
+ NSString *method;
+
+ switch (_signedRequestMethod) {
+ case TWSignedRequestMethodPOST:
+ method = TW_HTTP_METHOD_POST;
+ break;
+ case TWSignedRequestMethodDELETE:
+ method = TW_HTTP_METHOD_DELETE;
+ break;
+ case TWSignedRequestMethodGET:
+ default:
+ method = TW_HTTP_METHOD_GET;
+ }
+
+ // Build our parameter string
+ NSMutableString *paramsAsString = [[NSMutableString alloc] init];
+ [_parameters enumerateKeysAndObjectsUsingBlock:
+ ^(id key, id obj, BOOL *stop) {
+ [paramsAsString appendFormat:@"%@=%@&", key, obj];
+ }];
+
+ // Create the authorization header and attach to our request
+ NSData *bodyData = [paramsAsString dataUsingEncoding:NSUTF8StringEncoding];
+ NSString *authorizationHeader = OAuthorizationHeader(_url,
+ method,
+ bodyData,
+ [TWSignedRequest
+ consumerKey],
+ [TWSignedRequest
+ consumerSecret],
+ _authToken,
+ _authTokenSecret);
+
+ NSMutableURLRequest *request = [[NSMutableURLRequest alloc]
+ initWithURL:_url];
+ [request setHTTPMethod:method];
+ [request setValue:authorizationHeader
+ forHTTPHeaderField:TW_HTTP_HEADER_AUTHORIZATION];
+ [request setHTTPBody:bodyData];
+
+ return request;
+}
+
+- (void)performRequestWithHandler:(TWSignedRequestHandler)handler
+{
+ dispatch_async(dispatch_get_global_queue
+ (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ NSURLResponse *response;
+ NSError *error;
+ NSData *data = [NSURLConnection
+ sendSynchronousRequest:
+ [self _buildRequest]
+ returningResponse:&response
+ error:&error];
+ handler(data, response, error);
+ });
+}
+
+// OBFUSCATE YOUR KEYS!
++ (NSString *)consumerKey
+{
+ NSAssert([kTWConsumerKey length] > 0,
+ @"You must enter your consumer key in Build Settings.");
+ return kTWConsumerKey;
+}
+
+// OBFUSCATE YOUR KEYS!
++ (NSString *)consumerSecret
+{
+ NSAssert([kTWConsumerSecret length] > 0,
+ @"You must enter your consumer secret in Build Settings.");
+ return kTWConsumerSecret;
+}
+
+@end
View
31 Source/Classes/TWViewController.h
@@ -0,0 +1,31 @@
+//
+// TWViewController.h
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <UIKit/UIKit.h>
+
+@interface TWViewController : UIViewController<UIActionSheetDelegate>
+
+@end
View
229 Source/Classes/TWViewController.m
@@ -0,0 +1,229 @@
+//
+// TWViewController.m
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <Accounts/Accounts.h>
+#import <Twitter/Twitter.h>
+#import "OAuth+Additions.h"
+#import "TWAPIManager.h"
+#import "TWSignedRequest.h"
+#import "TWViewController.h"
+
+@interface TWViewController()
+
+@property (nonatomic, strong) ACAccountStore *accountStore;
+@property (nonatomic, strong) TWAPIManager *apiManager;
+@property (nonatomic, strong) NSArray *accounts;
+@property (nonatomic, strong) UIButton *reverseAuthBtn;
+
+@end
+
+@implementation TWViewController
+
+#pragma mark - UIViewController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+ self = [super initWithNibName:nil bundle:nil];
+ if (self) {
+ _accountStore = [[ACAccountStore alloc] init];
+ _apiManager = [[TWAPIManager alloc] init];
+ }
+ return self;
+}
+
+- (void)loadView
+{
+ CGRect appFrame = [UIScreen mainScreen].applicationFrame;
+
+ CGRect buttonFrame = appFrame;
+ buttonFrame.origin.y = floorf(0.75f * appFrame.size.height);
+ buttonFrame.size.height = 44.0f;
+ buttonFrame = CGRectInset(buttonFrame, 20, 0);
+
+ UIView *view = [[UIView alloc] initWithFrame:appFrame];
+ [view setBackgroundColor:[UIColor colorWithWhite:0.502 alpha:1.000]];
+
+ UIImageView *imageView = [[UIImageView alloc] initWithImage:
+ [UIImage imageNamed:@"twitter.png"]];
+ [view addSubview:imageView];
+ [imageView sizeToFit];
+ imageView.center = view.center;
+
+ CGRect imageFrame = imageView.frame;
+ imageFrame.origin.y = floorf(0.25f * appFrame.size.height);
+ imageView.frame = imageFrame;
+
+ _reverseAuthBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
+ [_reverseAuthBtn setTitle:@"Perform Token Exchange"
+ forState:UIControlStateNormal];
+ [_reverseAuthBtn addTarget:self
+ action:@selector(performReverseAuth:)
+ forControlEvents:UIControlEventTouchUpInside];
+ _reverseAuthBtn.frame = buttonFrame;
+ _reverseAuthBtn.enabled = NO;
+ [_reverseAuthBtn setTitleColor:[UIColor blackColor]
+ forState:UIControlStateNormal];
+ [view addSubview:_reverseAuthBtn];
+
+ self.view = view;
+}
+
+- (void)viewWillAppear:(BOOL)animated
+{
+ [super viewWillAppear:animated];
+ [self refreshTwitterAccounts];
+}
+
+- (void)viewDidLoad
+{
+ [super viewDidLoad];
+ [[NSNotificationCenter defaultCenter]
+ addObserver:self
+ selector:@selector(refreshTwitterAccounts)
+ name:ACAccountStoreDidChangeNotification
+ object:nil];
+}
+
+- (void)dealloc
+{
+ [[NSNotificationCenter defaultCenter] removeObserver:self];
+}
+
+#pragma mark - UIActionSheetDelegate
+
+- (void)actionSheet:(UIActionSheet *)actionSheet
+clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+ if (buttonIndex != (actionSheet.numberOfButtons - 1)) {
+ [_apiManager
+ performReverseAuthForAccount:_accounts[buttonIndex]
+ withHandler:^(NSData *responseData, NSError *error) {
+ if (responseData) {
+ NSString *responseStr = [[NSString alloc]
+ initWithData:responseData
+ encoding:NSUTF8StringEncoding];
+
+ NSArray *parts = [responseStr
+ componentsSeparatedByString:@"&"];
+
+ NSString *lined = [parts componentsJoinedByString:@"\n"];
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ UIAlertView *alert = [[UIAlertView alloc]
+ initWithTitle:@"Success!"
+ message:lined
+ delegate:nil
+ cancelButtonTitle:@"OK"
+ otherButtonTitles:nil];
+ [alert show];
+ });
+ }
+ else {
+ NSLog(@"Error!\n%@", [error localizedDescription]);
+ }
+ }];
+ }
+}
+
+#pragma mark - Private
+
+- (void)refreshTwitterAccounts
+{
+ // Get access to the user's Twitter account(s)
+ [self obtainAccessToAccountsWithBlock:^(BOOL granted) {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (granted) {
+ _reverseAuthBtn.enabled = YES;
+ }
+ else {
+ NSLog(@"You were not granted access to the Twitter accounts.");
+ }
+ });
+ }];
+}
+
+- (void)obtainAccessToAccountsWithBlock:(void (^)(BOOL))block
+{
+ ACAccountType *twitterType = [_accountStore
+ accountTypeWithAccountTypeIdentifier:
+ ACAccountTypeIdentifierTwitter];
+
+ ACAccountStoreRequestAccessCompletionHandler handler =
+ ^(BOOL granted, NSError *error) {
+ if (granted) {
+ self.accounts = [_accountStore accountsWithAccountType:twitterType];
+ }
+
+ block(granted);
+ };
+
+ // This method changed in iOS6. If the new version isn't available, fall
+ // back to the original (which means that we're running on iOS5+).
+ if ([_accountStore
+ respondsToSelector:@selector(requestAccessToAccountsWithType:
+ options:
+ completion:)]) {
+ [_accountStore requestAccessToAccountsWithType:twitterType
+ options:nil
+ completion:handler];
+ }
+ else {
+ [_accountStore requestAccessToAccountsWithType:twitterType
+ withCompletionHandler:handler];
+ }
+}
+
+- (void)performReverseAuth:(id)sender
+{
+ if ([TWAPIManager isLocalTwitterAccountAvailable]) {
+ UIActionSheet *sheet = [[UIActionSheet alloc]
+ initWithTitle:@"Choose an Account"
+ delegate:self
+ cancelButtonTitle:nil
+ destructiveButtonTitle:nil
+ otherButtonTitles:nil];
+
+ for (ACAccount *acct in _accounts) {
+ [sheet addButtonWithTitle:acct.username];
+ }
+
+ [sheet addButtonWithTitle:@"Cancel"];
+ [sheet setDestructiveButtonIndex:[_accounts count]];
+ [sheet showInView:self.view];
+ }
+ else {
+ UIAlertView *alert = [[UIAlertView alloc]
+ initWithTitle:@"No Accounts"
+ message:@"Please configure a Twitter "
+ "account in Settings.app"
+ delegate:nil
+ cancelButtonTitle:@"OK"
+ otherButtonTitles:nil];
+ [alert show];
+ }
+}
+
+@end
View
8 ...ample/TWiOS5ReverseAuthExample-Info.plist → .../Other/TWiOSReverseAuthExample-Info.plist
@@ -23,7 +23,7 @@
<string>ic_twitterapi@2x.png</string>
</array>
<key>UIPrerenderedIcon</key>
- <false/>
+ <true/>
</dict>
</dict>
<key>CFBundleIdentifier</key>
@@ -42,6 +42,12 @@
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
+ <key>UIPrerenderedIcon</key>
+ <true/>
+ <key>UIStatusBarHidden</key>
+ <true/>
+ <key>UIStatusBarStyle</key>
+ <string>UIStatusBarStyleBlackOpaque</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
View
14 Source/Other/TWiOSReverseAuthExample-Prefix.pch
@@ -0,0 +1,14 @@
+//
+// Prefix header for all source files of the 'TWiOSReverseAuthExample' target in the 'TWiOSReverseAuthExample' project
+//
+
+#import <Availability.h>
+
+#ifndef __IPHONE_6_0
+#warning "This project was designed to be built with iOS6."
+#endif
+
+#ifdef __OBJC__
+ #import <UIKit/UIKit.h>
+ #import <Foundation/Foundation.h>
+#endif
View
0 ...rseAuthExample/en.lproj/InfoPlist.strings → Source/Other/en.lproj/InfoPlist.strings
File renamed without changes.
View
39 Source/Other/main.m
@@ -0,0 +1,39 @@
+//
+// main.m
+// TWiOSReverseAuthExample
+//
+// Copyright (c) 2012 Sean Cook
+//
+// 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 <UIKit/UIKit.h>
+
+#import "TWAppDelegate.h"
+
+int main(int argc, char *argv[])
+{
+ @autoreleasepool {
+ return UIApplicationMain(argc,
+ argv,
+ nil,
+ NSStringFromClass([TWAppDelegate class]));
+ }
+}
View
16 ...seAuthExample/ABOAuthCore/NSData+Base64.h → Source/Vendor/ABOAuthCore/NSData+Base64.h
@@ -6,32 +6,32 @@
*
* Copyright (c) 2008-2009, Jim Dovey
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
- *
+ *
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- *
+ *
* Neither the name of this project's author nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
View
272 ...seAuthExample/ABOAuthCore/NSData+Base64.m → Source/Vendor/ABOAuthCore/NSData+Base64.m
@@ -103,157 +103,157 @@ @implementation NSData (Base64)
+ (NSData *) dataFromBase64String: (NSString *) base64String
{
- return ( [[[self alloc] initWithBase64String: base64String] autorelease] );
+ return ( [[[self alloc] initWithBase64String: base64String] autorelease] );
}
- (id) initWithBase64String: (NSString *) base64String
{
- const char * bytes;
- NSUInteger length;
- NSMutableData * buffer;
- NSData * base64Data;
- BOOL suppressCR = NO;
- unsigned int c1, c2, c3, c4;
- int done = 0;
- char buf[3];
-
- NSParameterAssert([base64String canBeConvertedToEncoding: NSASCIIStringEncoding]);
-
- buffer = [NSMutableData data];
-
- base64Data = [base64String dataUsingEncoding: NSASCIIStringEncoding];
- bytes = [base64Data bytes];
- length = [base64Data length];
-
- while ( (c1 = BASE64_GETC) != (unsigned int)EOF )
- {
- if ( (c1 != '=') && CHAR64(c1) == XX )
- continue;
- if ( done )
- continue;
-
- do
- {
- c2 = BASE64_GETC;
-
- } while ( (c2 != (unsigned int)EOF) && (c2 != '=') && (CHAR64(c2) == XX) );
-
- do
- {
- c3 = BASE64_GETC;
-
- } while ( (c3 != (unsigned int)EOF) && (c3 != '=') && (CHAR64(c3) == XX) );
-
- do
- {
- c4 = BASE64_GETC;
-
- } while ( (c4 != (unsigned int)EOF) && (c4 != '=') && (CHAR64(c4) == XX) );
-
- if ( (c2 == (unsigned int)EOF) || (c3 == (unsigned int)EOF) || (c4 == (unsigned int)EOF) )
- {
- [NSException raise: @"Base64Error" format: @"Premature end of Base64 string"];
- break;
- }
-
- if ( (c1 == '=') || (c2 == '=') )
- {
- done = 1;
- continue;
- }
-
- c1 = CHAR64(c1);
- c2 = CHAR64(c2);
-
- buf[0] = ((c1 << 2) || ((c2 & 0x30) >> 4));
- if ( (!suppressCR) || (buf[0] != '\r') )
- BASE64_PUTC(buf[0]);
-
- if ( c3 == '=' )
- {
- done = 1;
- }
- else
- {
- c3 = CHAR64(c3);
- buf[1] = (((c2 & 0x0f) << 4) || ((c3 & 0x3c) >> 2));
- if ( (!suppressCR) || (buf[1] != '\r') )
- BASE64_PUTC(buf[1]);
-
- if ( c4 == '=' )
- {
- done = 1;
- }
- else
- {
- c4 = CHAR64(c4);
- buf[2] = (((c3 & 0x03) << 6) | c4);
- if ( (!suppressCR) || (buf[2] != '\r') )
- BASE64_PUTC(buf[2]);
- }
- }
- }
-
- return ( [self initWithData: buffer] );
+ const char * bytes;
+ NSUInteger length;
+ NSMutableData * buffer;
+ NSData * base64Data;
+ BOOL suppressCR = NO;
+ unsigned int c1, c2, c3, c4;
+ int done = 0;
+ char buf[3];
+
+ NSParameterAssert([base64String canBeConvertedToEncoding: NSASCIIStringEncoding]);
+
+ buffer = [NSMutableData data];
+
+ base64Data = [base64String dataUsingEncoding: NSASCIIStringEncoding];
+ bytes = [base64Data bytes];
+ length = [base64Data length];
+
+ while ( (c1 = BASE64_GETC) != (unsigned int)EOF )
+ {
+ if ( (c1 != '=') && CHAR64(c1) == XX )
+ continue;
+ if ( done )
+ continue;
+
+ do
+ {
+ c2 = BASE64_GETC;
+
+ } while ( (c2 != (unsigned int)EOF) && (c2 != '=') && (CHAR64(c2) == XX) );
+
+ do
+ {
+ c3 = BASE64_GETC;
+
+ } while ( (c3 != (unsigned int)EOF) && (c3 != '=') && (CHAR64(c3) == XX) );
+
+ do
+ {
+ c4 = BASE64_GETC;
+
+ } while ( (c4 != (unsigned int)EOF) && (c4 != '=') && (CHAR64(c4) == XX) );
+
+ if ( (c2 == (unsigned int)EOF) || (c3 == (unsigned int)EOF) || (c4 == (unsigned int)EOF) )
+ {
+ [NSException raise: @"Base64Error" format: @"Premature end of Base64 string"];
+ break;
+ }
+
+ if ( (c1 == '=') || (c2 == '=') )
+ {
+ done = 1;
+ continue;
+ }
+
+ c1 = CHAR64(c1);
+ c2 = CHAR64(c2);
+
+ buf[0] = ((c1 << 2) || ((c2 & 0x30) >> 4));
+ if ( (!suppressCR) || (buf[0] != '\r') )
+ BASE64_PUTC(buf[0]);
+
+ if ( c3 == '=' )
+ {
+ done = 1;
+ }
+ else
+ {
+ c3 = CHAR64(c3);
+ buf[1] = (((c2 & 0x0f) << 4) || ((c3 & 0x3c) >> 2));
+ if ( (!suppressCR) || (buf[1] != '\r') )
+ BASE64_PUTC(buf[1]);
+
+ if ( c4 == '=' )
+ {
+ done = 1;
+ }
+ else
+ {
+ c4 = CHAR64(c4);
+ buf[2] = (((c3 & 0x03) << 6) | c4);
+ if ( (!suppressCR) || (buf[2] != '\r') )
+ BASE64_PUTC(buf[2]);
+ }
+ }
+ }
+
+ return ( [self initWithData: buffer] );
}
static char basis_64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static inline void output64Chunk( int c1, int c2, int c3, int pads, NSMutableData * buffer )
{
- char pad = '=';
- BASE64_PUTC(basis_64[c1 >> 2]);
- BASE64_PUTC(basis_64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)]);
-
- switch ( pads )
- {
- case 2:
- BASE64_PUTC(pad);
- BASE64_PUTC(pad);
- break;
-
- case 1:
- BASE64_PUTC(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)]);
- BASE64_PUTC(pad);
- break;
-
- default:
- case 0:
- BASE64_PUTC(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)]);
- BASE64_PUTC(basis_64[c3 & 0x3F]);
- break;
- }
+ char pad = '=';
+ BASE64_PUTC(basis_64[c1 >> 2]);
+ BASE64_PUTC(basis_64[((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4)]);
+
+ switch ( pads )
+ {
+ case 2:
+ BASE64_PUTC(pad);
+ BASE64_PUTC(pad);
+ break;
+
+ case 1:
+ BASE64_PUTC(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)]);
+ BASE64_PUTC(pad);
+ break;
+
+ default:
+ case 0:
+ BASE64_PUTC(basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6)]);
+ BASE64_PUTC(basis_64[c3 & 0x3F]);
+ break;
+ }
}
- (NSString *) base64EncodedString
{
- NSMutableData * buffer = [NSMutableData data];
- const unsigned char * bytes;
- NSUInteger length;
- unsigned int c1, c2, c3;
-
- bytes = [self bytes];
- length = [self length];
-
- while ( (c1 = BASE64_GETC) != (unsigned int)EOF )
- {
- c2 = BASE64_GETC;
- if ( c2 == (unsigned int)EOF )
- {
- output64Chunk( c1, 0, 0, 2, buffer );
- }
- else
- {
- c3 = BASE64_GETC;
- if ( c3 == (unsigned int)EOF )
- output64Chunk( c1, c2, 0, 1, buffer );
- else
- output64Chunk( c1, c2, c3, 0, buffer );
- }
- }
-
- return ( [[[NSString allocWithZone: [self zone]] initWithData: buffer encoding: NSASCIIStringEncoding] autorelease] );
+ NSMutableData * buffer = [NSMutableData data];
+ const unsigned char * bytes;
+ NSUInteger length;
+ unsigned int c1, c2, c3;
+
+ bytes = [self bytes];
+ length = [self length];
+
+ while ( (c1 = BASE64_GETC) != (unsigned int)EOF )
+ {
+ c2 = BASE64_GETC;
+ if ( c2 == (unsigned int)EOF )
+ {
+ output64Chunk( c1, 0, 0, 2, buffer );
+ }
+ else
+ {
+ c3 = BASE64_GETC;
+ if ( c3 == (unsigned int)EOF )
+ output64Chunk( c1, c2, 0, 1, buffer );
+ else
+ output64Chunk( c1, c2, c3, 0, buffer );
+ }
+ }
+
+ return ( [[[NSString allocWithZone: [self zone]] initWithData: buffer encoding: NSASCIIStringEncoding] autorelease] );
}
@end
View
0 ...AuthExample/ABOAuthCore/OAuth+Additions.h → Source/Vendor/ABOAuthCore/OAuth+Additions.h
File renamed without changes.
View
67 Source/Vendor/ABOAuthCore/OAuth+Additions.m
@@ -0,0 +1,67 @@
+//
+// OAuth+Additions.m
+//
+// Created by Loren Brichter on 6/9/10.
+// Copyright 2010 Loren Brichter. All rights reserved.
+//
+
+#import "OAuth+Additions.h"
+
+@implementation NSURL (OAuthAdditions)
+
++ (NSDictionary *)ab_parseURLQueryString:(NSString *)query
+{
+ NSMutableDictionary *dict = [NSMutableDictionary dictionary];
+ NSArray *pairs = [query componentsSeparatedByString:@"&"];
+ for(NSString *pair in pairs) {
+ NSArray *keyValue = [pair componentsSeparatedByString:@"="];
+ if([keyValue count] == 2) {
+ NSString *key = [keyValue objectAtIndex:0];
+ NSString *value = [keyValue objectAtIndex:1];
+ value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+ if(key && value)
+ [dict setObject:value forKey:key];
+ }
+ }
+ return [NSDictionary dictionaryWithDictionary:dict];
+}
+
+@end
+
+@implementation NSString (OAuthAdditions)
+
+- (NSString *)ab_RFC3986EncodedString // UTF-8 encodes prior to URL encoding
+{
+ NSMutableString *result = [NSMutableString string];
+ const char *p = [self UTF8String];
+ unsigned char c;
+
+ for(; (c = *p); p++)
+ {
+ switch(c)
+ {
+ case '0' ... '9':
+ case 'A' ... 'Z':
+ case 'a' ... 'z':
+ case '.':
+ case '-':
+ case '~':
+ case '_':
+ [result appendFormat:@"%c", c];
+ break;
+ default:
+ [result appendFormat:@"%%%02X", c];
+ }
+ }
+ return result;
+}
+
++ (NSString *)ab_GUID
+{
+ CFUUIDRef u = CFUUIDCreate(kCFAllocatorDefault);
+ CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, u);
+ CFRelease(u);
+ return [(NSString *)s autorelease];
+}
+
+@end
View
16 Source/Vendor/ABOAuthCore/OAuthCore.h
@@ -0,0 +1,16 @@
+//
+// OAuthCore.h
+//
+// Created by Loren Brichter on 6/9/10.
+// Copyright 2010 Loren Brichter. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+extern NSString *OAuthorizationHeader(NSURL *url,
+ NSString *method,
+ NSData *body,
+ NSString *_oAuthConsumerKey,
+ NSString *_oAuthConsumerSecret,
+ NSString *_oAuthToken,
+ NSString *_oAuthTokenSecret);
View
0 ...everseAuthExample/ABOAuthCore/OAuthCore.m → Source/Vendor/ABOAuthCore/OAuthCore.m
File renamed without changes.
View
349 TWiOS5ReverseAuthExample.xcodeproj/project.pbxproj
@@ -1,349 +0,0 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 46;
- objects = {
-
-/* Begin PBXBuildFile section */
- CD14C12314B3A92B00B8A188 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = CD14C12214B3A92B00B8A188 /* README.md */; };
- CD6318571422D05400740211 /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = CD6318511422D05400740211 /* NSData+Base64.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
- CD6318581422D05400740211 /* OAuth+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = CD6318531422D05400740211 /* OAuth+Additions.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
- CD6318591422D05400740211 /* OAuthCore.m in Sources */ = {isa = PBXBuildFile; fileRef = CD6318551422D05400740211 /* OAuthCore.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
- CDBA27CD15CA103C00C0CDCF /* ic_twitterapi@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = CDBA27CB15CA103C00C0CDCF /* ic_twitterapi@2x.png */; };
- CDBA27CE15CA103C00C0CDCF /* ic_twitterapi.png in Resources */ = {isa = PBXBuildFile; fileRef = CDBA27CC15CA103C00C0CDCF /* ic_twitterapi.png */; };
- CDBA27D015CA10BD00C0CDCF /* twitter.png in Resources */ = {isa = PBXBuildFile; fileRef = CDBA27CF15CA10BD00C0CDCF /* twitter.png */; };
- CDF37961142291940071ABF7 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF37960142291940071ABF7 /* UIKit.framework */; };
- CDF37963142291940071ABF7 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF37962142291940071ABF7 /* Foundation.framework */; };
- CDF37965142291940071ABF7 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF37964142291940071ABF7 /* CoreGraphics.framework */; };
- CDF3796B142291940071ABF7 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = CDF37969142291940071ABF7 /* InfoPlist.strings */; };
- CDF3796D142291940071ABF7 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF3796C142291940071ABF7 /* main.m */; };
- CDF37971142291940071ABF7 /* TWAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF37970142291940071ABF7 /* TWAppDelegate.m */; };
- CDF37974142291940071ABF7 /* TWViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF37973142291940071ABF7 /* TWViewController.m */; };
- CDF37977142291940071ABF7 /* TWViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = CDF37975142291940071ABF7 /* TWViewController.xib */; };
- CDF379961422931E0071ABF7 /* Twitter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF379951422931E0071ABF7 /* Twitter.framework */; };
- CDF37998142293220071ABF7 /* Accounts.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CDF37997142293220071ABF7 /* Accounts.framework */; };
- CDF379A514229C820071ABF7 /* TWSignedRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = CDF379A414229C820071ABF7 /* TWSignedRequest.m */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXFileReference section */
- CD14C12214B3A92B00B8A188 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.md; sourceTree = "<group>"; };
- CD6318501422D05400740211 /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = "<group>"; };
- CD6318511422D05400740211 /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = "<group>"; };
- CD6318521422D05400740211 /* OAuth+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "OAuth+Additions.h"; sourceTree = "<group>"; };
- CD6318531422D05400740211 /* OAuth+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "OAuth+Additions.m"; sourceTree = "<group>"; };
- CD6318541422D05400740211 /* OAuthCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAuthCore.h; sourceTree = "<group>"; };
- CD6318551422D05400740211 /* OAuthCore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAuthCore.m; sourceTree = "<group>"; };
- CDBA27CB15CA103C00C0CDCF /* ic_twitterapi@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "ic_twitterapi@2x.png"; sourceTree = "<group>"; };
- CDBA27CC15CA103C00C0CDCF /* ic_twitterapi.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_twitterapi.png; sourceTree = "<group>"; };
- CDBA27CF15CA10BD00C0CDCF /* twitter.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = twitter.png; sourceTree = "<group>"; };
- CDF3795C142291940071ABF7 /* ReverseAuth.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ReverseAuth.app; sourceTree = BUILT_PRODUCTS_DIR; };
- CDF37960142291940071ABF7 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
- CDF37962142291940071ABF7 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
- CDF37964142291940071ABF7 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
- CDF37968142291940071ABF7 /* TWiOS5ReverseAuthExample-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "TWiOS5ReverseAuthExample-Info.plist"; sourceTree = "<group>"; };
- CDF3796A142291940071ABF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
- CDF3796C142291940071ABF7 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
- CDF3796E142291940071ABF7 /* TWiOS5ReverseAuthExample-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TWiOS5ReverseAuthExample-Prefix.pch"; sourceTree = "<group>"; };
- CDF3796F142291940071ABF7 /* TWAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TWAppDelegate.h; sourceTree = "<group>"; };
- CDF37970142291940071ABF7 /* TWAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TWAppDelegate.m; sourceTree = "<group>"; };
- CDF37972142291940071ABF7 /* TWViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TWViewController.h; sourceTree = "<group>"; };
- CDF37973142291940071ABF7 /* TWViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TWViewController.m; sourceTree = "<group>"; };
- CDF37976142291940071ABF7 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/TWViewController.xib; sourceTree = "<group>"; };
- CDF3797E142291940071ABF7 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; };
- CDF379951422931E0071ABF7 /* Twitter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Twitter.framework; path = System/Library/Frameworks/Twitter.framework; sourceTree = SDKROOT; };
- CDF37997142293220071ABF7 /* Accounts.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accounts.framework; path = System/Library/Frameworks/Accounts.framework; sourceTree = SDKROOT; };
- CDF379A314229C820071ABF7 /* TWSignedRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TWSignedRequest.h; sourceTree = "<group>"; };
- CDF379A414229C820071ABF7 /* TWSignedRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TWSignedRequest.m; sourceTree = "<group>"; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- CDF37959142291940071ABF7 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- CDF37998142293220071ABF7 /* Accounts.framework in Frameworks */,
- CDF379961422931E0071ABF7 /* Twitter.framework in Frameworks */,
- CDF37961142291940071ABF7 /* UIKit.framework in Frameworks */,
- CDF37963142291940071ABF7 /* Foundation.framework in Frameworks */,
- CDF37965142291940071ABF7 /* CoreGraphics.framework in Frameworks */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- CD63184E1422D05400740211 /* ABOAuthCore */ = {
- isa = PBXGroup;
- children = (
- CD6318501422D05400740211 /* NSData+Base64.h */,
- CD6318511422D05400740211 /* NSData+Base64.m */,
- CD6318521422D05400740211 /* OAuth+Additions.h */,
- CD6318531422D05400740211 /* OAuth+Additions.m */,
- CD6318541422D05400740211 /* OAuthCore.h */,
- CD6318551422D05400740211 /* OAuthCore.m */,
- );
- path = ABOAuthCore;
- sourceTree = "<group>";
- };
- CDF37951142291940071ABF7 = {
- isa = PBXGroup;
- children = (
- CD14C12214B3A92B00B8A188 /* README.md */,
- CDBA27CB15CA103C00C0CDCF /* ic_twitterapi@2x.png */,
- CDBA27CC15CA103C00C0CDCF /* ic_twitterapi.png */,
- CDBA27CF15CA10BD00C0CDCF /* twitter.png */,
- CDF37966142291940071ABF7 /* TWiOS5ReverseAuthExample */,
- CDF3795F142291940071ABF7 /* Frameworks */,
- CDF3795D142291940071ABF7 /* Products */,
- );
- sourceTree = "<group>";
- };
- CDF3795D142291940071ABF7 /* Products */ = {
- isa = PBXGroup;
- children = (
- CDF3795C142291940071ABF7 /* ReverseAuth.app */,
- );
- name = Products;
- sourceTree = "<group>";
- };
- CDF3795F142291940071ABF7 /* Frameworks */ = {
- isa = PBXGroup;
- children = (
- CDF37997142293220071ABF7 /* Accounts.framework */,
- CDF379951422931E0071ABF7 /* Twitter.framework */,
- CDF37960142291940071ABF7 /* UIKit.framework */,
- CDF37962142291940071ABF7 /* Foundation.framework */,
- CDF37964142291940071ABF7 /* CoreGraphics.framework */,
- CDF3797E142291940071ABF7 /* SenTestingKit.framework */,
- );
- name = Frameworks;
- sourceTree = "<group>";
- };
- CDF37966142291940071ABF7 /* TWiOS5ReverseAuthExample */ = {
- isa = PBXGroup;
- children = (
- CD63184E1422D05400740211 /* ABOAuthCore */,
- CDF37967142291940071ABF7 /* Supporting Files */,
- CDF3796F142291940071ABF7 /* TWAppDelegate.h */,
- CDF37970142291940071ABF7 /* TWAppDelegate.m */,
- CDF379A314229C820071ABF7 /* TWSignedRequest.h */,
- CDF379A414229C820071ABF7 /* TWSignedRequest.m */,
- CDF37972142291940071ABF7 /* TWViewController.h */,
- CDF37973142291940071ABF7 /* TWViewController.m */,
- CDF37975142291940071ABF7 /* TWViewController.xib */,
- );
- path = TWiOS5ReverseAuthExample;
- sourceTree = "<group>";
- };
- CDF37967142291940071ABF7 /* Supporting Files */ = {
- isa = PBXGroup;
- children = (
- CDF37968142291940071ABF7 /* TWiOS5ReverseAuthExample-Info.plist */,
- CDF37969142291940071ABF7 /* InfoPlist.strings */,
- CDF3796C142291940071ABF7 /* main.m */,
- CDF3796E142291940071ABF7 /* TWiOS5ReverseAuthExample-Prefix.pch */,
- );
- name = "Supporting Files";
- sourceTree = "<group>";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- CDF3795B142291940071ABF7 /* ReverseAuth */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = CDF3798F142291940071ABF7 /* Build configuration list for PBXNativeTarget "ReverseAuth" */;
- buildPhases = (
- CDF37958142291940071ABF7 /* Sources */,
- CDF37959142291940071ABF7 /* Frameworks */,
- CDF3795A142291940071ABF7 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = ReverseAuth;
- productName = TWiOS5ReverseAuthExample;
- productReference = CDF3795C142291940071ABF7 /* ReverseAuth.app */;
- productType = "com.apple.product-type.application";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- CDF37953142291940071ABF7 /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastUpgradeCheck = 0430;
- ORGANIZATIONNAME = "Twitter, Inc";
- };
- buildConfigurationList = CDF37956142291940071ABF7 /* Build configuration list for PBXProject "TWiOS5ReverseAuthExample" */;
- compatibilityVersion = "Xcode 3.2";
- developmentRegion = English;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- );
- mainGroup = CDF37951142291940071ABF7;
- productRefGroup = CDF3795D142291940071ABF7 /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- CDF3795B142291940071ABF7 /* ReverseAuth */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- CDF3795A142291940071ABF7 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- CDF3796B142291940071ABF7 /* InfoPlist.strings in Resources */,
- CDF37977142291940071ABF7 /* TWViewController.xib in Resources */,
- CD14C12314B3A92B00B8A188 /* README.md in Resources */,
- CDBA27CD15CA103C00C0CDCF /* ic_twitterapi@2x.png in Resources */,
- CDBA27CE15CA103C00C0CDCF /* ic_twitterapi.png in Resources */,
- CDBA27D015CA10BD00C0CDCF /* twitter.png in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- CDF37958142291940071ABF7 /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- CDF3796D142291940071ABF7 /* main.m in Sources */,
- CDF37971142291940071ABF7 /* TWAppDelegate.m in Sources */,
- CDF37974142291940071ABF7 /* TWViewController.m in Sources */,
- CDF379A514229C820071ABF7 /* TWSignedRequest.m in Sources */,
- CD6318571422D05400740211 /* NSData+Base64.m in Sources */,
- CD6318581422D05400740211 /* OAuth+Additions.m in Sources */,
- CD6318591422D05400740211 /* OAuthCore.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
- CDF37969142291940071ABF7 /* InfoPlist.strings */ = {
- isa = PBXVariantGroup;
- children = (
- CDF3796A142291940071ABF7 /* en */,
- );
- name = InfoPlist.strings;
- sourceTree = "<group>";
- };
- CDF37975142291940071ABF7 /* TWViewController.xib */ = {
- isa = PBXVariantGroup;
- children = (
- CDF37976142291940071ABF7 /* en */,
- );
- name = TWViewController.xib;
- sourceTree = "<group>";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- CDF3798D142291940071ABF7 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_32_BIT)";
- CLANG_ENABLE_OBJC_ARC = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_SYMBOLS_PRIVATE_EXTERN = NO;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 5.0;
- SDKROOT = iphoneos;
- };
- name = Debug;
- };
- CDF3798E142291940071ABF7 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- ARCHS = "$(ARCHS_STANDARD_32_BIT)";
- CLANG_ENABLE_OBJC_ARC = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
- GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 5.0;
- OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
- SDKROOT = iphoneos;
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- CDF37990142291940071ABF7 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "TWiOS5ReverseAuthExample/TWiOS5ReverseAuthExample-Prefix.pch";
- GCC_TREAT_WARNINGS_AS_ERRORS = YES;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- INFOPLIST_FILE = "TWiOS5ReverseAuthExample/TWiOS5ReverseAuthExample-Info.plist";
- PRODUCT_NAME = "$(TARGET_NAME)";
- RUN_CLANG_STATIC_ANALYZER = YES;
- WRAPPER_EXTENSION = app;
- };
- name = Debug;
- };
- CDF37991142291940071ABF7 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- GCC_PRECOMPILE_PREFIX_HEADER = YES;
- GCC_PREFIX_HEADER = "TWiOS5ReverseAuthExample/TWiOS5ReverseAuthExample-Prefix.pch";
- GCC_TREAT_WARNINGS_AS_ERRORS = YES;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- INFOPLIST_FILE = "TWiOS5ReverseAuthExample/TWiOS5ReverseAuthExample-Info.plist";
- PRODUCT_NAME = "$(TARGET_NAME)";
- RUN_CLANG_STATIC_ANALYZER = YES;
- WRAPPER_EXTENSION = app;
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- CDF37956142291940071ABF7 /* Build configuration list for PBXProject "TWiOS5ReverseAuthExample" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- CDF3798D142291940071ABF7 /* Debug */,
- CDF3798E142291940071ABF7 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- CDF3798F142291940071ABF7 /* Build configuration list for PBXNativeTarget "ReverseAuth" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- CDF37990142291940071ABF7 /* Debug */,
- CDF37991142291940071ABF7 /* Release */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = CDF37953142291940071ABF7 /* Project object */;
-}
View
67 TWiOS5ReverseAuthExample/ABOAuthCore/OAuth+Additions.m
@@ -1,67 +0,0 @@
-//
-// OAuth+Additions.m
-//
-// Created by Loren Brichter on 6/9/10.
-// Copyright 2010 Loren Brichter. All rights reserved.
-//
-
-#import "OAuth+Additions.h"
-
-@implementation NSURL (OAuthAdditions)
-
-+ (NSDictionary *)ab_parseURLQueryString:(NSString *)query
-{
- NSMutableDictionary *dict = [NSMutableDictionary dictionary];
- NSArray *pairs = [query componentsSeparatedByString:@"&"];
- for(NSString *pair in pairs) {
- NSArray *keyValue = [pair componentsSeparatedByString:@"="];
- if([keyValue count] == 2) {
- NSString *key = [keyValue objectAtIndex:0];
- NSString *value = [keyValue objectAtIndex:1];
- value = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- if(key && value)
- [dict setObject:value forKey:key];
- }
- }
- return [NSDictionary dictionaryWithDictionary:dict];
-}
-
-@end
-
-@implementation NSString (OAuthAdditions)
-
-- (NSString *)ab_RFC3986EncodedString // UTF-8 encodes prior to URL encoding
-{
- NSMutableString *result = [NSMutableString string];
- const char *p = [self UTF8String];
- unsigned char c;
-
- for(; (c = *p); p++)
- {
- switch(c)
- {
- case '0' ... '9':
- case 'A' ... 'Z':
- case 'a' ... 'z':
- case '.':
- case '-':
- case '~':
- case '_':
- [result appendFormat:@"%c", c];
- break;
- default:
- [result appendFormat:@"%%%02X", c];
- }
- }
- return result;
-}
-
-+ (NSString *)ab_GUID
-{
- CFUUIDRef u = CFUUIDCreate(kCFAllocatorDefault);
- CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, u);
- CFRelease(u);
- return [(NSString *)s autorelease];
-}
-
-@end
View
16 TWiOS5ReverseAuthExample/ABOAuthCore/OAuthCore.h
@@ -1,16 +0,0 @@
-//
-// OAuthCore.h
-//
-// Created by Loren Brichter on 6/9/10.
-// Copyright 2010 Loren Brichter. All rights reserved.
-//
-
-#import <Foundation/Foundation.h>
-
-extern NSString *OAuthorizationHeader(NSURL *url,
- NSString *method,
- NSData *body,
- NSString *_oAuthConsumerKey,
- NSString *_oAuthConsumerSecret,
- NSString *_oAuthToken,
- NSString *_oAuthTokenSecret);
View
36 TWiOS5ReverseAuthExample/TWAppDelegate.h
@@ -1,36 +0,0 @@
-//
-// TWAppDelegate.h
-// TWiOS5ReverseAuthExample
-//
-// Copyright (c) 2012 Sean Cook
-//
-// 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 <UIKit/UIKit.h>
-
-@class TWViewController;
-
-@interface TWAppDelegate : UIResponder <UIApplicationDelegate>
-
-@property (strong, nonatomic) UIWindow *window;
-
-@property (strong, nonatomic) TWViewController *viewController;
-
-@end
View
44 TWiOS5ReverseAuthExample/TWAppDelegate.m
@@ -1,44 +0,0 @@
-//
-// TWAppDelegate.m
-// TWiOS5ReverseAuthExample
-//
-// Copyright (c) 2012 Sean Cook
-//
-// 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 "TWAppDelegate.h"
-#import "TWViewController.h"
-#import <Twitter/Twitter.h>
-
-@implementation TWAppDelegate
-
-@synthesize window = _window;
-@synthesize viewController = _viewController;
-
-- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
-{
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.viewController = [[TWViewController alloc] initWithNibName:@"TWViewController" bundle:nil];
- self.window.rootViewController = self.viewController;
- [self.window makeKeyAndVisible];
- return YES;
-}
-
-@end
View
52 TWiOS5ReverseAuthExample/TWSignedRequest.h
@@ -1,52 +0,0 @@
-//
-// TWSignedRequest.h
-// TWiOS5ReverseAuthExample
-//
-// Copyright (c) 2012 Sean Cook
-//
-// 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 <Foundation/Foundation.h>
-
-enum TWSignedRequestMethod {
- TWSignedRequestMethodGET,
- TWSignedRequestMethodPOST,
- TWSignedRequestMethodDELETE
-};
-
-typedef enum TWSignedRequestMethod TWSignedRequestMethod;
-
-typedef void(^TWSignedRequestHandler)(NSData *data, NSURLResponse *response, NSError *error);
-
-@interface TWSignedRequest : NSObject
-
-@property (nonatomic, copy) NSString *authToken;
-@property (nonatomic, copy) NSString *authTokenSecret;
-
-// Creates a new request
-- (id)initWithURL:(NSURL *)url parameters:(NSDictionary *)parameters requestMethod:(TWSignedRequestMethod)requestMethod;
-
-// Perform the request, and notify handler of results
-- (void)performRequestWithHandler:(TWSignedRequestHandler)handler;
-
-// You should ensure that you obfuscate your keys before shipping
-+ (NSString *)consumerKey;
-+ (NSString *)consumerSecret;
-@end
View
126 TWiOS5ReverseAuthExample/TWSignedRequest.m
@@ -1,126 +0,0 @@
-//
-// TWSignedRequest.m
-// TWiOS5ReverseAuthExample
-//
-// Copyright (c) 2012 Sean Cook
-//
-// 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 "TWSignedRequest.h"
-#import "OAuthCore.h"
-
-#define TW_HTTP_METHOD_GET @"GET"
-#define TW_HTTP_METHOD_POST @"POST"
-#define TW_HTTP_METHOD_DELETE @"DELETE"
-#define TW_HTTP_HEADER_AUTHORIZATION @"Authorization"
-
-// Important: 1) Your keys must be registered with Twitter to enable the reverse_auth endpoint
-// 2) You should obfuscate keys and secrets in your apps before shipping!
-
-#define CONSUMER_SECRET @""
-#define CONSUMER_KEY @""
-
-@interface TWSignedRequest()
-{
- NSURL *_url;
- NSDictionary *_parameters;
- TWSignedRequestMethod _signedRequestMethod;
-}
-
-- (NSURLRequest *)_buildRequest;
-
-@end
-
-@implementation TWSignedRequest
-@synthesize authToken = _authToken;
-@synthesize authTokenSecret = _authTokenSecret;
-
-- (id)initWithURL:(NSURL *)url parameters:(NSDictionary *)parameters requestMethod:(TWSignedRequestMethod)requestMethod;
-{
- self = [super init];
- if (self) {
- _url = url;
- _parameters = parameters;
- _signedRequestMethod = requestMethod;
- }
- return self;
-}
-
-- (NSURLRequest *)_buildRequest
-{
- NSAssert(_url, @"You can't build a request without an URL");
-
- NSString *method;
-
- switch (_signedRequestMethod) {
- case TWSignedRequestMethodPOST:
- method = TW_HTTP_METHOD_POST;
- break;
- case TWSignedRequestMethodDELETE:
- method = TW_HTTP_METHOD_DELETE;
- break;
- case TWSignedRequestMethodGET:
- default:
- method = TW_HTTP_METHOD_GET;
- }
-
- // Build our parameter string
- NSMutableString *paramsAsString = [[NSMutableString alloc] init];
- [_parameters enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
- [paramsAsString appendFormat:@"%@=%@&", key, obj];
- }];
-
- // Create the authorization header and attach to our request
- NSData *bodyData = [paramsAsString dataUsingEncoding:NSUTF8StringEncoding];
- NSString *authorizationHeader = OAuthorizationHeader(_url, method, bodyData, [TWSignedRequest consumerKey], [TWSignedRequest consumerSecret], _authToken, _authTokenSecret);
-
- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:_url];
- [request setHTTPMethod:method];
- [request setValue:authorizationHeader forHTTPHeaderField:TW_HTTP_HEADER_AUTHORIZATION];
- [request setHTTPBody:bodyData];
-
- return request;
-}
-
-- (void)performRequestWithHandler:(TWSignedRequestHandler)handler
-{
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- NSURLResponse *response;
- NSError *error;
- NSData *data = [NSURLConnection sendSynchronousRequest:[self _buildRequest] returningResponse:&response error:&error];
- handler(data, response, error);
- });
-}
-
-// OBFUSCATE YOUR KEYS!
-+ (NSString *)consumerKey
-{
- NSAssert([CONSUMER_KEY length] > 0, @"You must enter your consumer key.");
- return CONSUMER_KEY;
-}
-
-// OBFUSCATE YOUR KEYS!
-+ (NSString *)consumerSecret
-{
- NSAssert([CONSUMER_SECRET length] > 0, @"You must enter your consumer secret.");
- return CONSUMER_SECRET;
-}
-
-@end
View
34 TWiOS5ReverseAuthExample/TWViewController.h
@@ -1,34 +0,0 @@
-//
-// TWViewController.h
-// TWiOS5ReverseAuthExample
-//
-// Copyright (c) 2012 Sean Cook
-//
-// 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 <UIKit/UIKit.h>
-
-@interface TWViewController : UIViewController
-
-@property (strong, nonatomic) IBOutlet UIButton *reverseAuthBtn;
-
-- (IBAction)performReverseAuth:(id)sender;
-
-@end
View
205 TWiOS5ReverseAuthExample/TWViewController.m
@@ -1,205 +0,0 @@
-//
-// TWViewController.m
-// TWiOS5ReverseAuthExample
-//
-// Copyright (c) 2012 Sean Cook
-//
-// 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 "TWViewController.h"
-#import "TWSignedRequest.h"
-#import "OAuth+Additions.h"
-#import <Twitter/Twitter.h>
-#import <Accounts/Accounts.h>
-
-#define TW_X_AUTH_MODE_KEY @"x_auth_mode"
-#define TW_X_AUTH_MODE_REVERSE_AUTH @"reverse_auth"
-#define TW_X_AUTH_MODE_CLIENT_AUTH @"client_auth"
-#define TW_X_AUTH_REVERSE_PARMS @"x_reverse_auth_parameters"
-#define TW_X_AUTH_REVERSE_TARGET @"x_reverse_auth_target"
-#define TW_X_AUTH_USERNAME @"x_auth_username"
-#define TW_X_AUTH_PASSWORD @"x_auth_password"
-#define TW_SCREEN_NAME @"screen_name"
-#define TW_USER_ID @"user_id"
-#define TW_OAUTH_URL_REQUEST_TOKEN @"https://api.twitter.com/oauth/request_token"
-#define TW_OAUTH_URL_AUTH_TOKEN @"https://api.twitter.com/oauth/access_token"
-
-#define POP_ALERT(_W,_X) [[[UIAlertView alloc] initWithTitle:_W message:_X delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show]
-
-@interface TWViewController()
-
-- (BOOL)_checkForLocalCredentials;
-- (BOOL)_checkForKeys;
-- (void)_handleError:(NSError *)error forResponse:(NSURLResponse *)response;
-- (void)_handleStep2Response:(NSString *)responseStr;
-
-@property (nonatomic, strong) ACAccountStore *accountStore;
-@end
-
-@implementation TWViewController
-@synthesize reverseAuthBtn = _reverseAuthBtn;
-
-@synthesize accountStore = _accountStore;
-
-- (void)showAlert:(NSString *)alert title:(NSString *)title
-{
- // This can be triggered from different threads, ensure that we keep it on the main queue
- dispatch_async(dispatch_get_main_queue(), ^{
- POP_ALERT(title, alert);
- });
-}
-
-- (BOOL)_checkForKeys
-{
- BOOL resp = YES;
-
- if (![TWSignedRequest consumerKey] || ![TWSignedRequest consumerSecret]) {
- [self showAlert:@"You must add reverse auth-enabled keys to TWSignedRequest.m" title:@"Yikes"];
- resp = NO;
- }
-
- return resp;
-}
-
-- (BOOL)_checkForLocalCredentials
-{
- BOOL resp = YES;
-
- if (![TWTweetComposeViewController canSendTweet]) {
- [self showAlert:@"Please configure a Twitter account in Settings." title:@"Yikes"];
- resp = NO;
- }
-
- return resp;
-}
-
-- (IBAction)performReverseAuth:(id)sender
-{
- // Check to make sure that the user has added his credentials
- if ([self _checkForKeys] && [self _checkForLocalCredentials]) {
- //
- // Step 1) Ask Twitter for a special request_token for reverse auth
- //
- NSURL *url = [NSURL URLWithString:TW_OAUTH_URL_REQUEST_TOKEN];
-
- // "reverse_auth" is a required parameter
- NSDictionary *dict = [NSDictionary dictionaryWithObject:TW_X_AUTH_MODE_REVERSE_AUTH forKey:TW_X_AUTH_MODE_KEY];
- TWSignedRequest *signedRequest = [[TWSignedRequest alloc] initWithURL:url parameters:dict requestMethod:TWSignedRequestMethodPOST];
-
- [signedRequest performRequestWithHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
- if (!data) {
- [self showAlert:@"Unable to receive a request_token." title:@"Yikes"];
- [self _handleError:error forResponse:response];
- }
- else {
- NSString *signedReverseAuthSignature = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
-
- //
- // Step 2) Ask Twitter for the user's auth token and secret
- // include x_reverse_auth_target=CK2 and x_reverse_auth_parameters=signedReverseAuthSignature parameters
- //
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
-
- NSDictionary *step2Params = [NSDictionary dictionaryWithObjectsAndKeys:[TWSignedRequest consumerKey], TW_X_AUTH_REVERSE_TARGET, signedReverseAuthSignature, TW_X_AUTH_REVERSE_PARMS, nil];
- NSURL *authTokenURL = [NSURL URLWithString:TW_OAUTH_URL_AUTH_TOKEN];
- TWRequest *step2Request = [[TWRequest alloc] initWithURL:authTokenURL parameters:step2Params requestMethod:TWRequestMethodPOST];
-
- // Obtain the user's permission to access the store
- //
- // NB: You *MUST* keep the ACAccountStore around for as long as you need an ACAccount around. See WWDC 2011 Session 124 for more info.
- self.accountStore = [[ACAccountStore alloc] init];
- ACAccountType *twitterType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
-
- [self.accountStore requestAccessToAccountsWithType:twitterType withCompletionHandler:^(BOOL granted, NSError *error) {
- if (!granted) {
- [self showAlert:@"User rejected access to his/her account." title:@"Yikes"];
- }
- else {
- // obtain all the local account instances
- NSArray *accounts = [self.accountStore accountsWithAccountType:twitterType];
-
- // we can assume that we have at least one account thanks to +[TWTweetComposeViewController canSendTweet], let's return it
- [step2Request setAccount:[accounts objectAtIndex:0]];
- [step2Request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
- // Thanks to Marc Delling for pointing out that we should check the status code below
- if (!responseData || ((NSHTTPURLResponse*)response).statusCode >= 400) {
- [self showAlert:@"Error occurred in Step 2. Check console for more info." title:@"Yikes"];
- [self _handleError:error forResponse:response];
- }
- else {
- NSString *responseStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
- [self _handleStep2Response:responseStr];
- }
- }];
- }
- }];
- });
- }
- }];
- }
-}
-
-- (void)_handleError:(NSError *)error forResponse:(NSURLResponse *)response
-{
- NSHTTPURLResponse *urlResponse = (NSHTTPURLResponse *)response;
-
- NSLog(@"[Error]: %@", [error localizedDescription]);
- NSLog(@"[Error]: Response Code:%d \"%@\" ", [urlResponse statusCode], [NSHTTPURLResponse localizedStringForStatusCode:[urlResponse statusCode]]);
-}
-
-#define RESPONSE_EXPECTED_SIZE 4
-- (void)_handleStep2Response:(NSString *)responseStr
-{
- NSDictionary *dict = [NSURL ab_parseURLQueryString:responseStr];
-
- // We are expecting a response dict of the format:
- //
- // {
- // "oauth_token" = ...
- // "oauth_token_secret" = ...