adium 5464:794a4d6869e2: Bring STTwitter more up to date with wh...

commits at adium.im commits at adium.im
Fri May 3 10:58:34 UTC 2013


details:	http://hg.adium.im/adium/rev/794a4d6869e2
revision:	5464:794a4d6869e2
branch:		adium-1.6
author:		Thijs Alkemade <me at thijsalkema.de>
date:		Fri May 03 11:30:45 2013 +0200

Bring STTwitter more up to date with what's on github (specifically, merge a leak fix from upstream).
Subject: adium 5465:0d3d3a9afde1: Merged with wixardy.

details:	http://hg.adium.im/adium/rev/0d3d3a9afde1
revision:	5465:0d3d3a9afde1
branch:		adium-1.6
author:		Thijs Alkemade <me at thijsalkema.de>
date:		Fri May 03 12:58:24 2013 +0200

Merged with wixardy.

diffs (704 lines):

diff -r 0c51e1c6487d -r 0d3d3a9afde1 Adium.xcodeproj/project.pbxproj
--- a/Adium.xcodeproj/project.pbxproj	Fri May 03 02:31:52 2013 +0200
+++ b/Adium.xcodeproj/project.pbxproj	Fri May 03 12:58:24 2013 +0200
@@ -1361,6 +1361,7 @@
 		76AA110D1635585E00A6EC4B /* AIAccountSelectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76AA110B1635585E00A6EC4B /* AIAccountSelectionViewController.m */; };
 		76AA1110163558B200A6EC4B /* AIRejoinGroupChatViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76AA110F163558B200A6EC4B /* AIRejoinGroupChatViewController.m */; };
 		76C1AF9C125A906A00D269A9 /* AIAdiumURLProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 76C1AF9B125A906A00D269A9 /* AIAdiumURLProtocol.m */; };
+		76FBDAC91733B9CA00C9F10B /* STTwitterHTML.m in Sources */ = {isa = PBXBuildFile; fileRef = 76FBDAC61733B9C900C9F10B /* STTwitterHTML.m */; };
 		76FF925A14B524B40043E23B /* AIIRCConsoleController.h in Headers */ = {isa = PBXBuildFile; fileRef = 76FF925814B524B40043E23B /* AIIRCConsoleController.h */; };
 		76FF925B14B524B40043E23B /* AIIRCConsoleController.m in Sources */ = {isa = PBXBuildFile; fileRef = 76FF925914B524B40043E23B /* AIIRCConsoleController.m */; };
 		76FF926414B62A980043E23B /* AIConsole.xib in Resources */ = {isa = PBXBuildFile; fileRef = 76FF926314B62A980043E23B /* AIConsole.xib */; };
@@ -4420,6 +4421,10 @@
 		76AA110F163558B200A6EC4B /* AIRejoinGroupChatViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIRejoinGroupChatViewController.m; path = "Plugins/Dual Window Interface/AIRejoinGroupChatViewController.m"; sourceTree = "<group>"; };
 		76C1AF9A125A906A00D269A9 /* AIAdiumURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIAdiumURLProtocol.h; path = "Plugins/WebKit Message View/AIAdiumURLProtocol.h"; sourceTree = "<group>"; };
 		76C1AF9B125A906A00D269A9 /* AIAdiumURLProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIAdiumURLProtocol.m; path = "Plugins/WebKit Message View/AIAdiumURLProtocol.m"; sourceTree = "<group>"; };
+		76FBDAC51733B9C900C9F10B /* STTwitterHTML.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STTwitterHTML.h; path = "Plugins/Twitter Plugin/STTwitter/STTwitterHTML.h"; sourceTree = "<group>"; };
+		76FBDAC61733B9C900C9F10B /* STTwitterHTML.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = STTwitterHTML.m; path = "Plugins/Twitter Plugin/STTwitter/STTwitterHTML.m"; sourceTree = "<group>"; };
+		76FBDAC71733B9C900C9F10B /* STTwitterOAuthOSX.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = STTwitterOAuthOSX.h; path = "Plugins/Twitter Plugin/STTwitter/STTwitterOAuthOSX.h"; sourceTree = "<group>"; };
+		76FBDAC81733B9C900C9F10B /* STTwitterOAuthOSX.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = STTwitterOAuthOSX.m; path = "Plugins/Twitter Plugin/STTwitter/STTwitterOAuthOSX.m"; sourceTree = "<group>"; };
 		76FF925814B524B40043E23B /* AIIRCConsoleController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AIIRCConsoleController.h; path = "Plugins/Purple Service/AIIRCConsoleController.h"; sourceTree = "<group>"; };
 		76FF925914B524B40043E23B /* AIIRCConsoleController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AIIRCConsoleController.m; path = "Plugins/Purple Service/AIIRCConsoleController.m"; sourceTree = "<group>"; };
 		76FF926314B62A980043E23B /* AIConsole.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AIConsole.xib; path = "Frameworks/Adium Framework/Resources/AIConsole.xib"; sourceTree = "<group>"; };
@@ -7330,6 +7335,10 @@
 				5A3B4D7116D878AB00903E40 /* STTwitterOAuth.h */,
 				5A3B4D7216D878AB00903E40 /* STTwitterOAuth.m */,
 				5A3B4D7516D878AB00903E40 /* STTwitterOAuthProtocol.h */,
+				76FBDAC51733B9C900C9F10B /* STTwitterHTML.h */,
+				76FBDAC61733B9C900C9F10B /* STTwitterHTML.m */,
+				76FBDAC71733B9C900C9F10B /* STTwitterOAuthOSX.h */,
+				76FBDAC81733B9C900C9F10B /* STTwitterOAuthOSX.m */,
 				5A3B4D7616D878AC00903E40 /* Vendor */,
 			);
 			name = STTwitter;
@@ -10565,6 +10574,7 @@
 				5A3B4D7E16D878AC00903E40 /* STHTTPRequest.m in Sources */,
 				5A0D236A16F4C7BC005DF211 /* STTwitterAppOnly.m in Sources */,
 				5A4B77E916FBDDC700DF398C /* NSData+Base64.m in Sources */,
+				76FBDAC91733B9CA00C9F10B /* STTwitterHTML.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Frameworks/PSMTabBarControl.framework/Versions/A/PSMTabBarControl
Binary file Frameworks/PSMTabBarControl.framework/Versions/A/PSMTabBarControl has changed
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/STTwitterAPIWrapper.h
--- a/Plugins/Twitter Plugin/STTwitter/STTwitterAPIWrapper.h	Fri May 03 02:31:52 2013 +0200
+++ b/Plugins/Twitter Plugin/STTwitter/STTwitterAPIWrapper.h	Fri May 03 12:58:24 2013 +0200
@@ -89,8 +89,12 @@
 @property (nonatomic, readonly) NSString *bearerToken;
 
 - (void)profileImageFor:(NSString *)screenName
-				successBlock:(void(^)(NSImage *image))successBlock
-				  errorBlock:(void(^)(NSError *error))errorBlock;;
+#if TARGET_OS_IPHONE
+           successBlock:(void(^)(UIImage *image))successBlock
+#else
+           successBlock:(void(^)(NSImage *image))successBlock
+#endif
+             errorBlock:(void(^)(NSError *error))errorBlock;
 
 #pragma mark Timelines
 
@@ -284,7 +288,11 @@
 
 //	POST	account/update_profile_image
 //	Returns Users (1: the user)
+#if TARGET_OS_IPHONE
+- (void)postUpdateProfileImage:(UIImage *)newImage
+#else
 - (void)postUpdateProfileImage:(NSImage *)newImage
+#endif
 				  successBlock:(void(^)(NSDictionary *myInfo))successBlock
 					errorBlock:(void(^)(NSError *error))errorBlock;
 
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/STTwitterAPIWrapper.m
--- a/Plugins/Twitter Plugin/STTwitter/STTwitterAPIWrapper.m	Fri May 03 02:31:52 2013 +0200
+++ b/Plugins/Twitter Plugin/STTwitter/STTwitterAPIWrapper.m	Fri May 03 12:58:24 2013 +0200
@@ -22,18 +22,6 @@
 @synthesize consumerName = _consumerName;
 @synthesize userName = _userName;
 
-#if TARGET_OS_IPHONE
-#else
-
-- (id)init {
-    self = [super init];
-	
-    return self;
-}
-
-
-#endif
-
 + (STTwitterAPIWrapper *)twitterAPIWithOAuthConsumerName:(NSString *)consumerName
                                              consumerKey:(NSString *)consumerKey
                                           consumerSecret:(NSString *)consumerSecret
@@ -160,8 +148,14 @@
 /**/
 
 - (void)profileImageFor:(NSString *)screenName
-				successBlock:(void(^)(NSImage *image))successBlock
-				  errorBlock:(void(^)(NSError *error))errorBlock {
+
+#if TARGET_OS_IPHONE
+           successBlock:(void(^)(UIImage *image))successBlock
+#else
+           successBlock:(void(^)(NSImage *image))successBlock
+#endif
+
+             errorBlock:(void(^)(NSError *error))errorBlock {
 	[self getUserInformationFor:screenName
 				   successBlock:^(NSDictionary *response) {
 					   NSString *imageURL = [response objectForKey:@"profile_image_url"];
@@ -169,7 +163,13 @@
 					   NSURLRequest *imageRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURL]];
 					   
 					   NSData *imageData = [NSURLConnection sendSynchronousRequest:imageRequest returningResponse:nil error:nil];
-					   successBlock([[NSImage alloc] initWithData:imageData]);
+                       
+#if TARGET_OS_IPHONE
+					   successBlock([[[UIImage alloc] initWithData:imageData] autorelease]);
+#else
+					   successBlock([[[NSImage alloc] initWithData:imageData] autorelease]);
+#endif
+                       
 				   } errorBlock:^(NSError *error) {
 					   errorBlock(error);
 				   }];
@@ -471,7 +471,7 @@
 		errorBlock:(void(^)(NSError *error))errorBlock {
 	NSDictionary *d = @{@"screen_name" : screenName};
     
-    [_oauth getResource:@"friendships/create.json" parameters:d successBlock:^(id response) {
+    [_oauth postResource:@"friendships/create.json" parameters:d successBlock:^(id response) {
         successBlock(removeNull(response));
     } errorBlock:^(NSError *error) {
         errorBlock(error);
@@ -483,7 +483,7 @@
 		  errorBlock:(void(^)(NSError *error))errorBlock {
 	NSDictionary *d = @{@"screen_name" : screenName};
     
-    [_oauth getResource:@"friendships/destroy.json" parameters:d successBlock:^(id response) {
+    [_oauth postResource:@"friendships/destroy.json" parameters:d successBlock:^(id response) {
         successBlock(removeNull(response));
     } errorBlock:^(NSError *error) {
         errorBlock(error);
@@ -497,7 +497,7 @@
 	NSMutableDictionary *d = [NSMutableDictionary dictionaryWithObject:screenName forKey:@"screen_name"];
 	[d setObject:notify ? @"true" : @"false" forKey:@"device"];
     
-    [_oauth getResource:@"friendships/update.json" parameters:d successBlock:^(id response) {
+    [_oauth postResource:@"friendships/update.json" parameters:d successBlock:^(id response) {
         successBlock(removeNull(response));
     } errorBlock:^(NSError *error) {
         errorBlock(error);
@@ -541,7 +541,11 @@
     }];
 }
 
+#if TARGET_OS_IPHONE
+- (void)postUpdateProfileImage:(UIImage *)newImage
+#else
 - (void)postUpdateProfileImage:(NSImage *)newImage
+#endif
 				  successBlock:(void(^)(NSDictionary *myInfo))successBlock
 					errorBlock:(void(^)(NSError *error))errorBlock {
 	NSMutableDictionary *md = [NSMutableDictionary dictionaryWithObject:newImage forKey:@"image"];
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/STTwitterHTML.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Twitter Plugin/STTwitter/STTwitterHTML.h	Fri May 03 12:58:24 2013 +0200
@@ -0,0 +1,35 @@
+//
+//  STTwitterWeb.h
+//  STTwitterRequests
+//
+//  Created by Nicolas Seriot on 9/13/12.
+//  Copyright (c) 2012 Nicolas Seriot. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+ at interface STTwitterHTML : NSObject
+
+- (void)getLoginForm:(void(^)(NSString *authenticityToken))successBlock
+            errorBlock:(void(^)(NSError *error))errorBlock;
+
+- (void)postLoginFormWithUsername:(NSString *)username
+                                 password:(NSString *)password
+                        authenticityToken:(NSString *)authenticityToken
+                             successBlock:(void(^)())successBlock
+                               errorBlock:(void(^)(NSError *error))errorBlock;
+
+
+/**/
+
+- (void)getAuthorizeFormAtURL:(NSURL *)url
+                   successBlock:(void(^)(NSString *authenticityToken, NSString *oauthToken))successBlock
+                     errorBlock:(void(^)(NSError *error))errorBlock;
+
+- (void)postAuthorizeFormResultsAtURL:(NSURL *)url
+                    authenticityToken:(NSString *)authenticityToken
+                           oauthToken:(NSString *)oauthToken
+                         successBlock:(void(^)(NSString *PIN))successBlock
+                           errorBlock:(void(^)(NSError *error))errorBlock;
+
+ at end
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/STTwitterHTML.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Twitter Plugin/STTwitter/STTwitterHTML.m	Fri May 03 12:58:24 2013 +0200
@@ -0,0 +1,142 @@
+//
+//  STTwitterWeb.m
+//  STTwitterRequests
+//
+//  Created by Nicolas Seriot on 9/13/12.
+//  Copyright (c) 2012 Nicolas Seriot. All rights reserved.
+//
+
+#import "STTwitterHTML.h"
+#import "STHTTPRequest.h"
+#import "NSString+STTwitter.h"
+
+ at implementation STTwitterHTML
+
+- (void)getLoginForm:(void(^)(NSString *authenticityToken))successBlock errorBlock:(void(^)(NSError *error))errorBlock {
+    
+    STHTTPRequest *r = [STHTTPRequest requestWithURLString:@"https://twitter.com/login"];
+    
+    r.completionBlock = ^(NSDictionary *headers, NSString *body) {
+
+        NSError *error = nil;
+//        NSString *token = [body firstMatchWithRegex:@"<input type=\"hidden\" value=\"(\\S+)\" name=\"authenticity_token\"/>" error:&error];        
+        NSString *token = [body firstMatchWithRegex:@"formAuthenticityToken":"(\\S+?)&quot" error:&error];
+
+        if(token == nil) {
+            errorBlock(error);
+            return;
+        }
+
+        successBlock(token);
+    };
+    
+    r.errorBlock = ^(NSError *error) {
+        errorBlock(error);
+    };
+    
+    [r startAsynchronous];
+}
+
+- (void)postLoginFormWithUsername:(NSString *)username
+                                 password:(NSString *)password
+                        authenticityToken:(NSString *)authenticityToken
+                             successBlock:(void(^)())successBlock
+                               errorBlock:(void(^)(NSError *error))errorBlock {
+    
+    if([username length] == 0 || [password length] == 0) {
+        NSString *errorDescription = [NSString stringWithFormat:@"Missing credentials"];
+        NSError *error = [NSError errorWithDomain:NSStringFromClass([self class]) code:0 userInfo:@{NSLocalizedDescriptionKey : errorDescription}];
+        errorBlock(error);
+        return;
+    }
+    
+    STHTTPRequest *r = [STHTTPRequest requestWithURLString:@"https://twitter.com/sessions"];
+    
+    r.POSTDictionary = @{@"authenticity_token" : authenticityToken,
+                         @"session[username_or_email]" : username,
+                         @"session[password]" : password,
+                         @"remember_me" : @"1",
+                         @"commit" : @"Sign in"};
+    
+    r.completionBlock = ^(NSDictionary *headers, NSString *body) {
+        successBlock();
+    };
+    
+    r.errorBlock = ^(NSError *error) {
+        errorBlock(error);
+    };
+    
+    [r startAsynchronous];
+}
+
+- (void)getAuthorizeFormAtURL:(NSURL *)url successBlock:(void(^)(NSString *authenticityToken, NSString *oauthToken))successBlock errorBlock:(void(^)(NSError *error))errorBlock {
+
+    STHTTPRequest *r = [STHTTPRequest requestWithURL:url];
+        
+    r.completionBlock = ^(NSDictionary *headers, NSString *body) {
+        /*
+        <form action="https://api.twitter.com/oauth/authorize" id="oauth_form" method="post"><div style="margin:0;padding:0"><input name="authenticity_token" type="hidden" value="dacd811cf06655518633ad93e950132614eab7f4" /></div>
+        
+        <input id="oauth_token" name="oauth_token" type="hidden" value="3qp5r3Ya65aVks8lNZEZm7313080zTdMQTOplalzQI" />
+        */
+        
+        NSError *error1 = nil;
+        NSString *authenticityToken = [body firstMatchWithRegex:@"<input name=\"authenticity_token\" type=\"hidden\" value=\"(\\S+)\" />" error:&error1];
+        
+        if(authenticityToken == nil) {
+            errorBlock(error1);
+            return;
+        }
+        
+        /**/
+        
+        NSError *error2 = nil;
+        
+        NSString *oauthToken = [body firstMatchWithRegex:@"<input id=\"oauth_token\" name=\"oauth_token\" type=\"hidden\" value=\"(\\S+)\" />" error:&error2];
+        
+        if(oauthToken == nil) {
+            errorBlock(error2);
+            return;
+        }
+        
+        /**/
+        
+        successBlock(authenticityToken, oauthToken);
+    };
+    
+    r.errorBlock = ^(NSError *error) {
+        errorBlock(error);
+    };
+    
+    [r startAsynchronous];
+}
+
+- (void)postAuthorizeFormResultsAtURL:(NSURL *)url authenticityToken:(NSString *)authenticityToken oauthToken:(NSString *)oauthToken successBlock:(void(^)(NSString *PIN))successBlock errorBlock:(void(^)(NSError *error))errorBlock {
+
+    STHTTPRequest *r = [STHTTPRequest requestWithURL:url];
+    
+    r.POSTDictionary = @{@"authenticity_token" : authenticityToken,
+                         @"oauth_token" : oauthToken};
+    
+    r.completionBlock = ^(NSDictionary *headers, NSString *body) {
+        
+        NSError *error = nil;
+        NSString *pin = [body firstMatchWithRegex:@"<code>(\\d+)</code>" error:&error];
+        
+        if(pin == nil) {
+            errorBlock(error);
+            return;
+        }
+        
+        successBlock(pin);
+    };
+    
+    r.errorBlock = ^(NSError *error) {
+        errorBlock(error);
+    };
+    
+    [r startAsynchronous];
+}
+
+ at end
+
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/STTwitterOAuthOSX.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Twitter Plugin/STTwitter/STTwitterOAuthOSX.h	Fri May 03 12:58:24 2013 +0200
@@ -0,0 +1,35 @@
+//
+//  MGTwitterEngine+TH.h
+//  TwitHunter
+//
+//  Created by Nicolas Seriot on 5/1/10.
+//  Copyright 2010 seriot.ch. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import "STTwitterOAuthProtocol.h"
+
+#if TARGET_OS_IPHONE
+#else
+
+typedef void (^STTE_completionBlock_t)(NSArray *statuses);
+typedef void (^STTE_errorBlock_t)(NSError *error);
+
+ at class ACAccount;
+
+ at interface STTwitterOAuthOSX : NSObject <STTwitterOAuthProtocol> {
+
+}
+
+
+- (BOOL)canVerifyCredentials;
+- (void)verifyCredentialsWithSuccessBlock:(void(^)(NSString *username))successBlock errorBlock:(void(^)(NSError *error))errorBlock;
+
+- (void)getResource:(NSString *)resource parameters:(NSDictionary *)params successBlock:(STTE_completionBlock_t)completionBlock errorBlock:(STTE_errorBlock_t)errorBlock;
+- (void)postResource:(NSString *)resource parameters:(NSDictionary *)params successBlock:(STTE_completionBlock_t)completionBlock errorBlock:(STTE_errorBlock_t)errorBlock;
+
+- (NSString *)username;
+
+ at end
+
+#endif
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/STTwitterOAuthOSX.m
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Plugins/Twitter Plugin/STTwitter/STTwitterOAuthOSX.m	Fri May 03 12:58:24 2013 +0200
@@ -0,0 +1,181 @@
+//
+//  MGTwitterEngine+TH.m
+//  TwitHunter
+//
+//  Created by Nicolas Seriot on 5/1/10.
+//  Copyright 2010 seriot.ch. All rights reserved.
+//
+
+#import "STTwitterOAuthOSX.h"
+#import <Social/Social.h>
+#import <Accounts/Accounts.h>
+
+#if TARGET_OS_IPHONE
+#else
+
+ at implementation STTwitterOAuthOSX
+
+- (void)verifyCredentialsWithSuccessBlock:(void(^)(NSString *username))successBlock errorBlock:(void(^)(NSError *error))errorBlock {
+    [self requestAccessWithCompletionBlock:^(ACAccount *twitterAccount) {
+        successBlock(twitterAccount.username);
+    } errorBlock:^(NSError *error) {
+        errorBlock(error);
+    }];
+}
+
+- (NSString *)username {
+    ACAccountStore *accountStore = [[[ACAccountStore alloc] init] autorelease];
+    ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
+    NSArray *accounts = [accountStore accountsWithAccountType:accountType];
+    ACAccount *twitterAccount = [accounts lastObject];
+    return twitterAccount.username;
+}
+
+- (void)requestAccessWithCompletionBlock:(void(^)(ACAccount *twitterAccount))completionBlock errorBlock:(void(^)(NSError *))errorBlock {
+    
+    ACAccountStore *accountStore = [[ACAccountStore alloc] init];
+    ACAccountType *accountType = [accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
+    
+    [accountStore requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error) {
+        
+        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+            if(granted) {
+                
+                NSArray *accounts = [accountStore accountsWithAccountType:accountType];
+                
+                // TODO: let the user choose the account he wants
+                ACAccount *twitterAccount = [accounts lastObject];
+                
+//                id cred = [twitterAccount credential];
+                
+                completionBlock(twitterAccount);
+            } else {
+                NSError *e = error;
+                if(e == nil) {
+                    NSDictionary *userInfo = @{ NSLocalizedDescriptionKey : @"Cannot access OS X Twitter account." };
+                    e = [NSError errorWithDomain:@"STTwitterOAuthOSX" code:0 userInfo:userInfo];
+                }
+                errorBlock(e);
+            }
+        }];
+    }];
+}
+
+- (void)fetchAPIResource:(NSString *)resource httpMethod:(int)httpMethod parameters:(NSDictionary *)params completionBlock:(STTE_completionBlock_t)completionBlock errorBlock:(STTE_errorBlock_t)errorBlock {
+
+    NSData *mediaData = [params valueForKey:@"media[]"];
+    
+    NSMutableDictionary *paramsWithoutMedia = [[params mutableCopy] autorelease];
+    [paramsWithoutMedia removeObjectForKey:@"media[]"];
+    
+    [self requestAccessWithCompletionBlock:^(ACAccount *twitterAccount) {
+        NSString *urlString = [@"https://api.twitter.com/1.1/" stringByAppendingString:resource];
+        NSURL *url = [NSURL URLWithString:urlString];
+        SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:httpMethod URL:url parameters:paramsWithoutMedia];
+        request.account = twitterAccount;
+        
+        if(mediaData) {
+            [request addMultipartData:mediaData withName:@"media[]" type:@"application/octet-stream" filename:@"media.jpg"];
+        }
+        
+        [request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
+            if(responseData == nil) {
+                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+                    errorBlock(nil);
+                }];
+                return;
+            }
+            
+            NSError *jsonError = nil;
+            NSJSONSerialization *json = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableLeaves error:&jsonError];
+            
+            if(json == nil) {
+                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+                    errorBlock(jsonError);
+                }];
+                return;
+            }
+            
+            /**/
+            
+            if([json isKindOfClass:[NSArray class]] == NO && [json valueForKey:@"error"]) {
+                
+                NSString *message = [json valueForKey:@"error"];
+                NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey];
+                NSError *jsonErrorFromResponse = [NSError errorWithDomain:NSStringFromClass([self class]) code:0 userInfo:userInfo];
+                
+                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+                    errorBlock(jsonErrorFromResponse);
+                }];
+                
+                return;
+            }
+            
+            /**/
+            
+            id jsonErrors = [json valueForKey:@"errors"];
+            
+            if(jsonErrors != nil && [jsonErrors isKindOfClass:[NSArray class]] == NO) {
+                if(jsonErrors == nil) jsonErrors = @"";
+                jsonErrors = [NSArray arrayWithObject:@{@"message":jsonErrors, @"code" : @(0)}];
+            }
+            
+            if([jsonErrors count] > 0 && [[jsonErrors lastObject] isEqualTo:[NSNull null]] == NO) {
+                
+                NSDictionary *jsonErrorDictionary = [jsonErrors lastObject];
+                NSString *message = jsonErrorDictionary[@"message"];
+                NSInteger code = [jsonErrorDictionary[@"code"] intValue];
+                NSDictionary *userInfo = [NSDictionary dictionaryWithObject:message forKey:NSLocalizedDescriptionKey];
+                NSError *jsonErrorFromResponse = [NSError errorWithDomain:NSStringFromClass([self class]) code:code userInfo:userInfo];
+                
+                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+                    errorBlock(jsonErrorFromResponse);
+                }];
+                
+                return;
+            }
+            
+            /**/
+            
+            if(json) {
+                
+                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+                    completionBlock((NSArray *)json);
+                }];
+                
+            } else {
+                
+                [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+                    errorBlock(jsonError);
+                }];
+            }
+        }];
+        
+    } errorBlock:^(NSError *error) {
+        errorBlock(error);
+    }];
+}
+
+- (BOOL)canVerifyCredentials {
+    return YES;
+}
+
+- (void)getResource:(NSString *)resource parameters:(NSDictionary *)params successBlock:(STTE_completionBlock_t)completionBlock errorBlock:(STTE_errorBlock_t)errorBlock {
+    
+    int HTTPMethod = SLRequestMethodGET;
+    
+    [self fetchAPIResource:resource httpMethod:HTTPMethod parameters:params completionBlock:completionBlock errorBlock:errorBlock];
+}
+
+- (void)postResource:(NSString *)resource parameters:(NSDictionary *)params successBlock:(STTE_completionBlock_t)completionBlock errorBlock:(STTE_errorBlock_t)errorBlock {
+    
+    int HTTPMethod = SLRequestMethodPOST;
+    
+    NSDictionary *d = params ? params : @{};
+    
+    [self fetchAPIResource:resource httpMethod:HTTPMethod parameters:d completionBlock:completionBlock errorBlock:errorBlock];
+}
+
+ at end
+
+#endif
diff -r 0c51e1c6487d -r 0d3d3a9afde1 Plugins/Twitter Plugin/STTwitter/Vendor/STHTTPRequest.m
--- a/Plugins/Twitter Plugin/STTwitter/Vendor/STHTTPRequest.m	Fri May 03 02:31:52 2013 +0200
+++ b/Plugins/Twitter Plugin/STTwitter/Vendor/STHTTPRequest.m	Fri May 03 12:58:24 2013 +0200
@@ -332,7 +332,7 @@
         [body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
         
         [request setHTTPMethod:@"POST"];
-        [request setValue:[NSString stringWithFormat:@"%lu", [body length]] forHTTPHeaderField:@"Content-Length"];
+        [request setValue:[NSString stringWithFormat:@"%u", (unsigned int)[body length]] forHTTPHeaderField:@"Content-Length"];
         [request setHTTPBody:body];
         
     } else if(_POSTDictionary != nil) { // may be empty (POST request without body)
@@ -365,11 +365,11 @@
         NSData *data = [s dataUsingEncoding:_postDataEncoding allowLossyConversion:YES];
         
         [request setHTTPMethod:@"POST"];
-        [request setValue:[NSString stringWithFormat:@"%lu", [data length]] forHTTPHeaderField:@"Content-Length"];
+        [request setValue:[NSString stringWithFormat:@"%u", (unsigned int)[data length]] forHTTPHeaderField:@"Content-Length"];
         [request setHTTPBody:data];
     } else if (_POSTData != nil) {
         [request setHTTPMethod:@"POST"];
-        [request setValue:[NSString stringWithFormat:@"%lu", [_POSTData length]] forHTTPHeaderField:@"Content-Length"];
+        [request setValue:[NSString stringWithFormat:@"%u", (unsigned int)[_POSTData length]] forHTTPHeaderField:@"Content-Length"];
         [request setHTTPBody:_POSTData];
     }
     
@@ -442,6 +442,82 @@
     return [[[NSString alloc] initWithData:data encoding:encoding] autorelease];
 }
 
+#if DEBUG
+- (NSString *)curlDescription {
+    
+    NSMutableArray *ma = [NSMutableArray array];
+    [ma addObject:@"$ curl -i"];
+    
+    // -u usernane:password
+    
+    NSURLCredential *credential = [[self class] sessionAuthenticationCredentialsForURL:[self url]];
+    if(credential) {
+        NSString *s = [NSString stringWithFormat:@"-u \"%@:%@\"", credential.user, credential.password];
+        [ma addObject:s];
+    }
+    
+    // -d "k1=v1&k2=v2"                                             // POST, url encoded params
+    
+    if(_POSTDictionary) {
+        NSMutableArray *postParameters = [NSMutableArray array];
+        [_POSTDictionary enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
+            NSString *s = [NSString stringWithFormat:@"%@=%@", key, obj];
+            [postParameters addObject:s];
+        }];
+        NSString *ss = [postParameters componentsJoinedByString:@"&"];
+        [ma addObject:[NSString stringWithFormat:@"-d \"%@\"", ss]];
+    }
+    
+    // -F "coolfiles=@fil1.gif;type=image/gif,fil2.txt,fil3.html"   // file upload
+    
+    if(_POSTFileParameter && _POSTFilePath) {
+        
+        NSString *s = [NSString stringWithFormat:@"%@@%@", _POSTFileParameter, _POSTFilePath];
+        
+        if(_POSTFileMimeType) {
+            s = [s stringByAppendingFormat:@";type=%@", _POSTFileMimeType];
+        }
+        
+        [ma addObject:[NSString stringWithFormat:@"-F \"%@\"", s]];
+    }
+    
+    // -b "name=Daniel;age=35"                                      // cookies
+    
+    NSArray *cookies = [self requestCookies];
+    
+    NSMutableArray *cookiesStrings = [NSMutableArray array];
+    for(NSHTTPCookie *cookie in cookies) {
+        NSString *s = [NSString stringWithFormat:@"%@=%@", [cookie name], [cookie value]];
+        [cookiesStrings addObject:s];
+    }
+    
+    if([cookiesStrings count] > 0) {
+        [ma addObject:[NSString stringWithFormat:@"-b \"%@\"", [cookiesStrings componentsJoinedByString:@";"]]];
+    }
+    
+    // -H "X-you-and-me: yes"                                       // extra headers
+    
+    NSMutableDictionary *headers = [[[self requestHeaders] mutableCopy] autorelease];
+    
+    [headers addEntriesFromDictionary:[self.request allHTTPHeaderFields]];
+    
+    NSMutableArray *headersStrings = [NSMutableArray array];
+    [headers enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
+        NSString *s = [NSString stringWithFormat:@"-H \"%@: %@\"", key, obj];
+        [headersStrings addObject:s];
+    }];
+    
+    if([headersStrings count] > 0) {
+        [ma addObject:[headersStrings componentsJoinedByString:@" \\\n"]];
+    }
+    
+    // url
+    
+    [ma addObject:[NSString stringWithFormat:@"\"%@\"", _url]];
+    
+    return [ma componentsJoinedByString:@" \\\n"];
+}
+
 - (void)logRequest:(NSURLRequest *)request {
     
     NSLog(@"--------------------------------------");
@@ -481,14 +557,17 @@
         NSLog(@"\t %@ = %@", _POSTFileParameter, _POSTFilePath);
     } else if (_POSTFileParameter && _POSTFileData) {
         NSLog(@"UPLOAD DATA");
-        NSLog(@"\t %@ = [%lu bytes]", _POSTFileParameter, [_POSTFileData length]);
+        NSLog(@"\t %@ = [%u bytes]", _POSTFileParameter, (unsigned int)[_POSTFileData length]);
     } else if (_POSTData) {
         NSLog(@"UPLOAD DATA");
-        NSLog(@"\t [%lu bytes]", [_POSTData length]);
+        NSLog(@"\t [%u bytes]", (unsigned int)[_POSTData length]);
     }
     
+    NSLog(@"--");
+    NSLog(@"%@", [self curlDescription]);
     NSLog(@"--------------------------------------");
 }
+#endif
 
 #pragma mark Start Request
 




More information about the commits mailing list