├── .gitignore ├── Classes ├── LROAuth2AccessToken.h ├── LROAuth2AccessToken.m ├── LROAuth2Client.h ├── LROAuth2Client.m ├── LROAuth2ClientDelegate.h ├── LRURLRequestOperation.h └── LRURLRequestOperation.m ├── Framework.plist ├── LROAuth2Client.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── LROAuth2Client_Prefix.pch ├── MIT-LICENSE ├── NSDictionary+QueryString.h ├── NSDictionary+QueryString.m ├── NSString+QueryString.h ├── NSString+QueryString.m ├── NSURL+QueryInspector.h ├── NSURL+QueryInspector.m ├── README.markdown ├── Rakefile └── Scripts ├── CombineLibs.sh └── iPhoneFramework.sh /.gitignore: -------------------------------------------------------------------------------- 1 | # xcode noise 2 | build/* 3 | *.pbxuser 4 | *.mode1v3 5 | *.mode* 6 | *.perspectivev* 7 | 8 | # osx noise 9 | .DS_Store 10 | profile 11 | 12 | Constants.h 13 | *.xcodeproj/xcuserdata 14 | *.xcodeproj/*.xcworkspace/xcuserdata 15 | *.xcworkspace/xcuserdata 16 | 17 | log 18 | Scripts/*.pid 19 | Docs 20 | Pods 21 | xcodebuild 22 | dist 23 | .bundle 24 | xcodebuild.log 25 | -------------------------------------------------------------------------------- /Classes/LROAuth2AccessToken.h: -------------------------------------------------------------------------------- 1 | // 2 | // LROAuth2AccessToken.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface LROAuth2AccessToken : UIView { 13 | NSDictionary *authResponseData; 14 | NSDate *expiresAt; 15 | } 16 | @property (unsafe_unretained, nonatomic, readonly) NSString *accessToken; 17 | @property (unsafe_unretained, nonatomic, readonly) NSString *refreshToken; 18 | @property (nonatomic, readonly) NSDate *expiresAt; 19 | 20 | - (id)initWithAuthorizationResponse:(NSDictionary *)_data; 21 | - (void)refreshFromAuthorizationResponse:(NSDictionary *)_data; 22 | - (BOOL)hasExpired; 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/LROAuth2AccessToken.m: -------------------------------------------------------------------------------- 1 | // 2 | // LROAuth2AccessToken.m 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "LROAuth2AccessToken.h" 10 | 11 | @interface LROAuth2AccessToken () 12 | @property (nonatomic, copy) NSDictionary *authResponseData; 13 | - (void)extractExpiresAtFromResponse; 14 | @end 15 | 16 | #pragma mark - 17 | 18 | @implementation LROAuth2AccessToken 19 | 20 | @dynamic accessToken; 21 | @dynamic refreshToken; 22 | @synthesize authResponseData; 23 | @synthesize expiresAt; 24 | 25 | - (id)initWithAuthorizationResponse:(NSDictionary *)data; 26 | { 27 | if (self = [super init]) { 28 | authResponseData = [data copy]; 29 | [self extractExpiresAtFromResponse]; 30 | } 31 | return self; 32 | } 33 | 34 | 35 | - (NSString *)description; 36 | { 37 | return [NSString stringWithFormat:@"", self.accessToken, self.expiresAt]; 38 | } 39 | 40 | - (BOOL)hasExpired; 41 | { 42 | return ([[NSDate date] earlierDate:expiresAt] == expiresAt); 43 | } 44 | 45 | - (void)refreshFromAuthorizationResponse:(NSDictionary *)data; 46 | { 47 | NSMutableDictionary *tokenData = [self.authResponseData mutableCopy]; 48 | 49 | [tokenData setObject:[data valueForKey:@"access_token"] forKey:@"access_token"]; 50 | [tokenData setObject:[data objectForKey:@"expires_in"] forKey:@"expires_in"]; 51 | 52 | [self setAuthResponseData:tokenData]; 53 | [self extractExpiresAtFromResponse]; 54 | } 55 | 56 | - (void)extractExpiresAtFromResponse 57 | { 58 | NSTimeInterval expiresIn = (NSTimeInterval)[[self.authResponseData objectForKey:@"expires_in"] intValue]; 59 | expiresAt = [[NSDate alloc] initWithTimeIntervalSinceNow:expiresIn]; 60 | } 61 | 62 | #pragma mark - 63 | #pragma mark Dynamic accessors 64 | 65 | - (NSString *)accessToken; 66 | { 67 | return [authResponseData objectForKey:@"access_token"]; 68 | } 69 | 70 | - (NSString *)refreshToken; 71 | { 72 | return [authResponseData objectForKey:@"refresh_token"]; 73 | } 74 | 75 | #pragma mark - 76 | #pragma mark NSCoding 77 | 78 | - (void)encodeWithCoder:(NSCoder *)aCoder 79 | { 80 | [aCoder encodeObject:authResponseData forKey:@"data"]; 81 | [aCoder encodeObject:expiresAt forKey:@"expiresAt"]; 82 | } 83 | 84 | - (id)initWithCoder:(NSCoder *)aDecoder 85 | { 86 | if (self = [super init]) { 87 | authResponseData = [[aDecoder decodeObjectForKey:@"data"] copy]; 88 | expiresAt = [aDecoder decodeObjectForKey:@"expiresAt"]; 89 | } 90 | return self; 91 | } 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Classes/LROAuth2Client.h: -------------------------------------------------------------------------------- 1 | // 2 | // LROAuth2Client.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "LROAuth2ClientDelegate.h" 11 | 12 | @class LROAuth2AccessToken; 13 | 14 | @interface LROAuth2Client : NSObject { 15 | NSString *clientID; 16 | NSString *clientSecret; 17 | NSURL *redirectURL; 18 | NSURL *cancelURL; 19 | NSURL *userURL; 20 | NSURL *tokenURL; 21 | LROAuth2AccessToken *accessToken; 22 | NSMutableArray *requests; 23 | id __unsafe_unretained delegate; 24 | BOOL debug; 25 | 26 | @private 27 | BOOL isVerifying; 28 | } 29 | @property (nonatomic, copy) NSString *clientID; 30 | @property (nonatomic, copy) NSString *clientSecret; 31 | @property (nonatomic, copy) NSURL *redirectURL; 32 | @property (nonatomic, copy) NSURL *cancelURL; 33 | @property (nonatomic, copy) NSURL *userURL; 34 | @property (nonatomic, copy) NSURL *tokenURL; 35 | @property (nonatomic, readonly) LROAuth2AccessToken *accessToken; 36 | @property (nonatomic, unsafe_unretained) id delegate; 37 | @property (nonatomic, assign) BOOL debug; 38 | 39 | - (id)initWithClientID:(NSString *)_clientID 40 | secret:(NSString *)_secret 41 | redirectURL:(NSURL *)url; 42 | 43 | - (NSURLRequest *)userAuthorizationRequestWithParameters:(NSDictionary *)additionalParameters; 44 | - (void)verifyAuthorizationWithAccessCode:(NSString *)accessCode; 45 | - (void)refreshAccessToken:(LROAuth2AccessToken *)_accessToken; 46 | @end 47 | 48 | @interface LROAuth2Client (UIWebViewIntegration) 49 | - (void)authorizeUsingWebView:(UIWebView *)webView; 50 | - (void)authorizeUsingWebView:(UIWebView *)webView additionalParameters:(NSDictionary *)additionalParameters; 51 | - (void)extractAccessCodeFromCallbackURL:(NSURL *)url; 52 | @end 53 | -------------------------------------------------------------------------------- /Classes/LROAuth2Client.m: -------------------------------------------------------------------------------- 1 | // 2 | // LROAuth2Client.m 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "LROAuth2Client.h" 10 | #import "NSURL+QueryInspector.h" 11 | #import "LROAuth2AccessToken.h" 12 | #import "LRURLRequestOperation.h" 13 | #import "NSDictionary+QueryString.h" 14 | 15 | #pragma mark - 16 | 17 | @implementation LROAuth2Client { 18 | NSOperationQueue *_networkQueue; 19 | } 20 | 21 | @synthesize clientID; 22 | @synthesize clientSecret; 23 | @synthesize redirectURL; 24 | @synthesize cancelURL; 25 | @synthesize userURL; 26 | @synthesize tokenURL; 27 | @synthesize delegate; 28 | @synthesize accessToken; 29 | @synthesize debug; 30 | 31 | - (id)initWithClientID:(NSString *)_clientID 32 | secret:(NSString *)_secret 33 | redirectURL:(NSURL *)url; 34 | { 35 | if (self = [super init]) { 36 | clientID = [_clientID copy]; 37 | clientSecret = [_secret copy]; 38 | redirectURL = [url copy]; 39 | requests = [[NSMutableArray alloc] init]; 40 | debug = NO; 41 | _networkQueue = [[NSOperationQueue alloc] init]; 42 | } 43 | return self; 44 | } 45 | 46 | - (void)dealloc; 47 | { 48 | [_networkQueue cancelAllOperations]; 49 | } 50 | 51 | #pragma mark - 52 | #pragma mark Authorization 53 | 54 | - (NSURLRequest *)userAuthorizationRequestWithParameters:(NSDictionary *)additionalParameters; 55 | { 56 | NSDictionary *params = [NSMutableDictionary dictionary]; 57 | [params setValue:@"web_server" forKey:@"type"]; 58 | [params setValue:clientID forKey:@"client_id"]; 59 | [params setValue:[redirectURL absoluteString] forKey:@"redirect_uri"]; 60 | 61 | if (additionalParameters) { 62 | for (NSString *key in additionalParameters) { 63 | [params setValue:[additionalParameters valueForKey:key] forKey:key]; 64 | } 65 | } 66 | NSURL *fullURL = [NSURL URLWithString:[[self.userURL absoluteString] stringByAppendingFormat:@"?%@", [params stringWithFormEncodedComponents]]]; 67 | NSMutableURLRequest *authRequest = [NSMutableURLRequest requestWithURL:fullURL]; 68 | [authRequest setHTTPMethod:@"GET"]; 69 | 70 | return [authRequest copy]; 71 | } 72 | 73 | - (void)verifyAuthorizationWithAccessCode:(NSString *)accessCode; 74 | { 75 | @synchronized(self) { 76 | if (isVerifying) return; // don't allow more than one auth request 77 | 78 | isVerifying = YES; 79 | 80 | NSDictionary *params = [NSMutableDictionary dictionary]; 81 | [params setValue:@"authorization_code" forKey:@"grant_type"]; 82 | [params setValue:clientID forKey:@"client_id"]; 83 | [params setValue:clientSecret forKey:@"client_secret"]; 84 | [params setValue:[redirectURL absoluteString] forKey:@"redirect_uri"]; 85 | [params setValue:accessCode forKey:@"code"]; 86 | 87 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:self.tokenURL]; 88 | [request setHTTPMethod:@"POST"]; 89 | [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 90 | [request setHTTPBody:[[params stringWithFormEncodedComponents] dataUsingEncoding:NSUTF8StringEncoding]]; 91 | 92 | LRURLRequestOperation *operation = [[LRURLRequestOperation alloc] initWithURLRequest:request]; 93 | 94 | __unsafe_unretained id blockOperation = operation; 95 | 96 | [operation setCompletionBlock:^{ 97 | [self handleCompletionForAuthorizationRequestOperation:blockOperation]; 98 | }]; 99 | 100 | [_networkQueue addOperation:operation]; 101 | } 102 | } 103 | 104 | - (void)refreshAccessToken:(LROAuth2AccessToken *)_accessToken; 105 | { 106 | accessToken = _accessToken; 107 | 108 | NSDictionary *params = [NSMutableDictionary dictionary]; 109 | [params setValue:@"refresh_token" forKey:@"grant_type"]; 110 | [params setValue:clientID forKey:@"client_id"]; 111 | [params setValue:clientSecret forKey:@"client_secret"]; 112 | [params setValue:[redirectURL absoluteString] forKey:@"redirect_uri"]; 113 | [params setValue:_accessToken.refreshToken forKey:@"refresh_token"]; 114 | 115 | NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:self.tokenURL]; 116 | [request setHTTPMethod:@"POST"]; 117 | [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]; 118 | [request setHTTPBody:[[params stringWithFormEncodedComponents] dataUsingEncoding:NSUTF8StringEncoding]]; 119 | 120 | LRURLRequestOperation *operation = [[LRURLRequestOperation alloc] initWithURLRequest:request]; 121 | 122 | __unsafe_unretained id blockOperation = operation; 123 | 124 | [operation setCompletionBlock:^{ 125 | [self handleCompletionForAuthorizationRequestOperation:blockOperation]; 126 | }]; 127 | 128 | [_networkQueue addOperation:operation]; 129 | } 130 | 131 | - (void)handleCompletionForAuthorizationRequestOperation:(LRURLRequestOperation *)operation 132 | { 133 | NSHTTPURLResponse *response = (NSHTTPURLResponse *)operation.URLResponse; 134 | 135 | if (response.statusCode == 200) { 136 | NSError *parserError; 137 | NSDictionary *authData = [NSJSONSerialization JSONObjectWithData:operation.responseData options:0 error:&parserError]; 138 | 139 | if (authData == nil) { 140 | // try and decode the response body as a query string instead 141 | NSString *responseString = [[NSString alloc] initWithData:operation.responseData encoding:NSUTF8StringEncoding]; 142 | authData = [NSDictionary dictionaryWithFormEncodedString:responseString]; 143 | } 144 | if ([authData objectForKey:@"access_token"] == nil) { 145 | NSAssert(NO, @"Unhandled parsing failure"); 146 | } 147 | if (accessToken == nil) { 148 | accessToken = [[LROAuth2AccessToken alloc] initWithAuthorizationResponse:authData]; 149 | if ([self.delegate respondsToSelector:@selector(oauthClientDidReceiveAccessToken:)]) { 150 | [self.delegate oauthClientDidReceiveAccessToken:self]; 151 | } 152 | } else { 153 | [accessToken refreshFromAuthorizationResponse:authData]; 154 | if ([self.delegate respondsToSelector:@selector(oauthClientDidRefreshAccessToken:)]) { 155 | [self.delegate oauthClientDidRefreshAccessToken:self]; 156 | } 157 | } 158 | } 159 | else { 160 | if (operation.connectionError) { 161 | NSLog(@"Connection error: %@", operation.connectionError); 162 | } 163 | } 164 | } 165 | 166 | @end 167 | 168 | @implementation LROAuth2Client (UIWebViewIntegration) 169 | 170 | - (void)authorizeUsingWebView:(UIWebView *)webView; 171 | { 172 | [self authorizeUsingWebView:webView additionalParameters:nil]; 173 | } 174 | 175 | - (void)authorizeUsingWebView:(UIWebView *)webView additionalParameters:(NSDictionary *)additionalParameters; 176 | { 177 | [webView setDelegate:self]; 178 | [webView loadRequest:[self userAuthorizationRequestWithParameters:additionalParameters]]; 179 | } 180 | 181 | - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType; 182 | { 183 | if ([[request.URL absoluteString] hasPrefix:[self.redirectURL absoluteString]]) { 184 | [self extractAccessCodeFromCallbackURL:request.URL]; 185 | 186 | return NO; 187 | } else if (self.cancelURL && [[request.URL absoluteString] hasPrefix:[self.cancelURL absoluteString]]) { 188 | if ([self.delegate respondsToSelector:@selector(oauthClientDidCancel:)]) { 189 | [self.delegate oauthClientDidCancel:self]; 190 | } 191 | 192 | return NO; 193 | } 194 | 195 | if ([self.delegate respondsToSelector:@selector(webView:shouldStartLoadWithRequest:navigationType:)]) { 196 | return [self.delegate webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; 197 | } 198 | 199 | return YES; 200 | } 201 | 202 | /** 203 | * custom URL schemes will typically cause a failure so we should handle those here 204 | */ 205 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 206 | { 207 | 208 | #if __IPHONE_OS_VERSION_MAX_ALLOWED <= __IPHONE_3_2 209 | NSString *failingURLString = [error.userInfo objectForKey:NSErrorFailingURLStringKey]; 210 | #else 211 | NSString *failingURLString = [error.userInfo objectForKey:NSURLErrorFailingURLStringErrorKey]; 212 | #endif 213 | 214 | if ([failingURLString hasPrefix:[self.redirectURL absoluteString]]) { 215 | [webView stopLoading]; 216 | [self extractAccessCodeFromCallbackURL:[NSURL URLWithString:failingURLString]]; 217 | } else if (self.cancelURL && [failingURLString hasPrefix:[self.cancelURL absoluteString]]) { 218 | [webView stopLoading]; 219 | if ([self.delegate respondsToSelector:@selector(oauthClientDidCancel:)]) { 220 | [self.delegate oauthClientDidCancel:self]; 221 | } 222 | } 223 | 224 | if ([self.delegate respondsToSelector:@selector(webView:didFailLoadWithError:)]) { 225 | [self.delegate webView:webView didFailLoadWithError:error]; 226 | } 227 | } 228 | 229 | - (void)webViewDidStartLoad:(UIWebView *)webView 230 | { 231 | if ([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) { 232 | [self.delegate webViewDidStartLoad:webView]; 233 | } 234 | } 235 | 236 | - (void)webViewDidFinishLoad:(UIWebView *)webView 237 | { 238 | if ([self.delegate respondsToSelector:@selector(webViewDidFinishLoad:)]) { 239 | [self.delegate webViewDidFinishLoad:webView]; 240 | } 241 | } 242 | 243 | - (void)extractAccessCodeFromCallbackURL:(NSURL *)callbackURL; 244 | { 245 | NSString *accessCode = [[callbackURL queryDictionary] valueForKey:@"code"]; 246 | 247 | if ([self.delegate respondsToSelector:@selector(oauthClientDidReceiveAccessCode:)]) { 248 | [self.delegate oauthClientDidReceiveAccessCode:self]; 249 | } 250 | [self verifyAuthorizationWithAccessCode:accessCode]; 251 | } 252 | 253 | @end 254 | -------------------------------------------------------------------------------- /Classes/LROAuth2ClientDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LROAuth2ClientDelegate.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class LROAuth2Client; 12 | 13 | @protocol LROAuth2ClientDelegate 14 | 15 | @required 16 | - (void)oauthClientDidReceiveAccessToken:(LROAuth2Client *)client; 17 | - (void)oauthClientDidRefreshAccessToken:(LROAuth2Client *)client; 18 | 19 | @optional 20 | - (void)oauthClientDidReceiveAccessCode:(LROAuth2Client *)client; 21 | - (void)oauthClientDidCancel:(LROAuth2Client *)client; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Classes/LRURLRequestOperation.h: -------------------------------------------------------------------------------- 1 | // 2 | // LRURLConnectionOperation.h 3 | // LRResty 4 | // 5 | // Created by Luke Redpath on 04/10/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface LRURLRequestOperation : NSOperation { 13 | BOOL _isExecuting; 14 | BOOL _isFinished; 15 | NSURLRequest *URLRequest; 16 | NSURLResponse *URLResponse; 17 | NSURLConnection *URLConnection; 18 | NSError *connectionError; 19 | NSMutableData *responseData; 20 | } 21 | @property (nonatomic, strong) NSURLRequest *URLRequest; 22 | @property (nonatomic, strong, readonly) NSURLResponse *URLResponse; 23 | @property (nonatomic, strong, readonly) NSError *connectionError; 24 | @property (nonatomic, strong, readonly) NSData *responseData; 25 | 26 | - (id)initWithURLRequest:(NSURLRequest *)request; 27 | - (void)finish; 28 | - (void)cancelImmediately; 29 | @end 30 | 31 | @interface LRURLRequestOperation (NSURLConnectionDelegate) 32 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)theResponse; 33 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; 34 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection; 35 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error; 36 | @end 37 | -------------------------------------------------------------------------------- /Classes/LRURLRequestOperation.m: -------------------------------------------------------------------------------- 1 | // 2 | // LRURLConnectionOperation.m 3 | // LRResty 4 | // 5 | // Created by Luke Redpath on 04/10/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "LRURLRequestOperation.h" 10 | 11 | @interface LRURLRequestOperation () 12 | @property (nonatomic, strong, readwrite) NSURLResponse *URLResponse; 13 | @property (nonatomic, strong, readwrite) NSError *connectionError; 14 | @property (nonatomic, strong, readwrite) NSData *responseData; 15 | 16 | - (void)setExecuting:(BOOL)isExecuting; 17 | - (void)setFinished:(BOOL)isFinished; 18 | @end 19 | 20 | #pragma mark - 21 | 22 | @implementation LRURLRequestOperation 23 | 24 | @synthesize URLRequest; 25 | @synthesize URLResponse; 26 | @synthesize connectionError; 27 | @synthesize responseData; 28 | 29 | - (id)initWithURLRequest:(NSURLRequest *)request; 30 | { 31 | if ((self = [super init])) { 32 | URLRequest = request; 33 | } 34 | return self; 35 | } 36 | 37 | 38 | - (void)start 39 | { 40 | NSAssert(URLRequest, @"Cannot start URLRequestOperation without a NSURLRequest."); 41 | 42 | if (![NSThread isMainThread]) { 43 | return [self performSelector:@selector(start) onThread:[NSThread mainThread] withObject:nil waitUntilDone:NO]; 44 | } 45 | 46 | [self setExecuting:YES]; 47 | 48 | URLConnection = [[NSURLConnection alloc] initWithRequest:URLRequest delegate:self startImmediately:NO]; 49 | 50 | if (URLConnection == nil) { 51 | [self setFinished:YES]; 52 | } 53 | 54 | // Common modes instead of default so it won't stall uiscrollview scrolling 55 | [URLConnection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; 56 | [URLConnection start]; 57 | } 58 | 59 | - (void)finish; 60 | { 61 | [self setFinished:YES]; 62 | } 63 | 64 | - (BOOL)isConcurrent 65 | { 66 | return YES; 67 | } 68 | 69 | - (BOOL)isExecuting 70 | { 71 | return _isExecuting; 72 | } 73 | 74 | - (BOOL)isFinished 75 | { 76 | return _isFinished; 77 | } 78 | 79 | #pragma mark - 80 | #pragma mark NSURLConnection delegate methods 81 | 82 | - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)theResponse 83 | { 84 | self.URLResponse = theResponse; 85 | self.responseData = [NSMutableData data]; 86 | 87 | if ([self isCancelled]) { 88 | [connection cancel]; 89 | [self finish]; 90 | } 91 | } 92 | 93 | - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 94 | { 95 | if (self.responseData == nil) { // this might be called before didReceiveResponse 96 | self.responseData = [NSMutableData data]; 97 | } 98 | 99 | [responseData appendData:data]; 100 | 101 | if ([self isCancelled]) { 102 | [connection cancel]; 103 | [self finish]; 104 | } 105 | } 106 | 107 | - (void)connectionDidFinishLoading:(NSURLConnection *)connection 108 | { 109 | [self finish]; 110 | } 111 | 112 | - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 113 | { 114 | self.connectionError = error; 115 | [self finish]; 116 | } 117 | 118 | - (void)cancelImmediately 119 | { 120 | [URLConnection cancel]; 121 | [self finish]; 122 | } 123 | 124 | #pragma mark - 125 | #pragma mark Private methods 126 | 127 | - (void)setExecuting:(BOOL)isExecuting; 128 | { 129 | [self willChangeValueForKey:@"isExecuting"]; 130 | _isExecuting = isExecuting; 131 | [self didChangeValueForKey:@"isExecuting"]; 132 | } 133 | 134 | - (void)setFinished:(BOOL)isFinished; 135 | { 136 | [self willChangeValueForKey:@"isFinished"]; 137 | [self setExecuting:NO]; 138 | _isFinished = isFinished; 139 | [self didChangeValueForKey:@"isFinished"]; 140 | } 141 | 142 | @end 143 | -------------------------------------------------------------------------------- /Framework.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleIdentifier 8 | co.uk.lukeredpath.LROAuth2Client 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundlePackageType 12 | FMWK 13 | CFBundleSignature 14 | ???? 15 | CFBundleVersion 16 | 1.0 17 | 18 | 19 | -------------------------------------------------------------------------------- /LROAuth2Client.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A3289DAD122D707B00D89A88 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C124119DEFD50035081C /* SystemConfiguration.framework */; }; 11 | A3289DAE122D707B00D89A88 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C126119DEFDE0035081C /* UIKit.framework */; }; 12 | A3289DAF122D708700D89A88 /* NSDictionary+QueryString.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C24B119DF7420035081C /* NSDictionary+QueryString.m */; }; 13 | A3289DB0122D708700D89A88 /* NSString+QueryString.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C24C119DF7420035081C /* NSString+QueryString.m */; }; 14 | A3289DB1122D708700D89A88 /* NSURL+QueryInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */; }; 15 | A3289DB2122D708700D89A88 /* LROAuth2Client.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8BFBB119DEE450035081C /* LROAuth2Client.m */; }; 16 | A3289DB3122D708700D89A88 /* LROAuth2AccessToken.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8BFBE119DEE450035081C /* LROAuth2AccessToken.m */; }; 17 | A3289EB6122D758F00D89A88 /* NSDictionary+QueryString.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C24B119DF7420035081C /* NSDictionary+QueryString.m */; }; 18 | A3289EB7122D758F00D89A88 /* NSString+QueryString.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C24C119DF7420035081C /* NSString+QueryString.m */; }; 19 | A3289EB8122D758F00D89A88 /* NSURL+QueryInspector.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */; }; 20 | A3289EB9122D758F00D89A88 /* LROAuth2Client.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8BFBB119DEE450035081C /* LROAuth2Client.m */; }; 21 | A3289EBA122D758F00D89A88 /* LROAuth2AccessToken.m in Sources */ = {isa = PBXBuildFile; fileRef = A3F8BFBE119DEE450035081C /* LROAuth2AccessToken.m */; }; 22 | A3289EBC122D758F00D89A88 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C124119DEFD50035081C /* SystemConfiguration.framework */; }; 23 | A3289EBD122D758F00D89A88 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A3F8C126119DEFDE0035081C /* UIKit.framework */; }; 24 | A3289FD6122D819500D89A88 /* LROAuth2Client.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8BFBA119DEE450035081C /* LROAuth2Client.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | A3289FD7122D819500D89A88 /* LROAuth2ClientDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8BFBC119DEE450035081C /* LROAuth2ClientDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | A3289FD8122D819500D89A88 /* LROAuth2AccessToken.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8BFBD119DEE450035081C /* LROAuth2AccessToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | A3289FD9122D819800D89A88 /* LROAuth2Client.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8BFBA119DEE450035081C /* LROAuth2Client.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28 | A3289FDA122D819800D89A88 /* LROAuth2ClientDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8BFBC119DEE450035081C /* LROAuth2ClientDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; 29 | A3289FDB122D819800D89A88 /* LROAuth2AccessToken.h in Headers */ = {isa = PBXBuildFile; fileRef = A3F8BFBD119DEE450035081C /* LROAuth2AccessToken.h */; settings = {ATTRIBUTES = (Public, ); }; }; 30 | A3ABE4D61528797B006E9AC0 /* LRURLRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = A3ABE4D41528797B006E9AC0 /* LRURLRequestOperation.h */; }; 31 | A3ABE4D71528797B006E9AC0 /* LRURLRequestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = A3ABE4D41528797B006E9AC0 /* LRURLRequestOperation.h */; }; 32 | A3ABE4D81528797B006E9AC0 /* LRURLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = A3ABE4D51528797B006E9AC0 /* LRURLRequestOperation.m */; }; 33 | A3ABE4D91528797B006E9AC0 /* LRURLRequestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = A3ABE4D51528797B006E9AC0 /* LRURLRequestOperation.m */; }; 34 | /* End PBXBuildFile section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | A3289D4B122D705500D89A88 /* libLROAuth2Client-Device.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libLROAuth2Client-Device.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | A3289EC3122D758F00D89A88 /* libLROAuth2Client-Simulator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libLROAuth2Client-Simulator.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | A3ABE4D41528797B006E9AC0 /* LRURLRequestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LRURLRequestOperation.h; sourceTree = ""; }; 40 | A3ABE4D51528797B006E9AC0 /* LRURLRequestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LRURLRequestOperation.m; sourceTree = ""; }; 41 | A3F8BFBA119DEE450035081C /* LROAuth2Client.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LROAuth2Client.h; sourceTree = ""; }; 42 | A3F8BFBB119DEE450035081C /* LROAuth2Client.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LROAuth2Client.m; sourceTree = ""; }; 43 | A3F8BFBC119DEE450035081C /* LROAuth2ClientDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LROAuth2ClientDelegate.h; sourceTree = ""; }; 44 | A3F8BFBD119DEE450035081C /* LROAuth2AccessToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LROAuth2AccessToken.h; sourceTree = ""; }; 45 | A3F8BFBE119DEE450035081C /* LROAuth2AccessToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LROAuth2AccessToken.m; sourceTree = ""; }; 46 | A3F8C124119DEFD50035081C /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; 47 | A3F8C126119DEFDE0035081C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 48 | A3F8C12F119DF00C0035081C /* NSURL+QueryInspector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+QueryInspector.h"; sourceTree = ""; }; 49 | A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+QueryInspector.m"; sourceTree = ""; }; 50 | A3F8C24B119DF7420035081C /* NSDictionary+QueryString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDictionary+QueryString.m"; sourceTree = ""; }; 51 | A3F8C24C119DF7420035081C /* NSString+QueryString.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+QueryString.m"; sourceTree = ""; }; 52 | A3F8C254119DF7790035081C /* NSDictionary+QueryString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+QueryString.h"; sourceTree = ""; }; 53 | A3F8C258119DF79D0035081C /* NSString+QueryString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+QueryString.h"; sourceTree = ""; }; 54 | AA747D9E0F9514B9006C5449 /* LROAuth2Client_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LROAuth2Client_Prefix.pch; sourceTree = ""; }; 55 | AACBBE490F95108600F1A2B1 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 56 | B25E603F11CFB44E001DA5CD /* Test App-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Test App-Info.plist"; sourceTree = ""; }; 57 | B25E609711CFB581001DA5CD /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; }; 58 | B25E609B11CFB581001DA5CD /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 59 | /* End PBXFileReference section */ 60 | 61 | /* Begin PBXFrameworksBuildPhase section */ 62 | A3289D49122D705500D89A88 /* Frameworks */ = { 63 | isa = PBXFrameworksBuildPhase; 64 | buildActionMask = 2147483647; 65 | files = ( 66 | A3289DAD122D707B00D89A88 /* SystemConfiguration.framework in Frameworks */, 67 | A3289DAE122D707B00D89A88 /* UIKit.framework in Frameworks */, 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | A3289EBB122D758F00D89A88 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | A3289EBC122D758F00D89A88 /* SystemConfiguration.framework in Frameworks */, 76 | A3289EBD122D758F00D89A88 /* UIKit.framework in Frameworks */, 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | /* End PBXFrameworksBuildPhase section */ 81 | 82 | /* Begin PBXGroup section */ 83 | 034768DFFF38A50411DB9C8B /* Products */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | A3289D4B122D705500D89A88 /* libLROAuth2Client-Device.a */, 87 | A3289EC3122D758F00D89A88 /* libLROAuth2Client-Simulator.a */, 88 | ); 89 | name = Products; 90 | sourceTree = ""; 91 | }; 92 | 0867D691FE84028FC02AAC07 /* Untitled */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 08FB77AEFE84172EC02AAC07 /* Classes */, 96 | 32C88DFF0371C24200C91783 /* Other Sources */, 97 | 0867D69AFE84028FC02AAC07 /* Frameworks */, 98 | 034768DFFF38A50411DB9C8B /* Products */, 99 | B25E603F11CFB44E001DA5CD /* Test App-Info.plist */, 100 | ); 101 | name = Untitled; 102 | sourceTree = ""; 103 | }; 104 | 0867D69AFE84028FC02AAC07 /* Frameworks */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | B25E609B11CFB581001DA5CD /* MobileCoreServices.framework */, 108 | B25E609711CFB581001DA5CD /* CFNetwork.framework */, 109 | AACBBE490F95108600F1A2B1 /* Foundation.framework */, 110 | A3F8C124119DEFD50035081C /* SystemConfiguration.framework */, 111 | A3F8C126119DEFDE0035081C /* UIKit.framework */, 112 | ); 113 | name = Frameworks; 114 | sourceTree = ""; 115 | }; 116 | 08FB77AEFE84172EC02AAC07 /* Classes */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | A3F8C12D119DEFF80035081C /* Categories */, 120 | A3F8BFB9119DEE390035081C /* LROAuth2 */, 121 | ); 122 | path = Classes; 123 | sourceTree = ""; 124 | }; 125 | 32C88DFF0371C24200C91783 /* Other Sources */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | AA747D9E0F9514B9006C5449 /* LROAuth2Client_Prefix.pch */, 129 | ); 130 | name = "Other Sources"; 131 | sourceTree = ""; 132 | }; 133 | A3F8BFB9119DEE390035081C /* LROAuth2 */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | A3ABE4D41528797B006E9AC0 /* LRURLRequestOperation.h */, 137 | A3ABE4D51528797B006E9AC0 /* LRURLRequestOperation.m */, 138 | A3F8BFBA119DEE450035081C /* LROAuth2Client.h */, 139 | A3F8BFBB119DEE450035081C /* LROAuth2Client.m */, 140 | A3F8BFBC119DEE450035081C /* LROAuth2ClientDelegate.h */, 141 | A3F8BFBD119DEE450035081C /* LROAuth2AccessToken.h */, 142 | A3F8BFBE119DEE450035081C /* LROAuth2AccessToken.m */, 143 | ); 144 | name = LROAuth2; 145 | sourceTree = ""; 146 | }; 147 | A3F8C12D119DEFF80035081C /* Categories */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | A3F8C254119DF7790035081C /* NSDictionary+QueryString.h */, 151 | A3F8C24B119DF7420035081C /* NSDictionary+QueryString.m */, 152 | A3F8C258119DF79D0035081C /* NSString+QueryString.h */, 153 | A3F8C24C119DF7420035081C /* NSString+QueryString.m */, 154 | A3F8C12F119DF00C0035081C /* NSURL+QueryInspector.h */, 155 | A3F8C130119DF00D0035081C /* NSURL+QueryInspector.m */, 156 | ); 157 | name = Categories; 158 | path = ..; 159 | sourceTree = ""; 160 | }; 161 | /* End PBXGroup section */ 162 | 163 | /* Begin PBXHeadersBuildPhase section */ 164 | A3289D47122D705500D89A88 /* Headers */ = { 165 | isa = PBXHeadersBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | A3289FD6122D819500D89A88 /* LROAuth2Client.h in Headers */, 169 | A3289FD7122D819500D89A88 /* LROAuth2ClientDelegate.h in Headers */, 170 | A3289FD8122D819500D89A88 /* LROAuth2AccessToken.h in Headers */, 171 | A3ABE4D61528797B006E9AC0 /* LRURLRequestOperation.h in Headers */, 172 | ); 173 | runOnlyForDeploymentPostprocessing = 0; 174 | }; 175 | A3289EB4122D758F00D89A88 /* Headers */ = { 176 | isa = PBXHeadersBuildPhase; 177 | buildActionMask = 2147483647; 178 | files = ( 179 | A3289FD9122D819800D89A88 /* LROAuth2Client.h in Headers */, 180 | A3289FDA122D819800D89A88 /* LROAuth2ClientDelegate.h in Headers */, 181 | A3289FDB122D819800D89A88 /* LROAuth2AccessToken.h in Headers */, 182 | A3ABE4D71528797B006E9AC0 /* LRURLRequestOperation.h in Headers */, 183 | ); 184 | runOnlyForDeploymentPostprocessing = 0; 185 | }; 186 | /* End PBXHeadersBuildPhase section */ 187 | 188 | /* Begin PBXNativeTarget section */ 189 | A3289D4A122D705500D89A88 /* LROAuth2Client-Device */ = { 190 | isa = PBXNativeTarget; 191 | buildConfigurationList = A3289DCD122D70A800D89A88 /* Build configuration list for PBXNativeTarget "LROAuth2Client-Device" */; 192 | buildPhases = ( 193 | A3289D47122D705500D89A88 /* Headers */, 194 | A3289D48122D705500D89A88 /* Sources */, 195 | A3289D49122D705500D89A88 /* Frameworks */, 196 | ); 197 | buildRules = ( 198 | ); 199 | dependencies = ( 200 | ); 201 | name = "LROAuth2Client-Device"; 202 | productName = libLROAuth2Client; 203 | productReference = A3289D4B122D705500D89A88 /* libLROAuth2Client-Device.a */; 204 | productType = "com.apple.product-type.library.static"; 205 | }; 206 | A3289EB3122D758F00D89A88 /* LROAuth2Client-Simulator */ = { 207 | isa = PBXNativeTarget; 208 | buildConfigurationList = A3289EC0122D758F00D89A88 /* Build configuration list for PBXNativeTarget "LROAuth2Client-Simulator" */; 209 | buildPhases = ( 210 | A3289EB4122D758F00D89A88 /* Headers */, 211 | A3289EB5122D758F00D89A88 /* Sources */, 212 | A3289EBB122D758F00D89A88 /* Frameworks */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | ); 218 | name = "LROAuth2Client-Simulator"; 219 | productName = libLROAuth2Client; 220 | productReference = A3289EC3122D758F00D89A88 /* libLROAuth2Client-Simulator.a */; 221 | productType = "com.apple.product-type.library.static"; 222 | }; 223 | /* End PBXNativeTarget section */ 224 | 225 | /* Begin PBXProject section */ 226 | 0867D690FE84028FC02AAC07 /* Project object */ = { 227 | isa = PBXProject; 228 | buildConfigurationList = 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "LROAuth2Client" */; 229 | compatibilityVersion = "Xcode 3.1"; 230 | developmentRegion = English; 231 | hasScannedForEncodings = 1; 232 | knownRegions = ( 233 | English, 234 | Japanese, 235 | French, 236 | German, 237 | ); 238 | mainGroup = 0867D691FE84028FC02AAC07 /* Untitled */; 239 | productRefGroup = 034768DFFF38A50411DB9C8B /* Products */; 240 | projectDirPath = ""; 241 | projectRoot = ""; 242 | targets = ( 243 | A3289D4A122D705500D89A88 /* LROAuth2Client-Device */, 244 | A3289EB3122D758F00D89A88 /* LROAuth2Client-Simulator */, 245 | ); 246 | }; 247 | /* End PBXProject section */ 248 | 249 | /* Begin PBXSourcesBuildPhase section */ 250 | A3289D48122D705500D89A88 /* Sources */ = { 251 | isa = PBXSourcesBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | A3289DAF122D708700D89A88 /* NSDictionary+QueryString.m in Sources */, 255 | A3289DB0122D708700D89A88 /* NSString+QueryString.m in Sources */, 256 | A3289DB1122D708700D89A88 /* NSURL+QueryInspector.m in Sources */, 257 | A3289DB2122D708700D89A88 /* LROAuth2Client.m in Sources */, 258 | A3289DB3122D708700D89A88 /* LROAuth2AccessToken.m in Sources */, 259 | A3ABE4D81528797B006E9AC0 /* LRURLRequestOperation.m in Sources */, 260 | ); 261 | runOnlyForDeploymentPostprocessing = 0; 262 | }; 263 | A3289EB5122D758F00D89A88 /* Sources */ = { 264 | isa = PBXSourcesBuildPhase; 265 | buildActionMask = 2147483647; 266 | files = ( 267 | A3289EB6122D758F00D89A88 /* NSDictionary+QueryString.m in Sources */, 268 | A3289EB7122D758F00D89A88 /* NSString+QueryString.m in Sources */, 269 | A3289EB8122D758F00D89A88 /* NSURL+QueryInspector.m in Sources */, 270 | A3289EB9122D758F00D89A88 /* LROAuth2Client.m in Sources */, 271 | A3289EBA122D758F00D89A88 /* LROAuth2AccessToken.m in Sources */, 272 | A3ABE4D91528797B006E9AC0 /* LRURLRequestOperation.m in Sources */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | /* End PBXSourcesBuildPhase section */ 277 | 278 | /* Begin XCBuildConfiguration section */ 279 | 1DEB922308733DC00010E9CD /* Debug */ = { 280 | isa = XCBuildConfiguration; 281 | buildSettings = { 282 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 283 | GCC_C_LANGUAGE_STANDARD = c99; 284 | GCC_OPTIMIZATION_LEVEL = 0; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 286 | GCC_WARN_UNUSED_VARIABLE = YES; 287 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 288 | OTHER_LDFLAGS = "-ObjC"; 289 | PREBINDING = NO; 290 | SDKROOT = iphoneos; 291 | }; 292 | name = Debug; 293 | }; 294 | 1DEB922408733DC00010E9CD /* Release */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 298 | GCC_C_LANGUAGE_STANDARD = c99; 299 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 300 | GCC_WARN_UNUSED_VARIABLE = YES; 301 | IPHONEOS_DEPLOYMENT_TARGET = 3.0; 302 | OTHER_LDFLAGS = "-ObjC"; 303 | PREBINDING = NO; 304 | SDKROOT = iphoneos; 305 | }; 306 | name = Release; 307 | }; 308 | A3289D4C122D705600D89A88 /* Debug */ = { 309 | isa = XCBuildConfiguration; 310 | buildSettings = { 311 | ALWAYS_SEARCH_USER_PATHS = NO; 312 | COPY_PHASE_STRIP = NO; 313 | FRAMEWORK_SEARCH_PATHS = ( 314 | "$(inherited)", 315 | "\"$(SRCROOT)/Vendor/yajl-objc/Project-IPhone/build/Framework\"", 316 | "\"$(SRCROOT)/Classes\"", 317 | "\"$(SRCROOT)/Vendor\"", 318 | ); 319 | GCC_DYNAMIC_NO_PIC = NO; 320 | GCC_OPTIMIZATION_LEVEL = 0; 321 | GCC_PREFIX_HEADER = LROAuth2Client_Prefix.pch; 322 | OTHER_LDFLAGS = ( 323 | "-ObjC", 324 | "-all_load", 325 | ); 326 | PREBINDING = NO; 327 | PRODUCT_NAME = "LROAuth2Client-Device"; 328 | SDKROOT = iphoneos; 329 | }; 330 | name = Debug; 331 | }; 332 | A3289D4D122D705600D89A88 /* Release */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | ALWAYS_SEARCH_USER_PATHS = NO; 336 | COPY_PHASE_STRIP = YES; 337 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 338 | FRAMEWORK_SEARCH_PATHS = ( 339 | "$(inherited)", 340 | "\"$(SRCROOT)/Vendor/yajl-objc/Project-IPhone/build/Framework\"", 341 | "\"$(SRCROOT)/Classes\"", 342 | "\"$(SRCROOT)/Vendor\"", 343 | ); 344 | GCC_ENABLE_FIX_AND_CONTINUE = NO; 345 | GCC_PREFIX_HEADER = LROAuth2Client_Prefix.pch; 346 | OTHER_LDFLAGS = ( 347 | "-ObjC", 348 | "-all_load", 349 | ); 350 | PREBINDING = NO; 351 | PRODUCT_NAME = "LROAuth2Client-Device"; 352 | SDKROOT = iphoneos; 353 | ZERO_LINK = NO; 354 | }; 355 | name = Release; 356 | }; 357 | A3289EC1122D758F00D89A88 /* Debug */ = { 358 | isa = XCBuildConfiguration; 359 | buildSettings = { 360 | ALWAYS_SEARCH_USER_PATHS = NO; 361 | CLANG_ENABLE_OBJC_ARC = YES; 362 | COPY_PHASE_STRIP = NO; 363 | FRAMEWORK_SEARCH_PATHS = ( 364 | "$(inherited)", 365 | "\"$(SRCROOT)/Vendor/yajl-objc/Project-IPhone/build/Framework\"", 366 | "\"$(SRCROOT)/Classes\"", 367 | "\"$(SRCROOT)/Vendor\"", 368 | ); 369 | GCC_DYNAMIC_NO_PIC = NO; 370 | GCC_OPTIMIZATION_LEVEL = 0; 371 | GCC_PREFIX_HEADER = LROAuth2Client_Prefix.pch; 372 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 373 | OTHER_LDFLAGS = ( 374 | "-ObjC", 375 | "-all_load", 376 | ); 377 | PREBINDING = NO; 378 | PRODUCT_NAME = "LROAuth2Client-Simulator"; 379 | SDKROOT = iphoneos; 380 | }; 381 | name = Debug; 382 | }; 383 | A3289EC2122D758F00D89A88 /* Release */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | CLANG_ENABLE_OBJC_ARC = YES; 388 | COPY_PHASE_STRIP = YES; 389 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 390 | FRAMEWORK_SEARCH_PATHS = ( 391 | "$(inherited)", 392 | "\"$(SRCROOT)/Vendor/yajl-objc/Project-IPhone/build/Framework\"", 393 | "\"$(SRCROOT)/Classes\"", 394 | "\"$(SRCROOT)/Vendor\"", 395 | ); 396 | GCC_ENABLE_FIX_AND_CONTINUE = NO; 397 | GCC_PREFIX_HEADER = LROAuth2Client_Prefix.pch; 398 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 399 | OTHER_LDFLAGS = ( 400 | "-ObjC", 401 | "-all_load", 402 | ); 403 | PREBINDING = NO; 404 | PRODUCT_NAME = "LROAuth2Client-Simulator"; 405 | SDKROOT = iphoneos; 406 | ZERO_LINK = NO; 407 | }; 408 | name = Release; 409 | }; 410 | /* End XCBuildConfiguration section */ 411 | 412 | /* Begin XCConfigurationList section */ 413 | 1DEB922208733DC00010E9CD /* Build configuration list for PBXProject "LROAuth2Client" */ = { 414 | isa = XCConfigurationList; 415 | buildConfigurations = ( 416 | 1DEB922308733DC00010E9CD /* Debug */, 417 | 1DEB922408733DC00010E9CD /* Release */, 418 | ); 419 | defaultConfigurationIsVisible = 0; 420 | defaultConfigurationName = Release; 421 | }; 422 | A3289DCD122D70A800D89A88 /* Build configuration list for PBXNativeTarget "LROAuth2Client-Device" */ = { 423 | isa = XCConfigurationList; 424 | buildConfigurations = ( 425 | A3289D4C122D705600D89A88 /* Debug */, 426 | A3289D4D122D705600D89A88 /* Release */, 427 | ); 428 | defaultConfigurationIsVisible = 0; 429 | defaultConfigurationName = Release; 430 | }; 431 | A3289EC0122D758F00D89A88 /* Build configuration list for PBXNativeTarget "LROAuth2Client-Simulator" */ = { 432 | isa = XCConfigurationList; 433 | buildConfigurations = ( 434 | A3289EC1122D758F00D89A88 /* Debug */, 435 | A3289EC2122D758F00D89A88 /* Release */, 436 | ); 437 | defaultConfigurationIsVisible = 0; 438 | defaultConfigurationName = Release; 439 | }; 440 | /* End XCConfigurationList section */ 441 | }; 442 | rootObject = 0867D690FE84028FC02AAC07 /* Project object */; 443 | } 444 | -------------------------------------------------------------------------------- /LROAuth2Client.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LROAuth2Client_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // LROAuth2Client_Prefix.pch 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #ifdef __OBJC__ 10 | #import 11 | #import 12 | #import "Availability.h" 13 | #endif 14 | -------------------------------------------------------------------------------- /MIT-LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Luke Redpath 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /NSDictionary+QueryString.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+QueryString.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | @interface NSDictionary (QueryString) 10 | 11 | + (NSDictionary *)dictionaryWithFormEncodedString:(NSString *)encodedString; 12 | - (NSString *)stringWithFormEncodedComponents; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /NSDictionary+QueryString.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSDictionary+QueryString.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "NSDictionary+QueryString.h" 10 | #import "NSString+QueryString.h" 11 | 12 | @implementation NSDictionary (QueryString) 13 | 14 | + (NSDictionary *)dictionaryWithFormEncodedString:(NSString *)encodedString 15 | { 16 | NSMutableDictionary* result = [NSMutableDictionary dictionary]; 17 | NSArray* pairs = [encodedString componentsSeparatedByString:@"&"]; 18 | 19 | for (NSString* kvp in pairs) 20 | { 21 | if ([kvp length] == 0) 22 | continue; 23 | 24 | NSRange pos = [kvp rangeOfString:@"="]; 25 | NSString *key; 26 | NSString *val; 27 | 28 | if (pos.location == NSNotFound) 29 | { 30 | key = [kvp stringByUnescapingFromURLQuery]; 31 | val = @""; 32 | } 33 | else 34 | { 35 | key = [[kvp substringToIndex:pos.location] stringByUnescapingFromURLQuery]; 36 | val = [[kvp substringFromIndex:pos.location + pos.length] stringByUnescapingFromURLQuery]; 37 | } 38 | 39 | if (!key || !val) 40 | continue; // I'm sure this will bite my arse one day 41 | 42 | [result setObject:val forKey:key]; 43 | } 44 | return result; 45 | } 46 | 47 | - (NSString *)stringWithFormEncodedComponents 48 | { 49 | NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:[self count]]; 50 | for (NSString* key in self) 51 | { 52 | [arguments addObject:[NSString stringWithFormat:@"%@=%@", 53 | [key stringByEscapingForURLQuery], 54 | [[[self objectForKey:key] description] stringByEscapingForURLQuery]]]; 55 | } 56 | 57 | return [arguments componentsJoinedByString:@"&"]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /NSString+QueryString.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+QueryString.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | @interface NSString (QueryString) 10 | 11 | - (NSString*)stringByEscapingForURLQuery; 12 | - (NSString*)stringByUnescapingFromURLQuery; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /NSString+QueryString.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+QueryString.m 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "NSString+QueryString.h" 10 | 11 | @implementation NSString (QueryString) 12 | 13 | - (NSString*)stringByEscapingForURLQuery 14 | { 15 | NSString *result = self; 16 | 17 | CFStringRef originalAsCFString = (__bridge CFStringRef) self; 18 | CFStringRef leaveAlone = CFSTR(" "); 19 | CFStringRef toEscape = CFSTR("\n\r?[]()$,!'*;:@&=#%+/"); 20 | 21 | CFStringRef escapedStr; 22 | escapedStr = CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, originalAsCFString, leaveAlone, toEscape, kCFStringEncodingUTF8); 23 | 24 | if (escapedStr) { 25 | NSMutableString *mutable = [NSMutableString stringWithString:(__bridge NSString *)escapedStr]; 26 | CFRelease(escapedStr); 27 | 28 | [mutable replaceOccurrencesOfString:@" " withString:@"+" options:0 range:NSMakeRange(0, [mutable length])]; 29 | result = mutable; 30 | } 31 | return result; 32 | } 33 | 34 | - (NSString*)stringByUnescapingFromURLQuery 35 | { 36 | return [[self stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"+" withString:@" "]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /NSURL+QueryInspector.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+QueryInspector.h 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSURL (QueryInspector) 13 | 14 | - (NSDictionary *)queryDictionary; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /NSURL+QueryInspector.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSURL+QueryInspector.m 3 | // LROAuth2Client 4 | // 5 | // Created by Luke Redpath on 14/05/2010. 6 | // Copyright 2010 LJR Software Limited. All rights reserved. 7 | // 8 | 9 | #import "NSURL+QueryInspector.h" 10 | #import "NSDictionary+QueryString.h" 11 | 12 | @implementation NSURL (QueryInspector) 13 | 14 | - (NSDictionary *)queryDictionary; 15 | { 16 | return [NSDictionary dictionaryWithFormEncodedString:self.query]; 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # LROAuth2Client, OAuth2 client for iPhone/iPad 2 | 3 | Not much documentation here right now, but check out [my introductory blog post](http://lukeredpath.co.uk/blog/oauth2-for-iphone-and-ipad-applications.html). 4 | 5 | A demo project can be found [here](http://github.com/lukeredpath/LROAuth2Demo). -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/tasklib' 2 | 3 | TARGET_NAME = "LROAuth2Client" 4 | 5 | module XcodeBuild 6 | class BuildTask < Rake::TaskLib 7 | attr_accessor :target, :configuration, :sdk 8 | 9 | def initialize(name) 10 | @name = name 11 | @configuration = "Debug" 12 | yield self if block_given? 13 | define 14 | end 15 | 16 | def define 17 | raise "Xcode build target must be defined (in task: #{@name})" if target.nil? 18 | 19 | desc "Build the #{target} target in #{configuration}" 20 | task @name do 21 | system("xcodebuild -target #{target} -configuration #{configuration} build -sdk #{sdk}") 22 | end 23 | end 24 | end 25 | 26 | def self.clean! 27 | system("xcodebuild clean") 28 | end 29 | end 30 | 31 | def xcodebuild(name, &block) 32 | XcodeBuild::BuildTask.new(name, &block) 33 | end 34 | 35 | SDK_VERSION = ENV['SDK'] || '4.0' 36 | 37 | namespace :build do 38 | xcodebuild :device do |t| 39 | t.target = "#{TARGET_NAME}-Device" 40 | t.configuration = "Release" 41 | t.sdk = "iphoneos#{SDK_VERSION}" 42 | end 43 | 44 | xcodebuild :simulator do |t| 45 | t.target = "#{TARGET_NAME}-Simulator" 46 | t.configuration = "Release" 47 | t.sdk = "iphonesimulator#{SDK_VERSION}" 48 | end 49 | 50 | desc "Build the combined static library" 51 | task :combined => [:device, :simulator] do 52 | ENV["BUILD_DIR"] = "build" 53 | ENV["BUILD_STYLE"] = "Release" 54 | 55 | if system("sh Scripts/CombineLibs.sh") 56 | puts "Combined libraries built successfully." 57 | else 58 | puts "There was an error building the combined libraries." 59 | end 60 | end 61 | 62 | desc "Package up the framework for release" 63 | task :framework => [:clean, :combined] do 64 | if system("sh Scripts/iPhoneFramework.sh") 65 | puts "Framework built successfully." 66 | else 67 | puts "There was an error building the framework." 68 | end 69 | end 70 | end 71 | 72 | desc "Clean the build directory" 73 | task :clean do 74 | XcodeBuild.clean! 75 | end 76 | 77 | task :default => "build:framework" 78 | -------------------------------------------------------------------------------- /Scripts/CombineLibs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | FLAVOR="" 6 | NAME=libLROAuth2Client 7 | OUTPUT_DIR=${BUILD_DIR}/Combined${BUILD_STYLE}${FLAVOR} 8 | OUTPUT_FILE=${NAME}${FLAVOR}.a 9 | ZIP_DIR=${BUILD_DIR}/Zip 10 | 11 | if [ ! -d ${OUTPUT_DIR} ]; then 12 | mkdir ${OUTPUT_DIR} 13 | fi 14 | 15 | # Combine lib files 16 | lipo -create "${BUILD_DIR}/${BUILD_STYLE}-iphoneos/${NAME}-Device${FLAVOR}.a" "${BUILD_DIR}/${BUILD_STYLE}-iphonesimulator/${NAME}-Simulator${FLAVOR}.a" -output ${OUTPUT_DIR}/${OUTPUT_FILE} 17 | 18 | # Copy to direcory for zipping 19 | if [ ! -d ${ZIP_DIR} ]; then 20 | mkdir ${ZIP_DIR} 21 | fi 22 | cp ${OUTPUT_DIR}/${OUTPUT_FILE} ${ZIP_DIR} 23 | cp ${BUILD_DIR}/${BUILD_STYLE}-iphonesimulator/usr/local/include/*.h ${ZIP_DIR} 24 | 25 | cd ${ZIP_DIR} 26 | zip -m ${NAME}${FLAVOR}.zip * 27 | mv ${NAME}${FLAVOR}.zip .. 28 | rm -rf ${ZIP_DIR} 29 | -------------------------------------------------------------------------------- /Scripts/iPhoneFramework.sh: -------------------------------------------------------------------------------- 1 | # Original Script by Pete Goodliffe 2 | # from http://accu.org/index.php/journals/1594 3 | 4 | # Modified by Juan Batiz-Benet for GHUnitIOS 5 | # Modified by Gabriel Handford for YAJL 6 | 7 | set -e 8 | 9 | # Define these to suit your nefarious purposes 10 | FRAMEWORK_NAME=LROAuth2Client 11 | LIB_NAME=libLROAuth2Client 12 | FRAMEWORK_VERSION=A 13 | BUILD_TYPE=Release 14 | 15 | # Where we'll put the build framework. 16 | # The script presumes we're in the project root 17 | # directory. Xcode builds in "build" by default 18 | FRAMEWORK_BUILD_PATH="build/Framework" 19 | 20 | # Clean any existing framework that might be there 21 | # already 22 | echo "Framework: Cleaning framework..." 23 | [ -d "$FRAMEWORK_BUILD_PATH" ] && \ 24 | rm -rf "$FRAMEWORK_BUILD_PATH" 25 | 26 | # This is the full name of the framework we'll 27 | # build 28 | FRAMEWORK_DIR=$FRAMEWORK_BUILD_PATH/$FRAMEWORK_NAME.framework 29 | 30 | # Build the canonical Framework bundle directory 31 | # structure 32 | echo "Framework: Setting up directories..." 33 | mkdir -p $FRAMEWORK_DIR 34 | mkdir -p $FRAMEWORK_DIR/Versions 35 | mkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION 36 | mkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION/Resources 37 | mkdir -p $FRAMEWORK_DIR/Versions/$FRAMEWORK_VERSION/Headers 38 | 39 | echo "Framework: Creating symlinks..." 40 | ln -s $FRAMEWORK_VERSION $FRAMEWORK_DIR/Versions/Current 41 | ln -s Versions/Current/Headers $FRAMEWORK_DIR/Headers 42 | ln -s Versions/Current/Resources $FRAMEWORK_DIR/Resources 43 | ln -s Versions/Current/$FRAMEWORK_NAME $FRAMEWORK_DIR/$FRAMEWORK_NAME 44 | 45 | # Check that this is what your static libraries 46 | # are called 47 | ARM_FILES="build/$BUILD_TYPE-iphoneos/${LIB_NAME}-Device.a" 48 | I386_FILES="build/$BUILD_TYPE-iphonesimulator/${LIB_NAME}-Simulator.a" 49 | 50 | # The trick for creating a fully usable library is 51 | # to use lipo to glue the different library 52 | # versions together into one file. When an 53 | # application is linked to this library, the 54 | # linker will extract the appropriate platform 55 | # version and use that. 56 | # The library file is given the same name as the 57 | # framework with no .a extension. 58 | echo "Framework: Creating library..." 59 | 60 | lipo \ 61 | -create \ 62 | "$ARM_FILES" \ 63 | "$I386_FILES" \ 64 | -o "$FRAMEWORK_DIR/Versions/Current/$FRAMEWORK_NAME" 65 | 66 | # Now copy the final assets over: your library 67 | # header files and the plist file 68 | echo "Framework: Copying assets into current version..." 69 | cp ./build/$BUILD_TYPE-iphoneos/usr/local/include/*.h $FRAMEWORK_DIR/Headers/ 70 | cp Framework.plist $FRAMEWORK_DIR/Resources/Info.plist 71 | --------------------------------------------------------------------------------