Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Posterous Integration #211

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Classes/ShareKit/Core/SHKSharers.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<string>SHKReadItLater</string>
<string>SHKInstapaper</string>
<string>SHKTumblr</string>
<string>SHKPosterous</string>
</array>
</dict>
</plist>
3 changes: 2 additions & 1 deletion Classes/ShareKit/SHKConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
leaving that decision up to the user.
*/


// Posterous - http://apidocs.posterous.com/
#define SHKPosterousAPIKey @""

// Delicious - https://developer.apps.yahoo.com/projects
#define SHKDeliciousConsumerKey @""
Expand Down
17 changes: 17 additions & 0 deletions Classes/ShareKit/Sharers/Services/SHKPosterous.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// SHKPinboard.h
// ShareKit
//
// Created by Arik Devens on 4/8/11.

#import <Foundation/Foundation.h>
#import "SHKSharer.h"

@interface SHKPosterous : SHKSharer {
NSMutableData *photoData;
NSHTTPURLResponse *URLResponse;
}

- (void)finish;

@end
192 changes: 192 additions & 0 deletions Classes/ShareKit/Sharers/Services/SHKPosterous.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
//
// SHKPinboard.m
// ShareKit
//
// Created by Arik Devens on 4/8/11.

#import "SHKPosterous.h"
#include "Base64Transcoder.h"

static NSString * const kPosterousPostURL = @"http://posterous.com/api/2/sites/primary/posts";

@implementation SHKPosterous

#pragma mark -
#pragma mark Memory management
- (void)dealloc {
[photoData release];
[URLResponse release];

[super dealloc];
}

#pragma mark -
#pragma mark Configuration : Service Definition

+ (NSString *)sharerTitle {
return @"Posterous";
}

+ (BOOL)canShareText {
return YES;
}

+ (BOOL)canShareImage {
return YES;
}

+ (BOOL)canShareURL{
return YES;
}

//+ (BOOL)canShareFile
//{
// return YES;
//}

#pragma mark -
#pragma mark Authorization

+ (NSString *)authorizationFormCaption {
return SHKLocalizedString(@"Create an account at %@", @"http://posterous.com");
}

- (void)authorizationFormValidate:(SHKFormController *)form {
if (!quiet) {
[[SHKActivityIndicator currentIndicator] displayActivity:SHKLocalizedString(@"Logging In...")];
}

[form saveForm];
}

- (void)authFinished:(SHKRequest *)aRequest {
[[SHKActivityIndicator currentIndicator] hide];
}


#pragma mark -
#pragma mark Share Form

- (NSArray *)shareFormFieldsForType:(SHKShareType)type {
if (type == SHKShareTypeText) {
return [NSArray arrayWithObjects:[SHKFormFieldSettings label:SHKLocalizedString(@"Title") key:@"title" type:SHKFormFieldTypeText start:item.title], nil];
}

return nil;
}

#pragma mark -
#pragma mark Share API Methods

- (NSString *)httpAuthBasicHeaderWith:(NSString *)user andPass:(NSString *)pass {
NSData *data = [[NSString stringWithFormat:@"%@:%@", user, pass] dataUsingEncoding:NSUTF8StringEncoding];

size_t est_out_len = EstimateBas64DecodedDataSize([data length]);
size_t out_len = est_out_len + 512; // a safety margin of 512 is perhaps too big
char outdata[out_len];
Base64EncodeData([data bytes], [data length], outdata, &out_len);
outdata[out_len] = '\0'; // make it a null terminated string

NSString *value = [NSString stringWithFormat:@"Basic %@", [NSString stringWithCString:outdata encoding:NSUTF8StringEncoding]];

return value;
}

- (BOOL)send {
if ([self validateItem]) {
NSURL *URLWithToken = [NSURL URLWithString:[NSString stringWithFormat:@"%@?api_token=%@", kPosterousPostURL, SHKPosterousAPIKey]];
NSMutableURLRequest *aRequest = [[NSMutableURLRequest alloc] initWithURL:URLWithToken cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:90];

NSString *username = [self getAuthValueForKey:@"username"];
NSString *password = [self getAuthValueForKey:@"password"];
NSString *boundary = @"0xKhTmLbOuNdArY";

NSMutableDictionary *headers = [NSMutableDictionary dictionary];
[headers setObject:[self httpAuthBasicHeaderWith:username andPass:password] forKey:@"Authorization"];
[headers setObject:[NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary] forKey:@"Content-Type"];

[aRequest setAllHTTPHeaderFields:headers];
[aRequest setHTTPMethod:@"POST"];

NSMutableData *body = [NSMutableData data];

[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"api_token\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithString:SHKPosterousAPIKey] dataUsingEncoding:NSUTF8StringEncoding]];

if ([item title]) {
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"post[title]\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[item.title dataUsingEncoding:NSUTF8StringEncoding]];
}

if ([item text]) {
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"post[body]\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[item.text dataUsingEncoding:NSUTF8StringEncoding]];
}
else if ([item URL]) {
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"post[body]\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[item.URL absoluteString] dataUsingEncoding:NSUTF8StringEncoding]];
}

if ([item image]) {
[body appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Disposition: form-data; name=\"media[0]\"; filename=\"upload.jpg\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Transfer-Encoding: image/jpg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:UIImageJPEGRepresentation([item image], 0.9)];
}

[body appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];

[aRequest setHTTPBody:body];

[NSURLConnection connectionWithRequest:aRequest delegate:self];
[aRequest release];

[self sendDidStart];

return YES;
}

return NO;
}

#pragma mark -
#pragma mark NSURLConnection delegate methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)theResponse {
[URLResponse release];
URLResponse = nil;
URLResponse = [theResponse retain];

[photoData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)d {
[photoData appendData:d];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self finish];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self finish];
}

- (void)finish {
if (URLResponse.statusCode == 200 || URLResponse.statusCode == 201) {
[self sendDidFinish];
} else {
if (URLResponse.statusCode == 403 || URLResponse.statusCode == 401) {
[self sendDidFailWithError:[SHK error:SHKLocalizedString(@"Invalid username or password.")] shouldRelogin:YES];
} else if (URLResponse.statusCode == 500) {
[self sendDidFailWithError:[SHK error:SHKLocalizedString(@"The service encountered an error. Please try again later.")]];
} else {
[self sendDidFailWithError:[SHK error:SHKLocalizedString(@"There was an error sending your post to Posterous.")]];
}
}
}

@end
19 changes: 17 additions & 2 deletions ShareKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
07FE2747135FA99000E05A8E /* SHKPosterous.m in Sources */ = {isa = PBXBuildFile; fileRef = 07FE2746135FA99000E05A8E /* SHKPosterous.m */; };
1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; };
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
Expand All @@ -30,7 +31,6 @@
4379F2BE1291AC9700D2A41E /* TMemoryBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2AA1291AC9700D2A41E /* TMemoryBuffer.m */; };
4379F2BF1291AC9700D2A41E /* TTransportException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2AD1291AC9700D2A41E /* TTransportException.m */; };
4379F2C01291AC9700D2A41E /* TSharedProcessorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2AF1291AC9700D2A41E /* TSharedProcessorFactory.m */; };
4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2B11291AC9700D2A41E /* SHKEvernote.m */; };
4379F2C21291AC9700D2A41E /* SHKEvernote.md in Resources */ = {isa = PBXBuildFile; fileRef = 4379F2B21291AC9700D2A41E /* SHKEvernote.md */; };
4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2E91291AE5700D2A41E /* NSData+md5.m */; };
4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F3B11291C45700D2A41E /* SHKTextMessage.m */; };
Expand Down Expand Up @@ -109,6 +109,8 @@
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
07FE2745135FA99000E05A8E /* SHKPosterous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKPosterous.h; sourceTree = "<group>"; };
07FE2746135FA99000E05A8E /* SHKPosterous.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKPosterous.m; sourceTree = "<group>"; };
1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
1D6058910D05DD3D006BFB54 /* ShareKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShareKit.app; sourceTree = BUILT_PRODUCTS_DIR; };
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -330,6 +332,15 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
07FE2744135FA98000E05A8E /* Posterous */ = {
isa = PBXGroup;
children = (
07FE2745135FA99000E05A8E /* SHKPosterous.h */,
07FE2746135FA99000E05A8E /* SHKPosterous.m */,
);
name = Posterous;
sourceTree = "<group>";
};
080E96DDFE201D6D7F000001 /* Classes */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -726,6 +737,7 @@
43A536DE11DBE3B9004A1712 /* Google Reader */,
43150A8A11E78697008C6B68 /* Instapaper */,
43A536E111DBE3B9004A1712 /* Pinboard */,
07FE2744135FA98000E05A8E /* Posterous */,
43A536E411DBE3B9004A1712 /* Read It Later */,
43C91DF211EBAE4800F31FAE /* Tumblr */,
43A536E711DBE3B9004A1712 /* Twitter */,
Expand Down Expand Up @@ -916,6 +928,9 @@
/* Begin PBXProject section */
29B97313FDCFA39411CA2CEA /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
};
buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ShareKit" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
Expand Down Expand Up @@ -1049,9 +1064,9 @@
4379F2BE1291AC9700D2A41E /* TMemoryBuffer.m in Sources */,
4379F2BF1291AC9700D2A41E /* TTransportException.m in Sources */,
4379F2C01291AC9700D2A41E /* TSharedProcessorFactory.m in Sources */,
4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */,
4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */,
4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */,
07FE2747135FA99000E05A8E /* SHKPosterous.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down