00001
00002
00003
00004
00005
00006
00007
00008
00009 #import <CommonCrypto/CommonDigest.h>
00010 #import "TDApi.h"
00011 #import "TDApiConstants.h"
00012 #import "TDSimpleParser.h"
00013 #import "TDFoldersParser.h"
00014 #import "TDContextsParser.h"
00015 #import "TDTasksParser.h"
00016 #import "TDDeletedTasksParser.h"
00017 #import "TDNotesParser.h"
00018 #import "TDUserInfoParser.h"
00019
00020 @interface TDApi ()
00021
00022 - (BOOL)loadServerInfos;
00023 - (BOOL)loadAccountInfo;
00024 - (NSString *)getUserIdForUsername:(NSString *)aUsername andPassword:(NSString *)aPassword;
00025 - (NSURLRequest *)requestForURLString:(NSString *)anUrlString additionalParameters:(NSDictionary *)additionalParameters;
00026 - (NSURLRequest *)authenticatedRequestForURLString:(NSString *)anUrlString additionalParameters:(NSDictionary *)additionalParameters;
00027 - (void)setPasswordHashWithPassword:(NSString *)password;
00028
00029 @property (nonatomic, copy) NSString *userId;
00030 @property (nonatomic, copy) NSString *key;
00031 @property (nonatomic, copy) NSString *passwordHash;
00032 @property (nonatomic, retain) NSDate *keyValidity;
00033 @property (nonatomic, retain) NSDictionary *accountInfo;
00034
00035 @end
00036
00037
00038
00039 NSString *const GtdApiErrorDomain = @"GtdApiErrorDomain";
00040
00041
00042 @implementation TDApi
00043
00044 @synthesize userId, key, keyValidity, passwordHash, accountInfo;
00045
00046 - (void) dealloc {
00047 [passwordHash release];
00048 [keyValidity release];
00049 [key release];
00050 [userId release];
00051 [super dealloc];
00052 }
00053
00054 #pragma mark -
00055 #pragma mark GtdApi protocol implementation
00056
00057 - (id)initWithUsername:(NSString *)username password:(NSString *)password error:(NSError **)error {
00058 if (self = [super init]) {
00059 self.userId = [self getUserIdForUsername:username andPassword:password];
00060
00061
00062 if (self.userId == nil) {
00063
00064 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00065 [errorDetail setValue:@"Unknown error." forKey:NSLocalizedDescriptionKey];
00066 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:errorDetail];
00067 [self release];
00068 return nil;
00069 }
00070 else if ([userId isEqualToString:@"0"]) {
00071
00072 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00073 [errorDetail setValue:@"Missing input parameters." forKey:NSLocalizedDescriptionKey];
00074 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingCredentialsError userInfo:errorDetail];
00075 [self release];
00076 return nil;
00077 }
00078 else if ([userId isEqualToString:@"1"]) {
00079
00080 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00081 [errorDetail setValue:@"User could not be found, probably wrong credentials" forKey:NSLocalizedDescriptionKey];
00082 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiWrongCredentialsError userInfo:errorDetail];
00083 [self release];
00084 return nil;
00085 }
00086 else {
00087 [self setPasswordHashWithPassword:password];
00088
00089 [self key];
00090 [self loadServerInfos];
00091 }
00092 }
00093 return self;
00094 }
00095
00096 - (BOOL)isAuthenticated {
00097 if (key == nil || keyValidity == nil | [keyValidity compare:[NSDate date]] == NSOrderedDescending)
00098 return NO;
00099 else
00100 return YES;
00101 }
00102
00103 - (NSDictionary *)getLastModificationsDates:(NSError **)error {
00104
00105 NSDictionary *returnResult = nil;
00106
00107 if ([self loadAccountInfo] != NO) {
00108 returnResult = [NSDictionary dictionary];
00109
00110 if ([accountInfo valueForKey:@"lastaddedit"] != nil) {
00111 [returnResult setValue:[accountInfo valueForKey:@"lastaddedit"] forKey:@"lastTaskAddEdit"];
00112 }
00113 if ([accountInfo valueForKey:@"lastdelete"] != nil) {
00114 [returnResult setValue:[accountInfo valueForKey:@"lastdelete"] forKey:@"lastTaskDelete"];
00115 }
00116 if ([accountInfo valueForKey:@"lastfolderedit"] != nil) {
00117 [returnResult setValue:[accountInfo valueForKey:@"lastfolderedit"] forKey:@"lastFolderEdit"];
00118 }
00119 if ([accountInfo valueForKey:@"lastcontextedit"] != nil) {
00120 [returnResult setValue:[accountInfo valueForKey:@"lastcontextedit"] forKey:@"lastContextEdit"];
00121 }
00122 }
00123 else {
00124 *error = [NSError errorWithDomain:GtdApiErrorDomain code:-1 userInfo:nil];
00125 }
00126
00127 return returnResult;
00128 }
00129
00130
00131 #pragma mark folder actions
00132
00133 - (NSArray *)getFolders:(NSError **)error {
00134
00135 id returnResult = nil;
00136
00137 if (self.key != nil) {
00138 NSError *requestError = nil, *parseError = nil;
00139 NSURLRequest *request = [self authenticatedRequestForURLString:kGetFoldersURLFormat additionalParameters:nil];
00140 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00141
00142 if (requestError == nil) {
00143
00144 TDFoldersParser *parser = [[TDFoldersParser alloc] initWithData:responseData];
00145 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00146
00147 if (parseError != nil) {
00148
00149 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00150 }
00151 else {
00152
00153 returnResult = result;
00154 }
00155 [parser release];
00156 }
00157 else {
00158
00159 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00160 }
00161 }
00162 else {
00163
00164 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00165 }
00166
00167 return returnResult;
00168 }
00169
00170 - (NSInteger)addFolder:(GtdFolder *)aFolder error:(NSError **)error {
00171
00172 NSInteger returnResult = -1;
00173
00174
00175 if (aFolder == nil || aFolder.title == nil) {
00176 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00177 }
00178
00179 else if (self.key != nil) {
00180 NSError *requestError = nil, *parseError = nil;
00181 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:aFolder.title, @"title", (aFolder.private == NO ? 0 : 1), @"private", nil];
00182 NSURLRequest *request = [self authenticatedRequestForURLString:kAddFolderURLFormat additionalParameters:params];
00183 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00184 [params release];
00185
00186 if (requestError == nil) {
00187
00188 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00189 parser.tagName = @"added";
00190 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00191
00192 if ([result count] == 1 && parseError == nil) {
00193
00194 returnResult = [[result objectAtIndex:0] intValue];
00195 }
00196 else {
00197
00198 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiFolderNotAddedError userInfo:nil];
00199 }
00200 [parser release];
00201 }
00202 else {
00203
00204 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00205 }
00206 }
00207 else {
00208
00209 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00210 }
00211
00212 return returnResult;
00213 }
00214
00215 - (BOOL)deleteFolder:(GtdFolder *)aFolder error:(NSError **)error {
00216
00217 BOOL returnResult = NO;
00218
00219
00220 if (aFolder == nil || aFolder.uid == -1) {
00221 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00222 }
00223
00224 else if (self.key != nil) {
00225 NSError *requestError = nil, *parseError = nil;
00226 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithFormat:@"%d", aFolder.uid], @"id", nil];
00227 NSURLRequest *request = [self authenticatedRequestForURLString:kDeleteFolderURLFormat additionalParameters:params];
00228 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00229
00230 if (requestError == nil) {
00231
00232 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00233 parser.tagName = @"success";
00234 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00235
00236 if ([result count] == 1 && parseError == nil) {
00237
00238 returnResult = YES;
00239 }
00240 else {
00241
00242 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiFolderNotDeletedError userInfo:nil];
00243 }
00244 [parser release];
00245 }
00246 else {
00247
00248 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00249 }
00250 }
00251 else {
00252
00253 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00254 }
00255
00256 return returnResult;
00257 }
00258
00259 - (BOOL)editFolder:(GtdFolder *)aFolder error:(NSError **)error {
00260
00261 BOOL returnResult = NO;
00262
00263
00264 if (aFolder == nil || aFolder.uid == -1 || aFolder.title == nil) {
00265 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00266 }
00267
00268 else if (self.key != nil) {
00269 NSError *requestError = nil, *parseError = nil;
00270 NSDictionary *params = [[NSDictionary alloc] init];
00271
00272 [params setValue:aFolder.title forKey:@"key"];
00273 [params setValue:[NSString stringWithFormat:@"%d", aFolder.private] forKey:@"private"];
00274 [params setValue:[NSString stringWithFormat:@"%d", aFolder.archived] forKey:@"archived"];
00275
00276 NSURLRequest *request = [self authenticatedRequestForURLString:kEditFolderURLFormat additionalParameters:params];
00277 [params release];
00278
00279 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00280
00281 if (requestError == nil) {
00282
00283 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00284 parser.tagName = @"success";
00285 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00286
00287 if ([result count] == 1 && parseError == nil) {
00288
00289 returnResult = YES;
00290 }
00291 else {
00292
00293 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiFolderNotEditedError userInfo:nil];
00294 }
00295 [parser release];
00296 }
00297 else {
00298
00299 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00300 }
00301 }
00302 else {
00303
00304 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00305 }
00306
00307 return returnResult;
00308 }
00309
00310
00311 #pragma mark task actions
00312
00313 - (NSArray *)getTasks:(NSError **)error {
00314
00315 id returnResult = nil;
00316
00317 if (self.key != nil) {
00318
00319 NSError *requestError = nil, *parseError = nil;
00320 NSURLRequest *request = [self authenticatedRequestForURLString:kGetTasksURLFormat additionalParameters:nil];
00321 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00322
00323 if (requestError == nil) {
00324
00325 TDTasksParser *parser = [[TDTasksParser alloc] initWithData:responseData];
00326 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00327
00328 if(parseError != nil)
00329 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00330 else {
00331
00332 returnResult = result;
00333 }
00334 [parser release];
00335 }
00336 else
00337 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00338 }
00339 else
00340 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00341 return returnResult;
00342 }
00343
00344 - (NSArray *)getDeleted:(NSError **)error {
00345
00346 id returnResult = nil;
00347
00348 if (self.key != nil) {
00349 NSError *requestError = nil, *parseError = nil;
00350 NSURLRequest *request = [self authenticatedRequestForURLString:kGetDeletedTasksURLFormat additionalParameters:nil];
00351 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00352
00353 if (requestError == nil) {
00354
00355 TDDeletedTasksParser *parser = [[TDDeletedTasksParser alloc] initWithData:responseData];
00356 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00357
00358 if(parseError != nil)
00359 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00360 else {
00361
00362 returnResult = result;
00363 }
00364 [parser release];
00365 }
00366 else
00367 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00368 }
00369 else
00370 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00371 return returnResult;
00372 }
00373
00374
00375 - (NSInteger)addTask:(GtdTask *)aTask error:(NSError **)error {
00376
00377 NSInteger returnResult = -1;
00378
00379
00380 if (aTask == nil || aTask.uid == -1 || aTask.title == nil)
00381 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00382
00383 else if (self.key != nil) {
00384 NSError *requestError = nil, *parseError = nil;
00385 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:
00386 aTask.title, @"title",
00387 aTask.tag, @"tag",
00388 aTask.folder, @"folder",
00389 aTask.context, @"context",
00390
00391
00392 aTask.date_due, @"dueDate",
00393 aTask.date_start, @"startDate",
00394
00395
00396 aTask.reminder, @"reminder",
00397 aTask.repeat, @"repeat",
00398
00399 aTask.status, @"status",
00400 aTask.length, @"length",
00401 aTask.priority, @"priority",
00402 aTask.star, @"star",
00403 aTask.note, @"note",
00404 nil
00405 ];
00406 NSURLRequest *request = [self authenticatedRequestForURLString:kAddTaskURLFormat additionalParameters:params];
00407 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00408 [params release];
00409
00410 if (requestError == nil) {
00411
00412 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00413 parser.tagName = @"added";
00414 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00415
00416 if ([result count] == 1 && parseError == nil) {
00417
00418 returnResult = [[result objectAtIndex:0] intValue];
00419 }
00420 else
00421 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00422 [parser release];
00423 }
00424 else
00425 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00426 }
00427 else
00428 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00429 return returnResult;
00430 }
00431
00432 - (BOOL)editTask:(GtdTask *)aTask error:(NSError **)error {
00433
00434 BOOL returnResult = NO;
00435
00436
00437 if (aTask == nil || aTask.uid == -1 || aTask.title == nil)
00438 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00439
00440 else if (self.key != nil) {
00441 NSError *requestError = nil, *parseError = nil;
00442 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:
00443 [NSString stringWithFormat:@"%d", aTask.uid], @"id",
00444 aTask.title, @"title",
00445 aTask.tag, @"tag",
00446 aTask.folder, @"folder",
00447 aTask.context, @"context",
00448
00449
00450
00451
00452 aTask.completed, @"completed",
00453
00454
00455 aTask.date_due, @"dueDate",
00456 aTask.date_start, @"startDate",
00457
00458
00459 aTask.reminder, @"reminder",
00460 aTask.repeat, @"repeat",
00461
00462 aTask.status, @"status",
00463 aTask.length, @"length",
00464 aTask.priority, @"priority",
00465 aTask.star, @"star",
00466 aTask.note, @"note",
00467 nil
00468 ];
00469 NSURLRequest *request = [self authenticatedRequestForURLString:kEditTaskURLFormat additionalParameters:params];
00470 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00471
00472 [params release];
00473
00474 if (requestError == nil) {
00475
00476 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00477 parser.tagName = @"success";
00478 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00479
00480 if ([result count] == 1 && parseError == nil) {
00481
00482 returnResult = YES;
00483 }
00484 else
00485 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00486 [parser release];
00487 }
00488 else
00489 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00490 }
00491 else
00492 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00493 return returnResult;
00494 }
00495
00496 - (BOOL)deleteTask:(GtdTask *)aTask error:(NSError **)error {
00497
00498
00499 BOOL returnResult = NO;
00500
00501
00502 if (aTask == nil || aTask.uid == -1 || aTask.title == nil)
00503 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00504
00505 else if (self.key != nil) {
00506
00507 NSError *requestError = nil, *parseError = nil;
00508 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithFormat:@"%d", aTask.uid], @"id", nil];
00509 NSURLRequest *request = [self authenticatedRequestForURLString:kDeleteTaskURLFormat additionalParameters:params];
00510 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00511
00512 if (requestError == nil) {
00513
00514 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00515 parser.tagName = @"success";
00516 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00517
00518 if ([result count] == 1 && parseError == nil) {
00519
00520 returnResult = YES;
00521 }
00522 else
00523 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00524 }
00525 else
00526 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00527 }
00528 else
00529 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00530 return returnResult;
00531 }
00532
00533
00534 #pragma mark context actions
00535
00536 - (NSInteger)addContext:(GtdContext *)aContext error:(NSError **)error {
00537
00538
00539
00540 if ([self isAuthenticated]) {
00541
00542 NSError *requestError = nil, *parseError = nil;
00543 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:aContext.title, @"title", nil];
00544 NSURLRequest *request = [self authenticatedRequestForURLString:kAddContextURLFormat additionalParameters:params];
00545 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00546
00547 if (requestError == nil) {
00548
00549 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00550 parser.tagName = @"added";
00551 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00552 [parser release];
00553
00554 if ([result count] == 1) {
00555 return [[result objectAtIndex:0] intValue];
00556 }
00557 else {
00558 return -1;
00559 }
00560 }
00561 else {
00562
00563 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00564 [errorDetail setValue:[requestError localizedDescription] forKey:NSLocalizedDescriptionKey];
00565 *error = [NSError errorWithDomain:GtdApiErrorDomain code:-2 userInfo:errorDetail];
00566 return -1;
00567 }
00568 }
00569 else {
00570
00571 return -1;
00572 }
00573 }
00574
00575 - (NSArray *)getContexts:(NSError **)error {
00576
00577 if ([self isAuthenticated]) {
00578
00579 NSError *requestError = nil, *parseError = nil;
00580 NSURLRequest *request = [self authenticatedRequestForURLString:kGetContextsURLFormat additionalParameters:nil];
00581 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00582
00583 if (requestError == nil) {
00584
00585 TDContextsParser *parser = [[TDContextsParser alloc] initWithData:responseData];
00586 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00587 [parser release];
00588 return result;
00589 }
00590 else {
00591
00592 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00593 [errorDetail setValue:[requestError localizedDescription] forKey:NSLocalizedDescriptionKey];
00594 *error = [NSError errorWithDomain:GtdApiErrorDomain code:-2 userInfo:errorDetail];
00595 return nil;
00596 }
00597 }
00598 else {
00599
00600 return nil;
00601 }
00602 }
00603
00604 - (BOOL)deleteContext:(GtdContext *)aContext error:(NSError **)error {
00605
00606
00607
00608 if ([self isAuthenticated]) {
00609
00610 NSError *requestError = nil, *parseError = nil;
00611 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithFormat:@"%d", aContext.contextId], @"id", nil];
00612 NSURLRequest *request = [self authenticatedRequestForURLString:kDeleteContextURLFormat additionalParameters:params];
00613 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00614
00615 if (requestError == nil) {
00616
00617 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00618 parser.tagName = @"success";
00619 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00620 [parser release];
00621 if ([result count] == 1) {
00622 if ([[result objectAtIndex:0] intValue] == 1)
00623 return YES;
00624 else
00625 return NO;
00626
00627 }
00628 else {
00629 return NO;
00630
00631 }
00632 }
00633 else {
00634
00635 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00636 [errorDetail setValue:[requestError localizedDescription] forKey:NSLocalizedDescriptionKey];
00637 *error = [NSError errorWithDomain:GtdApiErrorDomain code:-2 userInfo:errorDetail];
00638 return -1;
00639 }
00640 }
00641 else {
00642
00643 return -1;
00644 }
00645 }
00646
00647
00648 #pragma mark notes actions
00649
00650 - (NSArray *)getNotes:(NSError **)error {
00651
00652 id returnResult = nil;
00653
00654 if (self.key != nil) {
00655 NSError *requestError = nil, *parseError = nil;
00656 NSURLRequest *request = [self authenticatedRequestForURLString:kGetNotesURLFormat additionalParameters:nil];
00657 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00658
00659 if (requestError == nil) {
00660
00661
00662 TDNotesParser *parser = [[TDNotesParser alloc] initWithData:responseData];
00663 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00664
00665 if (parseError != nil) {
00666
00667 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00668 [errorDetail setValue:@"Api data error." forKey:NSLocalizedDescriptionKey];
00669 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:errorDetail];
00670 }
00671 else {
00672
00673 returnResult = result;
00674 }
00675 [parser release];
00676 }
00677 else {
00678
00679 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00680 [errorDetail setValue:[requestError localizedDescription] forKey:NSLocalizedDescriptionKey];
00681 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:errorDetail];
00682 }
00683 }
00684 else {
00685
00686 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00687 [errorDetail setValue:@"Api Error, no valid key." forKey:NSLocalizedDescriptionKey];
00688 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:errorDetail];
00689 }
00690
00691 return returnResult;
00692 }
00693
00694
00695
00696 - (BOOL)deleteNote:(GtdNote *)aNote error:(NSError **)error
00697 {
00698
00699
00700 BOOL returnResult = NO;
00701
00702
00703 if (aNote.uid == -1)
00704 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiMissingParameters userInfo:nil];
00705
00706 else if (self.key != nil) {
00707
00708 NSError *requestError = nil, *parseError = nil;
00709 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:[NSString stringWithFormat:@"%d", aNote.uid], @"id", nil];
00710 NSURLRequest *request = [self authenticatedRequestForURLString:kDeleteNotesURLFormat additionalParameters:params];
00711 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00712
00713 if (requestError == nil) {
00714
00715 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00716 parser.tagName = @"success";
00717 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00718
00719 if ([result count] == 1 && parseError == nil) {
00720
00721 returnResult = YES;
00722 }
00723 else
00724 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00725 }
00726 else
00727 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiNotReachableError userInfo:nil];
00728 }
00729 else
00730 *error = [NSError errorWithDomain:GtdApiErrorDomain code:GtdApiDataError userInfo:nil];
00731 return returnResult;
00732
00733 }
00734
00735
00736
00737 - (NSInteger)addNote:(GtdNote *)aNote error:(NSError **)error
00738 {
00739
00740
00741 if ([self isAuthenticated]) {
00742
00743 NSError *requestError = nil, *parseError = nil;
00744 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:
00745
00746 aNote.title, @"title",
00747 aNote.text, @"text",
00748 aNote.folder, @"folder",
00749 aNote.private, @"private", nil ];
00750
00751
00752
00753 NSURLRequest *request = [self authenticatedRequestForURLString:kAddNotesURLFormat additionalParameters:params];
00754 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00755
00756 if (requestError == nil) {
00757
00758 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00759 parser.tagName = @"added";
00760 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00761 [parser release];
00762
00763 if ([result count] == 1) {
00764 return [[result objectAtIndex:0] intValue];
00765 }
00766 else {
00767 return -1;
00768 }
00769 }
00770 else {
00771
00772 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00773 [errorDetail setValue:[requestError localizedDescription] forKey:NSLocalizedDescriptionKey];
00774 *error = [NSError errorWithDomain:GtdApiErrorDomain code:-2 userInfo:errorDetail];
00775 return -1;
00776 }
00777 }
00778 else {
00779
00780 return -1;
00781 }
00782
00783 }
00784
00785
00786 - (BOOL)editNote:(GtdNote *)aNote error:(NSError **)error
00787 {
00788
00789
00790 if ([self isAuthenticated]) {
00791
00792 NSError *requestError = nil, *parseError = nil;
00793 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:
00794 [NSString stringWithFormat:@"%d", aNote.uid], @"id",
00795 aNote.title, @"title",
00796 aNote.text, @"text",
00797 aNote.folder, @"folder",
00798 aNote.private, @"private", nil ];
00799
00800
00801
00802 NSURLRequest *request = [self authenticatedRequestForURLString:kAddNotesURLFormat additionalParameters:params];
00803 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00804
00805 if (requestError == nil) {
00806
00807 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00808 parser.tagName = @"success";
00809 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00810 [parser release];
00811
00812 if ([result count] == 1 && parseError == nil) {
00813
00814 return YES;
00815 }
00816 else {
00817 return -1;
00818 }
00819 }
00820 else {
00821
00822 NSMutableDictionary *errorDetail = [NSMutableDictionary dictionary];
00823 [errorDetail setValue:[requestError localizedDescription] forKey:NSLocalizedDescriptionKey];
00824 *error = [NSError errorWithDomain:GtdApiErrorDomain code:-2 userInfo:errorDetail];
00825 return NO;
00826 }
00827 }
00828 else {
00829
00830 return NO;
00831 }
00832 }
00833
00834
00835 #pragma mark -
00836 #pragma mark helper methods
00837
00838
00839 - (BOOL)loadServerInfos {
00840
00841 if ([self isAuthenticated]) {
00842 NSError *parseError = nil;
00843 NSURLRequest *request = [self authenticatedRequestForURLString:kServerInfoURLFormat additionalParameters:nil];
00844 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
00845
00846 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00847 parser.tagName = @"unixtime";
00848 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00849 [parser release];
00850
00851 if ([result count] == 1) {
00852 NSDate *serverDate = [NSDate dateWithTimeIntervalSince1970:[[result objectAtIndex:0] doubleValue]];
00853 servertimeDifference = [serverDate timeIntervalSinceNow];
00854 [serverDate release];
00855 DLog(@"Server infos retrieved, servertime difference: %f.", servertimeDifference);
00856 return YES;
00857 }
00858 else {
00859 DLog(@"Could not fetch server infos.");
00860 return NO;
00861 }
00862 }
00863 else {
00864 return NO;
00865 }
00866 }
00867
00868 - (BOOL)loadAccountInfo {
00869
00870 BOOL returnResult = NO;
00871
00872 if (self.key != nil) {
00873 NSError *requestError = nil, *parseError = nil;
00874 NSURLRequest *request = [self authenticatedRequestForURLString:kGetFoldersURLFormat additionalParameters:nil];
00875 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&requestError];
00876
00877 if (requestError == nil) {
00878
00879 TDUserInfoParser *parser = [[TDUserInfoParser alloc] initWithData:responseData];
00880 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00881
00882 if (parseError == nil) {
00883 self.accountInfo = [result objectAtIndex:0];
00884 returnResult = YES;
00885 }
00886 [parser release];
00887 }
00888 }
00889 return returnResult;
00890 }
00891
00892
00893 - (NSString *)getUserIdForUsername:(NSString *)aUsername andPassword:(NSString *)aPassword {
00894
00895
00896 NSError *parseError = nil;
00897 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:aUsername, @"email", aPassword, @"pass", nil];
00898 NSURLRequest *request = [self requestForURLString:kUserIdURLFormat additionalParameters:params];
00899 [params release];
00900 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
00901
00902 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00903 parser.tagName = @"userid";
00904 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00905 [parser release];
00906
00907 if ([result count] == 1) {
00908 DLog(@"Got user id: %@", [result objectAtIndex:0]);
00909 return [result objectAtIndex:0];
00910 }
00911 else {
00912 DLog(@"Could not fetch user id.");
00913 return nil;
00914 }
00915
00916 }
00917
00918
00919 - (NSString *)key {
00920 if (key == nil || keyValidity == nil | [keyValidity compare:[NSDate date]] == NSOrderedDescending) {
00921
00922 NSError *parseError = nil;
00923
00924
00925 NSDictionary *params = [[NSDictionary alloc] initWithObjectsAndKeys:userId, @"userid", @"welldone", @"appid", nil];
00926 NSURLRequest *request = [self requestForURLString:kAuthenticationURLFormat additionalParameters:params];
00927 [params release];
00928
00929 NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
00930
00931 TDSimpleParser *parser = [[TDSimpleParser alloc] initWithData:responseData];
00932 parser.tagName = @"token";
00933 NSArray *result = [[[parser parseResults:&parseError] retain] autorelease];
00934 [parser release];
00935
00936 if ([result count] == 1) {
00937 NSString *token = [result objectAtIndex:0];
00938 DLog(@"New token: %@", token);
00939
00940 const char *cStr = [[NSString stringWithFormat:@"%@%@%@", passwordHash, token, userId] UTF8String];
00941 unsigned char result[CC_MD5_DIGEST_LENGTH];
00942
00943 CC_MD5(cStr, strlen(cStr), result);
00944
00945 self.key = [[NSString stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
00946 result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]] lowercaseString];
00947 self.keyValidity = [NSDate date];
00948 DLog(@"Loaded new key: %@", key);
00949 }
00950 else {
00951 self.key = nil;
00952 }
00953 }
00954 return key;
00955 }
00956
00957
00958 - (void)setPasswordHashWithPassword:(NSString *)password {
00959 const char *cStr = [password UTF8String];
00960 unsigned char result[CC_MD5_DIGEST_LENGTH];
00961
00962 CC_MD5(cStr, strlen(cStr), result);
00963
00964 self.passwordHash = [[NSString stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
00965 result[0], result[1], result[2], result[3], result[4], result[5], result[6], result[7], result[8], result[9], result[10], result[11], result[12], result[13], result[14], result[15]] lowercaseString];
00966 }
00967
00968
00969 - (NSURLRequest *)authenticatedRequestForURLString:(NSString *)anUrlString additionalParameters:(NSDictionary *)additionalParameters {
00970
00971
00972 NSMutableString *params = [[NSMutableString alloc] initWithFormat:@"%@key=%@;", anUrlString, self.key];
00973 for (NSString *paramKey in additionalParameters)
00974 [params appendFormat:@"%@=%@;", paramKey, [additionalParameters objectForKey:paramKey]];
00975
00976
00977
00978 NSURL *url = [[NSURL alloc] initWithString:params];
00979 [params release];
00980
00981 NSURLRequest *request = [[[NSURLRequest alloc] initWithURL:url] autorelease];
00982 [url release];
00983
00984 DLog(@"Created request with url: %@", [[request URL] absoluteString]);
00985
00986 return request;
00987 }
00988
00989
00990 - (NSURLRequest *)requestForURLString:(NSString *)anUrlString additionalParameters:(NSDictionary *)additionalParameters {
00991
00992
00993 NSMutableString *params = [[NSMutableString alloc] initWithString:anUrlString];
00994 for (NSString *paramKey in additionalParameters)
00995 [params appendFormat:@"%@=%@;", paramKey, [additionalParameters valueForKey:paramKey]];
00996
00997
00998
00999 NSURL *url = [[NSURL alloc] initWithString:params];
01000 [params release];
01001 NSURLRequest *request = [[[NSURLRequest alloc] initWithURL:url] autorelease];
01002 [url release];
01003
01004 DLog(@"Created request with url: %@", [[request URL] absoluteString]);
01005
01006 return request;
01007 }
01008
01009 @end