From 8ccab3679d34a90ea6e309a61984030c95719564 Mon Sep 17 00:00:00 2001 From: Arrix Date: Tue, 25 Jan 2011 10:29:26 +0800 Subject: [PATCH] Added web service Diigo --- Classes/ShareKit/Core/SHKSharers.plist | 1 + Classes/ShareKit/SHKConfig.h | 3 + Classes/ShareKit/Sharers/Services/SHKDiigo.h | 16 + Classes/ShareKit/Sharers/Services/SHKDiigo.m | 341 +++++++++++++++++++ ShareKit.xcodeproj/project.pbxproj | 14 + 5 files changed, 375 insertions(+) create mode 100644 Classes/ShareKit/Sharers/Services/SHKDiigo.h create mode 100644 Classes/ShareKit/Sharers/Services/SHKDiigo.m diff --git a/Classes/ShareKit/Core/SHKSharers.plist b/Classes/ShareKit/Core/SHKSharers.plist index db686302..1a8650a8 100644 --- a/Classes/ShareKit/Core/SHKSharers.plist +++ b/Classes/ShareKit/Core/SHKSharers.plist @@ -21,6 +21,7 @@ SHKReadItLater SHKInstapaper SHKTumblr + SHKDiigo diff --git a/Classes/ShareKit/SHKConfig.h b/Classes/ShareKit/SHKConfig.h index c2aa3565..71fce349 100644 --- a/Classes/ShareKit/SHKConfig.h +++ b/Classes/ShareKit/SHKConfig.h @@ -42,6 +42,9 @@ #define SHKDeliciousConsumerKey @"" #define SHKDeliciousSecretKey @"" +// Diigo - http://www.diigo.com/api_dev +#define SHKDiigoKey @"" + // Facebook - http://www.facebook.com/developers // If SHKFacebookUseSessionProxy is enabled then SHKFacebookSecret is ignored and should be left blank diff --git a/Classes/ShareKit/Sharers/Services/SHKDiigo.h b/Classes/ShareKit/Sharers/Services/SHKDiigo.h new file mode 100644 index 00000000..81eb30a4 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/SHKDiigo.h @@ -0,0 +1,16 @@ +// +// SHKDiigo.h +// ShareKit +// +// Created by Arrix Zhou on 1/21/11. +// Copyright 2011 Diigo. All rights reserved. +// + +#import +#import "SHKSharer.h" + +@interface SHKDiigo : SHKSharer { + +} + +@end diff --git a/Classes/ShareKit/Sharers/Services/SHKDiigo.m b/Classes/ShareKit/Sharers/Services/SHKDiigo.m new file mode 100644 index 00000000..d2372251 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/SHKDiigo.m @@ -0,0 +1,341 @@ +// +// SHKDiigo.m +// ShareKit +// +// Created by Arrix Zhou on 1/21/11. +// Copyright 2011 Diigo. All rights reserved. +// + +#import "SHKDiigo.h" +#include "Base64Transcoder.h" + +@implementation SHKDiigo + +static NSString * const kDiigoAPIUrl = @"https://secure.diigo.com/api/v2/"; + +#pragma mark - +#pragma mark Configuration : Service Defination + ++ (NSString *)sharerTitle +{ + return @"Diigo"; +} + ++ (BOOL)canShareURL { + return YES; +} + +#pragma mark - +#pragma mark Configuration : Dynamic Enable + ++ (BOOL)canShare +{ + return YES; +} + + + +#pragma mark - +#pragma mark Authentication + +// Return the form fields required to authenticate the user with the service ++ (NSArray *)authorizationFormFields +{ + return [NSArray arrayWithObjects: + [SHKFormFieldSettings label:@"Username" key:@"username" type:SHKFormFieldTypeText start:nil], + [SHKFormFieldSettings label:@"Password" key:@"password" type:SHKFormFieldTypePassword start:nil], + nil]; +} + +// Return the footer title to display under the login form ++ (NSString *)authorizationFormCaption +{ + // This should tell the user how to get an account. Be concise! The standard format is: + return SHKLocalizedString(@"Create a free account at %@", @"diigo.com"); // This function works like (NSString *)stringWithFormat:(NSString*)format, ... | but translates the 'create a free account' part into any supported languages automatically +} + +// Authenticate the user using the data they've entered into the form +- (void)authorizationFormValidate:(SHKFormController *)form +{ + /* + This is called when the user taps 'Login' on the login form after entering their information. + + Supply the necessary logic to validate the user input and authenticate the user. + + You can get a dictionary of the field values from [form formValues] + + -- + + A common implementation looks like: + + 1. Validate the form data. + - Make sure necessary fields were completed. + - If there is a problem, display an error with UIAlertView + + 2. Authenticate the user with the web service. + - Display the activity indicator + - Send a request to the server + - If the request fails, display an error + - If the request is successful, save the form + */ + + + + // Here is an example. + // This example assumes the form created by authorizationFormFields had a username and password field. + + // Get the form data + NSDictionary *formValues = [form formValues]; + + // 1. Validate the form data + if ([formValues objectForKey:@"username"] == nil || [formValues objectForKey:@"password"] == nil) + { + // display an error + [[[[UIAlertView alloc] initWithTitle:@"Login Error" + message:@"You must enter a username and password" + delegate:nil + cancelButtonTitle:@"Close" + otherButtonTitles:nil] autorelease] show]; + + } + + // 2. Authenticate the user with the web service + else + { + // Show the activity spinner + [[SHKActivityIndicator currentIndicator] displayActivity:@"Logging In..."]; + + // Retain the form so we can access it after the request finishes + self.pendingForm = form; + + // -- Send a request to the server + // See http://getsharekit.com/docs/#requests for documentation on using the SHKRequest and SHKEncode helpers + + // Set the parameters for the request + NSString *params = [NSMutableString stringWithFormat:@"username=%@&password=%@", + SHKEncode([formValues objectForKey:@"username"]), + SHKEncode([formValues objectForKey:@"password"]) + ]; + + // Send request + self.request = [[[SHKRequest alloc] initWithURL:[NSURL URLWithString:[kDiigoAPIUrl stringByAppendingFormat:@"check_sign_in"]] + params:params + delegate:self + isFinishedSelector:@selector(authFinished:) + method:@"POST" + autostart:YES] autorelease]; + } + +} + +// This is a continuation of the example provided in authorizationFormValidate above. It handles the SHKRequest response +// This is not a required method and is only provided as an example + + - (void)authFinished:(SHKRequest *)aRequest + { + // Hide the activity indicator + [[SHKActivityIndicator currentIndicator] hide]; + + // If the result is successful, save the form to continue sharing + if (aRequest.success) + [pendingForm saveForm]; + + // If there is an error, display it to the user + else + { + // See http://getsharekit.com/docs/#requests for documentation on SHKRequest + // SHKRequest contains three properties that may assist you in responding to errors: + // aRequest.response is the NSHTTPURLResponse of the request + // aRequest.response.statusCode is the HTTTP status code of the response + // [aRequest getResult] returns a NSString of the body of the response + // aRequest.headers is a NSDictionary of all response headers + + [[[[UIAlertView alloc] initWithTitle:@"Login Error" + message:@"Your username and password did not match" + delegate:nil + cancelButtonTitle:@"Close" + otherButtonTitles:nil] autorelease] show]; + } + } + + + +#pragma mark - +#pragma mark Share Form + +- (NSArray *)shareFormFieldsForType:(SHKShareType)type +{ + if (type == SHKShareTypeURL) + { + return [NSArray arrayWithObjects: + [SHKFormFieldSettings label:@"Title" key:@"title" type:SHKFormFieldTypeText start:item.title], + [SHKFormFieldSettings label:@"Tags" key:@"tags" type:SHKFormFieldTypeText start:item.tags], + [SHKFormFieldSettings label:@"Description" key:@"text" type:SHKFormFieldTypeText start:item.text], + [SHKFormFieldSettings label:@"Read later" key:@"unread" type:SHKFormFieldTypeSwitch start:SHKFormFieldSwitchOff], + [SHKFormFieldSettings label:@"Private" key:@"private" type:SHKFormFieldTypeSwitch start:SHKFormFieldSwitchOff], + nil]; + } + return nil; +} + +// Validate the user input on the share form +- (void)shareFormValidate:(SHKCustomFormController *)form +{ + /* + + Services should subclass this if they need to validate any data before sending. + You can get a dictionary of the field values from [form formValues] + + -- + + You should perform one of the following actions: + + 1. Save the form - If everything is correct call [form saveForm] + + 2. Display an error - If the user input was incorrect, display an error to the user and tell them what to do to fix it + + + */ + + // default does no checking and proceeds to share + [form saveForm]; +} + + + +#pragma mark - +#pragma mark Implementation + +// When an attempt is made to share the item, verify that it has everything it needs, otherwise display the share form +/* + - (BOOL)validateItem + { + // The super class will verify that: + // -if sharing a url : item.url != nil + // -if sharing an image : item.image != nil + // -if sharing text : item.text != nil + // -if sharing a file : item.data != nil + + // You only need to implement this if you need to check additional variables. + + // If you return NO, you should probably pop up a UIAlertView to notify the user they missed something. + + return [super validateItem]; + } + */ + +- (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; +} + +// Send the share item to the server +- (BOOL)send +{ + // Make sure that the item has minimum requirements + if (![self validateItem]) + return NO; + + /* + Enter the necessary logic to share the item here. + + The shared item and relevant data is in self.item + // See http://getsharekit.com/docs/#sending + + -- + + A common implementation looks like: + + - Send a request to the server + - call [self sendDidStart] after you start your action + - after the action completes, fails or is cancelled, call one of these on 'self': + - (void)sendDidFinish (if successful) + - (void)sendDidFailShouldRelogin (if failed because the user's current credentials are out of date) + - (void)sendDidFailWithError:(NSError *)error shouldRelogin:(BOOL)shouldRelogin + - (void)sendDidCancel + */ + + + // Here is an example. + // This example is for a service that can share a URL + + + // Determine which type of share to do + if (item.shareType == SHKShareTypeURL) // sharing a URL + { + // Set the parameters for the request + NSString *params = [NSMutableString stringWithFormat:@"key=%@&url=%@&title=%@&shared=%@&readLater=%@&tags=%@%&desc=%@", + SHKDiigoKey, + SHKEncodeURL(item.URL), + SHKEncode(item.title), + ![item customBoolForSwitchKey:@"private"] ? @"yes" : @"no", + [item customBoolForSwitchKey:@"unread"] ? @"yes" : @"no", + SHKEncode(item.tags), + SHKEncode(item.text) + ]; + + // Send request + self.request = [[[SHKRequest alloc] initWithURL:[NSURL URLWithString:[kDiigoAPIUrl stringByAppendingFormat:@"bookmarks"]] + params:params + delegate:self + isFinishedSelector:@selector(sendFinished:) + method:@"POST" + autostart:NO] autorelease]; + + // Attach the HTTP Basic Auth header + NSString *username = [self getAuthValueForKey:@"username"]; + NSString *password = [self getAuthValueForKey:@"password"]; + NSMutableDictionary *headers = [NSMutableDictionary dictionaryWithDictionary: self.request.headerFields]; + [headers setObject:[self httpAuthBasicHeaderWith:username andPass:password] forKey:@"Authorization"]; + self.request.headerFields = headers; + + [self.request start]; + + // Notify self and it's delegates that we started + [self sendDidStart]; + + return YES; // we started the request + } + + return NO; +} + + +// This is a continuation of the example provided in authorizationFormValidate above. It handles the SHKRequest response +// This is not a required method and is only provided as an example + +- (void)sendFinished:(SHKRequest *)aRequest +{ + if (!aRequest.success) + { + // See http://getsharekit.com/docs/#requests for documentation on SHKRequest + // SHKRequest contains three properties that may assist you in responding to errors: + // aRequest.response is the NSHTTPURLResponse of the request + // aRequest.response.statusCode is the HTTTP status code of the response + // [aRequest getResult] returns a NSString of the body of the response + // aRequest.headers is a NSDictionary of all response headers + + if (aRequest.response.statusCode == 401) + { + [self sendDidFailShouldRelogin]; + return; + } + + // If there was an error that was not login related, send error along to the delegate + [self sendDidFailWithError:[SHK error:@"There was a problem sharing"] shouldRelogin:NO]; + return; + } + + [self sendDidFinish]; +} + + +@end diff --git a/ShareKit.xcodeproj/project.pbxproj b/ShareKit.xcodeproj/project.pbxproj index adcbf90e..c767c070 100755 --- a/ShareKit.xcodeproj/project.pbxproj +++ b/ShareKit.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 00A7D89012E974D50033F86E /* SHKDiigo.m in Sources */ = {isa = PBXBuildFile; fileRef = 00A7D88F12E974D50033F86E /* SHKDiigo.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 */; }; @@ -109,6 +110,8 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 00A7D88E12E974D50033F86E /* SHKDiigo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKDiigo.h; sourceTree = ""; }; + 00A7D88F12E974D50033F86E /* SHKDiigo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKDiigo.m; sourceTree = ""; }; 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; }; @@ -330,6 +333,15 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 00A7D88712E9749D0033F86E /* Diigo */ = { + isa = PBXGroup; + children = ( + 00A7D88E12E974D50033F86E /* SHKDiigo.h */, + 00A7D88F12E974D50033F86E /* SHKDiigo.m */, + ); + name = Diigo; + sourceTree = ""; + }; 080E96DDFE201D6D7F000001 /* Classes */ = { isa = PBXGroup; children = ( @@ -721,6 +733,7 @@ isa = PBXGroup; children = ( 43A536C111DBE3B9004A1712 /* Delicious */, + 00A7D88712E9749D0033F86E /* Diigo */, 4379F2891291AC9700D2A41E /* Evernote */, 43A536C411DBE3B9004A1712 /* Facebook */, 43A536DE11DBE3B9004A1712 /* Google Reader */, @@ -1052,6 +1065,7 @@ 4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */, 4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */, 4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */, + 00A7D89012E974D50033F86E /* SHKDiigo.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };