diff --git a/Classes/ShareKit/Core/SHKSharers.plist b/Classes/ShareKit/Core/SHKSharers.plist
index db686302..8ca035e5 100644
--- a/Classes/ShareKit/Core/SHKSharers.plist
+++ b/Classes/ShareKit/Core/SHKSharers.plist
@@ -21,6 +21,7 @@
SHKReadItLater
SHKInstapaper
SHKTumblr
+ SHKFlickr
diff --git a/Classes/ShareKit/SHKConfig.h b/Classes/ShareKit/SHKConfig.h
index c2aa3565..db07ec7d 100644
--- a/Classes/ShareKit/SHKConfig.h
+++ b/Classes/ShareKit/SHKConfig.h
@@ -86,6 +86,11 @@
#define SHKSharedWithSignature 0
+// Flickr - http://www.flickr.com/services/apps/create/
+#define SHKFlickrConsumerKey @"" // The consumer key
+#define SHKFlickrSecretKey @"" // The secret key
+#define SHKFlickrCallbackUrl @"app://flickr" // The user defined callback url
+
/*
UI Configuration : Basic
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/LFHTTPRequest.h b/Classes/ShareKit/Sharers/Services/Flickr/LFHTTPRequest.h
new file mode 100644
index 00000000..14dc73f8
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/LFHTTPRequest.h
@@ -0,0 +1,157 @@
+//
+// LFHTTPRequest.h
+//
+// Copyright (c) 2007-2009 Lithoglyph Inc. (http://lithoglyph.com)
+// Copyright (c) 2007-2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import
+#if TARGET_OS_IPHONE
+ #import
+ #import
+ #import
+#endif
+
+extern NSString *const LFHTTPRequestConnectionError;
+extern NSString *const LFHTTPRequestTimeoutError;
+extern const NSTimeInterval LFHTTPRequestDefaultTimeoutInterval;
+extern NSString *const LFHTTPRequestWWWFormURLEncodedContentType;
+extern NSString *const LFHTTPRequestGETMethod;
+extern NSString *const LFHTTPRequestHEADMethod;
+extern NSString *const LFHTTPRequestPOSTMethod;
+
+@interface LFHTTPRequest : NSObject
+{
+ id _delegate;
+
+ NSTimeInterval _timeoutInterval;
+ NSString *_userAgent;
+ NSString *_contentType;
+
+ NSDictionary *_requestHeader;
+
+ NSMutableData *_receivedData;
+ NSString *_receivedContentType;
+
+ CFReadStreamRef _readStream;
+ NSTimer *_receivedDataTracker;
+ NSTimeInterval _lastReceivedDataUpdateTime;
+
+ NSTimer *_requestMessageBodyTracker;
+ NSTimeInterval _lastSentDataUpdateTime;
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+ NSUInteger _requestMessageBodySize;
+ NSUInteger _expectedDataLength;
+ NSUInteger _lastReceivedBytes;
+ NSUInteger _lastSentBytes;
+#else
+ unsigned int _requestMessageBodySize;
+ unsigned int _expectedDataLength;
+ unsigned int _lastReceivedBytes;
+ unsigned int _lastSentBytes;
+#endif
+
+ void *_readBuffer;
+ size_t _readBufferSize;
+
+ id _sessionInfo;
+
+ BOOL _shouldWaitUntilDone;
+ NSMessagePort *_synchronousMessagePort;
+}
+
+- (id)init;
+- (BOOL)isRunning;
+- (void)cancel;
+- (void)cancelWithoutDelegateMessage;
+
+- (BOOL)shouldWaitUntilDone;
+- (void)setShouldWaitUntilDone:(BOOL)waitUntilDone;
+
+- (BOOL)performMethod:(NSString *)methodName onURL:(NSURL *)url withData:(NSData *)data;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+- (BOOL)performMethod:(NSString *)methodName onURL:(NSURL *)url withInputStream:(NSInputStream *)inputStream knownContentSize:(NSUInteger)byteStreamSize;
+#else
+- (BOOL)performMethod:(NSString *)methodName onURL:(NSURL *)url withInputStream:(NSInputStream *)inputStream knownContentSize:(unsigned int)byteStreamSize;
+#endif
+
+- (NSData *)getReceivedDataAndDetachFromRequest;
+
+- (NSDictionary *)requestHeader;
+- (void)setRequestHeader:(NSDictionary *)requestHeader;
+- (NSTimeInterval)timeoutInterval;
+- (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval;
+- (NSString *)userAgent;
+- (void)setUserAgent:(NSString *)userAgent;
+- (NSString *)contentType;
+- (void)setContentType:(NSString *)contentType;
+- (NSData *)receivedData;
+- (NSString *)receivedContentType;
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+- (NSUInteger)expectedDataLength;
+#else
+- (unsigned int)expectedDataLength;
+#endif
+- (id)delegate;
+- (void)setDelegate:(id)delegate;
+
+- (void)setSessionInfo:(id)aSessionInfo;
+- (id)sessionInfo;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+@property (copy) NSDictionary *requestHeader;
+@property (assign) NSTimeInterval timeoutInterval;
+@property (copy) NSString *userAgent;
+@property (copy) NSString *contentType;
+@property (readonly) NSData *receivedData;
+@property (readonly) NSUInteger expectedDataLength;
+@property (assign) id delegate;
+@property (retain) id sessionInfo;
+@property (assign) BOOL shouldWaitUntilDone;
+@property (readonly) BOOL isRunning;
+#endif
+@end
+
+@interface NSObject (LFHTTPRequestDelegate)
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+- (void)httpRequest:(LFHTTPRequest *)request didReceiveStatusCode:(NSUInteger)statusCode URL:(NSURL *)url responseHeader:(CFHTTPMessageRef)header;
+- (void)httpRequestDidComplete:(LFHTTPRequest *)request;
+- (void)httpRequestDidCancel:(LFHTTPRequest *)request;
+- (void)httpRequest:(LFHTTPRequest *)request didFailWithError:(NSString *)error;
+- (void)httpRequest:(LFHTTPRequest *)request receivedBytes:(NSUInteger)bytesReceived expectedTotal:(NSUInteger)total;
+- (void)httpRequest:(LFHTTPRequest *)request sentBytes:(NSUInteger)bytesSent total:(NSUInteger)total;
+
+// note if you implemented this, the data is never written to the receivedData of the HTTP request instance
+- (void)httpRequest:(LFHTTPRequest *)request writeReceivedBytes:(void *)bytes size:(NSUInteger)blockSize expectedTotal:(NSUInteger)total;
+#else
+- (void)httpRequest:(LFHTTPRequest *)request didReceiveStatusCode:(unsigned int)statusCode URL:(NSURL *)url responseHeader:(CFHTTPMessageRef)header;
+- (void)httpRequestDidComplete:(LFHTTPRequest *)request;
+- (void)httpRequestDidCancel:(LFHTTPRequest *)request;
+- (void)httpRequest:(LFHTTPRequest *)request didFailWithError:(NSString *)error;
+- (void)httpRequest:(LFHTTPRequest *)request receivedBytes:(unsigned int)bytesReceived expectedTotal:(unsigned int)total;
+- (void)httpRequest:(LFHTTPRequest *)request sentBytes:(unsigned int)bytesSent total:(unsigned int)total;
+- (void)httpRequest:(LFHTTPRequest *)request writeReceivedBytes:(void *)bytes size:(unsigned int)blockSize expectedTotal:(unsigned int)total;
+#endif
+@end
\ No newline at end of file
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/LFHTTPRequest.m b/Classes/ShareKit/Sharers/Services/Flickr/LFHTTPRequest.m
new file mode 100644
index 00000000..5c658251
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/LFHTTPRequest.m
@@ -0,0 +1,776 @@
+//
+// LFHTTPRequest.m
+//
+// Copyright (c) 2007-2009 Lithoglyph Inc. (http://lithoglyph.com)
+// Copyright (c) 2007-2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import
+#import "LFHTTPRequest.h"
+
+// these typedefs are for this compilation unit only
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ typedef unsigned int NSUInteger;
+ typedef int NSInteger;
+ #define NSUIntegerMax UINT_MAX
+#endif
+
+
+
+NSString *const LFHTTPRequestConnectionError = @"HTTP request connection lost";
+NSString *const LFHTTPRequestTimeoutError = @"HTTP request timeout";
+
+const NSTimeInterval LFHTTPRequestDefaultTimeoutInterval = 10.0;
+NSString *const LFHTTPRequestWWWFormURLEncodedContentType = @"application/x-www-form-urlencoded";
+NSString *const LFHTTPRequestGETMethod = @"GET";
+NSString *const LFHTTPRequestHEADMethod = @"HEAD";
+NSString *const LFHTTPRequestPOSTMethod = @"POST";
+
+
+// internal defaults
+NSString *const LFHRDefaultUserAgent = nil;
+const size_t LFHTTPRequestDefaultReadBufferSize = 16384;
+const NSTimeInterval LFHTTPRequestDefaultTrackerFireInterval = 1.0;
+
+
+void LFHRReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo);
+
+@interface LFHTTPRequest (PrivateMethods)
+- (void)cleanUp;
+- (void)dealloc;
+- (void)handleTimeout;
+- (void)handleRequestMessageBodyTrackerTick:(NSTimer *)timer;
+- (void)handleReceivedDataTrackerTick:(NSTimer *)timer;
+- (void)readStreamHasBytesAvailable;
+- (void)readStreamErrorOccurred;
+- (void)readStreamEndEncountered;
+@end
+
+@implementation LFHTTPRequest (PrivateMethods)
+- (void)cleanUp
+{
+ if (_readStream) {
+ CFReadStreamUnscheduleFromRunLoop(_readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ CFReadStreamClose(_readStream);
+ CFRelease(_readStream);
+ _readStream = NULL;
+ }
+
+ if (_receivedDataTracker) {
+ [_receivedDataTracker invalidate];
+ [_receivedDataTracker release];
+ _receivedDataTracker = nil;
+ }
+
+ if (_requestMessageBodyTracker) {
+ [_requestMessageBodyTracker invalidate];
+ [_requestMessageBodyTracker release];
+ _requestMessageBodyTracker = nil;
+ }
+
+ _requestMessageBodySize = 0;
+ _expectedDataLength = NSUIntegerMax;
+
+ _lastReceivedDataUpdateTime = 0.0;
+ _lastReceivedBytes = 0;
+
+ _lastSentDataUpdateTime = 0.0;
+ _lastSentBytes = 0;
+
+}
+- (void)dealloc
+{
+ [self cleanUp];
+ [_userAgent release];
+ [_contentType release];
+ [_requestHeader release];
+ [_receivedData release];
+ [_receivedContentType release];
+
+ [_sessionInfo release];
+ _sessionInfo = nil;
+
+ free(_readBuffer);
+ [super dealloc];
+}
+
+- (void)finalize
+{
+ [self cleanUp];
+ if (_readBuffer) {
+ free(_readBuffer);
+ _readBuffer = NULL;
+ }
+
+ [super finalize];
+}
+
+
+- (void)_exitRunLoop
+{
+#if TARGET_OS_IPHONE
+ [_synchronousMessagePort sendBeforeDate:[NSDate date] msgid:0 components:nil from:_synchronousMessagePort reserved:0];
+
+#else
+ NSPortMessage *message = [[[NSPortMessage alloc] initWithSendPort:_synchronousMessagePort receivePort:_synchronousMessagePort components:nil] autorelease];
+ [message setMsgid:0];
+ [message sendBeforeDate:[NSDate date]];
+#endif
+}
+
+- (void)handleTimeout
+{
+ if (_shouldWaitUntilDone) {
+ [self _exitRunLoop];
+ }
+
+ [self cleanUp];
+ if ([_delegate respondsToSelector:@selector(httpRequest:didFailWithError:)]) {
+ [_delegate httpRequest:self didFailWithError:LFHTTPRequestTimeoutError];
+ }
+}
+- (void)handleRequestMessageBodyTrackerTick:(NSTimer *)timer
+{
+ if (timer != _requestMessageBodyTracker) {
+ return;
+ }
+
+ // get the number of sent bytes
+ CFTypeRef sentBytesObject = CFReadStreamCopyProperty(_readStream, kCFStreamPropertyHTTPRequestBytesWrittenCount);
+ if (!sentBytesObject) {
+ // or should we send an error message?
+ return;
+ }
+
+ NSInteger signedSentBytes = 0;
+ CFNumberGetValue(sentBytesObject, kCFNumberCFIndexType, &signedSentBytes);
+ CFRelease(sentBytesObject);
+
+ if (signedSentBytes < 0) {
+ // or should we send an error message?
+ return;
+ }
+
+ // interestingly, this logic also works when ALL REQUEST MESSAGE BODY IS SENT
+ NSUInteger sentBytes = (NSUInteger)signedSentBytes;
+ if (sentBytes > _lastSentBytes) {
+ _lastSentBytes = sentBytes;
+ _lastSentDataUpdateTime = [NSDate timeIntervalSinceReferenceDate];
+
+ if ([_delegate respondsToSelector:@selector(httpRequest:sentBytes:total:)]) {
+ [_delegate httpRequest:self sentBytes:_lastSentBytes total:_requestMessageBodySize];
+ }
+
+ return;
+ }
+
+ if ([NSDate timeIntervalSinceReferenceDate] - _lastSentDataUpdateTime > _timeoutInterval) {
+ // remove ourselve from the runloop
+ [_requestMessageBodyTracker invalidate];
+ [self handleTimeout];
+ }
+}
+- (void)handleReceivedDataTrackerTick:(NSTimer *)timer
+{
+ if (timer != _receivedDataTracker) {
+ return;
+ }
+
+ if ([NSDate timeIntervalSinceReferenceDate] - _lastReceivedDataUpdateTime > _timeoutInterval) {
+ // remove ourselves from the runloop
+ [_receivedDataTracker invalidate];
+ [self handleTimeout];
+ }
+}
+- (void)readStreamHasBytesAvailable
+{
+ // to prevent from stray callbacks entering here
+ if (![self isRunning]) {
+ return;
+ }
+
+ if (!_receivedDataTracker) {
+ // update one last time the total sent bytes
+ if ([_delegate respondsToSelector:@selector(httpRequest:sentBytes:total:)]) {
+ [_delegate httpRequest:self sentBytes:_lastSentBytes total:_lastSentBytes];
+ }
+
+ // stops _requestMessageBodyTracker
+ [_requestMessageBodyTracker invalidate];
+ [_requestMessageBodyTracker release];
+ _requestMessageBodyTracker = nil;
+
+ NSUInteger statusCode = 0;
+
+ CFURLRef finalURL = CFReadStreamCopyProperty(_readStream, kCFStreamPropertyHTTPFinalURL);
+ CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(_readStream, kCFStreamPropertyHTTPResponseHeader);
+ if (response) {
+ statusCode = (NSUInteger)CFHTTPMessageGetResponseStatusCode(response);
+
+ CFStringRef contentLengthString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Length"));
+ if (contentLengthString) {
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ _expectedDataLength = [(NSString *)contentLengthString intValue];
+#else
+ if ([(NSString *)contentLengthString respondsToSelector:@selector(integerValue)]) {
+ _expectedDataLength = [(NSString *)contentLengthString integerValue];
+ }
+ else {
+ _expectedDataLength = [(NSString *)contentLengthString intValue];
+ }
+#endif
+
+ CFRelease(contentLengthString);
+ }
+
+ [_receivedContentType release];
+ _receivedContentType = nil;
+
+ CFStringRef contentTypeString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Type"));
+ if (contentTypeString) {
+ _receivedContentType = [(NSString *)contentTypeString copy];
+ CFRelease(contentTypeString);
+ }
+ }
+
+ CFReadStreamRef presentReadStream = _readStream;
+
+ if ([_delegate respondsToSelector:@selector(httpRequest:didReceiveStatusCode:URL:responseHeader:)]) {
+ [_delegate httpRequest:self didReceiveStatusCode:statusCode URL:(NSURL *)finalURL responseHeader:response];
+ }
+
+ if (finalURL) {
+ CFRelease(finalURL);
+ }
+
+ if (response) {
+ CFRelease(response);
+ }
+
+ // better to see if we're still running... (we might be canceled by the delegate's httpRequest:didReceiveStatusCode:URL:responseHeader: !)
+ if (presentReadStream != _readStream) {
+ return;
+ }
+
+ // start tracking received bytes
+ _lastReceivedBytes = 0;
+ _lastReceivedDataUpdateTime = [NSDate timeIntervalSinceReferenceDate];
+
+ // now we fire _receivedDataTracker
+ _receivedDataTracker = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:LFHTTPRequestDefaultTrackerFireInterval target:self selector:@selector(handleReceivedDataTrackerTick:) userInfo:nil repeats:YES];
+ #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+ // this is 10.5 only
+ [[NSRunLoop currentRunLoop] addTimer:_receivedDataTracker forMode:NSRunLoopCommonModes];
+ #endif
+
+ [[NSRunLoop currentRunLoop] addTimer:_receivedDataTracker forMode:NSDefaultRunLoopMode];
+
+ // These two are defined in the AppKit, not in the Foundation
+ #if TARGET_OS_MAC && !TARGET_OS_IPHONE
+ extern NSString *NSModalPanelRunLoopMode;
+ extern NSString *NSEventTrackingRunLoopMode;
+ [[NSRunLoop currentRunLoop] addTimer:_receivedDataTracker forMode:NSEventTrackingRunLoopMode];
+ [[NSRunLoop currentRunLoop] addTimer:_receivedDataTracker forMode:NSModalPanelRunLoopMode];
+ #endif
+ }
+
+ // sets a 25,600-byte block, approximately for 256 KBPS connection
+ CFIndex bytesRead = CFReadStreamRead(_readStream, _readBuffer, _readBufferSize);
+ if (bytesRead > 0) {
+ if ([_delegate respondsToSelector:@selector(httpRequest:writeReceivedBytes:size:expectedTotal:)]) {
+ [_delegate httpRequest:self writeReceivedBytes:_readBuffer size:bytesRead expectedTotal:_expectedDataLength];
+
+ _lastReceivedBytes += bytesRead;
+ _lastReceivedDataUpdateTime = [NSDate timeIntervalSinceReferenceDate];
+
+ }
+ else {
+ [_receivedData appendBytes:_readBuffer length:bytesRead];
+ _lastReceivedBytes = [_receivedData length];
+ _lastReceivedDataUpdateTime = [NSDate timeIntervalSinceReferenceDate];
+
+ if ([_delegate respondsToSelector:@selector(httpRequest:receivedBytes:expectedTotal:)]) {
+ [_delegate httpRequest:self receivedBytes:_lastReceivedBytes expectedTotal:_expectedDataLength];
+ }
+ }
+ }
+}
+
+- (void)readStreamEndEncountered
+{
+ // to prevent from stray callbacks entering here
+ if (![self isRunning]) {
+ return;
+ }
+
+ // if no byte read, we need to present the header at least again, because readStreamHasBytesAvailable is never called
+ if (![_receivedData length] && ![_delegate respondsToSelector:@selector(httpRequest:writeReceivedBytes:size:expectedTotal:)]) {
+ if ([_delegate respondsToSelector:@selector(httpRequest:sentBytes:total:)]) {
+ [_delegate httpRequest:self sentBytes:_lastSentBytes total:_lastSentBytes];
+ }
+
+ // stops _requestMessageBodyTracker
+ [_requestMessageBodyTracker invalidate];
+ [_requestMessageBodyTracker release];
+ _requestMessageBodyTracker = nil;
+
+ NSUInteger statusCode = 0;
+
+ CFURLRef finalURL = CFReadStreamCopyProperty(_readStream, kCFStreamPropertyHTTPFinalURL);
+ CFHTTPMessageRef response = (CFHTTPMessageRef)CFReadStreamCopyProperty(_readStream, kCFStreamPropertyHTTPResponseHeader);
+ if (response) {
+ statusCode = (NSUInteger)CFHTTPMessageGetResponseStatusCode(response);
+
+ CFStringRef contentLengthString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Length"));
+ if (contentLengthString) {
+
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ _expectedDataLength = [(NSString *)contentLengthString intValue];
+ #else
+ if ([(NSString *)contentLengthString respondsToSelector:@selector(integerValue)]) {
+ _expectedDataLength = [(NSString *)contentLengthString integerValue];
+ }
+ else {
+ _expectedDataLength = [(NSString *)contentLengthString intValue];
+ }
+ #endif
+
+ CFRelease(contentLengthString);
+ }
+
+ [_receivedContentType release];
+ _receivedContentType = nil;
+
+ CFStringRef contentTypeString = CFHTTPMessageCopyHeaderFieldValue(response, CFSTR("Content-Type"));
+ if (contentTypeString) {
+ _receivedContentType = [(NSString *)contentTypeString copy];
+ CFRelease(contentTypeString);
+ }
+ }
+
+ if ([_delegate respondsToSelector:@selector(httpRequest:didReceiveStatusCode:URL:responseHeader:)]) {
+ [_delegate httpRequest:self didReceiveStatusCode:statusCode URL:(NSURL *)finalURL responseHeader:response];
+ }
+
+ if (finalURL) {
+ CFRelease(finalURL);
+ }
+
+ if (response) {
+ CFRelease(response);
+ }
+ }
+
+
+ [self cleanUp];
+
+ if ([_delegate respondsToSelector:@selector(httpRequestDidComplete:)]) {
+ [_delegate httpRequestDidComplete:self];
+ }
+}
+- (void)readStreamErrorOccurred
+{
+ // to prevent from stray callbacks entering here
+ if (![self isRunning]) {
+ return;
+ }
+
+ [self cleanUp];
+
+ if ([_delegate respondsToSelector:@selector(httpRequest:didFailWithError:)]) {
+ [_delegate httpRequest:self didFailWithError:LFHTTPRequestConnectionError];
+ }
+}
+@end
+
+@implementation LFHTTPRequest
+- (id)init
+{
+ if ((self = [super init])) {
+ _timeoutInterval = LFHTTPRequestDefaultTimeoutInterval;
+
+ _receivedData = [NSMutableData new];
+ _expectedDataLength = NSUIntegerMax;
+ _readBufferSize = LFHTTPRequestDefaultReadBufferSize;
+ _readBuffer = calloc(1, _readBufferSize);
+ NSAssert(_readBuffer, @"Must have enough memory for _readBuffer");
+ }
+
+ return self;
+}
+
+- (BOOL)isRunning
+{
+ return !!_readStream;
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+- (BOOL)_performMethod:(NSString *)methodName onURL:(NSURL *)url withData:(NSData *)data orWithInputStream:(NSInputStream *)inputStream knownContentSize:(NSUInteger)byteStreamSize
+#else
+- (BOOL)_performMethod:(NSString *)methodName onURL:(NSURL *)url withData:(NSData *)data orWithInputStream:(NSInputStream *)inputStream knownContentSize:(unsigned int)byteStreamSize
+#endif
+{
+ if (!url) {
+ return NO;
+ }
+
+ if (_readStream) {
+ return NO;
+ }
+
+ CFHTTPMessageRef request = CFHTTPMessageCreateRequest(NULL, (CFStringRef)methodName, (CFURLRef)url, kCFHTTPVersion1_1);
+ if (!request) {
+ return NO;
+ }
+
+ // combine the header
+ NSMutableDictionary *headerDictionary = [NSMutableDictionary dictionary];
+ if (_userAgent) {
+ [headerDictionary setObject:_userAgent forKey:@"User-Agent"];
+ }
+
+ if (_contentType) {
+ [headerDictionary setObject:_contentType forKey:@"Content-Type"];
+ }
+
+ if (inputStream) {
+ if (byteStreamSize && byteStreamSize != NSUIntegerMax) {
+ [headerDictionary setObject:[NSString stringWithFormat:@"%lu", byteStreamSize] forKey:@"Content-Length"];
+ _requestMessageBodySize = byteStreamSize;
+ }
+ else {
+ _requestMessageBodySize = NSUIntegerMax;
+ }
+ }
+ else {
+ if ([data length]) {
+ [headerDictionary setObject:[NSString stringWithFormat:@"%lu", [data length]] forKey:@"Content-Length"];
+ }
+ _requestMessageBodySize = [data length];
+ }
+
+ if (_requestHeader) {
+ [headerDictionary addEntriesFromDictionary:_requestHeader];
+ }
+
+ NSEnumerator *dictEnumerator = [headerDictionary keyEnumerator];
+ id key;
+ while ((key = [dictEnumerator nextObject])) {
+ CFHTTPMessageSetHeaderFieldValue(request, (CFStringRef)[key description], (CFStringRef)[headerDictionary objectForKey:key]);
+ }
+
+ if (!inputStream && data) {
+ CFHTTPMessageSetBody(request, (CFDataRef)data);
+ }
+
+ CFReadStreamRef tmpReadStream;
+
+ if (inputStream) {
+ tmpReadStream = CFReadStreamCreateForStreamedHTTPRequest(NULL, request, (CFReadStreamRef)inputStream);
+ }
+ else {
+ tmpReadStream = CFReadStreamCreateForHTTPRequest(NULL, request);
+ }
+
+ CFRelease(request);
+ if (!tmpReadStream) {
+ return NO;
+ }
+
+ CFReadStreamSetProperty(tmpReadStream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue);
+
+ // apply current proxy settings
+ #if !TARGET_OS_IPHONE
+ CFDictionaryRef proxyDict = SCDynamicStoreCopyProxies(NULL); // kCFNetworkProxiesHTTPProxy
+ #else
+ CFDictionaryRef proxyDict = CFNetworkCopySystemProxySettings();
+ #endif
+
+ if (proxyDict) {
+ CFReadStreamSetProperty(tmpReadStream, kCFStreamPropertyHTTPProxy, proxyDict);
+ CFRelease(proxyDict);
+ }
+
+ CFStreamClientContext streamContext;
+ streamContext.version = 0;
+ streamContext.info = self;
+ streamContext.retain = 0;
+ streamContext.release = 0;
+ streamContext.copyDescription = 0;
+
+ CFOptionFlags eventFlags = kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred;
+
+ // open the stream with callback function
+ if (!CFReadStreamSetClient(tmpReadStream, eventFlags, LFHRReadStreamClientCallBack, &streamContext))
+ {
+ CFRelease(tmpReadStream);
+ return NO;
+ }
+
+ // detach and release the previous data buffer
+ if ([_receivedData length]) {
+ NSMutableData *tmp = _receivedData;
+ _receivedData = [NSMutableData new];
+ [tmp release];
+ }
+
+ CFReadStreamScheduleWithRunLoop(tmpReadStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+
+ // we need to assign this in advance, because the callback might be called anytime between this and the next statement
+ _readStream = tmpReadStream;
+
+ _expectedDataLength = NSUIntegerMax;
+
+ // open the stream
+ Boolean result = CFReadStreamOpen(tmpReadStream);
+ if (!result) {
+ CFReadStreamUnscheduleFromRunLoop(tmpReadStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
+ CFRelease(tmpReadStream);
+ _readStream = NULL;
+ return NO;
+ }
+
+
+ _lastSentBytes = 0;
+ _lastSentDataUpdateTime = [NSDate timeIntervalSinceReferenceDate];
+
+ // we create _requestMessageBodyTracker (timer for tracking sent data) first
+ _requestMessageBodyTracker = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:LFHTTPRequestDefaultTrackerFireInterval target:self selector:@selector(handleRequestMessageBodyTrackerTick:) userInfo:nil repeats:YES];
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+ // this is 10.5 only
+ [[NSRunLoop currentRunLoop] addTimer:_requestMessageBodyTracker forMode:NSRunLoopCommonModes];
+#endif
+
+ [[NSRunLoop currentRunLoop] addTimer:_requestMessageBodyTracker forMode:NSDefaultRunLoopMode];
+
+ // These two are defined in the AppKit, not in the Foundation
+ #if TARGET_OS_MAC && !TARGET_OS_IPHONE
+ extern NSString *NSModalPanelRunLoopMode;
+ extern NSString *NSEventTrackingRunLoopMode;
+ [[NSRunLoop currentRunLoop] addTimer:_requestMessageBodyTracker forMode:NSEventTrackingRunLoopMode];
+ [[NSRunLoop currentRunLoop] addTimer:_requestMessageBodyTracker forMode:NSModalPanelRunLoopMode];
+ #endif
+
+ if (_shouldWaitUntilDone) {
+ NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop];
+ NSString *currentMode = [currentRunLoop currentMode];
+
+ if (![currentMode length]) {
+ currentMode = NSDefaultRunLoopMode;
+ }
+
+ BOOL isReentrant = (_synchronousMessagePort != nil);
+
+ if (!isReentrant) {
+ _synchronousMessagePort = [[NSPort port] retain];
+ [currentRunLoop addPort:_synchronousMessagePort forMode:currentMode];
+ }
+
+ while ([self isRunning]) {
+ [currentRunLoop runMode:currentMode beforeDate:[NSDate distantFuture]];
+ }
+
+ if (!isReentrant) {
+ [currentRunLoop removePort:_synchronousMessagePort forMode:currentMode];
+ [_synchronousMessagePort release];
+ _synchronousMessagePort = nil;
+ }
+ else {
+ // sends another message to exit the runloop
+ [self _exitRunLoop];
+ }
+ }
+
+ return YES;
+}
+
+- (BOOL)performMethod:(NSString *)methodName onURL:(NSURL *)url withData:(NSData *)data
+{
+ return [self _performMethod:methodName onURL:url withData:data orWithInputStream:nil knownContentSize:0];
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+- (BOOL)performMethod:(NSString *)methodName onURL:(NSURL *)url withInputStream:(NSInputStream *)inputStream knownContentSize:(NSUInteger)byteStreamSize
+#else
+- (BOOL)performMethod:(NSString *)methodName onURL:(NSURL *)url withInputStream:(NSInputStream *)inputStream knownContentSize:(unsigned int)byteStreamSize
+#endif
+{
+ return [self _performMethod:methodName onURL:url withData:nil orWithInputStream:inputStream knownContentSize:byteStreamSize];
+}
+
+- (void)cancel
+{
+ [self cancelWithoutDelegateMessage];
+ if ([_delegate respondsToSelector:@selector(httpRequestDidCancel:)]) {
+ [_delegate httpRequestDidCancel:self];
+ }
+}
+- (void)cancelWithoutDelegateMessage
+{
+ [self cleanUp];
+}
+- (NSData *)getReceivedDataAndDetachFromRequest
+{
+ NSData *returnedData = [_receivedData autorelease];
+ _receivedData = [NSMutableData new];
+
+ [_receivedContentType release];
+ _receivedContentType = nil;
+
+ return returnedData;
+}
+- (NSDictionary *)requestHeader
+{
+ return [[_requestHeader copy] autorelease];
+}
+- (void)setRequestHeader:(NSDictionary *)requestHeader
+{
+ if (![_requestHeader isEqualToDictionary:requestHeader]) {
+ NSDictionary *tmp = _requestHeader;
+ _requestHeader = [requestHeader copy];
+ [tmp release];
+ }
+}
+- (NSTimeInterval)timeoutInterval
+{
+ return _timeoutInterval;
+}
+- (void)setTimeoutInterval:(NSTimeInterval)timeoutInterval
+{
+ if (_timeoutInterval != timeoutInterval) {
+ _timeoutInterval = timeoutInterval;
+ }
+}
+- (NSString *)userAgent
+{
+ return [[_userAgent copy] autorelease];
+}
+- (void)setUserAgent:(NSString *)userAgent
+{
+ if ([_userAgent isEqualToString:userAgent]) {
+ return;
+ }
+
+ NSString *tmp = _userAgent;
+ _userAgent = [userAgent copy];
+ [tmp release];
+}
+- (NSString *)contentType
+{
+ return [[_contentType copy] autorelease];
+}
+- (void)setContentType:(NSString *)contentType
+{
+ if ([_contentType isEqualToString:contentType]) {
+ return;
+ }
+
+ NSString *tmp = _contentType;
+ _contentType = [contentType copy];
+ [tmp release];
+}
+- (NSData *)receivedData
+{
+ return [[_receivedData retain] autorelease];
+}
+
+- (NSString *)receivedContentType
+{
+ return [[_receivedContentType copy] autorelease];
+}
+
+- (NSUInteger)expectedDataLength
+{
+ return _expectedDataLength;
+}
+- (id)delegate
+{
+ return _delegate;
+}
+- (void)setDelegate:(id)delegate
+{
+ if (delegate != _delegate) {
+ _delegate = delegate;
+ }
+}
+
+- (void)setSessionInfo:(id)aSessionInfo
+{
+ id tmp = _sessionInfo;
+ _sessionInfo = [aSessionInfo retain];
+ [tmp release];
+}
+- (id)sessionInfo
+{
+ return [[_sessionInfo retain] autorelease];
+}
+
+- (size_t)readBufferSize
+{
+ return _readBufferSize;
+}
+
+- (void)setReadBufferSize:(size_t)newSize
+{
+ NSAssert(![self isRunning], @"Cannot set read buffer size while the request is running");
+ NSAssert(newSize, @"Read buffer size must > 0");
+
+ _readBufferSize = newSize;
+ _readBuffer = realloc(_readBuffer, newSize);
+ NSAssert(_readBuffer, @"Must have enough memory for reallocing _readBuffer");
+ bzero(_readBuffer, newSize);
+}
+
+- (BOOL)shouldWaitUntilDone
+{
+ return _shouldWaitUntilDone;
+}
+
+- (void)setShouldWaitUntilDone:(BOOL)waitUntilDone
+{
+ _shouldWaitUntilDone = waitUntilDone;
+}
+
+@end
+
+void LFHRReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void *clientCallBackInfo)
+{
+ id pool = [NSAutoreleasePool new];
+
+ LFHTTPRequest *request = (LFHTTPRequest *)clientCallBackInfo;
+ switch (eventType) {
+ case kCFStreamEventHasBytesAvailable:
+ [request readStreamHasBytesAvailable];
+ break;
+ case kCFStreamEventEndEncountered:
+ [request readStreamEndEncountered];
+ break;
+ case kCFStreamEventErrorOccurred:
+ [request readStreamErrorOccurred];
+ break;
+ }
+ [pool drain];
+}
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/OFUtilities.h b/Classes/ShareKit/Sharers/Services/Flickr/OFUtilities.h
new file mode 100644
index 00000000..9925afad
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/OFUtilities.h
@@ -0,0 +1,85 @@
+//
+// OFUtilities.h
+//
+// Copyright (c) 2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import
+
+#if !defined(NS_INLINE)
+#if defined(__GNUC__)
+#define NS_INLINE static __inline__ __attribute__((always_inline))
+#elif defined(__MWERKS__) || defined(__cplusplus)
+#define NS_INLINE static inline
+#elif defined(_MSC_VER)
+#define NS_INLINE static __inline
+#elif defined(__WIN32__)
+#define NS_INLINE static __inline__
+#endif
+#endif
+
+NS_INLINE NSString *OFMD5HexStringFromNSString(NSString *inStr)
+{
+ const char *data = [inStr UTF8String];
+ CC_LONG length = (CC_LONG) strlen(data);
+
+ unsigned char *md5buf = (unsigned char*)calloc(1, CC_MD5_DIGEST_LENGTH);
+
+ CC_MD5_CTX md5ctx;
+ CC_MD5_Init(&md5ctx);
+ CC_MD5_Update(&md5ctx, data, length);
+ CC_MD5_Final(md5buf, &md5ctx);
+
+ NSMutableString *md5hex = [NSMutableString string];
+ size_t i;
+ for (i = 0 ; i < CC_MD5_DIGEST_LENGTH ; i++) {
+ [md5hex appendFormat:@"%02x", md5buf[i]];
+ }
+ free(md5buf);
+ return md5hex;
+}
+
+NS_INLINE NSString *OFEscapedURLStringFromNSString(NSString *inStr)
+{
+ CFStringRef escaped = CFURLCreateStringByAddingPercentEscapes(NULL, (CFStringRef)inStr, NULL, CFSTR("&"), kCFStringEncodingUTF8);
+
+ #if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ return (NSString *)[(NSString*)escaped autorelease];
+ #else
+ return (NSString *)[NSMakeCollectable(escaped) autorelease];
+ #endif
+}
+
+NS_INLINE NSString *OFGenerateUUIDString()
+{
+ CFUUIDRef uuid = CFUUIDCreate(NULL);
+ CFStringRef uuidStr = CFUUIDCreateString(NULL, uuid);
+ CFRelease(uuid);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ return (NSString *)[(NSString*)uuidStr autorelease];
+#else
+ return (NSString *)[NSMakeCollectable(uuidStr) autorelease];
+#endif
+}
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/OFXMLMapper.h b/Classes/ShareKit/Sharers/Services/Flickr/OFXMLMapper.h
new file mode 100644
index 00000000..c5c16c4e
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/OFXMLMapper.h
@@ -0,0 +1,53 @@
+//
+// OFXMLMapper.h
+//
+// Copyright (c) 2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import
+
+extern NSString *const OFXMLTextContentKey;
+
+#if (MAC_OS_X_VERSION_10_6 && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_6) || (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_2_0)
+@interface OFXMLMapper : NSObject
+#else
+@interface OFXMLMapper : NSObject
+#endif
+{
+ NSMutableDictionary *resultantDictionary;
+
+ NSMutableArray *elementStack;
+ NSMutableDictionary *currentDictionary;
+ NSString *currentElementName;
+}
++ (NSDictionary *)dictionaryMappedFromXMLData:(NSData *)inData;
+@end
+
+@interface NSDictionary (OFXMLMapperExtension)
+- (NSString *)textContent;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+@property (nonatomic, readonly) NSString *textContent;
+#endif
+@end
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/OFXMLMapper.m b/Classes/ShareKit/Sharers/Services/Flickr/OFXMLMapper.m
new file mode 100644
index 00000000..d9e6dec5
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/OFXMLMapper.m
@@ -0,0 +1,154 @@
+//
+// OFXMLMapper.m
+//
+// Copyright (c) 2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import "OFXMLMapper.h"
+
+NSString *const OFXMLMapperExceptionName = @"OFXMLMapperException";
+NSString *const OFXMLTextContentKey = @"_text";
+
+@implementation OFXMLMapper
+- (void)dealloc
+{
+ [resultantDictionary release];
+ [elementStack release];
+ [currentElementName release];
+ [super dealloc];
+}
+
+- (id)init
+{
+ if ((self = [super init])) {
+ resultantDictionary = [[NSMutableDictionary alloc] init];
+ elementStack = [[NSMutableArray alloc] init];
+ }
+
+ return self;
+}
+
+- (void)runWithData:(NSData *)inData
+{
+ currentDictionary = resultantDictionary;
+
+ NSXMLParser *parser = [[NSXMLParser alloc] initWithData:inData];
+ [parser setDelegate:self];
+ [parser parse];
+ [parser release];
+}
+
+- (NSDictionary *)resultantDictionary
+{
+ return [[resultantDictionary retain] autorelease];
+}
+
++ (NSDictionary *)dictionaryMappedFromXMLData:(NSData *)inData
+{
+ OFXMLMapper *mapper = [[OFXMLMapper alloc] init];
+ [mapper runWithData:inData];
+ NSDictionary *result = [mapper resultantDictionary];
+ [mapper release];
+ return result;
+}
+
+- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
+{
+ NSMutableDictionary *mutableAttrDict = attributeDict ? [NSMutableDictionary dictionaryWithDictionary:attributeDict] : [NSMutableDictionary dictionary];
+
+ // see if it's duplicated
+ id element = [currentDictionary objectForKey:elementName];
+ if (element) {
+ if (![element isKindOfClass:[NSMutableArray class]]) {
+ if ([element isKindOfClass:[NSMutableDictionary class]]) {
+ [element retain];
+ [currentDictionary removeObjectForKey:elementName];
+
+ NSMutableArray *newArray = [NSMutableArray arrayWithObject:element];
+ [currentDictionary setObject:newArray forKey:elementName];
+ [element release];
+
+ element = newArray;
+ }
+ else {
+ @throw [NSException exceptionWithName:OFXMLMapperExceptionName reason:@"Faulty XML structure" userInfo:nil];
+ }
+ }
+
+ [element addObject:mutableAttrDict];
+ }
+ else {
+ // plural tag rule: if the parent's tag is plural and the incoming is singular, we'll make it into an array (we only handles the -s case)
+
+ if ([currentElementName length] > [elementName length] && [currentElementName hasPrefix:elementName] && [currentElementName hasSuffix:@"s"]) {
+ [currentDictionary setObject:[NSMutableArray arrayWithObject:mutableAttrDict] forKey:elementName];
+ }
+ else {
+ [currentDictionary setObject:mutableAttrDict forKey:elementName];
+ }
+ }
+
+ [elementStack insertObject:currentDictionary atIndex:0];
+ currentDictionary = mutableAttrDict;
+
+ NSString *tmp = currentElementName;
+ currentElementName = [elementName retain];
+ [tmp release];
+}
+
+- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
+{
+ if (![elementStack count]) {
+ @throw [NSException exceptionWithName:OFXMLMapperExceptionName reason:@"Unbalanced XML element tag closing" userInfo:nil];
+ }
+
+ currentDictionary = [elementStack objectAtIndex:0];
+ [elementStack removeObjectAtIndex:0];
+}
+
+- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
+{
+ NSString *existingContent = [currentDictionary objectForKey:OFXMLTextContentKey];
+ if (existingContent) {
+ NSString *newContent = [existingContent stringByAppendingString:string];
+ [currentDictionary setObject:newContent forKey:OFXMLTextContentKey];
+ }
+ else {
+ [currentDictionary setObject:string forKey:OFXMLTextContentKey];
+ }
+}
+
+- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
+{
+ [resultantDictionary release];
+ resultantDictionary = nil;
+}
+@end
+
+@implementation NSDictionary (OFXMLMapperExtension)
+- (NSString *)textContent
+{
+ return [self objectForKey:OFXMLTextContentKey];
+}
+@end
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/ObjectiveFlickr.h b/Classes/ShareKit/Sharers/Services/Flickr/ObjectiveFlickr.h
new file mode 100644
index 00000000..9cf735fa
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/ObjectiveFlickr.h
@@ -0,0 +1,161 @@
+//
+// ObjectiveFlickr.h
+//
+// Copyright (c) 2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import "LFHTTPRequest.h"
+#import "OFUtilities.h"
+#import "OFXMLMapper.h"
+
+extern NSString *const OFFlickrSmallSquareSize; // "s" - 75x75
+extern NSString *const OFFlickrThumbnailSize; // "t" - 100 on longest side
+extern NSString *const OFFlickrSmallSize; // "m" - 240 on longest side
+extern NSString *const OFFlickrMediumSize; // (no size modifier) - 500 on longest side
+extern NSString *const OFFlickrLargeSize; // "b" - 1024 on longest side
+
+extern NSString *const OFFlickrReadPermission;
+extern NSString *const OFFlickrWritePermission;
+extern NSString *const OFFlickrDeletePermission;
+
+@interface OFFlickrAPIContext : NSObject
+{
+ NSString *key;
+ NSString *sharedSecret;
+ NSString *authToken;
+
+ NSString *RESTAPIEndpoint;
+ NSString *photoSource;
+ NSString *photoWebPageSource;
+ NSString *authEndpoint;
+ NSString *uploadEndpoint;
+}
+- (id)initWithAPIKey:(NSString *)inKey sharedSecret:(NSString *)inSharedSecret;
+
+- (void)setAuthToken:(NSString *)inAuthToken;
+- (NSString *)authToken;
+
+// URL provisioning
+- (NSURL *)photoSourceURLFromDictionary:(NSDictionary *)inDictionary size:(NSString *)inSizeModifier;
+- (NSURL *)photoWebPageURLFromDictionary:(NSDictionary *)inDictionary;
+- (NSURL *)loginURLFromFrobDictionary:(NSDictionary *)inFrob requestedPermission:(NSString *)inPermission;
+
+// API endpoints
+- (void)setRESTAPIEndpoint:(NSString *)inEndpoint;
+- (NSString *)RESTAPIEndpoint;
+
+- (void)setPhotoSource:(NSString *)inSource;
+- (NSString *)photoSource;
+
+- (void)setAuthEndpoint:(NSString *)inEndpoint;
+- (NSString *)authEndpoint;
+
+- (void)setUploadEndpoint:(NSString *)inEndpoint;
+- (NSString *)uploadEndpoint;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+@property (nonatomic, readonly) NSString *key;
+@property (nonatomic, readonly) NSString *sharedSecret;
+@property (nonatomic, retain) NSString *authToken;
+
+@property (nonatomic, retain) NSString *RESTAPIEndpoint;
+@property (nonatomic, retain) NSString *photoSource;
+@property (nonatomic, retain) NSString *photoWebPageSource;
+@property (nonatomic, retain) NSString *authEndpoint;
+@property (nonatomic, retain) NSString *uploadEndpoint;
+#endif
+@end
+
+extern NSString *const OFFlickrAPIReturnedErrorDomain;
+extern NSString *const OFFlickrAPIRequestErrorDomain;
+
+enum {
+ // refer to Flickr API document for Flickr's own error codes
+ OFFlickrAPIRequestConnectionError = 0x7fff0001,
+ OFFlickrAPIRequestTimeoutError = 0x7fff0002,
+ OFFlickrAPIRequestFaultyXMLResponseError = 0x7fff0003,
+ OFFlickrAPIRequestUnknownError = 0x7fff0042
+};
+
+@class OFFlickrAPIRequest;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+@protocol OFFlickrAPIRequestDelegate
+@optional
+#else
+@interface NSObject (OFFlickrAPIRequestDelegateCategory)
+#endif
+- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary;
+- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didFailWithError:(NSError *)inError;
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest imageUploadSentBytes:(NSUInteger)inSentBytes totalBytes:(NSUInteger)inTotalBytes;
+#else
+- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest imageUploadSentBytes:(unsigned int)inSentBytes totalBytes:(unsigned int)inTotalBytes;
+#endif
+@end
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+typedef id OFFlickrAPIRequestDelegateType;
+#else
+typedef id OFFlickrAPIRequestDelegateType;
+#endif
+
+@interface OFFlickrAPIRequest : NSObject
+{
+ OFFlickrAPIContext *context;
+ LFHTTPRequest *HTTPRequest;
+
+ OFFlickrAPIRequestDelegateType delegate;
+ id sessionInfo;
+
+ NSString *uploadTempFilename;
+}
+- (id)initWithAPIContext:(OFFlickrAPIContext *)inContext;
+- (OFFlickrAPIContext *)context;
+
+- (OFFlickrAPIRequestDelegateType)delegate;
+- (void)setDelegate:(OFFlickrAPIRequestDelegateType)inDelegate;
+
+- (id)sessionInfo;
+- (void)setSessionInfo:(id)inInfo;
+
+- (NSTimeInterval)requestTimeoutInterval;
+- (void)setRequestTimeoutInterval:(NSTimeInterval)inTimeInterval;
+- (BOOL)isRunning;
+- (void)cancel;
+
+// elementary methods
+- (BOOL)callAPIMethodWithGET:(NSString *)inMethodName arguments:(NSDictionary *)inArguments;
+- (BOOL)callAPIMethodWithPOST:(NSString *)inMethodName arguments:(NSDictionary *)inArguments;
+
+// image upload—we use NSInputStream here because we want to have flexibity; with this you can upload either a file or NSData from NSImage
+- (BOOL)uploadImageStream:(NSInputStream *)inImageStream suggestedFilename:(NSString *)inFilename MIMEType:(NSString *)inType arguments:(NSDictionary *)inArguments;
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+@property (nonatomic, readonly) OFFlickrAPIContext *context;
+@property (nonatomic, assign) OFFlickrAPIRequestDelegateType delegate;
+@property (nonatomic, retain) id sessionInfo;
+@property (nonatomic, assign) NSTimeInterval requestTimeoutInterval;
+#endif
+@end
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/ObjectiveFlickr.m b/Classes/ShareKit/Sharers/Services/Flickr/ObjectiveFlickr.m
new file mode 100644
index 00000000..ca0ed7a2
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/ObjectiveFlickr.m
@@ -0,0 +1,565 @@
+//
+// ObjectiveFlickr.m
+//
+// Copyright (c) 2009 Lukhnos D. Liu (http://lukhnos.org)
+//
+// 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.
+//
+
+#import "ObjectiveFlickr.h"
+#import "OFUtilities.h"
+#import "OFXMLMapper.h"
+
+NSString *const OFFlickrSmallSquareSize = @"s";
+NSString *const OFFlickrThumbnailSize = @"t";
+NSString *const OFFlickrSmallSize = @"m";
+NSString *const OFFlickrMediumSize = nil;
+NSString *const OFFlickrLargeSize = @"b";
+
+NSString *const OFFlickrReadPermission = @"read";
+NSString *const OFFlickrWritePermission = @"write";
+NSString *const OFFlickrDeletePermission = @"delete";
+
+NSString *const OFFlickrUploadTempFilenamePrefix = @"org.lukhnos.ObjectiveFlickr.upload";
+NSString *const OFFlickrAPIReturnedErrorDomain = @"com.flickr";
+NSString *const OFFlickrAPIRequestErrorDomain = @"org.lukhnos.ObjectiveFlickr";
+
+// compatibility typedefs
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+typedef unsigned int NSUInteger;
+#endif
+
+@interface OFFlickrAPIContext (PrivateMethods)
+- (NSArray *)signedArgumentComponentsFromArguments:(NSDictionary *)inArguments useURIEscape:(BOOL)inUseEscape;
+- (NSString *)signedQueryFromArguments:(NSDictionary *)inArguments;
+@end
+
+#define kDefaultFlickrRESTAPIEndpoint @"http://api.flickr.com/services/rest/"
+#define kDefaultFlickrPhotoSource @"http://static.flickr.com/"
+#define kDefaultFlickrPhotoWebPageSource @"http://www.flickr.com/photos/"
+#define kDefaultFlickrAuthEndpoint @"http://flickr.com/services/auth/"
+#define kDefaultFlickrUploadEndpoint @"http://api.flickr.com/services/upload/"
+
+@implementation OFFlickrAPIContext
+- (void)dealloc
+{
+ [key release];
+ [sharedSecret release];
+ [authToken release];
+
+ [RESTAPIEndpoint release];
+ [photoSource release];
+ [photoWebPageSource release];
+ [authEndpoint release];
+ [uploadEndpoint release];
+
+ [super dealloc];
+}
+
+- (id)initWithAPIKey:(NSString *)inKey sharedSecret:(NSString *)inSharedSecret
+{
+ if ((self = [super init])) {
+ key = [inKey copy];
+ sharedSecret = [inSharedSecret copy];
+
+ RESTAPIEndpoint = kDefaultFlickrRESTAPIEndpoint;
+ photoSource = kDefaultFlickrPhotoSource;
+ photoWebPageSource = kDefaultFlickrPhotoWebPageSource;
+ authEndpoint = kDefaultFlickrAuthEndpoint;
+ uploadEndpoint = kDefaultFlickrUploadEndpoint;
+ }
+ return self;
+}
+
+- (void)setAuthToken:(NSString *)inAuthToken
+{
+ NSString *tmp = authToken;
+ authToken = [inAuthToken copy];
+ [tmp release];
+}
+
+- (NSString *)authToken
+{
+ return authToken;
+}
+
+- (NSURL *)photoSourceURLFromDictionary:(NSDictionary *)inDictionary size:(NSString *)inSizeModifier
+{
+ // http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}_[mstb].jpg
+ // http://farm{farm-id}.static.flickr.com/{server-id}/{id}_{secret}.jpg
+
+ NSString *farm = [inDictionary objectForKey:@"farm"];
+ NSString *photoID = [inDictionary objectForKey:@"id"];
+ NSString *secret = [inDictionary objectForKey:@"secret"];
+ NSString *server = [inDictionary objectForKey:@"server"];
+
+ NSMutableString *URLString = [NSMutableString stringWithString:@"http://"];
+ if ([farm length]) {
+ [URLString appendFormat:@"farm%@.", farm];
+ }
+
+ // skips "http://"
+ NSAssert([server length], @"Must have server attribute");
+ NSAssert([photoID length], @"Must have id attribute");
+ NSAssert([secret length], @"Must have secret attribute");
+ [URLString appendString:[photoSource substringFromIndex:7]];
+ [URLString appendFormat:@"%@/%@_%@", server, photoID, secret];
+
+ if ([inSizeModifier length]) {
+ [URLString appendFormat:@"_%@.jpg", inSizeModifier];
+ }
+ else {
+ [URLString appendString:@".jpg"];
+ }
+
+ return [NSURL URLWithString:URLString];
+}
+
+- (NSURL *)photoWebPageURLFromDictionary:(NSDictionary *)inDictionary
+{
+ return [NSURL URLWithString:[NSString stringWithFormat:@"%@%@/%@", photoWebPageSource, [inDictionary objectForKey:@"owner"], [inDictionary objectForKey:@"id"]]];
+}
+
+- (NSURL *)loginURLFromFrobDictionary:(NSDictionary *)inFrob requestedPermission:(NSString *)inPermission
+{
+ NSString *frob = [[inFrob objectForKey:@"frob"] objectForKey:OFXMLTextContentKey];
+ NSDictionary *argDict = [frob length] ? [NSDictionary dictionaryWithObjectsAndKeys:frob, @"frob", inPermission, @"perms", nil] : [NSDictionary dictionaryWithObjectsAndKeys:inPermission, @"perms", nil];
+ NSString *URLString = [NSString stringWithFormat:@"%@?%@", authEndpoint, [self signedQueryFromArguments:argDict]];
+ return [NSURL URLWithString:URLString];
+}
+
+- (void)setRESTAPIEndpoint:(NSString *)inEndpoint
+{
+ NSString *tmp = RESTAPIEndpoint;
+ RESTAPIEndpoint = [inEndpoint copy];
+ [tmp release];
+}
+
+- (NSString *)RESTAPIEndpoint
+{
+ return RESTAPIEndpoint;
+}
+
+- (void)setPhotoSource:(NSString *)inSource
+{
+ if (![inSource hasPrefix:@"http://"]) {
+ return;
+ }
+
+ NSString *tmp = photoSource;
+ photoSource = [inSource copy];
+ [tmp release];
+}
+
+- (NSString *)photoSource
+{
+ return photoSource;
+}
+
+- (void)setPhotoWebPageSource:(NSString *)inSource
+{
+ if (![inSource hasPrefix:@"http://"]) {
+ return;
+ }
+
+ NSString *tmp = photoWebPageSource;
+ photoWebPageSource = [inSource copy];
+ [tmp release];
+}
+
+- (NSString *)photoWebPageSource
+{
+ return photoWebPageSource;
+}
+
+- (void)setAuthEndpoint:(NSString *)inEndpoint
+{
+ NSString *tmp = authEndpoint;
+ authEndpoint = [inEndpoint copy];
+ [tmp release];
+}
+
+- (NSString *)authEndpoint
+{
+ return authEndpoint;
+}
+
+- (void)setUploadEndpoint:(NSString *)inEndpoint
+{
+ NSString *tmp = uploadEndpoint;
+ uploadEndpoint = [inEndpoint copy];
+ [tmp release];
+}
+
+- (NSString *)uploadEndpoint
+{
+ return uploadEndpoint;
+}
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
+@synthesize key;
+@synthesize sharedSecret;
+#endif
+@end
+
+@implementation OFFlickrAPIContext (PrivateMethods)
+- (NSArray *)signedArgumentComponentsFromArguments:(NSDictionary *)inArguments useURIEscape:(BOOL)inUseEscape
+{
+ NSMutableDictionary *newArgs = [NSMutableDictionary dictionaryWithDictionary:inArguments];
+ if ([key length]) {
+ [newArgs setObject:key forKey:@"api_key"];
+ }
+
+ if ([authToken length]) {
+ [newArgs setObject:authToken forKey:@"auth_token"];
+ }
+
+ // combine the args
+ NSMutableArray *argArray = [NSMutableArray array];
+ NSMutableString *sigString = [NSMutableString stringWithString:[sharedSecret length] ? sharedSecret : @""];
+ NSArray *sortedArgs = [[newArgs allKeys] sortedArrayUsingSelector:@selector(compare:)];
+ NSEnumerator *argEnumerator = [sortedArgs objectEnumerator];
+ NSString *nextKey;
+ while ((nextKey = [argEnumerator nextObject])) {
+ NSString *value = [newArgs objectForKey:nextKey];
+ [sigString appendFormat:@"%@%@", nextKey, value];
+ [argArray addObject:[NSArray arrayWithObjects:nextKey, (inUseEscape ? OFEscapedURLStringFromNSString(value) : value), nil]];
+ }
+
+ NSString *signature = OFMD5HexStringFromNSString(sigString);
+ [argArray addObject:[NSArray arrayWithObjects:@"api_sig", signature, nil]];
+ return argArray;
+}
+
+
+- (NSString *)signedQueryFromArguments:(NSDictionary *)inArguments
+{
+ NSArray *argComponents = [self signedArgumentComponentsFromArguments:inArguments useURIEscape:YES];
+ NSMutableArray *args = [NSMutableArray array];
+ NSEnumerator *componentEnumerator = [argComponents objectEnumerator];
+ NSArray *nextArg;
+ while ((nextArg = [componentEnumerator nextObject])) {
+ [args addObject:[nextArg componentsJoinedByString:@"="]];
+ }
+
+ return [args componentsJoinedByString:@"&"];
+}
+@end
+
+@interface OFFlickrAPIRequest (PrivateMethods)
+- (void)cleanUpTempFile;
+@end
+
+@implementation OFFlickrAPIRequest
+- (void)dealloc
+{
+ [context release];
+ [HTTPRequest release];
+ [sessionInfo release];
+
+ [self cleanUpTempFile];
+
+ [super dealloc];
+}
+
+- (id)initWithAPIContext:(OFFlickrAPIContext *)inContext
+{
+ if ((self = [super init])) {
+ context = [inContext retain];
+
+ HTTPRequest = [[LFHTTPRequest alloc] init];
+ [HTTPRequest setDelegate:self];
+ }
+
+ return self;
+}
+
+- (OFFlickrAPIContext *)context
+{
+ return context;
+}
+
+- (OFFlickrAPIRequestDelegateType)delegate
+{
+ return delegate;
+}
+
+- (void)setDelegate:(OFFlickrAPIRequestDelegateType)inDelegate
+{
+ delegate = inDelegate;
+}
+
+- (id)sessionInfo
+{
+ return [[sessionInfo retain] autorelease];
+}
+
+- (void)setSessionInfo:(id)inInfo
+{
+ id tmp = sessionInfo;
+ sessionInfo = [inInfo retain];
+ [tmp release];
+}
+
+- (NSTimeInterval)requestTimeoutInterval
+{
+ return [HTTPRequest timeoutInterval];
+}
+
+- (void)setRequestTimeoutInterval:(NSTimeInterval)inTimeInterval
+{
+ [HTTPRequest setTimeoutInterval:inTimeInterval];
+}
+
+- (BOOL)isRunning
+{
+ return [HTTPRequest isRunning];
+}
+
+- (void)cancel
+{
+ [HTTPRequest cancelWithoutDelegateMessage];
+ [self cleanUpTempFile];
+}
+
+- (BOOL)callAPIMethodWithGET:(NSString *)inMethodName arguments:(NSDictionary *)inArguments
+{
+ if ([HTTPRequest isRunning]) {
+ return NO;
+ }
+
+ // combine the parameters
+ NSMutableDictionary *newArgs = inArguments ? [NSMutableDictionary dictionaryWithDictionary:inArguments] : [NSMutableDictionary dictionary];
+ [newArgs setObject:inMethodName forKey:@"method"];
+ NSString *query = [context signedQueryFromArguments:newArgs];
+ NSString *URLString = [NSString stringWithFormat:@"%@?%@", [context RESTAPIEndpoint], query];
+
+ [HTTPRequest setContentType:nil];
+ return [HTTPRequest performMethod:LFHTTPRequestGETMethod onURL:[NSURL URLWithString:URLString] withData:nil];
+}
+
+- (BOOL)callAPIMethodWithPOST:(NSString *)inMethodName arguments:(NSDictionary *)inArguments
+{
+ if ([HTTPRequest isRunning]) {
+ return NO;
+ }
+
+ // combine the parameters
+ NSMutableDictionary *newArgs = inArguments ? [NSMutableDictionary dictionaryWithDictionary:inArguments] : [NSMutableDictionary dictionary];
+ [newArgs setObject:inMethodName forKey:@"method"];
+ NSString *arguments = [context signedQueryFromArguments:newArgs];
+ NSData *postData = [arguments dataUsingEncoding:NSUTF8StringEncoding];
+
+ [HTTPRequest setContentType:LFHTTPRequestWWWFormURLEncodedContentType];
+ return [HTTPRequest performMethod:LFHTTPRequestPOSTMethod onURL:[NSURL URLWithString:[context RESTAPIEndpoint]] withData:postData];
+}
+
+- (BOOL)uploadImageStream:(NSInputStream *)inImageStream suggestedFilename:(NSString *)inFilename MIMEType:(NSString *)inType arguments:(NSDictionary *)inArguments
+{
+ if ([HTTPRequest isRunning]) {
+ return NO;
+ }
+
+ if (![[context authToken] length]) {
+ return NO;
+ }
+
+ // get the api_sig
+ NSArray *argComponents = [[self context] signedArgumentComponentsFromArguments:(inArguments ? inArguments : [NSDictionary dictionary]) useURIEscape:NO];
+ NSString *separator = OFGenerateUUIDString();
+ NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", separator];
+
+ // build the multipart form
+ NSMutableString *multipartBegin = [NSMutableString string];
+ NSMutableString *multipartEnd = [NSMutableString string];
+
+ NSEnumerator *componentEnumerator = [argComponents objectEnumerator];
+ NSArray *nextArgComponent;
+ while ((nextArgComponent = [componentEnumerator nextObject])) {
+ [multipartBegin appendFormat:@"--%@\r\nContent-Disposition: form-data; name=\"%@\"\r\n\r\n%@\r\n", separator, [nextArgComponent objectAtIndex:0], [nextArgComponent objectAtIndex:1]];
+ }
+
+ // add filename, if nil, generate a UUID
+ [multipartBegin appendFormat:@"--%@\r\nContent-Disposition: form-data; name=\"photo\"; filename=\"%@\"\r\n", separator, [inFilename length] ? inFilename : OFGenerateUUIDString()];
+ [multipartBegin appendFormat:@"Content-Type: %@\r\n\r\n", inType];
+
+ [multipartEnd appendFormat:@"\r\n--%@--", separator];
+
+
+ // now we have everything, create a temp file for this purpose; although UUID is inferior to
+ [self cleanUpTempFile];
+
+ uploadTempFilename = [[NSTemporaryDirectory() stringByAppendingFormat:@"%@.%@", OFFlickrUploadTempFilenamePrefix, OFGenerateUUIDString()] retain];
+
+ // create the write stream
+ NSOutputStream *outputStream = [NSOutputStream outputStreamToFileAtPath:uploadTempFilename append:NO];
+ [outputStream open];
+
+ const char *UTF8String;
+ size_t writeLength;
+ UTF8String = [multipartBegin UTF8String];
+ writeLength = strlen(UTF8String);
+
+ size_t __unused actualWrittenLength;
+ actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength];
+ NSAssert(actualWrittenLength == writeLength, @"Must write multipartBegin");
+
+ // open the input stream
+ const size_t bufferSize = 65536;
+ size_t readSize = 0;
+ uint8_t *buffer = (uint8_t *)calloc(1, bufferSize);
+ NSAssert(buffer, @"Must have enough memory for copy buffer");
+
+ [inImageStream open];
+ while ([inImageStream hasBytesAvailable]) {
+ if (!(readSize = [inImageStream read:buffer maxLength:bufferSize])) {
+ break;
+ }
+
+
+ size_t __unused actualWrittenLength;
+ actualWrittenLength = [outputStream write:buffer maxLength:readSize];
+ NSAssert (actualWrittenLength == readSize, @"Must completes the writing");
+ }
+
+ [inImageStream close];
+ free(buffer);
+
+
+ UTF8String = [multipartEnd UTF8String];
+ writeLength = strlen(UTF8String);
+ actualWrittenLength = [outputStream write:(uint8_t *)UTF8String maxLength:writeLength];
+ NSAssert(actualWrittenLength == writeLength, @"Must write multipartBegin");
+ [outputStream close];
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ NSDictionary *fileInfo = [[NSFileManager defaultManager] fileAttributesAtPath:uploadTempFilename traverseLink:YES];
+ NSAssert(fileInfo, @"Must have upload temp file");
+#else
+ NSError *error = nil;
+ NSDictionary *fileInfo = [[NSFileManager defaultManager] attributesOfItemAtPath:uploadTempFilename error:&error];
+ NSAssert(fileInfo && !error, @"Must have upload temp file");
+#endif
+ NSNumber *fileSizeNumber = [fileInfo objectForKey:NSFileSize];
+ NSUInteger fileSize = 0;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ fileSize = [fileSizeNumber intValue];
+#else
+ if ([fileSizeNumber respondsToSelector:@selector(integerValue)]) {
+ fileSize = [fileSizeNumber integerValue];
+ }
+ else {
+ fileSize = [fileSizeNumber intValue];
+ }
+#endif
+
+ NSInputStream *inputStream = [NSInputStream inputStreamWithFileAtPath:uploadTempFilename];
+
+ [HTTPRequest setContentType:contentType];
+ return [HTTPRequest performMethod:LFHTTPRequestPOSTMethod onURL:[NSURL URLWithString:[context uploadEndpoint]] withInputStream:inputStream knownContentSize:fileSize];
+}
+
+#pragma mark LFHTTPRequest delegate methods
+- (void)httpRequestDidComplete:(LFHTTPRequest *)request
+{
+ NSDictionary *responseDictionary = [OFXMLMapper dictionaryMappedFromXMLData:[request receivedData]];
+ NSDictionary *rsp = [responseDictionary objectForKey:@"rsp"];
+ NSString *stat = [rsp objectForKey:@"stat"];
+
+ // this also fails when (responseDictionary, rsp, stat) == nil, so it's a guranteed way of checking the result
+ if (![stat isEqualToString:@"ok"]) {
+ NSDictionary *err = [rsp objectForKey:@"err"];
+ NSString *code = [err objectForKey:@"code"];
+ NSString *msg = [err objectForKey:@"msg"];
+
+ NSError *toDelegateError;
+ if ([code length]) {
+ // intValue for 10.4-compatibility
+ toDelegateError = [NSError errorWithDomain:OFFlickrAPIReturnedErrorDomain code:[code intValue] userInfo:[msg length] ? [NSDictionary dictionaryWithObjectsAndKeys:msg, NSLocalizedFailureReasonErrorKey, nil] : nil];
+ }
+ else {
+ toDelegateError = [NSError errorWithDomain:OFFlickrAPIRequestErrorDomain code:OFFlickrAPIRequestFaultyXMLResponseError userInfo:nil];
+ }
+
+ if ([delegate respondsToSelector:@selector(flickrAPIRequest:didFailWithError:)]) {
+ [delegate flickrAPIRequest:self didFailWithError:toDelegateError];
+ }
+ return;
+ }
+
+ [self cleanUpTempFile];
+ if ([delegate respondsToSelector:@selector(flickrAPIRequest:didCompleteWithResponse:)]) {
+ [delegate flickrAPIRequest:self didCompleteWithResponse:rsp];
+ }
+}
+
+- (void)httpRequest:(LFHTTPRequest *)request didFailWithError:(NSString *)error
+{
+ NSError *toDelegateError = nil;
+ if ([error isEqualToString:LFHTTPRequestConnectionError]) {
+ toDelegateError = [NSError errorWithDomain:OFFlickrAPIRequestErrorDomain code:OFFlickrAPIRequestConnectionError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Network connection error", NSLocalizedFailureReasonErrorKey, nil]];
+ }
+ else if ([error isEqualToString:LFHTTPRequestTimeoutError]) {
+ toDelegateError = [NSError errorWithDomain:OFFlickrAPIRequestErrorDomain code:OFFlickrAPIRequestTimeoutError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Request timeout", NSLocalizedFailureReasonErrorKey, nil]];
+ }
+ else {
+ toDelegateError = [NSError errorWithDomain:OFFlickrAPIRequestErrorDomain code:OFFlickrAPIRequestUnknownError userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Unknown error", NSLocalizedFailureReasonErrorKey, nil]];
+ }
+
+ [self cleanUpTempFile];
+ if ([delegate respondsToSelector:@selector(flickrAPIRequest:didFailWithError:)]) {
+ [delegate flickrAPIRequest:self didFailWithError:toDelegateError];
+ }
+}
+
+- (void)httpRequest:(LFHTTPRequest *)request sentBytes:(NSUInteger)bytesSent total:(NSUInteger)total
+{
+ if (uploadTempFilename && [delegate respondsToSelector:@selector(flickrAPIRequest:imageUploadSentBytes:totalBytes:)]) {
+ [delegate flickrAPIRequest:self imageUploadSentBytes:bytesSent totalBytes:total];
+ }
+}
+@end
+
+@implementation OFFlickrAPIRequest (PrivateMethods)
+- (void)cleanUpTempFile
+
+{
+ if (uploadTempFilename) {
+ NSFileManager *fileManager = [NSFileManager defaultManager];
+ if ([fileManager fileExistsAtPath:uploadTempFilename]) {
+ BOOL __unused removeResult = NO;
+#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
+ removeResult = [fileManager removeFileAtPath:uploadTempFilename handler:nil];
+#else
+ NSError *error = nil;
+ removeResult = [fileManager removeItemAtPath:uploadTempFilename error:&error];
+#endif
+
+ NSAssert(removeResult, @"Should be able to remove temp file");
+ }
+
+ [uploadTempFilename release];
+ uploadTempFilename = nil;
+ }
+}
+@end
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/SHKFlickr.h b/Classes/ShareKit/Sharers/Services/Flickr/SHKFlickr.h
new file mode 100644
index 00000000..8ae2dcf5
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/SHKFlickr.h
@@ -0,0 +1,45 @@
+//
+// SHKFlickr
+// Flickr
+//
+// Created by Neil Bostrom on 23/02/2011.
+//
+// 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.
+//
+//
+
+#import
+#import "SHK.h"
+#import "SHKSharer.h"
+#import "SHKOAuthView.h"
+#import "ObjectiveFlickr.h"
+
+@interface SHKFlickr : SHKSharer {
+
+ OFFlickrAPIContext *flickrContext;
+ OFFlickrAPIRequest *flickrRequest;
+ NSString *flickrUserName;
+}
+
+@property (nonatomic, readonly) OFFlickrAPIContext *flickrContext;
+@property (nonatomic, retain) NSString *flickrUserName;
+
+- (void)sendPhoto;
+
+@end
diff --git a/Classes/ShareKit/Sharers/Services/Flickr/SHKFlickr.m b/Classes/ShareKit/Sharers/Services/Flickr/SHKFlickr.m
new file mode 100644
index 00000000..dd3d2dd8
--- /dev/null
+++ b/Classes/ShareKit/Sharers/Services/Flickr/SHKFlickr.m
@@ -0,0 +1,219 @@
+//
+// SHKFlickr
+// Flickr
+//
+// Created by Neil Bostrom on 23/02/2011.
+//
+// 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.
+//
+// Flickr Library: ObjectiveFlickr - https://github.com/lukhnos/objectiveflickr
+
+
+#import "SHKFlickr.h"
+
+NSString *kStoredAuthTokenKeyName = @"FlickrAuthToken";
+
+NSString *kGetAuthTokenStep = @"kGetAuthTokenStep";
+NSString *kCheckTokenStep = @"kCheckTokenStep";
+NSString *kUploadImageStep = @"kUploadImageStep";
+NSString *kSetImagePropertiesStep = @"kSetImagePropertiesStep";
+
+@implementation SHKFlickr
+
+@synthesize flickrContext, flickrUserName;
+
++ (NSString *)sharerTitle
+{
+ return @"Flickr";
+}
+
++ (BOOL)canShareImage
+{
+ return YES;
+}
+
++ (BOOL)canShare
+{
+ return YES;
+}
+
+- (BOOL)isAuthorized
+{
+ return [self.flickrContext.authToken length];
+}
+
+- (OFFlickrAPIContext *)flickrContext
+{
+ if (!flickrContext) {
+ flickrContext = [[OFFlickrAPIContext alloc] initWithAPIKey: SHKFlickrConsumerKey sharedSecret: SHKFlickrSecretKey];
+
+ NSString *authToken = [SHK getAuthValueForKey: kStoredAuthTokenKeyName forSharer:[self sharerId]];
+ if (authToken != nil) {
+ flickrContext.authToken = authToken;
+ }
+ }
+
+ return flickrContext;
+}
+
+- (OFFlickrAPIRequest *)flickrRequest
+{
+ if (!flickrRequest) {
+ flickrRequest = [[OFFlickrAPIRequest alloc] initWithAPIContext:self.flickrContext];
+ flickrRequest.delegate = self;
+ flickrRequest.requestTimeoutInterval = 60.0;
+ }
+
+ return flickrRequest;
+}
+
++ (void)logout
+{
+ [SHK removeAuthValueForKey:kStoredAuthTokenKeyName forSharer:[self sharerId]];
+}
+
+- (void)authorizationFormShow
+{
+ NSURL *loginURL = [self.flickrContext loginURLFromFrobDictionary:nil requestedPermission:OFFlickrWritePermission];
+ SHKOAuthView *auth = [[SHKOAuthView alloc] initWithURL:loginURL delegate:self];
+ [[SHK currentHelper] showViewController:auth];
+ [auth release];
+}
+
+- (BOOL)send
+{
+ if (self.flickrUserName != nil) {
+ [self sendPhoto];
+ }
+ else {
+
+ [[SHKActivityIndicator currentIndicator] displayActivity:SHKLocalizedString(@"Logging In...")];
+
+ [self flickrRequest].sessionInfo = kCheckTokenStep;
+ [flickrRequest callAPIMethodWithGET:@"flickr.auth.checkToken" arguments:nil];
+ }
+
+ return YES;
+}
+
+- (void)sendPhoto {
+
+ [self sendDidStart];
+
+ NSData *JPEGData = UIImageJPEGRepresentation(item.image, 1.0);
+
+ self.flickrRequest.sessionInfo = kUploadImageStep;
+ [self.flickrRequest uploadImageStream:[NSInputStream inputStreamWithData:JPEGData] suggestedFilename:item.title MIMEType:@"image/jpeg" arguments: nil];
+}
+
+- (NSURL *)authorizeCallbackURL {
+ return [NSURL URLWithString: SHKFlickrCallbackUrl];
+}
+
+- (void)tokenAuthorizeView:(SHKOAuthView *)authView didFinishWithSuccess:(BOOL)success queryParams:(NSMutableDictionary *)queryParams error:(NSError *)error {
+
+ [[SHK currentHelper] hideCurrentViewControllerAnimated:YES];
+
+ if (!success)
+ {
+ [[[[UIAlertView alloc] initWithTitle:SHKLocalizedString(@"Authorize Error")
+ message:error!=nil?[error localizedDescription]:SHKLocalizedString(@"There was an error while authorizing")
+ delegate:nil
+ cancelButtonTitle:SHKLocalizedString(@"Close")
+ otherButtonTitles:nil] autorelease] show];
+ }
+ else
+ {
+ [[SHKActivityIndicator currentIndicator] displayActivity:SHKLocalizedString(@"Logging In...")];
+
+ // query has the form of "&frob=", the rest is the frob
+ NSString *frob = [queryParams objectForKey:@"frob"];
+
+ [self flickrRequest].sessionInfo = kGetAuthTokenStep;
+ [flickrRequest callAPIMethodWithGET:@"flickr.auth.getToken" arguments:[NSDictionary dictionaryWithObjectsAndKeys:frob, @"frob", nil]];
+ }
+}
+
+- (void)tokenAuthorizeCancelledView:(SHKOAuthView *)authView {
+
+ [[SHK currentHelper] hideCurrentViewControllerAnimated:YES];
+}
+
+- (void)setAndStoreFlickrAuthToken:(NSString *)inAuthToken
+{
+ if (![inAuthToken length]) {
+
+ [SHKFlickr logout];
+ }
+ else {
+
+ self.flickrContext.authToken = inAuthToken;
+ [SHK setAuthValue:inAuthToken forKey:kStoredAuthTokenKeyName forSharer:[self sharerId]];
+ }
+}
+
+- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didCompleteWithResponse:(NSDictionary *)inResponseDictionary
+{
+ if (inRequest.sessionInfo == kUploadImageStep) {
+
+ NSString *photoID = [[inResponseDictionary valueForKeyPath:@"photoid"] textContent];
+
+ flickrRequest.sessionInfo = kSetImagePropertiesStep;
+ [flickrRequest callAPIMethodWithPOST:@"flickr.photos.setMeta" arguments:[NSDictionary dictionaryWithObjectsAndKeys:photoID, @"photo_id", item.title, @"title", nil, @"description", nil]];
+ }
+ else if (inRequest.sessionInfo == kSetImagePropertiesStep) {
+
+ [self sendDidFinish];
+ }
+ else {
+
+ if (inRequest.sessionInfo == kGetAuthTokenStep) {
+ [self setAndStoreFlickrAuthToken:[[inResponseDictionary valueForKeyPath:@"auth.token"] textContent]];
+ self.flickrUserName = [inResponseDictionary valueForKeyPath:@"auth.user.username"];
+
+ [self share];
+ }
+ else if (inRequest.sessionInfo == kCheckTokenStep) {
+ self.flickrUserName = [inResponseDictionary valueForKeyPath:@"auth.user.username"];
+
+ [self sendPhoto];
+ }
+ }
+}
+
+- (void)flickrAPIRequest:(OFFlickrAPIRequest *)inRequest didFailWithError:(NSError *)inError
+{
+ if (inRequest.sessionInfo == kGetAuthTokenStep) {
+ }
+ else if (inRequest.sessionInfo == kCheckTokenStep) {
+ [self setAndStoreFlickrAuthToken:nil];
+ }
+
+ [self sharer: self failedWithError: inError shouldRelogin: NO];
+}
+
+- (void)dealloc
+{
+ [flickrContext release];
+ [flickrRequest release];
+ [flickrUserName release];
+ [super dealloc];
+}
+
+@end
diff --git a/ShareKit.xcodeproj/project.pbxproj b/ShareKit.xcodeproj/project.pbxproj
index adcbf90e..bcfbcf54 100755
--- a/ShareKit.xcodeproj/project.pbxproj
+++ b/ShareKit.xcodeproj/project.pbxproj
@@ -11,27 +11,16 @@
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; };
2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; };
+ 2896265F142C725C00BFC10F /* LFHTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 28962652142C725C00BFC10F /* LFHTTPRequest.m */; };
+ 28962662142C725C00BFC10F /* ObjectiveFlickr.m in Sources */ = {isa = PBXBuildFile; fileRef = 28962659142C725C00BFC10F /* ObjectiveFlickr.m */; };
+ 28962663142C725C00BFC10F /* OFXMLMapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 2896265C142C725C00BFC10F /* OFXMLMapper.m */; };
+ 28962664142C725C00BFC10F /* SHKFlickr.m in Sources */ = {isa = PBXBuildFile; fileRef = 2896265E142C725C00BFC10F /* SHKFlickr.m */; };
+ 28962666142C728100BFC10F /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28962665142C728100BFC10F /* CFNetwork.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 */; };
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 */; };
- 4379F2B41291AC9700D2A41E /* Errors.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F28F1291AC9700D2A41E /* Errors.m */; };
- 4379F2B51291AC9700D2A41E /* NoteStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2911291AC9700D2A41E /* NoteStore.m */; };
- 4379F2B61291AC9700D2A41E /* Types.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2931291AC9700D2A41E /* Types.m */; };
- 4379F2B71291AC9700D2A41E /* UserStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2951291AC9700D2A41E /* UserStore.m */; };
- 4379F2B81291AC9700D2A41E /* TBinaryProtocol.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2991291AC9700D2A41E /* TBinaryProtocol.m */; };
- 4379F2B91291AC9700D2A41E /* TProtocolException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F29C1291AC9700D2A41E /* TProtocolException.m */; };
- 4379F2BA1291AC9700D2A41E /* TProtocolUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F29F1291AC9700D2A41E /* TProtocolUtil.m */; };
- 4379F2BB1291AC9700D2A41E /* TApplicationException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2A11291AC9700D2A41E /* TApplicationException.m */; };
- 4379F2BC1291AC9700D2A41E /* TException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2A31291AC9700D2A41E /* TException.m */; };
- 4379F2BD1291AC9700D2A41E /* THTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2A81291AC9700D2A41E /* THTTPClient.m */; };
- 4379F2BE1291AC9700D2A41E /* TMemoryBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2AA1291AC9700D2A41E /* TMemoryBuffer.m */; };
- 4379F2BF1291AC9700D2A41E /* TTransportException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2AD1291AC9700D2A41E /* TTransportException.m */; };
- 4379F2C01291AC9700D2A41E /* TSharedProcessorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2AF1291AC9700D2A41E /* TSharedProcessorFactory.m */; };
- 4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2B11291AC9700D2A41E /* SHKEvernote.m */; };
- 4379F2C21291AC9700D2A41E /* SHKEvernote.md in Resources */ = {isa = PBXBuildFile; fileRef = 4379F2B21291AC9700D2A41E /* SHKEvernote.md */; };
4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F2E91291AE5700D2A41E /* NSData+md5.m */; };
4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 4379F3B11291C45700D2A41E /* SHKTextMessage.m */; };
43A5370011DBE3B9004A1712 /* SHKOAuthSharer.m in Sources */ = {isa = PBXBuildFile; fileRef = 43A5367511DBE3B9004A1712 /* SHKOAuthSharer.m */; };
@@ -113,6 +102,16 @@
1D6058910D05DD3D006BFB54 /* ShareKit.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ShareKit.app; sourceTree = BUILT_PRODUCTS_DIR; };
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 28962651142C725C00BFC10F /* LFHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LFHTTPRequest.h; sourceTree = ""; };
+ 28962652142C725C00BFC10F /* LFHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LFHTTPRequest.m; sourceTree = ""; };
+ 28962658142C725C00BFC10F /* ObjectiveFlickr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectiveFlickr.h; sourceTree = ""; };
+ 28962659142C725C00BFC10F /* ObjectiveFlickr.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjectiveFlickr.m; sourceTree = ""; };
+ 2896265A142C725C00BFC10F /* OFUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OFUtilities.h; sourceTree = ""; };
+ 2896265B142C725C00BFC10F /* OFXMLMapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OFXMLMapper.h; sourceTree = ""; };
+ 2896265C142C725C00BFC10F /* OFXMLMapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OFXMLMapper.m; sourceTree = ""; };
+ 2896265D142C725C00BFC10F /* SHKFlickr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKFlickr.h; sourceTree = ""; };
+ 2896265E142C725C00BFC10F /* SHKFlickr.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKFlickr.m; sourceTree = ""; };
+ 28962665142C728100BFC10F /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = System/Library/Frameworks/CFNetwork.framework; sourceTree = SDKROOT; };
28A0AAE50D9B0CCF005BE974 /* ShareKit_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShareKit_Prefix.pch; sourceTree = ""; };
28AD735F0D9D9599002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; };
28F335F01007B36200424DE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; };
@@ -122,42 +121,6 @@
43150A8C11E78697008C6B68 /* SHKInstapaper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKInstapaper.m; sourceTree = ""; };
432B147A11FF4B0700291B37 /* SHKPhotoAlbum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKPhotoAlbum.h; sourceTree = ""; };
432B147B11FF4B0700291B37 /* SHKPhotoAlbum.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKPhotoAlbum.m; sourceTree = ""; };
- 4379F28C1291AC9700D2A41E /* EDAMLimits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EDAMLimits.h; sourceTree = ""; };
- 4379F28D1291AC9700D2A41E /* EDAMLimits.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EDAMLimits.m; sourceTree = ""; };
- 4379F28E1291AC9700D2A41E /* Errors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Errors.h; sourceTree = ""; };
- 4379F28F1291AC9700D2A41E /* Errors.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Errors.m; sourceTree = ""; };
- 4379F2901291AC9700D2A41E /* NoteStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NoteStore.h; sourceTree = ""; };
- 4379F2911291AC9700D2A41E /* NoteStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoteStore.m; sourceTree = ""; };
- 4379F2921291AC9700D2A41E /* Types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Types.h; sourceTree = ""; };
- 4379F2931291AC9700D2A41E /* Types.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Types.m; sourceTree = ""; };
- 4379F2941291AC9700D2A41E /* UserStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserStore.h; sourceTree = ""; };
- 4379F2951291AC9700D2A41E /* UserStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserStore.m; sourceTree = ""; };
- 4379F2981291AC9700D2A41E /* TBinaryProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TBinaryProtocol.h; sourceTree = ""; };
- 4379F2991291AC9700D2A41E /* TBinaryProtocol.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TBinaryProtocol.m; sourceTree = ""; };
- 4379F29A1291AC9700D2A41E /* TProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProtocol.h; sourceTree = ""; };
- 4379F29B1291AC9700D2A41E /* TProtocolException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProtocolException.h; sourceTree = ""; };
- 4379F29C1291AC9700D2A41E /* TProtocolException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TProtocolException.m; sourceTree = ""; };
- 4379F29D1291AC9700D2A41E /* TProtocolFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProtocolFactory.h; sourceTree = ""; };
- 4379F29E1291AC9700D2A41E /* TProtocolUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProtocolUtil.h; sourceTree = ""; };
- 4379F29F1291AC9700D2A41E /* TProtocolUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TProtocolUtil.m; sourceTree = ""; };
- 4379F2A01291AC9700D2A41E /* TApplicationException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TApplicationException.h; sourceTree = ""; };
- 4379F2A11291AC9700D2A41E /* TApplicationException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TApplicationException.m; sourceTree = ""; };
- 4379F2A21291AC9700D2A41E /* TException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TException.h; sourceTree = ""; };
- 4379F2A31291AC9700D2A41E /* TException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TException.m; sourceTree = ""; };
- 4379F2A41291AC9700D2A41E /* TProcessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProcessor.h; sourceTree = ""; };
- 4379F2A51291AC9700D2A41E /* TProcessorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TProcessorFactory.h; sourceTree = ""; };
- 4379F2A71291AC9700D2A41E /* THTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = THTTPClient.h; sourceTree = ""; };
- 4379F2A81291AC9700D2A41E /* THTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = THTTPClient.m; sourceTree = ""; };
- 4379F2A91291AC9700D2A41E /* TMemoryBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TMemoryBuffer.h; sourceTree = ""; };
- 4379F2AA1291AC9700D2A41E /* TMemoryBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TMemoryBuffer.m; sourceTree = ""; };
- 4379F2AB1291AC9700D2A41E /* TTransport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTransport.h; sourceTree = ""; };
- 4379F2AC1291AC9700D2A41E /* TTransportException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TTransportException.h; sourceTree = ""; };
- 4379F2AD1291AC9700D2A41E /* TTransportException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TTransportException.m; sourceTree = ""; };
- 4379F2AE1291AC9700D2A41E /* TSharedProcessorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TSharedProcessorFactory.h; sourceTree = ""; };
- 4379F2AF1291AC9700D2A41E /* TSharedProcessorFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TSharedProcessorFactory.m; sourceTree = ""; };
- 4379F2B01291AC9700D2A41E /* SHKEvernote.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHKEvernote.h; sourceTree = ""; };
- 4379F2B11291AC9700D2A41E /* SHKEvernote.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SHKEvernote.m; sourceTree = ""; };
- 4379F2B21291AC9700D2A41E /* SHKEvernote.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SHKEvernote.md; sourceTree = ""; };
4379F2D31291ACD800D2A41E /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Classes/ShareKit/Localization/ja.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
4379F2D41291ACE600D2A41E /* eu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = eu; path = Classes/ShareKit/Localization/eu.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
4379F2D51291ACF700D2A41E /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = Classes/ShareKit/Localization/nl.lproj/Localizable.strings; sourceTree = SOURCE_ROOT; };
@@ -318,6 +281,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 28962666142C728100BFC10F /* CFNetwork.framework in Frameworks */,
1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */,
1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */,
2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */,
@@ -347,6 +311,22 @@
name = Products;
sourceTree = "";
};
+ 28962650142C725C00BFC10F /* Flickr */ = {
+ isa = PBXGroup;
+ children = (
+ 28962651142C725C00BFC10F /* LFHTTPRequest.h */,
+ 28962652142C725C00BFC10F /* LFHTTPRequest.m */,
+ 28962658142C725C00BFC10F /* ObjectiveFlickr.h */,
+ 28962659142C725C00BFC10F /* ObjectiveFlickr.m */,
+ 2896265A142C725C00BFC10F /* OFUtilities.h */,
+ 2896265B142C725C00BFC10F /* OFXMLMapper.h */,
+ 2896265C142C725C00BFC10F /* OFXMLMapper.m */,
+ 2896265D142C725C00BFC10F /* SHKFlickr.h */,
+ 2896265E142C725C00BFC10F /* SHKFlickr.m */,
+ );
+ path = Flickr;
+ sourceTree = "";
+ };
29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
isa = PBXGroup;
children = (
@@ -384,6 +364,7 @@
29B97323FDCFA39411CA2CEA /* Frameworks */ = {
isa = PBXGroup;
children = (
+ 28962665142C728100BFC10F /* CFNetwork.framework */,
1DF5F4DF0D08C38300B7A737 /* UIKit.framework */,
1D30AB110D05D00D00671497 /* Foundation.framework */,
2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */,
@@ -431,89 +412,6 @@
name = "Example Project";
sourceTree = "";
};
- 4379F2891291AC9700D2A41E /* Evernote */ = {
- isa = PBXGroup;
- children = (
- 4379F28A1291AC9700D2A41E /* Helpers */,
- 4379F2B01291AC9700D2A41E /* SHKEvernote.h */,
- 4379F2B11291AC9700D2A41E /* SHKEvernote.m */,
- 4379F2B21291AC9700D2A41E /* SHKEvernote.md */,
- );
- path = Evernote;
- sourceTree = "";
- };
- 4379F28A1291AC9700D2A41E /* Helpers */ = {
- isa = PBXGroup;
- children = (
- 4379F28B1291AC9700D2A41E /* edam */,
- 4379F2961291AC9700D2A41E /* thrift */,
- );
- path = Helpers;
- sourceTree = "";
- };
- 4379F28B1291AC9700D2A41E /* edam */ = {
- isa = PBXGroup;
- children = (
- 4379F28C1291AC9700D2A41E /* EDAMLimits.h */,
- 4379F28D1291AC9700D2A41E /* EDAMLimits.m */,
- 4379F28E1291AC9700D2A41E /* Errors.h */,
- 4379F28F1291AC9700D2A41E /* Errors.m */,
- 4379F2901291AC9700D2A41E /* NoteStore.h */,
- 4379F2911291AC9700D2A41E /* NoteStore.m */,
- 4379F2921291AC9700D2A41E /* Types.h */,
- 4379F2931291AC9700D2A41E /* Types.m */,
- 4379F2941291AC9700D2A41E /* UserStore.h */,
- 4379F2951291AC9700D2A41E /* UserStore.m */,
- );
- path = edam;
- sourceTree = "";
- };
- 4379F2961291AC9700D2A41E /* thrift */ = {
- isa = PBXGroup;
- children = (
- 4379F2971291AC9700D2A41E /* protocol */,
- 4379F2A01291AC9700D2A41E /* TApplicationException.h */,
- 4379F2A11291AC9700D2A41E /* TApplicationException.m */,
- 4379F2A21291AC9700D2A41E /* TException.h */,
- 4379F2A31291AC9700D2A41E /* TException.m */,
- 4379F2A41291AC9700D2A41E /* TProcessor.h */,
- 4379F2A51291AC9700D2A41E /* TProcessorFactory.h */,
- 4379F2A61291AC9700D2A41E /* transport */,
- 4379F2AE1291AC9700D2A41E /* TSharedProcessorFactory.h */,
- 4379F2AF1291AC9700D2A41E /* TSharedProcessorFactory.m */,
- );
- path = thrift;
- sourceTree = "";
- };
- 4379F2971291AC9700D2A41E /* protocol */ = {
- isa = PBXGroup;
- children = (
- 4379F2981291AC9700D2A41E /* TBinaryProtocol.h */,
- 4379F2991291AC9700D2A41E /* TBinaryProtocol.m */,
- 4379F29A1291AC9700D2A41E /* TProtocol.h */,
- 4379F29B1291AC9700D2A41E /* TProtocolException.h */,
- 4379F29C1291AC9700D2A41E /* TProtocolException.m */,
- 4379F29D1291AC9700D2A41E /* TProtocolFactory.h */,
- 4379F29E1291AC9700D2A41E /* TProtocolUtil.h */,
- 4379F29F1291AC9700D2A41E /* TProtocolUtil.m */,
- );
- path = protocol;
- sourceTree = "";
- };
- 4379F2A61291AC9700D2A41E /* transport */ = {
- isa = PBXGroup;
- children = (
- 4379F2A71291AC9700D2A41E /* THTTPClient.h */,
- 4379F2A81291AC9700D2A41E /* THTTPClient.m */,
- 4379F2A91291AC9700D2A41E /* TMemoryBuffer.h */,
- 4379F2AA1291AC9700D2A41E /* TMemoryBuffer.m */,
- 4379F2AB1291AC9700D2A41E /* TTransport.h */,
- 4379F2AC1291AC9700D2A41E /* TTransportException.h */,
- 4379F2AD1291AC9700D2A41E /* TTransportException.m */,
- );
- path = transport;
- sourceTree = "";
- };
4379F3AF1291C45700D2A41E /* Text Message */ = {
isa = PBXGroup;
children = (
@@ -720,8 +618,8 @@
43A536C011DBE3B9004A1712 /* Services */ = {
isa = PBXGroup;
children = (
+ 28962650142C725C00BFC10F /* Flickr */,
43A536C111DBE3B9004A1712 /* Delicious */,
- 4379F2891291AC9700D2A41E /* Evernote */,
43A536C411DBE3B9004A1712 /* Facebook */,
43A536DE11DBE3B9004A1712 /* Google Reader */,
43150A8A11E78697008C6B68 /* Instapaper */,
@@ -957,7 +855,6 @@
43A5382911DBE480004A1712 /* sanFran.jpg in Resources */,
43C91D1D11EB963600F31FAE /* MainWindow-iPad.xib in Resources */,
43FF9C7412270E9F00ADE53C /* Localizable.strings in Resources */,
- 4379F2C21291AC9700D2A41E /* SHKEvernote.md in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1035,23 +932,12 @@
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 */,
- 4379F2B51291AC9700D2A41E /* NoteStore.m in Sources */,
- 4379F2B61291AC9700D2A41E /* Types.m in Sources */,
- 4379F2B71291AC9700D2A41E /* UserStore.m in Sources */,
- 4379F2B81291AC9700D2A41E /* TBinaryProtocol.m in Sources */,
- 4379F2B91291AC9700D2A41E /* TProtocolException.m in Sources */,
- 4379F2BA1291AC9700D2A41E /* TProtocolUtil.m in Sources */,
- 4379F2BB1291AC9700D2A41E /* TApplicationException.m in Sources */,
- 4379F2BC1291AC9700D2A41E /* TException.m in Sources */,
- 4379F2BD1291AC9700D2A41E /* THTTPClient.m in Sources */,
- 4379F2BE1291AC9700D2A41E /* TMemoryBuffer.m in Sources */,
- 4379F2BF1291AC9700D2A41E /* TTransportException.m in Sources */,
- 4379F2C01291AC9700D2A41E /* TSharedProcessorFactory.m in Sources */,
- 4379F2C11291AC9700D2A41E /* SHKEvernote.m in Sources */,
4379F2EA1291AE5700D2A41E /* NSData+md5.m in Sources */,
4379F3B21291C45700D2A41E /* SHKTextMessage.m in Sources */,
+ 2896265F142C725C00BFC10F /* LFHTTPRequest.m in Sources */,
+ 28962662142C725C00BFC10F /* ObjectiveFlickr.m in Sources */,
+ 28962663142C725C00BFC10F /* OFXMLMapper.m in Sources */,
+ 28962664142C725C00BFC10F /* SHKFlickr.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};