1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242 |
- //
- // FHSTwitterEngine.m
- // FHSTwitterEngine
- //
- // Created by Nathaniel Symer on 8/22/12.
- // Copyright (C) 2012 Nathaniel Symer.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- #import "FHSTwitterEngine.h"
- #import "OAuthConsumer.h"
- #import <QuartzCore/QuartzCore.h>
- #import <SystemConfiguration/SystemConfiguration.h>
- #import <sys/socket.h>
- #import <netinet/in.h>
- #import <ifaddrs.h>
- #import <objc/runtime.h>
- NSString * const FHSProfileBackgroundColorKey = @"profile_background_color";
- NSString * const FHSProfileLinkColorKey = @"profile_link_color";
- NSString * const FHSProfileSidebarBorderColorKey = @"profile_sidebar_border_color";
- NSString * const FHSProfileSidebarFillColorKey = @"profile_sidebar_fill_color";
- NSString * const FHSProfileTextColorKey = @"profile_text_color";
- NSString * const FHSProfileNameKey = @"name";
- NSString * const FHSProfileURLKey = @"url";
- NSString * const FHSProfileLocationKey = @"location";
- NSString * const FHSProfileDescriptionKey = @"description";
- static NSString * const errorFourhundred = @"Bad Request: The request you are trying to make has missing or bad parameters.";
- static NSString * const authBlockKey = @"FHSTwitterEngineOAuthCompletion";
- static FHSTwitterEngine *sharedInstance = nil;
- id removeNull(id rootObject) {
- if ([rootObject isKindOfClass:[NSDictionary class]]) {
- NSMutableDictionary *sanitizedDictionary = [NSMutableDictionary dictionaryWithDictionary:rootObject];
- [rootObject enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
- id sanitized = removeNull(obj);
- if (!sanitized) {
- [sanitizedDictionary setObject:@"" forKey:key];
- } else {
- [sanitizedDictionary setObject:sanitized forKey:key];
- }
- }];
- return [NSMutableDictionary dictionaryWithDictionary:sanitizedDictionary];
- }
-
- if ([rootObject isKindOfClass:[NSArray class]]) {
- NSMutableArray *sanitizedArray = [NSMutableArray arrayWithArray:rootObject];
- [rootObject enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
- id sanitized = removeNull(obj);
- if (!sanitized) {
- [sanitizedArray replaceObjectAtIndex:[sanitizedArray indexOfObject:obj] withObject:@""];
- } else {
- [sanitizedArray replaceObjectAtIndex:[sanitizedArray indexOfObject:obj] withObject:sanitized];
- }
- }];
- return [NSMutableArray arrayWithArray:sanitizedArray];
- }
- if ([rootObject isKindOfClass:[NSNull class]]) {
- return (id)nil;
- } else {
- return rootObject;
- }
- }
- NSError * getBadRequestError() {
- return [NSError errorWithDomain:errorFourhundred code:400 userInfo:nil];
- }
- NSError * getNilReturnLengthError() {
- return [NSError errorWithDomain:@"Twitter successfully processed the request, but did not return any content" code:204 userInfo:nil];
- }
- @interface FHSTwitterEngineController : UIViewController <UIWebViewDelegate>
- @property (nonatomic, retain) UINavigationBar *navBar;
- @property (nonatomic, retain) UIView *blockerView;
- @property (nonatomic, retain) UIToolbar *pinCopyBar;
- //@property (nonatomic, retain) FHSTwitterEngine *engine;
- @property (nonatomic, retain) UIWebView *theWebView;
- @property (nonatomic, retain) OAToken *requestToken;
- //- (id)initWithEngine:(FHSTwitterEngine *)theEngine;
- - (NSString *)locatePin;
- - (void)showPinCopyPrompt;
- @end
- @interface FHSTwitterEngine()
- // Login stuff
- - (NSString *)getRequestTokenString;
- // General Get request sender
- - (id)sendRequest:(NSURLRequest *)request;
- // These are here to obfuscate them from prying eyes
- @property (retain, nonatomic) OAConsumer *consumer;
- @property (assign, nonatomic) BOOL shouldClearConsumer;
- @property (retain, nonatomic) NSDateFormatter *dateFormatter;
- @end
- @implementation NSString (FHSTwitterEngine)
- - (NSString *)fhs_trimForTwitter {
- NSString *string = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
- return (string.length > 140)?[string substringToIndex:140]:string;
- }
- - (NSString *)fhs_stringWithRange:(NSRange)range {
- return [[self substringFromIndex:range.location]substringToIndex:range.length];
- }
- - (BOOL)fhs_isNumeric {
- const char *raw = (const char *)[self UTF8String];
-
- for (int i = 0; i < strlen(raw); i++) {
- if (raw[i] < '0' || raw[i] > '9') {
- return NO;
- }
- }
- return YES;
- }
- @end
- @implementation FHSTwitterEngine
- static NSString * const url_search_tweets = @"https://api.twitter.com/1.1/search/tweets.json";
- static NSString * const url_users_search = @"https://api.twitter.com/1.1/users/search.json";
- static NSString * const url_users_show = @"https://api.twitter.com/1.1/users/show.json";
- static NSString * const url_users_report_spam = @"https://api.twitter.com/1.1/users/report_spam.json";
- static NSString * const url_users_lookup = @"https://api.twitter.com/1.1/users/lookup.json";
- static NSString * const url_lists_create = @"https://api.twitter.com/1.1/lists/create.json";
- static NSString * const url_lists_show = @"https://api.twitter.com/1.1/lists/show.json";
- static NSString * const url_lists_update = @"https://api.twitter.com/1.1/lists/update.json";
- static NSString * const url_lists_members = @"https://api.twitter.com/1.1/lists/members.json";
- static NSString * const url_lists_members_destroy_all = @"https://api.twitter.com/1.1/lists/members/destroy_all.json";
- static NSString * const url_lists_members_create_all = @"https://api.twitter.com/1.1/lists/members/create_all.json";
- static NSString * const url_lists_statuses = @"https://api.twitter.com/1.1/lists/statuses.json";
- static NSString * const url_lists_list = @"https://api.twitter.com/1.1/lists/list.json";
- static NSString * const url_statuses_home_timeline = @"https://api.twitter.com/1.1/statuses/home_timeline.json";
- static NSString * const url_statuses_update = @"https://api.twitter.com/1.1/statuses/update.json";
- static NSString * const url_statuses_retweets_of_me = @"https://api.twitter.com/1.1/statuses/retweets_of_me.json";
- static NSString * const url_statuses_user_timeline = @"https://api.twitter.com/1.1/statuses/user_timeline.json";
- static NSString * const url_statuses_metions_timeline = @"https://api.twitter.com/1.1/statuses/mentions_timeline.json";
- static NSString * const url_statuses_update_with_media = @"https://api.twitter.com/1.1/statuses/update_with_media.json";
- static NSString * const url_statuses_destroy = @"https://api.twitter.com/1.1/statuses/destroy.json";
- static NSString * const url_statuses_show = @"https://api.twitter.com/1.1/statuses/show.json";
- static NSString * const url_statuses_oembed = @"https://api.twitter.com/1.1/statuses/oembed.json";
- static NSString * const url_blocks_exists = @"https://api.twitter.com/1.1/blocks/exists.json";
- static NSString * const url_blocks_blocking = @"https://api.twitter.com/1.1/blocks/blocking.json";
- static NSString * const url_blocks_blocking_ids = @"https://api.twitter.com/1.1/blocks/blocking/ids.json";
- static NSString * const url_blocks_destroy = @"https://api.twitter.com/1.1/blocks/destroy.json";
- static NSString * const url_blocks_create = @"https://api.twitter.com/1.1/blocks/create.json";
- static NSString * const url_help_languages = @"https://api.twitter.com/1.1/help/languages.json";
- static NSString * const url_help_configuration = @"https://api.twitter.com/1.1/help/configuration.json";
- static NSString * const url_help_privacy = @"https://api.twitter.com/1.1/help/privacy.json";
- static NSString * const url_help_tos = @"https://api.twitter.com/1.1/help/tos.json";
- static NSString * const url_help_test = @"https://api.twitter.com/1.1/help/test.json";
- static NSString * const url_direct_messages_show = @"https://api.twitter.com/1.1/direct_messages/show.json";
- static NSString * const url_direct_messages_new = @"https://api.twitter.com/1.1/direct_messages/new.json";
- static NSString * const url_direct_messages_sent = @"https://api.twitter.com/1.1/direct_messages/sent.json";
- static NSString * const url_direct_messages_destroy = @"https://api.twitter.com/1.1/direct_messages/destroy.json";
- static NSString * const url_direct_messages = @"https://api.twitter.com/1.1/direct_messages.json";
- static NSString * const url_friendships_no_retweets_ids = @"https://api.twitter.com/1.1/friendships/no_retweets/ids.json";
- static NSString * const url_friendships_update = @"https://api.twitter.com/1.1/friendships/update.json";
- static NSString * const url_friendships_outgoing = @"https://api.twitter.com/1.1/friendships/outgoing.json";
- static NSString * const url_friendships_incoming = @"https://api.twitter.com/1.1/friendships/incoming.json";
- static NSString * const url_friendships_lookup = @"https://api.twitter.com/1.1/friendships/lookup.json";
- static NSString * const url_friendships_destroy = @"https://api.twitter.com/1.1/friendships/destroy.json";
- static NSString * const url_friendships_create = @"https://api.twitter.com/1.1/friendships/create.json";
- static NSString * const url_account_verify_credentials = @"https://api.twitter.com/1.1/account/verify_credentials.json";
- static NSString * const url_account_update_profile_colors = @"https://api.twitter.com/1.1/account/update_profile_colors.json";
- static NSString * const url_account_update_profile_background_image = @"https://api.twitter.com/1.1/account/update_profile_background_image.json";
- static NSString * const url_account_update_profile_image = @"https://api.twitter.com/1.1/account/update_profile_image.json";
- static NSString * const url_account_settings = @"https://api.twitter.com/1.1/account/settings.json";
- static NSString * const url_account_update_profile = @"https://api.twitter.com/1.1/account/update_profile.json";
- static NSString * const url_favorites_list = @"https://api.twitter.com/1.1/favorites/list.json";
- static NSString * const url_favorites_create = @"https://api.twitter.com/1.1/favorites/create.json";
- static NSString * const url_favorites_destroy = @"https://api.twitter.com/1.1/favorites/destroy.json";
- static NSString * const url_application_rate_limit_status = @"https://api.twitter.com/1.1/application/rate_limit_status.json";
- static NSString * const url_followers_ids = @"https://api.twitter.com/1.1/followers/ids.json";
- static NSString * const url_followers_list = @"https://api.twitter.com/1.1/followers/list.json";
- static NSString * const url_friends_ids = @"https://api.twitter.com/1.1/friends/ids.json";
- static NSString * const url_friends_list = @"https://api.twitter.com/1.1/friends/list.json";
- - (id)listFollowersForUser:(NSString *)user isID:(BOOL)isID withCursor:(NSString *)cursor {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_friends_list];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipstatusP = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- OARequestParameter *include_entitiesP = [OARequestParameter requestParameterWithName:@"include_entities" value:self.includeEntities?@"true":@"false"];
- OARequestParameter *screen_nameP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- OARequestParameter *cursorP = [OARequestParameter requestParameterWithName:@"cursor" value:cursor];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:include_entitiesP, skipstatusP, screen_nameP, cursorP, nil]];
- }
- - (id)listFriendsForUser:(NSString *)user isID:(BOOL)isID withCursor:(NSString *)cursor {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_friends_list];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipstatusP = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- OARequestParameter *include_entitiesP = [OARequestParameter requestParameterWithName:@"include_entities" value:self.includeEntities?@"true":@"false"];
- OARequestParameter *screen_nameP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- OARequestParameter *cursorP = [OARequestParameter requestParameterWithName:@"cursor" value:cursor];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:include_entitiesP, skipstatusP, screen_nameP, cursorP, nil]];
- }
- - (id)searchUsersWithQuery:(NSString *)q andCount:(int)count {
-
- if (count == 0) {
- return nil;
- }
-
- if (q.length == 0) {
- return getBadRequestError();
- }
-
- if (q.length > 1000) {
- q = [q substringToIndex:1000];
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_users_search];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *include_entitiesP = [OARequestParameter requestParameterWithName:@"include_entities" value:self.includeEntities?@"true":@"false"];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *qP = [OARequestParameter requestParameterWithName:@"q" value:q];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:include_entitiesP, countP, qP, nil]];
- }
- - (id)searchTweetsWithQuery:(NSString *)q count:(int)count resultType:(FHSTwitterEngineResultType)resultType unil:(NSDate *)untilDate sinceID:(NSString *)sinceID maxID:(NSString *)maxID {
-
- if (count == 0) {
- return nil;
- }
-
- if (q.length == 0) {
- return getBadRequestError();
- }
-
- if (q.length > 1000) {
- q = [q substringToIndex:1000];
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_search_tweets];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *include_entitiesP = [OARequestParameter requestParameterWithName:@"include_entities" value:self.includeEntities?@"true":@"false"];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *untilP = [OARequestParameter requestParameterWithName:@"until" value:nil];
- OARequestParameter *result_typeP = [OARequestParameter requestParameterWithName:@"result_type" value:nil];
- OARequestParameter *qP = [OARequestParameter requestParameterWithName:@"q" value:q];
-
- [self.dateFormatter setDateFormat:@"YYYY-MM-DD"];
- NSString *untilString = [self.dateFormatter stringFromDate:untilDate];
- [self.dateFormatter setDateFormat:@"EEE MMM dd HH:mm:ss ZZZZ yyyy"];
-
- untilP.value = untilString;
- if (resultType == FHSTwitterEngineResultTypeMixed) {
- result_typeP.value = @"mixed";
- } else if (resultType == FHSTwitterEngineResultTypeRecent) {
- result_typeP.value = @"recent";
- } else if (resultType == FHSTwitterEngineResultTypePopular) {
- result_typeP.value = @"popular";
- }
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:countP, include_entitiesP, qP, nil];
-
- if (maxID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"max_id" value:maxID]];
- }
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (NSError *)createListWithName:(NSString *)name isPrivate:(BOOL)isPrivate description:(NSString *)description {
-
- if (name.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_create];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *nameP = [OARequestParameter requestParameterWithName:@"name" value:name];
- OARequestParameter *isPrivateP = [OARequestParameter requestParameterWithName:@"mode" value:isPrivate?@"private":@"public"];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:nameP, isPrivateP, nil];
-
- if (description.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"description" value:description]];
- }
-
- return [self sendPOSTRequest:request withParameters:params];
- }
- - (id)getListWithID:(NSString *)listID {
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_show];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *listIDP = [OARequestParameter requestParameterWithName:@"list_id" value:listID];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:listIDP, nil]];
- }
- - (NSError *)changeDescriptionOfListWithID:(NSString *)listID toDescription:(NSString *)newName {
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- if (newName.length == 0 ) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_update];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *listIDP = [OARequestParameter requestParameterWithName:@"list_id" value:listID];
- OARequestParameter *nameP = [OARequestParameter requestParameterWithName:@"description" value:newName];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:listIDP, nameP, nil]];
- }
- - (NSError *)changeNameOfListWithID:(NSString *)listID toName:(NSString *)newName {
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- if (newName.length == 0 ) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_update];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *listIDP = [OARequestParameter requestParameterWithName:@"list_id" value:listID];
- OARequestParameter *nameP = [OARequestParameter requestParameterWithName:@"name" value:newName];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:listIDP, nameP, nil]];
- }
- - (NSError *)setModeOfListWithID:(NSString *)listID toPrivate:(BOOL)isPrivate {
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_update];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *listIDP = [OARequestParameter requestParameterWithName:@"list_id" value:listID];
- OARequestParameter *isPrivateP = [OARequestParameter requestParameterWithName:@"mode" value:isPrivate?@"private":@"public"];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:listIDP, isPrivateP, nil]];
- }
- - (id)listUsersInListWithID:(NSString *)listID {
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_members];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *listIDP = [OARequestParameter requestParameterWithName:@"list_id" value:listID];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:listIDP, nil]];
- }
- - (NSError *)removeUsersFromListWithID:(NSString *)listID users:(NSArray *)users {
-
- if (users.count == 0) {
- return getBadRequestError();
- }
-
- if (users.count > 100) {
- return getBadRequestError();
- }
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_members_destroy_all];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *screen_name = [OARequestParameter requestParameterWithName:@"screen_name" value:[users componentsJoinedByString:@","]];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:screen_name, nil]];
- }
- - (NSError *)addUsersToListWithID:(NSString *)listID users:(NSArray *)users {
-
- if (users.count == 0) {
- return getBadRequestError();
- }
-
- if (users.count > 100) {
- return getBadRequestError();
- }
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_members_create_all];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *screen_name = [OARequestParameter requestParameterWithName:@"screen_name" value:[users componentsJoinedByString:@","]];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:screen_name, nil]];
- }
- - (id)getTimelineForListWithID:(NSString *)listID count:(int)count {
- return [self getTimelineForListWithID:listID count:count sinceID:nil maxID:nil];
- }
- - (id)getTimelineForListWithID:(NSString *)listID count:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID {
- return [self getTimelineForListWithID:listID count:count sinceID:sinceID maxID:maxID excludeRetweets:YES excludeReplies:YES];
- }
- - (id)getTimelineForListWithID:(NSString *)listID count:(int)count excludeRetweets:(BOOL)excludeRetweets excludeReplies:(BOOL)excludeReplies {
- return [self getTimelineForListWithID:listID count:count sinceID:nil maxID:nil excludeRetweets:excludeRetweets excludeReplies:excludeReplies];
- }
- - (id)getTimelineForListWithID:(NSString *)listID count:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID excludeRetweets:(BOOL)excludeRetweets excludeReplies:(BOOL)excludeReplies {
-
- if (count == 0) {
- return nil;
- }
-
- if (listID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_statuses];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *excludeRepliesP = [OARequestParameter requestParameterWithName:@"exclude_replies" value:excludeReplies?@"true":@"false"];
- OARequestParameter *includeRTsP = [OARequestParameter requestParameterWithName:@"include_rts" value:excludeRetweets?@"false":@"true"];
- OARequestParameter *listIDP = [OARequestParameter requestParameterWithName:@"list_id" value:listID];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:countP, excludeRepliesP, includeRTsP, listIDP, nil];
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- if (maxID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"max_id" value:maxID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (id)getListsForUser:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_lists_list];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:userP, nil]];
- }
- - (id)getRetweetsForTweet:(NSString *)identifier count:(int)count {
-
- if (count == 0) {
- return nil;
- }
-
- if (identifier.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.twitter.com/1.1/statuses/retweets/%@.json",identifier]];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *identifierP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:identifierP, nil]];
- }
- - (id)getRetweetedTimelineWithCount:(int)count {
- return [self getRetweetedTimelineWithCount:count sinceID:nil maxID:nil];
- }
- - (id)getRetweetedTimelineWithCount:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID {
-
- if (count == 0) {
- return nil;
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_retweets_of_me];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *excludeRepliesP = [OARequestParameter requestParameterWithName:@"exclude_replies" value:@"false"];
- OARequestParameter *includeRTsP = [OARequestParameter requestParameterWithName:@"include_rts" value:@"true"];
-
- NSMutableArray *params = [NSMutableArray array];
- [params addObject:countP];
- [params addObject:excludeRepliesP];
- [params addObject:includeRTsP];
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- if (maxID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"max_id" value:maxID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (id)getMentionsTimelineWithCount:(int)count {
- return [self getMentionsTimelineWithCount:count sinceID:nil maxID:nil];
- }
- - (id)getMentionsTimelineWithCount:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID {
-
- if (count == 0) {
- return nil;
- }
- NSURL *baseURL = [NSURL URLWithString:url_statuses_metions_timeline];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *excludeRepliesP = [OARequestParameter requestParameterWithName:@"exclude_replies" value:@"false"];
- OARequestParameter *includeRTsP = [OARequestParameter requestParameterWithName:@"include_rts" value:@"true"];
- NSMutableArray *params = [NSMutableArray array];
- [params addObject:countP];
- [params addObject:excludeRepliesP];
- [params addObject:includeRTsP];
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- if (maxID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"max_id" value:maxID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (NSError *)postTweet:(NSString *)tweetString withImageData:(NSData *)theData {
- return [self postTweet:tweetString withImageData:theData inReplyTo:nil];
- }
- - (NSError *)postTweet:(NSString *)tweetString withImageData:(NSData *)theData inReplyTo:(NSString *)irt {
-
- if (tweetString.length == 0) {
- return getBadRequestError();
- }
-
- if (theData.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_update_with_media];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *statusP = [OARequestParameter requestParameterWithName:@"status" value:tweetString];
- OARequestParameter *mediaP = [OARequestParameter requestParameterWithName:@"media_data[]" value:[theData base64EncodingWithLineLength:0]];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:statusP, mediaP, nil];
-
- if (irt.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"in_reply_to_status_id" value:irt]];
- }
-
- return [self sendPOSTRequest:request withParameters:params];
- }
- - (NSError *)destroyTweet:(NSString *)identifier {
-
- if (identifier.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_destroy];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *identifierP = [OARequestParameter requestParameterWithName:@"id" value:identifier];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:identifierP, nil]];
- }
- - (id)getDetailsForTweet:(NSString *)identifier {
-
- if (identifier.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_show];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *identifierP = [OARequestParameter requestParameterWithName:@"id" value:identifier];
- OARequestParameter *includeMyRetweet = [OARequestParameter requestParameterWithName:@"include_my_retweet" value:@"true"];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:includeMyRetweet, identifierP, nil]];
- }
- - (id)oembedTweet:(NSString *)identifier maxWidth:(float)maxWidth alignmentMode:(FHSTwitterEngineAlignMode)alignmentMode {
-
- if (identifier.length == 0) {
- return getBadRequestError();
- }
-
- NSString *language = [[NSLocale preferredLanguages]objectAtIndex:0];
- NSString *alignment = [[NSArray arrayWithObjects:@"left", @"right", @"center", @"none", nil]objectAtIndex:alignmentMode];
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_oembed];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *identifierP = [OARequestParameter requestParameterWithName:@"id" value:identifier];
- OARequestParameter *maxWidthP = [OARequestParameter requestParameterWithName:@"maxwidth" value:[NSString stringWithFormat:@"%f",maxWidth]];
- OARequestParameter *languageP= [OARequestParameter requestParameterWithName:@"lang" value:language];
- OARequestParameter *alignmentP = [OARequestParameter requestParameterWithName:@"align" value:alignment];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:identifierP, maxWidthP, languageP,alignmentP, nil]];
- }
- - (NSError *)retweet:(NSString *)identifier {
-
- if (identifier.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:@"https://api.twitter.com/1.1/statuses/retweet/%@.json",identifier]];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- return [self sendPOSTRequest:request withParameters:nil];
- }
- - (id)getTimelineForUser:(NSString *)user isID:(BOOL)isID count:(int)count {
- return [self getTimelineForUser:user isID:isID count:count sinceID:nil maxID:nil];
- }
- - (id)getTimelineForUser:(NSString *)user isID:(BOOL)isID count:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID {
-
- if (count == 0) {
- return nil;
- }
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_user_timeline];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- OARequestParameter *excludeRepliesP = [OARequestParameter requestParameterWithName:@"exclude_replies" value:@"false"];
- OARequestParameter *includeRTsP = [OARequestParameter requestParameterWithName:@"include_rts" value:@"true"];
- NSMutableArray *params = [NSMutableArray array];
- [params addObject:countP];
- [params addObject:userP];
- [params addObject:excludeRepliesP];
- [params addObject:includeRTsP];
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- if (maxID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"max_id" value:maxID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (id)getProfileImageForUsername:(NSString *)username andSize:(FHSTwitterEngineImageSize)size {
-
- if (username.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_users_show];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *usernameP = [OARequestParameter requestParameterWithName:@"screen_name" value:username];
-
- NSArray *params = [NSArray arrayWithObjects:usernameP, nil];
-
- id userShowReturn = [self sendGETRequest:request withParameters:params];
-
- if ([userShowReturn isKindOfClass:[NSError class]]) {
- return [NSError errorWithDomain:[(NSError *)userShowReturn domain] code:[(NSError *)userShowReturn code] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- } else if ([userShowReturn isKindOfClass:[NSDictionary class]]) {
- NSString *url = [userShowReturn objectForKey:@"profile_image_url"]; // normal
-
- if (size == 0) { // mini
- url = [url stringByReplacingOccurrencesOfString:@"_normal" withString:@"_mini"];
- } else if (size == 2) { // bigger
- url = [url stringByReplacingOccurrencesOfString:@"_normal" withString:@"_bigger"];
- } else if (size == 3) { // original
- url = [url stringByReplacingOccurrencesOfString:@"_normal" withString:@""];
- }
-
- id ret = [self sendRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:url]]];
-
- if ([ret isKindOfClass:[NSData class]]) {
- return [UIImage imageWithData:(NSData *)ret];
- }
- return ret;
- }
-
- return [NSError errorWithDomain:@"Bad Request: The request you attempted to make messed up royally." code:400 userInfo:nil];
- }
- - (id)authenticatedUserIsBlocking:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_blocks_exists];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- OARequestParameter *skipstatusP = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
-
- id obj = [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:skipstatusP, userP, nil]];
-
- if ([obj isKindOfClass:[NSError class]]) {
- return obj;
- } else if ([obj isKindOfClass:[NSDictionary class]]) {
- if ([[obj objectForKey:@"error"]isEqualToString:@"You are not blocking this user."]) {
- return @"NO";
- } else {
- return @"YES";
- }
- }
-
- return getBadRequestError();
- }
- - (id)listBlockedUsers {
- NSURL *baseURL = [NSURL URLWithString:url_blocks_blocking];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipstatusP = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:skipstatusP, nil]];
- }
- - (id)listBlockedIDs {
- NSURL *baseURL = [NSURL URLWithString:url_blocks_blocking_ids];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *stringifyIDsP = [OARequestParameter requestParameterWithName:@"stringify_ids" value:@"true"];
-
- id object = [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:stringifyIDsP, nil]];
-
- if ([object isKindOfClass:[NSDictionary class]]) {
- return [(NSDictionary *)object objectForKey:@"ids"];
- }
- return object;
- }
- - (id)getLanguages {
- NSURL *baseURL = [NSURL URLWithString:url_help_languages];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- return [self sendGETRequest:request withParameters:nil];
- }
- - (id)getConfiguration {
- NSURL *baseURL = [NSURL URLWithString:url_help_configuration];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- return [self sendGETRequest:request withParameters:nil];
- }
- - (NSError *)reportUserAsSpam:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_users_report_spam];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:userP, nil]];
- }
- - (id)showDirectMessage:(NSString *)messageID {
-
- if (messageID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_direct_messages_show];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *id_ = [OARequestParameter requestParameterWithName:@"id" value:messageID];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:id_, nil]];
- }
- - (NSError *)sendDirectMessage:(NSString *)body toUser:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- if (body.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_direct_messages_new];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *bodyP = [OARequestParameter requestParameterWithName:@"text" value:[body fhs_trimForTwitter]];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:userP, bodyP, nil]];
- }
- - (id)getSentDirectMessages:(int)count {
-
- if (count == 0) {
- return nil;
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_direct_messages_sent];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:countP, nil]];
- }
- - (NSError *)deleteDirectMessage:(NSString *)messageID {
-
- if (messageID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_direct_messages_destroy];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *identitifierP = [OARequestParameter requestParameterWithName:@"id" value:messageID];
- OARequestParameter *includeEntitiesP = [OARequestParameter requestParameterWithName:@"include_entities" value:self.includeEntities?@"true":@"false"];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:identitifierP, includeEntitiesP, nil]];
- }
- - (id)getDirectMessages:(int)count {
-
- if (count == 0) {
- return nil;
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_direct_messages];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *skipStatusP = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:countP, skipStatusP, nil]];
- }
- - (id)getPrivacyPolicy {
- NSURL *baseURL = [NSURL URLWithString:url_help_privacy];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
-
- id object = [self sendGETRequest:request withParameters:nil];
-
- if ([object isKindOfClass:[NSDictionary class]]) {
- NSDictionary *dict = (NSDictionary *)object;
- if ([dict.allKeys containsObject:@"privacy"]) {
- return [dict objectForKey:@"privacy"];
- }
- }
- return object;
- }
- - (id)getTermsOfService {
- NSURL *baseURL = [NSURL URLWithString:url_help_tos];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
-
- id object = [self sendGETRequest:request withParameters:nil];
-
- if ([object isKindOfClass:[NSDictionary class]]) {
- NSDictionary *dict = (NSDictionary *)object;
- if ([dict.allKeys containsObject:@"tos"]) {
- return [dict objectForKey:@"tos"];
- }
- }
- return object;
- }
- - (id)getNoRetweetIDs {
- NSURL *baseURL = [NSURL URLWithString:url_friendships_no_retweets_ids];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *stringifyIDsP = [OARequestParameter requestParameterWithName:@"stringify_ids" value:@"true"];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:stringifyIDsP, nil]];
- }
- - (NSError *)enableRetweets:(BOOL)enableRTs andDeviceNotifs:(BOOL)devNotifs forUser:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_friendships_update];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- OARequestParameter *retweetsP = [OARequestParameter requestParameterWithName:@"retweets" value:enableRTs?@"true":@"false"];
- OARequestParameter *deviceP = [OARequestParameter requestParameterWithName:@"device" value:devNotifs?@"true":@"false"];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:userP, retweetsP, deviceP, nil]];
- }
- - (id)getPendingOutgoingFollowers {
- NSURL *baseURL = [NSURL URLWithString:url_friendships_outgoing];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *stringifyIDsP = [OARequestParameter requestParameterWithName:@"stringify_ids" value:@"true"];
-
- id object = [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:stringifyIDsP, nil]];
-
- if ([object isKindOfClass:[NSDictionary class]]) {
- NSDictionary *dict = (NSDictionary *)object;
- if ([dict.allKeys containsObject:@"ids"]) {
- return [dict objectForKey:@"ids"];
- }
- }
- return object;
- }
- - (id)getPendingIncomingFollowers {
- NSURL *baseURL = [NSURL URLWithString:url_friendships_incoming];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *stringifyIDsP = [OARequestParameter requestParameterWithName:@"stringify_ids" value:@"true"];
-
- id object = [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:stringifyIDsP, nil]];
-
- if ([object isKindOfClass:[NSDictionary class]]) {
- NSDictionary *dict = (NSDictionary *)object;
- if ([dict.allKeys containsObject:@"ids"]) {
- return [dict objectForKey:@"ids"];
- }
- }
- return object;
- }
- - (id)lookupFriendshipStatusForUsers:(NSArray *)users areIDs:(BOOL)areIDs {
-
- if (users.count == 0) {
- return nil;
- }
-
- NSMutableArray *returnedDictionaries = [NSMutableArray array];
- NSArray *reqStrings = [self generateRequestStringsFromArray:users];
-
- NSURL *baseURL = [NSURL URLWithString:url_friendships_lookup];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
-
- for (NSString *reqString in reqStrings) {
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:areIDs?@"user_id":@"screen_name" value:reqString];
-
- id retObj = [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:userP, nil]];
-
- if ([retObj isKindOfClass:[NSArray class]]) {
- [returnedDictionaries addObjectsFromArray:(NSArray *)retObj];
- } else if ([retObj isKindOfClass:[NSError class]]) {
- return retObj;
- }
- }
- return returnedDictionaries;
- }
- - (NSError *)unfollowUser:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_friendships_destroy];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:userP, nil]];
- }
- - (NSError *)followUser:(NSString *)user isID:(BOOL)isID {
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_friendships_create];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:userP, nil]];
- }
- - (id)verifyCredentials {
- NSURL *baseURL = [NSURL URLWithString:url_account_verify_credentials];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- return [self sendGETRequest:request withParameters:nil];
- }
- - (id)getFavoritesForUser:(NSString *)user isID:(BOOL)isID andCount:(int)count {
- return [self getFavoritesForUser:user isID:isID andCount:count sinceID:nil maxID:nil];
- }
- - (id)getFavoritesForUser:(NSString *)user isID:(BOOL)isID andCount:(int)count sinceID:(NSString *)sinceID maxID:(NSString *)maxID {
- if (count == 0) {
- return nil;
- }
-
- if (user.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_favorites_list];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countP = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d",count]];
- OARequestParameter *userP = [OARequestParameter requestParameterWithName:isID?@"user_id":@"screen_name" value:user];
- OARequestParameter *includeEntitiesP = [OARequestParameter requestParameterWithName:@"include_entities" value:self.includeEntities?@"true":@"false"];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:countP, userP, includeEntitiesP, nil];
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- if (maxID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"max_id" value:maxID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (NSError *)markTweet:(NSString *)tweetID asFavorite:(BOOL)flag {
-
- if (tweetID.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:flag?url_favorites_create:url_favorites_destroy];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *idP = [OARequestParameter requestParameterWithName:@"id" value:tweetID];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:idP, nil]];
- }
- - (id)getRateLimitStatus {
- NSURL *baseURL = [NSURL URLWithString:url_application_rate_limit_status];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- return [self sendGETRequest:request withParameters:nil];
- }
- - (NSError *)updateProfileColorsWithDictionary:(NSDictionary *)dictionary {
-
- // profile_background_color - hex color
- // profile_link_color - hex color
- // profile_sidebar_border_color - hex color
- // profile_sidebar_fill_color - hex color
- // profile_text_color - hex color
-
- NSString *profile_background_color = nil;
- NSString *profile_link_color = nil;
- NSString *profile_sidebar_border_color = nil;
- NSString *profile_sidebar_fill_color = nil;
- NSString *profile_text_color = nil;
-
- if (!dictionary) {
- profile_background_color = @"C0DEED";
- profile_link_color = @"0084B4";
- profile_sidebar_border_color = @"C0DEED";
- profile_sidebar_fill_color = @"DDEEF6";
- profile_text_color = @"333333";
- } else {
- profile_background_color = [dictionary objectForKey:FHSProfileBackgroundColorKey];
- profile_link_color = [dictionary objectForKey:FHSProfileLinkColorKey];
- profile_sidebar_border_color = [dictionary objectForKey:FHSProfileSidebarBorderColorKey];
- profile_sidebar_fill_color = [dictionary objectForKey:FHSProfileSidebarFillColorKey];
- profile_text_color = [dictionary objectForKey:FHSProfileTextColorKey];
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_account_update_profile_colors];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipStatus = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:skipStatus, nil];
-
- if (profile_background_color.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"profile_background_color" value:profile_background_color]];
- }
-
- if (profile_link_color.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"profile_link_color" value:profile_link_color]];
- }
-
- if (profile_sidebar_border_color.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"profile_sidebar_border_color" value:profile_sidebar_border_color]];
- }
-
- if (profile_sidebar_fill_color.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"profile_sidebar_fill_color" value:profile_sidebar_fill_color]];
- }
-
- if (profile_text_color.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"profile_text_color" value:profile_text_color]];
- }
-
- return [self sendPOSTRequest:request withParameters:params];
- }
- - (NSError *)setUseProfileBackgroundImage:(BOOL)shouldUseBGImg {
- NSURL *baseURL = [NSURL URLWithString:url_account_update_profile_background_image];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipStatus = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- OARequestParameter *useImage = [OARequestParameter requestParameterWithName:@"profile_use_background_image" value:shouldUseBGImg?@"true":@"false"];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:skipStatus, useImage, nil]];
- }
- - (NSError *)setProfileBackgroundImageWithImageData:(NSData *)data tiled:(BOOL)isTiled {
- if (data.length == 0) {
- return getBadRequestError();
- }
-
- if (data.length >= 800000) {
- return [NSError errorWithDomain:@"The image you are trying to upload is too large." code:422 userInfo:nil];
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_account_update_profile_background_image];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *tiled = [OARequestParameter requestParameterWithName:@"tiled" value:isTiled?@"true":@"false"];
- OARequestParameter *skipStatus = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- OARequestParameter *useImage = [OARequestParameter requestParameterWithName:@"profile_use_background_image" value:@"true"];
- OARequestParameter *image = [OARequestParameter requestParameterWithName:@"image" value:[data base64EncodingWithLineLength:0]];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:tiled, skipStatus, useImage, image, nil]];
- }
- - (NSError *)setProfileBackgroundImageWithImageAtPath:(NSString *)file tiled:(BOOL)isTiled {
- return [self setProfileBackgroundImageWithImageData:[NSData dataWithContentsOfFile:file] tiled:isTiled];
- }
- - (NSError *)setProfileImageWithImageData:(NSData *)data {
- if (data.length == 0) {
- return getBadRequestError();
- }
-
- if (data.length >= 700000) {
- return [NSError errorWithDomain:@"The image you are trying to upload is too large." code:422 userInfo:nil];
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_account_update_profile_image];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipStatus = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
- OARequestParameter *image = [OARequestParameter requestParameterWithName:@"image" value:[data base64EncodingWithLineLength:0]];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:image, skipStatus, nil]];
- }
- - (NSError *)setProfileImageWithImageAtPath:(NSString *)file {
- return [self setProfileImageWithImageData:[NSData dataWithContentsOfFile:file]];
- }
- - (id)getUserSettings {
- NSURL *baseURL = [NSURL URLWithString:url_account_settings];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- return [self sendGETRequest:request withParameters:nil];
- }
- - (NSError *)updateUserProfileWithDictionary:(NSDictionary *)settings {
-
- if (!settings) {
- return getBadRequestError();
- }
-
- // all of the values are just non-normalized strings. They appear:
-
- // setting - length in characters
- // name - 20
- // url - 100
- // location - 30
- // description - 160
-
- NSString *name = [settings objectForKey:FHSProfileNameKey];
- NSString *url = [settings objectForKey:FHSProfileURLKey];
- NSString *location = [settings objectForKey:FHSProfileLocationKey];
- NSString *description = [settings objectForKey:FHSProfileDescriptionKey];
-
- NSURL *baseURL = [NSURL URLWithString:url_account_update_profile];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *skipStatus = [OARequestParameter requestParameterWithName:@"skip_status" value:@"true"];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:skipStatus, nil];
-
- if (name.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"name" value:name]];
- }
-
- if (url.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"url" value:url]];
- }
-
- if (location.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"location" value:location]];
- }
-
- if (description.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"description" value:description]];
- }
-
- return [self sendPOSTRequest:request withParameters:params];
- }
- - (NSError *)updateSettingsWithDictionary:(NSDictionary *)settings {
-
- if (!settings) {
- return getBadRequestError();
- }
-
- // Dictionary with keys:
- // All strings... You could have guessed that.
- // sleep_time_enabled - true/false
- // start_sleep_time - UTC time
- // end_sleep_time - UTC time
- // time_zone - Europe/Copenhagen, Pacific/Tongatapu
- // lang - en, it, es
-
- NSString *sleep_time_enabled = [settings objectForKey:@"sleep_time_enabled"];
- NSString *start_sleep_time = [settings objectForKey:@"start_sleep_time"];
- NSString *end_sleep_time = [settings objectForKey:@"end_sleep_time"];
- NSString *time_zone = [settings objectForKey:@"time_zone"];
- NSString *lang = [settings objectForKey:@"lang"];
-
- NSURL *baseURL = [NSURL URLWithString:url_account_settings];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
-
- NSMutableArray *params = [NSMutableArray array];
-
- if (sleep_time_enabled.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"sleep_time_enabled" value:sleep_time_enabled]];
- }
-
- if (start_sleep_time.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"start_sleep_time" value:start_sleep_time]];
- }
-
- if (end_sleep_time.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"end_sleep_time" value:end_sleep_time]];
- }
-
- if (time_zone.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"time_zone" value:time_zone]];
- }
-
- if (lang.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"lang" value:lang]];
- }
-
- return [self sendPOSTRequest:request withParameters:params];
- }
- - (id)lookupUsers:(NSArray *)users areIDs:(BOOL)areIDs {
-
- if (users.count == 0) {
- return nil;
- }
-
- if (users.count > 100) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_users_lookup];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *usernames = [OARequestParameter requestParameterWithName:areIDs?@"user_id":@"screen_name" value:[users componentsJoinedByString:@","]];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:usernames, nil]];
- }
- - (NSError *)unblock:(NSString *)username {
- if (username.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_blocks_destroy];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *usernameP = [OARequestParameter requestParameterWithName:@"screen_name" value:username];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:usernameP, nil]];
- }
- - (NSError *)block:(NSString *)username {
-
- if (username.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_blocks_create];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *usernameP = [OARequestParameter requestParameterWithName:@"screen_name" value:username];
- return [self sendPOSTRequest:request withParameters:[NSArray arrayWithObjects:usernameP, nil]];
- }
- - (id)testService {
- NSURL *baseURL = [NSURL URLWithString:url_help_test];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
-
- id retValue = [self sendGETRequest:request withParameters:nil];
-
- if ([retValue isKindOfClass:[NSString class]]) {
- if ([(NSString *)retValue isEqualToString:@"ok"]) {
- return @"YES";
- } else {
- return @"NO";
- }
- } else if ([retValue isKindOfClass:[NSError class]]) {
- return retValue;
- }
-
- return getBadRequestError();
- }
- - (id)getHomeTimelineSinceID:(NSString *)sinceID count:(int)count {
-
- if (count == 0) {
- return nil;
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_home_timeline];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *countParam = [OARequestParameter requestParameterWithName:@"count" value:[NSString stringWithFormat:@"%d", count]];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:countParam, nil];
-
- if (sinceID.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"since_id" value:sinceID]];
- }
-
- return [self sendGETRequest:request withParameters:params];
- }
- - (NSError *)postTweet:(NSString *)tweetString inReplyTo:(NSString *)inReplyToString {
-
- if (tweetString.length == 0) {
- return getBadRequestError();
- }
-
- NSURL *baseURL = [NSURL URLWithString:url_statuses_update];
- OARequestParameter *status = [OARequestParameter requestParameterWithName:@"status" value:[tweetString fhs_trimForTwitter]];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
-
- NSMutableArray *params = [NSMutableArray arrayWithObjects:status, nil];
-
- if (inReplyToString.length > 0) {
- [params addObject:[OARequestParameter requestParameterWithName:@"in_reply_to_status_id" value:inReplyToString]];
- }
-
- return [self sendPOSTRequest:request withParameters:params];
- }
- - (NSError *)postTweet:(NSString *)tweetString {
- return [self postTweet:tweetString inReplyTo:nil];
- }
- - (id)getFollowersIDs {
- NSURL *baseURL = [NSURL URLWithString:url_followers_ids];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *param = [OARequestParameter requestParameterWithName:@"screen_name" value:self.loggedInUsername];
- OARequestParameter *stringify_ids = [OARequestParameter requestParameterWithName:@"stringify_ids" value:@"true"];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:param, stringify_ids, nil]];
- }
- - (id)getFriendsIDs {
- NSURL *baseURL = [NSURL URLWithString:url_friends_ids];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:self.accessToken];
- OARequestParameter *param = [OARequestParameter requestParameterWithName:@"screen_name" value:self.loggedInUsername];
- OARequestParameter *stringify_ids = [OARequestParameter requestParameterWithName:@"stringify_ids" value:@"true"];
- return [self sendGETRequest:request withParameters:[NSArray arrayWithObjects:param, stringify_ids, nil]];
- }
- - (id)init {
- self = [super init];
- if (self) {
- // Twitter API datestamps are UTC
- // Don't question this code.
- self.dateFormatter = [[[NSDateFormatter alloc]init]autorelease];
- _dateFormatter.locale = [[[NSLocale alloc]initWithLocaleIdentifier:@"en_US"]autorelease];
- _dateFormatter.dateStyle = NSDateFormatterLongStyle;
- _dateFormatter.formatterBehavior = NSDateFormatterBehavior10_4;
- _dateFormatter.dateFormat = @"EEE MMM dd HH:mm:ss ZZZZ yyyy";
- }
- return self;
- }
- // The shared* class method
- + (FHSTwitterEngine *)sharedEngine {
- @synchronized (self) {
- if (sharedInstance == nil) {
- [[self alloc]init];
- }
- }
- return sharedInstance;
- }
- // Override stuff to make sure that the singleton is never dealloc'd. Fun.
- + (id)allocWithZone:(NSZone *)zone {
- @synchronized(self) {
- if (sharedInstance == nil) {
- sharedInstance = [super allocWithZone:zone];
- return sharedInstance;
- }
- }
- return nil;
- }
- - (id)retain {
- return self;
- }
- - (oneway void)release {
- // Do nothing
- }
- - (id)autorelease {
- return self;
- }
- - (NSUInteger)retainCount {
- return NSUIntegerMax;
- }
- - (NSArray *)generateRequestStringsFromArray:(NSArray *)array {
-
- NSString *initialString = [array componentsJoinedByString:@","];
-
- if (array.count <= 100) {
- return [NSArray arrayWithObjects:initialString, nil];
- }
-
- int offset = 0;
- int remainder = fmod(array.count, 100);
- int numberOfStrings = (int)((array.count-remainder)/100);
-
- NSMutableArray *reqStrs = [NSMutableArray array];
-
- for (int i = 1; i <= numberOfStrings; ++i) {
- NSString *ninetyNinththItem = (NSString *)[array objectAtIndex:(i*100)-1];
- NSRange range = [initialString rangeOfString:ninetyNinththItem];
- int endOffset = (int)(range.location+range.length);
- NSRange rangeOfAString = NSMakeRange(offset, endOffset-offset);
- offset = endOffset;
- NSString *endResult = [initialString fhs_stringWithRange:rangeOfAString];
-
- if ([[endResult substringToIndex:1]isEqualToString:@","]) {
- endResult = [endResult substringFromIndex:1];
- }
-
- [reqStrs addObject:endResult];
- }
-
- NSString *remainderString = [initialString stringByReplacingOccurrencesOfString:[reqStrs componentsJoinedByString:@","] withString:@""];
-
- if ([[remainderString substringToIndex:1]isEqualToString:@","]) {
- remainderString = [remainderString substringFromIndex:1];
- }
-
- [reqStrs addObject:remainderString];
-
- return reqStrs;
- }
- //
- // XAuth
- //
- - (NSError *)getXAuthAccessTokenForUsername:(NSString *)username password:(NSString *)password {
-
- if (password.length == 0) {
- return [NSError errorWithDomain:@"Bad Request: The request you are trying to make is missing parameters." code:400 userInfo:nil];
- }
-
- if (username.length == 0) {
- return [NSError errorWithDomain:@"Bad Request: The request you are trying to make is missing parameters." code:400 userInfo:nil];
- }
-
- NSURL *baseURL = [NSURL URLWithString:@"https://api.twitter.com/oauth/access_token"];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:baseURL consumer:self.consumer token:nil];
- OARequestParameter *x_auth_mode = [OARequestParameter requestParameterWithName:@"x_auth_mode" value:@"client_auth"];
- OARequestParameter *x_auth_username = [OARequestParameter requestParameterWithName:@"x_auth_username" value:username];
- OARequestParameter *x_auth_password = [OARequestParameter requestParameterWithName:@"x_auth_password" value:password];
- [request setHTTPMethod:@"POST"];
-
- [request setParameters:[NSArray arrayWithObjects:x_auth_mode, x_auth_username, x_auth_password, nil]];
- [request prepare];
-
- if (self.shouldClearConsumer) {
- self.shouldClearConsumer = NO;
- self.consumer = nil;
- }
-
- id ret = [self sendRequest:request];
-
- if ([ret isKindOfClass:[NSError class]]) {
- return ret;
- }
-
- NSString *httpBody = [[[NSString alloc]initWithData:(NSData *)ret encoding:NSUTF8StringEncoding]autorelease];
-
- if (httpBody.length > 0) {
- [self storeAccessToken:httpBody];
- } else {
- [self storeAccessToken:nil];
- return [NSError errorWithDomain:@"Twitter messed up and did not return anything for some reason. Please try again later." code:500 userInfo:nil];
- }
- return nil;
- }
- //
- // sendRequest:
- //
- - (id)sendRequest:(NSURLRequest *)request {
-
- NSHTTPURLResponse *response = nil;
- NSError *error = nil;
-
- NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
-
- if (error) {
- return error;
- }
-
- if (response == nil) {
- return error;
- }
-
- if (response.statusCode >= 304) {
- return error;
- }
-
- if (data.length == 0) {
- return error;
- }
-
- return data;
- }
- - (NSError *)sendPOSTRequest:(OAMutableURLRequest *)request withParameters:(NSArray *)params {
-
- if (![self isAuthorized]) {
- [self loadAccessToken];
- if (![self isAuthorized]) {
- return [NSError errorWithDomain:@"You are not authorized via OAuth" code:401 userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- }
- }
-
- [request setHTTPMethod:@"POST"];
- [request setParameters:params];
- [request prepare];
-
- if (_shouldClearConsumer) {
- self.shouldClearConsumer = NO;
- self.consumer = nil;
- }
-
- id retobj = [self sendRequest:request];
-
- if (retobj == nil) {
- return getNilReturnLengthError();
- }
-
- if ([retobj isKindOfClass:[NSError class]]) {
- return retobj;
- }
-
- id parsedJSONResponse = removeNull([NSJSONSerialization JSONObjectWithData:(NSData *)retobj options:NSJSONReadingMutableContainers error:nil]);
-
- if ([parsedJSONResponse isKindOfClass:[NSDictionary class]]) {
- NSString *errorMessage = [parsedJSONResponse objectForKey:@"error"];
- NSArray *errorArray = [parsedJSONResponse objectForKey:@"errors"];
- if (errorMessage.length > 0) {
- return [NSError errorWithDomain:errorMessage code:[[parsedJSONResponse objectForKey:@"code"]intValue] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- } else if (errorArray.count > 0) {
- if (errorArray.count > 1) {
- return [NSError errorWithDomain:@"Multiple Errors" code:1337 userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- } else {
- NSDictionary *theError = [errorArray objectAtIndex:0];
- return [NSError errorWithDomain:[theError objectForKey:@"message"] code:[[theError objectForKey:@"code"]integerValue] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- }
- }
- }
-
- return nil;
- }
- - (id)sendGETRequest:(OAMutableURLRequest *)request withParameters:(NSArray *)params {
-
- if (![self isAuthorized]) {
- [self loadAccessToken];
- if (![self isAuthorized]) {
- return [NSError errorWithDomain:@"You are not authorized via OAuth" code:401 userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- }
- }
-
- [request setHTTPMethod:@"GET"];
- [request setParameters:params];
- [request prepare];
-
- if (_shouldClearConsumer) {
- self.shouldClearConsumer = NO;
- self.consumer = nil;
- }
-
- id retobj = [self sendRequest:request];
-
- if (retobj == nil) {
- return getNilReturnLengthError();
- }
-
- if ([retobj isKindOfClass:[NSError class]]) {
- return retobj;
- }
-
- id parsedJSONResponse = removeNull([NSJSONSerialization JSONObjectWithData:(NSData *)retobj options:NSJSONReadingMutableContainers error:nil]);
-
- if ([parsedJSONResponse isKindOfClass:[NSDictionary class]]) {
- NSString *errorMessage = [parsedJSONResponse objectForKey:@"error"];
- NSArray *errorArray = [parsedJSONResponse objectForKey:@"errors"];
- if (errorMessage.length > 0) {
- return [NSError errorWithDomain:errorMessage code:[[parsedJSONResponse objectForKey:@"code"]intValue] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- } else if (errorArray.count > 0) {
- if (errorArray.count > 1) {
- return [NSError errorWithDomain:@"Multiple Errors" code:1337 userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- } else {
- NSDictionary *theError = [errorArray objectAtIndex:0];
- return [NSError errorWithDomain:[theError objectForKey:@"message"] code:[[theError objectForKey:@"code"]integerValue] userInfo:[NSDictionary dictionaryWithObject:request forKey:@"request"]];
- }
- }
- }
-
- return parsedJSONResponse;
- }
- //
- // OAuth
- //
- - (NSString *)getRequestTokenString {
- NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/oauth/request_token"];
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:url consumer:self.consumer token:nil];
- [request setHTTPMethod:@"POST"];
- [request prepare];
-
- id retobj = [self sendRequest:request];
-
- if ([retobj isKindOfClass:[NSData class]]) {
- return [[[NSString alloc]initWithData:(NSData *)retobj encoding:NSUTF8StringEncoding]autorelease];
- }
-
- return nil;
- }
- - (BOOL)finishAuthWithRequestToken:(OAToken *)reqToken {
- NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/oauth/access_token"];
-
- OAMutableURLRequest *request = [OAMutableURLRequest requestWithURL:url consumer:self.consumer token:reqToken];
- [request setHTTPMethod:@"POST"];
- [request prepare];
-
- if (_shouldClearConsumer) {
- self.shouldClearConsumer = NO;
- self.consumer = nil;
- }
-
- id retobj = [self sendRequest:request];
-
- if ([retobj isKindOfClass:[NSError class]]) {
- return NO;
- }
-
- NSString *response = [[[NSString alloc]initWithData:(NSData *)retobj encoding:NSUTF8StringEncoding]autorelease];
-
- if (response.length == 0) {
- return NO;
- }
-
- [self storeAccessToken:response];
-
- return YES;
- }
- //
- // Access Token Management
- //
- - (void)loadAccessToken {
-
- NSString *savedHttpBody = nil;
-
- if (self.delegate && [self.delegate respondsToSelector:@selector(loadAccessToken)]) {
- savedHttpBody = [self.delegate loadAccessToken];
- } else {
- savedHttpBody = [[NSUserDefaults standardUserDefaults]objectForKey:@"SavedAccessHTTPBody"];
- }
-
- self.accessToken = [OAToken tokenWithHTTPResponseBody:savedHttpBody];
- self.loggedInUsername = [self extractValueForKey:@"screen_name" fromHTTPBody:savedHttpBody];
- self.loggedInID = [self extractValueForKey:@"user_id" fromHTTPBody:savedHttpBody];
- }
- - (void)storeAccessToken:(NSString *)accessTokenZ {
- self.accessToken = [OAToken tokenWithHTTPResponseBody:accessTokenZ];
- self.loggedInUsername = [self extractValueForKey:@"screen_name" fromHTTPBody:accessTokenZ];
- self.loggedInID = [self extractValueForKey:@"user_id" fromHTTPBody:accessTokenZ];
-
- if ([self.delegate respondsToSelector:@selector(storeAccessToken:)]) {
- [self.delegate storeAccessToken:accessTokenZ];
- } else {
- [[NSUserDefaults standardUserDefaults]setObject:accessTokenZ forKey:@"SavedAccessHTTPBody"];
- }
- }
- - (NSString *)extractValueForKey:(NSString *)target fromHTTPBody:(NSString *)body {
- if (body.length == 0) {
- return nil;
- }
-
- if (target.length == 0) {
- return nil;
- }
-
- NSArray *tuples = [body componentsSeparatedByString:@"&"];
- if (tuples.count < 1) {
- return nil;
- }
-
- for (NSString *tuple in tuples) {
- NSArray *keyValueArray = [tuple componentsSeparatedByString:@"="];
-
- if (keyValueArray.count >= 2) {
- NSString *key = [keyValueArray objectAtIndex:0];
- NSString *value = [keyValueArray objectAtIndex:1];
-
- if ([key isEqualToString:target]) {
- return value;
- }
- }
- }
-
- return nil;
- }
- - (BOOL)isAuthorized {
- if (!self.consumer) {
- return NO;
- }
-
- if (self.accessToken.key && self.accessToken.secret) {
- if (self.accessToken.key.length > 0 && self.accessToken.secret.length > 0) {
- return YES;
- }
- }
-
- return NO;
- }
- - (void)clearAccessToken {
- [self storeAccessToken:@""];
- self.accessToken = nil;
- self.loggedInUsername = nil;
- }
- - (NSDate *)getDateFromTwitterCreatedAt:(NSString *)twitterDate {
- return [self.dateFormatter dateFromString:twitterDate];
- }
- - (void)clearConsumer {
- self.consumer = nil;
- }
- - (void)permanentlySetConsumerKey:(NSString *)consumerKey andSecret:(NSString *)consumerSecret {
- self.shouldClearConsumer = NO;
- self.consumer = [OAConsumer consumerWithKey:consumerKey secret:consumerSecret];
- }
- - (void)temporarilySetConsumerKey:(NSString *)consumerKey andSecret:(NSString *)consumerSecret {
- self.shouldClearConsumer = YES;
- self.consumer = [OAConsumer consumerWithKey:consumerKey secret:consumerSecret];
- }
- - (void)showOAuthLoginControllerFromViewController:(UIViewController *)sender {
- [self showOAuthLoginControllerFromViewController:sender withCompletion:nil];
- }
- - (void)showOAuthLoginControllerFromViewController:(UIViewController *)sender withCompletion:(void(^)(BOOL success))block {
- FHSTwitterEngineController *vc = [[[FHSTwitterEngineController alloc]init]autorelease];
- vc.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
- objc_setAssociatedObject(authBlockKey, "FHSTwitterEngineOAuthCompletion", block, OBJC_ASSOCIATION_COPY_NONATOMIC);
- [sender presentModalViewController:vc animated:YES];
- }
- + (BOOL)isConnectedToInternet {
- struct sockaddr_in zeroAddress;
- bzero(&zeroAddress, sizeof(zeroAddress));
- zeroAddress.sin_len = sizeof(zeroAddress);
- zeroAddress.sin_family = AF_INET;
-
- SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithAddress(kCFAllocatorDefault, (const struct sockaddr *)&zeroAddress);
- if (reachability) {
- SCNetworkReachabilityFlags flags;
- BOOL worked = SCNetworkReachabilityGetFlags(reachability, &flags);
- CFRelease(reachability);
-
- if (worked) {
-
- if ((flags & kSCNetworkReachabilityFlagsReachable) == 0) {
- return NO;
- }
-
- if ((flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0) {
- return YES;
- }
-
-
- if ((((flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0) || (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0)) {
- if ((flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0) {
- return YES;
- }
- }
-
- if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN) {
- return YES;
- }
- }
-
- }
- return NO;
- }
- - (void)dealloc {
- [self setConsumer:nil];
- [self setDateFormatter:nil];
- [self setLoggedInUsername:nil];
- [self setLoggedInID:nil];
- [self setDelegate:nil];
- [self setAccessToken:nil];
- [super dealloc];
- }
- @end
- @implementation FHSTwitterEngineController
- static NSString * const newPinJS = @"var d = document.getElementById('oauth-pin'); if (d == null) d = document.getElementById('oauth_pin'); if (d) { var d2 = d.getElementsByTagName('code'); if (d2.length > 0) d2[0].innerHTML; }";
- static NSString * const oldPinJS = @"var d = document.getElementById('oauth-pin'); if (d == null) d = document.getElementById('oauth_pin'); if (d) d = d.innerHTML; d;";
- - (void)loadView {
- [super loadView];
- [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(pasteboardChanged:) name:UIPasteboardChangedNotification object:nil];
-
- self.view = [[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]autorelease];
- self.view.backgroundColor = [UIColor grayColor];
- self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
-
- self.theWebView = [[[UIWebView alloc]initWithFrame:CGRectMake(0, 44, 320, 416)]autorelease];
- _theWebView.hidden = YES;
- _theWebView.delegate = self;
- _theWebView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
- _theWebView.dataDetectorTypes = UIDataDetectorTypeNone;
- _theWebView.backgroundColor = [UIColor darkGrayColor];
-
- self.navBar = [[[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]autorelease];
- _navBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
-
- [self.view addSubview:_theWebView];
- [self.view addSubview:_navBar];
-
- self.blockerView = [[[UIView alloc]initWithFrame:CGRectMake(0, 0, 200, 60)]autorelease];
- _blockerView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.8];
- _blockerView.center = CGPointMake(self.view.bounds.size.width/2, self.view.bounds.size.height/2);
- _blockerView.clipsToBounds = YES;
- _blockerView.layer.cornerRadius = 10;
-
- self.pinCopyBar = [[[UIToolbar alloc]initWithFrame:CGRectMake(0, 44, self.view.bounds.size.width, 44)]autorelease];
- _pinCopyBar.barStyle = UIBarStyleBlackTranslucent;
- _pinCopyBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin;
- _pinCopyBar.items = [NSArray arrayWithObjects:[[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]autorelease], [[[UIBarButtonItem alloc]initWithTitle:@"Select and Copy the PIN" style: UIBarButtonItemStylePlain target:nil action: nil]autorelease], [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]autorelease], nil];
-
- UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 5, _blockerView.bounds.size.width, 15)];
- label.text = @"Please Wait...";
- label.backgroundColor = [UIColor clearColor];
- label.textColor = [UIColor whiteColor];
- label.textAlignment = UITextAlignmentCenter;
- label.font = [UIFont boldSystemFontOfSize:15];
- [_blockerView addSubview:label];
- [label release];
-
- UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
- spinner.center = CGPointMake(_blockerView.bounds.size.width/2, (_blockerView.bounds.size.height/2)+10);
- [_blockerView addSubview:spinner];
- [self.view addSubview:_blockerView];
- [spinner startAnimating];
- [spinner release];
-
- UINavigationItem *navItem = [[[UINavigationItem alloc]initWithTitle:@"Twitter Login"]autorelease];
- navItem.leftBarButtonItem = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(close)]autorelease];
- [_navBar pushNavigationItem:navItem animated:NO];
-
- [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
-
- dispatch_async(GCDBackgroundThread, ^{
- NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
-
- NSString *reqString = [[FHSTwitterEngine sharedEngine]getRequestTokenString];
-
- if (reqString.length == 0) {
- [self dismissModalViewControllerAnimated:YES];
- [pool release];
- return;
- }
-
- self.requestToken = [OAToken tokenWithHTTPResponseBody:reqString];
- NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"https://api.twitter.com/oauth/authorize?oauth_token=%@",_requestToken.key]]];
-
- dispatch_sync(GCDMainThread, ^{
- NSAutoreleasePool *poolTwo = [[NSAutoreleasePool alloc]init];
- [_theWebView loadRequest:request];
- [poolTwo release];
- });
-
- [pool release];
- });
- }
- - (void)gotPin:(NSString *)pin {
- _requestToken.verifier = pin;
- BOOL ret = [[FHSTwitterEngine sharedEngine]finishAuthWithRequestToken:_requestToken];
-
- void(^block)(BOOL success) = objc_getAssociatedObject(authBlockKey, "FHSTwitterEngineOAuthCompletion");
- objc_removeAssociatedObjects(authBlockKey);
-
- if (block) {
- block(ret);
- }
-
- [self dismissModalViewControllerAnimated:YES];
- }
- - (void)pasteboardChanged:(NSNotification *)note {
-
- if (![note.userInfo objectForKey:UIPasteboardChangedTypesAddedKey]) {
- return;
- }
-
- NSString *string = [[UIPasteboard generalPasteboard]string];
-
- if (string.length != 7 || !string.fhs_isNumeric) {
- return;
- }
-
- [self gotPin:string];
- }
- - (NSString *)locatePin {
- NSString *pin = [[_theWebView stringByEvaluatingJavaScriptFromString:newPinJS]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
-
- if (pin.length == 7) {
- return pin;
- } else {
- pin = [[_theWebView stringByEvaluatingJavaScriptFromString:oldPinJS]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
-
- if (pin.length == 7) {
- return pin;
- }
- }
-
- return nil;
- }
- - (void)webViewDidFinishLoad:(UIWebView *)webView {
- _theWebView.userInteractionEnabled = YES;
- NSString *authPin = [self locatePin];
-
- if (authPin.length > 0) {
- [self gotPin:authPin];
- return;
- }
-
- NSString *formCount = [webView stringByEvaluatingJavaScriptFromString:@"document.forms.length"];
-
- if ([formCount isEqualToString:@"0"]) {
- [self showPinCopyPrompt];
- }
-
- [UIView beginAnimations:nil context:nil];
- _blockerView.hidden = YES;
- [UIView commitAnimations];
-
- [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
-
- _theWebView.hidden = NO;
- }
- - (void)showPinCopyPrompt {
- if (_pinCopyBar.superview) {
- return;
- }
-
- _pinCopyBar.center = CGPointMake(_pinCopyBar.bounds.size.width/2, _pinCopyBar.bounds.size.height/2);
- [self.view insertSubview:_pinCopyBar belowSubview:_navBar];
-
- [UIView beginAnimations:nil context:nil];
- _pinCopyBar.center = CGPointMake(_pinCopyBar.bounds.size.width/2, _navBar.bounds.size.height+_pinCopyBar.bounds.size.height/2);
- [UIView commitAnimations];
- }
- - (void)webViewDidStartLoad:(UIWebView *)webView {
- _theWebView.userInteractionEnabled = NO;
- [_theWebView setHidden:YES];
- [_blockerView setHidden:NO];
- [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
- }
- - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
-
- if (strstr([request.URL.absoluteString UTF8String], "denied=")) {
- [self dismissModalViewControllerAnimated:YES];
- return NO;
- }
-
- NSData *data = request.HTTPBody;
- char *raw = data?(char *)[data bytes]:"";
-
- if (raw && (strstr(raw, "cancel=") || strstr(raw, "deny="))) {
- [self dismissModalViewControllerAnimated:YES];
- return NO;
- }
-
- return YES;
- }
- - (void)close {
- [self dismissModalViewControllerAnimated:YES];
- }
- - (void)dismissModalViewControllerAnimated:(BOOL)animated {
- [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
- [[NSNotificationCenter defaultCenter]removeObserver:self];
- [_theWebView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]];
- [super dismissModalViewControllerAnimated:animated];
- }
- - (void)dealloc {
- [self setNavBar:nil];
- [self setBlockerView:nil];
- [self setPinCopyBar:nil];
- [self setTheWebView:nil];
- [self setRequestToken:nil];
- [super dealloc];
- }
- @end
- static char const encodingTable[64] = {
- 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
- 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
- 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
- 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' };
- @implementation NSData (Base64)
- + (NSData *)dataWithBase64EncodedString:(NSString *)string {
- return [[[NSData alloc]initWithBase64EncodedString:string]autorelease];
- }
- - (id)initWithBase64EncodedString:(NSString *)string {
- NSMutableData *mutableData = nil;
-
- if (string) {
- unsigned long ixtext = 0;
- unsigned char ch = 0;
- unsigned char inbuf[4] = {0,0,0,0};
- unsigned char outbuf[3] = {0,0,0};
- short ixinbuf = 0;
- BOOL flignore = NO;
- BOOL flendtext = NO;
-
- NSData *base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];
- const unsigned char *base64Bytes = [base64Data bytes];
- mutableData = [NSMutableData dataWithCapacity:base64Data.length];
- unsigned long lentext = [base64Data length];
-
- while (!(ixtext >= lentext)) {
-
- ch = base64Bytes[ixtext++];
- flignore = NO;
-
- if ((ch >= 'A') && (ch <= 'Z')) {
- ch = ch - 'A';
- } else if ((ch >= 'a') && (ch <= 'z')) {
- ch = ch - 'a' + 26;
- } else if ((ch >= '0') && (ch <= '9')) {
- ch = ch - '0' + 52;
- } else if (ch == '+') {
- ch = 62;
- } else if (ch == '=') {
- flendtext = YES;
- } else if (ch == '/') {
- ch = 63;
- } else {
- flignore = YES;
- }
-
- if (!flignore) {
- short ctcharsinbuf = 3;
- BOOL flbreak = NO;
-
- if (flendtext) {
- if (!ixinbuf) {
- break;
- }
-
- if (ixinbuf == 1 || ixinbuf == 2) {
- ctcharsinbuf = 1;
- } else {
- ctcharsinbuf = 2;
- }
-
- ixinbuf = 3;
- flbreak = YES;
- }
-
- inbuf[ixinbuf++] = ch;
-
- if (ixinbuf == 4) {
- ixinbuf = 0;
- outbuf[0] = (inbuf[0] << 2) | ((inbuf[1] & 0x30) >> 4);
- outbuf[1] = ((inbuf[1] & 0x0F) << 4) | ((inbuf[2] & 0x3C) >> 2);
- outbuf[2] = ((inbuf[2] & 0x03) << 6) | (inbuf[3] & 0x3F);
-
- for (int i = 0; i < ctcharsinbuf; i++) {
- [mutableData appendBytes:&outbuf[i] length:1];
- }
- }
-
- if (flbreak) {
- break;
- }
- }
- }
- }
-
- self = [self initWithData:mutableData];
- return self;
- }
- - (NSString *)base64EncodingWithLineLength:(unsigned int)lineLength {
-
- const unsigned char *bytes = [self bytes];
- unsigned long ixtext = 0;
- unsigned long lentext = [self length];
- long ctremaining = 0;
- unsigned char inbuf[3] = {0,0,0};
- unsigned char outbuf[4] = {0,0,0,0};
-
- short charsonline = 0;
- short ctcopy = 0;
- unsigned long ix = 0;
-
- NSMutableString *result = [NSMutableString stringWithCapacity:lentext];
-
- while (YES) {
- ctremaining = lentext-ixtext;
-
- if (ctremaining <= 0) {
- break;
- }
-
- for (int i = 0; i < 3; i++) {
- ix = ixtext + i;
- inbuf[i] = (ix < lentext)?bytes[ix]:0;
- }
-
- outbuf[0] = (inbuf[0] & 0xFC) >> 2;
- outbuf[1] = ((inbuf[0] & 0x03) << 4) | ((inbuf[1] & 0xF0) >> 4);
- outbuf[2] = ((inbuf[1] & 0x0F) << 2) | ((inbuf[2] & 0xC0) >> 6);
- outbuf[3] = inbuf[2] & 0x3F;
-
- switch (ctremaining) {
- case 1:
- ctcopy = 2;
- break;
- case 2:
- ctcopy = 3;
- break;
- default:
- ctcopy = 4;
- break;
- }
-
- for (int i = 0; i < ctcopy; i++) {
- [result appendFormat:@"%c",encodingTable[outbuf[i]]];
- }
-
- for (int i = ctcopy; i < 4; i++) {
- [result appendString:@"="];
- }
-
- ixtext += 3;
- charsonline += 4;
-
- if (lineLength > 0) {
- if (charsonline >= lineLength) {
- charsonline = 0;
- [result appendString:@"\n"];
- }
- }
- }
- return result;
- }
- @end
|