├── TODO ├── .gitignore ├── English.lproj ├── InfoPlist.strings └── MainMenu.nib │ └── keyedobjects.nib ├── MGTwitterEngine_Prefix.pch ├── main.m ├── NSString+UUID.h ├── MGTwitterStatusesParser.h ├── MGTwitterUsersParser.h ├── MGTwitterMessagesParser.h ├── MGTwitterMiscLibXMLParser.h ├── MGTwitterUsersLibXMLParser.h ├── MGTwitterMiscParser.h ├── MGTwitterMessagesLibXMLParser.h ├── MGTwitterStatusesLibXMLParser.h ├── MGTwitterUserListsParser.h ├── MGTwitterMiscYAJLParser.h ├── MGTwitterSocialGraphParser.h ├── MGTwitterUsersYAJLParser.h ├── MGTwitterMessagesYAJLParser.h ├── MGTwitterStatusesYAJLParser.h ├── AppController.h ├── MGTwitterSocialGraphLibXMLParser.h ├── MGTwitterSearchYAJLParser.h ├── NSString+UUID.m ├── Info.plist ├── MGTwitterParserDelegate.h ├── MGTwitterUsersLibXMLParser.m ├── MGTwitterStatusesLibXMLParser.m ├── MGTwitterXMLParser.h ├── MGTwitterHTTPURLConnection.h ├── MGTwitterTouchJSONParser.h ├── MGTwitterMiscLibXMLParser.m ├── MGTwitterMiscParser.m ├── MGTwitterMiscYAJLParser.m ├── NSData+Base64.h ├── MGTwitterLibXMLParser.h ├── MGTwitterYAJLParser.h ├── MGTwitterUsersParser.m ├── MGTwitterUserListsParser.m ├── MGTwitterUsersYAJLParser.m ├── MGTwitterMessagesParser.m ├── MGTwitterSocialGraphParser.m ├── MGTwitterEngineGlobalHeader.h ├── MGTwitterHTTPURLConnection.m ├── MGTwitterMessagesYAJLParser.m ├── MGTwitterEngineDelegate.h ├── MGTwitterStatusesParser.m ├── MGTwitterSocialGraphLibXMLParser.m ├── MGTwitterStatusesYAJLParser.m ├── MGTwitterMessagesLibXMLParser.m ├── MGTwitterSearchYAJLParser.m ├── NSData+Base64.m ├── MGTwitterTouchJSONParser.m ├── MGTwitterRequestTypes.h ├── MGTwitterXMLParser.m ├── Source Code License.rtf ├── README.txt ├── AppController.m ├── MGTwitterYAJLParser.m ├── MGTwitterLibXMLParser.m ├── MGTwitterEngine.h └── MGTwitterEngine.xcodeproj └── project.pbxproj /TODO: -------------------------------------------------------------------------------- 1 | MGTwitterEngine TODO 2 | 3 | 4 | - Write a Twitter client using this code. ;) 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pbxuser 2 | *.perspectivev3 3 | *.mode1v3 4 | build 5 | yajl 6 | OAuthConsumer 7 | -------------------------------------------------------------------------------- /English.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattgemmell/MGTwitterEngine/HEAD/English.lproj/InfoPlist.strings -------------------------------------------------------------------------------- /English.lproj/MainMenu.nib/keyedobjects.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mattgemmell/MGTwitterEngine/HEAD/English.lproj/MainMenu.nib/keyedobjects.nib -------------------------------------------------------------------------------- /MGTwitterEngine_Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'MGTwitterEngine' target in the 'MGTwitterEngine' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 10/02/2008. 6 | // Copyright Instinctive Code 2008. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **) argv); 14 | } 15 | -------------------------------------------------------------------------------- /NSString+UUID.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+UUID.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 16/09/2007. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | @interface NSString (UUID) 12 | 13 | + (NSString*)stringWithNewUUID; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /MGTwitterStatusesParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterStatusesParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterXMLParser.h" 12 | 13 | @interface MGTwitterStatusesParser : MGTwitterXMLParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterUsersParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUsersParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 19/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterStatusesParser.h" 12 | 13 | @interface MGTwitterUsersParser : MGTwitterStatusesParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterMessagesParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMessagesParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 19/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterStatusesParser.h" 12 | 13 | @interface MGTwitterMessagesParser : MGTwitterStatusesParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterMiscLibXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMiscLibXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterLibXMLParser.h" 12 | 13 | @interface MGTwitterMiscLibXMLParser : MGTwitterLibXMLParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterUsersLibXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUsersLibXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterLibXMLParser.h" 12 | 13 | @interface MGTwitterUsersLibXMLParser : MGTwitterLibXMLParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterMiscParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMiscParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 06/06/2008. 6 | // Copyright 2008 Instinctive Code. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterStatusesParser.h" 12 | 13 | @interface MGTwitterMiscParser : MGTwitterStatusesParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterMessagesLibXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMessagesLibXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterLibXMLParser.h" 12 | 13 | @interface MGTwitterMessagesLibXMLParser : MGTwitterLibXMLParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterStatusesLibXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterStatusesLibXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterLibXMLParser.h" 12 | 13 | @interface MGTwitterStatusesLibXMLParser : MGTwitterLibXMLParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterUserListsParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUserListsParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Clinton Shryock on 6/10/10. 6 | // Copyright 2010 scary-robot. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterStatusesParser.h" 12 | 13 | @interface MGTwitterUserListsParser : MGTwitterStatusesParser { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterMiscYAJLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMiscYAJLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterYAJLParser.h" 12 | 13 | @interface MGTwitterMiscYAJLParser : MGTwitterYAJLParser { 14 | 15 | NSMutableDictionary *_results; 16 | 17 | } 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /MGTwitterSocialGraphParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterSocialGraphParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Robert McGovern on 2010/03/19. 6 | // Copyright 2010 Tarasis. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterStatusesParser.h" 12 | 13 | @interface MGTwitterSocialGraphParser : MGTwitterStatusesParser { 14 | NSMutableArray * twitterIDs; 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /MGTwitterUsersYAJLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUsersYAJLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterYAJLParser.h" 12 | 13 | @interface MGTwitterUsersYAJLParser : MGTwitterYAJLParser { 14 | 15 | NSMutableDictionary *_user; 16 | NSMutableDictionary *_status; 17 | 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /MGTwitterMessagesYAJLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMessagesYAJLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterYAJLParser.h" 12 | 13 | @interface MGTwitterMessagesYAJLParser : MGTwitterYAJLParser { 14 | 15 | NSMutableDictionary *_status; 16 | NSMutableDictionary *_sender; 17 | NSMutableDictionary *_recipient; 18 | 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /MGTwitterStatusesYAJLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterStatusesYAJLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterYAJLParser.h" 12 | 13 | @interface MGTwitterStatusesYAJLParser : MGTwitterYAJLParser { 14 | NSMutableArray *_dictionaries; // effectively a stack for parsing nested dictionaries 15 | NSMutableArray *_dictionaryKeys; 16 | } 17 | 18 | @end -------------------------------------------------------------------------------- /AppController.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppController.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 10/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import 10 | #import "MGTwitterEngine.h" 11 | 12 | @class OAToken; 13 | 14 | @interface AppController : NSObject { 15 | MGTwitterEngine *twitterEngine; 16 | 17 | OAToken *token; 18 | } 19 | 20 | // this gets called when the OAuth token is received 21 | -(void)runTests; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MGTwitterSocialGraphLibXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterSocialGraphLibXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Robert McGovern on 2010/03/20. 6 | // Copyright 2010 Tarasis. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterLibXMLParser.h" 12 | 13 | @interface MGTwitterSocialGraphLibXMLParser : MGTwitterLibXMLParser { 14 | NSMutableArray * twitterIDs; 15 | } 16 | 17 | - (NSDictionary *)_socialGraphDictionaryForNodeWithName:(const xmlChar *)parentNodeName; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /MGTwitterSearchYAJLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterSearchYAJLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterYAJLParser.h" 12 | 13 | @interface MGTwitterSearchYAJLParser : MGTwitterYAJLParser { 14 | BOOL insideArray; 15 | NSMutableDictionary *_status; 16 | NSMutableArray *_dictionaries; // effectively a stack for parsing nested dictionaries 17 | NSMutableArray *_dictionaryKeys; 18 | } 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /NSString+UUID.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+UUID.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 16/09/2007. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "NSString+UUID.h" 10 | 11 | 12 | @implementation NSString (UUID) 13 | 14 | 15 | + (NSString*)stringWithNewUUID 16 | { 17 | // Create a new UUID 18 | CFUUIDRef uuidObj = CFUUIDCreate(nil); 19 | 20 | // Get the string representation of the UUID 21 | NSString *newUUID = (NSString*)CFUUIDCreateString(nil, uuidObj); 22 | CFRelease(uuidObj); 23 | return [newUUID autorelease]; 24 | } 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.instinctivecode.MGTwitterEngine 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | NSMainNibFile 24 | MainMenu 25 | NSPrincipalClass 26 | NSApplication 27 | 28 | 29 | -------------------------------------------------------------------------------- /MGTwitterParserDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterParserDelegate.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterRequestTypes.h" 12 | 13 | @protocol MGTwitterParserDelegate 14 | 15 | - (void)parsingSucceededForRequest:(NSString *)identifier 16 | ofResponseType:(MGTwitterResponseType)responseType 17 | withParsedObjects:(NSArray *)parsedObjects; 18 | 19 | - (void)parsingFailedForRequest:(NSString *)requestIdentifier 20 | ofResponseType:(MGTwitterResponseType)responseType 21 | withError:(NSError *)error; 22 | 23 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 24 | - (void)parsedObject:(NSDictionary *)parsedObject forRequest:(NSString *)identifier 25 | ofResponseType:(MGTwitterResponseType)responseType; 26 | #endif 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /MGTwitterUsersLibXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUsersLibXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterUsersLibXMLParser.h" 10 | 11 | 12 | @implementation MGTwitterUsersLibXMLParser 13 | 14 | - (void)parse 15 | { 16 | int readerResult = xmlTextReaderRead(_reader); 17 | if (readerResult != 1) 18 | return; 19 | int nodeType = xmlTextReaderNodeType(_reader); 20 | const xmlChar *name = xmlTextReaderConstName(_reader); 21 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(BAD_CAST "users", name))) 22 | { 23 | if (nodeType == XML_READER_TYPE_ELEMENT) 24 | { 25 | if (xmlStrEqual(name, BAD_CAST "user")) 26 | { 27 | [parsedObjects addObject:[self _userDictionaryForNodeWithName:name]]; 28 | } 29 | } 30 | 31 | // advance reader 32 | readerResult = xmlTextReaderRead(_reader); 33 | if (readerResult != 1) 34 | { 35 | break; 36 | } 37 | nodeType = xmlTextReaderNodeType(_reader); 38 | name = xmlTextReaderConstName(_reader); 39 | } 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /MGTwitterStatusesLibXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterStatusesLibXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterStatusesLibXMLParser.h" 10 | 11 | 12 | @implementation MGTwitterStatusesLibXMLParser 13 | 14 | 15 | - (void)parse 16 | { 17 | int readerResult = xmlTextReaderRead(_reader); 18 | if (readerResult != 1) 19 | return; 20 | int nodeType = xmlTextReaderNodeType(_reader); 21 | const xmlChar *name = xmlTextReaderConstName(_reader); 22 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(BAD_CAST "statuses", name))) 23 | { 24 | if (nodeType == XML_READER_TYPE_ELEMENT) 25 | { 26 | if (xmlStrEqual(name, BAD_CAST "status")) 27 | { 28 | [parsedObjects addObject:[self _statusDictionaryForNodeWithName:name]]; 29 | } 30 | } 31 | 32 | // advance reader 33 | readerResult = xmlTextReaderRead(_reader); 34 | if (readerResult != 1) 35 | { 36 | break; 37 | } 38 | nodeType = xmlTextReaderNodeType(_reader); 39 | name = xmlTextReaderConstName(_reader); 40 | } 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /MGTwitterXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | #import "MGTwitterParserDelegate.h" 11 | 12 | @interface MGTwitterXMLParser : NSObject { 13 | __weak NSObject *delegate; // weak ref 14 | NSString *identifier; 15 | MGTwitterRequestType requestType; 16 | MGTwitterResponseType responseType; 17 | NSData *xml; 18 | NSMutableArray *parsedObjects; 19 | NSXMLParser *parser; 20 | __weak NSMutableDictionary *currentNode; 21 | NSString *lastOpenedElement; 22 | } 23 | 24 | + (id)parserWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 25 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 26 | responseType:(MGTwitterResponseType)respType; 27 | - (id)initWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 28 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 29 | responseType:(MGTwitterResponseType)respType; 30 | 31 | - (NSString *)lastOpenedElement; 32 | - (void)setLastOpenedElement:(NSString *)value; 33 | 34 | - (void)addSource; 35 | 36 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 37 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName; 38 | 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /MGTwitterHTTPURLConnection.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterHTTPURLConnection.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 16/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterRequestTypes.h" 12 | 13 | 14 | @interface MGTwitterHTTPURLConnection : NSURLConnection 15 | { 16 | NSMutableData *_data; // accumulated data received on this connection 17 | MGTwitterRequestType _requestType; // general type of this request, mostly for error handling 18 | MGTwitterResponseType _responseType; // type of response data expected (if successful) 19 | NSString *_identifier; 20 | NSURL *_URL; // the URL used for the connection (needed as a base URL when parsing with libxml) 21 | NSHTTPURLResponse * _response; // the response. 22 | } 23 | 24 | // Initializer 25 | - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate 26 | requestType:(MGTwitterRequestType)requestType responseType:(MGTwitterResponseType)responseType; 27 | 28 | // Data helper methods 29 | - (void)resetDataLength; 30 | - (void)appendData:(NSData *)data; 31 | 32 | // Accessors 33 | - (NSString *)identifier; 34 | - (NSData *)data; 35 | - (NSURL *)URL; 36 | - (MGTwitterRequestType)requestType; 37 | - (MGTwitterResponseType)responseType; 38 | - (NSString *)description; 39 | 40 | @property (nonatomic, retain) NSHTTPURLResponse *response; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /MGTwitterTouchJSONParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterTouchJSONParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Steve Streza on 3/24/10. 6 | // Copyright 2010 MGTwitterEngine. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "MGTwitterParserDelegate.h" 12 | #import "MGTwitterEngineDelegate.h" 13 | 14 | @interface MGTwitterTouchJSONParser : NSObject { 15 | __weak NSObject *delegate; // weak ref 16 | NSString *identifier; 17 | MGTwitterRequestType requestType; 18 | MGTwitterResponseType responseType; 19 | NSURL *URL; 20 | NSData *json; 21 | NSMutableArray *parsedObjects; 22 | MGTwitterEngineDeliveryOptions deliveryOptions; 23 | } 24 | 25 | + (id)parserWithJSON:(NSData *)theJSON 26 | delegate:(NSObject *)theDelegate 27 | connectionIdentifier:(NSString *)identifier 28 | requestType:(MGTwitterRequestType)reqType 29 | responseType:(MGTwitterResponseType)respType 30 | URL:(NSURL *)URL 31 | deliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions; 32 | - (id)initWithJSON:(NSData *)theJSON 33 | delegate:(NSObject *)theDelegate 34 | connectionIdentifier:(NSString *)identifier 35 | requestType:(MGTwitterRequestType)reqType 36 | responseType:(MGTwitterResponseType)respType 37 | URL:(NSURL *)URL 38 | deliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions; 39 | 40 | // delegate callbacks 41 | - (void)_parsingDidEnd; 42 | - (void)_parsingErrorOccurred:(NSError *)parseError; 43 | - (void)_parsedObject:(NSDictionary *)dictionary; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /MGTwitterMiscLibXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMiscLibXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterMiscLibXMLParser.h" 10 | 11 | 12 | @implementation MGTwitterMiscLibXMLParser 13 | 14 | - (void)parse 15 | { 16 | int readerResult = xmlTextReaderRead(_reader); 17 | if (readerResult != 1) 18 | return; 19 | 20 | int nodeType = xmlTextReaderNodeType(_reader); 21 | const xmlChar *name = xmlTextReaderConstName(_reader); 22 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT)) 23 | { 24 | if (nodeType == XML_READER_TYPE_ELEMENT) 25 | { 26 | if (xmlStrEqual(name, BAD_CAST "hash")) 27 | { 28 | [parsedObjects addObject:[self _hashDictionaryForNodeWithName:name]]; 29 | } 30 | else 31 | { 32 | // process element as a string -- API calls like friendships/exists.xml just return false or true 33 | NSString *string = [self _nodeValueAsString]; 34 | if (string) 35 | { 36 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 37 | [dictionary setObject:string forKey:[NSString stringWithUTF8String:(const char *)name]]; 38 | [parsedObjects addObject:dictionary]; 39 | } 40 | } 41 | } 42 | 43 | // advance reader 44 | readerResult = xmlTextReaderRead(_reader); 45 | if (readerResult != 1) 46 | { 47 | break; 48 | } 49 | nodeType = xmlTextReaderNodeType(_reader); 50 | name = xmlTextReaderConstName(_reader); 51 | } 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /MGTwitterMiscParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMiscParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 06/06/2008. 6 | // Copyright 2008 Instinctive Code. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterMiscParser.h" 10 | 11 | 12 | @implementation MGTwitterMiscParser 13 | 14 | 15 | #pragma mark NSXMLParser delegate methods 16 | 17 | 18 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 19 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 20 | attributes:(NSDictionary *)attributeDict 21 | { 22 | //NSLog(@"Started element: %@ (%@)", elementName, attributeDict); 23 | [self setLastOpenedElement:elementName]; 24 | 25 | if (!currentNode) { 26 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 27 | [parsedObjects addObject:newNode]; 28 | currentNode = newNode; 29 | } 30 | 31 | // Create relevant name-value pair. 32 | [currentNode setObject:[NSMutableString string] forKey:elementName]; 33 | } 34 | 35 | 36 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 37 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 38 | { 39 | [super parser:theParser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName]; 40 | 41 | if ([elementName isEqualToString:@"remaining_hits"]) { 42 | NSNumber *hits = [NSNumber numberWithInt:[[currentNode objectForKey:elementName] intValue]]; 43 | [currentNode setObject:hits forKey:elementName]; 44 | } 45 | } 46 | 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /MGTwitterMiscYAJLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMiscYAJLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterMiscYAJLParser.h" 10 | 11 | #define DEBUG_PARSING 0 12 | 13 | @implementation MGTwitterMiscYAJLParser 14 | 15 | - (void)addValue:(id)value forKey:(NSString *)key 16 | { 17 | if (_results) 18 | { 19 | [_results setObject:value forKey:key]; 20 | #if DEBUG_PARSING 21 | NSLog(@"misc: results: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 22 | #endif 23 | } 24 | } 25 | 26 | - (void)startDictionaryWithKey:(NSString *)key 27 | { 28 | #if DEBUG_PARSING 29 | NSLog(@"misc: dictionary start = %@", key); 30 | #endif 31 | 32 | if (! _results) 33 | { 34 | _results = [[NSMutableDictionary alloc] initWithCapacity:0]; 35 | } 36 | } 37 | 38 | - (void)endDictionary 39 | { 40 | [_results setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 41 | 42 | [self _parsedObject:_results]; 43 | 44 | if(_results){ 45 | [parsedObjects addObject:_results]; 46 | } 47 | 48 | [_results release]; 49 | _results = nil; 50 | 51 | #if DEBUG_PARSING 52 | NSLog(@"misc: dictionary end"); 53 | #endif 54 | } 55 | 56 | - (void)startArrayWithKey:(NSString *)key 57 | { 58 | #if DEBUG_PARSING 59 | NSLog(@"misc: array start = %@", key); 60 | #endif 61 | } 62 | 63 | - (void)endArray 64 | { 65 | #if DEBUG_PARSING 66 | NSLog(@"misc: array end"); 67 | #endif 68 | } 69 | 70 | - (void)dealloc 71 | { 72 | [_results release]; 73 | 74 | [super dealloc]; 75 | } 76 | 77 | @end 78 | -------------------------------------------------------------------------------- /NSData+Base64.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.m 3 | // 4 | // Derived from http://colloquy.info/project/browser/trunk/NSDataAdditions.h?rev=1576 5 | // Created by khammond on Mon Oct 29 2001. 6 | // Formatted by Timothy Hatcher on Sun Jul 4 2004. 7 | // Copyright (c) 2001 Kyle Hammond. All rights reserved. 8 | // Original development by Dave Winer. 9 | // 10 | 11 | #import "MGTwitterEngineGlobalHeader.h" 12 | 13 | @interface NSData (Base64) 14 | 15 | /*! @function +dataWithBase64EncodedString: 16 | @discussion This method returns an autoreleased NSData object. The NSData object is initialized with the 17 | contents of the Base 64 encoded string. This is a convenience method. 18 | @param inBase64String An NSString object that contains only Base 64 encoded data. 19 | @result The NSData object. */ 20 | + (NSData *) dataWithBase64EncodedString:(NSString *) string; 21 | 22 | /*! @function -initWithBase64EncodedString: 23 | @discussion The NSData object is initialized with the contents of the Base 64 encoded string. 24 | This method returns self as a convenience. 25 | @param inBase64String An NSString object that contains only Base 64 encoded data. 26 | @result This method returns self. */ 27 | - (id) initWithBase64EncodedString:(NSString *) string; 28 | 29 | /*! @function -base64EncodingWithLineLength: 30 | @discussion This method returns a Base 64 encoded string representation of the data object. 31 | @param inLineLength A value of zero means no line breaks. This is crunched to a multiple of 4 (the next 32 | one greater than inLineLength). 33 | @result The base 64 encoded data. */ 34 | - (NSString *) base64EncodingWithLineLength:(unsigned int) lineLength; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /MGTwitterLibXMLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterLibXMLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | #include 11 | 12 | #import "MGTwitterParserDelegate.h" 13 | 14 | @interface MGTwitterLibXMLParser : NSObject { 15 | __weak NSObject *delegate; // weak ref 16 | NSString *identifier; 17 | MGTwitterRequestType requestType; 18 | MGTwitterResponseType responseType; 19 | NSURL *URL; 20 | NSData *xml; 21 | NSMutableArray *parsedObjects; 22 | 23 | xmlTextReaderPtr _reader; 24 | } 25 | 26 | + (id)parserWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 27 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 28 | responseType:(MGTwitterResponseType)respType URL:(NSURL *)URL; 29 | - (id)initWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 30 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 31 | responseType:(MGTwitterResponseType)respType URL:(NSURL *)URL; 32 | 33 | - (void)parse; 34 | 35 | // subclass utilities 36 | - (xmlChar *)_nodeValue; 37 | - (NSString *)_nodeValueAsString; 38 | - (NSDate *)_nodeValueAsDate; 39 | - (NSNumber *)_nodeValueAsInt; 40 | - (NSNumber *)_nodeValueAsBool; 41 | - (NSDictionary *)_statusDictionaryForNodeWithName:(const xmlChar *)parentNodeName; 42 | - (NSDictionary *)_userDictionaryForNodeWithName:(const xmlChar *)parentNodeName; 43 | - (NSDictionary *)_hashDictionaryForNodeWithName:(const xmlChar *)parentNodeName; 44 | 45 | // delegate callbacks 46 | - (void)_parsingDidEnd; 47 | - (void)_parsingErrorOccurred:(NSError *)parseError; 48 | 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /MGTwitterYAJLParser.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterYAJLParser.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | //#include 12 | #import "yajl_parse.h" 13 | 14 | #import "MGTwitterParserDelegate.h" 15 | #import "MGTwitterEngineDelegate.h" 16 | 17 | @interface MGTwitterYAJLParser : NSObject { 18 | __weak NSObject *delegate; // weak ref 19 | NSString *identifier; 20 | MGTwitterRequestType requestType; 21 | MGTwitterResponseType responseType; 22 | NSURL *URL; 23 | NSData *json; 24 | NSMutableArray *parsedObjects; 25 | MGTwitterEngineDeliveryOptions deliveryOptions; 26 | 27 | yajl_handle _handle; 28 | NSUInteger arrayDepth; 29 | } 30 | 31 | + (id)parserWithJSON:(NSData *)theJSON 32 | delegate:(NSObject *)theDelegate 33 | connectionIdentifier:(NSString *)identifier 34 | requestType:(MGTwitterRequestType)reqType 35 | responseType:(MGTwitterResponseType)respType 36 | URL:(NSURL *)URL 37 | deliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions; 38 | - (id)initWithJSON:(NSData *)theJSON 39 | delegate:(NSObject *)theDelegate 40 | connectionIdentifier:(NSString *)identifier 41 | requestType:(MGTwitterRequestType)reqType 42 | responseType:(MGTwitterResponseType)respType 43 | URL:(NSURL *)URL 44 | deliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions; 45 | - (void)clearCurrentKey; 46 | 47 | // subclass utilities 48 | - (void)addValue:(id)value forKey:(NSString *)key; 49 | - (void)addValue:(id)value forKey:(NSString *)key; 50 | - (void)startDictionaryWithKey:(NSString *)key; 51 | - (void)endDictionary; 52 | - (void)startArrayWithKey:(NSString *)key; 53 | - (void)endArray; 54 | 55 | // delegate callbacks 56 | - (void)_parsingDidEnd; 57 | - (void)_parsingErrorOccurred:(NSError *)parseError; 58 | - (void)_parsedObject:(NSDictionary *)dictionary; 59 | 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /MGTwitterUsersParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUsersParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 19/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterUsersParser.h" 10 | 11 | 12 | @implementation MGTwitterUsersParser 13 | 14 | 15 | #pragma mark NSXMLParser delegate methods 16 | 17 | 18 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 19 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 20 | attributes:(NSDictionary *)attributeDict 21 | { 22 | //NSLog(@"Started element: %@ (%@)", elementName, attributeDict); 23 | [self setLastOpenedElement:elementName]; 24 | 25 | if ([elementName isEqualToString:@"user"]) { 26 | // Make new entry in parsedObjects. 27 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 28 | [parsedObjects addObject:newNode]; 29 | currentNode = newNode; 30 | } else if ([elementName isEqualToString:@"status"]) { 31 | // Add an appropriate dictionary to current node. 32 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 33 | [currentNode setObject:newNode forKey:elementName]; 34 | currentNode = newNode; 35 | } else if (currentNode) { 36 | // Create relevant name-value pair. 37 | [currentNode setObject:[NSMutableString string] forKey:elementName]; 38 | } 39 | } 40 | 41 | 42 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 43 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 44 | { 45 | [super parser:theParser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName]; 46 | 47 | if ([elementName isEqualToString:@"status"]) { 48 | currentNode = [parsedObjects lastObject]; 49 | } else if ([elementName isEqualToString:@"user"]) { 50 | [self addSource]; 51 | currentNode = nil; 52 | } 53 | } 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /MGTwitterUserListsParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUserListsParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Clinton Shryock on 6/10/10. 6 | // Copyright 2010 scary-robot. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterUserListsParser.h" 10 | 11 | 12 | @implementation MGTwitterUserListsParser 13 | 14 | #pragma mark NSXMLParser delegate methods 15 | 16 | 17 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 18 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 19 | attributes:(NSDictionary *)attributeDict 20 | { 21 | //NSLog(@"Started element: %@ (%@)", elementName, attributeDict); 22 | [self setLastOpenedElement:elementName]; 23 | 24 | if ([elementName isEqualToString:@"list"]) { 25 | // Make new entry in parsedObjects. 26 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 27 | [parsedObjects addObject:newNode]; 28 | currentNode = newNode; 29 | } else if ([elementName isEqualToString:@"user"]) { 30 | // Add a 'user' dictionary to current node. 31 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 32 | [currentNode setObject:newNode forKey:elementName]; 33 | currentNode = newNode; 34 | } else if (currentNode) { 35 | // Create relevant name-value pair. 36 | [currentNode setObject:[NSMutableString string] forKey:elementName]; 37 | } 38 | } 39 | 40 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 41 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 42 | { 43 | [super parser:theParser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName]; 44 | 45 | if ([elementName isEqualToString:@"list"]) { 46 | currentNode = [parsedObjects lastObject]; 47 | } else if ([elementName isEqualToString:@"user"]) { 48 | [self addSource]; 49 | currentNode = nil; 50 | } 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /MGTwitterUsersYAJLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterUsersYAJLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterUsersYAJLParser.h" 10 | 11 | #define DEBUG_PARSING 0 12 | 13 | @implementation MGTwitterUsersYAJLParser 14 | 15 | - (void)addValue:(id)value forKey:(NSString *)key 16 | { 17 | if (_status) 18 | { 19 | [_status setObject:value forKey:key]; 20 | #if DEBUG_PARSING 21 | NSLog(@"user: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 22 | #endif 23 | } 24 | else if (_user) 25 | { 26 | [_user setObject:value forKey:key]; 27 | #if DEBUG_PARSING 28 | NSLog(@"user: user: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 29 | #endif 30 | } 31 | } 32 | 33 | - (void)startDictionaryWithKey:(NSString *)key 34 | { 35 | #if DEBUG_PARSING 36 | NSLog(@"user: dictionary start = %@", key); 37 | #endif 38 | 39 | if (! _user) 40 | { 41 | _user = [[NSMutableDictionary alloc] initWithCapacity:0]; 42 | } 43 | else 44 | { 45 | if (! _status) 46 | { 47 | _status = [[NSMutableDictionary alloc] initWithCapacity:0]; 48 | } 49 | } 50 | } 51 | 52 | - (void)endDictionary 53 | { 54 | if (_status) 55 | { 56 | [_user setObject:_status forKey:@"status"]; 57 | [_status release]; 58 | _status = nil; 59 | } 60 | else 61 | { 62 | [_user setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 63 | 64 | [self _parsedObject:_user]; 65 | 66 | [parsedObjects addObject:_user]; 67 | [_user release]; 68 | _user = nil; 69 | } 70 | 71 | #if DEBUG_PARSING 72 | NSLog(@"user: dictionary end"); 73 | #endif 74 | } 75 | 76 | - (void)startArrayWithKey:(NSString *)key 77 | { 78 | #if DEBUG_PARSING 79 | NSLog(@"user: array start = %@", key); 80 | #endif 81 | } 82 | 83 | - (void)endArray 84 | { 85 | #if DEBUG_PARSING 86 | NSLog(@"user: array end"); 87 | #endif 88 | } 89 | 90 | - (void)dealloc 91 | { 92 | [_user release]; 93 | [_status release]; 94 | 95 | [super dealloc]; 96 | } 97 | 98 | @end 99 | -------------------------------------------------------------------------------- /MGTwitterMessagesParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMessagesParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 19/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterMessagesParser.h" 10 | 11 | 12 | @implementation MGTwitterMessagesParser 13 | 14 | 15 | #pragma mark NSXMLParser delegate methods 16 | 17 | 18 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 19 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 20 | attributes:(NSDictionary *)attributeDict 21 | { 22 | //NSLog(@"Started element: %@ (%@)", elementName, attributeDict); 23 | [self setLastOpenedElement:elementName]; 24 | 25 | if ([elementName isEqualToString:@"direct_message"]) { 26 | // Make new entry in parsedObjects. 27 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 28 | [parsedObjects addObject:newNode]; 29 | currentNode = newNode; 30 | } else if ([elementName isEqualToString:@"sender"] || [elementName isEqualToString:@"recipient"]) { 31 | // Add an appropriate dictionary to current node. 32 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 33 | [currentNode setObject:newNode forKey:elementName]; 34 | currentNode = newNode; 35 | } else if (currentNode) { 36 | // Create relevant name-value pair. 37 | [currentNode setObject:[NSMutableString string] forKey:elementName]; 38 | } 39 | } 40 | 41 | 42 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 43 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 44 | { 45 | [super parser:theParser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName]; 46 | 47 | if ([elementName isEqualToString:@"sender"] || [elementName isEqualToString:@"recipient"]) { 48 | currentNode = [parsedObjects lastObject]; 49 | } else if ([elementName isEqualToString:@"direct_message"]) { 50 | [self addSource]; 51 | currentNode = nil; 52 | } 53 | } 54 | 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /MGTwitterSocialGraphParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterSocialGraphParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Robert McGovern on 2010/03/19. 6 | // Copyright 2010 Tarasis. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterSocialGraphParser.h" 10 | #import "MGTwitterMiscParser.h" 11 | 12 | 13 | @implementation MGTwitterSocialGraphParser 14 | 15 | 16 | #pragma mark NSXMLParser delegate methods 17 | 18 | 19 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 20 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 21 | attributes:(NSDictionary *)attributeDict 22 | { 23 | //NSLog(@"SG: Started element: %@ (%@)", elementName, attributeDict); 24 | [self setLastOpenedElement:elementName]; 25 | 26 | if ([elementName isEqualToString:@"ids"]) { 27 | twitterIDs = [NSMutableArray arrayWithCapacity:0]; 28 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 29 | [parsedObjects addObject:newNode]; 30 | currentNode = newNode; 31 | } else if (currentNode && ![elementName isEqualToString:@"id"]) { 32 | // Create relevant name-value pair. 33 | [currentNode setObject:[NSMutableString string] forKey:elementName]; 34 | } 35 | } 36 | 37 | - (void)parser:(NSXMLParser *)theParser foundCharacters:(NSString *)characters 38 | { 39 | //NSLog(@"SG: Found characters: %@", characters); 40 | // Add the Twitter ID to the array 41 | if ([lastOpenedElement isEqualToString:@"id"]) { 42 | [twitterIDs addObject:characters]; 43 | // Append found characters to value of lastOpenedElement in currentNode. 44 | } else if (lastOpenedElement && currentNode) { 45 | [[currentNode objectForKey:lastOpenedElement] appendString:characters]; 46 | } 47 | } 48 | 49 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 50 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 51 | { 52 | //NSLog(@"SG: didEndElement: %@", elementName); 53 | 54 | [super parser:theParser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName]; 55 | 56 | // At the end of parsing, add the source type 57 | if ([elementName isEqualToString:@"id_list"]) { 58 | [self addSource]; 59 | currentNode = nil; 60 | } else if ([elementName isEqualToString:@"ids"]) { 61 | [currentNode setObject:twitterIDs forKey:elementName]; 62 | currentNode = [parsedObjects lastObject]; 63 | } 64 | } 65 | 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /MGTwitterEngineGlobalHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterEngineGlobalHeader.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 09/08/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | /* 10 | This file conditionally includes the correct headers for either Mac OS X or iPhone deployment. 11 | */ 12 | 13 | #if TARGET_OS_IPHONE 14 | #import 15 | #import 16 | #else 17 | #import 18 | #endif 19 | 20 | /* 21 | Set YAJL_AVAILABLE to 1 if the YAJL JSON parser is available and you'd like MGTwitterEngine to use it. 22 | 23 | More information about this parser here: 24 | 25 | http://lloydforge.org/projects/yajl/ 26 | 27 | There are some speed advantages to using JSON instead of XML. Also, the Twitter Search API 28 | uses JSON, so adding this library to your project makes additional methods available to your 29 | application. 30 | 31 | Be aware, however, that the data types in the dictionaries returned by JSON may be different 32 | than the ones returned by XML. There is more type information in a JSON stream, so you may find 33 | that you get an NSNumber value instead of an NSString value for some keys in the dictionary. 34 | Make sure to test the new result sets in your application after switching from XML to JSON. 35 | 36 | Likewise, some keys may differ between the XML and JSON parsers. An example is the hourly limit 37 | returned by the getRateLimitStatus: method. For JSON, the key is "hourly_limit", for XML it is 38 | "hourly-limit". 39 | 40 | The event driven nature of the YAJL parser also allows delivery options to be specified. By 41 | default, all results are returned as an array of dictionaries. In some environments, such as the 42 | iPhone, the memory overhead of putting all the data into the array can be avoided by choosing 43 | the individual results option. This allows your application to process and store results without 44 | instantatiating a large collection and then enumerating over the items. 45 | 46 | If you want to use YAJL, change the following definition and make sure that the 47 | MGTwitterEngine*YAJLParser.m files are added to the Compile Sources phase of the MGTwitterEngine 48 | target. 49 | */ 50 | 51 | #define YAJL_AVAILABLE 0 52 | #define TOUCHJSON_AVAILABLE 0 53 | 54 | #ifndef __MGTWITTERENGINEID__ 55 | #define __MGTWITTERENGINEID__ 56 | typedef unsigned long long MGTwitterEngineID; 57 | typedef long long MGTwitterEngineCursorID; 58 | #endif 59 | 60 | #ifndef __MGTWITTERENGINELOCATIONDEGREES__ 61 | #define __MGTWITTERENGINELOCATIONDEGREES__ 62 | typedef double MGTwitterEngineLocationDegrees; 63 | #endif 64 | -------------------------------------------------------------------------------- /MGTwitterHTTPURLConnection.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterHTTPURLConnection.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 16/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterHTTPURLConnection.h" 10 | #import "NSString+UUID.h" 11 | 12 | 13 | 14 | @interface NSURLRequest (OAuthExtensions) 15 | -(void)prepare; 16 | @end 17 | 18 | @implementation NSURLRequest (OAuthExtensions) 19 | 20 | -(void)prepare{ 21 | // do nothing 22 | } 23 | 24 | @end 25 | 26 | 27 | 28 | @implementation MGTwitterHTTPURLConnection 29 | 30 | 31 | @synthesize response = _response; 32 | 33 | #pragma mark Initializer 34 | 35 | 36 | - (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate 37 | requestType:(MGTwitterRequestType)requestType responseType:(MGTwitterResponseType)responseType 38 | { 39 | // OAuth requests need to have -prepare called on them first. handle that case before the NSURLConnection sends it 40 | [request prepare]; 41 | 42 | if ((self = [super initWithRequest:request delegate:delegate])) { 43 | _data = [[NSMutableData alloc] initWithCapacity:0]; 44 | _identifier = [[NSString stringWithNewUUID] retain]; 45 | _requestType = requestType; 46 | _responseType = responseType; 47 | _URL = [[request URL] retain]; 48 | } 49 | 50 | return self; 51 | } 52 | 53 | 54 | - (void)dealloc 55 | { 56 | [_response release]; 57 | [_data release]; 58 | [_identifier release]; 59 | [_URL release]; 60 | [super dealloc]; 61 | } 62 | 63 | 64 | #pragma mark Data helper methods 65 | 66 | 67 | - (void)resetDataLength 68 | { 69 | [_data setLength:0]; 70 | } 71 | 72 | 73 | - (void)appendData:(NSData *)data 74 | { 75 | [_data appendData:data]; 76 | } 77 | 78 | 79 | #pragma mark Accessors 80 | 81 | 82 | - (NSString *)identifier 83 | { 84 | return [[_identifier retain] autorelease]; 85 | } 86 | 87 | 88 | - (NSData *)data 89 | { 90 | return [[_data retain] autorelease]; 91 | } 92 | 93 | 94 | - (NSURL *)URL 95 | { 96 | return [[_URL retain] autorelease]; 97 | } 98 | 99 | 100 | - (MGTwitterRequestType)requestType 101 | { 102 | return _requestType; 103 | } 104 | 105 | 106 | - (MGTwitterResponseType)responseType 107 | { 108 | return _responseType; 109 | } 110 | 111 | 112 | - (NSString *)description 113 | { 114 | NSString *description = [super description]; 115 | 116 | return [description stringByAppendingFormat:@" (requestType = %d, identifier = %@)", _requestType, _identifier]; 117 | } 118 | 119 | @end 120 | -------------------------------------------------------------------------------- /MGTwitterMessagesYAJLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMessagesYAJLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterMessagesYAJLParser.h" 10 | 11 | #define DEBUG_PARSING 0 12 | 13 | @implementation MGTwitterMessagesYAJLParser 14 | 15 | - (void)addValue:(id)value forKey:(NSString *)key 16 | { 17 | if (_sender) 18 | { 19 | [_sender setObject:value forKey:key]; 20 | #if DEBUG_PARSING 21 | NSLog(@"messages: sender: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 22 | #endif 23 | } 24 | else if (_recipient) 25 | { 26 | [_recipient setObject:value forKey:key]; 27 | #if DEBUG_PARSING 28 | NSLog(@"messages: recipient: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 29 | #endif 30 | } 31 | else if (_status) 32 | { 33 | [_status setObject:value forKey:key]; 34 | #if DEBUG_PARSING 35 | NSLog(@"messages: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 36 | #endif 37 | } 38 | } 39 | 40 | - (void)startDictionaryWithKey:(NSString *)key 41 | { 42 | #if DEBUG_PARSING 43 | NSLog(@"messages: dictionary start = %@", key); 44 | #endif 45 | 46 | if (! _status) 47 | { 48 | _status = [[NSMutableDictionary alloc] initWithCapacity:0]; 49 | } 50 | else 51 | { 52 | if ([key isEqualToString:@"sender"]) 53 | { 54 | _sender = [[NSMutableDictionary alloc] initWithCapacity:0]; 55 | } 56 | else 57 | { 58 | _recipient = [[NSMutableDictionary alloc] initWithCapacity:0]; 59 | } 60 | } 61 | } 62 | 63 | - (void)endDictionary 64 | { 65 | if (_sender) 66 | { 67 | [_status setObject:_sender forKey:@"sender"]; 68 | [_sender release]; 69 | _sender = nil; 70 | } 71 | else if (_recipient) 72 | { 73 | [_status setObject:_recipient forKey:@"recipient"]; 74 | [_recipient release]; 75 | _recipient = nil; 76 | } 77 | else 78 | { 79 | [_status setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 80 | 81 | [self _parsedObject:_status]; 82 | 83 | [parsedObjects addObject:_status]; 84 | [_status release]; 85 | _status = nil; 86 | } 87 | 88 | #if DEBUG_PARSING 89 | NSLog(@"messages: dictionary end"); 90 | #endif 91 | } 92 | 93 | - (void)startArrayWithKey:(NSString *)key 94 | { 95 | #if DEBUG_PARSING 96 | NSLog(@"messages: array start = %@", key); 97 | #endif 98 | } 99 | 100 | - (void)endArray 101 | { 102 | #if DEBUG_PARSING 103 | NSLog(@"messages: array end"); 104 | #endif 105 | } 106 | 107 | - (void)dealloc 108 | { 109 | [_status release]; 110 | [_sender release]; 111 | [_recipient release]; 112 | 113 | [super dealloc]; 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /MGTwitterEngineDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterEngineDelegate.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 16/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | @class OAToken; 11 | 12 | typedef enum _MGTwitterEngineDeliveryOptions { 13 | // all results will be delivered as an array via statusesReceived: and similar delegate methods 14 | MGTwitterEngineDeliveryAllResultsOption = 1 << 0, 15 | 16 | // individual results will be delivered as a dictionary via the receivedObject: delegate method 17 | MGTwitterEngineDeliveryIndividualResultsOption = 1 << 1, 18 | 19 | // these options can be combined with the | operator 20 | } MGTwitterEngineDeliveryOptions; 21 | 22 | 23 | 24 | @protocol MGTwitterEngineDelegate 25 | 26 | // These delegate methods are called after a connection has been established 27 | - (void)requestSucceeded:(NSString *)connectionIdentifier; 28 | - (void)requestFailed:(NSString *)connectionIdentifier withError:(NSError *)error; 29 | 30 | @optional 31 | 32 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 33 | // This delegate method is called each time a new result is parsed from the connection and 34 | // the deliveryOption is configured for MGTwitterEngineDeliveryIndividualResults. 35 | - (void)receivedObject:(NSDictionary *)dictionary forRequest:(NSString *)connectionIdentifier; 36 | #endif 37 | 38 | // These delegate methods are called after all results are parsed from the connection. If 39 | // the deliveryOption is configured for MGTwitterEngineDeliveryAllResults (the default), a 40 | // collection of all results is also returned. 41 | - (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier; 42 | - (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)connectionIdentifier; 43 | - (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier; 44 | - (void)userListsReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier; 45 | - (void)miscInfoReceived:(NSArray *)miscInfo forRequest:(NSString *)connectionIdentifier; 46 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 47 | - (void)searchResultsReceived:(NSArray *)searchResults forRequest:(NSString *)connectionIdentifier; 48 | #endif 49 | - (void)socialGraphInfoReceived:(NSArray *)socialGraphInfo forRequest:(NSString *)connectionIdentifier; 50 | - (void)accessTokenReceived:(OAToken *)token forRequest:(NSString *)connectionIdentifier; 51 | 52 | #if TARGET_OS_IPHONE 53 | - (void)imageReceived:(UIImage *)image forRequest:(NSString *)connectionIdentifier; 54 | #else 55 | - (void)imageReceived:(NSImage *)image forRequest:(NSString *)connectionIdentifier; 56 | #endif 57 | 58 | // This delegate method is called whenever a connection has finished. 59 | - (void)connectionStarted:(NSString *)connectionIdentifier; 60 | - (void)connectionFinished:(NSString *)connectionIdentifier; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /MGTwitterStatusesParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterStatusesParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterStatusesParser.h" 10 | 11 | 12 | @implementation MGTwitterStatusesParser 13 | 14 | 15 | #pragma mark NSXMLParser delegate methods 16 | 17 | 18 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 19 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 20 | attributes:(NSDictionary *)attributeDict 21 | { 22 | //NSLog(@"Started element: %@ (%@)", elementName, attributeDict); 23 | [self setLastOpenedElement:elementName]; 24 | 25 | if ([elementName isEqualToString:@"status"]) { 26 | // Make new entry in parsedObjects. 27 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 28 | [parsedObjects addObject:newNode]; 29 | currentNode = newNode; 30 | } else if ([elementName isEqualToString:@"user"]) { 31 | // Add a 'user' dictionary to current node. 32 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 33 | [currentNode setObject:newNode forKey:elementName]; 34 | currentNode = newNode; 35 | } else if ([elementName isEqualToString:@"place"]) { 36 | // Add a 'place' dictionary to current node. 37 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 38 | [currentNode setObject:newNode forKey:elementName]; 39 | currentNode = newNode; 40 | } else if ([elementName isEqualToString:@"retweeted_status"]) { 41 | // Add a 'retweet_status' dictionary to current node. 42 | NSMutableDictionary *newNode = [NSMutableDictionary dictionaryWithCapacity:0]; 43 | [currentNode setObject:newNode forKey:elementName]; 44 | currentNode = newNode; 45 | } else if (currentNode) { 46 | // Create relevant name-value pair. 47 | [currentNode setObject:[NSMutableString string] forKey:elementName]; 48 | } 49 | } 50 | 51 | 52 | - (void)parser:(NSXMLParser *)theParser foundCharacters:(NSString *)characters 53 | { 54 | //NSLog(@"Found characters: %@", characters); 55 | // Append found characters to value of lastOpenedElement in currentNode. 56 | if (lastOpenedElement && currentNode) { 57 | [[currentNode objectForKey:lastOpenedElement] appendString:characters]; 58 | } 59 | } 60 | 61 | 62 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 63 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 64 | { 65 | [super parser:theParser didEndElement:elementName namespaceURI:namespaceURI qualifiedName:qName]; 66 | 67 | if ([elementName isEqualToString:@"user"]) { 68 | currentNode = [parsedObjects lastObject]; 69 | } else if ([elementName isEqualToString:@"place"]) { 70 | currentNode = [parsedObjects lastObject]; 71 | } else if ([elementName isEqualToString:@"retweeted_status"]) { 72 | currentNode = [parsedObjects lastObject]; 73 | } else if ([elementName isEqualToString:@"status"]) { 74 | [self addSource]; 75 | currentNode = nil; 76 | } 77 | } 78 | 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /MGTwitterSocialGraphLibXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterSocialGraphLibXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Robert McGovern on 2010/03/20. 6 | // Copyright 2010 Tarasis. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterSocialGraphLibXMLParser.h" 10 | 11 | 12 | @implementation MGTwitterSocialGraphLibXMLParser 13 | - (void)parse 14 | { 15 | int readerResult = xmlTextReaderRead(_reader); 16 | if (readerResult != 1) 17 | return; 18 | 19 | int nodeType = xmlTextReaderNodeType(_reader); 20 | const xmlChar *name = xmlTextReaderConstName(_reader); 21 | 22 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 23 | 24 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT)) 25 | { 26 | //NSLog(@"name is: %@", [NSString stringWithUTF8String:(const char *)name]); 27 | if (nodeType == XML_READER_TYPE_ELEMENT) 28 | { 29 | if (xmlStrEqual(name, BAD_CAST "ids")) 30 | { 31 | [dictionary addEntriesFromDictionary:[self _socialGraphDictionaryForNodeWithName:name]]; 32 | } 33 | else if (xmlStrEqual(BAD_CAST "previous_cursor", name) || xmlStrEqual(BAD_CAST "next_cursor", name)) 34 | { 35 | // process element as a string -- API calls like friendships/exists.xml just return false or true 36 | NSString *string = [self _nodeValueAsString]; 37 | if (string) 38 | { 39 | [dictionary setObject:string forKey:[NSString stringWithUTF8String:(const char *)name]]; 40 | } 41 | } 42 | 43 | } 44 | 45 | // advance reader 46 | readerResult = xmlTextReaderRead(_reader); 47 | if (readerResult != 1) 48 | { 49 | break; 50 | } 51 | nodeType = xmlTextReaderNodeType(_reader); 52 | name = xmlTextReaderConstName(_reader); 53 | } 54 | 55 | [dictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 56 | [parsedObjects addObject:dictionary]; 57 | } 58 | 59 | - (NSDictionary *)_socialGraphDictionaryForNodeWithName:(const xmlChar *)parentNodeName 60 | { 61 | if (xmlTextReaderIsEmptyElement(_reader)) 62 | return nil; 63 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 64 | twitterIDs = [NSMutableArray arrayWithCapacity:0]; 65 | 66 | int readerResult = xmlTextReaderRead(_reader); 67 | if (readerResult != 1) 68 | return nil; 69 | int nodeType = xmlTextReaderNodeType(_reader); 70 | const xmlChar *name = xmlTextReaderConstName(_reader); 71 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(parentNodeName, name))) 72 | { 73 | if (nodeType == XML_READER_TYPE_ELEMENT) 74 | { 75 | //NSLog(@" name is: %@", [NSString stringWithUTF8String:(const char *)name]); 76 | // process element as an integer 77 | NSNumber *number = [self _nodeValueAsInt]; 78 | if (number) 79 | { 80 | //[dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 81 | [twitterIDs addObject:number]; 82 | } 83 | } 84 | 85 | // advance reader 86 | readerResult = xmlTextReaderRead(_reader); 87 | if (readerResult != 1) 88 | break; 89 | nodeType = xmlTextReaderNodeType(_reader); 90 | name = xmlTextReaderConstName(_reader); 91 | } 92 | 93 | [dictionary setObject:twitterIDs forKey:[NSString stringWithUTF8String:(const char *)name]]; 94 | 95 | return dictionary; 96 | } 97 | 98 | 99 | @end 100 | -------------------------------------------------------------------------------- /MGTwitterStatusesYAJLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterStatusesYAJLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterStatusesYAJLParser.h" 10 | 11 | #define DEBUG_PARSING 0 12 | 13 | @implementation MGTwitterStatusesYAJLParser 14 | 15 | - (void)addValue:(id)value forKey:(NSString *)key 16 | { 17 | //if for some reason there are no dictionaries, exit here 18 | if (!_dictionaries || [_dictionaries count] == 0) 19 | { 20 | return; 21 | } 22 | 23 | NSMutableDictionary *lastDictionary = [_dictionaries lastObject]; 24 | if([[lastDictionary objectForKey:key] isKindOfClass:[NSArray class]]){ 25 | NSMutableArray *array = [lastDictionary objectForKey:key]; 26 | [array addObject:value]; 27 | }else{ 28 | [lastDictionary setObject:value forKey:key]; 29 | } 30 | 31 | #if DEBUG_PARSING 32 | NSLog(@"parsed item: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 33 | #endif 34 | } 35 | 36 | - (void)startDictionaryWithKey:(NSString *)key 37 | { 38 | #if DEBUG_PARSING 39 | NSLog(@"status: dictionary start = %@", key); 40 | #endif 41 | 42 | if (!_dictionaries) 43 | { 44 | _dictionaries = [[NSMutableArray alloc] init]; 45 | } 46 | 47 | if (!_dictionaryKeys) 48 | { 49 | _dictionaryKeys = [[NSMutableArray alloc] init]; 50 | } 51 | 52 | //add a new dictionary to the array 53 | NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] initWithCapacity:0]; 54 | [_dictionaries addObject:newDictionary]; 55 | [newDictionary release]; 56 | 57 | //add a key for the above dictionary to the array 58 | [_dictionaryKeys addObject:(key) ? key : @""]; 59 | } 60 | 61 | - (void)endDictionary 62 | { 63 | if (_dictionaries && _dictionaryKeys && [_dictionaries count] > 0 && [_dictionaryKeys count] > 0) 64 | { 65 | //is this the root dictionary? 66 | if ([_dictionaries count] == 1) 67 | { 68 | //one dictionary left, so it must be the root 69 | NSMutableDictionary *rootDictionary = [_dictionaries lastObject]; 70 | 71 | //set the request type in the root dictionary 72 | [rootDictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 73 | 74 | //send the root dictionary to the super class 75 | [self _parsedObject:rootDictionary]; 76 | [parsedObjects addObject:rootDictionary]; 77 | } 78 | else 79 | { 80 | //child dictionary found 81 | //add the child dictionary to its parent dictionary 82 | NSMutableDictionary *parentDictionary = [_dictionaries objectAtIndex:[_dictionaries count] - 2]; 83 | [parentDictionary setObject:[_dictionaries lastObject] forKey:[_dictionaryKeys lastObject]]; 84 | } 85 | 86 | //remove the last dictionary since it has been joined with its parent (or was the root dictionary) 87 | //also remove the corresponding key 88 | [_dictionaries removeLastObject]; 89 | [_dictionaryKeys removeLastObject]; 90 | } 91 | #if DEBUG_PARSING 92 | NSLog(@"status: dictionary end"); 93 | #endif 94 | } 95 | 96 | - (void)startArrayWithKey:(NSString *)key 97 | { 98 | arrayDepth++; 99 | 100 | NSMutableArray *newArray = [NSMutableArray array]; 101 | [self addValue:newArray forKey:key]; 102 | 103 | #if DEBUG_PARSING 104 | NSLog(@"status: array start = %@", key); 105 | #endif 106 | } 107 | 108 | - (void)endArray 109 | { 110 | #if DEBUG_PARSING 111 | NSLog(@"status: array end"); 112 | #endif 113 | 114 | arrayDepth--; 115 | [self clearCurrentKey]; 116 | } 117 | 118 | - (void)dealloc 119 | { 120 | [_dictionaries release]; 121 | [_dictionaryKeys release]; 122 | [super dealloc]; 123 | } 124 | 125 | @end 126 | -------------------------------------------------------------------------------- /MGTwitterMessagesLibXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterMessagesLibXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterMessagesLibXMLParser.h" 10 | 11 | 12 | @implementation MGTwitterMessagesLibXMLParser 13 | 14 | - (NSDictionary *)_directMessageDictionaryForNodeWithName:(const xmlChar *)parentNodeName { 15 | if (xmlTextReaderIsEmptyElement(_reader)) 16 | return nil; 17 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 18 | 19 | int readerResult = xmlTextReaderRead(_reader); 20 | if (readerResult != 1) 21 | return nil; 22 | int nodeType = xmlTextReaderNodeType(_reader); 23 | const xmlChar *name = xmlTextReaderConstName(_reader); 24 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(parentNodeName, name))) 25 | { 26 | if (nodeType == XML_READER_TYPE_ELEMENT) 27 | { 28 | if (xmlStrEqual(name, BAD_CAST "sender") || xmlStrEqual(name, BAD_CAST "recipient")) 29 | { 30 | // "user" is the name of a sub-dictionary in each item 31 | [dictionary setObject:[self _userDictionaryForNodeWithName:name] forKey:[NSString stringWithUTF8String:(const char *)name]]; 32 | } 33 | else if (xmlStrEqual(name, BAD_CAST "id") || xmlStrEqual(name, BAD_CAST "sender_id") || xmlStrEqual(name, BAD_CAST "recipient_id")) 34 | { 35 | // process element as an integer 36 | NSNumber *number = [self _nodeValueAsInt]; 37 | if (number) 38 | { 39 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 40 | } 41 | } 42 | else if (xmlStrEqual(name, BAD_CAST "created_at")) 43 | { 44 | // process element as a date 45 | NSDate *date = [self _nodeValueAsDate]; 46 | if (date) 47 | { 48 | [dictionary setObject:date forKey:[NSString stringWithUTF8String:(const char *)name]]; 49 | } 50 | } 51 | else if (xmlStrEqual(name, BAD_CAST "protected")) 52 | { 53 | // process element as a boolean 54 | NSNumber *number = [self _nodeValueAsBool]; 55 | if (number) 56 | { 57 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 58 | } 59 | } 60 | else 61 | { 62 | // process element as a string 63 | NSString *string = [self _nodeValueAsString]; 64 | if (string) 65 | { 66 | [dictionary setObject:string forKey:[NSString stringWithUTF8String:(const char *)name]]; 67 | } 68 | } 69 | } 70 | 71 | // advance reader 72 | readerResult = xmlTextReaderRead(_reader); 73 | if (readerResult != 1) 74 | break; 75 | nodeType = xmlTextReaderNodeType(_reader); 76 | name = xmlTextReaderConstName(_reader); 77 | } 78 | 79 | // save the request type in the tweet 80 | [dictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 81 | 82 | return dictionary; 83 | } 84 | 85 | 86 | - (void)parse 87 | { 88 | int readerResult = xmlTextReaderRead(_reader); 89 | if (readerResult != 1) 90 | return; 91 | int nodeType = xmlTextReaderNodeType(_reader); 92 | const xmlChar *name = xmlTextReaderConstName(_reader); 93 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(BAD_CAST "direct-messages", name))) 94 | { 95 | if (nodeType == XML_READER_TYPE_ELEMENT) 96 | { 97 | if (xmlStrEqual(name, BAD_CAST "direct_message")) 98 | { 99 | [parsedObjects addObject:[self _directMessageDictionaryForNodeWithName:BAD_CAST "direct_message"]]; 100 | } 101 | } 102 | 103 | // advance reader 104 | readerResult = xmlTextReaderRead(_reader); 105 | if (readerResult != 1) 106 | { 107 | break; 108 | } 109 | nodeType = xmlTextReaderNodeType(_reader); 110 | name = xmlTextReaderConstName(_reader); 111 | } 112 | } 113 | 114 | @end 115 | -------------------------------------------------------------------------------- /MGTwitterSearchYAJLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterSearchYAJLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 11/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterSearchYAJLParser.h" 10 | 11 | #define DEBUG_PARSING 0 12 | 13 | @implementation MGTwitterSearchYAJLParser 14 | 15 | - (void)addValue:(id)value forKey:(NSString *)key 16 | { 17 | if (insideArray) 18 | { 19 | //if for some reason there are no dictionaries, exit here 20 | if (!_dictionaries || [_dictionaries count] == 0) 21 | { 22 | return; 23 | } 24 | 25 | NSMutableDictionary *lastDictionary = [_dictionaries lastObject]; 26 | [lastDictionary setObject:value forKey:key]; 27 | 28 | #if DEBUG_PARSING 29 | NSLog(@"search: results: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 30 | #endif 31 | } 32 | else 33 | { 34 | if (_status) 35 | { 36 | [_status setObject:value forKey:key]; 37 | } 38 | #if DEBUG_PARSING 39 | NSLog(@"search: status: %@ = %@ (%@)", key, value, NSStringFromClass([value class])); 40 | #endif 41 | } 42 | } 43 | 44 | - (void)startDictionaryWithKey:(NSString *)key 45 | { 46 | #if DEBUG_PARSING 47 | NSLog(@"search: dictionary start = %@", key); 48 | #endif 49 | if (insideArray) 50 | { 51 | if (!_dictionaries) 52 | { 53 | _dictionaries = [[NSMutableArray alloc] init]; 54 | } 55 | 56 | if (!_dictionaryKeys) 57 | { 58 | _dictionaryKeys = [[NSMutableArray alloc] init]; 59 | } 60 | 61 | //add a new dictionary to the array 62 | NSMutableDictionary *newDictionary = [[NSMutableDictionary alloc] initWithCapacity:0]; 63 | [_dictionaries addObject:newDictionary]; 64 | [newDictionary release]; 65 | 66 | //add a key for the above dictionary to the array 67 | [_dictionaryKeys addObject:(key) ? key : @""]; 68 | } 69 | else 70 | { 71 | if (! _status) 72 | { 73 | _status = [[NSMutableDictionary alloc] initWithCapacity:0]; 74 | } 75 | } 76 | } 77 | 78 | - (void)endDictionary 79 | { 80 | if (insideArray) 81 | { 82 | if (_dictionaries && _dictionaryKeys && [_dictionaries count] > 0 && [_dictionaryKeys count] > 0) 83 | { 84 | //is this the root dictionary? 85 | if ([_dictionaries count] == 1) 86 | { 87 | //one dictionary left, so it must be the root 88 | NSMutableDictionary *rootDictionary = [_dictionaries lastObject]; 89 | 90 | //set the request type in the root dictionary 91 | [rootDictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 92 | 93 | //send the root dictionary to the super class 94 | [self _parsedObject:rootDictionary]; 95 | [parsedObjects addObject:rootDictionary]; 96 | } 97 | else 98 | { 99 | //child dictionary found 100 | //add the child dictionary to its parent dictionary 101 | NSMutableDictionary *parentDictionary = [_dictionaries objectAtIndex:[_dictionaries count] - 2]; 102 | [parentDictionary setObject:[_dictionaries lastObject] forKey:[_dictionaryKeys lastObject]]; 103 | } 104 | 105 | //remove the last dictionary since it has been joined with its parent (or was the root dictionary) 106 | //also remove the corresponding key 107 | [_dictionaries removeLastObject]; 108 | [_dictionaryKeys removeLastObject]; 109 | } 110 | } 111 | else 112 | { 113 | if (_status) 114 | { 115 | [_status setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 116 | 117 | [parsedObjects addObject:_status]; 118 | [_status release]; 119 | _status = nil; 120 | } 121 | } 122 | 123 | #if DEBUG_PARSING 124 | NSLog(@"search: dictionary end"); 125 | #endif 126 | } 127 | 128 | - (void)startArrayWithKey:(NSString *)key 129 | { 130 | #if DEBUG_PARSING 131 | NSLog(@"search: array start = %@", key); 132 | #endif 133 | insideArray = YES; 134 | } 135 | 136 | - (void)endArray 137 | { 138 | #if DEBUG_PARSING 139 | NSLog(@"search: array end"); 140 | #endif 141 | insideArray = NO; 142 | } 143 | 144 | - (void)dealloc 145 | { 146 | [_dictionaries release]; 147 | [_dictionaryKeys release]; 148 | [_status release]; 149 | 150 | [super dealloc]; 151 | } 152 | 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /NSData+Base64.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSData+Base64.m 3 | // 4 | // Derived from http://colloquy.info/project/browser/trunk/NSDataAdditions.h?rev=1576 5 | // Created by khammond on Mon Oct 29 2001. 6 | // Formatted by Timothy Hatcher on Sun Jul 4 2004. 7 | // Copyright (c) 2001 Kyle Hammond. All rights reserved. 8 | // Original development by Dave Winer. 9 | // 10 | 11 | #import "NSData+Base64.h" 12 | 13 | #import 14 | 15 | static char encodingTable[64] = { 16 | 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 17 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 18 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 19 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' }; 20 | 21 | @implementation NSData (Base64) 22 | 23 | + (NSData *) dataWithBase64EncodedString:(NSString *) string { 24 | NSData *result = [[NSData alloc] initWithBase64EncodedString:string]; 25 | return [result autorelease]; 26 | } 27 | 28 | - (id) initWithBase64EncodedString:(NSString *) string { 29 | NSMutableData *mutableData = nil; 30 | 31 | if( string ) { 32 | unsigned long ixtext = 0; 33 | unsigned long lentext = 0; 34 | unsigned char ch = 0; 35 | unsigned char inbuf[3], outbuf[4]; 36 | short i = 0, ixinbuf = 0; 37 | BOOL flignore = NO; 38 | BOOL flendtext = NO; 39 | NSData *base64Data = nil; 40 | const unsigned char *base64Bytes = nil; 41 | 42 | // Convert the string to ASCII data. 43 | base64Data = [string dataUsingEncoding:NSASCIIStringEncoding]; 44 | base64Bytes = [base64Data bytes]; 45 | mutableData = [NSMutableData dataWithCapacity:[base64Data length]]; 46 | lentext = [base64Data length]; 47 | 48 | while( YES ) { 49 | if( ixtext >= lentext ) break; 50 | ch = base64Bytes[ixtext++]; 51 | flignore = NO; 52 | 53 | if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A'; 54 | else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26; 55 | else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52; 56 | else if( ch == '+' ) ch = 62; 57 | else if( ch == '=' ) flendtext = YES; 58 | else if( ch == '/' ) ch = 63; 59 | else flignore = YES; 60 | 61 | if( ! flignore ) { 62 | short ctcharsinbuf = 3; 63 | BOOL flbreak = NO; 64 | 65 | if( flendtext ) { 66 | if( ! ixinbuf ) break; 67 | if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1; 68 | else ctcharsinbuf = 2; 69 | ixinbuf = 3; 70 | flbreak = YES; 71 | } 72 | 73 | inbuf [ixinbuf++] = ch; 74 | 75 | if( ixinbuf == 4 ) { 76 | ixinbuf = 0; 77 | outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 ); 78 | outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 ); 79 | outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F ); 80 | 81 | for( i = 0; i < ctcharsinbuf; i++ ) 82 | [mutableData appendBytes:&outbuf[i] length:1]; 83 | } 84 | 85 | if( flbreak ) break; 86 | } 87 | } 88 | } 89 | 90 | self = [self initWithData:mutableData]; 91 | return self; 92 | } 93 | 94 | - (NSString *) base64EncodingWithLineLength:(unsigned int) lineLength { 95 | const unsigned char *bytes = [self bytes]; 96 | NSMutableString *result = [NSMutableString stringWithCapacity:[self length]]; 97 | unsigned long ixtext = 0; 98 | unsigned long lentext = [self length]; 99 | long ctremaining = 0; 100 | unsigned char inbuf[3], outbuf[4]; 101 | short i = 0; 102 | unsigned int charsonline = 0; 103 | short ctcopy = 0; 104 | unsigned long ix = 0; 105 | 106 | while( YES ) { 107 | ctremaining = lentext - ixtext; 108 | if( ctremaining <= 0 ) break; 109 | 110 | for( i = 0; i < 3; i++ ) { 111 | ix = ixtext + i; 112 | if( ix < lentext ) inbuf[i] = bytes[ix]; 113 | else inbuf [i] = 0; 114 | } 115 | 116 | outbuf [0] = (inbuf [0] & 0xFC) >> 2; 117 | outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4); 118 | outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6); 119 | outbuf [3] = inbuf [2] & 0x3F; 120 | ctcopy = 4; 121 | 122 | switch( ctremaining ) { 123 | case 1: 124 | ctcopy = 2; 125 | break; 126 | case 2: 127 | ctcopy = 3; 128 | break; 129 | } 130 | 131 | for( i = 0; i < ctcopy; i++ ) 132 | [result appendFormat:@"%c", encodingTable[outbuf[i]]]; 133 | 134 | for( i = ctcopy; i < 4; i++ ) 135 | [result appendFormat:@"%c",'=']; 136 | 137 | ixtext += 3; 138 | charsonline += 4; 139 | 140 | if( lineLength > 0 ) { 141 | if (charsonline >= lineLength) { 142 | charsonline = 0; 143 | [result appendString:@"\n"]; 144 | } 145 | } 146 | } 147 | 148 | return result; 149 | } 150 | 151 | @end 152 | -------------------------------------------------------------------------------- /MGTwitterTouchJSONParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterTouchJSONParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Steve Streza on 3/24/10. 6 | // Copyright 2010 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "MGTwitterTouchJSONParser.h" 10 | #import "CJSONDeserializer.h" 11 | 12 | @implementation MGTwitterTouchJSONParser 13 | 14 | + (id)parserWithJSON:(NSData *)theJSON 15 | delegate:(NSObject *)theDelegate 16 | connectionIdentifier:(NSString *)identifier 17 | requestType:(MGTwitterRequestType)reqType 18 | responseType:(MGTwitterResponseType)respType 19 | URL:(NSURL *)URL 20 | deliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions 21 | { 22 | return [[[self alloc] initWithJSON:theJSON 23 | delegate:theDelegate 24 | connectionIdentifier:identifier 25 | requestType:reqType 26 | responseType:respType 27 | URL:URL 28 | deliveryOptions:deliveryOptions] autorelease]; 29 | } 30 | 31 | - (id) initWithJSON:(NSData *)theJSON 32 | delegate:(NSObject *)theDelegate 33 | connectionIdentifier:(NSString *)theIdentifier 34 | requestType:(MGTwitterRequestType)reqType 35 | responseType:(MGTwitterResponseType)respType 36 | URL:(NSURL *)theURL 37 | deliveryOptions:(MGTwitterEngineDeliveryOptions)theDeliveryOptions 38 | { 39 | if(self = [super init]){ 40 | json = [theJSON retain]; 41 | identifier = [theIdentifier retain]; 42 | requestType = reqType; 43 | responseType = respType; 44 | URL = [theURL retain]; 45 | deliveryOptions = theDeliveryOptions; 46 | delegate = theDelegate; 47 | 48 | if (deliveryOptions & MGTwitterEngineDeliveryAllResultsOption) 49 | { 50 | parsedObjects = [[NSMutableArray alloc] initWithCapacity:0]; 51 | } 52 | else 53 | { 54 | parsedObjects = nil; // rely on nil target to discard addObject 55 | } 56 | 57 | if ([json length] <= 5) 58 | { 59 | // NOTE: this is a hack for API methods that return short JSON responses that can't be parsed by YAJL. These include: 60 | // friendships/exists: returns "true" or "false" 61 | // help/test: returns "ok" 62 | // An empty response of "[]" is a special case. 63 | NSString *result = [[[NSString alloc] initWithBytes:[json bytes] length:[json length] encoding:NSUTF8StringEncoding] autorelease]; 64 | if (! [result isEqualToString:@"[]"]) 65 | { 66 | NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease]; 67 | 68 | if ([result isEqualToString:@"\"ok\""]) 69 | { 70 | [dictionary setObject:[NSNumber numberWithBool:YES] forKey:@"ok"]; 71 | } 72 | else 73 | { 74 | [dictionary setObject:[NSNumber numberWithBool:[result isEqualToString:@"true"]] forKey:@"friends"]; 75 | } 76 | [dictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 77 | 78 | [self _parsedObject:dictionary]; 79 | 80 | [parsedObjects addObject:dictionary]; 81 | } 82 | } 83 | else 84 | { 85 | id results = [[CJSONDeserializer deserializer] deserialize:json 86 | error:nil]; 87 | if([results isKindOfClass:[NSArray class]]){ 88 | for(NSDictionary *result in results){ 89 | [self _parsedObject:result]; 90 | } 91 | }else{ 92 | [self _parsedObject:results]; 93 | } 94 | 95 | } 96 | 97 | // notify the delegate that parsing completed 98 | [self _parsingDidEnd]; 99 | } 100 | return self; 101 | } 102 | 103 | - (void)dealloc 104 | { 105 | [parsedObjects release]; 106 | [json release]; 107 | [identifier release]; 108 | [URL release]; 109 | 110 | delegate = nil; 111 | [super dealloc]; 112 | } 113 | 114 | #pragma mark Delegate callbacks 115 | 116 | - (BOOL) _isValidDelegateForSelector:(SEL)selector 117 | { 118 | return ((delegate != nil) && [delegate respondsToSelector:selector]); 119 | } 120 | 121 | - (void)_parsingDidEnd 122 | { 123 | if ([self _isValidDelegateForSelector:@selector(parsingSucceededForRequest:ofResponseType:withParsedObjects:)]) 124 | [delegate parsingSucceededForRequest:identifier ofResponseType:responseType withParsedObjects:parsedObjects]; 125 | } 126 | 127 | - (void)_parsingErrorOccurred:(NSError *)parseError 128 | { 129 | if ([self _isValidDelegateForSelector:@selector(parsingFailedForRequest:ofResponseType:withError:)]) 130 | [delegate parsingFailedForRequest:identifier ofResponseType:responseType withError:parseError]; 131 | } 132 | 133 | - (void)_parsedObject:(NSDictionary *)dictionary 134 | { 135 | [parsedObjects addObject:dictionary]; 136 | if (deliveryOptions & MGTwitterEngineDeliveryIndividualResultsOption) 137 | if ([self _isValidDelegateForSelector:@selector(parsedObject:forRequest:ofResponseType:)]) 138 | [delegate parsedObject:(NSDictionary *)dictionary forRequest:identifier ofResponseType:responseType]; 139 | } 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /MGTwitterRequestTypes.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterEngineDelegate.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 17/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | typedef enum _MGTwitterRequestType { 12 | MGTwitterPublicTimelineRequest = 0, // latest statuses from the public timeline 13 | MGTwitterHomeTimelineRequest, // latest statuses from the home timeline 14 | MGTwitterFollowedTimelineRequest, // latest statuses from the people that the current users follows 15 | MGTwitterUserTimelineRequest, // statuses archive for the current user 16 | MGTwitterUserTimelineForUserRequest, // statuses archive for the specified user 17 | MGTwitterUpdateGetRequest, // get a status update for the specified id 18 | MGTwitterUpdateSendRequest, // send a new update for the current user 19 | MGTwitterUpdateDeleteRequest, // delete an update for the current user using the specified id 20 | MGTwitterRepliesRequest, // latest reply status for the current user 21 | MGTwitterRetweetSendRequest, // send a new retweet for the current user 22 | MGTwitterFeaturedUsersRequest, // latest status from featured users 23 | MGTwitterFriendUpdatesRequest, // last status for the people that the current user follows 24 | MGTwitterFriendUpdatesForUserRequest, // last status for the people that the specified user follows 25 | MGTwitterFollowerUpdatesRequest, // last status for the people that follow the current user 26 | MGTwitterUserInformationRequest, // user information using the specified id or email 27 | MGTwitterBulkUserInformationRequest, // user information using the specified id or email 28 | MGTwitterDirectMessagesRequest, // latest direct messages to the current user 29 | MGTwitterDirectMessagesSentRequest, // latest direct messages from the current user 30 | MGTwitterDirectMessageSendRequest, // send a new direct message from the current user 31 | MGTwitterDirectMessageDeleteRequest, // delete a direct message to/from the current user 32 | MGTwitterUpdatesEnableRequest, // enable status updates for specified user (e.g. follow) 33 | MGTwitterUpdatesDisableRequest, // disable status updates for specified user (e.g. unfollow) 34 | MGTwitterUpdatesCheckRequest, // check if the specified user is following another user 35 | MGTwitterAccountRequest, // changing account information for the current user 36 | MGTwitterAccountLocationRequest, // change location in account information for the current user 37 | MGTwitterAccountDeliveryRequest, // change notification delivery in account information for the current user 38 | MGTwitterAccountStatusRequest, // get rate limiting status for the current user 39 | MGTwitterFavoritesRequest, // latest favorites for the current user 40 | MGTwitterFavoritesForUserRequest, // latest favorites for the specified user 41 | MGTwitterFavoritesEnableRequest, // create a favorite for the current user using the specified id 42 | MGTwitterFavoritesDisableRequest, // remove a favorite for the current user using the specified id 43 | MGTwitterNotificationsEnableRequest, // enable notifications for the specified user 44 | MGTwitterNotificationsDisableRequest, // disable notifications for the specified user 45 | MGTwitterBlockEnableRequest, // enable block for the specified user 46 | MGTwitterBlockDisableRequest, // disable block for the specified user 47 | MGTwitterImageRequest, // requesting an image 48 | MGTwitterFriendIDsRequest, // request the numeric IDs for every user the specified user is following 49 | MGTwitterFollowerIDsRequest, // request the numeric IDs of the followers of the specified user 50 | MGTwitterUserListsRequest, 51 | MGTwitterUserListCreate, 52 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 53 | MGTwitterSearchRequest, // performing a search 54 | MGTwitterSearchCurrentTrendsRequest, // getting the current trends 55 | #endif 56 | MGTwitterOAuthTokenRequest, 57 | } MGTwitterRequestType; 58 | 59 | typedef enum _MGTwitterResponseType { 60 | MGTwitterStatuses = 0, // one or more statuses 61 | MGTwitterStatus = 1, // exactly one status 62 | MGTwitterUsers = 2, // one or more user's information 63 | MGTwitterUser = 3, // info for exactly one user 64 | MGTwitterDirectMessages = 4, // one or more direct messages 65 | MGTwitterDirectMessage = 5, // exactly one direct message 66 | MGTwitterGeneric = 6, // a generic response not requiring parsing 67 | MGTwitterMiscellaneous = 8, // a miscellaneous response of key-value pairs 68 | MGTwitterImage = 7, // an image 69 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 70 | MGTwitterSearchResults = 9, // search results 71 | #endif 72 | MGTwitterSocialGraph = 10, 73 | MGTwitterOAuthToken = 11, 74 | MGTwitterUserLists = 12, 75 | } MGTwitterResponseType; 76 | 77 | // This key is added to each tweet or direct message returned, 78 | // with an NSNumber value containing an MGTwitterRequestType. 79 | // This is designed to help client applications aggregate updates. 80 | #define TWITTER_SOURCE_REQUEST_TYPE @"source_api_request_type" 81 | -------------------------------------------------------------------------------- /MGTwitterXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterXMLParser.h" 10 | 11 | 12 | @implementation MGTwitterXMLParser 13 | 14 | 15 | #pragma mark Creation and Destruction 16 | 17 | 18 | + (id)parserWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 19 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 20 | responseType:(MGTwitterResponseType)respType 21 | { 22 | id parser = [[self alloc] initWithXML:theXML 23 | delegate:theDelegate 24 | connectionIdentifier:identifier 25 | requestType:reqType 26 | responseType:respType]; 27 | return [parser autorelease]; 28 | } 29 | 30 | 31 | - (id)initWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 32 | connectionIdentifier:(NSString *)theIdentifier requestType:(MGTwitterRequestType)reqType 33 | responseType:(MGTwitterResponseType)respType 34 | { 35 | if ((self = [super init])) { 36 | xml = [theXML retain]; 37 | identifier = [theIdentifier retain]; 38 | requestType = reqType; 39 | responseType = respType; 40 | delegate = theDelegate; 41 | parsedObjects = [[NSMutableArray alloc] initWithCapacity:0]; 42 | 43 | // Set up the parser object. 44 | parser = [[NSXMLParser alloc] initWithData:xml]; 45 | [parser setDelegate:self]; 46 | [parser setShouldReportNamespacePrefixes:NO]; 47 | [parser setShouldProcessNamespaces:NO]; 48 | [parser setShouldResolveExternalEntities:NO]; 49 | 50 | // Begin parsing. 51 | [parser parse]; 52 | } 53 | 54 | return self; 55 | } 56 | 57 | 58 | - (void)dealloc 59 | { 60 | [parser release]; 61 | [parsedObjects release]; 62 | [xml release]; 63 | [identifier release]; 64 | delegate = nil; 65 | [super dealloc]; 66 | } 67 | 68 | 69 | #pragma mark NSXMLParser delegate methods 70 | 71 | 72 | - (void)parserDidStartDocument:(NSXMLParser *)theParser 73 | { 74 | //NSLog(@"Parsing begun"); 75 | } 76 | 77 | 78 | - (void)parserDidEndDocument:(NSXMLParser *)theParser 79 | { 80 | //NSLog(@"Parsing complete: %@", parsedObjects); 81 | [delegate parsingSucceededForRequest:identifier ofResponseType:responseType 82 | withParsedObjects:parsedObjects]; 83 | } 84 | 85 | 86 | - (void)parser:(NSXMLParser *)theParser didStartElement:(NSString *)elementName 87 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 88 | attributes:(NSDictionary *)attributeDict 89 | { 90 | //NSLog(@"Started element: %@ (%@)", elementName, attributeDict); 91 | } 92 | 93 | 94 | - (void)parser:(NSXMLParser *)theParser foundCharacters:(NSString *)characters 95 | { 96 | //NSLog(@"Found characters: %@", characters); 97 | } 98 | 99 | 100 | - (void)parser:(NSXMLParser *)theParser didEndElement:(NSString *)elementName 101 | namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 102 | { 103 | //NSLog(@"Ended element: %@", elementName); 104 | [self setLastOpenedElement:nil]; 105 | 106 | if ([elementName isEqualToString:@"protected"] 107 | || [elementName isEqualToString:@"truncated"] 108 | || [elementName isEqualToString:@"following"]) { 109 | // Change "true"/"false" into an NSNumber with a BOOL value. 110 | NSNumber *boolNumber = [NSNumber numberWithBool:[[currentNode objectForKey:elementName] isEqualToString:@"true"]]; 111 | [currentNode setObject:boolNumber forKey:elementName]; 112 | } else if ([elementName isEqualToString:@"created_at"]) { 113 | // Change date-string into an NSDate. 114 | // NSLog(@"%@", [currentNode objectForKey:elementName]); 115 | NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 116 | [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; 117 | dateFormatter.dateFormat = @"EEE MMM dd HH:mm:ss +0000 yyyy"; 118 | NSDate *creationDate = [dateFormatter dateFromString:[currentNode objectForKey:elementName]]; 119 | [dateFormatter release]; 120 | if (creationDate) { 121 | [currentNode setObject:creationDate forKey:elementName]; 122 | } 123 | } 124 | } 125 | 126 | 127 | - (void)parser:(NSXMLParser *)theParser foundAttributeDeclarationWithName:(NSString *)attributeName 128 | forElement:(NSString *)elementName type:(NSString *)type defaultValue:(NSString *)defaultValue 129 | { 130 | //NSLog(@"Found attribute: %@ (%@) [%@] {%@}", attributeName, elementName, type, defaultValue); 131 | } 132 | 133 | 134 | - (void)parser:(NSXMLParser *)theParser foundIgnorableWhitespace:(NSString *)whitespaceString 135 | { 136 | //NSLog(@"Found ignorable whitespace: %@", whitespaceString); 137 | } 138 | 139 | 140 | - (void)parser:(NSXMLParser *)theParser parseErrorOccurred:(NSError *)parseError 141 | { 142 | //NSLog(@"Parsing error occurred: %@", parseError); 143 | [delegate parsingFailedForRequest:identifier ofResponseType:responseType 144 | withError:parseError]; 145 | } 146 | 147 | 148 | #pragma mark Accessors 149 | 150 | 151 | - (NSString *)lastOpenedElement { 152 | return [[lastOpenedElement retain] autorelease]; 153 | } 154 | 155 | 156 | - (void)setLastOpenedElement:(NSString *)value { 157 | if (lastOpenedElement != value) { 158 | [lastOpenedElement release]; 159 | lastOpenedElement = [value copy]; 160 | } 161 | } 162 | 163 | 164 | #pragma mark Utility methods 165 | 166 | 167 | - (void)addSource 168 | { 169 | if (![currentNode objectForKey:TWITTER_SOURCE_REQUEST_TYPE]) { 170 | [currentNode setObject:[NSNumber numberWithInt:requestType] 171 | forKey:TWITTER_SOURCE_REQUEST_TYPE]; 172 | } 173 | } 174 | 175 | 176 | @end 177 | -------------------------------------------------------------------------------- /Source Code License.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf949\cocoasubrtf270 2 | {\fonttbl\f0\fnil\fcharset0 LucidaGrande;} 3 | {\colortbl;\red255\green255\blue255;\red51\green51\blue51;\red0\green180\blue128;\red255\green0\blue0; 4 | \red31\green105\blue199;\red119\green119\blue119;} 5 | {\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc0\levelnfcn0\leveljc2\leveljcn2\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{decimal\}.}{\leveltext\leveltemplateid0\'02\'05.;}{\levelnumbers\'01;}}{\listname ;}\listid1}} 6 | {\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} 7 | \deftab720 8 | \pard\pardeftab720\ql\qnatural 9 | 10 | \f0\b\fs24 \cf2 Matt Gemmell / Instinctive Code Source Code License\ 11 | 12 | \b0\fs22 Last updated: 19th May 2008 13 | \fs24 \ 14 | \ 15 | \ 16 | Thanks for downloading some of our source code!\ 17 | \ 18 | This is the license agreement for the source code which this document accompanies (don\'92t worry: you\'92re allowed to use it in your own products, commercial or otherwise).\ 19 | \ 20 | The full license text is further down this page, and you should only use the source code if you agree to the terms in that text. For convenience, though, we\'92ve put together a human-readable 21 | \b non-authoritative 22 | \b0 interpretation of the license which will hopefully answer any questions you have.\ 23 | \ 24 | \ 25 | 26 | \b \cf3 Green 27 | \b0 \cf2 text shows 28 | \b \cf3 what you can do with the code 29 | \b0 \cf2 .\ 30 | 31 | \b \cf4 Red 32 | \b0 \cf2 text means 33 | \b \cf4 restrictions you must abide by 34 | \b0 \cf2 .\ 35 | \ 36 | Basically, the license says that:\ 37 | \ 38 | \pard\tx220\tx720\pardeftab720\li720\fi-720\ql\qnatural 39 | \ls1\ilvl0\cf2 {\listtext 1. }You can 40 | \b \cf3 use the code in your own products, including commercial and/or closed-source products 41 | \b0 \cf2 .\ 42 | {\listtext 2. }You can 43 | \b \cf3 modify the code 44 | \b0 \cf0 as you wish\cf2 , and 45 | \b \cf3 use the modified code in your products 46 | \b0 \cf2 .\ 47 | {\listtext 3. }You can 48 | \b \cf3 redistribute the original, unmodified code 49 | \b0 \cf2 , but you 50 | \b \cf4 have to include the full license text below 51 | \b0 \cf2 .\ 52 | {\listtext 4. }You can 53 | \b \cf3 redistribute the modified code 54 | \b0 \cf2 as you wish ( 55 | \b \cf4 without the full license text below 56 | \b0 \cf2 ).\ 57 | {\listtext 5. }In all cases, you 58 | \b \cf4 must include a credit mentioning Matt Gemmell 59 | \b0 \cf2 as the original author of the source.\ 60 | {\listtext 6. }Matt Gemmell is \cf0 not liable for anything you do with the code\cf2 , no matter what. So be sensible.\ 61 | {\listtext 7. }You 62 | \b \cf4 can\'92t use the name Matt Gemmell, the name Instinctive Code, the Instinctive Code logo or any other related marks to promote your products 63 | \b0 \cf2 based on the code.\ 64 | {\listtext 8. }If you agree to all of that, go ahead and use the source. Otherwise, don\'92t!\ 65 | \pard\pardeftab720\ql\qnatural 66 | \cf2 \ 67 | 68 | \b \ 69 | \ 70 | Suggested Attribution Format\ 71 | 72 | \b0 \ 73 | The license requires that you give credit to Matt Gemmell, as the original author of any of our source that you use. The placement and format of the credit is up to you, but we prefer the credit to be in the software\'92s \'93About\'94 window. Alternatively, you could put the credit in a list of acknowledgements within the software, in the software\'92s documentation, or on the web page for the software. The suggested format for the attribution is:\ 74 | \ 75 | \pard\pardeftab720\ql\qnatural 76 | 77 | \b \cf0 Includes code by {\field{\*\fldinst{HYPERLINK "http://mattgemmell.com/"}}{\fldrslt \cf5 Matt Gemmell}}\cf6 . 78 | \b0 \ 79 | \pard\pardeftab720\ql\qnatural 80 | \cf2 \ 81 | where would be replaced by the name of the specific source-code package you made use of. Where possible, please link the text \'93Matt Gemmell\'94 to the following URL, or include the URL as plain text: {\field{\*\fldinst{HYPERLINK "http://mattgemmell.com/"}}{\fldrslt \cf5 http://mattgemmell.com/}}\ 82 | \ 83 | \ 84 | 85 | \b Full Source Code License Text\ 86 | \ 87 | 88 | \b0 Below you can find the actual text of the license agreement. 89 | \b \ 90 | \ 91 | \pard\pardeftab720\ql\qnatural 92 | \cf6 \ 93 | License Agreement for Source Code provided by Matt Gemmell 94 | \b0 \ 95 | \ 96 | This software is supplied to you by Matt Gemmell in consideration of your agreement to the following terms, and your use, installation, modification or redistribution of this software constitutes acceptance of these terms. If you do not agree with these terms, please do not use, install, modify or redistribute this software.\ 97 | \ 98 | In consideration of your agreement to abide by the following terms, and subject to these terms, Matt Gemmell grants you a personal, non-exclusive license, to use, reproduce, modify and redistribute the software, with or without modifications, in source and/or binary forms; provided that if you redistribute the software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the software, and that in all cases attribution of Matt Gemmell as the original author of the source code shall be included in all such resulting software products or distributions.\uc0\u8232 \ 99 | Neither the name, trademarks, service marks or logos of Matt Gemmell or Instinctive Code may be used to endorse or promote products derived from the software without specific prior written permission from Matt Gemmell. Except as expressly stated in this notice, no other rights or licenses, express or implied, are granted by Matt Gemmell herein, including but not limited to any patent rights that may be infringed by your derivative works or by other works in which the software may be incorporated.\ 100 | \ 101 | The software is provided by Matt Gemmell on an "AS IS" basis. MATT GEMMELL AND INSTINCTIVE CODE MAKE NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, REGARDING THE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.\ 102 | \ 103 | IN NO EVENT SHALL MATT GEMMELL OR INSTINCTIVE CODE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION OF THE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF MATT GEMMELL OR INSTINCTIVE CODE HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\ 104 | } -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | MGTwitterEngine 2 | by Matt Legend Gemmell - http://mattgemmell.com 3 | 4 | 5 | 6 | How to use MGTwitterEngine 7 | ========================== 8 | 9 | MGTwitterEngine is an Objective-C/Cocoa class which makes it easy to add Twitter integration to your own Cocoa apps. It communicates with Twitter via the public Twitter API, which you can read about here: 10 | http://apiwiki.twitter.com/REST+API+Documentation 11 | 12 | Using MGTwitterEngine is easy. The basic steps are: 13 | 14 | 15 | 1. Copy all the relevant source files into your own project. You need everything that starts with "MGTwitter", and also the NSString+UUID and NSData+Base64 category files. 16 | 17 | 18 | 2. In whatever class you're going to use MGTwitterEngine from, obviously make sure you #import the MGTwitterEngine.h header file. You should also declare that your class implements the MGTwitterEngineDelegate protocol. The AppController.h header file in the demo project is an example you can use. 19 | 20 | 21 | 3. Implement the MGTwitterEngineDelegate methods, just as the AppController in the demo project does. These are the methods you'll need to implement: 22 | 23 | - (void)requestSucceeded:(NSString *)requestIdentifier; 24 | - (void)requestFailed:(NSString *)requestIdentifier withError:(NSError *)error; 25 | - (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)identifier; 26 | - (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)identifier; 27 | - (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)identifier; 28 | 29 | 30 | 4. Go ahead and use MGTwitterEngine! Just instantiate the object and set the relevant username and password (as AppController does in the demo project), and then go ahead and call some of the Twitter API methods - you can see a full list of them in the MGTwitterEngine.h header file, which also includes a link to the Twitter API documentation online. 31 | 32 | 33 | A note about XML parsing 34 | ======================== 35 | 36 | You may wish to use the LibXML parser rather than the NSXMLParser, since LibXML can be faster and has a smaller memory footprint. 37 | 38 | In this case, you make need to make the following changes to your project: 39 | 40 | 1. Set USE_LIBXML to 1, near the top of the MGTwitterEngine.m file. 41 | 42 | 2. Add libxml2.dylib in Other Frameworks. You'll find the library in: 43 | 44 | /usr/lib/libxml2.dylib 45 | 46 | 3. Add "/usr/include/libxml2" as a Header Search Path in your Project Settings. 47 | 48 | 49 | 50 | A note about using MGTwitterEngine on the iPhone 51 | ================================================ 52 | 53 | MGTwitterEngine can also be used on the iPhone (with the official iPhone SDK). Simply add it to your iPhone application project as usual. 54 | 55 | It's recommended that you use the LibXML parser rather than the NSXMLParser on the iPhone. The native parser is faster and has a smaller memory footprint, and every little bit counts on the device. If you configure USE_LIBXML to 1 in MGTwitterEngine.m, you'll need to make a couple of additions to your project. 56 | 57 | 1. Add libxml2.dylib in Other Frameworks. You'll find the library in: 58 | 59 | /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.0.sdk/usr/lib/libxml2.dylib 60 | 61 | 2. Add "$SDKROOT/usr/include/libxml2" as a Header Search Path in your Project Settings. 62 | 63 | 64 | 65 | A note about the data returned from Twitter 66 | =========================================== 67 | 68 | Each Twitter API method returns an NSString which is a unique identifier for that connection. Those identifiers are passed to all the delegate methods, so you can keep track of what's happening. 69 | 70 | Whenever a request is successful, you will receive a call to your implementation of requestSucceeded: so you'll know that everything went OK. For most of the API methods, you will then receive a call to the appropriate method for the type of data you requested (statusesReceived:... or directMessagesReceived:... or userInfoReceived:...). The values sent to these methods are all NSArrays containing an NSDictionary for each status or user or direct message, with sub-dictionaries if necessary (for example, the timeline methods usually return statuses, each of which has a sub-dictionary giving information about the user who posted that status). 71 | 72 | Just try calling some of the methods and use NSLog() to see what data you get back; you should find the format very easy to integrate into your applications. 73 | 74 | Sometimes, of course, requests will fail - that's just how life is. In the unlikely event that the initial connection for a request can't be made, you will simply get nil back instead of a connection identifier, and then receive no further calls relating to that request. If you get nil back instead of an NSString, the connection has failed entirely. That's a good time to check that the computer is connected to the internet, and so on. 75 | 76 | It's far more common however that the connection itself will go ahead just fine, but there will be an error on Twitter's side, either due to technical difficulties, or because there was something wrong with your request (e.g. you entered the wrong username and password, or you tried to get info on a user that doesn't exist, or some such thing). The specific error conditions are mostly documented in the Twitter API documentation online. 77 | 78 | In these cases you'll receive a call to requestFailed:withError: which will include an NSError object detailing the error. Twitter usually returns meaningful HTTP error codes (like 404 for 'user not found', etc), and in that case the -domain of the NSError will be "HTTP" and the -code will be the relevant HTTP status code. The userInfo of the NSError will contain a key "body" that may contain the response body and "response" which will contain the NSHTTPURLResponse. This makes it really, really easy to know what's happening with your connections. 79 | 80 | 81 | 82 | About twitter.com cookies 83 | ========================= 84 | 85 | Like most web sites/services, twitter.com sets cookies on your computer when you authenticate with their server. These cookies (stored in NSHTTPCookieStorage) are shared amongst all applications which use NSURLConnection (including Safari and many more). 86 | 87 | MGTwitterEngine does not use those cookies, since it does its own direct authentication in the URLs of the requests it makes to the twitter servers. For this reason, as of version 1.0.4 (11th April 2008), it does not attempt to clear any saved cookies for twitter.com when you set a username and password for MGTwitterEngine to use. However, previous versions of MGTwitterEngine did indeed clear twitter's cookies whenever you called the -setUsername:password: method, in order to avoid an old and now fixed possibility of using the wrong credentials for the next request. There are two outcomes from this: 88 | 89 | 1. MGTwitterEngine no longer clears your twitter.com cookies, so for example you will now no longer have to re-login to Twitter in Safari after using an app which includes MGTwitterEngine. You would usually only have had to re-login with Safari once, but it was still an annoyance if you regularly used Twitter both on the web and with an MGTwitterEngine-using client. This should be fixed now. 90 | 91 | 2. In the unlikely event that you have any authentication problems when your MGTwitterEngine-using app switches from one Twitter account to another (for example, after switching accounts you still get data back from the old account, at least for the very first new request), you can easily re-enable the old cookie-clearing behaviour. Simply call the method -setClearsCookies: passing YES as the argument, and then call -setUsername:password: again, and all should be well. 92 | 93 | 94 | 95 | About supplying a custom name and other information for your Twitter client 96 | =========================================================================== 97 | 98 | The client name, url and version information supplied to -setClientName:version:URL:token: is used only for tracking purposes at Twitter; it is not displayed on the website. In order to have a custom name shown for your client when it sends updates to Twitter (e.g. "from MyCoolApp"), you must first contact Twitter and agree on a special identifier which you will send whenever you post an update - this is the 'token' parameter to the previously mentioned method. 99 | 100 | You can request such a token using this form at twitter.com: 101 | 102 | http://twitter.com/help/request_source 103 | 104 | When you receive your token, you can then set that token value using the aforementioned method, and MGTwitterEngine will do the right thing. 105 | 106 | 107 | 108 | That's about it. If you have trouble with the code, or want to make a feature request or report a bug (or even contribute some improvements), you can get in touch with me using the info below. I hope you enjoy using MGTwitterEngine! 109 | 110 | 111 | Cheers, 112 | -Matt Legend Gemmell 113 | 114 | 115 | Web: http://mattgemmell.com 116 | AIM: MadMcProgrammer 117 | MSN: mulderuk@hotmail.com 118 | Twitter: mattgemmell 119 | 120 | P.S. If you'd like to hire me for your own Mac OS X (Cocoa) or iPhone / iPod Touch development project, take a look at my consulting site at http://instinctivecode.com :) 121 | -------------------------------------------------------------------------------- /AppController.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppController.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 10/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "AppController.h" 10 | 11 | @implementation AppController 12 | 13 | 14 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 15 | { 16 | // Put your Twitter username and password here: 17 | NSString *username = nil; 18 | NSString *password = nil; 19 | 20 | NSString *consumerKey = nil; 21 | NSString *consumerSecret = nil; 22 | 23 | // Most API calls require a name and password to be set... 24 | if (! username || ! password || !consumerKey || !consumerSecret) { 25 | NSLog(@"You forgot to specify your username/password/key/secret in AppController.m, things might not work!"); 26 | NSLog(@"And if things are mysteriously working without the username/password, it's because NSURLConnection is using a session cookie from another connection."); 27 | } 28 | 29 | // Create a TwitterEngine and set our login details. 30 | twitterEngine = [[MGTwitterEngine alloc] initWithDelegate:self]; 31 | [twitterEngine setUsesSecureConnection:NO]; 32 | [twitterEngine setConsumerKey:consumerKey secret:consumerSecret]; 33 | // This has been undepreciated for the purposes of dealing with Lists. 34 | // At present the list API calls require you to specify a user that owns the list. 35 | [twitterEngine setUsername:username]; 36 | 37 | [twitterEngine getXAuthAccessTokenForUsername:username password:password]; 38 | } 39 | 40 | -(void)runTests{ 41 | [twitterEngine setAccessToken:token]; 42 | 43 | // Configure how the delegate methods are called to deliver results. See MGTwitterEngineDelegate.h for more info 44 | //[twitterEngine setDeliveryOptions:MGTwitterEngineDeliveryIndividualResultsOption]; 45 | 46 | // Get the public timeline 47 | NSLog(@"getPublicTimelineSinceID: connectionIdentifier = %@", [twitterEngine getPublicTimeline]); 48 | 49 | // Other types of information available from the API: 50 | 51 | #define TESTING_ID 1131604824 52 | #define TESTING_PRIMARY_USER @"gnitset" 53 | #define TESTING_SECONDARY_USER @"chockenberry" 54 | #define TESTING_MESSAGE_ID 52182684 55 | 56 | // Status methods: 57 | NSLog(@"getHomeTimelineFor: connectionIdentifier = %@", [twitterEngine getHomeTimelineSinceID:0 startingAtPage:0 count:20]); 58 | NSLog(@"getUserTimelineFor: connectionIdentifier = %@", [twitterEngine getUserTimelineFor:TESTING_SECONDARY_USER sinceID:0 startingAtPage:0 count:3]); 59 | NSLog(@"getUpdate: connectionIdentifier = %@", [twitterEngine getUpdate:TESTING_ID]); 60 | //NSLog(@"sendUpdate: connectionIdentifier = %@", [twitterEngine sendUpdate:[@"This is a test on " stringByAppendingString:[[NSDate date] description]]]); 61 | NSLog(@"getRepliesStartingAtPage: connectionIdentifier = %@", [twitterEngine getRepliesStartingAtPage:0]); 62 | //NSLog(@"deleteUpdate: connectionIdentifier = %@", [twitterEngine deleteUpdate:TESTING_ID]); 63 | 64 | // Lists 65 | //NSLog(@"get Lists for User:%@ connectionIdentifier = %@", TESTING_PRIMARY_USER, [twitterEngine getListsForUser:TESTING_PRIMARY_USER]); 66 | 67 | // NSString *listName = @"test list 3"; 68 | // NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"private", @"mode", @"a description", @"description", nil]; 69 | // 70 | // NSLog(@"creating list %@, connection identifier: %@", listName, [twitterEngine createListsForUser:TESTING_PRIMARY_USER withName:listName withOptions:dict]); 71 | 72 | // User methods: 73 | //NSLog(@"getRecentlyUpdatedFriendsFor: connectionIdentifier = %@", [twitterEngine getRecentlyUpdatedFriendsFor:nil startingAtPage:0]); 74 | //NSLog(@"getFollowersIncludingCurrentStatus: connectionIdentifier = %@", [twitterEngine getFollowersIncludingCurrentStatus:YES]); 75 | //NSLog(@"getUserInformationFor: connectionIdentifier = %@", [twitterEngine getUserInformationFor:TESTING_PRIMARY_USER]); 76 | 77 | // Direct Message methods: 78 | //NSLog(@"getDirectMessagesSinceID: connectionIdentifier = %@", [twitterEngine getDirectMessagesSinceID:0 startingAtPage:0]); 79 | //NSLog(@"getSentDirectMessagesSinceID: connectionIdentifier = %@", [twitterEngine getSentDirectMessagesSinceID:0 startingAtPage:0]); 80 | //NSLog(@"sendDirectMessage: connectionIdentifier = %@", [twitterEngine sendDirectMessage:[@"This is a test on " stringByAppendingString:[[NSDate date] description]] to:TESTING_SECONDARY_USER]); 81 | //NSLog(@"deleteDirectMessage: connectionIdentifier = %@", [twitterEngine deleteDirectMessage:TESTING_MESSAGE_ID]); 82 | 83 | 84 | // Friendship methods: 85 | //NSLog(@"enableUpdatesFor: connectionIdentifier = %@", [twitterEngine enableUpdatesFor:TESTING_SECONDARY_USER]); 86 | //NSLog(@"disableUpdatesFor: connectionIdentifier = %@", [twitterEngine disableUpdatesFor:TESTING_SECONDARY_USER]); 87 | //NSLog(@"isUser:receivingUpdatesFor: connectionIdentifier = %@", [twitterEngine isUser:TESTING_SECONDARY_USER receivingUpdatesFor:TESTING_PRIMARY_USER]); 88 | 89 | 90 | // Account methods: 91 | //NSLog(@"checkUserCredentials: connectionIdentifier = %@", [twitterEngine checkUserCredentials]); 92 | //NSLog(@"endUserSession: connectionIdentifier = %@", [twitterEngine endUserSession]); 93 | //NSLog(@"setLocation: connectionIdentifier = %@", [twitterEngine setLocation:@"Playing in Xcode with a location that is really long and may or may not get truncated to 30 characters"]); 94 | //NSLog(@"setNotificationsDeliveryMethod: connectionIdentifier = %@", [twitterEngine setNotificationsDeliveryMethod:@"none"]); 95 | // TODO: Add: account/update_profile_colors 96 | // TODO: Add: account/update_profile_image 97 | // TODO: Add: account/update_profile_background_image 98 | //NSLog(@"getRateLimitStatus: connectionIdentifier = %@", [twitterEngine getRateLimitStatus]); 99 | // TODO: Add: account/update_profile 100 | 101 | // Favorite methods: 102 | //NSLog(@"getFavoriteUpdatesFor: connectionIdentifier = %@", [twitterEngine getFavoriteUpdatesFor:nil startingAtPage:0]); 103 | //NSLog(@"markUpdate: connectionIdentifier = %@", [twitterEngine markUpdate:TESTING_ID asFavorite:YES]); 104 | 105 | // Notification methods 106 | //NSLog(@"enableNotificationsFor: connectionIdentifier = %@", [twitterEngine enableNotificationsFor:TESTING_SECONDARY_USER]); 107 | //NSLog(@"disableNotificationsFor: connectionIdentifier = %@", [twitterEngine disableNotificationsFor:TESTING_SECONDARY_USER]); 108 | 109 | // Block methods 110 | //NSLog(@"block: connectionIdentifier = %@", [twitterEngine block:TESTING_SECONDARY_USER]); 111 | //NSLog(@"unblock: connectionIdentifier = %@", [twitterEngine unblock:TESTING_SECONDARY_USER]); 112 | 113 | // Help methods: 114 | //NSLog(@"testService: connectionIdentifier = %@", [twitterEngine testService]); 115 | 116 | // Social Graph methods 117 | //NSLog(@"getFriendIDsFor: connectionIdentifier = %@", [twitterEngine getFriendIDsFor:TESTING_SECONDARY_USER startingFromCursor:-1]); 118 | //NSLog(@"getFollowerIDsFor: connectionIdentifier = %@", [twitterEngine getFollowerIDsFor:TESTING_SECONDARY_USER startingFromCursor:-1]); 119 | 120 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 121 | // Search method 122 | //NSLog(@"getSearchResultsForQuery: connectionIdentifier = %@", [twitterEngine getSearchResultsForQuery:TESTING_PRIMARY_USER sinceID:0 startingAtPage:1 count:20]); 123 | 124 | // Trends method 125 | //NSLog(@"getTrends: connectionIdentifier = %@", [twitterEngine getTrends]); 126 | #endif 127 | } 128 | 129 | - (void)dealloc 130 | { 131 | [twitterEngine release]; 132 | [super dealloc]; 133 | } 134 | 135 | 136 | #pragma mark MGTwitterEngineDelegate methods 137 | 138 | 139 | - (void)requestSucceeded:(NSString *)connectionIdentifier 140 | { 141 | NSLog(@"Request succeeded for connectionIdentifier = %@", connectionIdentifier); 142 | } 143 | 144 | 145 | - (void)requestFailed:(NSString *)connectionIdentifier withError:(NSError *)error 146 | { 147 | NSLog(@"Request failed for connectionIdentifier = %@, error = %@ (%@)", 148 | connectionIdentifier, 149 | [error localizedDescription], 150 | [error userInfo]); 151 | } 152 | 153 | 154 | - (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier 155 | { 156 | NSLog(@"Got statuses for %@:\r%@", connectionIdentifier, statuses); 157 | } 158 | 159 | 160 | - (void)directMessagesReceived:(NSArray *)messages forRequest:(NSString *)connectionIdentifier 161 | { 162 | NSLog(@"Got direct messages for %@:\r%@", connectionIdentifier, messages); 163 | } 164 | 165 | 166 | - (void)userInfoReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier 167 | { 168 | NSLog(@"Got user info for %@:\r%@", connectionIdentifier, userInfo); 169 | } 170 | 171 | 172 | - (void)miscInfoReceived:(NSArray *)miscInfo forRequest:(NSString *)connectionIdentifier 173 | { 174 | NSLog(@"Got misc info for %@:\r%@", connectionIdentifier, miscInfo); 175 | } 176 | 177 | 178 | - (void)searchResultsReceived:(NSArray *)searchResults forRequest:(NSString *)connectionIdentifier 179 | { 180 | NSLog(@"Got search results for %@:\r%@", connectionIdentifier, searchResults); 181 | } 182 | 183 | 184 | - (void)socialGraphInfoReceived:(NSArray *)socialGraphInfo forRequest:(NSString *)connectionIdentifier 185 | { 186 | NSLog(@"Got social graph results for %@:\r%@", connectionIdentifier, socialGraphInfo); 187 | } 188 | 189 | - (void)userListsReceived:(NSArray *)userInfo forRequest:(NSString *)connectionIdentifier 190 | { 191 | NSLog(@"Got user lists for %@:\r%@", connectionIdentifier, userInfo); 192 | } 193 | 194 | - (void)imageReceived:(NSImage *)image forRequest:(NSString *)connectionIdentifier 195 | { 196 | NSLog(@"Got an image for %@: %@", connectionIdentifier, image); 197 | 198 | // Save image to the Desktop. 199 | NSString *path = [[NSString stringWithFormat:@"~/Desktop/%@.tiff", connectionIdentifier] stringByExpandingTildeInPath]; 200 | [[image TIFFRepresentation] writeToFile:path atomically:NO]; 201 | } 202 | 203 | - (void)connectionFinished:(NSString *)connectionIdentifier 204 | { 205 | NSLog(@"Connection finished %@", connectionIdentifier); 206 | 207 | if ([twitterEngine numberOfConnections] == 0) 208 | { 209 | [NSApp terminate:self]; 210 | } 211 | } 212 | 213 | - (void)accessTokenReceived:(OAToken *)aToken forRequest:(NSString *)connectionIdentifier 214 | { 215 | NSLog(@"Access token received! %@",aToken); 216 | 217 | token = [aToken retain]; 218 | [self runTests]; 219 | } 220 | 221 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 222 | 223 | - (void)receivedObject:(NSDictionary *)dictionary forRequest:(NSString *)connectionIdentifier 224 | { 225 | NSLog(@"Got an object for %@: %@", connectionIdentifier, dictionary); 226 | } 227 | 228 | #endif 229 | 230 | @end 231 | -------------------------------------------------------------------------------- /MGTwitterYAJLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterYAJLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | 8 | #import "MGTwitterYAJLParser.h" 9 | 10 | 11 | @implementation MGTwitterYAJLParser 12 | 13 | #pragma mark Callbacks 14 | 15 | static NSString *currentKey; 16 | 17 | int MGTwitterYAJLParser_processNull(void *ctx) 18 | { 19 | id self = ctx; 20 | 21 | if (currentKey) 22 | { 23 | [self addValue:[NSNull null] forKey:currentKey]; 24 | } 25 | 26 | return 1; 27 | } 28 | 29 | int MGTwitterYAJLParser_processBoolean(void * ctx, int boolVal) 30 | { 31 | id self = ctx; 32 | 33 | if (currentKey) 34 | { 35 | [self addValue:[NSNumber numberWithBool:(BOOL)boolVal] forKey:currentKey]; 36 | 37 | [self clearCurrentKey]; 38 | } 39 | 40 | return 1; 41 | } 42 | 43 | int MGTwitterYAJLParser_processNumber(void *ctx, const char *numberVal, unsigned int numberLen) 44 | { 45 | id self = ctx; 46 | 47 | if (currentKey) 48 | { 49 | NSString *stringValue = [[NSString alloc] initWithBytesNoCopy:(void *)numberVal length:numberLen encoding:NSUTF8StringEncoding freeWhenDone:NO]; 50 | 51 | // if there's a decimal, assume it's a double 52 | if([stringValue rangeOfString:@"."].location != NSNotFound){ 53 | NSNumber *doubleValue = [NSNumber numberWithDouble:[stringValue doubleValue]]; 54 | [self addValue:doubleValue forKey:currentKey]; 55 | }else{ 56 | NSNumber *longLongValue = [NSNumber numberWithLongLong:[stringValue longLongValue]]; 57 | [self addValue:longLongValue forKey:currentKey]; 58 | } 59 | 60 | [stringValue release]; 61 | 62 | [self clearCurrentKey]; 63 | } 64 | 65 | return 1; 66 | } 67 | 68 | int MGTwitterYAJLParser_processString(void *ctx, const unsigned char * stringVal, unsigned int stringLen) 69 | { 70 | id self = ctx; 71 | 72 | if (currentKey) 73 | { 74 | NSMutableString *value = [[[NSMutableString alloc] initWithBytes:stringVal length:stringLen encoding:NSUTF8StringEncoding] autorelease]; 75 | 76 | [value replaceOccurrencesOfString:@">" withString:@">" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])]; 77 | [value replaceOccurrencesOfString:@"<" withString:@"<" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])]; 78 | [value replaceOccurrencesOfString:@"&" withString:@"&" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])]; 79 | [value replaceOccurrencesOfString:@""" withString:@"\"" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])]; 80 | 81 | if ([currentKey isEqualToString:@"created_at"]) 82 | { 83 | // we have a priori knowledge that the value for created_at is a date, not a string 84 | struct tm theTime; 85 | if ([value hasSuffix:@"+0000"]) 86 | { 87 | // format for Search API: "Fri, 06 Feb 2009 07:28:06 +0000" 88 | strptime([value UTF8String], "%a, %d %b %Y %H:%M:%S +0000", &theTime); 89 | } 90 | else 91 | { 92 | // format for REST API: "Thu Jan 15 02:04:38 +0000 2009" 93 | strptime([value UTF8String], "%a %b %d %H:%M:%S +0000 %Y", &theTime); 94 | } 95 | time_t epochTime = timegm(&theTime); 96 | // save the date as a long with the number of seconds since the epoch in 1970 97 | [self addValue:[NSNumber numberWithLong:epochTime] forKey:currentKey]; 98 | // this value can be converted to a date with [NSDate dateWithTimeIntervalSince1970:epochTime] 99 | } 100 | else 101 | { 102 | [self addValue:value forKey:currentKey]; 103 | } 104 | 105 | [self clearCurrentKey]; 106 | } 107 | 108 | return 1; 109 | } 110 | 111 | int MGTwitterYAJLParser_processMapKey(void *ctx, const unsigned char * stringVal, unsigned int stringLen) 112 | { 113 | id self = (id)ctx; 114 | if (currentKey) 115 | { 116 | [self clearCurrentKey]; 117 | } 118 | 119 | currentKey = [[NSString alloc] initWithBytes:stringVal length:stringLen encoding:NSUTF8StringEncoding]; 120 | 121 | return 1; 122 | } 123 | 124 | int MGTwitterYAJLParser_processStartMap(void *ctx) 125 | { 126 | id self = ctx; 127 | 128 | [self startDictionaryWithKey:currentKey]; 129 | 130 | return 1; 131 | } 132 | 133 | 134 | int MGTwitterYAJLParser_processEndMap(void *ctx) 135 | { 136 | id self = ctx; 137 | 138 | [self endDictionary]; 139 | 140 | return 1; 141 | } 142 | 143 | int MGTwitterYAJLParser_processStartArray(void *ctx) 144 | { 145 | id self = ctx; 146 | 147 | [self startArrayWithKey:currentKey]; 148 | 149 | return 1; 150 | } 151 | 152 | int MGTwitterYAJLParser_processEndArray(void *ctx) 153 | { 154 | id self = ctx; 155 | 156 | [self endArray]; 157 | 158 | return 1; 159 | } 160 | 161 | static yajl_callbacks sMGTwitterYAJLParserCallbacks = { 162 | MGTwitterYAJLParser_processNull, 163 | MGTwitterYAJLParser_processBoolean, 164 | NULL, 165 | NULL, 166 | MGTwitterYAJLParser_processNumber, 167 | MGTwitterYAJLParser_processString, 168 | MGTwitterYAJLParser_processStartMap, 169 | MGTwitterYAJLParser_processMapKey, 170 | MGTwitterYAJLParser_processEndMap, 171 | MGTwitterYAJLParser_processStartArray, 172 | MGTwitterYAJLParser_processEndArray 173 | }; 174 | 175 | #pragma mark Creation and Destruction 176 | 177 | 178 | + (id)parserWithJSON:(NSData *)theJSON delegate:(NSObject *)theDelegate 179 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 180 | responseType:(MGTwitterResponseType)respType URL:(NSURL *)URL 181 | deliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions 182 | { 183 | id parser = [[self alloc] initWithJSON:theJSON 184 | delegate:theDelegate 185 | connectionIdentifier:identifier 186 | requestType:reqType 187 | responseType:respType 188 | URL:URL 189 | deliveryOptions:deliveryOptions]; 190 | 191 | return [parser autorelease]; 192 | } 193 | 194 | 195 | - (id)initWithJSON:(NSData *)theJSON delegate:(NSObject *)theDelegate 196 | connectionIdentifier:(NSString *)theIdentifier requestType:(MGTwitterRequestType)reqType 197 | responseType:(MGTwitterResponseType)respType URL:(NSURL *)theURL 198 | deliveryOptions:(MGTwitterEngineDeliveryOptions)theDeliveryOptions 199 | { 200 | if (self = [super init]) 201 | { 202 | json = [theJSON retain]; 203 | identifier = [theIdentifier retain]; 204 | requestType = reqType; 205 | responseType = respType; 206 | URL = [theURL retain]; 207 | deliveryOptions = theDeliveryOptions; 208 | delegate = theDelegate; 209 | 210 | if (deliveryOptions & MGTwitterEngineDeliveryAllResultsOption) 211 | { 212 | parsedObjects = [[NSMutableArray alloc] initWithCapacity:0]; 213 | } 214 | else 215 | { 216 | parsedObjects = nil; // rely on nil target to discard addObject 217 | } 218 | 219 | if ([json length] <= 5) 220 | { 221 | // NOTE: this is a hack for API methods that return short JSON responses that can't be parsed by YAJL. These include: 222 | // friendships/exists: returns "true" or "false" 223 | // help/test: returns "ok" 224 | // An empty response of "[]" is a special case. 225 | NSString *result = [[[NSString alloc] initWithBytes:[json bytes] length:[json length] encoding:NSUTF8StringEncoding] autorelease]; 226 | if (! [result isEqualToString:@"[]"]) 227 | { 228 | NSMutableDictionary *dictionary = [[[NSMutableDictionary alloc] initWithCapacity:1] autorelease]; 229 | 230 | if ([result isEqualToString:@"\"ok\""]) 231 | { 232 | [dictionary setObject:[NSNumber numberWithBool:YES] forKey:@"ok"]; 233 | } 234 | else 235 | { 236 | [dictionary setObject:[NSNumber numberWithBool:[result isEqualToString:@"true"]] forKey:@"friends"]; 237 | } 238 | [dictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 239 | 240 | [self _parsedObject:dictionary]; 241 | 242 | [parsedObjects addObject:dictionary]; 243 | } 244 | } 245 | else 246 | { 247 | // setup the yajl parser 248 | yajl_parser_config cfg = { 249 | 0, // allowComments: if nonzero, javascript style comments will be allowed in the input (both /* */ and //) 250 | 0 // checkUTF8: if nonzero, invalid UTF8 strings will cause a parse error 251 | }; 252 | _handle = yajl_alloc(&sMGTwitterYAJLParserCallbacks, &cfg, NULL, self); 253 | if (! _handle) 254 | { 255 | return nil; 256 | } 257 | 258 | yajl_status status = yajl_parse(_handle, [json bytes], [json length]); 259 | if (status != yajl_status_insufficient_data && status != yajl_status_ok) 260 | { 261 | unsigned char *errorMessage = yajl_get_error(_handle, 0, [json bytes], [json length]); 262 | NSLog(@"MGTwitterYAJLParser: error = %s", errorMessage); 263 | [self _parsingErrorOccurred:[NSError errorWithDomain:@"YAJL" code:status userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithUTF8String:(char *)errorMessage] forKey:@"errorMessage"]]]; 264 | yajl_free_error(_handle, errorMessage); 265 | } 266 | 267 | // free the yajl parser 268 | yajl_free(_handle); 269 | } 270 | 271 | // notify the delegate that parsing completed 272 | [self _parsingDidEnd]; 273 | } 274 | 275 | return self; 276 | } 277 | 278 | 279 | - (void)dealloc 280 | { 281 | [parsedObjects release]; 282 | [json release]; 283 | [identifier release]; 284 | [URL release]; 285 | 286 | delegate = nil; 287 | [super dealloc]; 288 | } 289 | 290 | - (void)parse 291 | { 292 | // empty implementation -- override in subclasses 293 | } 294 | 295 | #pragma mark Subclass utilities 296 | 297 | - (void)addValue:(id)value forKey:(NSString *)key 298 | { 299 | // default implementation -- override in subclasses 300 | 301 | NSLog(@"%@ = %@ (%@)", key, value, NSStringFromClass([value class])); 302 | } 303 | 304 | - (void)startDictionaryWithKey:(NSString *)key 305 | { 306 | // default implementation -- override in subclasses 307 | 308 | NSLog(@"dictionary start = %@", key); 309 | } 310 | 311 | - (void)endDictionary 312 | { 313 | // default implementation -- override in subclasses 314 | 315 | NSLog(@"dictionary end"); 316 | } 317 | 318 | - (void)startArrayWithKey:(NSString *)key 319 | { 320 | // default implementation -- override in subclasses 321 | 322 | NSLog(@"array start = %@", key); 323 | 324 | arrayDepth++; 325 | } 326 | 327 | - (void)endArray 328 | { 329 | // default implementation -- override in subclasses 330 | 331 | NSLog(@"array end"); 332 | 333 | arrayDepth--; 334 | [self clearCurrentKey]; 335 | } 336 | 337 | - (void)clearCurrentKey{ 338 | if(arrayDepth == 0){ 339 | [currentKey release]; 340 | currentKey = nil; 341 | } 342 | } 343 | 344 | #pragma mark Delegate callbacks 345 | 346 | - (BOOL) _isValidDelegateForSelector:(SEL)selector 347 | { 348 | return ((delegate != nil) && [delegate respondsToSelector:selector]); 349 | } 350 | 351 | - (void)_parsingDidEnd 352 | { 353 | if ([self _isValidDelegateForSelector:@selector(parsingSucceededForRequest:ofResponseType:withParsedObjects:)]) 354 | [delegate parsingSucceededForRequest:identifier ofResponseType:responseType withParsedObjects:parsedObjects]; 355 | } 356 | 357 | - (void)_parsingErrorOccurred:(NSError *)parseError 358 | { 359 | if ([self _isValidDelegateForSelector:@selector(parsingFailedForRequest:ofResponseType:withError:)]) 360 | [delegate parsingFailedForRequest:identifier ofResponseType:responseType withError:parseError]; 361 | } 362 | 363 | - (void)_parsedObject:(NSDictionary *)dictionary 364 | { 365 | if (deliveryOptions & MGTwitterEngineDeliveryIndividualResultsOption) 366 | if ([self _isValidDelegateForSelector:@selector(parsedObject:forRequest:ofResponseType:)]) 367 | [delegate parsedObject:(NSDictionary *)dictionary forRequest:identifier ofResponseType:responseType]; 368 | } 369 | 370 | 371 | @end 372 | -------------------------------------------------------------------------------- /MGTwitterLibXMLParser.m: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterLibXMLParser.m 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 18/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | // Major portions derived from BSTweetParser by Brent Simmons 9 | // 10 | 11 | #import "MGTwitterLibXMLParser.h" 12 | 13 | 14 | @implementation MGTwitterLibXMLParser 15 | 16 | 17 | #pragma mark Creation and Destruction 18 | 19 | 20 | + (id)parserWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 21 | connectionIdentifier:(NSString *)identifier requestType:(MGTwitterRequestType)reqType 22 | responseType:(MGTwitterResponseType)respType URL:(NSURL *)URL 23 | { 24 | id parser = [[self alloc] initWithXML:theXML 25 | delegate:theDelegate 26 | connectionIdentifier:identifier 27 | requestType:reqType 28 | responseType:respType 29 | URL:URL]; 30 | 31 | return [parser autorelease]; 32 | } 33 | 34 | 35 | - (id)initWithXML:(NSData *)theXML delegate:(NSObject *)theDelegate 36 | connectionIdentifier:(NSString *)theIdentifier requestType:(MGTwitterRequestType)reqType 37 | responseType:(MGTwitterResponseType)respType URL:(NSURL *)theURL 38 | { 39 | if ((self = [super init])) 40 | { 41 | xml = [theXML retain]; 42 | identifier = [theIdentifier retain]; 43 | requestType = reqType; 44 | responseType = respType; 45 | URL = [theURL retain]; 46 | delegate = theDelegate; 47 | parsedObjects = [[NSMutableArray alloc] initWithCapacity:0]; 48 | 49 | // setup the xml reader 50 | _reader = xmlReaderForMemory([xml bytes], (int)[xml length], [[URL absoluteString] UTF8String], nil, XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING); 51 | if (! _reader) 52 | { 53 | return nil; 54 | } 55 | 56 | // run the parser and create parsedObjects 57 | [self parse]; 58 | 59 | // free the xml reader used for parsing 60 | xmlFree(_reader); 61 | 62 | // notify the delegate that parsing completed 63 | [self _parsingDidEnd]; 64 | } 65 | 66 | return self; 67 | } 68 | 69 | 70 | - (void)dealloc 71 | { 72 | [parsedObjects release]; 73 | [xml release]; 74 | [identifier release]; 75 | [URL release]; 76 | 77 | delegate = nil; 78 | [super dealloc]; 79 | } 80 | 81 | - (void)parse 82 | { 83 | // empty implementation -- override in subclasses 84 | } 85 | 86 | #pragma mark Subclass utilities 87 | 88 | // get the value from the current node 89 | - (xmlChar *)_nodeValue 90 | { 91 | if (xmlTextReaderIsEmptyElement(_reader)) 92 | { 93 | return nil; 94 | } 95 | 96 | xmlChar *result = nil; 97 | int nodeType = xmlTextReaderNodeType(_reader); 98 | while (nodeType != XML_READER_TYPE_END_ELEMENT) 99 | { 100 | if (nodeType == XML_READER_TYPE_TEXT) 101 | { 102 | result = xmlTextReaderValue(_reader); 103 | } 104 | 105 | // advance reader 106 | int readerResult = xmlTextReaderRead(_reader); 107 | if (readerResult != 1) 108 | { 109 | break; 110 | } 111 | nodeType = xmlTextReaderNodeType(_reader); 112 | } 113 | 114 | //NSLog(@"node: %25s = %s", xmlTextReaderConstName(_reader), result); 115 | 116 | return result; 117 | } 118 | 119 | - (NSString *)_nodeValueAsString 120 | { 121 | xmlChar *nodeValue = [self _nodeValue]; 122 | if (! nodeValue) 123 | { 124 | return nil; 125 | } 126 | 127 | NSMutableString *value = [NSMutableString stringWithUTF8String:(const char *)nodeValue]; 128 | xmlFree(nodeValue); 129 | 130 | // convert HTML entities back into UTF-8 131 | [value replaceOccurrencesOfString:@">" withString:@">" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])]; 132 | [value replaceOccurrencesOfString:@"<" withString:@"<" options:NSCaseInsensitiveSearch range:NSMakeRange(0, [value length])]; 133 | 134 | NSString *result = [NSString stringWithString:value]; 135 | return result; 136 | } 137 | 138 | - (NSDate *)_nodeValueAsDate 139 | { 140 | xmlChar *nodeValue = [self _nodeValue]; 141 | if (! nodeValue) 142 | { 143 | return nil; 144 | } 145 | 146 | struct tm theTime; 147 | strptime((char *)nodeValue, "%a %b %d %H:%M:%S +0000 %Y", &theTime); 148 | xmlFree(nodeValue); 149 | time_t epochTime = timegm(&theTime); 150 | return [NSDate dateWithTimeIntervalSince1970:epochTime]; 151 | } 152 | 153 | - (NSNumber *)_nodeValueAsInt 154 | { 155 | xmlChar *nodeValue = [self _nodeValue]; 156 | if (! nodeValue) 157 | { 158 | return nil; 159 | } 160 | 161 | NSString *intString = [NSString stringWithUTF8String:(const char *)nodeValue]; 162 | xmlFree(nodeValue); 163 | return [NSNumber numberWithLongLong:[intString longLongValue]]; 164 | } 165 | 166 | - (NSNumber *)_nodeValueAsBool 167 | { 168 | xmlChar *nodeValue = [self _nodeValue]; 169 | if (! nodeValue) 170 | { 171 | return nil; 172 | } 173 | 174 | NSString *boolString = [NSString stringWithUTF8String:(const char *)nodeValue]; 175 | xmlFree(nodeValue); 176 | return [NSNumber numberWithBool:[boolString isEqualToString:@"true"]]; 177 | } 178 | 179 | - (NSDictionary *)_statusDictionaryForNodeWithName:(const xmlChar *)parentNodeName 180 | { 181 | if (xmlTextReaderIsEmptyElement(_reader)) 182 | return nil; 183 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 184 | 185 | int readerResult = xmlTextReaderRead(_reader); 186 | if (readerResult != 1) 187 | return nil; 188 | int nodeType = xmlTextReaderNodeType(_reader); 189 | const xmlChar *name = xmlTextReaderConstName(_reader); 190 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(parentNodeName, name))) 191 | { 192 | if (nodeType == XML_READER_TYPE_ELEMENT) 193 | { 194 | if (xmlStrEqual(name, BAD_CAST "user")) 195 | { 196 | // "user" is the name of a sub-dictionary in each item 197 | [dictionary setObject:[self _userDictionaryForNodeWithName:name] forKey:@"user"]; 198 | } 199 | else if (xmlStrEqual(name, BAD_CAST "id") || xmlStrEqual(name, BAD_CAST "in_reply_to_user_id") || xmlStrEqual(name, BAD_CAST "in_reply_to_status_id")) 200 | { 201 | // process element as an integer 202 | NSNumber *number = [self _nodeValueAsInt]; 203 | if (number) 204 | { 205 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 206 | } 207 | } 208 | else if (xmlStrEqual(name, BAD_CAST "created_at")) 209 | { 210 | // process element as a date 211 | NSDate *date = [self _nodeValueAsDate]; 212 | if (date) 213 | { 214 | [dictionary setObject:date forKey:[NSString stringWithUTF8String:(const char *)name]]; 215 | } 216 | } 217 | else if (xmlStrEqual(name, BAD_CAST "truncated") || xmlStrEqual(name, BAD_CAST "favorited")) 218 | { 219 | // process element as a boolean 220 | NSNumber *number = [self _nodeValueAsBool]; 221 | if (number) 222 | { 223 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 224 | } 225 | } 226 | else if (xmlStrEqual(name, BAD_CAST "retweeted_status")) 227 | { 228 | [dictionary setObject:[self _statusDictionaryForNodeWithName:name] forKey:[NSString stringWithUTF8String:(const char *)name]]; 229 | } 230 | else 231 | { 232 | // process element as a string 233 | NSString *string = [self _nodeValueAsString]; 234 | if (string) 235 | { 236 | [dictionary setObject:string forKey:[NSString stringWithUTF8String:(const char *)name]]; 237 | } 238 | } 239 | } 240 | 241 | // advance reader 242 | readerResult = xmlTextReaderRead(_reader); 243 | if (readerResult != 1) 244 | break; 245 | nodeType = xmlTextReaderNodeType(_reader); 246 | name = xmlTextReaderConstName(_reader); 247 | } 248 | 249 | // save the request type in the tweet 250 | [dictionary setObject:[NSNumber numberWithInt:requestType] forKey:TWITTER_SOURCE_REQUEST_TYPE]; 251 | 252 | return dictionary; 253 | } 254 | 255 | - (NSDictionary *)_userDictionaryForNodeWithName:(const xmlChar *)parentNodeName 256 | { 257 | if (xmlTextReaderIsEmptyElement(_reader)) 258 | return nil; 259 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 260 | 261 | int readerResult = xmlTextReaderRead(_reader); 262 | if (readerResult != 1) 263 | return nil; 264 | int nodeType = xmlTextReaderNodeType(_reader); 265 | const xmlChar *name = xmlTextReaderConstName(_reader); 266 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(parentNodeName, name))) 267 | { 268 | if (nodeType == XML_READER_TYPE_ELEMENT) 269 | { 270 | if (xmlStrEqual(name, BAD_CAST "id") || xmlStrEqual(name, BAD_CAST "followers_count") 271 | || xmlStrEqual(name, BAD_CAST "friends_count") || xmlStrEqual(name, BAD_CAST "favourites_count") 272 | || xmlStrEqual(name, BAD_CAST "statuses_count")) 273 | { 274 | // process element as an integer 275 | NSNumber *number = [self _nodeValueAsInt]; 276 | if (number) 277 | { 278 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 279 | } 280 | } 281 | else if (xmlStrEqual(name, BAD_CAST "protected")) 282 | { 283 | // process element as a boolean 284 | NSNumber *number = [self _nodeValueAsBool]; 285 | if (number) 286 | { 287 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 288 | } 289 | } 290 | else 291 | { 292 | // process element as a string 293 | NSString *s = [self _nodeValueAsString]; 294 | if (s) 295 | { 296 | [dictionary setObject:s forKey:[NSString stringWithUTF8String:(const char *)name]]; 297 | } 298 | } 299 | } 300 | 301 | // advance reader 302 | readerResult = xmlTextReaderRead(_reader); 303 | if (readerResult != 1) 304 | break; 305 | nodeType = xmlTextReaderNodeType(_reader); 306 | name = xmlTextReaderConstName(_reader); 307 | } 308 | 309 | return dictionary; 310 | } 311 | 312 | - (NSDictionary *)_hashDictionaryForNodeWithName:(const xmlChar *)parentNodeName 313 | { 314 | if (xmlTextReaderIsEmptyElement(_reader)) 315 | return nil; 316 | NSMutableDictionary *dictionary = [NSMutableDictionary dictionary]; 317 | 318 | int readerResult = xmlTextReaderRead(_reader); 319 | if (readerResult != 1) 320 | return nil; 321 | int nodeType = xmlTextReaderNodeType(_reader); 322 | const xmlChar *name = xmlTextReaderConstName(_reader); 323 | while (! (nodeType == XML_READER_TYPE_END_ELEMENT && xmlStrEqual(parentNodeName, name))) 324 | { 325 | if (nodeType == XML_READER_TYPE_ELEMENT) 326 | { 327 | if (xmlStrEqual(name, BAD_CAST "hourly-limit") || xmlStrEqual(name, BAD_CAST "remaining-hits") 328 | || xmlStrEqual(name, BAD_CAST "reset-time-in-seconds")) 329 | { 330 | // process element as an integer 331 | NSNumber *number = [self _nodeValueAsInt]; 332 | if (number) 333 | { 334 | [dictionary setObject:number forKey:[NSString stringWithUTF8String:(const char *)name]]; 335 | } 336 | } 337 | else 338 | { 339 | // process element as a string 340 | NSString *s = [self _nodeValueAsString]; 341 | if (s) 342 | { 343 | [dictionary setObject:s forKey:[NSString stringWithUTF8String:(const char *)name]]; 344 | } 345 | } 346 | } 347 | 348 | // advance reader 349 | readerResult = xmlTextReaderRead(_reader); 350 | if (readerResult != 1) 351 | break; 352 | nodeType = xmlTextReaderNodeType(_reader); 353 | name = xmlTextReaderConstName(_reader); 354 | } 355 | 356 | return dictionary; 357 | } 358 | 359 | 360 | #pragma mark Delegate callbacks 361 | 362 | - (void)_parsingDidEnd 363 | { 364 | //NSLog(@"Parsing complete: %@", parsedObjects); 365 | [delegate parsingSucceededForRequest:identifier ofResponseType:responseType withParsedObjects:parsedObjects]; 366 | } 367 | 368 | - (void)_parsingErrorOccurred:(NSError *)parseError 369 | { 370 | //NSLog(@"Parsing error occurred: %@", parseError); 371 | [delegate parsingFailedForRequest:identifier ofResponseType:responseType withError:parseError]; 372 | } 373 | 374 | @end 375 | -------------------------------------------------------------------------------- /MGTwitterEngine.h: -------------------------------------------------------------------------------- 1 | // 2 | // MGTwitterEngine.h 3 | // MGTwitterEngine 4 | // 5 | // Created by Matt Gemmell on 10/02/2008. 6 | // Copyright 2008 Instinctive Code. 7 | // 8 | 9 | #import "MGTwitterEngineGlobalHeader.h" 10 | 11 | #import "MGTwitterEngineDelegate.h" 12 | #import "MGTwitterParserDelegate.h" 13 | 14 | #import "OAToken.h" 15 | 16 | 17 | @interface MGTwitterEngine : NSObject 18 | { 19 | __weak NSObject *_delegate; 20 | NSMutableDictionary *_connections; // MGTwitterHTTPURLConnection objects 21 | NSString *_clientName; 22 | NSString *_clientVersion; 23 | NSString *_clientURL; 24 | NSString *_clientSourceToken; 25 | NSString *_APIDomain; 26 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 27 | NSString *_searchDomain; 28 | #endif 29 | BOOL _secureConnection; 30 | BOOL _clearsCookies; 31 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 32 | MGTwitterEngineDeliveryOptions _deliveryOptions; 33 | #endif 34 | 35 | // OAuth 36 | NSString *_consumerKey; 37 | NSString *_consumerSecret; 38 | OAToken *_accessToken; 39 | 40 | // basic auth - deprecated 41 | NSString *_username; 42 | NSString *_password; 43 | } 44 | 45 | #pragma mark Class management 46 | 47 | // Constructors 48 | + (MGTwitterEngine *)twitterEngineWithDelegate:(NSObject *)delegate; 49 | - (MGTwitterEngine *)initWithDelegate:(NSObject *)delegate; 50 | 51 | // Configuration and Accessors 52 | + (NSString *)version; // returns the version of MGTwitterEngine 53 | - (NSString *)clientName; // see README.txt for info on clientName/Version/URL/SourceToken 54 | - (NSString *)clientVersion; 55 | - (NSString *)clientURL; 56 | - (NSString *)clientSourceToken; 57 | - (void)setClientName:(NSString *)name version:(NSString *)version URL:(NSString *)url token:(NSString *)token; 58 | - (NSString *)APIDomain; 59 | - (void)setAPIDomain:(NSString *)domain; 60 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 61 | - (NSString *)searchDomain; 62 | - (void)setSearchDomain:(NSString *)domain; 63 | #endif 64 | - (BOOL)usesSecureConnection; // YES = uses HTTPS, default is YES 65 | - (void)setUsesSecureConnection:(BOOL)flag; 66 | - (BOOL)clearsCookies; // YES = deletes twitter.com cookies when setting username/password, default is NO (see README.txt) 67 | - (void)setClearsCookies:(BOOL)flag; 68 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 69 | - (MGTwitterEngineDeliveryOptions)deliveryOptions; 70 | - (void)setDeliveryOptions:(MGTwitterEngineDeliveryOptions)deliveryOptions; 71 | #endif 72 | 73 | // Connection methods 74 | - (NSUInteger)numberOfConnections; 75 | - (NSArray *)connectionIdentifiers; 76 | - (void)closeConnection:(NSString *)identifier; 77 | - (void)closeAllConnections; 78 | 79 | // Utility methods 80 | /// Note: the -getImageAtURL: method works for any image URL, not just Twitter images. 81 | // It does not require authentication, and is provided here for convenience. 82 | // As with the Twitter API methods below, it returns a unique connection identifier. 83 | // Retrieved images are sent to the delegate via the -imageReceived:forRequest: method. 84 | - (NSString *)getImageAtURL:(NSString *)urlString; 85 | 86 | #pragma mark REST API methods 87 | 88 | // ====================================================================================================== 89 | // Twitter REST API methods 90 | // See documentation at: http://apiwiki.twitter.com/Twitter-API-Documentation 91 | // All methods below return a unique connection identifier. 92 | // ====================================================================================================== 93 | 94 | // Status methods 95 | 96 | - (NSString *)getPublicTimeline; // statuses/public_timeline 97 | 98 | - (NSString *)getHomeTimelineSinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/home_timeline 99 | - (NSString *)getHomeTimelineSinceID:(MGTwitterEngineID)sinceID withMaximumID:(MGTwitterEngineID)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/home_timeline 100 | 101 | - (NSString *)getFollowedTimelineSinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/friends_timeline 102 | - (NSString *)getFollowedTimelineSinceID:(MGTwitterEngineID)sinceID withMaximumID:(MGTwitterEngineID)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/friends_timeline 103 | 104 | - (NSString *)getUserTimelineFor:(NSString *)username sinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/user_timeline & statuses/user_timeline/user 105 | - (NSString *)getUserTimelineFor:(NSString *)username sinceID:(MGTwitterEngineID)sinceID withMaximumID:(MGTwitterEngineID)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/user_timeline & statuses/user_timeline/user 106 | 107 | - (NSString *)getUpdate:(MGTwitterEngineID)updateID; // statuses/show 108 | - (NSString *)sendUpdate:(NSString *)status; // statuses/update 109 | 110 | - (NSString *)sendUpdate:(NSString *)status withLatitude:(MGTwitterEngineLocationDegrees)latitude longitude:(MGTwitterEngineLocationDegrees)longitude; // statuses/update 111 | - (NSString *)sendUpdate:(NSString *)status inReplyTo:(MGTwitterEngineID)updateID; // statuses/update 112 | - (NSString *)sendUpdate:(NSString *)status inReplyTo:(MGTwitterEngineID)updateID withLatitude:(MGTwitterEngineLocationDegrees)latitude longitude:(MGTwitterEngineLocationDegrees)longitude; // statuses/update 113 | - (NSString *)sendRetweet:(MGTwitterEngineID)tweetID; // statuses/retweet 114 | 115 | - (NSString *)getRepliesStartingAtPage:(int)pageNum; // statuses/mentions 116 | - (NSString *)getRepliesSinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum count:(int)count; // statuses/mentions 117 | - (NSString *)getRepliesSinceID:(MGTwitterEngineID)sinceID withMaximumID:(MGTwitterEngineID)maxID startingAtPage:(int)pageNum count:(int)count; // statuses/mentions 118 | 119 | - (NSString *)deleteUpdate:(MGTwitterEngineID)updateID; // statuses/destroy 120 | 121 | - (NSString *)getFeaturedUsers; // statuses/features (undocumented, returns invalid JSON data) 122 | 123 | 124 | // User methods 125 | 126 | - (NSString *)getRecentlyUpdatedFriendsFor:(NSString *)username startingAtPage:(int)pageNum; // statuses/friends & statuses/friends/user 127 | 128 | - (NSString *)getFollowersIncludingCurrentStatus:(BOOL)flag; // statuses/followers 129 | 130 | - (NSString *)getUserInformationFor:(NSString *)usernameOrID; // users/show 131 | - (NSString *)getBulkUserInformationFor:(NSString *)userIDs; 132 | 133 | - (NSString *)getUserInformationForEmail:(NSString *)email; // users/show 134 | 135 | // List Methods 136 | 137 | // List the lists of the specified user. Private lists will be included if the 138 | // authenticated users is the same as the user who's lists are being returned. 139 | - (NSString *)getListsForUser:(NSString *)username; 140 | 141 | // Creates a new list for the authenticated user. Accounts are limited to 20 lists. 142 | // Options include: 143 | // mode - Whether your list is public or private. Values can be public or private. 144 | // If no mode is specified the list will be public. 145 | // description - The description to give the list. 146 | - (NSString *)createListForUser:(NSString *)username withName:(NSString *)listName withOptions:(NSDictionary *)options; 147 | 148 | // update an existing list 149 | - (NSString *)updateListForUser:(NSString *)username withID:(MGTwitterEngineID)listID withOptions:(NSDictionary *)options; 150 | 151 | // Show the specified list. Private lists will only be shown if the authenticated user owns the specified list. 152 | - (NSString *)getListForUser:(NSString *)username withID:(MGTwitterEngineID)listID; 153 | 154 | // Direct Message methods 155 | 156 | - (NSString *)getDirectMessagesSinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum; // direct_messages 157 | - (NSString *)getDirectMessagesSinceID:(MGTwitterEngineID)sinceID withMaximumID:(MGTwitterEngineID)maxID startingAtPage:(int)pageNum count:(int)count; // direct_messages 158 | 159 | - (NSString *)getSentDirectMessagesSinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum; // direct_messages/sent 160 | - (NSString *)getSentDirectMessagesSinceID:(MGTwitterEngineID)sinceID withMaximumID:(MGTwitterEngineID)maxID startingAtPage:(int)pageNum count:(int)count; // direct_messages/sent 161 | 162 | - (NSString *)sendDirectMessage:(NSString *)message to:(NSString *)username; // direct_messages/new 163 | - (NSString *)deleteDirectMessage:(MGTwitterEngineID)updateID;// direct_messages/destroy 164 | 165 | 166 | // Friendship methods 167 | 168 | - (NSString *)enableUpdatesFor:(NSString *)username; // friendships/create (follow username) 169 | - (NSString *)disableUpdatesFor:(NSString *)username; // friendships/destroy (unfollow username) 170 | - (NSString *)isUser:(NSString *)username1 receivingUpdatesFor:(NSString *)username2; // friendships/exists (test if username1 follows username2) 171 | 172 | 173 | // Account methods 174 | 175 | - (NSString *)checkUserCredentials; // account/verify_credentials 176 | - (NSString *)endUserSession; // account/end_session 177 | 178 | - (NSString *)setLocation:(NSString *)location; // account/update_location (deprecated, use account/update_profile instead) 179 | 180 | - (NSString *)setNotificationsDeliveryMethod:(NSString *)method; // account/update_delivery_device 181 | 182 | // TODO: Add: account/update_profile_colors 183 | - (NSString *)setProfileImageWithImageAtPath:(NSString *)pathToFile; 184 | - (NSString *)setProfileBackgroundImageWithImageAtPath:(NSString *)pathToFile andTitle:(NSString *)title; 185 | 186 | - (NSString *)getRateLimitStatus; // account/rate_limit_status 187 | 188 | // TODO: Add: account/update_profile 189 | 190 | // - (NSString *)getUserUpdatesArchiveStartingAtPage:(int)pageNum; // account/archive (removed, use /statuses/user_timeline instead) 191 | 192 | 193 | // Favorite methods 194 | 195 | - (NSString *)getFavoriteUpdatesFor:(NSString *)username startingAtPage:(int)pageNum; // favorites 196 | 197 | - (NSString *)markUpdate:(MGTwitterEngineID)updateID asFavorite:(BOOL)flag; // favorites/create, favorites/destroy 198 | 199 | 200 | // Notification methods 201 | 202 | - (NSString *)enableNotificationsFor:(NSString *)username; // notifications/follow 203 | - (NSString *)disableNotificationsFor:(NSString *)username; // notifications/leave 204 | 205 | 206 | // Block methods 207 | 208 | - (NSString *)block:(NSString *)username; // blocks/create 209 | - (NSString *)unblock:(NSString *)username; // blocks/destroy 210 | 211 | 212 | // Help methods 213 | 214 | - (NSString *)testService; // help/test 215 | 216 | - (NSString *)getDowntimeSchedule; // help/downtime_schedule (undocumented) 217 | 218 | 219 | // Social Graph methods 220 | - (NSString *)getFriendIDsFor:(NSString *)username startingFromCursor:(MGTwitterEngineCursorID)cursor; // friends/ids 221 | - (NSString *)getFollowerIDsFor:(NSString *)username startingFromCursor:(MGTwitterEngineCursorID)cursor; // followers/ids 222 | 223 | 224 | #pragma mark Search API methods 225 | 226 | // ====================================================================================================== 227 | // Twitter Search API methods 228 | // See documentation at: http://apiwiki.twitter.com/Twitter-API-Documentation 229 | // All methods below return a unique connection identifier. 230 | // ====================================================================================================== 231 | 232 | #if YAJL_AVAILABLE || TOUCHJSON_AVAILABLE 233 | 234 | // Search method 235 | 236 | - (NSString *)getSearchResultsForQuery:(NSString *)query; 237 | - (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum count:(int)count; // search 238 | - (NSString *)getSearchResultsForQuery:(NSString *)query sinceID:(MGTwitterEngineID)sinceID startingAtPage:(int)pageNum count:(int)count geocode:(NSString *)geocode; 239 | 240 | // Trends method 241 | 242 | - (NSString *)getCurrentTrends; // current trends 243 | 244 | #endif 245 | 246 | @end 247 | 248 | @interface MGTwitterEngine (BasicAuth) 249 | 250 | - (NSString *)username; 251 | - (void)setUsername:(NSString *) newUsername; 252 | 253 | - (NSString *)password DEPRECATED_ATTRIBUTE; 254 | - (void)setUsername:(NSString *)username password:(NSString *)password DEPRECATED_ATTRIBUTE; 255 | 256 | @end 257 | 258 | @interface MGTwitterEngine (OAuth) 259 | 260 | - (void)setConsumerKey:(NSString *)key secret:(NSString *)secret; 261 | - (NSString *)consumerKey; 262 | - (NSString *)consumerSecret; 263 | 264 | - (void)setAccessToken: (OAToken *)token; 265 | - (OAToken *)accessToken; 266 | 267 | // XAuth login - NOTE: You MUST email Twitter with your application's OAuth key/secret to 268 | // get OAuth access. This will not work if you don't do this. 269 | - (NSString *)getXAuthAccessTokenForUsername:(NSString *)username 270 | password:(NSString *)password; 271 | 272 | @end 273 | 274 | 275 | -------------------------------------------------------------------------------- /MGTwitterEngine.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 44; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1E4C01691186A3780092F9AD /* MGTwitterMiscYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFEA0F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.m */; }; 11 | 1E4C016A1186A3780092F9AD /* MGTwitterStatusesYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFEC0F2141AB004F5AE3 /* MGTwitterStatusesYAJLParser.m */; }; 12 | 1E4C016B1186A3780092F9AD /* MGTwitterMessagesYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFE80F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m */; }; 13 | 1E4C016C1186A3780092F9AD /* MGTwitterYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFF00F2141AB004F5AE3 /* MGTwitterYAJLParser.m */; }; 14 | 1E4C016D1186A3780092F9AD /* MGTwitterUsersYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44AEFFEE0F2141AB004F5AE3 /* MGTwitterUsersYAJLParser.m */; }; 15 | 1E4C016E1186A3780092F9AD /* MGTwitterSearchYAJLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 440E60660F257C1300EF8874 /* MGTwitterSearchYAJLParser.m */; }; 16 | 1E4C01951186A47C0092F9AD /* yajl_alloc.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01881186A47C0092F9AD /* yajl_alloc.c */; }; 17 | 1E4C01961186A47C0092F9AD /* yajl_buf.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C018A1186A47C0092F9AD /* yajl_buf.c */; }; 18 | 1E4C01971186A47C0092F9AD /* yajl_encode.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C018D1186A47C0092F9AD /* yajl_encode.c */; }; 19 | 1E4C01981186A47C0092F9AD /* yajl_gen.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C018F1186A47C0092F9AD /* yajl_gen.c */; }; 20 | 1E4C01991186A47C0092F9AD /* yajl_lex.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01901186A47C0092F9AD /* yajl_lex.c */; }; 21 | 1E4C019A1186A47C0092F9AD /* yajl_parser.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01921186A47C0092F9AD /* yajl_parser.c */; }; 22 | 1E4C019B1186A47C0092F9AD /* yajl.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01941186A47C0092F9AD /* yajl.c */; }; 23 | 1E4C01C81186A49C0092F9AD /* NSMutableURLRequest+Parameters.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01A11186A49C0092F9AD /* NSMutableURLRequest+Parameters.m */; }; 24 | 1E4C01C91186A49C0092F9AD /* NSString+URLEncoding.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01A31186A49C0092F9AD /* NSString+URLEncoding.m */; }; 25 | 1E4C01CA1186A49C0092F9AD /* NSURL+Base.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01A51186A49C0092F9AD /* NSURL+Base.m */; }; 26 | 1E4C01CB1186A49C0092F9AD /* Base64Transcoder.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01A71186A49C0092F9AD /* Base64Transcoder.c */; }; 27 | 1E4C01CC1186A49C0092F9AD /* hmac.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01A91186A49C0092F9AD /* hmac.c */; }; 28 | 1E4C01CD1186A49C0092F9AD /* sha1.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01AB1186A49C0092F9AD /* sha1.c */; }; 29 | 1E4C01CE1186A49C0092F9AD /* OACall.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01AE1186A49C0092F9AD /* OACall.m */; }; 30 | 1E4C01CF1186A49C0092F9AD /* OAConsumer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01B01186A49C0092F9AD /* OAConsumer.m */; }; 31 | 1E4C01D01186A49C0092F9AD /* OADataFetcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01B21186A49C0092F9AD /* OADataFetcher.m */; }; 32 | 1E4C01D11186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01B41186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.m */; }; 33 | 1E4C01D21186A49C0092F9AD /* OAMutableURLRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01B61186A49C0092F9AD /* OAMutableURLRequest.m */; }; 34 | 1E4C01D31186A49C0092F9AD /* OAPlaintextSignatureProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01B81186A49C0092F9AD /* OAPlaintextSignatureProvider.m */; }; 35 | 1E4C01D41186A49C0092F9AD /* OAProblem.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01BA1186A49C0092F9AD /* OAProblem.m */; }; 36 | 1E4C01D51186A49C0092F9AD /* OARequestParameter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01BC1186A49C0092F9AD /* OARequestParameter.m */; }; 37 | 1E4C01D61186A49C0092F9AD /* OAServiceTicket.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01BE1186A49C0092F9AD /* OAServiceTicket.m */; }; 38 | 1E4C01D81186A49C0092F9AD /* OAToken_KeychainExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01C21186A49C0092F9AD /* OAToken_KeychainExtensions.m */; }; 39 | 1E4C01D91186A49C0092F9AD /* OAToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E4C01C41186A49C0092F9AD /* OAToken.m */; }; 40 | 1E4C01E01186A5260092F9AD /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E4C01DF1186A5260092F9AD /* Security.framework */; }; 41 | 1E79899F118D071E00DDD6D9 /* MGTwitterTouchJSONParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E79899E118D071E00DDD6D9 /* MGTwitterTouchJSONParser.m */; }; 42 | 1E798A66118D077E00DDD6D9 /* CDataScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989E7118D077E00DDD6D9 /* CDataScanner.m */; }; 43 | 1E798A67118D077E00DDD6D9 /* CDataScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989EA118D077E00DDD6D9 /* CDataScanner_Extensions.m */; }; 44 | 1E798A68118D077E00DDD6D9 /* NSCharacterSet_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989EC118D077E00DDD6D9 /* NSCharacterSet_Extensions.m */; }; 45 | 1E798A69118D077E00DDD6D9 /* NSDictionary_JSONExtensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989EE118D077E00DDD6D9 /* NSDictionary_JSONExtensions.m */; }; 46 | 1E798A6A118D077E00DDD6D9 /* NSScanner_Extensions.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989F0118D077E00DDD6D9 /* NSScanner_Extensions.m */; }; 47 | 1E798A6B118D077E00DDD6D9 /* CJSONDataSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989F3118D077E00DDD6D9 /* CJSONDataSerializer.m */; }; 48 | 1E798A6C118D077E00DDD6D9 /* CJSONDeserializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989F5118D077E00DDD6D9 /* CJSONDeserializer.m */; }; 49 | 1E798A6D118D077E00DDD6D9 /* CJSONScanner.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989F7118D077E00DDD6D9 /* CJSONScanner.m */; }; 50 | 1E798A6E118D077E00DDD6D9 /* CJSONSerializer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989F9118D077E00DDD6D9 /* CJSONSerializer.m */; }; 51 | 1E798A6F118D077E00DDD6D9 /* CSerializedJSONData.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E7989FB118D077E00DDD6D9 /* CSerializedJSONData.m */; }; 52 | 44F7517C0E47DBD600858A1B /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 44F7517B0E47DBD600858A1B /* libxml2.dylib */; }; 53 | 44F7518F0E47DDD500858A1B /* MGTwitterUsersLibXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44F751890E47DDD500858A1B /* MGTwitterUsersLibXMLParser.m */; }; 54 | 44F751900E47DDD500858A1B /* MGTwitterMiscLibXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44F7518A0E47DDD500858A1B /* MGTwitterMiscLibXMLParser.m */; }; 55 | 44F751910E47DDD500858A1B /* MGTwitterMessagesLibXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44F7518C0E47DDD500858A1B /* MGTwitterMessagesLibXMLParser.m */; }; 56 | 44F751920E47DDD500858A1B /* MGTwitterLibXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44F7518D0E47DDD500858A1B /* MGTwitterLibXMLParser.m */; }; 57 | 44F751930E47DDD500858A1B /* MGTwitterStatusesLibXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 44F7518E0E47DDD500858A1B /* MGTwitterStatusesLibXMLParser.m */; }; 58 | 44F751A70E47DEC400858A1B /* NSData+Base64.m in Sources */ = {isa = PBXBuildFile; fileRef = 44F751A50E47DEC400858A1B /* NSData+Base64.m */; }; 59 | 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */ = {isa = PBXBuildFile; fileRef = 29B97318FDCFA39411CA2CEA /* MainMenu.nib */; }; 60 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; }; 61 | 8D11072D0486CEB800E47090 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; settings = {ATTRIBUTES = (); }; }; 62 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */; }; 63 | C90031BC0D6B796400C38924 /* MGTwitterUsersParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C90031BB0D6B796400C38924 /* MGTwitterUsersParser.m */; }; 64 | C90031C00D6B798800C38924 /* MGTwitterMessagesParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C90031BF0D6B798800C38924 /* MGTwitterMessagesParser.m */; }; 65 | C90F74CE0D6A3B7500F602A5 /* MGTwitterXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C90F74CD0D6A3B7500F602A5 /* MGTwitterXMLParser.m */; }; 66 | C9811E5D0D5F696200720D77 /* AppController.m in Sources */ = {isa = PBXBuildFile; fileRef = C9811E5C0D5F696200720D77 /* AppController.m */; }; 67 | C9811E640D5F69B500720D77 /* MGTwitterEngine.m in Sources */ = {isa = PBXBuildFile; fileRef = C9811E630D5F69B500720D77 /* MGTwitterEngine.m */; }; 68 | C9AE949C0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.m in Sources */ = {isa = PBXBuildFile; fileRef = C9AE949B0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.m */; }; 69 | C9CB60EC0DF98ED300EE8FCF /* MGTwitterMiscParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C9CB60EB0DF98ED300EE8FCF /* MGTwitterMiscParser.m */; }; 70 | C9EF98A10D68AB970041A17E /* NSString+UUID.m in Sources */ = {isa = PBXBuildFile; fileRef = C9EF98A00D68AB970041A17E /* NSString+UUID.m */; }; 71 | C9FEB12C0D6095AF009AA322 /* MGTwitterStatusesParser.m in Sources */ = {isa = PBXBuildFile; fileRef = C9FEB12B0D6095AF009AA322 /* MGTwitterStatusesParser.m */; }; 72 | D47CF9B511541D0A00E07931 /* MGTwitterSocialGraphParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D47CF9B411541D0A00E07931 /* MGTwitterSocialGraphParser.m */; }; 73 | D47CFCA9115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = D47CFCA8115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.m */; }; 74 | F4763D2A11C1837300A35E7E /* MGTwitterUserListsParser.m in Sources */ = {isa = PBXBuildFile; fileRef = F4763D2911C1837300A35E7E /* MGTwitterUserListsParser.m */; }; 75 | /* End PBXBuildFile section */ 76 | 77 | /* Begin PBXFileReference section */ 78 | 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 79 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; }; 80 | 1E4C01851186A47C0092F9AD /* yajl_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_common.h; path = src/api/yajl_common.h; sourceTree = ""; }; 81 | 1E4C01861186A47C0092F9AD /* yajl_gen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_gen.h; path = src/api/yajl_gen.h; sourceTree = ""; }; 82 | 1E4C01871186A47C0092F9AD /* yajl_parse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_parse.h; path = src/api/yajl_parse.h; sourceTree = ""; }; 83 | 1E4C01881186A47C0092F9AD /* yajl_alloc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl_alloc.c; path = src/yajl_alloc.c; sourceTree = ""; }; 84 | 1E4C01891186A47C0092F9AD /* yajl_alloc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_alloc.h; path = src/yajl_alloc.h; sourceTree = ""; }; 85 | 1E4C018A1186A47C0092F9AD /* yajl_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl_buf.c; path = src/yajl_buf.c; sourceTree = ""; }; 86 | 1E4C018B1186A47C0092F9AD /* yajl_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_buf.h; path = src/yajl_buf.h; sourceTree = ""; }; 87 | 1E4C018C1186A47C0092F9AD /* yajl_bytestack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_bytestack.h; path = src/yajl_bytestack.h; sourceTree = ""; }; 88 | 1E4C018D1186A47C0092F9AD /* yajl_encode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl_encode.c; path = src/yajl_encode.c; sourceTree = ""; }; 89 | 1E4C018E1186A47C0092F9AD /* yajl_encode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_encode.h; path = src/yajl_encode.h; sourceTree = ""; }; 90 | 1E4C018F1186A47C0092F9AD /* yajl_gen.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl_gen.c; path = src/yajl_gen.c; sourceTree = ""; }; 91 | 1E4C01901186A47C0092F9AD /* yajl_lex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl_lex.c; path = src/yajl_lex.c; sourceTree = ""; }; 92 | 1E4C01911186A47C0092F9AD /* yajl_lex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_lex.h; path = src/yajl_lex.h; sourceTree = ""; }; 93 | 1E4C01921186A47C0092F9AD /* yajl_parser.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl_parser.c; path = src/yajl_parser.c; sourceTree = ""; }; 94 | 1E4C01931186A47C0092F9AD /* yajl_parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = yajl_parser.h; path = src/yajl_parser.h; sourceTree = ""; }; 95 | 1E4C01941186A47C0092F9AD /* yajl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = yajl.c; path = src/yajl.c; sourceTree = ""; }; 96 | 1E4C01A01186A49C0092F9AD /* NSMutableURLRequest+Parameters.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSMutableURLRequest+Parameters.h"; sourceTree = ""; }; 97 | 1E4C01A11186A49C0092F9AD /* NSMutableURLRequest+Parameters.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSMutableURLRequest+Parameters.m"; sourceTree = ""; }; 98 | 1E4C01A21186A49C0092F9AD /* NSString+URLEncoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+URLEncoding.h"; sourceTree = ""; }; 99 | 1E4C01A31186A49C0092F9AD /* NSString+URLEncoding.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+URLEncoding.m"; sourceTree = ""; }; 100 | 1E4C01A41186A49C0092F9AD /* NSURL+Base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+Base.h"; sourceTree = ""; }; 101 | 1E4C01A51186A49C0092F9AD /* NSURL+Base.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+Base.m"; sourceTree = ""; }; 102 | 1E4C01A71186A49C0092F9AD /* Base64Transcoder.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Base64Transcoder.c; sourceTree = ""; }; 103 | 1E4C01A81186A49C0092F9AD /* Base64Transcoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Base64Transcoder.h; sourceTree = ""; }; 104 | 1E4C01A91186A49C0092F9AD /* hmac.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hmac.c; sourceTree = ""; }; 105 | 1E4C01AA1186A49C0092F9AD /* hmac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hmac.h; sourceTree = ""; }; 106 | 1E4C01AB1186A49C0092F9AD /* sha1.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sha1.c; sourceTree = ""; }; 107 | 1E4C01AC1186A49C0092F9AD /* sha1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha1.h; sourceTree = ""; }; 108 | 1E4C01AD1186A49C0092F9AD /* OACall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OACall.h; sourceTree = ""; }; 109 | 1E4C01AE1186A49C0092F9AD /* OACall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OACall.m; sourceTree = ""; }; 110 | 1E4C01AF1186A49C0092F9AD /* OAConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAConsumer.h; sourceTree = ""; }; 111 | 1E4C01B01186A49C0092F9AD /* OAConsumer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAConsumer.m; sourceTree = ""; }; 112 | 1E4C01B11186A49C0092F9AD /* OADataFetcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OADataFetcher.h; sourceTree = ""; }; 113 | 1E4C01B21186A49C0092F9AD /* OADataFetcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OADataFetcher.m; sourceTree = ""; }; 114 | 1E4C01B31186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAHMAC_SHA1SignatureProvider.h; sourceTree = ""; }; 115 | 1E4C01B41186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAHMAC_SHA1SignatureProvider.m; sourceTree = ""; }; 116 | 1E4C01B51186A49C0092F9AD /* OAMutableURLRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAMutableURLRequest.h; sourceTree = ""; }; 117 | 1E4C01B61186A49C0092F9AD /* OAMutableURLRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAMutableURLRequest.m; sourceTree = ""; }; 118 | 1E4C01B71186A49C0092F9AD /* OAPlaintextSignatureProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAPlaintextSignatureProvider.h; sourceTree = ""; }; 119 | 1E4C01B81186A49C0092F9AD /* OAPlaintextSignatureProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAPlaintextSignatureProvider.m; sourceTree = ""; }; 120 | 1E4C01B91186A49C0092F9AD /* OAProblem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAProblem.h; sourceTree = ""; }; 121 | 1E4C01BA1186A49C0092F9AD /* OAProblem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAProblem.m; sourceTree = ""; }; 122 | 1E4C01BB1186A49C0092F9AD /* OARequestParameter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OARequestParameter.h; sourceTree = ""; }; 123 | 1E4C01BC1186A49C0092F9AD /* OARequestParameter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OARequestParameter.m; sourceTree = ""; }; 124 | 1E4C01BD1186A49C0092F9AD /* OAServiceTicket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAServiceTicket.h; sourceTree = ""; }; 125 | 1E4C01BE1186A49C0092F9AD /* OAServiceTicket.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAServiceTicket.m; sourceTree = ""; }; 126 | 1E4C01BF1186A49C0092F9AD /* OASignatureProviding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OASignatureProviding.h; sourceTree = ""; }; 127 | 1E4C01C11186A49C0092F9AD /* OAToken_KeychainExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAToken_KeychainExtensions.h; sourceTree = ""; }; 128 | 1E4C01C21186A49C0092F9AD /* OAToken_KeychainExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAToken_KeychainExtensions.m; sourceTree = ""; }; 129 | 1E4C01C31186A49C0092F9AD /* OAToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAToken.h; sourceTree = ""; }; 130 | 1E4C01C41186A49C0092F9AD /* OAToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OAToken.m; sourceTree = ""; }; 131 | 1E4C01C71186A49C0092F9AD /* OAuthConsumer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OAuthConsumer.h; sourceTree = ""; }; 132 | 1E4C01DF1186A5260092F9AD /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 133 | 1E79899D118D071E00DDD6D9 /* MGTwitterTouchJSONParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterTouchJSONParser.h; sourceTree = ""; }; 134 | 1E79899E118D071E00DDD6D9 /* MGTwitterTouchJSONParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterTouchJSONParser.m; sourceTree = ""; }; 135 | 1E7989E6118D077E00DDD6D9 /* CDataScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner.h; sourceTree = ""; }; 136 | 1E7989E7118D077E00DDD6D9 /* CDataScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner.m; sourceTree = ""; }; 137 | 1E7989E9118D077E00DDD6D9 /* CDataScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDataScanner_Extensions.h; sourceTree = ""; }; 138 | 1E7989EA118D077E00DDD6D9 /* CDataScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDataScanner_Extensions.m; sourceTree = ""; }; 139 | 1E7989EB118D077E00DDD6D9 /* NSCharacterSet_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSCharacterSet_Extensions.h; sourceTree = ""; }; 140 | 1E7989EC118D077E00DDD6D9 /* NSCharacterSet_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSCharacterSet_Extensions.m; sourceTree = ""; }; 141 | 1E7989ED118D077E00DDD6D9 /* NSDictionary_JSONExtensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSDictionary_JSONExtensions.h; sourceTree = ""; }; 142 | 1E7989EE118D077E00DDD6D9 /* NSDictionary_JSONExtensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSDictionary_JSONExtensions.m; sourceTree = ""; }; 143 | 1E7989EF118D077E00DDD6D9 /* NSScanner_Extensions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSScanner_Extensions.h; sourceTree = ""; }; 144 | 1E7989F0118D077E00DDD6D9 /* NSScanner_Extensions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSScanner_Extensions.m; sourceTree = ""; }; 145 | 1E7989F2118D077E00DDD6D9 /* CJSONDataSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDataSerializer.h; sourceTree = ""; }; 146 | 1E7989F3118D077E00DDD6D9 /* CJSONDataSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDataSerializer.m; sourceTree = ""; }; 147 | 1E7989F4118D077E00DDD6D9 /* CJSONDeserializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONDeserializer.h; sourceTree = ""; }; 148 | 1E7989F5118D077E00DDD6D9 /* CJSONDeserializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONDeserializer.m; sourceTree = ""; }; 149 | 1E7989F6118D077E00DDD6D9 /* CJSONScanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONScanner.h; sourceTree = ""; }; 150 | 1E7989F7118D077E00DDD6D9 /* CJSONScanner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONScanner.m; sourceTree = ""; }; 151 | 1E7989F8118D077E00DDD6D9 /* CJSONSerializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CJSONSerializer.h; sourceTree = ""; }; 152 | 1E7989F9118D077E00DDD6D9 /* CJSONSerializer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CJSONSerializer.m; sourceTree = ""; }; 153 | 1E7989FA118D077E00DDD6D9 /* CSerializedJSONData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSerializedJSONData.h; sourceTree = ""; }; 154 | 1E7989FB118D077E00DDD6D9 /* CSerializedJSONData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSerializedJSONData.m; sourceTree = ""; }; 155 | 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 156 | 29B97319FDCFA39411CA2CEA /* English */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; name = English; path = English.lproj/MainMenu.nib; sourceTree = ""; }; 157 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = /System/Library/Frameworks/AppKit.framework; sourceTree = ""; }; 158 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = ""; }; 159 | 32CA4F630368D1EE00C91783 /* MGTwitterEngine_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterEngine_Prefix.pch; sourceTree = ""; }; 160 | 440E60660F257C1300EF8874 /* MGTwitterSearchYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterSearchYAJLParser.m; sourceTree = ""; }; 161 | 440E60670F257C1300EF8874 /* MGTwitterSearchYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterSearchYAJLParser.h; sourceTree = ""; }; 162 | 44AEFFE70F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMessagesYAJLParser.h; sourceTree = ""; }; 163 | 44AEFFE80F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMessagesYAJLParser.m; sourceTree = ""; }; 164 | 44AEFFE90F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMiscYAJLParser.h; sourceTree = ""; }; 165 | 44AEFFEA0F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMiscYAJLParser.m; sourceTree = ""; }; 166 | 44AEFFEB0F2141AB004F5AE3 /* MGTwitterStatusesYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterStatusesYAJLParser.h; sourceTree = ""; }; 167 | 44AEFFEC0F2141AB004F5AE3 /* MGTwitterStatusesYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterStatusesYAJLParser.m; sourceTree = ""; }; 168 | 44AEFFED0F2141AB004F5AE3 /* MGTwitterUsersYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterUsersYAJLParser.h; sourceTree = ""; }; 169 | 44AEFFEE0F2141AB004F5AE3 /* MGTwitterUsersYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterUsersYAJLParser.m; sourceTree = ""; }; 170 | 44AEFFEF0F2141AB004F5AE3 /* MGTwitterYAJLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterYAJLParser.h; sourceTree = ""; }; 171 | 44AEFFF00F2141AB004F5AE3 /* MGTwitterYAJLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterYAJLParser.m; sourceTree = ""; }; 172 | 44F7517B0E47DBD600858A1B /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = /usr/lib/libxml2.dylib; sourceTree = ""; }; 173 | 44F751880E47DDD500858A1B /* MGTwitterMiscLibXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMiscLibXMLParser.h; sourceTree = ""; }; 174 | 44F751890E47DDD500858A1B /* MGTwitterUsersLibXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterUsersLibXMLParser.m; sourceTree = ""; }; 175 | 44F7518A0E47DDD500858A1B /* MGTwitterMiscLibXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMiscLibXMLParser.m; sourceTree = ""; }; 176 | 44F7518B0E47DDD500858A1B /* MGTwitterLibXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterLibXMLParser.h; sourceTree = ""; }; 177 | 44F7518C0E47DDD500858A1B /* MGTwitterMessagesLibXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMessagesLibXMLParser.m; sourceTree = ""; }; 178 | 44F7518D0E47DDD500858A1B /* MGTwitterLibXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterLibXMLParser.m; sourceTree = ""; }; 179 | 44F7518E0E47DDD500858A1B /* MGTwitterStatusesLibXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterStatusesLibXMLParser.m; sourceTree = ""; }; 180 | 44F7519A0E47DE4200858A1B /* MGTwitterStatusesLibXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterStatusesLibXMLParser.h; sourceTree = ""; }; 181 | 44F7519F0E47DE9100858A1B /* MGTwitterMessagesLibXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMessagesLibXMLParser.h; sourceTree = ""; }; 182 | 44F751A00E47DE9100858A1B /* MGTwitterUsersLibXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterUsersLibXMLParser.h; sourceTree = ""; }; 183 | 44F751A50E47DEC400858A1B /* NSData+Base64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSData+Base64.m"; sourceTree = ""; }; 184 | 44F751A60E47DEC400858A1B /* NSData+Base64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSData+Base64.h"; sourceTree = ""; }; 185 | 8D1107310486CEB800E47090 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 186 | 8D1107320486CEB800E47090 /* MGTwitterEngine.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MGTwitterEngine.app; sourceTree = BUILT_PRODUCTS_DIR; }; 187 | C90031BA0D6B796400C38924 /* MGTwitterUsersParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterUsersParser.h; sourceTree = ""; }; 188 | C90031BB0D6B796400C38924 /* MGTwitterUsersParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterUsersParser.m; sourceTree = ""; }; 189 | C90031BE0D6B798800C38924 /* MGTwitterMessagesParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMessagesParser.h; sourceTree = ""; }; 190 | C90031BF0D6B798800C38924 /* MGTwitterMessagesParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMessagesParser.m; sourceTree = ""; }; 191 | C90F74CC0D6A3B7500F602A5 /* MGTwitterXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterXMLParser.h; sourceTree = ""; }; 192 | C90F74CD0D6A3B7500F602A5 /* MGTwitterXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterXMLParser.m; sourceTree = ""; }; 193 | C90F74E10D6A3FF300F602A5 /* MGTwitterParserDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterParserDelegate.h; sourceTree = ""; }; 194 | C90F750D0D6A4CE100F602A5 /* TODO */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = TODO; sourceTree = ""; }; 195 | C92F28EE0E4DE7BC00CF98F8 /* MGTwitterEngineGlobalHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterEngineGlobalHeader.h; sourceTree = ""; }; 196 | C93312570D6EE53E00C76652 /* Source Code License.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Source Code License.rtf"; sourceTree = ""; }; 197 | C9811E5B0D5F696200720D77 /* AppController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppController.h; sourceTree = ""; }; 198 | C9811E5C0D5F696200720D77 /* AppController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppController.m; sourceTree = ""; }; 199 | C9811E620D5F69B500720D77 /* MGTwitterEngine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterEngine.h; sourceTree = ""; }; 200 | C9811E630D5F69B500720D77 /* MGTwitterEngine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterEngine.m; sourceTree = ""; }; 201 | C9AE94650D6761F800ADEBEC /* MGTwitterEngineDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterEngineDelegate.h; sourceTree = ""; }; 202 | C9AE949A0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterHTTPURLConnection.h; sourceTree = ""; }; 203 | C9AE949B0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterHTTPURLConnection.m; sourceTree = ""; }; 204 | C9CB60EA0DF98ED300EE8FCF /* MGTwitterMiscParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterMiscParser.h; sourceTree = ""; }; 205 | C9CB60EB0DF98ED300EE8FCF /* MGTwitterMiscParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterMiscParser.m; sourceTree = ""; }; 206 | C9E497610D686B3500C83995 /* MGTwitterRequestTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterRequestTypes.h; sourceTree = ""; }; 207 | C9EF989F0D68AB970041A17E /* NSString+UUID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+UUID.h"; sourceTree = ""; }; 208 | C9EF98A00D68AB970041A17E /* NSString+UUID.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+UUID.m"; sourceTree = ""; }; 209 | C9F6B4910D6F18290066FC1E /* README.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.txt; sourceTree = ""; }; 210 | C9FEB12A0D6095AF009AA322 /* MGTwitterStatusesParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterStatusesParser.h; sourceTree = ""; }; 211 | C9FEB12B0D6095AF009AA322 /* MGTwitterStatusesParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterStatusesParser.m; sourceTree = ""; }; 212 | D47CF9B311541D0A00E07931 /* MGTwitterSocialGraphParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterSocialGraphParser.h; sourceTree = ""; }; 213 | D47CF9B411541D0A00E07931 /* MGTwitterSocialGraphParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterSocialGraphParser.m; sourceTree = ""; }; 214 | D47CFCA7115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterSocialGraphLibXMLParser.h; sourceTree = ""; }; 215 | D47CFCA8115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterSocialGraphLibXMLParser.m; sourceTree = ""; }; 216 | F4763D2811C1837300A35E7E /* MGTwitterUserListsParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGTwitterUserListsParser.h; sourceTree = ""; }; 217 | F4763D2911C1837300A35E7E /* MGTwitterUserListsParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGTwitterUserListsParser.m; sourceTree = ""; }; 218 | /* End PBXFileReference section */ 219 | 220 | /* Begin PBXFrameworksBuildPhase section */ 221 | 8D11072E0486CEB800E47090 /* Frameworks */ = { 222 | isa = PBXFrameworksBuildPhase; 223 | buildActionMask = 2147483647; 224 | files = ( 225 | 8D11072F0486CEB800E47090 /* Cocoa.framework in Frameworks */, 226 | 44F7517C0E47DBD600858A1B /* libxml2.dylib in Frameworks */, 227 | 1E4C01E01186A5260092F9AD /* Security.framework in Frameworks */, 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | }; 231 | /* End PBXFrameworksBuildPhase section */ 232 | 233 | /* Begin PBXGroup section */ 234 | 080E96DDFE201D6D7F000001 /* Classes */ = { 235 | isa = PBXGroup; 236 | children = ( 237 | 1E7989A5118D077E00DDD6D9 /* TouchJSON */, 238 | 1E4C019E1186A48A0092F9AD /* OAuthConsumer */, 239 | 1E4C01841186A45C0092F9AD /* yajl */, 240 | C9FEB1280D609585009AA322 /* Demo */, 241 | C9FEB1290D609598009AA322 /* MATwitterEngine */, 242 | ); 243 | name = Classes; 244 | sourceTree = ""; 245 | }; 246 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */ = { 247 | isa = PBXGroup; 248 | children = ( 249 | 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, 250 | ); 251 | name = "Linked Frameworks"; 252 | sourceTree = ""; 253 | }; 254 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */ = { 255 | isa = PBXGroup; 256 | children = ( 257 | 44F7517B0E47DBD600858A1B /* libxml2.dylib */, 258 | 29B97324FDCFA39411CA2CEA /* AppKit.framework */, 259 | 29B97325FDCFA39411CA2CEA /* Foundation.framework */, 260 | ); 261 | name = "Other Frameworks"; 262 | sourceTree = ""; 263 | }; 264 | 19C28FACFE9D520D11CA2CBB /* Products */ = { 265 | isa = PBXGroup; 266 | children = ( 267 | 8D1107320486CEB800E47090 /* MGTwitterEngine.app */, 268 | ); 269 | name = Products; 270 | sourceTree = ""; 271 | }; 272 | 1E4C01841186A45C0092F9AD /* yajl */ = { 273 | isa = PBXGroup; 274 | children = ( 275 | 1E4C01851186A47C0092F9AD /* yajl_common.h */, 276 | 1E4C01861186A47C0092F9AD /* yajl_gen.h */, 277 | 1E4C01871186A47C0092F9AD /* yajl_parse.h */, 278 | 1E4C01881186A47C0092F9AD /* yajl_alloc.c */, 279 | 1E4C01891186A47C0092F9AD /* yajl_alloc.h */, 280 | 1E4C018A1186A47C0092F9AD /* yajl_buf.c */, 281 | 1E4C018B1186A47C0092F9AD /* yajl_buf.h */, 282 | 1E4C018C1186A47C0092F9AD /* yajl_bytestack.h */, 283 | 1E4C018D1186A47C0092F9AD /* yajl_encode.c */, 284 | 1E4C018E1186A47C0092F9AD /* yajl_encode.h */, 285 | 1E4C018F1186A47C0092F9AD /* yajl_gen.c */, 286 | 1E4C01901186A47C0092F9AD /* yajl_lex.c */, 287 | 1E4C01911186A47C0092F9AD /* yajl_lex.h */, 288 | 1E4C01921186A47C0092F9AD /* yajl_parser.c */, 289 | 1E4C01931186A47C0092F9AD /* yajl_parser.h */, 290 | 1E4C01941186A47C0092F9AD /* yajl.c */, 291 | ); 292 | path = yajl; 293 | sourceTree = ""; 294 | }; 295 | 1E4C019E1186A48A0092F9AD /* OAuthConsumer */ = { 296 | isa = PBXGroup; 297 | children = ( 298 | 1E4C019F1186A49C0092F9AD /* Categories */, 299 | 1E4C01A61186A49C0092F9AD /* Crytpo */, 300 | 1E4C01AD1186A49C0092F9AD /* OACall.h */, 301 | 1E4C01AE1186A49C0092F9AD /* OACall.m */, 302 | 1E4C01AF1186A49C0092F9AD /* OAConsumer.h */, 303 | 1E4C01B01186A49C0092F9AD /* OAConsumer.m */, 304 | 1E4C01B11186A49C0092F9AD /* OADataFetcher.h */, 305 | 1E4C01B21186A49C0092F9AD /* OADataFetcher.m */, 306 | 1E4C01B31186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.h */, 307 | 1E4C01B41186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.m */, 308 | 1E4C01B51186A49C0092F9AD /* OAMutableURLRequest.h */, 309 | 1E4C01B61186A49C0092F9AD /* OAMutableURLRequest.m */, 310 | 1E4C01B71186A49C0092F9AD /* OAPlaintextSignatureProvider.h */, 311 | 1E4C01B81186A49C0092F9AD /* OAPlaintextSignatureProvider.m */, 312 | 1E4C01B91186A49C0092F9AD /* OAProblem.h */, 313 | 1E4C01BA1186A49C0092F9AD /* OAProblem.m */, 314 | 1E4C01BB1186A49C0092F9AD /* OARequestParameter.h */, 315 | 1E4C01BC1186A49C0092F9AD /* OARequestParameter.m */, 316 | 1E4C01BD1186A49C0092F9AD /* OAServiceTicket.h */, 317 | 1E4C01BE1186A49C0092F9AD /* OAServiceTicket.m */, 318 | 1E4C01BF1186A49C0092F9AD /* OASignatureProviding.h */, 319 | 1E4C01C11186A49C0092F9AD /* OAToken_KeychainExtensions.h */, 320 | 1E4C01C21186A49C0092F9AD /* OAToken_KeychainExtensions.m */, 321 | 1E4C01C31186A49C0092F9AD /* OAToken.h */, 322 | 1E4C01C41186A49C0092F9AD /* OAToken.m */, 323 | 1E4C01C71186A49C0092F9AD /* OAuthConsumer.h */, 324 | ); 325 | path = OAuthConsumer; 326 | sourceTree = ""; 327 | }; 328 | 1E4C019F1186A49C0092F9AD /* Categories */ = { 329 | isa = PBXGroup; 330 | children = ( 331 | 1E4C01A01186A49C0092F9AD /* NSMutableURLRequest+Parameters.h */, 332 | 1E4C01A11186A49C0092F9AD /* NSMutableURLRequest+Parameters.m */, 333 | 1E4C01A21186A49C0092F9AD /* NSString+URLEncoding.h */, 334 | 1E4C01A31186A49C0092F9AD /* NSString+URLEncoding.m */, 335 | 1E4C01A41186A49C0092F9AD /* NSURL+Base.h */, 336 | 1E4C01A51186A49C0092F9AD /* NSURL+Base.m */, 337 | ); 338 | path = Categories; 339 | sourceTree = ""; 340 | }; 341 | 1E4C01A61186A49C0092F9AD /* Crytpo */ = { 342 | isa = PBXGroup; 343 | children = ( 344 | 1E4C01A71186A49C0092F9AD /* Base64Transcoder.c */, 345 | 1E4C01A81186A49C0092F9AD /* Base64Transcoder.h */, 346 | 1E4C01A91186A49C0092F9AD /* hmac.c */, 347 | 1E4C01AA1186A49C0092F9AD /* hmac.h */, 348 | 1E4C01AB1186A49C0092F9AD /* sha1.c */, 349 | 1E4C01AC1186A49C0092F9AD /* sha1.h */, 350 | ); 351 | path = Crytpo; 352 | sourceTree = ""; 353 | }; 354 | 1E79898F118D06EA00DDD6D9 /* Twitter TouchJSON Parsers */ = { 355 | isa = PBXGroup; 356 | children = ( 357 | 1E79899D118D071E00DDD6D9 /* MGTwitterTouchJSONParser.h */, 358 | 1E79899E118D071E00DDD6D9 /* MGTwitterTouchJSONParser.m */, 359 | ); 360 | name = "Twitter TouchJSON Parsers"; 361 | sourceTree = ""; 362 | }; 363 | 1E7989A5118D077E00DDD6D9 /* TouchJSON */ = { 364 | isa = PBXGroup; 365 | children = ( 366 | 1E7989E5118D077E00DDD6D9 /* Source */, 367 | ); 368 | path = TouchJSON; 369 | sourceTree = ""; 370 | }; 371 | 1E7989E5118D077E00DDD6D9 /* Source */ = { 372 | isa = PBXGroup; 373 | children = ( 374 | 1E7989E6118D077E00DDD6D9 /* CDataScanner.h */, 375 | 1E7989E7118D077E00DDD6D9 /* CDataScanner.m */, 376 | 1E7989E8118D077E00DDD6D9 /* Extensions */, 377 | 1E7989F1118D077E00DDD6D9 /* JSON */, 378 | ); 379 | path = Source; 380 | sourceTree = ""; 381 | }; 382 | 1E7989E8118D077E00DDD6D9 /* Extensions */ = { 383 | isa = PBXGroup; 384 | children = ( 385 | 1E7989E9118D077E00DDD6D9 /* CDataScanner_Extensions.h */, 386 | 1E7989EA118D077E00DDD6D9 /* CDataScanner_Extensions.m */, 387 | 1E7989EB118D077E00DDD6D9 /* NSCharacterSet_Extensions.h */, 388 | 1E7989EC118D077E00DDD6D9 /* NSCharacterSet_Extensions.m */, 389 | 1E7989ED118D077E00DDD6D9 /* NSDictionary_JSONExtensions.h */, 390 | 1E7989EE118D077E00DDD6D9 /* NSDictionary_JSONExtensions.m */, 391 | 1E7989EF118D077E00DDD6D9 /* NSScanner_Extensions.h */, 392 | 1E7989F0118D077E00DDD6D9 /* NSScanner_Extensions.m */, 393 | ); 394 | path = Extensions; 395 | sourceTree = ""; 396 | }; 397 | 1E7989F1118D077E00DDD6D9 /* JSON */ = { 398 | isa = PBXGroup; 399 | children = ( 400 | 1E7989F2118D077E00DDD6D9 /* CJSONDataSerializer.h */, 401 | 1E7989F3118D077E00DDD6D9 /* CJSONDataSerializer.m */, 402 | 1E7989F4118D077E00DDD6D9 /* CJSONDeserializer.h */, 403 | 1E7989F5118D077E00DDD6D9 /* CJSONDeserializer.m */, 404 | 1E7989F6118D077E00DDD6D9 /* CJSONScanner.h */, 405 | 1E7989F7118D077E00DDD6D9 /* CJSONScanner.m */, 406 | 1E7989F8118D077E00DDD6D9 /* CJSONSerializer.h */, 407 | 1E7989F9118D077E00DDD6D9 /* CJSONSerializer.m */, 408 | 1E7989FA118D077E00DDD6D9 /* CSerializedJSONData.h */, 409 | 1E7989FB118D077E00DDD6D9 /* CSerializedJSONData.m */, 410 | ); 411 | path = JSON; 412 | sourceTree = ""; 413 | }; 414 | 29B97314FDCFA39411CA2CEA /* MATwitterIntegration */ = { 415 | isa = PBXGroup; 416 | children = ( 417 | C9F6B4910D6F18290066FC1E /* README.txt */, 418 | C93312570D6EE53E00C76652 /* Source Code License.rtf */, 419 | C90F750D0D6A4CE100F602A5 /* TODO */, 420 | 080E96DDFE201D6D7F000001 /* Classes */, 421 | 29B97315FDCFA39411CA2CEA /* Other Sources */, 422 | 29B97317FDCFA39411CA2CEA /* Resources */, 423 | 29B97323FDCFA39411CA2CEA /* Frameworks */, 424 | 19C28FACFE9D520D11CA2CBB /* Products */, 425 | 1E4C01DF1186A5260092F9AD /* Security.framework */, 426 | ); 427 | name = MATwitterIntegration; 428 | sourceTree = ""; 429 | }; 430 | 29B97315FDCFA39411CA2CEA /* Other Sources */ = { 431 | isa = PBXGroup; 432 | children = ( 433 | 32CA4F630368D1EE00C91783 /* MGTwitterEngine_Prefix.pch */, 434 | 29B97316FDCFA39411CA2CEA /* main.m */, 435 | ); 436 | name = "Other Sources"; 437 | sourceTree = ""; 438 | }; 439 | 29B97317FDCFA39411CA2CEA /* Resources */ = { 440 | isa = PBXGroup; 441 | children = ( 442 | 8D1107310486CEB800E47090 /* Info.plist */, 443 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */, 444 | 29B97318FDCFA39411CA2CEA /* MainMenu.nib */, 445 | ); 446 | name = Resources; 447 | sourceTree = ""; 448 | }; 449 | 29B97323FDCFA39411CA2CEA /* Frameworks */ = { 450 | isa = PBXGroup; 451 | children = ( 452 | 1058C7A0FEA54F0111CA2CBB /* Linked Frameworks */, 453 | 1058C7A2FEA54F0111CA2CBB /* Other Frameworks */, 454 | ); 455 | name = Frameworks; 456 | sourceTree = ""; 457 | }; 458 | 44AEFFD00F213814004F5AE3 /* Twitter YAJL Parsers */ = { 459 | isa = PBXGroup; 460 | children = ( 461 | 44AEFFEF0F2141AB004F5AE3 /* MGTwitterYAJLParser.h */, 462 | 44AEFFF00F2141AB004F5AE3 /* MGTwitterYAJLParser.m */, 463 | 44AEFFEB0F2141AB004F5AE3 /* MGTwitterStatusesYAJLParser.h */, 464 | 44AEFFEC0F2141AB004F5AE3 /* MGTwitterStatusesYAJLParser.m */, 465 | 44AEFFED0F2141AB004F5AE3 /* MGTwitterUsersYAJLParser.h */, 466 | 44AEFFEE0F2141AB004F5AE3 /* MGTwitterUsersYAJLParser.m */, 467 | 44AEFFE70F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.h */, 468 | 44AEFFE80F2141AB004F5AE3 /* MGTwitterMessagesYAJLParser.m */, 469 | 44AEFFE90F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.h */, 470 | 44AEFFEA0F2141AB004F5AE3 /* MGTwitterMiscYAJLParser.m */, 471 | 440E60670F257C1300EF8874 /* MGTwitterSearchYAJLParser.h */, 472 | 440E60660F257C1300EF8874 /* MGTwitterSearchYAJLParser.m */, 473 | ); 474 | name = "Twitter YAJL Parsers"; 475 | sourceTree = ""; 476 | }; 477 | 44F7517D0E47DBF600858A1B /* Twitter LibXML Parsers */ = { 478 | isa = PBXGroup; 479 | children = ( 480 | 44F7518B0E47DDD500858A1B /* MGTwitterLibXMLParser.h */, 481 | 44F7518D0E47DDD500858A1B /* MGTwitterLibXMLParser.m */, 482 | 44F7519A0E47DE4200858A1B /* MGTwitterStatusesLibXMLParser.h */, 483 | 44F7518E0E47DDD500858A1B /* MGTwitterStatusesLibXMLParser.m */, 484 | 44F751A00E47DE9100858A1B /* MGTwitterUsersLibXMLParser.h */, 485 | 44F751890E47DDD500858A1B /* MGTwitterUsersLibXMLParser.m */, 486 | 44F7519F0E47DE9100858A1B /* MGTwitterMessagesLibXMLParser.h */, 487 | 44F7518C0E47DDD500858A1B /* MGTwitterMessagesLibXMLParser.m */, 488 | 44F751880E47DDD500858A1B /* MGTwitterMiscLibXMLParser.h */, 489 | 44F7518A0E47DDD500858A1B /* MGTwitterMiscLibXMLParser.m */, 490 | D47CFCA7115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.h */, 491 | D47CFCA8115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.m */, 492 | ); 493 | name = "Twitter LibXML Parsers"; 494 | sourceTree = ""; 495 | }; 496 | C90F748C0D69FDE000F602A5 /* Categories */ = { 497 | isa = PBXGroup; 498 | children = ( 499 | C9EF989F0D68AB970041A17E /* NSString+UUID.h */, 500 | C9EF98A00D68AB970041A17E /* NSString+UUID.m */, 501 | 44F751A60E47DEC400858A1B /* NSData+Base64.h */, 502 | 44F751A50E47DEC400858A1B /* NSData+Base64.m */, 503 | ); 504 | name = Categories; 505 | sourceTree = ""; 506 | }; 507 | C90F74CB0D6A3B5300F602A5 /* Twitter NSXML Parsers */ = { 508 | isa = PBXGroup; 509 | children = ( 510 | F4763D2811C1837300A35E7E /* MGTwitterUserListsParser.h */, 511 | F4763D2911C1837300A35E7E /* MGTwitterUserListsParser.m */, 512 | C90F74CC0D6A3B7500F602A5 /* MGTwitterXMLParser.h */, 513 | C90F74CD0D6A3B7500F602A5 /* MGTwitterXMLParser.m */, 514 | C9FEB12A0D6095AF009AA322 /* MGTwitterStatusesParser.h */, 515 | C9FEB12B0D6095AF009AA322 /* MGTwitterStatusesParser.m */, 516 | C90031BA0D6B796400C38924 /* MGTwitterUsersParser.h */, 517 | C90031BB0D6B796400C38924 /* MGTwitterUsersParser.m */, 518 | C90031BE0D6B798800C38924 /* MGTwitterMessagesParser.h */, 519 | C90031BF0D6B798800C38924 /* MGTwitterMessagesParser.m */, 520 | C9CB60EA0DF98ED300EE8FCF /* MGTwitterMiscParser.h */, 521 | C9CB60EB0DF98ED300EE8FCF /* MGTwitterMiscParser.m */, 522 | D47CF9B311541D0A00E07931 /* MGTwitterSocialGraphParser.h */, 523 | D47CF9B411541D0A00E07931 /* MGTwitterSocialGraphParser.m */, 524 | ); 525 | name = "Twitter NSXML Parsers"; 526 | sourceTree = ""; 527 | }; 528 | C9FEB1280D609585009AA322 /* Demo */ = { 529 | isa = PBXGroup; 530 | children = ( 531 | C9811E5B0D5F696200720D77 /* AppController.h */, 532 | C9811E5C0D5F696200720D77 /* AppController.m */, 533 | ); 534 | name = Demo; 535 | sourceTree = ""; 536 | }; 537 | C9FEB1290D609598009AA322 /* MATwitterEngine */ = { 538 | isa = PBXGroup; 539 | children = ( 540 | C92F28EE0E4DE7BC00CF98F8 /* MGTwitterEngineGlobalHeader.h */, 541 | C9811E620D5F69B500720D77 /* MGTwitterEngine.h */, 542 | C9811E630D5F69B500720D77 /* MGTwitterEngine.m */, 543 | C9AE94650D6761F800ADEBEC /* MGTwitterEngineDelegate.h */, 544 | C9AE949A0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.h */, 545 | C9AE949B0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.m */, 546 | C9E497610D686B3500C83995 /* MGTwitterRequestTypes.h */, 547 | C90F74E10D6A3FF300F602A5 /* MGTwitterParserDelegate.h */, 548 | 1E79898F118D06EA00DDD6D9 /* Twitter TouchJSON Parsers */, 549 | 44F7517D0E47DBF600858A1B /* Twitter LibXML Parsers */, 550 | C90F74CB0D6A3B5300F602A5 /* Twitter NSXML Parsers */, 551 | 44AEFFD00F213814004F5AE3 /* Twitter YAJL Parsers */, 552 | C90F748C0D69FDE000F602A5 /* Categories */, 553 | ); 554 | name = MATwitterEngine; 555 | sourceTree = ""; 556 | }; 557 | /* End PBXGroup section */ 558 | 559 | /* Begin PBXNativeTarget section */ 560 | 8D1107260486CEB800E47090 /* MGTwitterEngine */ = { 561 | isa = PBXNativeTarget; 562 | buildConfigurationList = C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "MGTwitterEngine" */; 563 | buildPhases = ( 564 | 8D1107290486CEB800E47090 /* Resources */, 565 | 8D11072C0486CEB800E47090 /* Sources */, 566 | 8D11072E0486CEB800E47090 /* Frameworks */, 567 | ); 568 | buildRules = ( 569 | ); 570 | dependencies = ( 571 | ); 572 | name = MGTwitterEngine; 573 | productInstallPath = "$(HOME)/Applications"; 574 | productName = MATwitterIntegration; 575 | productReference = 8D1107320486CEB800E47090 /* MGTwitterEngine.app */; 576 | productType = "com.apple.product-type.application"; 577 | }; 578 | /* End PBXNativeTarget section */ 579 | 580 | /* Begin PBXProject section */ 581 | 29B97313FDCFA39411CA2CEA /* Project object */ = { 582 | isa = PBXProject; 583 | buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MGTwitterEngine" */; 584 | compatibilityVersion = "Xcode 3.0"; 585 | hasScannedForEncodings = 1; 586 | mainGroup = 29B97314FDCFA39411CA2CEA /* MATwitterIntegration */; 587 | projectDirPath = ""; 588 | projectRoot = ""; 589 | targets = ( 590 | 8D1107260486CEB800E47090 /* MGTwitterEngine */, 591 | ); 592 | }; 593 | /* End PBXProject section */ 594 | 595 | /* Begin PBXResourcesBuildPhase section */ 596 | 8D1107290486CEB800E47090 /* Resources */ = { 597 | isa = PBXResourcesBuildPhase; 598 | buildActionMask = 2147483647; 599 | files = ( 600 | 8D11072A0486CEB800E47090 /* MainMenu.nib in Resources */, 601 | 8D11072B0486CEB800E47090 /* InfoPlist.strings in Resources */, 602 | ); 603 | runOnlyForDeploymentPostprocessing = 0; 604 | }; 605 | /* End PBXResourcesBuildPhase section */ 606 | 607 | /* Begin PBXSourcesBuildPhase section */ 608 | 8D11072C0486CEB800E47090 /* Sources */ = { 609 | isa = PBXSourcesBuildPhase; 610 | buildActionMask = 2147483647; 611 | files = ( 612 | 1E4C01691186A3780092F9AD /* MGTwitterMiscYAJLParser.m in Sources */, 613 | 1E4C016A1186A3780092F9AD /* MGTwitterStatusesYAJLParser.m in Sources */, 614 | 1E4C016B1186A3780092F9AD /* MGTwitterMessagesYAJLParser.m in Sources */, 615 | 1E4C016C1186A3780092F9AD /* MGTwitterYAJLParser.m in Sources */, 616 | 1E4C016D1186A3780092F9AD /* MGTwitterUsersYAJLParser.m in Sources */, 617 | 1E4C016E1186A3780092F9AD /* MGTwitterSearchYAJLParser.m in Sources */, 618 | 8D11072D0486CEB800E47090 /* main.m in Sources */, 619 | C9811E5D0D5F696200720D77 /* AppController.m in Sources */, 620 | C9811E640D5F69B500720D77 /* MGTwitterEngine.m in Sources */, 621 | C9FEB12C0D6095AF009AA322 /* MGTwitterStatusesParser.m in Sources */, 622 | C9AE949C0D678D4400ADEBEC /* MGTwitterHTTPURLConnection.m in Sources */, 623 | C9EF98A10D68AB970041A17E /* NSString+UUID.m in Sources */, 624 | C90F74CE0D6A3B7500F602A5 /* MGTwitterXMLParser.m in Sources */, 625 | C90031BC0D6B796400C38924 /* MGTwitterUsersParser.m in Sources */, 626 | C90031C00D6B798800C38924 /* MGTwitterMessagesParser.m in Sources */, 627 | C9CB60EC0DF98ED300EE8FCF /* MGTwitterMiscParser.m in Sources */, 628 | 44F7518F0E47DDD500858A1B /* MGTwitterUsersLibXMLParser.m in Sources */, 629 | 44F751900E47DDD500858A1B /* MGTwitterMiscLibXMLParser.m in Sources */, 630 | 44F751910E47DDD500858A1B /* MGTwitterMessagesLibXMLParser.m in Sources */, 631 | 44F751920E47DDD500858A1B /* MGTwitterLibXMLParser.m in Sources */, 632 | 44F751930E47DDD500858A1B /* MGTwitterStatusesLibXMLParser.m in Sources */, 633 | 44F751A70E47DEC400858A1B /* NSData+Base64.m in Sources */, 634 | D47CF9B511541D0A00E07931 /* MGTwitterSocialGraphParser.m in Sources */, 635 | D47CFCA9115567ED00E07931 /* MGTwitterSocialGraphLibXMLParser.m in Sources */, 636 | 1E4C01951186A47C0092F9AD /* yajl_alloc.c in Sources */, 637 | 1E4C01961186A47C0092F9AD /* yajl_buf.c in Sources */, 638 | 1E4C01971186A47C0092F9AD /* yajl_encode.c in Sources */, 639 | 1E4C01981186A47C0092F9AD /* yajl_gen.c in Sources */, 640 | 1E4C01991186A47C0092F9AD /* yajl_lex.c in Sources */, 641 | 1E4C019A1186A47C0092F9AD /* yajl_parser.c in Sources */, 642 | 1E4C019B1186A47C0092F9AD /* yajl.c in Sources */, 643 | 1E4C01C81186A49C0092F9AD /* NSMutableURLRequest+Parameters.m in Sources */, 644 | 1E4C01C91186A49C0092F9AD /* NSString+URLEncoding.m in Sources */, 645 | 1E4C01CA1186A49C0092F9AD /* NSURL+Base.m in Sources */, 646 | 1E4C01CB1186A49C0092F9AD /* Base64Transcoder.c in Sources */, 647 | 1E4C01CC1186A49C0092F9AD /* hmac.c in Sources */, 648 | 1E4C01CD1186A49C0092F9AD /* sha1.c in Sources */, 649 | 1E4C01CE1186A49C0092F9AD /* OACall.m in Sources */, 650 | 1E4C01CF1186A49C0092F9AD /* OAConsumer.m in Sources */, 651 | 1E4C01D01186A49C0092F9AD /* OADataFetcher.m in Sources */, 652 | 1E4C01D11186A49C0092F9AD /* OAHMAC_SHA1SignatureProvider.m in Sources */, 653 | 1E4C01D21186A49C0092F9AD /* OAMutableURLRequest.m in Sources */, 654 | 1E4C01D31186A49C0092F9AD /* OAPlaintextSignatureProvider.m in Sources */, 655 | 1E4C01D41186A49C0092F9AD /* OAProblem.m in Sources */, 656 | 1E4C01D51186A49C0092F9AD /* OARequestParameter.m in Sources */, 657 | 1E4C01D61186A49C0092F9AD /* OAServiceTicket.m in Sources */, 658 | 1E4C01D81186A49C0092F9AD /* OAToken_KeychainExtensions.m in Sources */, 659 | 1E4C01D91186A49C0092F9AD /* OAToken.m in Sources */, 660 | 1E79899F118D071E00DDD6D9 /* MGTwitterTouchJSONParser.m in Sources */, 661 | 1E798A66118D077E00DDD6D9 /* CDataScanner.m in Sources */, 662 | 1E798A67118D077E00DDD6D9 /* CDataScanner_Extensions.m in Sources */, 663 | 1E798A68118D077E00DDD6D9 /* NSCharacterSet_Extensions.m in Sources */, 664 | 1E798A69118D077E00DDD6D9 /* NSDictionary_JSONExtensions.m in Sources */, 665 | 1E798A6A118D077E00DDD6D9 /* NSScanner_Extensions.m in Sources */, 666 | 1E798A6B118D077E00DDD6D9 /* CJSONDataSerializer.m in Sources */, 667 | 1E798A6C118D077E00DDD6D9 /* CJSONDeserializer.m in Sources */, 668 | 1E798A6D118D077E00DDD6D9 /* CJSONScanner.m in Sources */, 669 | 1E798A6E118D077E00DDD6D9 /* CJSONSerializer.m in Sources */, 670 | 1E798A6F118D077E00DDD6D9 /* CSerializedJSONData.m in Sources */, 671 | F4763D2A11C1837300A35E7E /* MGTwitterUserListsParser.m in Sources */, 672 | ); 673 | runOnlyForDeploymentPostprocessing = 0; 674 | }; 675 | /* End PBXSourcesBuildPhase section */ 676 | 677 | /* Begin PBXVariantGroup section */ 678 | 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */ = { 679 | isa = PBXVariantGroup; 680 | children = ( 681 | 089C165DFE840E0CC02AAC07 /* English */, 682 | ); 683 | name = InfoPlist.strings; 684 | sourceTree = ""; 685 | }; 686 | 29B97318FDCFA39411CA2CEA /* MainMenu.nib */ = { 687 | isa = PBXVariantGroup; 688 | children = ( 689 | 29B97319FDCFA39411CA2CEA /* English */, 690 | ); 691 | name = MainMenu.nib; 692 | sourceTree = ""; 693 | }; 694 | /* End PBXVariantGroup section */ 695 | 696 | /* Begin XCBuildConfiguration section */ 697 | C01FCF4B08A954540054247B /* Debug */ = { 698 | isa = XCBuildConfiguration; 699 | buildSettings = { 700 | ARCHS = "$(ONLY_ACTIVE_ARCH_PRE_XCODE_3_1)"; 701 | COPY_PHASE_STRIP = NO; 702 | GCC_DYNAMIC_NO_PIC = NO; 703 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 704 | GCC_MODEL_TUNING = G5; 705 | GCC_OPTIMIZATION_LEVEL = 0; 706 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 707 | GCC_PREFIX_HEADER = MGTwitterEngine_Prefix.pch; 708 | HEADER_SEARCH_PATHS = ( 709 | /usr/include/libxml2, 710 | "\"$(SRCROOT)/yajl/build/yajl-1.0.7/include/yajl\"", 711 | ); 712 | INFOPLIST_FILE = Info.plist; 713 | INSTALL_PATH = "$(HOME)/Applications"; 714 | LIBRARY_SEARCH_PATHS = ( 715 | "$(inherited)", 716 | "\"$(SRCROOT)/yajl/build/yajl-1.0.7/lib\"", 717 | "\"$(SRCROOT)\"", 718 | ); 719 | ONLY_ACTIVE_ARCH_PRE_XCODE_3_1 = "$(NATIVE_ARCH_ACTUAL)"; 720 | PRODUCT_NAME = MGTwitterEngine; 721 | WRAPPER_EXTENSION = app; 722 | ZERO_LINK = YES; 723 | }; 724 | name = Debug; 725 | }; 726 | C01FCF4C08A954540054247B /* Release */ = { 727 | isa = XCBuildConfiguration; 728 | buildSettings = { 729 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 730 | GCC_MODEL_TUNING = G5; 731 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 732 | GCC_PREFIX_HEADER = MGTwitterEngine_Prefix.pch; 733 | HEADER_SEARCH_PATHS = ( 734 | /usr/include/libxml2, 735 | "\"$(SRCROOT)/yajl/build/yajl-1.0.7/include/yajl\"", 736 | ); 737 | INFOPLIST_FILE = Info.plist; 738 | INSTALL_PATH = "$(HOME)/Applications"; 739 | LIBRARY_SEARCH_PATHS = ( 740 | "$(inherited)", 741 | "\"$(SRCROOT)/yajl/build/yajl-1.0.7/lib\"", 742 | "\"$(SRCROOT)\"", 743 | ); 744 | PRODUCT_NAME = MGTwitterEngine; 745 | WRAPPER_EXTENSION = app; 746 | }; 747 | name = Release; 748 | }; 749 | C01FCF4F08A954540054247B /* Debug */ = { 750 | isa = XCBuildConfiguration; 751 | buildSettings = { 752 | ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; 753 | ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; 754 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 755 | GCC_WARN_UNUSED_VARIABLE = YES; 756 | HEADER_SEARCH_PATHS = /usr/include/libxml2; 757 | OTHER_CFLAGS = "-DDEBUG"; 758 | PREBINDING = NO; 759 | SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; 760 | }; 761 | name = Debug; 762 | }; 763 | C01FCF5008A954540054247B /* Release */ = { 764 | isa = XCBuildConfiguration; 765 | buildSettings = { 766 | ARCHS = "$(ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1)"; 767 | ARCHS_STANDARD_32_BIT_PRE_XCODE_3_1 = "ppc i386"; 768 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 769 | GCC_WARN_UNUSED_VARIABLE = YES; 770 | HEADER_SEARCH_PATHS = /usr/include/libxml2; 771 | PREBINDING = NO; 772 | SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk"; 773 | }; 774 | name = Release; 775 | }; 776 | /* End XCBuildConfiguration section */ 777 | 778 | /* Begin XCConfigurationList section */ 779 | C01FCF4A08A954540054247B /* Build configuration list for PBXNativeTarget "MGTwitterEngine" */ = { 780 | isa = XCConfigurationList; 781 | buildConfigurations = ( 782 | C01FCF4B08A954540054247B /* Debug */, 783 | C01FCF4C08A954540054247B /* Release */, 784 | ); 785 | defaultConfigurationIsVisible = 0; 786 | defaultConfigurationName = Release; 787 | }; 788 | C01FCF4E08A954540054247B /* Build configuration list for PBXProject "MGTwitterEngine" */ = { 789 | isa = XCConfigurationList; 790 | buildConfigurations = ( 791 | C01FCF4F08A954540054247B /* Debug */, 792 | C01FCF5008A954540054247B /* Release */, 793 | ); 794 | defaultConfigurationIsVisible = 0; 795 | defaultConfigurationName = Release; 796 | }; 797 | /* End XCConfigurationList section */ 798 | }; 799 | rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; 800 | } 801 | --------------------------------------------------------------------------------