From a983d715aa4ee2f9c01cc656a141206fd5079304 Mon Sep 17 00:00:00 2001 From: Colin Humber Date: Thu, 27 Jan 2011 15:29:34 -0700 Subject: [PATCH 1/2] Added support for Facebook's new SDK with Open Graph support Updated config file with new Facebook settings Added additional dictionary elements to SHKItem dictionaryRepresentation Updated example app to work with the new Facebook SDK --- .../FBDialog.bundle/images/close.png | Bin 0 -> 164 bytes .../FBDialog.bundle/images/fbicon.png | Bin 0 -> 226 bytes .../Services/Facebook/FBConnect/Facebook.h | 109 ++++ .../Services/Facebook/FBConnect/Facebook.m | 586 ++++++++++++++++++ .../Services/Facebook/FBConnect/JSON/JSON.h | 50 ++ .../Facebook/FBConnect/JSON/NSObject+SBJSON.h | 68 ++ .../Facebook/FBConnect/JSON/NSObject+SBJSON.m | 53 ++ .../Facebook/FBConnect/JSON/NSString+SBJSON.h | 58 ++ .../Facebook/FBConnect/JSON/NSString+SBJSON.m | 55 ++ .../Services/Facebook/FBConnect/JSON/SBJSON.h | 75 +++ .../Services/Facebook/FBConnect/JSON/SBJSON.m | 212 +++++++ .../Facebook/FBConnect/JSON/SBJsonBase.h | 86 +++ .../Facebook/FBConnect/JSON/SBJsonBase.m | 78 +++ .../Facebook/FBConnect/JSON/SBJsonParser.h | 87 +++ .../Facebook/FBConnect/JSON/SBJsonParser.m | 475 ++++++++++++++ .../Facebook/FBConnect/JSON/SBJsonWriter.h | 129 ++++ .../Facebook/FBConnect/JSON/SBJsonWriter.m | 237 +++++++ 17 files changed, 2358 insertions(+) create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.bundle/images/close.png create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.bundle/images/fbicon.png create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.m create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/JSON.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.m create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.m create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.m create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.m create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.m create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.h create mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.m diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.bundle/images/close.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.bundle/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..a89b82faba7910c645fd1ae8cc285c3e86a0763d GIT binary patch literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PI@$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GZk{fVAr-fhV)i{gR?nu;Q4pS<($FMoo!@kH#s$^{6Apua z|NqOoGO#(Q87`FWJd>VufO*D+w~mDZn^<;r&%B^IL6m_-f}!-QYBk%O&IF)|44$rj JF6*2UngF8LG#3B> literal 0 HcmV?d00001 diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.bundle/images/fbicon.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.bundle/images/fbicon.png new file mode 100644 index 0000000000000000000000000000000000000000..413396be6b5baaaf363d4aa1111e4935c234a1b9 GIT binary patch literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1SBVD?P>#3k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XT0C7GLn>}1`K*a4etl4y&B?*nv87X@)PW)7Sd+J3Xxxt7 zXM$ZONT1l&Ig3+eW`Snw>SpFS%amrbGy3qjFzYOni=5VXtZhcG>&w~S;~(-hY$%*1 zHDNDHo?MIXrfAQPV&dwv+a^iqWh&=Nay&k^H+;zqE#-6N?_LS}a6UQEt|H#Rz|0U9 Wr}l!o#w8Z$9tKZWKbLh*2~7ZwZcbkS literal 0 HcmV?d00001 diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.h new file mode 100644 index 00000000..81ca56b8 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.h @@ -0,0 +1,109 @@ +/* + * Copyright 2010 Facebook + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "FBLoginDialog.h" +#import "FBRequest.h" + +@protocol FBSessionDelegate; + +/** + * Main Facebook interface for interacting with the Facebook developer API. + * Provides methods to log in and log out a user, make requests using the REST + * and Graph APIs, and start user interface interactions (such as + * pop-ups promoting for credentials, permissions, stream posts, etc.) + */ +@interface Facebook : NSObject{ + NSString* _accessToken; + NSDate* _expirationDate; + id _sessionDelegate; + FBRequest* _request; + FBDialog* _loginDialog; + FBDialog* _fbDialog; + NSString* _appId; + NSArray* _permissions; +} + +@property(nonatomic, copy) NSString* accessToken; + +@property(nonatomic, copy) NSDate* expirationDate; + +@property(nonatomic, assign) id sessionDelegate; + +- (id)initWithAppId:(NSString *)app_id; + +- (void)authorize:(NSArray *)permissions + delegate:(id)delegate; + +- (BOOL)handleOpenURL:(NSURL *)url; + +- (void)logout:(id)delegate; + +- (void)requestWithParams:(NSMutableDictionary *)params + andDelegate:(id )delegate; + +- (void)requestWithMethodName:(NSString *)methodName + andParams:(NSMutableDictionary *)params + andHttpMethod:(NSString *)httpMethod + andDelegate:(id )delegate; + +- (void)requestWithGraphPath:(NSString *)graphPath + andDelegate:(id )delegate; + +- (void)requestWithGraphPath:(NSString *)graphPath + andParams:(NSMutableDictionary *)params + andDelegate:(id )delegate; + +- (void)requestWithGraphPath:(NSString *)graphPath + andParams:(NSMutableDictionary *)params + andHttpMethod:(NSString *)httpMethod + andDelegate:(id )delegate; + +- (void)dialog:(NSString *)action + andDelegate:(id)delegate; + +- (void)dialog:(NSString *)action + andParams:(NSMutableDictionary *)params + andDelegate:(id )delegate; + +- (BOOL)isSessionValid; + +@end + +//////////////////////////////////////////////////////////////////////////////// + +/** + * Your application should implement this delegate to receive session callbacks. + */ +@protocol FBSessionDelegate + +@optional + +/** + * Called when the user successfully logged in. + */ +- (void)fbDidLogin; + +/** + * Called when the user dismissed the dialog without logging in. + */ +- (void)fbDidNotLogin:(BOOL)cancelled; + +/** + * Called when the user logged out. + */ +- (void)fbDidLogout; + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.m new file mode 100644 index 00000000..aad3117b --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/Facebook.m @@ -0,0 +1,586 @@ +/* + * Copyright 2010 Facebook + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#import "Facebook.h" +#import "FBLoginDialog.h" +#import "FBRequest.h" + +static NSString* kDialogBaseURL = @"https://m.facebook.com/dialog/"; +static NSString* kGraphBaseURL = @"https://graph.facebook.com/"; +static NSString* kRestserverBaseURL = @"https://api.facebook.com/method/"; + +static NSString* kFBAppAuthURL = @"fbauth://authorize"; +static NSString* kRedirectURL = @"fbconnect://success"; + +static NSString* kLogin = @"oauth"; +static NSString* kSDK = @"ios"; +static NSString* kSDKVersion = @"2"; + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +@implementation Facebook + +@synthesize accessToken = _accessToken, + expirationDate = _expirationDate, + sessionDelegate = _sessionDelegate; + +/////////////////////////////////////////////////////////////////////////////////////////////////// +// private + + +/** + * Initialize the Facebook object with application ID. + */ +- (id)initWithAppId:(NSString *)app_id { + self = [super init]; + if (self) { + [_appId release]; + _appId = [app_id copy]; + } + return self; +} + +/** + * Override NSObject : free the space + */ +- (void)dealloc { + [_accessToken release]; + [_expirationDate release]; + [_request release]; + [_loginDialog release]; + [_fbDialog release]; + [_appId release]; + [_permissions release]; + [super dealloc]; +} + +/** + * A private helper function for sending HTTP requests. + * + * @param url + * url to send http request + * @param params + * parameters to append to the url + * @param httpMethod + * http method @"GET" or @"POST" + * @param delegate + * Callback interface for notifying the calling application when + * the request has received response + */ +- (void)openUrl:(NSString *)url + params:(NSMutableDictionary *)params + httpMethod:(NSString *)httpMethod + delegate:(id)delegate { + [params setValue:@"json" forKey:@"format"]; + [params setValue:kSDK forKey:@"sdk"]; + [params setValue:kSDKVersion forKey:@"sdk_version"]; + if ([self isSessionValid]) { + [params setValue:self.accessToken forKey:@"access_token"]; + } + + [_request release]; + _request = [[FBRequest getRequestWithParams:params + httpMethod:httpMethod + delegate:delegate + requestURL:url] retain]; + [_request connect]; +} + +/** + * A private function for opening the authorization dialog. + */ +- (void)authorizeWithFBAppAuth:(BOOL)tryFBAppAuth + safariAuth:(BOOL)trySafariAuth { + NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: + _appId, @"client_id", + @"user_agent", @"type", + kRedirectURL, @"redirect_uri", + @"touch", @"display", + kSDKVersion, @"sdk", + nil]; + + NSString *loginDialogURL = [kDialogBaseURL stringByAppendingString:kLogin]; + + if (_permissions != nil) { + NSString* scope = [_permissions componentsJoinedByString:@","]; + [params setValue:scope forKey:@"scope"]; + } + + // If the device is running a version of iOS that supports multitasking, + // try to obtain the access token from the Facebook app installed + // on the device. + // If the Facebook app isn't installed or it doesn't support + // the fbauth:// URL scheme, fall back on Safari for obtaining the access token. + // This minimizes the chance that the user will have to enter his or + // her credentials in order to authorize the application. + BOOL didOpenOtherApp = NO; + UIDevice *device = [UIDevice currentDevice]; + if ([device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported]) { + if (tryFBAppAuth) { + NSString *fbAppUrl = [FBRequest serializeURL:kFBAppAuthURL params:params]; + didOpenOtherApp = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:fbAppUrl]]; + } + + if (trySafariAuth && !didOpenOtherApp) { + NSString *nextUrl = [NSString stringWithFormat:@"fb%@://authorize", _appId]; + [params setValue:nextUrl forKey:@"redirect_uri"]; + + NSString *fbAppUrl = [FBRequest serializeURL:loginDialogURL params:params]; + didOpenOtherApp = [[UIApplication sharedApplication] openURL:[NSURL URLWithString:fbAppUrl]]; + } + } + + // If single sign-on failed, open an inline login dialog. This will require the user to + // enter his or her credentials. + if (!didOpenOtherApp) { + [_loginDialog release]; + _loginDialog = [[FBLoginDialog alloc] initWithURL:loginDialogURL + loginParams:params + delegate:self]; + [_loginDialog show]; + } +} + +/** + * A private function for parsing URL parameters. + */ +- (NSDictionary*)parseURLParams:(NSString *)query { + NSArray *pairs = [query componentsSeparatedByString:@"&"]; + NSMutableDictionary *params = [[[NSMutableDictionary alloc] init] autorelease]; + for (NSString *pair in pairs) { + NSArray *kv = [pair componentsSeparatedByString:@"="]; + NSString *val = + [[kv objectAtIndex:1] + stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + + [params setObject:val forKey:[kv objectAtIndex:0]]; + } + return params; +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// +//public + + + +/** + * Starts a dialog which prompts the user to log in to Facebook and grant + * the requested permissions to the application. + * + * If the device supports multitasking, we use fast app switching to show + * the dialog in the Facebook app or, if the Facebook app isn't installed, + * in Safari (this enables single sign-on by allowing multiple apps on + * the device to share the same user session). + * When the user grants or denies the permissions, the app that + * showed the dialog (the Facebook app or Safari) redirects back to + * the calling application, passing in the URL the access token + * and/or any other parameters the Facebook backend includes in + * the result (such as an error code if an error occurs). + * + * See http://developers.facebook.com/docs/authentication/ for more details. + * + * Also note that requests may be made to the API without calling + * authorize() first, in which case only public information is returned. + * + * @param application_id + * The Facebook application id, e.g. "350685531728". + * @param permissions + * A list of permission required for this application: e.g. + * "read_stream", "publish_stream", or "offline_access". see + * http://developers.facebook.com/docs/authentication/permissions + * This parameter should not be null -- if you do not require any + * permissions, then pass in an empty String array. + * @param delegate + * Callback interface for notifying the calling application when + * the user has logged in. + */ +- (void)authorize:(NSArray *)permissions + delegate:(id)delegate { + + [_permissions release]; + _permissions = [permissions retain]; + + _sessionDelegate = delegate; + + [self authorizeWithFBAppAuth:YES safariAuth:YES]; +} + +/** + * This function processes the URL the Facebook application or Safari used to + * open your application during a single sign-on flow. + * + * You MUST call this function in your UIApplicationDelegate's handleOpenURL + * method (see + * http://developer.apple.com/library/ios/#documentation/uikit/reference/UIApplicationDelegate_Protocol/Reference/Reference.html + * for more info). + * + * This will ensure that the authorization process will proceed smoothly once the + * Facebook application or Safari redirects back to your application. + * + * @param URL the URL that was passed to the application delegate's handleOpenURL method. + * + * @return YES if the URL starts with 'fb[app_id]://authorize and hence was handled + * by SDK, NO otherwise. + */ +- (BOOL)handleOpenURL:(NSURL *)url { + // If the URL's structure doesn't match the structure used for Facebook authorization, abort. + if (![[url absoluteString] hasPrefix:[NSString stringWithFormat:@"fb%@://authorize", _appId]]) { + return NO; + } + + NSString *query = [url fragment]; + + // Version 3.2.3 of the Facebook app encodes the parameters in the query but + // version 3.3 and above encode the parameters in the fragment. To support + // both versions of the Facebook app, we try to parse the query if + // the fragment is missing. + if (!query) { + query = [url query]; + } + + NSDictionary *params = [self parseURLParams:query]; + NSString *accessToken = [params valueForKey:@"access_token"]; + + // If the URL doesn't contain the access token, an error has occurred. + if (!accessToken) { + NSString *errorReason = [params valueForKey:@"error"]; + + // If the error response indicates that we should try again using Safari, open + // the authorization dialog in Safari. + if (errorReason && [errorReason isEqualToString:@"service_disabled_use_browser"]) { + [self authorizeWithFBAppAuth:NO safariAuth:YES]; + return YES; + } + + // If the error response indicates that we should try the authorization flow + // in an inline dialog, do that. + if (errorReason && [errorReason isEqualToString:@"service_disabled"]) { + [self authorizeWithFBAppAuth:NO safariAuth:NO]; + return YES; + } + + // The facebook app may return an error_code parameter in case it + // encounters a UIWebViewDelegate error. This should not be treated + // as a cancel. + NSString *errorCode = [params valueForKey:@"error_code"]; + + BOOL userDidCancel = + !errorCode && (!errorReason || [errorReason isEqualToString:@"access_denied"]); + [self fbDialogNotLogin:userDidCancel]; + return YES; + } + + // We have an access token, so parse the expiration date. + NSString *expTime = [params valueForKey:@"expires_in"]; + NSDate *expirationDate = [NSDate distantFuture]; + if (expTime != nil) { + int expVal = [expTime intValue]; + if (expVal != 0) { + expirationDate = [NSDate dateWithTimeIntervalSinceNow:expVal]; + } + } + + [self fbDialogLogin:accessToken expirationDate:expirationDate]; + return YES; +} + +/** + * Invalidate the current user session by removing the access token in + * memory, clearing the browser cookie, and calling auth.expireSession + * through the API. + * + * Note that this method dosen't unauthorize the application -- + * it just invalidates the access token. To unauthorize the application, + * the user must remove the app in the app settings page under the privacy + * settings screen on facebook.com. + * + * @param delegate + * Callback interface for notifying the calling application when + * the application has logged out + */ +- (void)logout:(id)delegate { + + _sessionDelegate = delegate; + + NSMutableDictionary * params = [[NSMutableDictionary alloc] init]; + [self requestWithMethodName:@"auth.expireSession" + andParams:params andHttpMethod:@"GET" + andDelegate:nil]; + + [params release]; + [_accessToken release]; + _accessToken = nil; + [_expirationDate release]; + _expirationDate = nil; + + NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage]; + NSArray* facebookCookies = [cookies cookiesForURL: + [NSURL URLWithString:@"http://login.facebook.com"]]; + + for (NSHTTPCookie* cookie in facebookCookies) { + [cookies deleteCookie:cookie]; + } + + if ([self.sessionDelegate respondsToSelector:@selector(fbDidLogout)]) { + [_sessionDelegate fbDidLogout]; + } +} + +/** + * Make a request to Facebook's REST API with the given + * parameters. One of the parameter keys must be "method" and its value + * should be a valid REST server API method. + * + * See http://developers.facebook.com/docs/reference/rest/ + * + * @param parameters + * Key-value pairs of parameters to the request. Refer to the + * documentation: one of the parameters must be "method". + * @param delegate + * Callback interface for notifying the calling application when + * the request has received response + */ +- (void)requestWithParams:(NSMutableDictionary *)params + andDelegate:(id )delegate { + if ([params objectForKey:@"method"] == nil) { + NSLog(@"API Method must be specified"); + return; + } + + NSString * methodName = [params objectForKey:@"method"]; + [params removeObjectForKey:@"method"]; + + [self requestWithMethodName:methodName + andParams:params + andHttpMethod:@"GET" + andDelegate:delegate]; +} + +/** + * Make a request to Facebook's REST API with the given method name and + * parameters. + * + * See http://developers.facebook.com/docs/reference/rest/ + * + * + * @param methodName + * a valid REST server API method. + * @param parameters + * Key-value pairs of parameters to the request. Refer to the + * documentation: one of the parameters must be "method". To upload + * a file, you should specify the httpMethod to be "POST" and the + * “params” you passed in should contain a value of the type + * (UIImage *) or (NSData *) which contains the content that you + * want to upload + * @param delegate + * Callback interface for notifying the calling application when + * the request has received response + */ +- (void)requestWithMethodName:(NSString *)methodName + andParams:(NSMutableDictionary *)params + andHttpMethod:(NSString *)httpMethod + andDelegate:(id )delegate { + NSString * fullURL = [kRestserverBaseURL stringByAppendingString:methodName]; + [self openUrl:fullURL params:params httpMethod:httpMethod delegate:delegate]; +} + +/** + * Make a request to the Facebook Graph API without any parameters. + * + * See http://developers.facebook.com/docs/api + * + * @param graphPath + * Path to resource in the Facebook graph, e.g., to fetch data + * about the currently logged authenticated user, provide "me", + * which will fetch http://graph.facebook.com/me + * @param delegate + * Callback interface for notifying the calling application when + * the request has received response + */ +- (void)requestWithGraphPath:(NSString *)graphPath + andDelegate:(id )delegate { + + [self requestWithGraphPath:graphPath + andParams:[NSMutableDictionary dictionary] + andHttpMethod:@"GET" + andDelegate:delegate]; +} + +/** + * Make a request to the Facebook Graph API with the given string + * parameters using an HTTP GET (default method). + * + * See http://developers.facebook.com/docs/api + * + * + * @param graphPath + * Path to resource in the Facebook graph, e.g., to fetch data + * about the currently logged authenticated user, provide "me", + * which will fetch http://graph.facebook.com/me + * @param parameters + * key-value string parameters, e.g. the path "search" with + * parameters "q" : "facebook" would produce a query for the + * following graph resource: + * https://graph.facebook.com/search?q=facebook + * @param delegate + * Callback interface for notifying the calling application when + * the request has received response + */ +- (void)requestWithGraphPath:(NSString *)graphPath + andParams:(NSMutableDictionary *)params + andDelegate:(id )delegate { + [self requestWithGraphPath:graphPath + andParams:params + andHttpMethod:@"GET" + andDelegate:delegate]; +} + +/** + * Make a request to the Facebook Graph API with the given + * HTTP method and string parameters. Note that binary data parameters + * (e.g. pictures) are not yet supported by this helper function. + * + * See http://developers.facebook.com/docs/api + * + * + * @param graphPath + * Path to resource in the Facebook graph, e.g., to fetch data + * about the currently logged authenticated user, provide "me", + * which will fetch http://graph.facebook.com/me + * @param parameters + * key-value string parameters, e.g. the path "search" with + * parameters {"q" : "facebook"} would produce a query for the + * following graph resource: + * https://graph.facebook.com/search?q=facebook + * To upload a file, you should specify the httpMethod to be + * "POST" and the “params” you passed in should contain a value + * of the type (UIImage *) or (NSData *) which contains the + * content that you want to upload + * @param httpMethod + * http verb, e.g. "GET", "POST", "DELETE" + * @param delegate + * Callback interface for notifying the calling application when + * the request has received response + */ +- (void)requestWithGraphPath:(NSString *)graphPath + andParams:(NSMutableDictionary *)params + andHttpMethod:(NSString *)httpMethod + andDelegate:(id )delegate { + NSString * fullURL = [kGraphBaseURL stringByAppendingString:graphPath]; + [self openUrl:fullURL params:params httpMethod:httpMethod delegate:delegate]; +} + +/** + * Generate a UI dialog for the request action. + * + * @param action + * String representation of the desired method: e.g. "login", + * "feed", ... + * @param delegate + * Callback interface to notify the calling application when the + * dialog has completed. + */ +- (void)dialog:(NSString *)action + andDelegate:(id)delegate { + NSMutableDictionary * params = [NSMutableDictionary dictionary]; + [self dialog:action andParams:params andDelegate:delegate]; +} + +/** + * Generate a UI dialog for the request action with the provided parameters. + * + * @param action + * String representation of the desired method: e.g. "login", + * "feed", ... + * @param parameters + * key-value string parameters + * @param delegate + * Callback interface to notify the calling application when the + * dialog has completed. + */ +- (void)dialog:(NSString *)action + andParams:(NSMutableDictionary *)params + andDelegate:(id )delegate { + + [_fbDialog release]; + + NSString *dialogURL = [kDialogBaseURL stringByAppendingString:action]; + [params setObject:@"touch" forKey:@"display"]; + [params setObject:kSDKVersion forKey:@"sdk"]; + [params setObject:kRedirectURL forKey:@"redirect_uri"]; + + if (action == kLogin) { + [params setObject:@"user_agent" forKey:@"type"]; + _fbDialog = [[FBLoginDialog alloc] initWithURL:dialogURL loginParams:params delegate:self]; + } else { + [params setObject:_appId forKey:@"app_id"]; + if ([self isSessionValid]) { + [params setValue:[self.accessToken stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] + forKey:@"access_token"]; + } + _fbDialog = [[FBDialog alloc] initWithURL:dialogURL params:params delegate:delegate]; + } + + [_fbDialog show]; +} + +/** + * @return boolean - whether this object has an non-expired session token + */ +- (BOOL)isSessionValid { + return (self.accessToken != nil && self.expirationDate != nil + && NSOrderedDescending == [self.expirationDate compare:[NSDate date]]); + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// +//FBLoginDialogDelegate + +/** + * Set the authToken and expirationDate after login succeed + */ +- (void)fbDialogLogin:(NSString *)token expirationDate:(NSDate *)expirationDate { + self.accessToken = token; + self.expirationDate = expirationDate; + if ([self.sessionDelegate respondsToSelector:@selector(fbDidLogin)]) { + [_sessionDelegate fbDidLogin]; + } + +} + +/** + * Did not login call the not login delegate + */ +- (void)fbDialogNotLogin:(BOOL)cancelled { + if ([self.sessionDelegate respondsToSelector:@selector(fbDidNotLogin:)]) { + [_sessionDelegate fbDidNotLogin:cancelled]; + } +} + + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +//FBRequestDelegate + +/** + * Handle the auth.ExpireSession api call failure + */ +- (void)request:(FBRequest*)request didFailWithError:(NSError*)error{ + NSLog(@"Failed to expire the session"); +} + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/JSON.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/JSON.h new file mode 100644 index 00000000..1e58c9ad --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/JSON.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + @mainpage A strict JSON parser and generator for Objective-C + + JSON (JavaScript Object Notation) is a lightweight data-interchange + format. This framework provides two apis for parsing and generating + JSON. One standard object-based and a higher level api consisting of + categories added to existing Objective-C classes. + + Learn more on the http://code.google.com/p/json-framework project site. + + This framework does its best to be as strict as possible, both in what it + accepts and what it generates. For example, it does not support trailing commas + in arrays or objects. Nor does it support embedded comments, or + anything else not in the JSON specification. This is considered a feature. + +*/ + +#import "SBJSON.h" +#import "NSObject+SBJSON.h" +#import "NSString+SBJSON.h" + diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.h new file mode 100644 index 00000000..ecf0ee40 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.h @@ -0,0 +1,68 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + + +/** + @brief Adds JSON generation to Foundation classes + + This is a category on NSObject that adds methods for returning JSON representations + of standard objects to the objects themselves. This means you can call the + -JSONRepresentation method on an NSArray object and it'll do what you want. + */ +@interface NSObject (NSObject_SBJSON) + +/** + @brief Returns a string containing the receiver encoded as a JSON fragment. + + This method is added as a category on NSObject but is only actually + supported for the following objects: + @li NSDictionary + @li NSArray + @li NSString + @li NSNumber (also used for booleans) + @li NSNull + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (NSString *)JSONFragment; + +/** + @brief Returns a string containing the receiver encoded in JSON. + + This method is added as a category on NSObject but is only actually + supported for the following objects: + @li NSDictionary + @li NSArray + */ +- (NSString *)JSONRepresentation; + +@end + diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.m new file mode 100644 index 00000000..20b084b6 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSObject+SBJSON.m @@ -0,0 +1,53 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NSObject+SBJSON.h" +#import "SBJsonWriter.h" + +@implementation NSObject (NSObject_SBJSON) + +- (NSString *)JSONFragment { + SBJsonWriter *jsonWriter = [SBJsonWriter new]; + NSString *json = [jsonWriter stringWithFragment:self]; + if (!json) + NSLog(@"-JSONFragment failed. Error trace is: %@", [jsonWriter errorTrace]); + [jsonWriter release]; + return json; +} + +- (NSString *)JSONRepresentation { + SBJsonWriter *jsonWriter = [SBJsonWriter new]; + NSString *json = [jsonWriter stringWithObject:self]; + if (!json) + NSLog(@"-JSONRepresentation failed. Error trace is: %@", [jsonWriter errorTrace]); + [jsonWriter release]; + return json; +} + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.h new file mode 100644 index 00000000..fad7179c --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +/** + @brief Adds JSON parsing methods to NSString + +This is a category on NSString that adds methods for parsing the target string. +*/ +@interface NSString (NSString_SBJSON) + + +/** + @brief Returns the object represented in the receiver, or nil on error. + + Returns a a scalar object represented by the string's JSON fragment representation. + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (id)JSONFragmentValue; + +/** + @brief Returns the NSDictionary or NSArray represented by the current string's JSON representation. + + Returns the dictionary or array represented in the receiver, or nil on error. + + Returns the NSDictionary or NSArray represented by the current string's JSON representation. + */ +- (id)JSONValue; + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.m new file mode 100644 index 00000000..41a5a85b --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/NSString+SBJSON.m @@ -0,0 +1,55 @@ +/* + Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "NSString+SBJSON.h" +#import "SBJsonParser.h" + +@implementation NSString (NSString_SBJSON) + +- (id)JSONFragmentValue +{ + SBJsonParser *jsonParser = [SBJsonParser new]; + id repr = [jsonParser fragmentWithString:self]; + if (!repr) + NSLog(@"-JSONFragmentValue failed. Error trace is: %@", [jsonParser errorTrace]); + [jsonParser release]; + return repr; +} + +- (id)JSONValue +{ + SBJsonParser *jsonParser = [SBJsonParser new]; + id repr = [jsonParser objectWithString:self]; + if (!repr) + NSLog(@"-JSONValue failed. Error trace is: %@", [jsonParser errorTrace]); + [jsonParser release]; + return repr; +} + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.h new file mode 100644 index 00000000..43d63c30 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "SBJsonParser.h" +#import "SBJsonWriter.h" + +/** + @brief Facade for SBJsonWriter/SBJsonParser. + + Requests are forwarded to instances of SBJsonWriter and SBJsonParser. + */ +@interface SBJSON : SBJsonBase { + +@private + SBJsonParser *jsonParser; + SBJsonWriter *jsonWriter; +} + + +/// Return the fragment represented by the given string +- (id)fragmentWithString:(NSString*)jsonrep + error:(NSError**)error; + +/// Return the object represented by the given string +- (id)objectWithString:(NSString*)jsonrep + error:(NSError**)error; + +/// Parse the string and return the represented object (or scalar) +- (id)objectWithString:(id)value + allowScalar:(BOOL)x + error:(NSError**)error; + + +/// Return JSON representation of an array or dictionary +- (NSString*)stringWithObject:(id)value + error:(NSError**)error; + +/// Return JSON representation of any legal JSON value +- (NSString*)stringWithFragment:(id)value + error:(NSError**)error; + +/// Return JSON representation (or fragment) for the given object +- (NSString*)stringWithObject:(id)value + allowScalar:(BOOL)x + error:(NSError**)error; + + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.m new file mode 100644 index 00000000..2a30f1a7 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJSON.m @@ -0,0 +1,212 @@ +/* + Copyright (C) 2007-2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJSON.h" + +@implementation SBJSON + +- (id)init { + self = [super init]; + if (self) { + jsonWriter = [SBJsonWriter new]; + jsonParser = [SBJsonParser new]; + [self setMaxDepth:512]; + + } + return self; +} + +- (void)dealloc { + [jsonWriter release]; + [jsonParser release]; + [super dealloc]; +} + +#pragma mark Writer + + +- (NSString *)stringWithObject:(id)obj { + NSString *repr = [jsonWriter stringWithObject:obj]; + if (repr) + return repr; + + [errorTrace release]; + errorTrace = [[jsonWriter errorTrace] mutableCopy]; + return nil; +} + +/** + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + @param allowScalar wether to return json fragments for scalar objects + @param error used to return an error by reference (pass NULL if this is not desired) + +@deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (NSString*)stringWithObject:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error { + + NSString *json = allowScalar ? [jsonWriter stringWithFragment:value] : [jsonWriter stringWithObject:value]; + if (json) + return json; + + [errorTrace release]; + errorTrace = [[jsonWriter errorTrace] mutableCopy]; + + if (error) + *error = [errorTrace lastObject]; + return nil; +} + +/** + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + @param error used to return an error by reference (pass NULL if this is not desired) + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (NSString*)stringWithFragment:(id)value error:(NSError**)error { + return [self stringWithObject:value + allowScalar:YES + error:error]; +} + +/** + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p error can be interrogated to find the cause of the error. + + @param value a NSDictionary or NSArray instance + @param error used to return an error by reference (pass NULL if this is not desired) + */ +- (NSString*)stringWithObject:(id)value error:(NSError**)error { + return [self stringWithObject:value + allowScalar:NO + error:error]; +} + +#pragma mark Parsing + +- (id)objectWithString:(NSString *)repr { + id obj = [jsonParser objectWithString:repr]; + if (obj) + return obj; + + [errorTrace release]; + errorTrace = [[jsonParser errorTrace] mutableCopy]; + + return nil; +} + +/** + Returns the object represented by the passed-in string or nil on error. The returned object can be + a string, number, boolean, null, array or dictionary. + + @param value the json string to parse + @param allowScalar whether to return objects for JSON fragments + @param error used to return an error by reference (pass NULL if this is not desired) + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (id)objectWithString:(id)value allowScalar:(BOOL)allowScalar error:(NSError**)error { + + id obj = allowScalar ? [jsonParser fragmentWithString:value] : [jsonParser objectWithString:value]; + if (obj) + return obj; + + [errorTrace release]; + errorTrace = [[jsonParser errorTrace] mutableCopy]; + + if (error) + *error = [errorTrace lastObject]; + return nil; +} + +/** + Returns the object represented by the passed-in string or nil on error. The returned object can be + a string, number, boolean, null, array or dictionary. + + @param repr the json string to parse + @param error used to return an error by reference (pass NULL if this is not desired) + + @deprecated Given we bill ourselves as a "strict" JSON library, this method should be removed. + */ +- (id)fragmentWithString:(NSString*)repr error:(NSError**)error { + return [self objectWithString:repr + allowScalar:YES + error:error]; +} + +/** + Returns the object represented by the passed-in string or nil on error. The returned object + will be either a dictionary or an array. + + @param repr the json string to parse + @param error used to return an error by reference (pass NULL if this is not desired) + */ +- (id)objectWithString:(NSString*)repr error:(NSError**)error { + return [self objectWithString:repr + allowScalar:NO + error:error]; +} + + + +#pragma mark Properties - parsing + +- (NSUInteger)maxDepth { + return jsonParser.maxDepth; +} + +- (void)setMaxDepth:(NSUInteger)d { + jsonWriter.maxDepth = jsonParser.maxDepth = d; +} + + +#pragma mark Properties - writing + +- (BOOL)humanReadable { + return jsonWriter.humanReadable; +} + +- (void)setHumanReadable:(BOOL)x { + jsonWriter.humanReadable = x; +} + +- (BOOL)sortKeys { + return jsonWriter.sortKeys; +} + +- (void)setSortKeys:(BOOL)x { + jsonWriter.sortKeys = x; +} + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.h new file mode 100644 index 00000000..7b108440 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.h @@ -0,0 +1,86 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import + +extern NSString * SBJSONErrorDomain; + + +enum { + EUNSUPPORTED = 1, + EPARSENUM, + EPARSE, + EFRAGMENT, + ECTRL, + EUNICODE, + EDEPTH, + EESCAPE, + ETRAILCOMMA, + ETRAILGARBAGE, + EEOF, + EINPUT +}; + +/** + @brief Common base class for parsing & writing. + + This class contains the common error-handling code and option between the parser/writer. + */ +@interface SBJsonBase : NSObject { + NSMutableArray *errorTrace; + +@protected + NSUInteger depth, maxDepth; +} + +/** + @brief The maximum recursing depth. + + Defaults to 512. If the input is nested deeper than this the input will be deemed to be + malicious and the parser returns nil, signalling an error. ("Nested too deep".) You can + turn off this security feature by setting the maxDepth value to 0. + */ +@property NSUInteger maxDepth; + +/** + @brief Return an error trace, or nil if there was no errors. + + Note that this method returns the trace of the last method that failed. + You need to check the return value of the call you're making to figure out + if the call actually failed, before you know call this method. + */ + @property(copy,readonly) NSArray* errorTrace; + +/// @internal for use in subclasses to add errors to the stack trace +- (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str; + +/// @internal for use in subclasess to clear the error before a new parsing attempt +- (void)clearErrorTrace; + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.m new file mode 100644 index 00000000..6684325d --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonBase.m @@ -0,0 +1,78 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonBase.h" +NSString * SBJSONErrorDomain = @"org.brautaset.JSON.ErrorDomain"; + + +@implementation SBJsonBase + +@synthesize errorTrace; +@synthesize maxDepth; + +- (id)init { + self = [super init]; + if (self) + self.maxDepth = 512; + return self; +} + +- (void)dealloc { + [errorTrace release]; + [super dealloc]; +} + +- (void)addErrorWithCode:(NSUInteger)code description:(NSString*)str { + NSDictionary *userInfo; + if (!errorTrace) { + errorTrace = [NSMutableArray new]; + userInfo = [NSDictionary dictionaryWithObject:str forKey:NSLocalizedDescriptionKey]; + + } else { + userInfo = [NSDictionary dictionaryWithObjectsAndKeys: + str, NSLocalizedDescriptionKey, + [errorTrace lastObject], NSUnderlyingErrorKey, + nil]; + } + + NSError *error = [NSError errorWithDomain:SBJSONErrorDomain code:code userInfo:userInfo]; + + [self willChangeValueForKey:@"errorTrace"]; + [errorTrace addObject:error]; + [self didChangeValueForKey:@"errorTrace"]; +} + +- (void)clearErrorTrace { + [self willChangeValueForKey:@"errorTrace"]; + [errorTrace release]; + errorTrace = nil; + [self didChangeValueForKey:@"errorTrace"]; +} + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.h new file mode 100644 index 00000000..e95304d9 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.h @@ -0,0 +1,87 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "SBJsonBase.h" + +/** + @brief Options for the parser class. + + This exists so the SBJSON facade can implement the options in the parser without having to re-declare them. + */ +@protocol SBJsonParser + +/** + @brief Return the object represented by the given string. + + Returns the object represented by the passed-in string or nil on error. The returned object can be + a string, number, boolean, null, array or dictionary. + + @param repr the json string to parse + */ +- (id)objectWithString:(NSString *)repr; + +@end + + +/** + @brief The JSON parser class. + + JSON is mapped to Objective-C types in the following way: + + @li Null -> NSNull + @li String -> NSMutableString + @li Array -> NSMutableArray + @li Object -> NSMutableDictionary + @li Boolean -> NSNumber (initialised with -initWithBool:) + @li Number -> NSDecimalNumber + + Since Objective-C doesn't have a dedicated class for boolean values, these turns into NSNumber + instances. These are initialised with the -initWithBool: method, and + round-trip back to JSON properly. (They won't silently suddenly become 0 or 1; they'll be + represented as 'true' and 'false' again.) + + JSON numbers turn into NSDecimalNumber instances, + as we can thus avoid any loss of precision. (JSON allows ridiculously large numbers.) + + */ +@interface SBJsonParser : SBJsonBase { + +@private + const char *c; +} + +@end + +// don't use - exists for backwards compatibility with 2.1.x only. Will be removed in 2.3. +@interface SBJsonParser (Private) +- (id)fragmentWithString:(id)repr; +@end + + diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.m new file mode 100644 index 00000000..eda051a8 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonParser.m @@ -0,0 +1,475 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonParser.h" + +@interface SBJsonParser () + +- (BOOL)scanValue:(NSObject **)o; + +- (BOOL)scanRestOfArray:(NSMutableArray **)o; +- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o; +- (BOOL)scanRestOfNull:(NSNull **)o; +- (BOOL)scanRestOfFalse:(NSNumber **)o; +- (BOOL)scanRestOfTrue:(NSNumber **)o; +- (BOOL)scanRestOfString:(NSMutableString **)o; + +// Cannot manage without looking at the first digit +- (BOOL)scanNumber:(NSNumber **)o; + +- (BOOL)scanHexQuad:(unichar *)x; +- (BOOL)scanUnicodeChar:(unichar *)x; + +- (BOOL)scanIsAtEnd; + +@end + +#define skipWhitespace(c) while (isspace(*c)) c++ +#define skipDigits(c) while (isdigit(*c)) c++ + + +@implementation SBJsonParser + +static char ctrl[0x22]; + + ++ (void)initialize { + ctrl[0] = '\"'; + ctrl[1] = '\\'; + for (int i = 1; i < 0x20; i++) + ctrl[i+1] = i; + ctrl[0x21] = 0; +} + +/** + @deprecated This exists in order to provide fragment support in older APIs in one more version. + It should be removed in the next major version. + */ +- (id)fragmentWithString:(id)repr { + [self clearErrorTrace]; + + if (!repr) { + [self addErrorWithCode:EINPUT description:@"Input was 'nil'"]; + return nil; + } + + depth = 0; + c = [repr UTF8String]; + + id o; + if (![self scanValue:&o]) { + return nil; + } + + // We found some valid JSON. But did it also contain something else? + if (![self scanIsAtEnd]) { + [self addErrorWithCode:ETRAILGARBAGE description:@"Garbage after JSON"]; + return nil; + } + + NSAssert1(o, @"Should have a valid object from %@", repr); + return o; +} + +- (id)objectWithString:(NSString *)repr { + + id o = [self fragmentWithString:repr]; + if (!o) + return nil; + + // Check that the object we've found is a valid JSON container. + if (![o isKindOfClass:[NSDictionary class]] && ![o isKindOfClass:[NSArray class]]) { + [self addErrorWithCode:EFRAGMENT description:@"Valid fragment, but not JSON"]; + return nil; + } + + return o; +} + +/* + In contrast to the public methods, it is an error to omit the error parameter here. + */ +- (BOOL)scanValue:(NSObject **)o +{ + skipWhitespace(c); + + switch (*c++) { + case '{': + return [self scanRestOfDictionary:(NSMutableDictionary **)o]; + break; + case '[': + return [self scanRestOfArray:(NSMutableArray **)o]; + break; + case '"': + return [self scanRestOfString:(NSMutableString **)o]; + break; + case 'f': + return [self scanRestOfFalse:(NSNumber **)o]; + break; + case 't': + return [self scanRestOfTrue:(NSNumber **)o]; + break; + case 'n': + return [self scanRestOfNull:(NSNull **)o]; + break; + case '-': + case '0'...'9': + c--; // cannot verify number correctly without the first character + return [self scanNumber:(NSNumber **)o]; + break; + case '+': + [self addErrorWithCode:EPARSENUM description: @"Leading + disallowed in number"]; + return NO; + break; + case 0x0: + [self addErrorWithCode:EEOF description:@"Unexpected end of string"]; + return NO; + break; + default: + [self addErrorWithCode:EPARSE description: @"Unrecognised leading character"]; + return NO; + break; + } + + NSAssert(0, @"Should never get here"); + return NO; +} + +- (BOOL)scanRestOfTrue:(NSNumber **)o +{ + if (!strncmp(c, "rue", 3)) { + c += 3; + *o = [NSNumber numberWithBool:YES]; + return YES; + } + [self addErrorWithCode:EPARSE description:@"Expected 'true'"]; + return NO; +} + +- (BOOL)scanRestOfFalse:(NSNumber **)o +{ + if (!strncmp(c, "alse", 4)) { + c += 4; + *o = [NSNumber numberWithBool:NO]; + return YES; + } + [self addErrorWithCode:EPARSE description: @"Expected 'false'"]; + return NO; +} + +- (BOOL)scanRestOfNull:(NSNull **)o { + if (!strncmp(c, "ull", 3)) { + c += 3; + *o = [NSNull null]; + return YES; + } + [self addErrorWithCode:EPARSE description: @"Expected 'null'"]; + return NO; +} + +- (BOOL)scanRestOfArray:(NSMutableArray **)o { + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + + *o = [NSMutableArray arrayWithCapacity:8]; + + for (; *c ;) { + id v; + + skipWhitespace(c); + if (*c == ']' && c++) { + depth--; + return YES; + } + + if (![self scanValue:&v]) { + [self addErrorWithCode:EPARSE description:@"Expected value while parsing array"]; + return NO; + } + + [*o addObject:v]; + + skipWhitespace(c); + if (*c == ',' && c++) { + skipWhitespace(c); + if (*c == ']') { + [self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in array"]; + return NO; + } + } + } + + [self addErrorWithCode:EEOF description: @"End of input while parsing array"]; + return NO; +} + +- (BOOL)scanRestOfDictionary:(NSMutableDictionary **)o +{ + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + + *o = [NSMutableDictionary dictionaryWithCapacity:7]; + + for (; *c ;) { + id k, v; + + skipWhitespace(c); + if (*c == '}' && c++) { + depth--; + return YES; + } + + if (!(*c == '\"' && c++ && [self scanRestOfString:&k])) { + [self addErrorWithCode:EPARSE description: @"Object key string expected"]; + return NO; + } + + skipWhitespace(c); + if (*c != ':') { + [self addErrorWithCode:EPARSE description: @"Expected ':' separating key and value"]; + return NO; + } + + c++; + if (![self scanValue:&v]) { + NSString *string = [NSString stringWithFormat:@"Object value expected for key: %@", k]; + [self addErrorWithCode:EPARSE description: string]; + return NO; + } + + [*o setObject:v forKey:k]; + + skipWhitespace(c); + if (*c == ',' && c++) { + skipWhitespace(c); + if (*c == '}') { + [self addErrorWithCode:ETRAILCOMMA description: @"Trailing comma disallowed in object"]; + return NO; + } + } + } + + [self addErrorWithCode:EEOF description: @"End of input while parsing object"]; + return NO; +} + +- (BOOL)scanRestOfString:(NSMutableString **)o +{ + *o = [NSMutableString stringWithCapacity:16]; + do { + // First see if there's a portion we can grab in one go. + // Doing this caused a massive speedup on the long string. + size_t len = strcspn(c, ctrl); + if (len) { + // check for + id t = [[NSString alloc] initWithBytesNoCopy:(char*)c + length:len + encoding:NSUTF8StringEncoding + freeWhenDone:NO]; + if (t) { + [*o appendString:t]; + [t release]; + c += len; + } + } + + if (*c == '"') { + c++; + return YES; + + } else if (*c == '\\') { + unichar uc = *++c; + switch (uc) { + case '\\': + case '/': + case '"': + break; + + case 'b': uc = '\b'; break; + case 'n': uc = '\n'; break; + case 'r': uc = '\r'; break; + case 't': uc = '\t'; break; + case 'f': uc = '\f'; break; + + case 'u': + c++; + if (![self scanUnicodeChar:&uc]) { + [self addErrorWithCode:EUNICODE description: @"Broken unicode character"]; + return NO; + } + c--; // hack. + break; + default: + [self addErrorWithCode:EESCAPE description: [NSString stringWithFormat:@"Illegal escape sequence '0x%x'", uc]]; + return NO; + break; + } + CFStringAppendCharacters((CFMutableStringRef)*o, &uc, 1); + c++; + + } else if (*c < 0x20) { + [self addErrorWithCode:ECTRL description: [NSString stringWithFormat:@"Unescaped control character '0x%x'", *c]]; + return NO; + + } else { + NSLog(@"should not be able to get here"); + } + } while (*c); + + [self addErrorWithCode:EEOF description:@"Unexpected EOF while parsing string"]; + return NO; +} + +- (BOOL)scanUnicodeChar:(unichar *)x +{ + unichar hi, lo; + + if (![self scanHexQuad:&hi]) { + [self addErrorWithCode:EUNICODE description: @"Missing hex quad"]; + return NO; + } + + if (hi >= 0xd800) { // high surrogate char? + if (hi < 0xdc00) { // yes - expect a low char + + if (!(*c == '\\' && ++c && *c == 'u' && ++c && [self scanHexQuad:&lo])) { + [self addErrorWithCode:EUNICODE description: @"Missing low character in surrogate pair"]; + return NO; + } + + if (lo < 0xdc00 || lo >= 0xdfff) { + [self addErrorWithCode:EUNICODE description:@"Invalid low surrogate char"]; + return NO; + } + + hi = (hi - 0xd800) * 0x400 + (lo - 0xdc00) + 0x10000; + + } else if (hi < 0xe000) { + [self addErrorWithCode:EUNICODE description:@"Invalid high character in surrogate pair"]; + return NO; + } + } + + *x = hi; + return YES; +} + +- (BOOL)scanHexQuad:(unichar *)x +{ + *x = 0; + for (int i = 0; i < 4; i++) { + unichar uc = *c; + c++; + int d = (uc >= '0' && uc <= '9') + ? uc - '0' : (uc >= 'a' && uc <= 'f') + ? (uc - 'a' + 10) : (uc >= 'A' && uc <= 'F') + ? (uc - 'A' + 10) : -1; + if (d == -1) { + [self addErrorWithCode:EUNICODE description:@"Missing hex digit in quad"]; + return NO; + } + *x *= 16; + *x += d; + } + return YES; +} + +- (BOOL)scanNumber:(NSNumber **)o +{ + const char *ns = c; + + // The logic to test for validity of the number formatting is relicensed + // from JSON::XS with permission from its author Marc Lehmann. + // (Available at the CPAN: http://search.cpan.org/dist/JSON-XS/ .) + + if ('-' == *c) + c++; + + if ('0' == *c && c++) { + if (isdigit(*c)) { + [self addErrorWithCode:EPARSENUM description: @"Leading 0 disallowed in number"]; + return NO; + } + + } else if (!isdigit(*c) && c != ns) { + [self addErrorWithCode:EPARSENUM description: @"No digits after initial minus"]; + return NO; + + } else { + skipDigits(c); + } + + // Fractional part + if ('.' == *c && c++) { + + if (!isdigit(*c)) { + [self addErrorWithCode:EPARSENUM description: @"No digits after decimal point"]; + return NO; + } + skipDigits(c); + } + + // Exponential part + if ('e' == *c || 'E' == *c) { + c++; + + if ('-' == *c || '+' == *c) + c++; + + if (!isdigit(*c)) { + [self addErrorWithCode:EPARSENUM description: @"No digits after exponent"]; + return NO; + } + skipDigits(c); + } + + id str = [[NSString alloc] initWithBytesNoCopy:(char*)ns + length:c - ns + encoding:NSUTF8StringEncoding + freeWhenDone:NO]; + [str autorelease]; + if (str && (*o = [NSDecimalNumber decimalNumberWithString:str])) + return YES; + + [self addErrorWithCode:EPARSENUM description: @"Failed creating decimal instance"]; + return NO; +} + +- (BOOL)scanIsAtEnd +{ + skipWhitespace(c); + return !*c; +} + + +@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.h new file mode 100644 index 00000000..f6f5e17b --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.h @@ -0,0 +1,129 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import +#import "SBJsonBase.h" + +/** + @brief Options for the writer class. + + This exists so the SBJSON facade can implement the options in the writer without having to re-declare them. + */ +@protocol SBJsonWriter + +/** + @brief Whether we are generating human-readable (multiline) JSON. + + Set whether or not to generate human-readable JSON. The default is NO, which produces + JSON without any whitespace. (Except inside strings.) If set to YES, generates human-readable + JSON with linebreaks after each array value and dictionary key/value pair, indented two + spaces per nesting level. + */ +@property BOOL humanReadable; + +/** + @brief Whether or not to sort the dictionary keys in the output. + + If this is set to YES, the dictionary keys in the JSON output will be in sorted order. + (This is useful if you need to compare two structures, for example.) The default is NO. + */ +@property BOOL sortKeys; + +/** + @brief Return JSON representation (or fragment) for the given object. + + Returns a string containing JSON representation of the passed in value, or nil on error. + If nil is returned and @p error is not NULL, @p *error can be interrogated to find the cause of the error. + + @param value any instance that can be represented as a JSON fragment + + */ +- (NSString*)stringWithObject:(id)value; + +@end + + +/** + @brief The JSON writer class. + + Objective-C types are mapped to JSON types in the following way: + + @li NSNull -> Null + @li NSString -> String + @li NSArray -> Array + @li NSDictionary -> Object + @li NSNumber (-initWithBool:) -> Boolean + @li NSNumber -> Number + + In JSON the keys of an object must be strings. NSDictionary keys need + not be, but attempting to convert an NSDictionary with non-string keys + into JSON will throw an exception. + + NSNumber instances created with the +initWithBool: method are + converted into the JSON boolean "true" and "false" values, and vice + versa. Any other NSNumber instances are converted to a JSON number the + way you would expect. + + */ +@interface SBJsonWriter : SBJsonBase { + +@private + BOOL sortKeys, humanReadable; +} + +@end + +// don't use - exists for backwards compatibility. Will be removed in 2.3. +@interface SBJsonWriter (Private) +- (NSString*)stringWithFragment:(id)value; +@end + +/** + @brief Allows generation of JSON for otherwise unsupported classes. + + If you have a custom class that you want to create a JSON representation for you can implement + this method in your class. It should return a representation of your object defined + in terms of objects that can be translated into JSON. For example, a Person + object might implement it like this: + + @code + - (id)jsonProxyObject { + return [NSDictionary dictionaryWithObjectsAndKeys: + name, @"name", + phone, @"phone", + email, @"email", + nil]; + } + @endcode + + */ +@interface NSObject (SBProxyForJson) +- (id)proxyForJson; +@end + diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.m new file mode 100644 index 00000000..0f329041 --- /dev/null +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/JSON/SBJsonWriter.m @@ -0,0 +1,237 @@ +/* + Copyright (C) 2009 Stig Brautaset. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither the name of the author nor the names of its contributors may be used + to endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#import "SBJsonWriter.h" + +@interface SBJsonWriter () + +- (BOOL)appendValue:(id)fragment into:(NSMutableString*)json; +- (BOOL)appendArray:(NSArray*)fragment into:(NSMutableString*)json; +- (BOOL)appendDictionary:(NSDictionary*)fragment into:(NSMutableString*)json; +- (BOOL)appendString:(NSString*)fragment into:(NSMutableString*)json; + +- (NSString*)indent; + +@end + +@implementation SBJsonWriter + +static NSMutableCharacterSet *kEscapeChars; + ++ (void)initialize { + kEscapeChars = [[NSMutableCharacterSet characterSetWithRange: NSMakeRange(0,32)] retain]; + [kEscapeChars addCharactersInString: @"\"\\"]; +} + + +@synthesize sortKeys; +@synthesize humanReadable; + +/** + @deprecated This exists in order to provide fragment support in older APIs in one more version. + It should be removed in the next major version. + */ +- (NSString*)stringWithFragment:(id)value { + [self clearErrorTrace]; + depth = 0; + NSMutableString *json = [NSMutableString stringWithCapacity:128]; + + if ([self appendValue:value into:json]) + return json; + + return nil; +} + + +- (NSString*)stringWithObject:(id)value { + + if ([value isKindOfClass:[NSDictionary class]] || [value isKindOfClass:[NSArray class]]) { + return [self stringWithFragment:value]; + } + + if ([value respondsToSelector:@selector(proxyForJson)]) { + NSString *tmp = [self stringWithObject:[value proxyForJson]]; + if (tmp) + return tmp; + } + + + [self clearErrorTrace]; + [self addErrorWithCode:EFRAGMENT description:@"Not valid type for JSON"]; + return nil; +} + + +- (NSString*)indent { + return [@"\n" stringByPaddingToLength:1 + 2 * depth withString:@" " startingAtIndex:0]; +} + +- (BOOL)appendValue:(id)fragment into:(NSMutableString*)json { + if ([fragment isKindOfClass:[NSDictionary class]]) { + if (![self appendDictionary:fragment into:json]) + return NO; + + } else if ([fragment isKindOfClass:[NSArray class]]) { + if (![self appendArray:fragment into:json]) + return NO; + + } else if ([fragment isKindOfClass:[NSString class]]) { + if (![self appendString:fragment into:json]) + return NO; + + } else if ([fragment isKindOfClass:[NSNumber class]]) { + if ('c' == *[fragment objCType]) + [json appendString:[fragment boolValue] ? @"true" : @"false"]; + else + [json appendString:[fragment stringValue]]; + + } else if ([fragment isKindOfClass:[NSNull class]]) { + [json appendString:@"null"]; + } else if ([fragment respondsToSelector:@selector(proxyForJson)]) { + [self appendValue:[fragment proxyForJson] into:json]; + + } else { + [self addErrorWithCode:EUNSUPPORTED description:[NSString stringWithFormat:@"JSON serialisation not supported for %@", [fragment class]]]; + return NO; + } + return YES; +} + +- (BOOL)appendArray:(NSArray*)fragment into:(NSMutableString*)json { + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + [json appendString:@"["]; + + BOOL addComma = NO; + for (id value in fragment) { + if (addComma) + [json appendString:@","]; + else + addComma = YES; + + if ([self humanReadable]) + [json appendString:[self indent]]; + + if (![self appendValue:value into:json]) { + return NO; + } + } + + depth--; + if ([self humanReadable] && [fragment count]) + [json appendString:[self indent]]; + [json appendString:@"]"]; + return YES; +} + +- (BOOL)appendDictionary:(NSDictionary*)fragment into:(NSMutableString*)json { + if (maxDepth && ++depth > maxDepth) { + [self addErrorWithCode:EDEPTH description: @"Nested too deep"]; + return NO; + } + [json appendString:@"{"]; + + NSString *colon = [self humanReadable] ? @" : " : @":"; + BOOL addComma = NO; + NSArray *keys = [fragment allKeys]; + if (self.sortKeys) + keys = [keys sortedArrayUsingSelector:@selector(compare:)]; + + for (id value in keys) { + if (addComma) + [json appendString:@","]; + else + addComma = YES; + + if ([self humanReadable]) + [json appendString:[self indent]]; + + if (![value isKindOfClass:[NSString class]]) { + [self addErrorWithCode:EUNSUPPORTED description: @"JSON object key must be string"]; + return NO; + } + + if (![self appendString:value into:json]) + return NO; + + [json appendString:colon]; + if (![self appendValue:[fragment objectForKey:value] into:json]) { + [self addErrorWithCode:EUNSUPPORTED description:[NSString stringWithFormat:@"Unsupported value for key %@ in object", value]]; + return NO; + } + } + + depth--; + if ([self humanReadable] && [fragment count]) + [json appendString:[self indent]]; + [json appendString:@"}"]; + return YES; +} + +- (BOOL)appendString:(NSString*)fragment into:(NSMutableString*)json { + + [json appendString:@"\""]; + + NSRange esc = [fragment rangeOfCharacterFromSet:kEscapeChars]; + if ( !esc.length ) { + // No special chars -- can just add the raw string: + [json appendString:fragment]; + + } else { + NSUInteger length = [fragment length]; + for (NSUInteger i = 0; i < length; i++) { + unichar uc = [fragment characterAtIndex:i]; + switch (uc) { + case '"': [json appendString:@"\\\""]; break; + case '\\': [json appendString:@"\\\\"]; break; + case '\t': [json appendString:@"\\t"]; break; + case '\n': [json appendString:@"\\n"]; break; + case '\r': [json appendString:@"\\r"]; break; + case '\b': [json appendString:@"\\b"]; break; + case '\f': [json appendString:@"\\f"]; break; + default: + if (uc < 0x20) { + [json appendFormat:@"\\u%04x", uc]; + } else { + CFStringAppendCharacters((CFMutableStringRef)json, &uc, 1); + } + break; + + } + } + } + + [json appendString:@"\""]; + return YES; +} + + +@end From 91d5bf2069743ec28d6d923e0f7c95f93bce9247 Mon Sep 17 00:00:00 2001 From: Colin Humber Date: Thu, 27 Jan 2011 15:45:04 -0700 Subject: [PATCH 2/2] Added support for Facebook's new SDK with Open Graph support Updated config file with new Facebook settings Added additional dictionary elements to SHKItem dictionaryRepresentation Updated example app to work with the new Facebook SDK --- Classes/Example/ShareKitAppDelegate.m | 5 + Classes/ShareKit/Core/SHKItem.h | 2 +- Classes/ShareKit/Core/SHKItem.m | 23 +- Classes/ShareKit/SHKConfig.h | 31 +- .../FBConnect.bundle/images/close.png | Bin 164 -> 0 bytes .../FBConnect.bundle/images/fbicon.png | Bin 226 -> 0 bytes .../FBConnect.bundle/images/login.png | Bin 2102 -> 0 bytes .../FBConnect.bundle/images/login2.png | Bin 3843 -> 0 bytes .../FBConnect.bundle/images/login2_down.png | Bin 3728 -> 0 bytes .../FBConnect.bundle/images/login_down.png | Bin 1980 -> 0 bytes .../FBConnect.bundle/images/logout.png | Bin 1661 -> 0 bytes .../FBConnect.bundle/images/logout_down.png | Bin 1551 -> 0 bytes .../Services/Facebook/FBConnect/FBConnect.h | 18 +- .../Facebook/FBConnect/FBConnectGlobal.h | 218 --------- .../Facebook/FBConnect/FBConnectGlobal.m | 45 -- .../Services/Facebook/FBConnect/FBDialog.h | 73 ++- .../Services/Facebook/FBConnect/FBDialog.m | 280 ++++++----- .../Facebook/FBConnect/FBFeedDialog.h | 42 -- .../Facebook/FBConnect/FBFeedDialog.m | 85 ---- .../Facebook/FBConnect/FBLoginButton.h | 49 -- .../Facebook/FBConnect/FBLoginButton.m | 196 -------- .../Facebook/FBConnect/FBLoginDialog.h | 36 +- .../Facebook/FBConnect/FBLoginDialog.m | 149 +++--- .../Facebook/FBConnect/FBPermissionDialog.h | 31 -- .../Facebook/FBConnect/FBPermissionDialog.m | 101 ---- .../Services/Facebook/FBConnect/FBRequest.h | 125 ++--- .../Services/Facebook/FBConnect/FBRequest.m | 460 +++++++++--------- .../Services/Facebook/FBConnect/FBSession.h | 205 -------- .../Services/Facebook/FBConnect/FBSession.m | 301 ------------ .../Facebook/FBConnect/FBStreamDialog.h | 62 --- .../Facebook/FBConnect/FBStreamDialog.m | 77 --- .../Facebook/FBConnect/FBXMLHandler.h | 32 -- .../Facebook/FBConnect/FBXMLHandler.m | 152 ------ .../Services/Facebook/SHKFBStreamDialog.h | 19 - .../Services/Facebook/SHKFBStreamDialog.m | 40 -- .../Sharers/Services/Facebook/SHKFacebook.h | 39 +- .../Sharers/Services/Facebook/SHKFacebook.m | 290 +++++------ ShareKit-Info.plist | 11 + ShareKit.xcodeproj/project.pbxproj | 182 +++---- 39 files changed, 842 insertions(+), 2537 deletions(-) delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/close.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/fbicon.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login2.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login2_down.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login_down.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/logout.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/logout_down.png delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnectGlobal.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnectGlobal.m delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.m delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.m delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.m delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.m delete mode 100755 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.h delete mode 100755 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.m delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.m delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.h delete mode 100644 Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.m diff --git a/Classes/Example/ShareKitAppDelegate.m b/Classes/Example/ShareKitAppDelegate.m index e905ec41..7708ab45 100644 --- a/Classes/Example/ShareKitAppDelegate.m +++ b/Classes/Example/ShareKitAppDelegate.m @@ -45,6 +45,11 @@ - (void)applicationWillTerminate:(UIApplication *)application // Save data if appropriate } +- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { + SHKFacebook *facebookSharer = [[[SHKFacebook alloc] init] autorelease]; + return [[facebookSharer facebook] handleOpenURL:url]; +} + #pragma mark - #pragma mark Memory management diff --git a/Classes/ShareKit/Core/SHKItem.h b/Classes/ShareKit/Core/SHKItem.h index 19064a41..dabca62b 100644 --- a/Classes/ShareKit/Core/SHKItem.h +++ b/Classes/ShareKit/Core/SHKItem.h @@ -37,7 +37,7 @@ typedef enum } SHKShareType; -@interface SHKItem : NSObject +@interface SHKItem : NSObject { SHKShareType shareType; diff --git a/Classes/ShareKit/Core/SHKItem.m b/Classes/ShareKit/Core/SHKItem.m index 76a44613..d412c50b 100644 --- a/Classes/ShareKit/Core/SHKItem.m +++ b/Classes/ShareKit/Core/SHKItem.m @@ -149,10 +149,19 @@ + (SHKItem *)itemFromDictionary:(NSDictionary *)dictionary item.title = [dictionary objectForKey:@"title"]; item.text = [dictionary objectForKey:@"text"]; item.tags = [dictionary objectForKey:@"tags"]; - + if ([dictionary objectForKey:@"custom"] != nil) item.custom = [[[dictionary objectForKey:@"custom"] mutableCopy] autorelease]; + if ([dictionary objectForKey:@"mimeType"] != nil) + item.mimeType = [dictionary objectForKey:@"mimeType"]; + + if ([dictionary objectForKey:@"filename"] != nil) + item.filename = [dictionary objectForKey:@"filename"]; + + if ([dictionary objectForKey:@"image"] != nil) + item.image = [UIImage imageWithData:[dictionary objectForKey:@"image"]]; + return [item autorelease]; } @@ -177,6 +186,18 @@ - (NSDictionary *)dictionaryRepresentation if (tags != nil) [dictionary setObject:tags forKey:@"tags"]; + if (mimeType != nil) + [dictionary setObject:mimeType forKey:@"mimeType"]; + + if (filename != nil) + [dictionary setObject:filename forKey:@"filename"]; + + if (data != nil) + [dictionary setObject:data forKey:@"data"]; + + if (image != nil) + [dictionary setObject:UIImagePNGRepresentation(image) forKey:@"image"]; + // If you add anymore, make sure to add a method for retrieving them to the itemWithDictionary function too return dictionary; diff --git a/Classes/ShareKit/SHKConfig.h b/Classes/ShareKit/SHKConfig.h index c2aa3565..35f0e5a2 100644 --- a/Classes/ShareKit/SHKConfig.h +++ b/Classes/ShareKit/SHKConfig.h @@ -43,12 +43,27 @@ #define SHKDeliciousSecretKey @"" // Facebook - http://www.facebook.com/developers -// If SHKFacebookUseSessionProxy is enabled then SHKFacebookSecret is ignored and should be left blank +// iOS SDK - https://github.com/facebook/facebook-ios-sdk +/* + Important Facebook settings to get right: + + URL Schemes + --- + You must create a URL scheme in your Info.plist that is in the format fb[app_id]. See the documentation on the iOS SDK under Authentication and Authorization for more details. This is to allow + the new Single Sign-on capabilities of the iOS SDK to callback to your application, should it use fast app switching to authenticate in the Facebook app or Safari. + + Modify AppDelegate class + --- + You must implement the application:handleOpenURL: method in your AppDelegate class. In this method, call the handleOpenURL: method on the facebook property of an SHKFacebook instance. + + For example: + - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { + SHKFacebook *facebookSharer = [[[SHKFacebook alloc] init] autorelease]; + return [[facebookSharer facebook] handleOpenURL:url]; + } + */ +#define SHKFacebookAppId @"" -#define SHKFacebookUseSessionProxy NO -#define SHKFacebookKey @"" -#define SHKFacebookSecret @"" -#define SHKFacebookSessionProxyURL @"" // Read It Later - http://readitlaterlist.com/api/?shk #define SHKReadItLaterKey @"" @@ -75,6 +90,12 @@ #define SHKTwitterUseXAuth 0 // To use xAuth, set to 1 #define SHKTwitterUsername @"" // Enter your app's twitter account if you'd like to ask the user to follow it when logging in. (Only for xAuth) +// Evernote - http://www.evernote.com/about/developer/api/ +#define SHKEvernoteUserStoreURL @"" +#define SHKEvernoteSecretKey @"" +#define SHKEvernoteConsumerKey @"" +#define SHKEvernoteNetStoreURLBase @"" + // Bit.ly (for shortening URLs on Twitter) - http://bit.ly/account/register - after signup: http://bit.ly/a/your_api_key #define SHKBitLyLogin @"" #define SHKBitLyKey @"" diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/close.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/close.png deleted file mode 100644 index a89b82faba7910c645fd1ae8cc285c3e86a0763d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 164 zcmeAS@N?(olHy`uVBq!ia0vp^>_E)H!3HEvS)PI@$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1GZk{fVAr-fhV)i{gR?nu;Q4pS<($FMoo!@kH#s$^{6Apua z|NqOoGO#(Q87`FWJd>VufO*D+w~mDZn^<;r&%B^IL6m_-f}!-QYBk%O&IF)|44$rj JF6*2UngF8LG#3B> diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/fbicon.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/fbicon.png deleted file mode 100644 index 413396be6b5baaaf363d4aa1111e4935c234a1b9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 226 zcmeAS@N?(olHy`uVBq!ia0vp^d?3uh1SBVD?P>#3k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*D5XT0C7GLn>}1`K*a4etl4y&B?*nv87X@)PW)7Sd+J3Xxxt7 zXM$ZONT1l&Ig3+eW`Snw>SpFS%amrbGy3qjFzYOni=5VXtZhcG>&w~S;~(-hY$%*1 zHDNDHo?MIXrfAQPV&dwv+a^iqWh&=Nay&k^H+;zqE#-6N?_LS}a6UQEt|H#Rz|0U9 Wr}l!o#w8Z$9tKZWKbLh*2~7ZwZcbkS diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login.png deleted file mode 100644 index 77bc30c27400597b79ccc126fabd5bcc0fb3a41c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2102 zcmV-62+8+}P)*hL`sNJ)3hS3TI$f|ffT8Va8oI?La8WKP?HeL zfgrVN3wB7sCK%HYY-)q;wY{wO{haB!cOPDx-Sq=ks;W8Y*uMAdJ#*(f-<)&qumVQK zM5-ngNriE$$iyO#Q;9T0>OumDW(II|b@f_{#qzu;iYsWWRj``|+OlkwB&oycbRKJN zZf=PJ?qon48OYnWZ?DUpTl`X9VWnYK-eSEVsuU(qLxO&H*k!*H7`%1KGt~FRFHfC1 z)yTl+KyTTyrOIqJ|E}zj@6FNZO)3Sh835ep3V;5WqkRsC0V zvPF$i6%NY^N;4n~%fgDSIo)mV@2BBzHBZ!nuvDM9KpzZC3PLj|`pkuT!nPFAE`w3n zEJH1XLkiF{D{3LyXvi_35mZvff3+DI1v(9zg8?5xK|j|i#Z#l>s?q8dphtmD&1h!3 z(AqJrD^#t0fGUHm038E5l&%m8yk^2+woJ*p$LZi}Q~8!92?4(wK97U{76cXa1~YUS zmjAb>Kvu{8N(VFpWFjdp%)x6fZbojFk&oByZjAdCk`P)7hv0G9VA2M$qq-D}7tV&; zLs{&mhIf;BgK|x(S1Y_LnoYG@6(m(i|%%bd(74n6yJhR*>X- z{CQn=%*j@xp?*7z8CrC9-^EvE=c1}|2{x>+zz<$M4O!GfrPfkVg0x0rZ74*QhJK4Y zP_i5zv$vR?5hIn2t&Igb91ifmRVppn)MH4HXk#xb{C+=v`u)dIwsanLJb#?}WPjA3 zFlnIqZo=spElAtiy_~-jTSi@#GZ()qkL}kd&yRl)Yj70gGB|IIQa6@$j>qHdF!wXKYIN% z25tRhv*7UIJun)yaoa0L&*Iq~Ysr?y=YGC_6B>Sd5!Y_o(&9Geq!H^pM8QuzxkApH?Cg+tsyI^ZNs`!uvaPT<4&SYP2mxwi z4?edU9)Fn6Gc_6X*t6?l9D4gRbP%vi*k0HkC&DZdw>YC+4%@UCJ#^PSCUwNdiGE{w zaXhOdXQu${!*{6P)>BIHLoIuWg_#&|Ik9^AD*l=G&RpSsPJU#=(={b{uwp*VMcU2F z9k*c}uwtNpfJSSe*NX6ZJxOgDIu*~cjL8GU)cw245P4H9qw0Z$ShaE)^0STj^SSHj zx^FEfkF8?Ga)=s~wXO<9MJYd3we0$-T$pOimmp`W0~R`txnQ*j-bO zhbjy4<~z+0L^Wh8LYvkt!;kmY;Q0HOX-*YAFnM|I6vSx2C~yL$4(?wH6LZ46fW`M4 zz20~m4|sIlm48`r_CiYktLBl zO+kw7iGezPkEv|zXZ!Vj?!SC#KHA#aap}@OQL}y#RxHVm+ctf@7$%hy7M&k&{$v-P z`sP}wwFbnB&4XpLp@EkI8JaY1>d{{L{@T0LJvglulCOW`*m-=b#*HU8lwkduVm`-i zl+E`KMi|ui$BU?Y>Z@q^;Be$gpx~T3b1k85Bi75*x`~?D3}Tt?9-AE5&x>!I!K(*0 zqUqQRe43?^KQwiYvAy?pecbl$>8sp!_8&K~WPTQYLEX|1>2vMZ2h!p;=FG=h#oF51 z9=mzV+;lm5a9}X)$uO2W65Bg=GR&Kumo!Hwiis-x;suf7$XJ!iJ}~6sH$GERv20Gt zYo@bJMP@la>N|1b#DaJqosP8kLFh@Xb-Dv+>+GMleY%p)=L}y@PAG;_TE-2<-d&`S zRa;+6UUg}$%M(!EOve~4rO7qygjBX-F-#d#`;T!KwL~srqa-PB@6=T2#GN~LrY(4O zrsPO~A01Gy(}tl_zSl7WqJlp>E7WdVUS7_+1dTxXgEfr0`uh53y83+2xrG9Q zPsq{J0aM8%(-08>Nhgo^jq+_z(Omtnj~qGj4o&-oXtFM1U^g~4u4!#;{f@`uDW*BK z0^8I@qtV!nM&lQim6d<0tE;<6Q$9fux`c$v$iTKli=!s0s;G)erA%A#B#eH0lxZNU g4hAy&(0>FN0K8&LR2ps7(*OVf07*qoM6N<$f~YXATM diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login2.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/login2.png deleted file mode 100644 index 03e8eba939acaebddd108b1efb168708b9fcdeb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3843 zcmV+e5B%_nP){~+iKvoh= zNPvKmT|rt_S=F`}p|xslr9E1u;k2a|+fxv8fq$P!l0&* zLjNlY4r&2verk3^fHQ#scfo=MQxg*tA5^JSW9eF__)eiAgW_PYEf5GCvDs|TZ{NOs zZy3ln24FJ-@2$7qx+-l%(c1LmKsW_^3O)?iU9?ow#T0@-aB5B=kr*1o>JJF2UzKVmg+&|XMKP#&NueQ245Rtum!_UN_{M6wT&dxOupks0hUFT3VnFebLPMSm!}1J- z*;0g09azdu2tp%>eg(h^eI7_7gbyBq5`f`TN(Y5LhldmW0FIM=eO@>GJ`Zn~G*7g8 z-n2S{;%bFHYXHa2z>HV3@5p71Fm39!RCz1eU7^ny!2Wm}IDzl=U`j~5B0`$hj|I4iH_qpNoxa8GIt2Yhwh1ZFI-v>dZhE8vUO0A8a zP&`gr6r=b#nOKr)Tc=}aU;byai@h&~#}Mf!G%4 z@yj19L|U?$U(Z-sCCe3p(H!H4)7}M(&WGg-N>P}X35U~z`i5q_`{4Izzi)QzGe?dg(IUE=(Ddg7lOGytbV1^`&2!=AcUIQ@PCgXXH(?eln$pQ%S_VLCpnJ$=<=v-q2J{)@6V zZkZZcCd34A@WLfPBzOlnfHsFhAb6fU7X@#4iUu1iZ-v>YL&K?VT$7oGY2~9ZcjkC} z{}9}oCIbPm=7{^*pz#njhWOBXxUyKF?9V!-2iW-O0owYbZ zfbcqcc$Q|Q)fstXzKmx(^Va}d)XWw&#un$`EAz+T)6+H_J>5q(`uS=(z-QEl$z{ZR z5XobWpS<5uM;KIpWsKl9`5j>f-G3f#<1)RoI2YJza}B%XaZVJnvPZwH(J`7%~Te?u&&`P!^b5IYqkIB|jX~1k(2OY>8 zkpQR5hci|mUuh&Dd0bTHxm#%ku@IR1V6vn_XSBdWs}u8QcDf#B6D6a@ZZ4BGRyH|p z9Y{0=kdZ?1BEN}b50fjX5@dTkE+;)BA~PcazJM03-4}(s{u1I!0UV2>0od>JVZxYf z4&INCw2^~*WnR_RdID=AI=WrtY!4RRScH2ku9x{WwWqMDY8PL2H?FDR!70c|k@*{c zw*&j?T8OtKDsS(>W{k`phIJ2r9T}+>e!s2Ljvqa~4eed$h?j^*AHA0cLgHf4FsSbXeh%nfHEN7vwS)h&$!?Pdp>v=QBLT5^j%9~38Vy3LSZvmWck@Ft- z`9CR`dLB40)s*Y*UkIm1kBkg>$49`eK zS!pgDl)=hIXVJ#Tfa&FhXr~Ezwp%4n9b1 zZA1F~)bIc5=kCX@E$i^^3v2Mzo2PQyX=vVe?NhtC4UEc4a|j&TsP=v5j@ii09)Z<& z&B8~At=zsRUZ_P`@dzxNJD$c44cO7`k>kL?I`{fgc-&6hyK*MKUi<6aTyG}-VH$_| zbLs4{JZ7v9>&s%vVw#_oO#7qI#4zXtY+AF3e4`~lf5b6xv3Qg-u)VMAvNCW-w_`vF zAzeqxm6pE2Svd4g#fzTKvplQK)Yo*Mydc`<|zEK*ate1!DCXD9G z-0QnO#mS~KTt>y3tvn++Xg07+!KjxqwNy{a6L)_jW=+gSab6#f_mYvgCO<7)_lg*EO=e8{md!5a*Lj&{JoJrnS>}|o9Mm7PMvcSd zvMg+^K7gqdkNTrl9Bydh&+XWK94i->Vch6k;^pysTi>pgWlS172b0ES;n2~L+?(f& z<-cFsc?4&ho49W!TVs)VFn|NW%iF}=a^Ge-^G04r$`zt41$z#*VC9lB%1-%s>bdQF z=?GHoH-E-xJapd@Y<}Z_Yy_*@SbZiR-_V2*qzzO+q!}s78wjp%c)YW{Wz zXU)l|Huc#Ylv(WX)3^mxQdlf1e9~?2pL_%$W>@6qYWIO={(Jt+Qe@HudE}W7Fl|B( z?zm-2cs%O>AG6QWHOp{5njBK5V|oWDX^3IH*<*|&NY6*e`O91N19VR|iFkVbZ8Sk0 zcxl@q{Pmp%{PB^SLwc&TQSBR+sF!`Tv*r}7irpb$+d}04vm;g<)Hv7xoX4dEJuY09fu<@9_x6B=b_iGN*L~N(pdf0%C>jg^)ra-)Q+2?&RDG&*M&eZ|^Arc?c9Y&n`t@XA_pr8WpO83H*{y46K87 zjKyO=>pnfl<(Cy_;NZbJ)YkqROJVA0GL*oYLo<_orvA_VZ9ng`_S-kn z2A=`lc~N-O^q=)!*)dw|Gvpwm9t0CT@%$cqZ3&xsC73z6NZtUj`{&w28Lx^ATXowc z?0xf5+1OWid=hayre^0#ynYJbfmHFF#|wt^`N0!A@QXF`Q2qS(_-$5Byj0yVfcMJp zD`nn`+YWQy&fSd|m6MD|DwpAh^jzJi)&YLoLx7!rZ7%ALhVIuBf8O-M5P0S11X-8k zr@Od}850YUXfabZt&{a;Hb?-M?2zKnZ)@mtqz+78V{}RoFea}L!OFT>>!kg-fii+l*gheCb z)xho6_PB52q!J?X7>&J&OV3P?S_4Otg*GaMxhY|%or}r0cG$VYuNJYa5o^qNyw3wg zt^}82yX5OweMb?GZ7ietB_59fJTuKg!0&?H>Ahn6l5B6cZrQRWS3U=hmt?OX0bf*K zo5PEP4d*VKf4LM-=4Ub9f0Hhxe=Pome9cyk%i*1)C!eF+9wA%| z7cdZ4RaH&iw{PEFPN%bo?r9XaDKu0_tJU_H&E{j}<>fE0TD59F-Es?pa8iia(J>Gw zhBtNEa8rkyO4;El^gr0C1^P)1RCwC#Tv==z*A+d(;U(xd@ur-_X; zR+2VOyxX#r*rM!cH6>CK_ibi+-y04|$rL4Tjah-emk9YsBcXZkug;%8 ze}sWpWK7%L-M!6hHvhV+X{*~@R7%XNgIAZ;C4xaTm@FkGYe~5!H2Y-A2s znpdH+;l=X$UY8)6MOjvKZ|SmnflL@JukR`Mja_7xVbT?d9*y8=;AbO7t}P>3j`Hy#uXz|h%OmxoYR24E?bge;{XNvS)F6VV6*HPL9& zU9HOl2C!5Bz%t;uF?m-{XlZUB1v?mS+T69s&X5?{f#cziY@&3H?Q_1 z6Bvd(PnKl@co-H@!sf1OxLpp!6Df>O&Eo3yX_&3WFjhZa!gGJ;R~c_QVscuArVJUn>!N>SpXa1 z8JkCfd@C3X_b2F*DU>^msIIVM_)GtN)6M4JBFZbWw~%B3TrkZq58zzzE^q(~3@Ohf z#3CpyG2ofK8(=XRG3AS((r!abLj^io>+rXCF9U*!Pl_x{EM)nMZ#LQN3v+I% z%{oNM6MYh;A`p0c3A`fS{$K?D`55nea%(*rYwYNHq!B|NFJjRk400SUXAy$o1j0#y z*w4lnlvQPB_-E%3k0*)2ZHUAqL=&pf)$ZcFeMU+ zRE9}ZP+nGoa5RZeE{?-Y0n6@jyUMvfyR8^bdjMJzlnD%?5++6#F-OcK8_ZO`m1Kf1 zcVhqa_TX*)jYk5guPTPS%)yUmX2Tern&%mfvG!v7nC&8!1}U;#Kmx8(3)v#kvnB3p z?RhC;ejzyzJ7o|CWV6LatZCu*B`IK>b|cI*=BeojA1~7@QxLJtWi=^uAI%r}O*U9m zdxSLMk$zSVSxqt=b}Nydi1~4a@=LvbbkDULEIRhrM{lLeIsLj zl#~Ab`?r%rRR;#calG~3W%``wea}Ao7%XOErth6ogV?pXnfg?~AAG74$3MDBlON{3 zNk|6ld%Od|P#muvzkqd(Rd{lHt2)+GL&RQdu%)K~ufKZ*Tf3`JTj{_*P7Pzn#x-1D zdrJjMiH*(=&G6&qdN(msy$VJutNwcYB4PwQZC#K{3c@i>h&_KgDKnW zd%T;lBI2EoZg56l(M}i3BDJ-(KSxo6J)P-pZ}bxm1t|>~Z&UEnPj+MHrffQ6-&yt}T)H`V+Z5SS%!z4wl)|aAEhB0j<8bg`ggr^^G$IXc#-Z*g`iKNUY zhJ8*`I_vAM#e6u4x8C<)>{bYEjZR`w6Fd`P^if^CxX(!A|Ki3pzPoP&*YU>5VGNGU zqPw-67_%6kdnWO{{hNpZ1b*L@VL#Tlx>4bF;Mj*ZQBzSuU@+s=HwX9_wJ|e>auRbi zR69ujER_jWJUARSD}nMB1zydJWqkZ zo*yM}G}StYxn+2LQO;ECc{2Ul+*!r_xNSo-wr^gCM>npepfy$!4L1jdxo%>vyhqfjcqH&3@ zS@!N~M_rWzZ@xc_&j!3?Lm4{OR^iO08|dw*$A*qtd~#_D|NNK&sI&+@k5m(p%#vOa zk5COf?GIvW&l(QiV+7uKLc)?*)G!ns4NXi;{62%oIMt*}Gw{;U5Q@YXln~l+MsGBn zx0Yd1r`BK+BE)=*U1T{)sg+WGSrG!k7}nIN40V2RoR9D9l?Wc~sYX+M8J$zN^+qS= z5DWwnm=DlV6M@t~Wk4ctpUK1~!pXrEAm({$OKmzWE5r~ktf{Z&eHRIIKHnVIarE`G zoW&AJiDwQbQA*JaEV*+1<}?RirOQe{w_#+IfZXCnmCM3ei|J%GNV2LU77ZaDOE2z{ zarz$49BbpA^sL*QhEHdN5p z5c4l(UvIk_5H2cx_U&Ag(b-g2hH-Bo?>sctIqCZtWemFJRsfSzetzBHuoqj`*HP{4 zqCOWtclOF?Mn_|9J2fZ2he>aHE&segb2{hu@paE~^{;vHB2K=`GU1PZIh|qR+~eHp zIbR9lp$OdCQ-`$#ocBK-K#~>xl&U(3z4m>r2d6KNa>miNjaY4(twq@CNX!J6%oh++ z&NG#~eF9&}iRtth#Gq#;uT9Z-oIn-h^_$yirP@~@hKl8sKq+pMkh3TpCcrZ3Tvr1J zf#mqmH8eLkIYaX25eRa9%_E6?zpwo%`;ezA9MYA`qKD6-)_<3bPfaDwE;yxu^*D?KdRd$Sx zjbU{3OZ2QOM=g~HT3_edN>~kXSdA%sfB#lm@i#Bnvu&<(Q0SUl-IXjUkFz}A3?fo zUts%U`!=s{f@gf5U&s7#{kn&0>ltk6s-n!AS?BZA9}WA_yUx8}9yGh1tfWnbxPHDR zO3%y8A&9*c7Wj>gt)-!iGYC6B zJ{3R*l@aWGKL1Yp!(2yeqZ?MMnHE{&nQ^PNwYb2Jj9oeQ2~=^ zzcaBCsF$+u^rbP*x+lr+dv>(orRSf{=o~`C-^^C&CTU6ijsKt{4v^Zk;#v;*@!vryl| zAZ+{zo(Up%WV`0;rS4?`Y^Gqy=a)i#>Y~=dcQ4o??OvrQc6sv5nKKQU{7?w(_ej9Y zDu~f)c5Ete*Zp@Zg>*iM=lw5bx$!U6znrhV{>WYRG4ct7;`iIkoPA)(1sKxE{{%D< zk1cu4FaPk~lJ~NdqKhsMLRQ4UZ1rAO^t|VmNyAXu+L^ zNGw53_m(cJOBi;I={@0;3Sj+@k#%_}h?o6hD?wfpm<$HPh)D^$lY+fScaAQrT?ngD z!t8Yoz~<`e>fcRFjJ=W+Tg?jpcVfEevN}aTN-C1Z{55rTzhzh!4;(n)XlrZpc|0CD z8Jq7>6oViWuoeA3H_>Hv0arFE;aHI}6LdLCUO9B=5Zm@rgmf{?Uf5gu`}?=txN+mT zL?W?{YGR}AHeFVWh@v=Wu~@D(G&H=id-v`$bSifE@Zk|5XGO_{)_Oz9@3n?YaU u>GBn<)MRA;H%itL=@ww%Wf%QdfB^t}ZpX{M9AEDM0000)^})o%#0Qg_n5a)i-+gd<)kx@r@xf@^V&W2QVieaZO=BxU zqO!=a6oG-+@9uxjy|XaRTn37X(fc<)lXL%j&OP@#-}%me&MgB)^P%(TEIL!>j%{v6 znd|5(dJ0NF^b>%i(dbdP+x-N?Fi|Xv4tCqJC0*BlktFH0v9Ymp7T`$&bR7Zt$dMzb zeY={U_66I$UVoDt5N!vut(&IGnv_|SQ>(L?)cVqM7cN{FB4BfbxrYxQJ}Qdh^DX=O zL!xIFGT8xnyT-5_E4bwhhAoRh2-MbM%+NdwJ0f0y@VD|2d#d)*3cI*P!1mjXt>l&M5f2 zE?R!!%m@?)kgf1!UB`h)gNxJPx@Z_e!FrHn73LP>@XK$1g6Q^w;PU=!kW!EgaxP_N z6QT$ESGT45MWAh`_vS#Cg1kX?$N*{;*q+P4t~wS@9={e`0uPHT8EE$VV1IiPbRCSq zyPsadWK^IUuj?A2KRqyDS&p6@kbyGD?zXgRR-9x{)nfTm2U1@*%r%E)c-&~P8%R(Z zBUMyIfxB;w!tRy;483&@^JLX(uXdnokdDoPE@yIKGE`{SK;U@nsBd@%*9 z>p2>`t-lTSw)!D@^a3x~WFW4y~lw#lI6()1o;i_2NStsDq~8=0HMnUp<7o&r6sPgWUyQ@_TpVLP6=PGeRcOTa2M2Eif1OE= zWLkpvKf8p#>oj)i)G=_0d?EJ9m*a5rbsZQp2j-sJyW!)nXK)bGHDkk;0#em&8hh%I z0qWJtq;7e8ND*YH3BYnZvmus~HJD#YL3}+84Stb=JTsq!Gw+ST_ZJsYS{kAEPy`3h z1VTYodHur)_~@%?TJG*_1y1xhOR5X8aUM(JdjA{U{C8Fde4RNIoiMTKWE^Eo-pidYrtz}x;Z<)2FXMc66*;p z?E{`?ar(;@V}iiK?&bhxasrup`}Mmm%{FiVgRrM9Ok+PyT!xjEHQL7T+vh>VnJ43@ zX;z=JnFP)#z9uG%gVKa9O`{;xaW>u2nPf> z)DeQ)ZtA9K-o(@j9SmZ2Q>~5+n#JUeOgPWDW&8zUhU_bO-(}BC&;&+gaNIh_%STo(&#LF0MTv^g#Ten*E zv)}y=M^kNZZC4mN_cfbRgD-ma+euhY5ebrDWON1w`u4&zkDam>!#K*uVliuD%&%=s zNvf59muj*1&W^)<$GhP1hwq@*h>ZOB^WuisqYo8hKU|upv5DW8p{crRg2n8Tv6d-Yf-jiCiH&n7f>)8c!hjBn#Ln zi?q~NeWqP(E9S{vS{NN2Z7<}}b|Z6zgx<7)oTNc)F|qCVcFnHM9e!R(9u2w;<9PZh z*F3wZY|p;@S=G8k4*u^}6Qjv$9cc{}lK5JU04!l%Y&b{V20t`3#10P++h!J-oQ&?A z-f!0k#=MnNt0vIS$L}2`GEKV)#sp}AW!WjgNQM-~?{UD{IYUgdi0yBApv7=F{L=h< z>{W$3C>r!!&9N&r22{7mg*9GJW{F@EC2@S~4u+}| z3<;Kq>6sHJPK*(Z8B44?NG3KiGIIU&^z_5BEO#Q(yu-__8^>{LE|=@q_V)I71_lO3 z$u{8h>C;n8$;wE;uD2FP!E(-W)>$cSS3Dhx|9h0UYvCP)Xv$!7@@Qp;X+}MQ~ARx~Lmh?IK_ox~SsHTFJ%-4KZeuK-EAJ$VTvy zMWQZz$JeN%jx+XrzjJO!lNm>6f=P2f__^oa^SI}J|9`*ppUc(Ie~1?rAxtk!D@@}# zYDq;PaC>aubKDcQEo`1VWC95w`1Qlqbeu3^5q)ENwsDqA7I)|P|%`g&dK>+824Jb3UI^w@1OnSLrLDAYwngp&w+ zm8B2>Twb|Spc@_@x-Cxs)U!})H0R^u;#87DjQIF?a2rFO32vN@g36OA4g7DngJonupp4uELX{c&&YRCl;#i&iBmP@;vP z^U+|ooGit$uXEqyh=y!!Z*TKkBQ{H7#g6#Dy#-7(9Y=H^`u$~M4Bh#;jAE@uJ}>;P zRT)?8mi+eJ+uLJ;Gcqzr|v-kJ~EfB?(|PJttEl=DM-SqF0DTPWv%z5x26{%9YVyoRd`hbGLoH$y72ID?t}93^6~*0o-q~|7nx`P0f06b z1LFlP9sbA+CiM%XFUat2hq8=F5Dq!X&d#PAH*P3xMn^~K?%liWl(e)os;a8u>(F|9 zZ-6s8Iy#uRy1F__NJvoXJ3BjRW@d(pi;LNCK0iNCnVFe%S;ry8|40YAA`8q#tTxl}uCF#--o!GU4Tq=ZcC7 zc1BxU8xvx+T9vdCbs!l|K|RK+uCC^ONIwBYw@gI=klxeN!{w(>pK>|S=kUdw647&W zbABU^$okH@rIpP?(jm_!FlleS^aVUD0C_+kslSkj^z?KtKYH|t=Q%JiKt)AGl$@N* zQh>fgLql8!^78T&$w)~_VF!(jjBwra=g+CMw3MTCV`GD_K{{|xdH&|j8)aT_;Oy*d zK+h1+Vt88EZgnb=?0p`L)Y$EIMWYP{gYuAw#?8%5#R)jdMGg|Nu&}_93O$B&NZpr` zAs1A+D9XhR&h@_M(fObrW6ArT3DKbjUi+(8uPTHft(usapljEzQDI>rN3P9gQ*;{9 z2168YZEaCZObjnzSUhDL$c))+=C>gyCx=OY{rWZE3xNKE#N6E6L;D5*vV(R@OG~_% ze)L4k=mJraNQs7q2D*R$KI?Q>SC>NIlP6EO+}_^KbxBD{EE6D6qQAeNiE3YP|jq`GfkXBvKyz&6_u|)cS1Y1Yw>m;8f6P=u-wbMq+4E_9QCa z3(w#fS`aBxs|~Rch%%c^DlH*|-M)de)h>!gM6~hJrAy88b2F~JVB|r?Tk8`z6`Q5s z5zHE)8TgQ3s;{sAb$Mm2=zP?9t;u8zdT;;95-hgyjx7hRuC2PGtxGe*N$+VoAnfZ5ZZS6fMhzQz$G+rws$i^R~ z20Hkw6ra<=JSm`#)Sn)Grf$Mq9^3Vp1KSQ^^B@_G{uN*V%EX(FG09w#00000NkvXX Hu0mjfJI@|W diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/logout_down.png b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnect.bundle/images/logout_down.png deleted file mode 100644 index 1ab14b9dc931eeb1b624cca1bbf422a2445f1754..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1551 zcmV+q2JrcbP)4o$iGOaKRRrBWWrYV<@q2Zm^>vh`gb`7bL0j?*j)uxX` z!aYYvM{kYt{Yt0PNvTvyL#TvSUhc%Dn&b=v8ewD$pe7e3Hef0+7C>uke&WnM`uecVU1VjYbXVT!04KfB)mApl=xIvul!+E6~DBW=me9C*rZ3Qbhz3`6p%! zbgitcjL(D*4QR@y(YXY{RqdcpKI$Te&CJVReLt`C&9?agz-UujTT8K6j80EaiS1DT zHB|6CH#avt_z1YwYURN%#*Ddunae_{2Kiy%TmogY*{Hp}o!D-Q&d$#M(MODfD_D=f z$g6tBI`M8|JlqF(5BtEyJ$QL}ISmaB(bm=$9UL4e;}!$7R0^OUGFknS>X%M8zK{y> z((32IVho0XX%2^je?~o+hL=Yf{mo`GU0hu7_NX(NOuRqp1uIdH*@6Wceen6}>PlI> zF-9a3;XuQ%i9;KVfx0J^j$%^3T>7Gox}CZVKp`iMjg8dZ-L13<27|P`yv&1AS64^< z{r$>W1N{2>nidxqIXELDBUDjQq0}!eEz#xWCAGD+aYs2E4wKvM=H;E89cpQ5;qB|| z>v?cjS67R|p=gc%VsiM=ay}ZJ323kryH>C&upm;paS=-y&%RxpR+MsT5aFAwaXO&qb*e%jffF1}0$nW>l?(Qz_?d=t<`wGyZ zP$-*c&X-zmz`XjFMF1SdN-c>rCgz5Q|N9+O46U@?=W zLd+uQtNhFB`JR&Q~w$?l;(4{sk zKAoMN%1eW-$H&L~p4aQ;%G|94tl<&>s#qi#A9bAt_*OQ&STM9V|zt1B3np zMAWIyD7Zm(&<-pwCdGR;Knr#OBmtzbnVA``&Cuz|$w>u3ELyOIg#}($U0uxqgbPDI z05vf&ac?mcW1uax9(@rAaa4@pp$@WzAmKZTm5yhzKgLS|&~ye+k=BExohHK;TVp#IZLg`R`6e8?WRj}=I9swa zZH6TCua%XR3oK!m#D4$(Ev$vRluGe46JQBU$HvBf1I9X8tZ`7` zn4h2jm?iz6vaPH$l}c&<6IOt+boSP4HlMrQ?w^K-hkwSo+SJt4ypjXSV7ugFI{c0V z!7h_iKqS%{@M%&vD240^*>TW -#import - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -extern const NSString* kFB_SDK_VersionNumber; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -#ifdef DEBUG -#define FBLOG -#define FBLOG2 -#else -#define FBLOG -#define FBLOG2 -#endif - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef unsigned long long FBUID; -typedef unsigned long long FBID; - -#define FBAPI_ERROR_DOMAIN @"api.facebook.com" - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// Error codes - -#define FBAPI_EC_SUCCESS 0 -#define FBAPI_EC_UNKNOWN 1 -#define FBAPI_EC_SERVICE 2 -#define FBAPI_EC_METHOD 3 -#define FBAPI_EC_TOO_MANY_CALLS 4 -#define FBAPI_EC_BAD_IP 5 -#define FBAPI_EC_HOST_API 6 -#define FBAPI_EC_HOST_UP 7 -#define FBAPI_EC_SECURE 8 -#define FBAPI_EC_RATE 9 -#define FBAPI_EC_PERMISSION_DENIED 10 -#define FBAPI_EC_DEPRECATED 11 -#define FBAPI_EC_VERSION 12 - -#define FBAPI_EC_PARAM 100 -#define FBAPI_EC_PARAM_FBAPI_KEY 101 -#define FBAPI_EC_PARAM_SESSION_KEY 102 -#define FBAPI_EC_PARAM_CALL_ID 103 -#define FBAPI_EC_PARAM_SIGNATURE 104 -#define FBAPI_EC_PARAM_TOO_MANY 105 -#define FBAPI_EC_PARAM_USER_ID 110 -#define FBAPI_EC_PARAM_USER_FIELD 111 -#define FBAPI_EC_PARAM_SOCIAL_FIELD 112 -#define FBAPI_EC_PARAM_EMAIL 113 -#define FBAPI_EC_PARAM_ALBUM_ID 120 -#define FBAPI_EC_PARAM_PHOTO_ID 121 -#define FBAPI_EC_PARAM_FEED_PRIORITY 130 -#define FBAPI_EC_PARAM_CATEGORY 140 -#define FBAPI_EC_PARAM_SUBCATEGORY 141 -#define FBAPI_EC_PARAM_TITLE 142 -#define FBAPI_EC_PARAM_DESCRIPTION 143 -#define FBAPI_EC_PARAM_BAD_JSON 144 -#define FBAPI_EC_PARAM_BAD_EID 150 -#define FBAPI_EC_PARAM_UNKNOWN_CITY 151 -#define FBAPI_EC_PARAM_BAD_PAGE_TYPE 152 - -#define FBAPI_EC_PERMISSION 200 -#define FBAPI_EC_PERMISSION_USER 210 -#define FBAPI_EC_PERMISSION_ALBUM 220 -#define FBAPI_EC_PERMISSION_PHOTO 221 -#define FBAPI_EC_PERMISSION_MESSAGE 230 -#define FBAPI_EC_PERMISSION_MARKUP_OTHER_USER 240 -#define FBAPI_EC_PERMISSION_STATUS_UPDATE 250 -#define FBAPI_EC_PERMISSION_PHOTO_UPLOAD 260 -#define FBAPI_EC_PERMISSION_SMS 270 -#define FBAPI_EC_PERMISSION_CREATE_LISTING 280 -#define FBAPI_EC_PERMISSION_EVENT 290 -#define FBAPI_EC_PERMISSION_LARGE_FBML_TEMPLATE 291 -#define FBAPI_EC_PERMISSION_LIVEMESSAGE 292 -#define FBAPI_EC_PERMISSION_RSVP_EVENT 299 - -#define FBAPI_EC_EDIT 300 -#define FBAPI_EC_EDIT_USER_DATA 310 -#define FBAPI_EC_EDIT_PHOTO 320 -#define FBAPI_EC_EDIT_ALBUM_SIZE 321 -#define FBAPI_EC_EDIT_PHOTO_TAG_SUBJECT 322 -#define FBAPI_EC_EDIT_PHOTO_TAG_PHOTO 323 -#define FBAPI_EC_EDIT_PHOTO_FILE 324 -#define FBAPI_EC_EDIT_PHOTO_PENDING_LIMIT 325 -#define FBAPI_EC_EDIT_PHOTO_TAG_LIMIT 326 -#define FBAPI_EC_EDIT_ALBUM_REORDER_PHOTO_NOT_IN_ALBUM 327 -#define FBAPI_EC_EDIT_ALBUM_REORDER_TOO_FEW_PHOTOS 328 -#define FBAPI_EC_MALFORMED_MARKUP 329 -#define FBAPI_EC_EDIT_MARKUP 330 -#define FBAPI_EC_EDIT_FEED_TOO_MANY_USER_CALLS 340 -#define FBAPI_EC_EDIT_FEED_TOO_MANY_USER_ACTION_CALLS 341 -#define FBAPI_EC_EDIT_FEED_TITLE_LINK 342 -#define FBAPI_EC_EDIT_FEED_TITLE_LENGTH 343 -#define FBAPI_EC_EDIT_FEED_TITLE_NAME 344 -#define FBAPI_EC_EDIT_FEED_TITLE_BLANK 345 -#define FBAPI_EC_EDIT_FEED_BODY_LENGTH 346 -#define FBAPI_EC_EDIT_FEED_PHOTO_SRC 347 -#define FBAPI_EC_EDIT_FEED_PHOTO_LINK 348 -#define FBAPI_EC_EDIT_VIDEO_SIZE 350 -#define FBAPI_EC_EDIT_VIDEO_INVALID_FILE 351 -#define FBAPI_EC_EDIT_VIDEO_INVALID_TYPE 352 -#define FBAPI_EC_EDIT_FEED_TITLE_ARRAY 360 -#define FBAPI_EC_EDIT_FEED_TITLE_PARAMS 361 -#define FBAPI_EC_EDIT_FEED_BODY_ARRAY 362 -#define FBAPI_EC_EDIT_FEED_BODY_PARAMS 363 -#define FBAPI_EC_EDIT_FEED_PHOTO 364 -#define FBAPI_EC_EDIT_FEED_TEMPLATE 365 -#define FBAPI_EC_EDIT_FEED_TARGET 366 -#define FBAPI_EC_USERS_CREATE_INVALID_EMAIL 370 -#define FBAPI_EC_USERS_CREATE_EXISTING_EMAIL 371 -#define FBAPI_EC_USERS_CREATE_BIRTHDAY 372 -#define FBAPI_EC_USERS_CREATE_PASSWORD 373 -#define FBAPI_EC_USERS_REGISTER_INVALID_CREDENTIAL 374 -#define FBAPI_EC_USERS_REGISTER_CONF_FAILURE 375 -#define FBAPI_EC_USERS_REGISTER_EXISTING 376 -#define FBAPI_EC_USERS_REGISTER_DEFAULT_ERROR 377 -#define FBAPI_EC_USERS_REGISTER_PASSWORD_BLANK 378 -#define FBAPI_EC_USERS_REGISTER_PASSWORD_INVALID_CHARS 379 -#define FBAPI_EC_USERS_REGISTER_PASSWORD_SHORT 380 -#define FBAPI_EC_USERS_REGISTER_PASSWORD_WEAK 381 -#define FBAPI_EC_USERS_REGISTER_USERNAME_ERROR 382 -#define FBAPI_EC_USERS_REGISTER_MISSING_INPUT 383 -#define FBAPI_EC_USERS_REGISTER_INCOMPLETE_BDAY 384 -#define FBAPI_EC_USERS_REGISTER_INVALID_EMAIL 385 -#define FBAPI_EC_USERS_REGISTER_EMAIL_DISABLED 386 -#define FBAPI_EC_USERS_REGISTER_ADD_USER_FAILED 387 -#define FBAPI_EC_USERS_REGISTER_NO_GENDER 388 - -#define FBAPI_EC_AUTH_EMAIL 400 -#define FBAPI_EC_AUTH_LOGIN 401 -#define FBAPI_EC_AUTH_SIG 402 -#define FBAPI_EC_AUTH_TIME 403 - -#define FBAPI_EC_SESSION_METHOD 451 -#define FBAPI_EC_SESSION_REQUIRED 453 -#define FBAPI_EC_SESSION_REQUIRED_FOR_SECRET 454 -#define FBAPI_EC_SESSION_CANNOT_USE_SESSION_SECRET 455 - -#define FBAPI_EC_MESG_BANNED 500 -#define FBAPI_EC_MESG_NO_BODY 501 -#define FBAPI_EC_MESG_TOO_LONG 502 -#define FBAPI_EC_MESG_RATE 503 -#define FBAPI_EC_MESG_INVALID_THREAD 504 -#define FBAPI_EC_MESG_INVALID_RECIP 505 -#define FBAPI_EC_POKE_INVALID_RECIP 510 -#define FBAPI_EC_POKE_OUTSTANDING 511 -#define FBAPI_EC_POKE_RATE 512 - -#define FQL_EC_UNKNOWN_ERROR 600 -#define FQL_EC_PARSER_ERROR 601 -#define FQL_EC_UNKNOWN_FIELD 602 -#define FQL_EC_UNKNOWN_TABLE 603 -#define FQL_EC_NO_INDEX 604 -#define FQL_EC_UNKNOWN_FUNCTION 605 -#define FQL_EC_INVALID_PARAM 606 -#define FQL_EC_INVALID_FIELD 607 -#define FQL_EC_INVALID_SESSION 608 - -#define FBAPI_EC_REF_SET_FAILED 700 -#define FBAPI_EC_FB_APP_UNKNOWN_ERROR 750 -#define FBAPI_EC_FB_APP_FETCH_FAILED 751 -#define FBAPI_EC_FB_APP_NO_DATA 752 -#define FBAPI_EC_FB_APP_NO_PERMISSIONS 753 -#define FBAPI_EC_FB_APP_TAG_MISSING 754 - -#define FBAPI_EC_DATA_UNKNOWN_ERROR 800 -#define FBAPI_EC_DATA_INVALID_OPERATION 801 -#define FBAPI_EC_DATA_QUOTA_EXCEEDED 802 -#define FBAPI_EC_DATA_OBJECT_NOT_FOUND 803 -#define FBAPI_EC_DATA_OBJECT_ALREADY_EXISTS 804 -#define FBAPI_EC_DATA_DATABASE_ERROR 805 -#define FBAPI_EC_DATA_CREATE_TEMPLATE_ERROR 806 -#define FBAPI_EC_DATA_TEMPLATE_EXISTS_ERROR 807 -#define FBAPI_EC_DATA_TEMPLATE_HANDLE_TOO_LONG 808 -#define FBAPI_EC_DATA_TEMPLATE_HANDLE_ALREADY_IN_USE 809 -#define FBAPI_EC_DATA_TOO_MANY_TEMPLATE_BUNDLES 810 -#define FBAPI_EC_DATA_MALFORMED_ACTION_LINK 811 -#define FBAPI_EC_DATA_TEMPLATE_USES_RESERVED_TOKEN 812 - -#define FBAPI_EC_NO_SUCH_APP 900 -#define FBAPI_BATCH_TOO_MANY_ITEMS 950 -#define FBAPI_EC_BATCH_ALREADY_STARTED 951 -#define FBAPI_EC_BATCH_NOT_STARTED 952 -#define FBAPI_EC_BATCH_METHOD_NOT_ALLOWED_IN_BATCH_MODE 953 - -#define FBAPI_EC_EVENT_INVALID_TIME 1000 -#define FBAPI_EC_INFO_NO_INFORMATION 1050 -#define FBAPI_EC_INFO_SET_FAILED 1051 - -#define FBAPI_EC_LIVEMESSAGE_SEND_FAILED 1100 -#define FBAPI_EC_LIVEMESSAGE_EVENT_NAME_TOO_LONG 1101 -#define FBAPI_EC_LIVEMESSAGE_MESSAGE_TOO_LONG 1102 - -#define FBAPI_EC_PAGES_CREATE 1201 - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -NSMutableArray* FBCreateNonRetainingArray(); - -BOOL FBIsDeviceIPad(); diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnectGlobal.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnectGlobal.m deleted file mode 100644 index 77ec5ca4..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBConnectGlobal.m +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBConnectGlobal.h" - -const NSString* kFB_SDK_VersionNumber = @"iphone/1.3.0"; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// private - -const void* RetainNoOp(CFAllocatorRef allocator, const void *value) { return value; } -void ReleaseNoOp(CFAllocatorRef allocator, const void *value) { } - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// public - -NSMutableArray* FBCreateNonRetainingArray() { - CFArrayCallBacks callbacks = kCFTypeArrayCallBacks; - callbacks.retain = RetainNoOp; - callbacks.release = ReleaseNoOp; - return (NSMutableArray*)CFArrayCreateMutable(nil, 0, &callbacks); -} - - -BOOL FBIsDeviceIPad() { -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200 - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - return YES; - } -#endif - return NO; -} diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.h index 097547bc..70bae3ac 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.h +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.h @@ -1,10 +1,10 @@ /* - * Copyright 2009 Facebook + * Copyright 2010 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software @@ -14,14 +14,21 @@ * limitations under the License. */ -#import "FBConnectGlobal.h" +#import +#import @protocol FBDialogDelegate; -@class FBSession; + +/** + * Do not use this interface directly, instead, use dialog in Facebook.h + * + * Facebook dialog interface for start the facebook webView UIServer Dialog. + */ @interface FBDialog : UIView { id _delegate; - FBSession* _session; + NSMutableDictionary *_params; + NSString * _serverURL; NSURL* _loadingURL; UIWebView* _webView; UIActivityIndicatorView* _spinner; @@ -30,6 +37,9 @@ UIButton* _closeButton; UIDeviceOrientation _orientation; BOOL _showingKeyboard; + + // Ensures that UI elements behind the dialog are disabled. + UIView* _modalBackgroundView; } /** @@ -38,19 +48,20 @@ @property(nonatomic,assign) id delegate; /** - * The session for which the login is taking place. + * The parameters. */ -@property(nonatomic,assign) FBSession* session; +@property(nonatomic, retain) NSMutableDictionary* params; /** - * The title that is shown in the header atop the view; + * The title that is shown in the header atop the view. */ @property(nonatomic,copy) NSString* title; -/** - * Creates the view but does not display it. - */ -- (id)initWithSession:(FBSession*)session; +- (NSString *) getStringFromUrl: (NSString*) url needle:(NSString *) needle; + +- (id)initWithURL: (NSString *) loadingURL + params: (NSMutableDictionary *) params + delegate: (id ) delegate; /** * Displays the view with an animation. @@ -69,8 +80,8 @@ /** * Displays a URL in the dialog. */ -- (void)loadURL:(NSString*)url method:(NSString*)method get:(NSDictionary*)getParams - post:(NSDictionary*)postParams; +- (void)loadURL:(NSString*)url + get:(NSDictionary*)getParams; /** * Hides the view and notifies delegates of success or cancellation. @@ -97,15 +108,21 @@ * * Implementations must call dismissWithSuccess:YES at some point to hide the dialog. */ -- (void)dialogDidSucceed:(NSURL*)url; +- (void)dialogDidSucceed:(NSURL *)url; -- (void)bounce2AnimationStopped; -- (void)keyboardWillShow:(NSNotification*)notification; -- (void)keyboardWillHide:(NSNotification*)notification; +/** + * Subclasses should override to process data returned from the server in a 'fbconnect' url. + * + * Implementations must call dismissWithSuccess:YES at some point to hide the dialog. + */ +- (void)dialogDidCancel:(NSURL *)url; @end /////////////////////////////////////////////////////////////////////////////////////////////////// +/* + *Your application should implement this delegate + */ @protocol FBDialogDelegate @optional @@ -113,28 +130,38 @@ /** * Called when the dialog succeeds and is about to be dismissed. */ -- (void)dialogDidSucceed:(FBDialog*)dialog; +- (void)dialogDidComplete:(FBDialog *)dialog; + +/** + * Called when the dialog succeeds with a returning url. + */ +- (void)dialogCompleteWithUrl:(NSURL *)url; + +/** + * Called when the dialog get canceled by the user. + */ +- (void)dialogDidNotCompleteWithUrl:(NSURL *)url; /** * Called when the dialog is cancelled and is about to be dismissed. */ -- (void)dialogDidCancel:(FBDialog*)dialog; +- (void)dialogDidNotComplete:(FBDialog *)dialog; /** * Called when dialog failed to load due to an error. */ -- (void)dialog:(FBDialog*)dialog didFailWithError:(NSError*)error; +- (void)dialog:(FBDialog*)dialog didFailWithError:(NSError *)error; /** * Asks if a link touched by a user should be opened in an external browser. * - * If a user touches a link, the default behavior is to open the link in the Safari browser, + * If a user touches a link, the default behavior is to open the link in the Safari browser, * which will cause your app to quit. You may want to prevent this from happening, open the link * in your own internal browser, or perhaps warn the user that they are about to leave your app. * If so, implement this method on your delegate and return NO. If you warn the user, you * should hold onto the URL and once you have received their acknowledgement open the URL yourself * using [[UIApplication sharedApplication] openURL:]. */ -- (BOOL)dialog:(FBDialog*)dialog shouldOpenURLInExternalBrowser:(NSURL*)url; +- (BOOL)dialog:(FBDialog*)dialog shouldOpenURLInExternalBrowser:(NSURL *)url; @end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.m index 1aaed9f4..40455fa7 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.m +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBDialog.m @@ -1,5 +1,5 @@ /* - * Copyright 2009 Facebook + * Copyright 2010 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ + #import "FBDialog.h" -#import "FBSession.h" +#import "Facebook.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // global static NSString* kDefaultTitle = @"Connect to Facebook"; -static NSString* kStringBoundary = @"3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f"; static CGFloat kFacebookBlue[4] = {0.42578125, 0.515625, 0.703125, 1.0}; static CGFloat kBorderGray[4] = {0.3, 0.3, 0.3, 0.8}; @@ -37,9 +37,21 @@ /////////////////////////////////////////////////////////////////////////////////////////////////// +BOOL FBIsDeviceIPad() { +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200 + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + return YES; + } +#endif + return NO; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////// + @implementation FBDialog -@synthesize session = _session, delegate = _delegate; +@synthesize delegate = _delegate, + params = _params; /////////////////////////////////////////////////////////////////////////////////////////////////// // private @@ -57,7 +69,7 @@ - (void)addRoundedRectToPath:(CGContextRef)context rect:(CGRect)rect radius:(flo CGContextScaleCTM(context, radius, radius); float fw = CGRectGetWidth(rect) / radius; float fh = CGRectGetHeight(rect) / radius; - + CGContextMoveToPoint(context, fw, fh/2); CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); @@ -84,7 +96,7 @@ - (void)drawRect:(CGRect)rect fill:(const CGFloat*)fillColors radius:(CGFloat)ra } CGContextRestoreGState(context); } - + CGColorSpaceRelease(space); } @@ -96,28 +108,28 @@ - (void)strokeLines:(CGRect)rect stroke:(const CGFloat*)strokeColor { CGContextSetStrokeColorSpace(context, space); CGContextSetStrokeColor(context, strokeColor); CGContextSetLineWidth(context, 1.0); - + { - CGPoint points[] = {rect.origin.x+0.5, rect.origin.y-0.5, - rect.origin.x+rect.size.width, rect.origin.y-0.5}; + CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y-0.5}, + {rect.origin.x+rect.size.width, rect.origin.y-0.5}}; CGContextStrokeLineSegments(context, points, 2); } { - CGPoint points[] = {rect.origin.x+0.5, rect.origin.y+rect.size.height-0.5, - rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height-0.5}; + CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y+rect.size.height-0.5}, + {rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height-0.5}}; CGContextStrokeLineSegments(context, points, 2); } { - CGPoint points[] = {rect.origin.x+rect.size.width-0.5, rect.origin.y, - rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height}; + CGPoint points[] = {{rect.origin.x+rect.size.width-0.5, rect.origin.y}, + {rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height}}; CGContextStrokeLineSegments(context, points, 2); } { - CGPoint points[] = {rect.origin.x+0.5, rect.origin.y, - rect.origin.x+0.5, rect.origin.y+rect.size.height}; + CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y}, + {rect.origin.x+0.5, rect.origin.y+rect.size.height}}; CGContextStrokeLineSegments(context, points, 2); } - + CGContextRestoreGState(context); CGColorSpaceRelease(space); @@ -211,11 +223,17 @@ - (NSURL*)generateURL:(NSString*)baseURL params:(NSDictionary*)params { NSMutableArray* pairs = [NSMutableArray array]; for (NSString* key in params.keyEnumerator) { NSString* value = [params objectForKey:key]; - NSString* val = [value stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSString* pair = [NSString stringWithFormat:@"%@=%@", key, val]; - [pairs addObject:pair]; + NSString* escaped_value = (NSString *)CFURLCreateStringByAddingPercentEscapes( + NULL, /* allocator */ + (CFStringRef)value, + NULL, /* charactersToLeaveUnescaped */ + (CFStringRef)@"!*'();:@&=+$,/?%#[]", + kCFStringEncodingUTF8); + + [pairs addObject:[NSString stringWithFormat:@"%@=%@", key, escaped_value]]; + [escaped_value release]; } - + NSString* query = [pairs componentsJoinedByString:@"&"]; NSString* url = [NSString stringWithFormat:@"%@?%@", baseURL, query]; return [NSURL URLWithString:url]; @@ -224,28 +242,6 @@ - (NSURL*)generateURL:(NSString*)baseURL params:(NSDictionary*)params { } } -- (NSMutableData*)generatePostBody:(NSDictionary*)params { - if (!params) { - return nil; - } - - NSMutableData* body = [NSMutableData data]; - NSString* endLine = [NSString stringWithFormat:@"\r\n--%@\r\n", kStringBoundary]; - - [body appendData:[[NSString stringWithFormat:@"--%@\r\n", kStringBoundary] - dataUsingEncoding:NSUTF8StringEncoding]]; - - for (id key in [params keyEnumerator]) { - [body appendData:[[NSString - stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n", key] - dataUsingEncoding:NSUTF8StringEncoding]]; - [body appendData:[[params valueForKey:key] dataUsingEncoding:NSUTF8StringEncoding]]; - [body appendData:[endLine dataUsingEncoding:NSUTF8StringEncoding]]; - } - - return body; -} - - (void)addObservers { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) @@ -268,6 +264,7 @@ - (void)removeObservers { - (void)postDismissCleanup { [self removeObservers]; [self removeFromSuperview]; + [_modalBackgroundView removeFromSuperview]; } - (void)dismiss:(BOOL)animated { @@ -275,7 +272,7 @@ - (void)dismiss:(BOOL)animated { [_loadingURL release]; _loadingURL = nil; - + if (animated) { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:kTransitionDuration]; @@ -289,37 +286,30 @@ - (void)dismiss:(BOOL)animated { } - (void)cancel { - [self dismissWithSuccess:NO animated:YES]; + [self dialogDidCancel:nil]; } /////////////////////////////////////////////////////////////////////////////////////////////////// // NSObject - (id)init { - return [self initWithSession:[FBSession session]]; -} - -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -- (id)initWithSession:(FBSession*)session { if (self = [super initWithFrame:CGRectZero]) { _delegate = nil; - _session = [session retain]; _loadingURL = nil; _orientation = UIDeviceOrientationUnknown; _showingKeyboard = NO; - + self.backgroundColor = [UIColor clearColor]; self.autoresizesSubviews = YES; self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.contentMode = UIViewContentModeRedraw; - - UIImage* iconImage = [UIImage imageNamed:@"FBConnect.bundle/images/fbicon.png"]; - UIImage* closeImage = [UIImage imageNamed:@"FBConnect.bundle/images/close.png"]; - + + UIImage* iconImage = [UIImage imageNamed:@"FBDialog.bundle/images/fbicon.png"]; + UIImage* closeImage = [UIImage imageNamed:@"FBDialog.bundle/images/close.png"]; + _iconView = [[UIImageView alloc] initWithImage:iconImage]; [self addSubview:_iconView]; - + UIColor* color = [UIColor colorWithRed:167.0/255 green:184.0/255 blue:216.0/255 alpha:1]; _closeButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; [_closeButton setImage:closeImage forState:UIControlStateNormal]; @@ -327,16 +317,19 @@ - (id)initWithSession:(FBSession*)session { [_closeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; [_closeButton addTarget:self action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside]; - if ([_closeButton respondsToSelector:@selector(titleLabel)]) { - _closeButton.titleLabel.font = [UIFont boldSystemFontOfSize:12]; - } else { // This triggers a deprecation warning but at least it will work on OS 2.x - _closeButton.font = [UIFont boldSystemFontOfSize:12]; - } - _closeButton.showsTouchWhenHighlighted = YES; + + // To be compatible with OS 2.x + #if __IPHONE_OS_VERSION_MAX_ALLOWED <= __IPHONE_2_2 + _closeButton.font = [UIFont boldSystemFontOfSize:12]; + #else + _closeButton.titleLabel.font = [UIFont boldSystemFontOfSize:12]; + #endif + + _closeButton.showsTouchWhenHighlighted = YES; _closeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin; [self addSubview:_closeButton]; - + CGFloat titleLabelFontSize = (FBIsDeviceIPad() ? 18 : 14); _titleLabel = [[UILabel alloc] initWithFrame:CGRectZero]; _titleLabel.text = kDefaultTitle; @@ -346,8 +339,8 @@ - (id)initWithSession:(FBSession*)session { _titleLabel.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; [self addSubview:_titleLabel]; - - _webView = [[UIWebView alloc] initWithFrame:CGRectZero]; + + _webView = [[UIWebView alloc] initWithFrame:CGRectMake(kPadding, kPadding, 480, 480)]; _webView.delegate = self; _webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self addSubview:_webView]; @@ -358,6 +351,7 @@ - (id)initWithSession:(FBSession*)session { UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; [self addSubview:_spinner]; + _modalBackgroundView = [[UIView alloc] init]; } return self; } @@ -365,12 +359,14 @@ - (id)initWithSession:(FBSession*)session { - (void)dealloc { _webView.delegate = nil; [_webView release]; + [_params release]; + [_serverURL release]; [_spinner release]; [_titleLabel release]; [_iconView release]; [_closeButton release]; [_loadingURL release]; - [_session release]; + [_modalBackgroundView release]; [super dealloc]; } @@ -399,9 +395,20 @@ - (void)drawRect:(CGRect)rect { - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL* url = request.URL; + if ([url.scheme isEqualToString:@"fbconnect"]) { - if ([url.resourceSpecifier isEqualToString:@"cancel"]) { - [self dismissWithSuccess:NO animated:YES]; + if ([[url.resourceSpecifier substringToIndex:8] isEqualToString:@"//cancel"]) { + NSString * errorCode = [self getStringFromUrl:[url absoluteString] needle:@"error_code="]; + NSString * errorStr = [self getStringFromUrl:[url absoluteString] needle:@"error_msg="]; + if (errorCode) { + NSDictionary * errorData = [NSDictionary dictionaryWithObject:errorStr forKey:@"error_msg"]; + NSError * error = [NSError errorWithDomain:@"facebookErrDomain" + code:[errorCode intValue] + userInfo:errorData]; + [self dismissWithError:error animated:YES]; + } else { + [self dialogDidCancel:url]; + } } else { [self dialogDidSucceed:url]; } @@ -414,7 +421,7 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) return NO; } } - + [[UIApplication sharedApplication] openURL:request.URL]; return NO; } else { @@ -425,7 +432,7 @@ - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *) - (void)webViewDidFinishLoad:(UIWebView *)webView { [_spinner stopAnimating]; _spinner.hidden = YES; - + self.title = [_webView stringByEvaluatingJavaScriptFromString:@"document.title"]; [self updateWebOrientation]; } @@ -457,8 +464,11 @@ - (void)deviceOrientationDidChange:(void*)object { // UIKeyboardNotifications - (void)keyboardWillShow:(NSNotification*)notification { + + _showingKeyboard = YES; + if (FBIsDeviceIPad()) { - // On the iPad the screen is large enough that we don't need to + // On the iPad the screen is large enough that we don't need to // resize the dialog to accomodate the keyboard popping up return; } @@ -469,11 +479,11 @@ - (void)keyboardWillShow:(NSNotification*)notification { -(kPadding + kBorderWidth), -(kPadding + kBorderWidth) - _titleLabel.frame.size.height); } - - _showingKeyboard = YES; } - (void)keyboardWillHide:(NSNotification*)notification { + _showingKeyboard = NO; + if (FBIsDeviceIPad()) { return; } @@ -483,13 +493,41 @@ - (void)keyboardWillHide:(NSNotification*)notification { kPadding + kBorderWidth, kPadding + kBorderWidth + _titleLabel.frame.size.height); } - - _showingKeyboard = NO; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////////////////////// // public +/** + * Find a specific parameter from the url + */ +- (NSString *) getStringFromUrl: (NSString*) url needle:(NSString *) needle { + NSString * str = nil; + NSRange start = [url rangeOfString:needle]; + if (start.location != NSNotFound) { + NSRange end = [[url substringFromIndex:start.location+start.length] rangeOfString:@"&"]; + NSUInteger offset = start.location+start.length; + str = end.location == NSNotFound + ? [url substringFromIndex:offset] + : [url substringWithRange:NSMakeRange(offset, end.location)]; + str = [str stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + } + + return str; +} + +- (id)initWithURL: (NSString *) serverURL + params: (NSMutableDictionary *) params + delegate: (id ) delegate { + + self = [self init]; + _serverURL = [serverURL retain]; + _params = [params retain]; + _delegate = delegate; + + return self; +} + - (NSString*)title { return _titleLabel.text; } @@ -498,11 +536,24 @@ - (void)setTitle:(NSString*)title { _titleLabel.text = title; } +- (void)load { + [self loadURL:_serverURL get:_params]; +} + +- (void)loadURL:(NSString*)url get:(NSDictionary*)getParams { + + [_loadingURL release]; + _loadingURL = [[self generateURL:url params:getParams] retain]; + NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:_loadingURL]; + + [_webView loadRequest:request]; +} + - (void)show { [self load]; [self sizeToFitOrientation:NO]; - CGFloat innerWidth = self.frame.size.width - (kBorderWidth+1)*2; + CGFloat innerWidth = self.frame.size.width - (kBorderWidth+1)*2; [_iconView sizeToFit]; [_titleLabel sizeToFit]; [_closeButton sizeToFit]; @@ -512,7 +563,7 @@ - (void)show { kBorderWidth, innerWidth - (_titleLabel.frame.size.height + _iconView.frame.size.width + kTitleMarginX*2), _titleLabel.frame.size.height + kTitleMarginY*2); - + _iconView.frame = CGRectMake( kBorderWidth + kTitleMarginX, kBorderWidth + floor(_titleLabel.frame.size.height/2 - _iconView.frame.size.height/2), @@ -524,7 +575,7 @@ - (void)show { kBorderWidth, _titleLabel.frame.size.height, _titleLabel.frame.size.height); - + _webView.frame = CGRectMake( kBorderWidth+1, kBorderWidth + _titleLabel.frame.size.height, @@ -539,10 +590,15 @@ - (void)show { if (!window) { window = [[UIApplication sharedApplication].windows objectAtIndex:0]; } + + _modalBackgroundView.frame = window.frame; + [_modalBackgroundView addSubview:self]; + [window addSubview:_modalBackgroundView]; + [window addSubview:self]; [self dialogWillAppear]; - + self.transform = CGAffineTransformScale([self transformForOrientation], 0.001, 0.001); [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:kTransitionDuration/1.5]; @@ -556,12 +612,12 @@ - (void)show { - (void)dismissWithSuccess:(BOOL)success animated:(BOOL)animated { if (success) { - if ([_delegate respondsToSelector:@selector(dialogDidSucceed:)]) { - [_delegate dialogDidSucceed:self]; + if ([_delegate respondsToSelector:@selector(dialogDidComplete:)]) { + [_delegate dialogDidComplete:self]; } } else { - if ([_delegate respondsToSelector:@selector(dialogDidCancel:)]) { - [_delegate dialogDidCancel:self]; + if ([_delegate respondsToSelector:@selector(dialogDidNotComplete:)]) { + [_delegate dialogDidNotComplete:self]; } } @@ -576,53 +632,25 @@ - (void)dismissWithError:(NSError*)error animated:(BOOL)animated { [self dismiss:animated]; } -- (void)load { - // Intended for subclasses to override -} - -- (void)loadURL:(NSString*)url method:(NSString*)method get:(NSDictionary*)getParams - post:(NSDictionary*)postParams { - // This "test cookie" is required by login.php, or it complains that you need to enable JavaScript - NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage]; - NSHTTPCookie* testCookie = [NSHTTPCookie cookieWithProperties: - [NSDictionary dictionaryWithObjectsAndKeys: - @"1", NSHTTPCookieValue, - @"test_cookie", NSHTTPCookieName, - @".facebook.com", NSHTTPCookieDomain, - @"/", NSHTTPCookiePath, - nil]]; - [cookies setCookie:testCookie]; - - [_loadingURL release]; - _loadingURL = [[self generateURL:url params:getParams] retain]; - NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:_loadingURL]; - - if (method) { - [request setHTTPMethod:method]; - - if ([[method uppercaseString] isEqualToString:@"POST"]) { - NSString* contentType = [NSString - stringWithFormat:@"multipart/form-data; boundary=%@", kStringBoundary]; - [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; - - NSData* body = [self generatePostBody:postParams]; - if (body) { - [request setHTTPBody:body]; - } - } - } - - [_webView loadRequest:request]; -} - - (void)dialogWillAppear { } - (void)dialogWillDisappear { } -- (void)dialogDidSucceed:(NSURL*)url { +- (void)dialogDidSucceed:(NSURL *)url { + + if ([_delegate respondsToSelector:@selector(dialogCompleteWithUrl:)]) { + [_delegate dialogCompleteWithUrl:url]; + } [self dismissWithSuccess:YES animated:YES]; } +- (void)dialogDidCancel:(NSURL *)url { + if ([_delegate respondsToSelector:@selector(dialogDidNotCompleteWithUrl:)]) { + [_delegate dialogDidNotCompleteWithUrl:url]; + } + [self dismissWithSuccess:NO animated:YES]; +} + @end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.h deleted file mode 100644 index 50ba0f61..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBDialog.h" - -@interface FBFeedDialog : FBDialog { - long long _templateBundleId; - NSString* _templateData; - NSString* _bodyGeneral; -} - -/** - * The id for a previously registered template bundle. - */ -@property(nonatomic) long long templateBundleId; - -/** - * A JSON string containing template data. - * - * See http://wiki.developers.facebook.com/index.php/Template_Data - */ -@property(nonatomic,copy) NSString* templateData; - -/** - * Additional markup for a short story. - */ -@property(nonatomic,copy) NSString* bodyGeneral; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.m deleted file mode 100644 index cc310fef..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBFeedDialog.m +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBFeedDialog.h" -#import "FBSession.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// global - -static NSString* kFeedURL = @"http://www.facebook.com/connect/prompt_feed.php"; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@implementation FBFeedDialog - -@synthesize templateBundleId = _templateBundleId, templateData = _templateData, - bodyGeneral = _bodyGeneral; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// private - -- (NSString*)generateFeedInfo { - NSMutableArray* pairs = [NSMutableArray array]; - - if (_templateBundleId) { - [pairs addObject:[NSString stringWithFormat:@"\"template_id\": %lld", _templateBundleId]]; - } - if (_templateData) { - [pairs addObject:[NSString stringWithFormat:@"\"template_data\": %@", _templateData]]; - } - if (_bodyGeneral) { - [pairs addObject:[NSString stringWithFormat:@"\"body_general\": \"%@\"", _bodyGeneral]]; - } - - return [NSString stringWithFormat:@"{%@}", [pairs componentsJoinedByString:@","]]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)initWithSession:(FBSession*)session { - if (self = [super initWithSession:session]) { - _templateBundleId = 0; - _templateData = nil; - _bodyGeneral = nil; - } - return self; -} - -- (void)dealloc { - [_templateData release]; - [_bodyGeneral release]; - [super dealloc]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// FBDialog - -- (void)load { - NSDictionary* getParams = [NSDictionary dictionaryWithObjectsAndKeys: - @"touch", @"display", nil]; - - NSString* feedInfo = [self generateFeedInfo]; - NSDictionary* postParams = [NSDictionary dictionaryWithObjectsAndKeys: - _session.apiKey, @"api_key", _session.sessionKey, @"session_key", - @"1", @"preview", @"fbconnect:success", @"callback", @"fbconnect:cancel", @"cancel", - feedInfo, @"feed_info", @"self_feed", @"feed_target_type", nil]; - - [self loadURL:kFeedURL method:@"POST" get:getParams post:postParams]; -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.h deleted file mode 100644 index 4f98f4f5..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBSession.h" - -typedef enum { - FBLoginButtonStyleNormal, - FBLoginButtonStyleWide, -} FBLoginButtonStyle; - -/** - * Standard button which lets the user log in or out of the session. - * - * The button will automatically change to reflect the state of the session, showing - * "login" if the session is not connected, and "logout" if the session is connected. - */ -@interface FBLoginButton : UIControl { - FBLoginButtonStyle _style; - FBSession* _session; - UIImageView* _imageView; -} - -/** - * The visual style of the button. - */ -@property(nonatomic) FBLoginButtonStyle style; - -/** - * The session object that the button will log in and out of. - * - * The default value is the global session singleton, so there is usually no need to - * set this property yourself. - */ -@property(nonatomic,retain) FBSession* session; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.m deleted file mode 100644 index 06b5818b..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginButton.m +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBLoginButton.h" -#import "FBLoginDialog.h" - -#import - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -static UIAccessibilityTraits *traitImage = nil, *traitButton = nil; - -@implementation FBLoginButton - -@synthesize session = _session, style = _style; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// private - -+ (void)initialize { - if (self == [FBLoginButton class]) { - // Try to load the accessibility trait values on OS 3.0 - traitImage = dlsym(RTLD_SELF, "UIAccessibilityTraitImage"); - traitButton = dlsym(RTLD_SELF, "UIAccessibilityTraitButton"); - } -} - -- (UIImage*)buttonImage { - if (_session.isConnected) { - return [UIImage imageNamed:@"FBConnect.bundle/images/logout.png"]; - } else { - if (_style == FBLoginButtonStyleNormal) { - return [UIImage imageNamed:@"FBConnect.bundle/images/login.png"]; - } else if (_style == FBLoginButtonStyleWide) { - return [UIImage imageNamed:@"FBConnect.bundle/images/login2.png"]; - } else { - return nil; - } - } -} - -- (UIImage*)buttonHighlightedImage { - if (_session.isConnected) { - return [UIImage imageNamed:@"FBConnect.bundle/images/logout_down.png"]; - } else { - if (_style == FBLoginButtonStyleNormal) { - return [UIImage imageNamed:@"FBConnect.bundle/images/login_down.png"]; - } else if (_style == FBLoginButtonStyleWide) { - return [UIImage imageNamed:@"FBConnect.bundle/images/login2_down.png"]; - } else { - return nil; - } - } -} - -- (void)updateImage { - if (self.highlighted) { - _imageView.image = [self buttonHighlightedImage]; - } else { - _imageView.image = [self buttonImage]; - } -} - -- (void)touchUpInside { - if (_session.isConnected) { - [_session logout]; - } else { - FBLoginDialog* dialog = [[[FBLoginDialog alloc] initWithSession:_session] autorelease]; - [dialog show]; - } -} - -- (void)initButton { - _style = FBLoginButtonStyleNormal; - - _imageView = [[UIImageView alloc] initWithFrame:CGRectZero]; - _imageView.contentMode = UIViewContentModeCenter; - [self addSubview:_imageView]; - - self.backgroundColor = [UIColor clearColor]; - [self addTarget:self action:@selector(touchUpInside) - forControlEvents:UIControlEventTouchUpInside]; - - self.session = [FBSession session]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { - [self initButton]; - if (CGRectIsEmpty(frame)) { - [self sizeToFit]; - } - } - return self; -} - -- (void)awakeFromNib { - [self initButton]; -} - -- (void)dealloc { - [_session.delegates removeObject:self]; - [_session release]; - [_imageView release]; - [super dealloc]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// UIView - -- (CGSize)sizeThatFits:(CGSize)size { - return _imageView.image.size; -} - -- (void)layoutSubviews { - _imageView.frame = self.bounds; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// UIControl - -- (void)setHighlighted:(BOOL)highlighted { - [super setHighlighted:highlighted]; - [self updateImage]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// FBSessionDelegate - -- (void)session:(FBSession*)session didLogin:(FBUID)uid { - [self updateImage]; -} - -- (void)sessionDidLogout:(FBSession*)session { - [self updateImage]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// UIAccessibility informal protocol (on 3.0 only) - -- (BOOL)isAccessibilityElement { - return YES; -} - -- (UIAccessibilityTraits)accessibilityTraits { - if (traitImage && traitButton) - return [super accessibilityTraits]|*traitImage|*traitButton; - else - return [super accessibilityTraits]; -} - -- (NSString *)accessibilityLabel { - if (_session.isConnected) { - return NSLocalizedString(@"Disconnect from Facebook", @"Accessibility label"); - } else { - return NSLocalizedString(@"Connect to Facebook", @"Accessibility label"); - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// public - -- (void)setSession:(FBSession*)session { - if (session != _session) { - [_session.delegates removeObject:self]; - [_session release]; - _session = [session retain]; - [_session.delegates addObject:self]; - - [self updateImage]; - } -} - -- (void)setStyle:(FBLoginButtonStyle)style { - _style = style; - - [self updateImage]; -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.h index 8eb0b908..f5c6ebae 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.h +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.h @@ -1,10 +1,10 @@ /* - * Copyright 2009 Facebook + * Copyright 2010 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software @@ -12,13 +12,37 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. -*/ + */ + #import "FBDialog.h" -#import "FBRequest.h" -@interface FBLoginDialog : FBDialog { - FBRequest* _getSessionRequest; +@protocol FBLoginDialogDelegate; + +/** + * Do not use this interface directly, instead, use authorize in Facebook.h + * + * Facebook Login Dialog interface for start the facebook webView login dialog. + * It start pop-ups prompting for credentials and permissions. + */ + +@interface FBLoginDialog : FBDialog { + id _loginDelegate; } +-(id) initWithURL:(NSString *) loginURL + loginParams:(NSMutableDictionary *) params + delegate:(id ) delegate; @end + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +@protocol FBLoginDialogDelegate + +- (void)fbDialogLogin:(NSString*)token expirationDate:(NSDate*)expirationDate; + +- (void)fbDialogNotLogin:(BOOL)cancelled; + +@end + + diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.m index 9d49f603..70552bf8 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.m +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBLoginDialog.m @@ -1,131 +1,94 @@ /* - * Copyright 2009 Facebook + * Copyright 2010 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 - + * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. -*/ + */ +#import "FBDialog.h" #import "FBLoginDialog.h" -#import "FBSession.h" -#import "FBRequest.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// global - -static NSString* kLoginURL = @"http://www.facebook.com/login.php"; /////////////////////////////////////////////////////////////////////////////////////////////////// @implementation FBLoginDialog /////////////////////////////////////////////////////////////////////////////////////////////////// -// private +// public -- (void)connectToGetSession:(NSString*)token { - _getSessionRequest = [[FBRequest requestWithSession:_session delegate:self] retain]; - NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObject:token forKey:@"auth_token"]; - if (!_session.apiSecret) { - [params setObject:@"1" forKey:@"generate_session_secret"]; - } +/* + * initialize the FBLoginDialog with url and parameters + */ +- (id)initWithURL:(NSString*) loginURL + loginParams:(NSMutableDictionary*) params + delegate:(id ) delegate{ - if (_session.getSessionProxy) { - [_getSessionRequest post:_session.getSessionProxy params:params]; - } else { - [_getSessionRequest call:@"facebook.auth.getSession" params:params]; - } -} - -- (void)loadLoginPage { - NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys: - @"1", @"fbconnect", @"touch", @"connect_display", _session.apiKey, @"api_key", - @"fbconnect://success", @"next", nil]; - - [self loadURL:kLoginURL method:@"GET" get:params post:nil]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)initWithSession:(FBSession*)session { - if (self = [super initWithSession:session]) { - _getSessionRequest = nil; - } + self = [super init]; + _serverURL = [loginURL retain]; + _params = [params retain]; + _loginDelegate = delegate; return self; } -- (void)dealloc { - _getSessionRequest.delegate = nil; - [_getSessionRequest release]; - [super dealloc]; -} - /////////////////////////////////////////////////////////////////////////////////////////////////// // FBDialog -- (void)load { - [self loadLoginPage]; -} - -- (void)dialogWillDisappear { - [_webView stringByEvaluatingJavaScriptFromString:@"email.blur();"]; - - [_getSessionRequest cancel]; +/** + * Override FBDialog : to call when the webView Dialog did succeed + */ +- (void) dialogDidSucceed:(NSURL*)url { + NSString *q = [url absoluteString]; + NSString *token = [self getStringFromUrl:q needle:@"access_token="]; + NSString *expTime = [self getStringFromUrl:q needle:@"expires_in="]; + NSDate *expirationDate =nil; - if (![_session isConnected]) { - [_session cancelLogin]; + if (expTime != nil) { + int expVal = [expTime intValue]; + if (expVal == 0) { + expirationDate = [NSDate distantFuture]; + } else { + expirationDate = [NSDate dateWithTimeIntervalSinceNow:expVal]; + } + } + + if ((token == (NSString *) [NSNull null]) || (token.length == 0)) { + [self dialogDidCancel:url]; + [self dismissWithSuccess:NO animated:YES]; + } else { + if ([_loginDelegate respondsToSelector:@selector(fbDialogLogin:expirationDate:)]) { + [_loginDelegate fbDialogLogin:token expirationDate:expirationDate]; + } + [self dismissWithSuccess:YES animated:YES]; } + } -- (void)dialogDidSucceed:(NSURL*)url { - NSString* q = url.query; - NSRange start = [q rangeOfString:@"auth_token="]; - if (start.location != NSNotFound) { - NSRange end = [q rangeOfString:@"&"]; - NSUInteger offset = start.location+start.length; - NSString* token = end.location == NSNotFound - ? [q substringFromIndex:offset] - : [q substringWithRange:NSMakeRange(offset, end.location-offset)]; - - if (token) { - [self connectToGetSession:token]; - } +/** + * Override FBDialog : to call with the login dialog get canceled + */ +- (void)dialogDidCancel:(NSURL *)url { + [self dismissWithSuccess:NO animated:YES]; + if ([_loginDelegate respondsToSelector:@selector(fbDialogNotLogin:)]) { + [_loginDelegate fbDialogNotLogin:YES]; } } -/////////////////////////////////////////////////////////////////////////////////////////////////// -// FBRequestDelegate - -- (void)request:(FBRequest*)request didLoad:(id)result { - NSDictionary* object = result; - FBUID uid = [[object objectForKey:@"uid"] longLongValue]; - NSString* sessionKey = [object objectForKey:@"session_key"]; - NSString* sessionSecret = [object objectForKey:@"secret"]; - NSTimeInterval expires = [[object objectForKey:@"expires"] floatValue]; - NSDate* expiration = expires ? [NSDate dateWithTimeIntervalSince1970:expires] : nil; - - [_getSessionRequest release]; - _getSessionRequest = nil; - - [_session begin:uid sessionKey:sessionKey sessionSecret:sessionSecret expires:expiration]; - [_session resume]; - - [self dismissWithSuccess:YES animated:YES]; +- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { + if (!(([error.domain isEqualToString:@"NSURLErrorDomain"] && error.code == -999) || + ([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 102))) { + [super webView:webView didFailLoadWithError:error]; + if ([_loginDelegate respondsToSelector:@selector(fbDialogNotLogin:)]) { + [_loginDelegate fbDialogNotLogin:NO]; + } + } } -- (void)request:(FBRequest*)request didFailWithError:(NSError*)error { - [_getSessionRequest release]; - _getSessionRequest = nil; - - [self dismissWithError:error animated:YES]; -} - @end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.h deleted file mode 100644 index d203ddbe..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBLoginDialog.h" - -@interface FBPermissionDialog : FBLoginDialog { - NSString* _permission; - NSTimer* _redirectTimer; -} - -/** - * The extended permission to request. - * - * See http://wiki.developers.facebook.com/index.php/Extended_permissions - */ -@property(nonatomic,copy) NSString* permission; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.m deleted file mode 100644 index f604ef6e..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBPermissionDialog.m +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBPermissionDialog.h" -#import "FBSession.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// global - -static NSString* kPermissionURL = @"http://www.facebook.com/connect/prompt_permission.php"; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@implementation FBPermissionDialog - -@synthesize permission = _permission; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// private - -- (void)redirectToLoginDelayed { - _redirectTimer = nil; - - // This loads the login page, which will just redirect back to the callback url - // since the login cookies are set - [super load]; -} - -- (void)redirectToLogin { - _redirectTimer = [NSTimer scheduledTimerWithTimeInterval:0.01 target:self - selector:@selector(redirectToLoginDelayed) userInfo:nil repeats:NO]; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)initWithSession:(FBSession*)session { - if (self = [super initWithSession:session]) { - _permission = nil; - _redirectTimer = nil; - } - return self; -} - -- (void)dealloc { - [_redirectTimer invalidate]; - [_permission release]; - [super dealloc]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// FBDialog - -- (void)load { - NSDictionary* params = [NSDictionary dictionaryWithObjectsAndKeys: - @"touch", @"display", _session.apiKey, @"api_key", _session.sessionKey, @"session_key", - _permission, @"ext_perm", @"fbconnect:success", @"next", @"fbconnect:cancel", @"cancel", nil]; - - [self loadURL:kPermissionURL method:@"GET" get:params post:nil]; -} - -- (void)dialogDidSucceed:(NSURL*)url { - if ([_permission isEqualToString:@"offline_access"]) { - [super dialogDidSucceed:url]; - } else { - [self dismissWithSuccess:YES animated:YES]; - } -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// UIWebViewDelegate - -- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request - navigationType:(UIWebViewNavigationType)navigationType { - if ([_permission isEqualToString:@"offline_access"]) { - NSURL* url = request.URL; - if ([url.scheme isEqualToString:@"fbconnect"]) { - if ([url.resourceSpecifier isEqualToString:@"success"]) { - [self redirectToLogin]; - return NO; - } - } - } - return [super webView:webView shouldStartLoadWithRequest:request navigationType:navigationType]; -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.h index 75ac9e74..07ea3666 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.h +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.h @@ -1,10 +1,10 @@ /* - * Copyright 2009 Facebook + * Copyright 2010 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software @@ -12,126 +12,74 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. -*/ + */ -#import "FBConnectGlobal.h" +#import +#import @protocol FBRequestDelegate; -@class FBSession; +/** + * Do not use this interface directly, instead, use method in Facebook.h + */ @interface FBRequest : NSObject { - FBSession* _session; id _delegate; NSString* _url; - NSString* _method; - id _userInfo; + NSString* _httpMethod; NSMutableDictionary* _params; - NSObject* _dataParam; - NSDate* _timestamp; NSURLConnection* _connection; NSMutableData* _responseText; } -/** - * Creates a new API request for the global session. - */ -+ (FBRequest*)request; - -/** - * Creates a new API request for the global session with a delegate. - */ -+ (FBRequest*)requestWithDelegate:(id)delegate; - -/** - * Creates a new API request for a particular session. - */ -+ (FBRequest*)requestWithSession:(FBSession*)session; - -/** - * Creates a new API request for the global session with a delegate. - */ -+ (FBRequest*)requestWithSession:(FBSession*)session delegate:(id)delegate; @property(nonatomic,assign) id delegate; /** * The URL which will be contacted to execute the request. */ -@property(nonatomic,readonly) NSString* url; +@property(nonatomic,copy) NSString* url; /** * The API method which will be called. */ -@property(nonatomic,readonly) NSString* method; - -/** - * An object used by the user of the request to help identify the meaning of the request. - */ -@property(nonatomic,retain) id userInfo; +@property(nonatomic,copy) NSString* httpMethod; /** * The dictionary of parameters to pass to the method. * - * These values in the dictionary will be converted to strings using the + * These values in the dictionary will be converted to strings using the * standard Objective-C object-to-string conversion facilities. */ -@property(nonatomic,readonly) NSDictionary* params; - -/** - * A data parameter. - * - * Used for methods such as photos.upload, video.upload, events.create, and - * events.edit. - */ -@property(nonatomic,readonly) NSObject* dataParam; +@property(nonatomic,retain) NSMutableDictionary* params; -/** - * The timestamp of when the request was sent to the server. - */ -@property(nonatomic,readonly) NSDate* timestamp; -/** - * Indicates if the request has been sent and is awaiting a response. - */ -@property(nonatomic,readonly) BOOL loading; +@property(nonatomic,assign) NSURLConnection* connection; -/** - * Creates a new request paired to a session. - */ -- (id)initWithSession:(FBSession*)session; +@property(nonatomic,assign) NSMutableData* responseText; -/** - * Calls a method on the server asynchronously. - * - * The delegate will be called for each stage of the loading process. - */ -- (void)call:(NSString*)method params:(NSDictionary*)params; -/** - * Calls a method on the server asynchronously, with a file upload component. - * - * The delegate will be called for each stage of the loading process. - */ -- (void)call:(NSString*)method params:(NSDictionary*)params dataParam:(NSData*)dataParam; ++ (NSString*)serializeURL:(NSString *)baseUrl + params:(NSDictionary *)params; -/** - * Calls a URL on the server asynchronously. - * - * The delegate will be called for each stage of the loading process. - */ -- (void)post:(NSString*)url params:(NSDictionary*)params; ++ (NSString*)serializeURL:(NSString *)baseUrl + params:(NSDictionary *)params + httpMethod:(NSString *)httpMethod; -/** - * Stops an active request before the response has returned. - */ -- (void)cancel; ++ (FBRequest*)getRequestWithParams:(NSMutableDictionary *) params + httpMethod:(NSString *) httpMethod + delegate:(id)delegate + requestURL:(NSString *) url; +- (BOOL) loading; -- (void)connect; +- (void) connect; @end /////////////////////////////////////////////////////////////////////////////////////////////////// +/* + *Your application should implement this delegate + */ @protocol FBRequestDelegate @optional @@ -139,17 +87,17 @@ /** * Called just before the request is sent to the server. */ -- (void)requestLoading:(FBRequest*)request; +- (void)requestLoading:(FBRequest *)request; /** * Called when the server responds and begins to send back data. */ -- (void)request:(FBRequest*)request didReceiveResponse:(NSURLResponse*)response; +- (void)request:(FBRequest *)request didReceiveResponse:(NSURLResponse *)response; /** * Called when an error prevents the request from completing successfully. */ -- (void)request:(FBRequest*)request didFailWithError:(NSError*)error; +- (void)request:(FBRequest *)request didFailWithError:(NSError *)error; /** * Called when a request returns and its response has been parsed into an object. @@ -157,11 +105,14 @@ * The resulting object may be a dictionary, an array, a string, or a number, depending * on thee format of the API response. */ -- (void)request:(FBRequest*)request didLoad:(id)result; +- (void)request:(FBRequest *)request didLoad:(id)result; /** - * Called when the request was cancelled. + * Called when a request returns a response. + * + * The result object is the raw response from the server of type NSData */ -- (void)requestWasCancelled:(FBRequest*)request; +- (void)request:(FBRequest *)request didLoadRawResponse:(NSData *)data; @end + diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.m index 50dd54e5..250fba90 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.m +++ b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBRequest.m @@ -1,10 +1,10 @@ /* - * Copyright 2009 Facebook + * Copyright 2010 Facebook * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software @@ -12,20 +12,17 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. -*/ + */ #import "FBRequest.h" -#import "FBSession.h" -#import "FBXMLHandler.h" -#import +#import "JSON.h" /////////////////////////////////////////////////////////////////////////////////////////////////// // global -static NSString* kAPIVersion = @"1.0"; -static NSString* kAPIFormat = @"XML"; static NSString* kUserAgent = @"FacebookConnect"; static NSString* kStringBoundary = @"3i2ndDfv2rTHiSisAbouNdArYfORhtTPEefj3q2f"; +static const int kGeneralErrorCode = 10000; static const NSTimeInterval kTimeoutInterval = 180.0; @@ -33,281 +30,321 @@ @implementation FBRequest -@synthesize delegate = _delegate, - url = _url, - method = _method, - params = _params, - dataParam = _dataParam, - userInfo = _userInfo, - timestamp = _timestamp; +@synthesize delegate = _delegate, + url = _url, + httpMethod = _httpMethod, + params = _params, + connection = _connection, + responseText = _responseText; -/////////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////////// // class public -+ (FBRequest*)request { - return [self requestWithSession:[FBSession session]]; -} - -+ (FBRequest*)requestWithDelegate:(id)delegate { - return [self requestWithSession:[FBSession session] delegate:delegate]; -} - -+ (FBRequest*)requestWithSession:(FBSession*)session { - return [[[FBRequest alloc] initWithSession:session] autorelease]; -} - -+ (FBRequest*)requestWithSession:(FBSession*)session delegate:(id)delegate { - FBRequest* request = [[[FBRequest alloc] initWithSession:session] autorelease]; ++ (FBRequest *)getRequestWithParams:(NSMutableDictionary *) params + httpMethod:(NSString *) httpMethod + delegate:(id) delegate + requestURL:(NSString *) url { + FBRequest* request = [[[FBRequest alloc] init] autorelease]; request.delegate = delegate; + request.url = url; + request.httpMethod = httpMethod; + request.params = params; + request.connection = nil; + request.responseText = nil; + return request; } /////////////////////////////////////////////////////////////////////////////////////////////////// // private -- (NSString*)md5HexDigest:(NSString*)input { - const char* str = [input UTF8String]; - unsigned char result[CC_MD5_DIGEST_LENGTH]; - CC_MD5(str, strlen(str), result); - - NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2]; - for(int i = 0; i 0) { + for (id key in dataDictionary) { + NSObject *dataParam = [dataDictionary valueForKey:key]; + if ([dataParam isKindOfClass:[UIImage class]]) { + NSData* imageData = UIImagePNGRepresentation((UIImage*)dataParam); + [self utfAppendBody:body + data:[NSString stringWithFormat: + @"Content-Disposition: form-data; filename=\"%@\"\r\n", key]]; + [self utfAppendBody:body + data:[NSString stringWithString:@"Content-Type: image/png\r\n\r\n"]]; + [body appendData:imageData]; + } else { + NSAssert([dataParam isKindOfClass:[NSData class]], + @"dataParam must be a UIImage or NSData"); + [self utfAppendBody:body + data:[NSString stringWithFormat: + @"Content-Disposition: form-data; filename=\"%@\"\r\n", key]]; + [self utfAppendBody:body + data:[NSString stringWithString:@"Content-Type: content/unknown\r\n\r\n"]]; + [body appendData:(NSData*)dataParam]; + } + [self utfAppendBody:body data:endLine]; + } - [self utfAppendBody:body data:endLine]; } - - FBLOG2(@"Sending %s", [body bytes]); + return body; } -- (id)parseXMLResponse:(NSData*)data error:(NSError**)error { - FBXMLHandler* handler = [[[FBXMLHandler alloc] init] autorelease]; - NSXMLParser* parser = [[[NSXMLParser alloc] initWithData:data] autorelease]; - parser.delegate = handler; - [parser parse]; +/** + * Formulate the NSError + */ +- (id)formError:(NSInteger)code userInfo:(NSDictionary *) errorData { + return [NSError errorWithDomain:@"facebookErrDomain" code:code userInfo:errorData]; - if (handler.parseError) { - if (error) { - *error = [[handler.parseError retain] autorelease]; +} + +/** + * parse the response data + */ +- (id)parseJsonResponse:(NSData *)data error:(NSError **)error { + + NSString* responseString = [[[NSString alloc] initWithData:data + encoding:NSUTF8StringEncoding] + autorelease]; + SBJSON *jsonParser = [[SBJSON new] autorelease]; + if ([responseString isEqualToString:@"true"]) { + return [NSDictionary dictionaryWithObject:@"true" forKey:@"result"]; + } else if ([responseString isEqualToString:@"false"]) { + if (error != nil) { + *error = [self formError:kGeneralErrorCode + userInfo:[NSDictionary + dictionaryWithObject:@"This operation can not be completed" + forKey:@"error_msg"]]; } return nil; - } else if ([handler.rootName isEqualToString:@"error_response"]) { - NSDictionary* errorDict = handler.rootObject; - NSInteger code = [[errorDict objectForKey:@"error_code"] intValue]; - NSDictionary* info = [NSDictionary dictionaryWithObjectsAndKeys: - [errorDict objectForKey:@"error_msg"], NSLocalizedDescriptionKey, - [errorDict objectForKey:@"request_args"], @"request_args", - nil]; - if (error) { - *error = [NSError errorWithDomain:FBAPI_ERROR_DOMAIN code:code userInfo:info]; + } + + + id result = [jsonParser objectWithString:responseString]; + + if (![result isKindOfClass:[NSArray class]]) { + if ([result objectForKey:@"error"] != nil) { + if (error != nil) { + *error = [self formError:kGeneralErrorCode + userInfo:result]; + } + return nil; + } + + if ([result objectForKey:@"error_code"] != nil) { + if (error != nil) { + *error = [self formError:[[result objectForKey:@"error_code"] intValue] userInfo:result]; + } + return nil; + } + + if ([result objectForKey:@"error_msg"] != nil) { + if (error != nil) { + *error = [self formError:kGeneralErrorCode userInfo:result]; + } + } + + if ([result objectForKey:@"error_reason"] != nil) { + if (error != nil) { + *error = [self formError:kGeneralErrorCode userInfo:result]; + } } - return nil; - } else { - return [[handler.rootObject retain] autorelease]; } + + return result; + } -- (void)failWithError:(NSError*)error { +/* + * private helper function: call the delegate function when the request fail with Error + */ +- (void)failWithError:(NSError *)error { if ([_delegate respondsToSelector:@selector(request:didFailWithError:)]) { [_delegate request:self didFailWithError:error]; } } -- (void)handleResponseData:(NSData*)data { - FBLOG2(@"DATA: %s", data.bytes); - NSError* error = nil; - id result = [self parseXMLResponse:data error:&error]; - if (error) { - [self failWithError:error]; - } else if ([_delegate respondsToSelector:@selector(request:didLoad:)]) { - [_delegate request:self didLoad:result]; +/* + * private helper function: handle the response data + */ +- (void)handleResponseData:(NSData *)data { + if ([_delegate respondsToSelector:@selector(request:didLoadRawResponse:)]) { + [_delegate request:self didLoadRawResponse:data]; } + + if ([_delegate respondsToSelector:@selector(request:didLoad:)] || + [_delegate respondsToSelector:@selector(request:didFailWithError:)]) { + NSError* error = nil; + id result = [self parseJsonResponse:data error:&error]; + if (error) { + [self failWithError:error]; + } else if ([_delegate respondsToSelector:@selector(request:didLoad:)]) { + [_delegate request:self didLoad:(result == nil ? data : result)]; + } + + } + } + + +////////////////////////////////////////////////////////////////////////////////////////////////// +// public + +/** + * @return boolean - whether this request is processing + */ +- (BOOL)loading { + return !!_connection; +} + +/** + * make the Facebook request + */ - (void)connect { - FBLOG(@"Connecting to %@ %@", _url, _params); if ([_delegate respondsToSelector:@selector(requestLoading:)]) { [_delegate requestLoading:self]; } - NSString* url = _method ? _url : [self generateGetURL]; - NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] - cachePolicy:NSURLRequestReloadIgnoringLocalCacheData - timeoutInterval:kTimeoutInterval]; + NSString* url = [[self class] serializeURL:_url params:_params httpMethod:_httpMethod]; + NSMutableURLRequest* request = + [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url] + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:kTimeoutInterval]; [request setValue:kUserAgent forHTTPHeaderField:@"User-Agent"]; - - if (_method) { - [request setHTTPMethod:@"POST"]; - + + + [request setHTTPMethod:self.httpMethod]; + if ([self.httpMethod isEqualToString: @"POST"]) { NSString* contentType = [NSString - stringWithFormat:@"multipart/form-data; boundary=%@", kStringBoundary]; + stringWithFormat:@"multipart/form-data; boundary=%@", kStringBoundary]; [request setValue:contentType forHTTPHeaderField:@"Content-Type"]; [request setHTTPBody:[self generatePostBody]]; } - - _timestamp = [[NSDate date] retain]; + _connection = [[NSURLConnection alloc] initWithRequest:request delegate:self]; -} -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)initWithSession:(FBSession*)session { - _session = session; - _delegate = nil; - _url = nil; - _method = nil; - _params = nil; - _userInfo = nil; - _timestamp = nil; - _connection = nil; - _responseText = nil; - return self; } +/** + * Free internal structure + */ - (void)dealloc { [_connection cancel]; [_connection release]; [_responseText release]; [_url release]; - [_method release]; + [_httpMethod release]; [_params release]; - [_userInfo release]; - [_timestamp release]; [super dealloc]; } -- (NSString*)description { - return [NSString stringWithFormat:@"", _method ? _method : _url]; -} - ////////////////////////////////////////////////////////////////////////////////////////////////// // NSURLConnectionDelegate - -- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response { + +- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { _responseText = [[NSMutableData alloc] init]; NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response; - if ([_delegate respondsToSelector:@selector(request:didReceiveResponse:)]) { + if ([_delegate respondsToSelector:@selector(request:didReceiveResponse:)]) { [_delegate request:self didReceiveResponse:httpResponse]; } } --(void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data { +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [_responseText appendData:data]; } -- (NSCachedURLResponse*)connection:(NSURLConnection*)connection +- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse*)cachedResponse { return nil; } --(void)connectionDidFinishLoading:(NSURLConnection*)connection { +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { [self handleResponseData:_responseText]; - + [_responseText release]; _responseText = nil; [_connection release]; _connection = nil; } -- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error { +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { [self failWithError:error]; [_responseText release]; @@ -316,63 +353,4 @@ - (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error _connection = nil; } -////////////////////////////////////////////////////////////////////////////////////////////////// -// public - -- (BOOL)loading { - return !!_connection; -} - -- (void)call:(NSString*)method params:(NSDictionary*)params { - [self call:method params:params dataParam:nil]; -} - -- (void)call:(NSString*)method params:(NSDictionary*)params dataParam:(NSData*)dataParam { - _url = [[self urlForMethod:method] retain]; - _method = [method copy]; - _params = params - ? [[NSMutableDictionary alloc] initWithDictionary:params] - : [[NSMutableDictionary alloc] init]; - _dataParam = dataParam; - - [_params setObject:_method forKey:@"method"]; - [_params setObject:_session.apiKey forKey:@"api_key"]; - [_params setObject:kAPIVersion forKey:@"v"]; - [_params setObject:kAPIFormat forKey:@"format"]; - - if (![self isSpecialMethod]) { - [_params setObject:_session.sessionKey forKey:@"session_key"]; - [_params setObject:[self generateCallId] forKey:@"call_id"]; - - if (_session.sessionSecret) { - [_params setObject:@"1" forKey:@"ss"]; - } - } - - [_params setObject:[self generateSig] forKey:@"sig"]; - - [_session send:self]; -} - -- (void)post:(NSString*)url params:(NSDictionary*)params { - _url = [url retain]; - _params = params - ? [[NSMutableDictionary alloc] initWithDictionary:params] - : [[NSMutableDictionary alloc] init]; - - [_session send:self]; -} - -- (void)cancel { - if (_connection) { - [_connection cancel]; - [_connection release]; - _connection = nil; - - if ([_delegate respondsToSelector:@selector(requestWasCancelled:)]) { - [_delegate requestWasCancelled:self]; - } - } -} - @end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.h deleted file mode 100644 index 15c77f50..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBConnectGlobal.h" - -@protocol FBSessionDelegate; -@class FBRequest; - -/** - * An FBSession represents a single user's authenticated session for a Facebook application. - * - * To create a session, you must use the session key of your application (which can - * be found on the Facebook developer website). You may then use the login dialog to ask - * the user to enter their email address and password. If successful, you will get back a - * session key which can be used to make requests to the Facebook API. - * - * Session keys are cached and stored on the disk of the device so that you do not need to ask - * the user to login every time they launch the app. To restore the last active session, call the - * resume method after instantiating your session. - */ -@interface FBSession : NSObject { - NSMutableArray* _delegates; - NSString* _apiKey; - NSString* _apiSecret; - NSString* _getSessionProxy; - FBUID _uid; - NSString* _sessionKey; - NSString* _sessionSecret; - NSDate* _expirationDate; - NSMutableArray* _requestQueue; - NSDate* _lastRequestTime; - int _requestBurstCount; - NSTimer* _requestTimer; -} - -/** - * Delegates which implement FBSessionDelegate. - */ -@property(nonatomic,readonly) NSMutableArray* delegates; - -/** - * The URL used for API HTTP requests. - */ -@property(nonatomic,readonly) NSString* apiURL; - -/** - * The URL used for secure API HTTP requests. - */ -@property(nonatomic,readonly) NSString* apiSecureURL; - -/** - * Your application's API key, as passed to the constructor. - */ -@property(nonatomic,readonly) NSString* apiKey; - -/** - * Your application's API secret, as passed to the constructor. - */ -@property(nonatomic,readonly) NSString* apiSecret; - -/** - * The URL to call to create a session key after login. - * - * This is an alternative to calling auth.getSession directly using the secret key. - */ -@property(nonatomic,readonly) NSString* getSessionProxy; - -/** - * The current user's Facebook id. - */ -@property(nonatomic,readonly) FBUID uid; - -/** - * The current user's session key. - */ -@property(nonatomic,readonly) NSString* sessionKey; - -/** - * The current user's session secret. - */ -@property(nonatomic,readonly) NSString* sessionSecret; - -/** - * The expiration date of the session key. - */ -@property(nonatomic,readonly) NSDate* expirationDate; - -/** - * Determines if the session is active and connected to a user. - */ -@property(nonatomic,readonly) BOOL isConnected; - -/** - * The globally shared session instance. - */ -+ (FBSession*)session; - -/** - * Sets the globally shared session instance. - * - * This session is not retained, so you are still responsible for retaining it yourself. The - * first session that is created is automatically stored here. - */ -+ (void)setSession:(FBSession*)session; - -/** - * Constructs a session and stores it as the globally shared session instance. - * - * @param secret the application secret (optional) - */ -+ (FBSession*)sessionForApplication:(NSString*)key secret:(NSString*)secret - delegate:(id)delegate; - -/** - * Constructs a session and stores it as the global singleton. - * - * @param getSessionProxy a url to that proxies auth.getSession (optional) - */ -+ (FBSession*)sessionForApplication:(NSString*)key getSessionProxy:(NSString*)getSessionProxy - delegate:(id)delegate; - -/** - * Constructs a session for an application. - * - * @param secret the application secret (optional) - * @param getSessionProxy a url to that proxies auth.getSession (optional) - */ -- (FBSession*)initWithKey:(NSString*)key secret:(NSString*)secret - getSessionProxy:(NSString*)getSessionProxy; - -/** - * Begins a session for a user with a given key and secret. - */ -- (void)begin:(FBUID)uid sessionKey:(NSString*)sessionKey sessionSecret:(NSString*)sessionSecret - expires:(NSDate*)expires; - -/** - * Resumes a previous session whose uid, session key, and secret are cached on disk. - */ -- (BOOL)resume; - -/** - * Cancels a login (no-op if the login is already complete). - */ -- (void)cancelLogin; - -/** - * Ends the current session and deletes the uid, session key, and secret from disk. - */ -- (void)logout; - -/** - * Sends a fully configured request to the server for execution. - */ -- (void)send:(FBRequest*)request; - -/** - * Deletes all cookies belonging to facebook - */ -- (void)deleteFacebookCookies; - -- (void)requestTimerReady; - -@end - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@protocol FBSessionDelegate - -/** - * Called when a user has successfully logged in and begun a session. - */ -- (void)session:(FBSession*)session didLogin:(FBUID)uid; - -@optional - -/** - * Called when a user closes the login dialog without logging in. - */ -- (void)sessionDidNotLogin:(FBSession*)session; - -/** - * Called when a session is about to log out. - */ -- (void)session:(FBSession*)session willLogout:(FBUID)uid; - -/** - * Called when a session has logged out. - */ -- (void)sessionDidLogout:(FBSession*)session; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.m deleted file mode 100644 index c21f11bb..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBSession.m +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBSession.h" -#import "FBRequest.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// global - -static NSString* kAPIRestURL = @"http://api.facebook.com/restserver.php"; -static NSString* kAPIRestSecureURL = @"https://api.facebook.com/restserver.php"; - -static const int kMaxBurstRequests = 3; -static const NSTimeInterval kBurstDuration = 2; - -static FBSession* sharedSession = nil; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@implementation FBSession - -@synthesize delegates = _delegates, apiKey = _apiKey, apiSecret = _apiSecret, - getSessionProxy = _getSessionProxy, uid = _uid, sessionKey = _sessionKey, - sessionSecret = _sessionSecret, expirationDate = _expirationDate; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// class public - -+ (FBSession*)session { - return sharedSession; -} - -+ (void)setSession:(FBSession*)session { - sharedSession = session; -} - -+ (FBSession*)sessionForApplication:(NSString*)key secret:(NSString*)secret - delegate:(id)delegate { - FBSession* session = [[[FBSession alloc] initWithKey:key secret:secret - getSessionProxy:nil] autorelease]; - [session.delegates addObject:delegate]; - return session; -} - -+ (FBSession*)sessionForApplication:(NSString*)key getSessionProxy:(NSString*)getSessionProxy - delegate:(id)delegate { - FBSession* session = [[[FBSession alloc] initWithKey:key secret:nil - getSessionProxy:getSessionProxy] autorelease]; - [session.delegates addObject:delegate]; - return session; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// private - -- (void)save { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - if (_uid) { - [defaults setObject:[NSNumber numberWithLongLong:_uid] forKey:@"FBUserId"]; - } else { - [defaults removeObjectForKey:@"FBUserId"]; - } - - if (_sessionKey) { - [defaults setObject:_sessionKey forKey:@"FBSessionKey"]; - } else { - [defaults removeObjectForKey:@"FBSessionKey"]; - } - - if (_sessionSecret) { - [defaults setObject:_sessionSecret forKey:@"FBSessionSecret"]; - } else { - [defaults removeObjectForKey:@"FBSessionSecret"]; - } - - if (_expirationDate) { - [defaults setObject:_expirationDate forKey:@"FBSessionExpires"]; - } else { - [defaults removeObjectForKey:@"FBSessionExpires"]; - } - - [defaults synchronize]; -} - -- (void)unsave { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults removeObjectForKey:@"FBUserId"]; - [defaults removeObjectForKey:@"FBSessionKey"]; - [defaults removeObjectForKey:@"FBSessionSecret"]; - [defaults removeObjectForKey:@"FBSessionExpires"]; - [defaults synchronize]; -} - -- (void)startFlushTimer { - if (!_requestTimer) { - NSTimeInterval t = kBurstDuration + [_lastRequestTime timeIntervalSinceNow]; - _requestTimer = [NSTimer scheduledTimerWithTimeInterval:t target:self - selector:@selector(requestTimerReady) userInfo:nil repeats:NO]; - } -} - -- (void)enqueueRequest:(FBRequest*)request { - [_requestQueue addObject:request]; - [self startFlushTimer]; -} - -- (BOOL)performRequest:(FBRequest*)request enqueue:(BOOL)enqueue { - // Stagger requests that happen in short bursts to prevent the server from rejecting - // them for making too many requests in a short time - NSTimeInterval t = [_lastRequestTime timeIntervalSinceNow]; - BOOL burst = t && t > -kBurstDuration; - if (burst && ++_requestBurstCount > kMaxBurstRequests) { - if (enqueue) { - [self enqueueRequest:request]; - } - return NO; - } else { - [request performSelector:@selector(connect)]; - - if (!burst) { - _requestBurstCount = 1; - [_lastRequestTime release]; - _lastRequestTime = [[request timestamp] retain]; - } - } - return YES; -} - -- (void)flushRequestQueue { - while (_requestQueue.count) { - FBRequest* request = [_requestQueue objectAtIndex:0]; - if ([self performRequest:request enqueue:NO]) { - [_requestQueue removeObjectAtIndex:0]; - } else { - [self startFlushTimer]; - break; - } - } -} - -- (void)requestTimerReady { - _requestTimer = nil; - [self flushRequestQueue]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (FBSession*)initWithKey:(NSString*)key secret:(NSString*)secret - getSessionProxy:(NSString*)getSessionProxy { - if (self = [super init]) { - if (!sharedSession) { - sharedSession = self; - } - - _delegates = FBCreateNonRetainingArray(); - _apiKey = [key copy]; - _apiSecret = [secret copy]; - _getSessionProxy = [getSessionProxy copy]; - _uid = 0; - _sessionKey = nil; - _sessionSecret = nil; - _expirationDate = nil; - _requestQueue = [[NSMutableArray alloc] init]; - _lastRequestTime = nil; - _requestBurstCount = 0; - _requestTimer = nil; - } - return self; -} - -- (void)dealloc { - if (sharedSession == self) { - sharedSession = nil; - } - - [_delegates release]; - [_requestQueue release]; - [_apiKey release]; - [_apiSecret release]; - [_getSessionProxy release]; - [_sessionKey release]; - [_sessionSecret release]; - [_expirationDate release]; - [_lastRequestTime release]; - [super dealloc]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// public - -- (NSString*)apiURL { - return kAPIRestURL; -} - -- (NSString*)apiSecureURL { - return kAPIRestSecureURL; -} - -- (BOOL)isConnected { - return !!_sessionKey; -} - -- (void)begin:(FBUID)uid sessionKey:(NSString*)sessionKey - sessionSecret:(NSString*)sessionSecret expires:(NSDate*)expires { - _uid = uid; - _sessionKey = [sessionKey copy]; - _sessionSecret = [sessionSecret copy]; - _expirationDate = [expires retain]; - - [self save]; -} - -- (BOOL)resume { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - FBUID uid = [[defaults objectForKey:@"FBUserId"] longLongValue]; - if (uid) { - NSDate* expirationDate = [defaults objectForKey:@"FBSessionExpires"]; - if (!expirationDate || [expirationDate timeIntervalSinceNow] > 0) { - _uid = uid; - _sessionKey = [[defaults stringForKey:@"FBSessionKey"] copy]; - _sessionSecret = [[defaults stringForKey:@"FBSessionSecret"] copy]; - _expirationDate = [expirationDate retain]; - - for (id delegate in _delegates) { - [delegate session:self didLogin:_uid]; - } - return YES; - } - } - return NO; -} - -- (void)cancelLogin { - if (![self isConnected]) { - for (id delegate in _delegates) { - if ([delegate respondsToSelector:@selector(sessionDidNotLogin:)]) { - [delegate sessionDidNotLogin:self]; - } - } - } -} - -- (void)logout { - if (_sessionKey) { - for (id delegate in _delegates) { - if ([delegate respondsToSelector:@selector(session:willLogout:)]) { - [delegate session:self willLogout:_uid]; - } - } - - [self deleteFacebookCookies]; - - - _uid = 0; - [_sessionKey release]; - _sessionKey = nil; - [_sessionSecret release]; - _sessionSecret = nil; - [_expirationDate release]; - _expirationDate = nil; - [self unsave]; - - for (id delegate in _delegates) { - if ([delegate respondsToSelector:@selector(sessionDidLogout:)]) { - [delegate sessionDidLogout:self]; - } - } - } else { - [self deleteFacebookCookies]; - [self unsave]; - } -} - -- (void)send:(FBRequest*)request { - [self performRequest:request enqueue:YES]; -} - -- (void)deleteFacebookCookies { - NSHTTPCookieStorage* cookies = [NSHTTPCookieStorage sharedHTTPCookieStorage]; - NSArray* facebookCookies = [cookies cookiesForURL: - [NSURL URLWithString:@"http://login.facebook.com"]]; - for (NSHTTPCookie* cookie in facebookCookies) { - [cookies deleteCookie:cookie]; - } -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.h deleted file mode 100755 index b926a01e..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FBDialog.h" - -@interface FBStreamDialog : FBDialog { - NSString* _attachment; - NSString* _actionLinks; - NSString* _targetId; - NSString* _userMessagePrompt; -} - -/** - * A JSON-encoded object containing the text of the post, relevant links, a - * media type (image, video, mp3, flash), as well as any other key/value pairs - * you may want to add. - * - * Note: If you want to use this call to update a user's status, don't pass an - * attachment; the content of the userMessage parameter will become the user's - * new status and will appear at the top of the user's profile. - * - * For more info, see http://wiki.developers.facebook.com/index.php/Attachment_(Streams) - */ -@property(nonatomic,copy) NSString* attachment; - -/** - * A JSON-encoded array of action link objects, containing the link text and a - * hyperlink. - */ -@property(nonatomic,copy) NSString* actionLinks; - -/** - * The ID of the user or the Page where you are publishing the content. If this - * is specified, the post appears on the Wall of the target user, not on the - * Wall of the user who published the post. This mimics the action of posting - * on a friend's Wall on Facebook itself. - * - * Note: To post on the user's own wall, leave this blank. - */ -@property(nonatomic,copy) NSString* targetId; - -/** - * Text you provide the user as a prompt to specify a userMessage. This appears - * above the box where the user enters a custom message. - * For example, "What's on your mind?" - */ -@property(nonatomic,copy) NSString* userMessagePrompt; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.m deleted file mode 100755 index 99fdf142..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBStreamDialog.m +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#import "FBStreamDialog.h" -#import "FBSession.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// global - -static NSString* kStreamURL = @"http://www.facebook.com/connect/prompt_feed.php"; - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@implementation FBStreamDialog - -@synthesize attachment = _attachment, - actionLinks = _actionLinks, - targetId = _targetId, - userMessagePrompt = _userMessagePrompt; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)initWithSession:(FBSession*)session { - if (self = [super initWithSession:session]) { - _attachment = @""; - _actionLinks = @""; - _targetId = @""; - _userMessagePrompt = @""; - } - return self; -} - -- (void)dealloc { - [_attachment release]; - [_actionLinks release]; - [_targetId release]; - [_userMessagePrompt release]; - [super dealloc]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// FBDialog - -- (void)load { - NSDictionary* getParams = [NSDictionary dictionaryWithObjectsAndKeys: - @"touch", @"display", nil]; - - NSDictionary* postParams = [NSDictionary dictionaryWithObjectsAndKeys: - _session.apiKey, @"api_key", - _session.sessionKey, @"session_key", - @"1", @"preview", - @"fbconnect:success", @"callback", - @"fbconnect:cancel", @"cancel", - _attachment, @"attachment", - _actionLinks, @"action_links", - _targetId, @"target_id", - _userMessagePrompt, @"user_message_prompt", - nil]; - - [self loadURL:kStreamURL method:@"POST" get:getParams post:postParams]; -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.h b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.h deleted file mode 100644 index a60ef6ad..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBConnectGlobal.h" - -@interface FBXMLHandler : NSObject { - NSMutableArray* _stack; - NSMutableArray* _nameStack; - id _rootObject; - NSString* _rootName; - NSMutableString* _chars; - NSError* _parseError; -} - -@property(nonatomic,readonly) id rootObject; -@property(nonatomic,readonly) NSString* rootName; -@property(nonatomic,readonly) NSError* parseError; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.m b/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.m deleted file mode 100644 index 54de261f..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/FBConnect/FBXMLHandler.m +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2009 Facebook - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -*/ - -#import "FBXMLHandler.h" - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -@implementation FBXMLHandler - -@synthesize rootObject = _rootObject, rootName = _rootName, parseError = _parseError; - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// private - -- (NSString*)topName { - return [_nameStack lastObject]; -} - -- (id)topObject:(BOOL)create { - id object = [_stack objectAtIndex:_stack.count-1]; - if (object == [NSNull null] && create) { - object = [NSMutableDictionary dictionary]; - [_stack replaceObjectAtIndex:_stack.count-1 withObject:object]; - } - return object; -} - -- (id)topContainer { - if (_stack.count < 2) { - return nil; - } else { - id object = [_stack objectAtIndex:_stack.count-2]; - if (object == [NSNull null]) { - object = [NSMutableDictionary dictionary]; - [_stack replaceObjectAtIndex:_stack.count-2 withObject:object]; - } - return object; - } -} - -- (void)flushCharacters { - NSCharacterSet* whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet]; - for (NSInteger i = 0; i < _chars.length; ++i) { - unichar c = [_chars characterAtIndex:i]; - if (![whitespace characterIsMember:c]) { - id topContainer = self.topContainer; - if ([topContainer isKindOfClass:[NSMutableArray class]]) { - id object = [NSDictionary dictionaryWithObject:_chars forKey:self.topName]; - [_stack replaceObjectAtIndex:_stack.count-1 withObject:object]; - } else { - [_stack replaceObjectAtIndex:_stack.count-1 withObject:_chars]; - } - break; - } - } - - [_chars release]; - _chars = nil; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSObject - -- (id)init { - if (self = [super init]) { - _stack = [[NSMutableArray alloc] init]; - _nameStack = [[NSMutableArray alloc] init]; - _rootObject = nil; - _rootName = nil; - _chars = nil; - _parseError = nil; - } - return self; -} - -- (void)dealloc { - [_stack release]; - [_nameStack release]; - [_rootObject release]; - [_rootName release]; - [_chars release]; - [_parseError release]; - [super dealloc]; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// -// NSXMLParserDelegate - -- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName - namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName - attributes:(NSDictionary *)attributeDict { - [self flushCharacters]; - - id object = nil; - if ([[attributeDict objectForKey:@"list"] isEqualToString:@"true"]) { - object = [NSMutableArray array]; - } else { - object = [NSNull null]; - } - - [_stack addObject:object]; - [_nameStack addObject:elementName]; -} - -- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { - if (!_chars) { - _chars = [string mutableCopy]; - } else { - [_chars appendString:string]; - } -} - -- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName - namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { - [self flushCharacters]; - - id object = [[[self topObject:NO] retain] autorelease]; - NSString* name = [[self.topName retain] autorelease]; - [_stack removeLastObject]; - [_nameStack removeLastObject]; - - if (!_stack.count) { - _rootObject = [object retain]; - _rootName = [name retain]; - } else { - id topObject = [self topObject:YES]; - if ([topObject isKindOfClass:[NSMutableArray class]]) { - [topObject addObject:object]; - } else if ([topObject isKindOfClass:[NSMutableDictionary class]]) { - [topObject setObject:object forKey:name]; - } - } -} - -- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)error { - _parseError = [error retain]; -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.h b/Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.h deleted file mode 100644 index a5190a03..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// SHKFBStreamDialog.h -// Adds a little bit extra control to FBStreamDialog -// -// Created by Nathan Weiner on 7/26/10. -// Copyright 2010 Idea Shower, LLC. All rights reserved. -// - -#import -#import "FBStreamDialog.h" - -@interface SHKFBStreamDialog : FBStreamDialog -{ - NSString *defaultStatus; -} - -@property (nonatomic, retain) NSString *defaultStatus; - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.m b/Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.m deleted file mode 100644 index 53ec2152..00000000 --- a/Classes/ShareKit/Sharers/Services/Facebook/SHKFBStreamDialog.m +++ /dev/null @@ -1,40 +0,0 @@ -// -// SHKFBStreamDialog.m -// RIL -// -// Created by Nathan Weiner on 7/26/10. -// Copyright 2010 Idea Shower, LLC. All rights reserved. -// - -#import "SHKFBStreamDialog.h" -#import "SHK.h" - -@implementation SHKFBStreamDialog - -@synthesize defaultStatus; - -- (void)dealloc -{ - [defaultStatus release]; - [super dealloc]; -} - -- (void)webViewDidFinishLoad:(UIWebView *)webView -{ - [super webViewDidFinishLoad:webView]; - - if (defaultStatus) - { - // Set the pre-filled status message - [_webView stringByEvaluatingJavaScriptFromString: - [NSString stringWithFormat:@"document.getElementsByName('feedform_user_message')[0].value = decodeURIComponent('%@')", - [SHKEncode(defaultStatus) stringByReplacingOccurrencesOfString:@"'" withString:@"\\'"] - ] - ]; - - // Make the text field bigger - [_webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('feedform_user_message')[0].style.height='100px'"]; - } -} - -@end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.h b/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.h index ab0ee137..5ded6dc9 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.h +++ b/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.h @@ -2,27 +2,8 @@ // SHKFacebook.h // ShareKit // -// Created by Nathan Weiner on 6/18/10. - -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +// Created by Colin Humber on 1/25/11. +// Copyright 2011 __MyCompanyName__. All rights reserved. // #import @@ -34,19 +15,17 @@ typedef enum SHKFacebookPendingNone, SHKFacebookPendingLogin, SHKFacebookPendingStatus, - SHKFacebookPendingImage + SHKFacebookPendingImage, + SHKFacebookPendingLink } SHKFacebookPendingAction; - -@interface SHKFacebook : SHKSharer -{ - FBSession *session; +@interface SHKFacebook : SHKSharer { + Facebook *facebook; SHKFacebookPendingAction pendingFacebookAction; - FBLoginDialog *login; + NSArray *permissions; } -@property (retain) FBSession *session; -@property SHKFacebookPendingAction pendingFacebookAction; -@property (retain) FBLoginDialog *login; +@property (nonatomic, retain) Facebook *facebook; +@property (nonatomic, assign) SHKFacebookPendingAction pendingFacebookAction; @end diff --git a/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.m b/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.m index 2e2be608..3382b8bb 100644 --- a/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.m +++ b/Classes/ShareKit/Sharers/Services/Facebook/SHKFacebook.m @@ -2,261 +2,205 @@ // SHKFacebook.m // ShareKit // -// Created by Nathan Weiner on 6/18/10. - -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -// +// Created by Colin Humber on 1/25/11. +// Copyright 2011 __MyCompanyName__. All rights reserved. // #import "SHKFacebook.h" -#import "SHKFBStreamDialog.h" + @implementation SHKFacebook -@synthesize session; +@synthesize facebook; @synthesize pendingFacebookAction; -@synthesize login; -- (void)dealloc -{ - [session.delegates removeObject:self]; - [session release]; - [login release]; +static NSString *const SHKFacebookAccessToken = @"SHKFacebookAccessToken"; +static NSString *const SHKFacebookExpirationDate = @"SHKFacebookExpirationDate"; +static NSString *const SHKFacebookPendingItem = @"SHKFacebookPendingItem"; + +- (id)init { + if (self = [super init]) { + permissions = [[NSArray alloc] initWithObjects:@"publish_stream", @"offline_access", nil]; + } + + return self; +} + +- (void)dealloc { + [facebook release], facebook = nil; [super dealloc]; } +- (Facebook*)facebook { + if (!facebook) { + facebook = [[Facebook alloc] initWithAppId:SHKFacebookAppId]; + facebook.sessionDelegate = self; + facebook.accessToken = [self getAuthValueForKey:SHKFacebookAccessToken]; + facebook.expirationDate = (NSDate*)[[NSUserDefaults standardUserDefaults] objectForKey:SHKFacebookExpirationDate]; + } + + return facebook; +} #pragma mark - -#pragma mark Configuration : Service Defination +#pragma mark Configuration : Service Definition -+ (NSString *)sharerTitle -{ ++ (NSString*)sharerTitle { return @"Facebook"; } -+ (BOOL)canShareURL -{ ++ (BOOL)canShareURL { return YES; } -+ (BOOL)canShareText -{ ++ (BOOL)canShareText { return YES; } -+ (BOOL)canShareImage -{ ++ (BOOL)canShareImage { return YES; } -+ (BOOL)canShareOffline -{ - return NO; // TODO - would love to make this work ++ (BOOL)canShareOffline { + return NO; // TODO - would love to make this work } #pragma mark - #pragma mark Configuration : Dynamic Enable -- (BOOL)shouldAutoShare -{ +- (BOOL)shouldAutoShare { return YES; // FBConnect presents its own dialog } #pragma mark - #pragma mark Authentication -- (BOOL)isAuthorized -{ - if (session == nil) - { - - if(!SHKFacebookUseSessionProxy){ - self.session = [FBSession sessionForApplication:SHKFacebookKey - secret:SHKFacebookSecret - delegate:self]; - - }else { - self.session = [FBSession sessionForApplication:SHKFacebookKey - getSessionProxy:SHKFacebookSessionProxyURL - delegate:self]; - } - - - return [session resume]; - } - - return [session isConnected]; +- (BOOL)isAuthorized { + return [self.facebook isSessionValid]; } -- (void)promptAuthorization -{ - self.pendingFacebookAction = SHKFacebookPendingLogin; - self.login = [[[FBLoginDialog alloc] initWithSession:[self session]] autorelease]; - [login show]; +- (void)promptAuthorization { + // store the pending item in NSUserDefaults as the authorize could kick the user out to the Facebook app or Safari + [[NSUserDefaults standardUserDefaults] setObject:[self.item dictionaryRepresentation] forKey:SHKFacebookPendingItem]; + [self.facebook authorize:permissions delegate:self]; } -- (void)authFinished:(SHKRequest *)request -{ - +- (void)authFinished:(SHKRequest*)request { } -+ (void)logout -{ - FBSession *fbSession; ++ (void)logout { + Facebook *fb = [[[Facebook alloc] initWithAppId:SHKFacebookAppId] autorelease]; + fb.accessToken = [[[[self alloc] init] autorelease] getAuthValueForKey:SHKFacebookAccessToken]; + fb.expirationDate = (NSDate*)[[NSUserDefaults standardUserDefaults] objectForKey:SHKFacebookExpirationDate]; + [fb logout:self]; - if(!SHKFacebookUseSessionProxy){ - fbSession = [FBSession sessionForApplication:SHKFacebookKey - secret:SHKFacebookSecret - delegate:self]; - - }else { - fbSession = [FBSession sessionForApplication:SHKFacebookKey - getSessionProxy:SHKFacebookSessionProxyURL - delegate:self]; - } - - [fbSession logout]; + [SHK removeAuthValueForKey:SHKFacebookAccessToken forSharer:[self sharerId]]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:SHKFacebookExpirationDate]; } #pragma mark - #pragma mark Share API Methods -- (BOOL)send -{ - if (item.shareType == SHKShareTypeURL) - { - self.pendingFacebookAction = SHKFacebookPendingStatus; +- (BOOL)send { + if (item.shareType == SHKShareTypeURL) { + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys: + [item.URL absoluteString], @"link", + item.title, @"name", + item.text, @"caption", + nil]; - SHKFBStreamDialog* dialog = [[[SHKFBStreamDialog alloc] init] autorelease]; - dialog.delegate = self; - dialog.userMessagePrompt = SHKLocalizedString(@"Enter your message:"); - dialog.attachment = [NSString stringWithFormat: - @"{\ - \"name\":\"%@\",\ - \"href\":\"%@\"\ - }", - item.title == nil ? SHKEncodeURL(item.URL) : SHKEncode(item.title), - SHKEncodeURL(item.URL) - ]; - dialog.defaultStatus = item.text; - dialog.actionLinks = [NSString stringWithFormat:@"[{\"text\":\"Get %@\",\"href\":\"%@\"}]", - SHKEncode(SHKMyAppName), - SHKEncode(SHKMyAppURL)]; - [dialog show]; + if ([item customValueForKey:@"image"]) { + [params setObject:[item customValueForKey:@"image"] forKey:@"picture"]; + } + [self.facebook requestWithGraphPath:@"me/feed" + andParams:params + andHttpMethod:@"POST" + andDelegate:self]; } - - else if (item.shareType == SHKShareTypeText) - { - self.pendingFacebookAction = SHKFacebookPendingStatus; + else if (item.shareType == SHKShareTypeText) { + NSString *actionLinks = [NSString stringWithFormat:@"{\"name\":\"Get %@\", \"link\":\"%@\"}", + SHKEncode(SHKMyAppName), + SHKEncode(SHKMyAppURL)]; - SHKFBStreamDialog* dialog = [[[SHKFBStreamDialog alloc] init] autorelease]; - dialog.delegate = self; - dialog.userMessagePrompt = SHKLocalizedString(@"Enter your message:"); - dialog.defaultStatus = item.text; - dialog.actionLinks = [NSString stringWithFormat:@"[{\"text\":\"Get %@\",\"href\":\"%@\"}]", - SHKEncode(SHKMyAppName), - SHKEncode(SHKMyAppURL)]; - [dialog show]; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys: + item.text, @"message", + actionLinks, @"actions", + nil]; + [self.facebook requestWithGraphPath:@"me/feed" + andParams:params + andHttpMethod:@"POST" + andDelegate:self]; } - - else if (item.shareType == SHKShareTypeImage) - { - self.pendingFacebookAction = SHKFacebookPendingImage; + else if (item.shareType == SHKShareTypeImage) { + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys: + item.image, @"source", + item.title, @"message", + nil]; - FBPermissionDialog* dialog = [[[FBPermissionDialog alloc] init] autorelease]; - dialog.delegate = self; - dialog.permission = @"photo_upload"; - [dialog show]; + [self.facebook requestWithGraphPath:@"me/photos" + andParams:params + andHttpMethod:@"POST" + andDelegate:self]; } - return YES; -} - -- (void)sendImage -{ [self sendDidStart]; - - [[FBRequest requestWithDelegate:self] call:@"facebook.photos.upload" - params:[NSDictionary dictionaryWithObjectsAndKeys:item.title, @"caption", nil] - dataParam:UIImageJPEGRepresentation(item.image,1.0)]; + + return YES; } -- (void)dialogDidSucceed:(FBDialog*)dialog -{ - if (pendingFacebookAction == SHKFacebookPendingImage) - [self sendImage]; - - // TODO - the dialog has a SKIP button. Skipping still calls this even though it doesn't appear to post. - // - need to intercept the skip and handle it as a cancel? - else if (pendingFacebookAction == SHKFacebookPendingStatus) +- (void)dialogDidComplete:(FBDialog *)dialog { + if (pendingFacebookAction == SHKFacebookPendingStatus) { [self sendDidFinish]; + } } -- (void)dialogDidCancel:(FBDialog*)dialog -{ - if (pendingFacebookAction == SHKFacebookPendingStatus) +- (void)dialogDidNotComplete:(FBDialog *)dialog { + if (pendingFacebookAction == SHKFacebookPendingStatus) { [self sendDidCancel]; + } } -- (BOOL)dialog:(FBDialog*)dialog shouldOpenURLInExternalBrowser:(NSURL*)url -{ +- (BOOL)dialog:(FBDialog *)dialog shouldOpenURLInExternalBrowser:(NSURL *)url { return YES; } - +#pragma mark - #pragma mark FBSessionDelegate methods - -- (void)session:(FBSession*)session didLogin:(FBUID)uid -{ - // Try to share again - if (pendingFacebookAction == SHKFacebookPendingLogin) - { - self.pendingFacebookAction = SHKFacebookPendingNone; - [self share]; +- (void)fbDidLogin { + // store the Facebook credentials for use in future requests + [SHK setAuthValue:self.facebook.accessToken forKey:SHKFacebookAccessToken forSharer:[self sharerId]]; + [[NSUserDefaults standardUserDefaults] setObject:self.facebook.expirationDate forKey:SHKFacebookExpirationDate]; + + // if the current device does not support multitasking, the shared item will still be set and we can skip restoring the item + // if the current device does support multitasking, this instance of SHKFacebook will be different that the original one and we need to restore the shared item + UIDevice *device = [UIDevice currentDevice]; + if ([device respondsToSelector:@selector(isMultitaskingSupported)] && [device isMultitaskingSupported]) { + self.item = [SHKItem itemFromDictionary:[[NSUserDefaults standardUserDefaults] objectForKey:SHKFacebookPendingItem]]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:SHKFacebookPendingItem]; } + + [self share]; } -- (void)session:(FBSession*)session willLogout:(FBUID)uid -{ - // Not handling this +- (void)fbDidNotLogin:(BOOL)cancelled { + // not handling this } +- (void)fbDidLogout { + // not handling this +} +#pragma mark - #pragma mark FBRequestDelegate methods -- (void)request:(FBRequest*)aRequest didLoad:(id)result -{ - if ([aRequest.method isEqualToString:@"facebook.photos.upload"]) - { - // PID is in [result objectForKey:@"pid"]; - [self sendDidFinish]; - } +- (void)request:(FBRequest*)aRequest didLoad:(id)result { + [self sendDidFinish]; } -- (void)request:(FBRequest*)aRequest didFailWithError:(NSError*)error -{ +- (void)request:(FBRequest *)request didFailWithError:(NSError *)error { [self sendDidFailWithError:error]; } - - @end diff --git a/ShareKit-Info.plist b/ShareKit-Info.plist index d5dc4bd3..2d918794 100644 --- a/ShareKit-Info.plist +++ b/ShareKit-Info.plist @@ -28,5 +28,16 @@ MainWindow NSMainNibFile~ipad MainWindow-iPad + CFBundleURLTypes + + + CFBundleURLName + + CFBundleURLSchemes + + fb[appId] + + + diff --git a/ShareKit.xcodeproj/project.pbxproj b/ShareKit.xcodeproj/project.pbxproj index adcbf90e..624776b7 100755 --- a/ShareKit.xcodeproj/project.pbxproj +++ b/ShareKit.xcodeproj/project.pbxproj @@ -13,7 +13,19 @@ 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; }; 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD735F0D9D9599002E5188 /* MainWindow.xib */; }; 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28F335F01007B36200424DE2 /* RootViewController.xib */; }; - 4312CF7C11CB33E200E61D7A /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4312CF7B11CB33E200E61D7A /* MessageUI.framework */; }; + 3B06B64412EF841800FC0583 /* Facebook.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B62D12EF841800FC0583 /* Facebook.m */; }; + 3B06B64512EF841800FC0583 /* FBDialog.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3B06B62F12EF841800FC0583 /* FBDialog.bundle */; }; + 3B06B64612EF841800FC0583 /* FBDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63112EF841800FC0583 /* FBDialog.m */; }; + 3B06B64712EF841800FC0583 /* FBLoginDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63312EF841800FC0583 /* FBLoginDialog.m */; }; + 3B06B64812EF841800FC0583 /* FBRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63512EF841800FC0583 /* FBRequest.m */; }; + 3B06B64912EF841800FC0583 /* NSObject+SBJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63912EF841800FC0583 /* NSObject+SBJSON.m */; }; + 3B06B64A12EF841800FC0583 /* NSString+SBJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63B12EF841800FC0583 /* NSString+SBJSON.m */; }; + 3B06B64B12EF841800FC0583 /* SBJSON.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63D12EF841800FC0583 /* SBJSON.m */; }; + 3B06B64C12EF841800FC0583 /* SBJsonBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B63F12EF841800FC0583 /* SBJsonBase.m */; }; + 3B06B64D12EF841800FC0583 /* SBJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B64112EF841800FC0583 /* SBJsonParser.m */; }; + 3B06B64E12EF841800FC0583 /* SBJsonWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B64312EF841800FC0583 /* SBJsonWriter.m */; }; + 3B06B65312EF842800FC0583 /* SHKFacebook.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B06B65212EF842800FC0583 /* SHKFacebook.m */; }; + 4312CF7C11CB33E200E61D7A /* MessageUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4312CF7B11CB33E200E61D7A /* MessageUI.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 43150A8D11E78697008C6B68 /* SHKInstapaper.m in Sources */ = {isa = PBXBuildFile; fileRef = 43150A8C11E78697008C6B68 /* SHKInstapaper.m */; }; 432B147C11FF4B0700291B37 /* SHKPhotoAlbum.m in Sources */ = {isa = PBXBuildFile; fileRef = 432B147B11FF4B0700291B37 /* SHKPhotoAlbum.m */; }; 4379F2B31291AC9700D2A41E /* EDAMLimits.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F28D1291AC9700D2A41E /* EDAMLimits.m */; }; @@ -65,18 +77,6 @@ 43A5371D11DBE3B9004A1712 /* SHKMail.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536BC11DBE3B9004A1712 /* SHKMail.m */; }; 43A5371E11DBE3B9004A1712 /* SHKSafari.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536BF11DBE3B9004A1712 /* SHKSafari.m */; }; 43A5371F11DBE3B9004A1712 /* SHKDelicious.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536C311DBE3B9004A1712 /* SHKDelicious.m */; }; - 43A5372011DBE3B9004A1712 /* FBConnect.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 43A536C611DBE3B9004A1712 /* FBConnect.bundle */; }; - 43A5372111DBE3B9004A1712 /* FBConnectGlobal.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536C911DBE3B9004A1712 /* FBConnectGlobal.m */; }; - 43A5372211DBE3B9004A1712 /* FBDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536CB11DBE3B9004A1712 /* FBDialog.m */; }; - 43A5372311DBE3B9004A1712 /* FBFeedDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536CD11DBE3B9004A1712 /* FBFeedDialog.m */; }; - 43A5372411DBE3B9004A1712 /* FBLoginButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536CF11DBE3B9004A1712 /* FBLoginButton.m */; }; - 43A5372511DBE3B9004A1712 /* FBLoginDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536D111DBE3B9004A1712 /* FBLoginDialog.m */; }; - 43A5372611DBE3B9004A1712 /* FBPermissionDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536D311DBE3B9004A1712 /* FBPermissionDialog.m */; }; - 43A5372711DBE3B9004A1712 /* FBRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536D511DBE3B9004A1712 /* FBRequest.m */; }; - 43A5372811DBE3B9004A1712 /* FBSession.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536D711DBE3B9004A1712 /* FBSession.m */; }; - 43A5372911DBE3B9004A1712 /* FBStreamDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536D911DBE3B9004A1712 /* FBStreamDialog.m */; }; - 43A5372A11DBE3B9004A1712 /* FBXMLHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536DB11DBE3B9004A1712 /* FBXMLHandler.m */; }; - 43A5372B11DBE3B9004A1712 /* SHKFacebook.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536DD11DBE3B9004A1712 /* SHKFacebook.m */; }; 43A5372C11DBE3B9004A1712 /* SHKGoogleReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536E011DBE3B9004A1712 /* SHKGoogleReader.m */; }; 43A5372D11DBE3B9004A1712 /* SHKPinboard.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536E311DBE3B9004A1712 /* SHKPinboard.m */; }; 43A5372E11DBE3B9004A1712 /* SHKReadItLater.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A536E611DBE3B9004A1712 /* SHKReadItLater.m */; }; @@ -100,7 +100,6 @@ 43A5383B11DBE493004A1712 /* ShareKitAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A5383511DBE493004A1712 /* ShareKitAppDelegate.m */; }; 43A53C0911DC07A9004A1712 /* SHKCustomShareMenuCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A53C0811DC07A9004A1712 /* SHKCustomShareMenuCell.m */; }; 43A53C1211DC08B1004A1712 /* SHKCustomShareMenu.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A53C1111DC08B1004A1712 /* SHKCustomShareMenu.m */; }; - 43B934B511FE682600C9D3F3 /* SHKFBStreamDialog.m in Sources */ = {isa = PBXBuildFile; fileRef = 43B934B411FE682600C9D3F3 /* SHKFBStreamDialog.m */; }; 43C91D1D11EB963600F31FAE /* MainWindow-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 43C91D1C11EB963600F31FAE /* MainWindow-iPad.xib */; }; 43C91DF511EBAE4800F31FAE /* SHKTumblr.m in Sources */ = {isa = PBXBuildFile; fileRef = 43C91DF411EBAE4800F31FAE /* SHKTumblr.m */; }; 43D1DEF011D5CDD200550D75 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 43D1DEEF11D5CDD200550D75 /* SystemConfiguration.framework */; }; @@ -117,6 +116,31 @@ 28AD735F0D9D9599002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 28F335F01007B36200424DE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; }; 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 3B06B62C12EF841800FC0583 /* Facebook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Facebook.h; sourceTree = ""; }; + 3B06B62D12EF841800FC0583 /* Facebook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Facebook.m; sourceTree = ""; }; + 3B06B62E12EF841800FC0583 /* FBConnect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBConnect.h; sourceTree = ""; }; + 3B06B62F12EF841800FC0583 /* FBDialog.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = FBDialog.bundle; sourceTree = ""; }; + 3B06B63012EF841800FC0583 /* FBDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDialog.h; sourceTree = ""; }; + 3B06B63112EF841800FC0583 /* FBDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDialog.m; sourceTree = ""; }; + 3B06B63212EF841800FC0583 /* FBLoginDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBLoginDialog.h; sourceTree = ""; }; + 3B06B63312EF841800FC0583 /* FBLoginDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBLoginDialog.m; sourceTree = ""; }; + 3B06B63412EF841800FC0583 /* FBRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBRequest.h; sourceTree = ""; }; + 3B06B63512EF841800FC0583 /* FBRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBRequest.m; sourceTree = ""; }; + 3B06B63712EF841800FC0583 /* JSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSON.h; sourceTree = ""; }; + 3B06B63812EF841800FC0583 /* NSObject+SBJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SBJSON.h"; sourceTree = ""; }; + 3B06B63912EF841800FC0583 /* NSObject+SBJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSObject+SBJSON.m"; sourceTree = ""; }; + 3B06B63A12EF841800FC0583 /* NSString+SBJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+SBJSON.h"; sourceTree = ""; }; + 3B06B63B12EF841800FC0583 /* NSString+SBJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+SBJSON.m"; sourceTree = ""; }; + 3B06B63C12EF841800FC0583 /* SBJSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJSON.h; sourceTree = ""; }; + 3B06B63D12EF841800FC0583 /* SBJSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJSON.m; sourceTree = ""; }; + 3B06B63E12EF841800FC0583 /* SBJsonBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonBase.h; sourceTree = ""; }; + 3B06B63F12EF841800FC0583 /* SBJsonBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonBase.m; sourceTree = ""; }; + 3B06B64012EF841800FC0583 /* SBJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonParser.h; sourceTree = ""; }; + 3B06B64112EF841800FC0583 /* SBJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonParser.m; sourceTree = ""; }; + 3B06B64212EF841800FC0583 /* SBJsonWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SBJsonWriter.h; sourceTree = ""; }; + 3B06B64312EF841800FC0583 /* SBJsonWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SBJsonWriter.m; sourceTree = ""; }; + 3B06B65112EF842800FC0583 /* SHKFacebook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKFacebook.h; sourceTree = ""; }; + 3B06B65212EF842800FC0583 /* SHKFacebook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKFacebook.m; sourceTree = ""; }; 4312CF7B11CB33E200E61D7A /* MessageUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MessageUI.framework; path = System/Library/Frameworks/MessageUI.framework; sourceTree = SDKROOT; }; 43150A8B11E78697008C6B68 /* SHKInstapaper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKInstapaper.h; sourceTree = ""; }; 43150A8C11E78697008C6B68 /* SHKInstapaper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKInstapaper.m; sourceTree = ""; }; @@ -232,30 +256,6 @@ 43A536BF11DBE3B9004A1712 /* SHKSafari.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKSafari.m; sourceTree = ""; }; 43A536C211DBE3B9004A1712 /* SHKDelicious.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKDelicious.h; sourceTree = ""; }; 43A536C311DBE3B9004A1712 /* SHKDelicious.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKDelicious.m; sourceTree = ""; }; - 43A536C611DBE3B9004A1712 /* FBConnect.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = FBConnect.bundle; sourceTree = ""; }; - 43A536C711DBE3B9004A1712 /* FBConnect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBConnect.h; sourceTree = ""; }; - 43A536C811DBE3B9004A1712 /* FBConnectGlobal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBConnectGlobal.h; sourceTree = ""; }; - 43A536C911DBE3B9004A1712 /* FBConnectGlobal.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBConnectGlobal.m; sourceTree = ""; }; - 43A536CA11DBE3B9004A1712 /* FBDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDialog.h; sourceTree = ""; }; - 43A536CB11DBE3B9004A1712 /* FBDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDialog.m; sourceTree = ""; }; - 43A536CC11DBE3B9004A1712 /* FBFeedDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBFeedDialog.h; sourceTree = ""; }; - 43A536CD11DBE3B9004A1712 /* FBFeedDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFeedDialog.m; sourceTree = ""; }; - 43A536CE11DBE3B9004A1712 /* FBLoginButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBLoginButton.h; sourceTree = ""; }; - 43A536CF11DBE3B9004A1712 /* FBLoginButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBLoginButton.m; sourceTree = ""; }; - 43A536D011DBE3B9004A1712 /* FBLoginDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBLoginDialog.h; sourceTree = ""; }; - 43A536D111DBE3B9004A1712 /* FBLoginDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBLoginDialog.m; sourceTree = ""; }; - 43A536D211DBE3B9004A1712 /* FBPermissionDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBPermissionDialog.h; sourceTree = ""; }; - 43A536D311DBE3B9004A1712 /* FBPermissionDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBPermissionDialog.m; sourceTree = ""; }; - 43A536D411DBE3B9004A1712 /* FBRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBRequest.h; sourceTree = ""; }; - 43A536D511DBE3B9004A1712 /* FBRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBRequest.m; sourceTree = ""; }; - 43A536D611DBE3B9004A1712 /* FBSession.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSession.h; sourceTree = ""; }; - 43A536D711DBE3B9004A1712 /* FBSession.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSession.m; sourceTree = ""; }; - 43A536D811DBE3B9004A1712 /* FBStreamDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBStreamDialog.h; sourceTree = ""; }; - 43A536D911DBE3B9004A1712 /* FBStreamDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBStreamDialog.m; sourceTree = ""; }; - 43A536DA11DBE3B9004A1712 /* FBXMLHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXMLHandler.h; sourceTree = ""; }; - 43A536DB11DBE3B9004A1712 /* FBXMLHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXMLHandler.m; sourceTree = ""; }; - 43A536DC11DBE3B9004A1712 /* SHKFacebook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKFacebook.h; sourceTree = ""; }; - 43A536DD11DBE3B9004A1712 /* SHKFacebook.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKFacebook.m; sourceTree = ""; }; 43A536DF11DBE3B9004A1712 /* SHKGoogleReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKGoogleReader.h; sourceTree = ""; }; 43A536E011DBE3B9004A1712 /* SHKGoogleReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKGoogleReader.m; sourceTree = ""; }; 43A536E211DBE3B9004A1712 /* SHKPinboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKPinboard.h; sourceTree = ""; }; @@ -301,8 +301,6 @@ 43A53C0811DC07A9004A1712 /* SHKCustomShareMenuCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKCustomShareMenuCell.m; sourceTree = ""; }; 43A53C1011DC08B1004A1712 /* SHKCustomShareMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKCustomShareMenu.h; sourceTree = ""; }; 43A53C1111DC08B1004A1712 /* SHKCustomShareMenu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKCustomShareMenu.m; sourceTree = ""; }; - 43B934B311FE682600C9D3F3 /* SHKFBStreamDialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKFBStreamDialog.h; sourceTree = ""; }; - 43B934B411FE682600C9D3F3 /* SHKFBStreamDialog.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKFBStreamDialog.m; sourceTree = ""; }; 43C91D1C11EB963600F31FAE /* MainWindow-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "MainWindow-iPad.xib"; path = "Resources-iPad/MainWindow-iPad.xib"; sourceTree = ""; }; 43C91DF311EBAE4800F31FAE /* SHKTumblr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKTumblr.h; sourceTree = ""; }; 43C91DF411EBAE4800F31FAE /* SHKTumblr.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKTumblr.m; sourceTree = ""; }; @@ -394,6 +392,44 @@ name = Frameworks; sourceTree = ""; }; + 3B06B62B12EF841800FC0583 /* FBConnect */ = { + isa = PBXGroup; + children = ( + 3B06B62C12EF841800FC0583 /* Facebook.h */, + 3B06B62D12EF841800FC0583 /* Facebook.m */, + 3B06B62E12EF841800FC0583 /* FBConnect.h */, + 3B06B62F12EF841800FC0583 /* FBDialog.bundle */, + 3B06B63012EF841800FC0583 /* FBDialog.h */, + 3B06B63112EF841800FC0583 /* FBDialog.m */, + 3B06B63212EF841800FC0583 /* FBLoginDialog.h */, + 3B06B63312EF841800FC0583 /* FBLoginDialog.m */, + 3B06B63412EF841800FC0583 /* FBRequest.h */, + 3B06B63512EF841800FC0583 /* FBRequest.m */, + 3B06B63612EF841800FC0583 /* JSON */, + ); + path = FBConnect; + sourceTree = ""; + }; + 3B06B63612EF841800FC0583 /* JSON */ = { + isa = PBXGroup; + children = ( + 3B06B63712EF841800FC0583 /* JSON.h */, + 3B06B63812EF841800FC0583 /* NSObject+SBJSON.h */, + 3B06B63912EF841800FC0583 /* NSObject+SBJSON.m */, + 3B06B63A12EF841800FC0583 /* NSString+SBJSON.h */, + 3B06B63B12EF841800FC0583 /* NSString+SBJSON.m */, + 3B06B63C12EF841800FC0583 /* SBJSON.h */, + 3B06B63D12EF841800FC0583 /* SBJSON.m */, + 3B06B63E12EF841800FC0583 /* SBJsonBase.h */, + 3B06B63F12EF841800FC0583 /* SBJsonBase.m */, + 3B06B64012EF841800FC0583 /* SBJsonParser.h */, + 3B06B64112EF841800FC0583 /* SBJsonParser.m */, + 3B06B64212EF841800FC0583 /* SBJsonWriter.h */, + 3B06B64312EF841800FC0583 /* SBJsonWriter.m */, + ); + path = JSON; + sourceTree = ""; + }; 43150A8A11E78697008C6B68 /* Instapaper */ = { isa = PBXGroup; children = ( @@ -745,44 +781,13 @@ 43A536C411DBE3B9004A1712 /* Facebook */ = { isa = PBXGroup; children = ( - 43A536C511DBE3B9004A1712 /* FBConnect */, - 43A536DC11DBE3B9004A1712 /* SHKFacebook.h */, - 43A536DD11DBE3B9004A1712 /* SHKFacebook.m */, - 43B934B311FE682600C9D3F3 /* SHKFBStreamDialog.h */, - 43B934B411FE682600C9D3F3 /* SHKFBStreamDialog.m */, + 3B06B62B12EF841800FC0583 /* FBConnect */, + 3B06B65112EF842800FC0583 /* SHKFacebook.h */, + 3B06B65212EF842800FC0583 /* SHKFacebook.m */, ); path = Facebook; sourceTree = ""; }; - 43A536C511DBE3B9004A1712 /* FBConnect */ = { - isa = PBXGroup; - children = ( - 43A536C611DBE3B9004A1712 /* FBConnect.bundle */, - 43A536C711DBE3B9004A1712 /* FBConnect.h */, - 43A536C811DBE3B9004A1712 /* FBConnectGlobal.h */, - 43A536C911DBE3B9004A1712 /* FBConnectGlobal.m */, - 43A536CA11DBE3B9004A1712 /* FBDialog.h */, - 43A536CB11DBE3B9004A1712 /* FBDialog.m */, - 43A536CC11DBE3B9004A1712 /* FBFeedDialog.h */, - 43A536CD11DBE3B9004A1712 /* FBFeedDialog.m */, - 43A536CE11DBE3B9004A1712 /* FBLoginButton.h */, - 43A536CF11DBE3B9004A1712 /* FBLoginButton.m */, - 43A536D011DBE3B9004A1712 /* FBLoginDialog.h */, - 43A536D111DBE3B9004A1712 /* FBLoginDialog.m */, - 43A536D211DBE3B9004A1712 /* FBPermissionDialog.h */, - 43A536D311DBE3B9004A1712 /* FBPermissionDialog.m */, - 43A536D411DBE3B9004A1712 /* FBRequest.h */, - 43A536D511DBE3B9004A1712 /* FBRequest.m */, - 43A536D611DBE3B9004A1712 /* FBSession.h */, - 43A536D711DBE3B9004A1712 /* FBSession.m */, - 43A536D811DBE3B9004A1712 /* FBStreamDialog.h */, - 43A536D911DBE3B9004A1712 /* FBStreamDialog.m */, - 43A536DA11DBE3B9004A1712 /* FBXMLHandler.h */, - 43A536DB11DBE3B9004A1712 /* FBXMLHandler.m */, - ); - path = FBConnect; - sourceTree = ""; - }; 43A536DE11DBE3B9004A1712 /* Google Reader */ = { isa = PBXGroup; children = ( @@ -952,12 +957,12 @@ 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */, 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */, 43A5371811DBE3B9004A1712 /* SHKSharers.plist in Resources */, - 43A5372011DBE3B9004A1712 /* FBConnect.bundle in Resources */, 43A5382811DBE480004A1712 /* example.pdf in Resources */, 43A5382911DBE480004A1712 /* sanFran.jpg in Resources */, 43C91D1D11EB963600F31FAE /* MainWindow-iPad.xib in Resources */, 43FF9C7412270E9F00ADE53C /* Localizable.strings in Resources */, 4379F2C21291AC9700D2A41E /* SHKEvernote.md in Resources */, + 3B06B64512EF841800FC0583 /* FBDialog.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -999,17 +1004,6 @@ 43A5371D11DBE3B9004A1712 /* SHKMail.m in Sources */, 43A5371E11DBE3B9004A1712 /* SHKSafari.m in Sources */, 43A5371F11DBE3B9004A1712 /* SHKDelicious.m in Sources */, - 43A5372111DBE3B9004A1712 /* FBConnectGlobal.m in Sources */, - 43A5372211DBE3B9004A1712 /* FBDialog.m in Sources */, - 43A5372311DBE3B9004A1712 /* FBFeedDialog.m in Sources */, - 43A5372411DBE3B9004A1712 /* FBLoginButton.m in Sources */, - 43A5372511DBE3B9004A1712 /* FBLoginDialog.m in Sources */, - 43A5372611DBE3B9004A1712 /* FBPermissionDialog.m in Sources */, - 43A5372711DBE3B9004A1712 /* FBRequest.m in Sources */, - 43A5372811DBE3B9004A1712 /* FBSession.m in Sources */, - 43A5372911DBE3B9004A1712 /* FBStreamDialog.m in Sources */, - 43A5372A11DBE3B9004A1712 /* FBXMLHandler.m in Sources */, - 43A5372B11DBE3B9004A1712 /* SHKFacebook.m in Sources */, 43A5372C11DBE3B9004A1712 /* SHKGoogleReader.m in Sources */, 43A5372D11DBE3B9004A1712 /* SHKPinboard.m in Sources */, 43A5372E11DBE3B9004A1712 /* SHKReadItLater.m in Sources */, @@ -1033,7 +1027,6 @@ 43A53C1211DC08B1004A1712 /* SHKCustomShareMenu.m in Sources */, 43150A8D11E78697008C6B68 /* SHKInstapaper.m in Sources */, 43C91DF511EBAE4800F31FAE /* SHKTumblr.m in Sources */, - 43B934B511FE682600C9D3F3 /* SHKFBStreamDialog.m in Sources */, 432B147C11FF4B0700291B37 /* SHKPhotoAlbum.m in Sources */, 4379F2B31291AC9700D2A41E /* EDAMLimits.m in Sources */, 4379F2B41291AC9700D2A41E /* Errors.m in Sources */, @@ -1052,6 +1045,17 @@ 4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */, 4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */, 4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */, + 3B06B64412EF841800FC0583 /* Facebook.m in Sources */, + 3B06B64612EF841800FC0583 /* FBDialog.m in Sources */, + 3B06B64712EF841800FC0583 /* FBLoginDialog.m in Sources */, + 3B06B64812EF841800FC0583 /* FBRequest.m in Sources */, + 3B06B64912EF841800FC0583 /* NSObject+SBJSON.m in Sources */, + 3B06B64A12EF841800FC0583 /* NSString+SBJSON.m in Sources */, + 3B06B64B12EF841800FC0583 /* SBJSON.m in Sources */, + 3B06B64C12EF841800FC0583 /* SBJsonBase.m in Sources */, + 3B06B64D12EF841800FC0583 /* SBJsonParser.m in Sources */, + 3B06B64E12EF841800FC0583 /* SBJsonWriter.m in Sources */, + 3B06B65312EF842800FC0583 /* SHKFacebook.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1082,6 +1086,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -1090,6 +1095,7 @@ INFOPLIST_FILE = "ShareKit-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.2; PRODUCT_NAME = ShareKit; + PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -1100,12 +1106,14 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ShareKit_Prefix.pch; INFOPLIST_FILE = "ShareKit-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.2; PRODUCT_NAME = ShareKit; + PROVISIONING_PROFILE = ""; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES;