00001
00002
00003
00004
00005
00006
00007
00008
00009 #import "DropIO.h"
00010 #import "XMLToObjectParser.h"
00011
00017 @implementation NSString (httpFormEncoding)
00018
00023 - (NSString*)stringUsingHTTPFormEncoding
00024 {
00025 NSString *result = (NSString *) CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)self, NULL, CFSTR("?=&+"), kCFStringEncodingUTF8);
00026 return [result autorelease];
00027 }
00028
00029 @end
00030
00037 @implementation NSMutableURLRequest (httpFormEncoding)
00038
00047 - (void) setHTTPPostBody:(NSDictionary*)postParams
00048 {
00049 NSMutableString* postBody = [[NSMutableString alloc] init];
00050 NSUInteger keyCount = [postParams count];
00051 NSUInteger k = 0;
00052 for (id key in postParams)
00053 {
00054 [postBody appendFormat:@"%@=%@", key, [[postParams objectForKey:key] stringUsingHTTPFormEncoding]];
00055 if (++k != keyCount)
00056 [postBody appendString:@"&"];
00057 }
00058
00059 NSLog(@"HTTP POST Data: %@", postBody);
00060
00061 NSData* postData = [postBody dataUsingEncoding:NSASCIIStringEncoding];
00062 NSString* postLength = [NSString stringWithFormat:@"%d", [postData length]];
00063 [self setHTTPBody:postData];
00064 [self setValue:postLength forHTTPHeaderField:@"Content-Length"];
00065 [self setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
00066
00067 [postBody release];
00068 }
00069
00070 @end
00071
00076 @implementation DropIO
00077
00078 static NSString* apiKey = nil;
00079 static NSError* lastError = nil;
00090 + (void) setAPIKey:(NSString*)aKey
00091 {
00092 [aKey retain];
00093 [apiKey release];
00094 apiKey = aKey;
00095 }
00096
00102 + (NSString*) APIKey
00103 {
00104 return apiKey;
00105 }
00106
00115 + (BOOL) checkAPIKey
00116 {
00117 if (apiKey == nil)
00118 {
00119 NSLog(@"Error: DropIO API key not set.");
00120 return false;
00121 }
00122 return true;
00123 }
00124
00139 + (NSError*) lastError
00140 {
00141 return lastError;
00142 }
00143
00153 + (void) setLastError:(NSError*)dropioError
00154 {
00155 if (dropioError != lastError)
00156 {
00157 [dropioError retain];
00158 [lastError release];
00159 lastError = dropioError;
00160 }
00161 }
00162
00171 + (void) errorHandler:(NSError*)error
00172 {
00173 if (error != nil)
00174 {
00175 [DropIO setLastError:error];
00176
00177 if (![[[error userInfo] objectForKey:kDropIOErrorResult] isEqualToString:kDropIOErrorResult_Success])
00178 {
00179 NSLog(@"Error: %@", error);
00180 for (id key in [error userInfo])
00181 {
00182 NSLog(@" %@: %@", key, [[error userInfo] valueForKey:key]);
00183 }
00184 }
00185 }
00186 }
00187
00215 + (NSArray*) parseResponseFromURL:(NSURL*)url
00216 fromNodeName:(NSString *)nodeName
00217 toObject:(NSString *)className
00218 parseError:(NSError **)error
00219 {
00220
00221 [DropIO setLastError:nil];
00222
00223 XMLToObjectParser* x2o = [[XMLToObjectParser alloc] init];
00224 [x2o parseXMLAtURL:url
00225 fromNodeName:nodeName
00226 toObject:className
00227 parseError:error];
00228 if (error != nil && (*error) != nil)
00229 {
00230 [DropIO errorHandler:*error];
00231 }
00232
00233 NSArray* result = [x2o items];
00234 [[result retain] autorelease];
00235 [x2o release];
00236 return result;
00237 }
00238
00266 + (NSArray*) parseResponse:(NSData*)responseData
00267 fromNodeName:(NSString *)nodeName
00268 toObject:(NSString *)className
00269 parseError:(NSError **)error
00270 {
00271
00272 [DropIO setLastError:nil];
00273
00274 XMLToObjectParser* x2o = [[XMLToObjectParser alloc] init];
00275 [x2o parseXMLData:responseData
00276 fromNodeName:nodeName
00277 toObject:className
00278 parseError:error];
00279 if (error != nil && (*error) != nil)
00280 {
00281 [DropIO errorHandler:*error];
00282 }
00283
00284 NSArray* result = [x2o items];
00285 [[result retain] autorelease];
00286 [x2o release];
00287 return result;
00288 }
00289
00307 + (DropIODrop*) dropOperation:(NSString*)opString atUrl:(NSString*)urlStr withParameters:(NSDictionary*)params
00308 {
00309
00310 [DropIO setLastError:nil];
00311
00312 if (![DropIO checkAPIKey])
00313 return nil;
00314
00315
00316 NSMutableURLRequest* dropReq = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:urlStr]];
00317 [dropReq setHTTPMethod:opString];
00318 [dropReq setHTTPPostBody:params];
00319
00320
00321 NSURLResponse* dropResp = nil;
00322 NSError* error = nil;
00323 NSData* dropXmlData = [NSURLConnection sendSynchronousRequest:dropReq
00324 returningResponse:&dropResp
00325 error:&error];
00326 if (error != nil)
00327 {
00328 NSLog(@"HTTP %@ Error: %@", opString, error);
00329 [DropIO setLastError:error];
00330 return nil;
00331 }
00332
00333
00334 DropIODrop* drop = nil;
00335 NSArray* dropArray = [self parseResponse:dropXmlData
00336 fromNodeName:@"drop"
00337 toObject:@"DropIODrop"
00338 parseError:&error];
00339 if ((dropArray == nil) || ([dropArray count] == 0))
00340 return nil;
00341
00342 drop = [dropArray objectAtIndex:0];
00343 return [[drop retain] autorelease];
00344 }
00345
00356 + (DropIODrop*) dropWithParameters:(NSDictionary*)params
00357 {
00358 return [DropIO dropOperation:@"POST"
00359 atUrl:kDropIONewDropUrl
00360 withParameters:params];
00361 }
00362
00374 + (void) updateDropNamed:(NSString*)dropName withParameters:(NSDictionary*)params
00375 {
00376 [DropIO dropOperation:@"PUT"
00377 atUrl:[NSString stringWithFormat:kDropIOUpdateDropUrlFormat, dropName]
00378 withParameters:params];
00379 }
00380
00392 + (void) deleteDropNamed:(NSString*)dropName withParameters:(NSDictionary*)params
00393 {
00394 [DropIO dropOperation:@"DELETE"
00395 atUrl:[NSString stringWithFormat:kDropIOUpdateDropUrlFormat, dropName]
00396 withParameters:params];
00397 }
00398
00405 + (DropIODrop*) dropWithRandomName
00406 {
00407 if (![DropIO checkAPIKey])
00408 return nil;
00409
00410 NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:3];
00411 [params setObject:kDropIOParamValue_Format_XML forKey:kDropIOParamKey_Format];
00412 [params setObject:kDropIOParamValue_Version_Latest forKey:kDropIOParamKey_Version];
00413 [params setObject:apiKey forKey:kDropIOParamKey_APIKey];
00414
00415 return [DropIO dropWithParameters:params];
00416 }
00417
00427 + (DropIODrop*) dropWithName:(NSString*)aName
00428 {
00429 if (![DropIO checkAPIKey])
00430 return nil;
00431
00432 NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:4];
00433 [params setObject:kDropIOParamValue_Format_XML forKey:kDropIOParamKey_Format];
00434 [params setObject:kDropIOParamValue_Version_Latest forKey:kDropIOParamKey_Version];
00435 [params setObject:apiKey forKey:kDropIOParamKey_APIKey];
00436 [params setObject:aName forKey:kDropIOParamKey_Name];
00437
00438 return [DropIO dropWithParameters:params];
00439 }
00440
00453 + (DropIODrop*) dropWithName:(NSString*)aName andPassword:(NSString*)aPassword
00454 {
00455 if (![DropIO checkAPIKey])
00456 return nil;
00457
00458 NSMutableDictionary* params = [NSMutableDictionary dictionaryWithCapacity:5];
00459 [params setObject:kDropIOParamValue_Format_XML forKey:kDropIOParamKey_Format];
00460 [params setObject:kDropIOParamValue_Version_Latest forKey:kDropIOParamKey_Version];
00461 [params setObject:apiKey forKey:kDropIOParamKey_APIKey];
00462 [params setObject:aName forKey:kDropIOParamKey_Name];
00463 [params setObject:aPassword forKey:kDropIOParamKey_AdminPassword];
00464
00465 return [DropIO dropWithParameters:params];
00466 }
00467
00479 + (NSURL*) URLForDropNamed:(NSString*)dropName withToken:(NSString*)aToken
00480 {
00481 if (![DropIO checkAPIKey])
00482 return nil;
00483
00484 NSString* urlStr = [NSString stringWithFormat:kDropIODropUrlFormat,
00485 dropName,
00486 kDropIOParamKey_APIKey, [DropIO APIKey],
00487 kDropIOParamKey_Format, kDropIOParamValue_Format_XML,
00488 kDropIOParamKey_Version, kDropIOParamValue_Version_Latest,
00489 kDropIOParamKey_Token, aToken];
00490 return [NSURL URLWithString:urlStr];
00491 }
00492
00506 + (DropIODrop*) findDropNamed:(NSString*)aName error:(NSError**)pError
00507 {
00508 return [DropIO findDropNamed:aName withToken:@"" error:pError];
00509 }
00510
00528 + (DropIODrop*) findDropNamed:(NSString*)aName withToken:(NSString*)aToken error:(NSError**)pError
00529 {
00530 return [DropIO findDropAtAPIURL:[DropIO URLForDropNamed:aName withToken:aToken] error:pError];
00531 }
00532
00546 + (DropIODrop*) findDropAtAPIURL:(NSURL*)dropAPIURL error:(NSError**)pError
00547 {
00548 DropIODrop* drop = nil;
00549 NSArray* dropArray = [self parseResponseFromURL:dropAPIURL
00550 fromNodeName:@"drop"
00551 toObject:@"DropIODrop"
00552 parseError:pError];
00553 if ((dropArray == nil) || ([dropArray count] == 0))
00554 return nil;
00555
00556 drop = [dropArray objectAtIndex:0];
00557 return [[drop retain] autorelease];
00558 }
00559
00573 + (DropIODrop*) findDropAtDropURL:(NSURL*)dropURL error:(NSError**)pError
00574 {
00575 NSString* dropUrlStr = [dropURL absoluteString];
00576 NSRange r = [dropUrlStr rangeOfString:@"http://drop.io/"];
00577 if (r.location == NSNotFound)
00578 r = [dropUrlStr rangeOfString:@"http://www.drop.io/"];
00579
00580 if (r.location != NSNotFound)
00581 {
00582 NSRange nameRange = NSMakeRange(r.location + r.length, 0);
00583 NSRange qRange = [dropUrlStr rangeOfString:@"?"];
00584 if (qRange.location != NSNotFound)
00585 nameRange.length = qRange.location - nameRange.location;
00586 else
00587 nameRange.length = [dropUrlStr length] - nameRange.location;
00588 NSString* dropName = [dropUrlStr substringWithRange:nameRange];
00589
00590
00591
00592 if (![dropName isEqualToString:@"faq"])
00593 return [DropIO findDropNamed:dropName error:pError];
00594 }
00595
00596 if (pError != nil)
00597 {
00598 NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
00599 @"Given URL is not a Drop.io drop URL", NSLocalizedFailureReasonErrorKey,
00600 dropURL, kDropIOErrorAPIURL,
00601 nil];
00602 *pError = [NSError errorWithDomain:kDropIOErrorDomain code:kDropIOErrorCode_NotDropURL userInfo:dict];
00603 }
00604 return nil;
00605 }
00606
00607 @end