From 4371dba9a1bf9ce2ef2c4b7cee21511daaffac5e Mon Sep 17 00:00:00 2001 From: Wolfgang Sourdeau Date: Mon, 22 Sep 2008 21:31:42 +0000 Subject: [PATCH] Monotone-Parent: 6b7485d7999f592e4a4b077024f47c2323c3fdbc Monotone-Revision: d47c52bbe608df33a336ba2d63dad8b7524aa9d7 Monotone-Author: wsourdeau@inverse.ca Monotone-Date: 2008-09-22T21:31:42 Monotone-Branch: ca.inverse.sogo --- ChangeLog | 20 ++ SoObjects/Mailer/SOGoMailFolder.h | 1 + SoObjects/Mailer/SOGoMailFolder.m | 47 +++++ SoObjects/Mailer/SOGoMailManager.h | 60 +----- SoObjects/Mailer/SOGoMailManager.m | 300 +++-------------------------- SoObjects/Mailer/SOGoMailObject.h | 1 - SoObjects/Mailer/SOGoMailObject.m | 44 ----- UI/MailerUI/UIxMailActions.m | 11 -- UI/MailerUI/UIxMailFolderActions.m | 33 +--- UI/MailerUI/product.plist | 5 - 10 files changed, 107 insertions(+), 415 deletions(-) diff --git a/ChangeLog b/ChangeLog index b3775fc66..5c0d4104c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2008-09-22 Ludovic Marcotte + + * UI/MailerUI/UIxMailFolderActions.m ([UIxMailFolderActions + -deleteMessagesAction]): make use of the new SOGoFolder's + deleteUIDs:inContext: method described below. + + * UI/MailerUI/UIxMailActions.m ([-trashAction]): removed web method. + + * SoObjects/Mailer/SOGoMailObject.m ([-trashInContext:_ctx]): + removed method, obsoleted by the new "deletedUIDS:..." method + described below. + + * SoObjects/Mailer/SOGoMailManager.[hm]: removed all methods + except -copyMailURL:srcurltoFolderURL:desturlpassword:pwd, which + is the only one still used. + + * SoObjects/Mailer/SOGoMailFolder.m ([SOGoMailFolder + -deleteUIDs:uidsinContext:localContext]): new method enabling the + deletion of many IMAP uids in one batch. + 2008-09-22 Wolfgang Sourdeau * SoObjects/Appointments/SOGoAppointmentFolder.m diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index 49e1fe654..839a36084 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -54,6 +54,7 @@ typedef enum { - (NSString *) absoluteImap4Name; /* messages */ +- (NSException *) deleteUIDs: (NSArray *) uids inContext: (id) context; - (NSArray *) fetchUIDsMatchingQualifier: (id)_q sortOrdering: (id) _so; - (NSArray *) fetchUIDs: (NSArray *) _uids parts: (NSArray *) _parts; diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 0fabcc1a6..4c903d63d 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -255,6 +255,53 @@ static BOOL aclConformsToIMAPExt = NO; } /* messages */ +- (NSException *) deleteUIDs: (NSArray *) uids + inContext: (id) localContext +{ + SOGoMailFolder *trashFolder; + id result; + NSException *error; + NSString *folderName; + NGImap4Client *client; + + // TODO: check for safe HTTP method + trashFolder = [[self mailAccountFolder] trashFolderInContext: localContext]; + if ([trashFolder isNotNull]) + { + if ([trashFolder isKindOfClass: [NSException class]]) + error = (NSException *) trashFolder; + else + { + client = [[self imap4Connection] client]; + folderName = [[self imap4Connection] + imap4FolderNameForURL: [trashFolder imap4URL]]; + result = [client copyUids: uids toFolder: folderName]; + if ([[result valueForKey: @"result"] boolValue]) + { + result = [client storeFlags: [NSArray arrayWithObject: @"Deleted"] + forUIDs: uids addOrRemove: YES]; + if ([[result valueForKey: @"result"] boolValue]) + { + [self markForExpunge]; + [trashFolder flushMailCaches]; + error = nil; + } + else + error + = [NSException exceptionWithHTTPStatus:500 + reason: @"Could not mark UIDs as Deleted"]; + } + else + error = [NSException exceptionWithHTTPStatus:500 + reason: @"Could not copy UIDs"]; + } + } + else + error = [NSException exceptionWithHTTPStatus: 500 + reason: @"Did not find Trash folder!"]; + + return error; +} - (NSArray *) fetchUIDsMatchingQualifier: (id) _q sortOrdering: (id) _so diff --git a/SoObjects/Mailer/SOGoMailManager.h b/SoObjects/Mailer/SOGoMailManager.h index 0e900e4ad..fdd743656 100644 --- a/SoObjects/Mailer/SOGoMailManager.h +++ b/SoObjects/Mailer/SOGoMailManager.h @@ -22,8 +22,6 @@ #ifndef __Mailer_SOGoMailManager_H__ #define __Mailer_SOGoMailManager_H__ -#import -#import #include /* @@ -32,61 +30,15 @@ Legacy methods, the methods were used prior the move to NGImap4. */ -@class NSString, NSData, NSURL, NSArray, NSMutableDictionary, NSTimer; -@class NSDictionary; @class NSException; -@class NGImap4Client; +@class NSString; +@class NSURL; -@interface NGImap4ConnectionManager(SOGoMailManager) +@interface NGImap4ConnectionManager (SOGoMailManager) -/* folder hierarchy */ - -- (NSArray *)subfoldersForURL:(NSURL *)_url password:(NSString *)_pwd; -- (NSArray *)allFoldersForURL:(NSURL *)_url password:(NSString *)_pwd; - -/* messages */ - -- (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_q - sortOrdering:(id)_so password:(NSString *)_pwd; -- (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url - parts:(NSArray *)_parts password:(NSString *)_pwd; - -- (NSException *)expungeAtURL:(NSURL *)_url password:(NSString *)_pwd; - -/* individual message */ - -- (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts password:(NSString *)_pwd; - -- (NSData *)fetchContentOfBodyPart:(NSString *)_partId - atURL:(NSURL *)_url password:(NSString *)_pwd; - -- (NSException *)addFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p; -- (NSException *)removeFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p; -- (NSException *)markURLDeleted:(NSURL *)_u password:(NSString *)_p; - -- (NSException *)postData:(NSData *)_data flags:(id)_flags - toFolderURL:(NSURL *)_url password:(NSString *)_p; - -- (NSException *)copyMailURL:(NSURL *)_srcurl toFolderURL:(NSURL *)_desturl - password:(NSString *)_pwd; - -/* managing folders */ - -- (BOOL)doesMailboxExistAtURL:(NSURL *)_url password:(NSString *)_pwd; -- (id)infoForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd; - -- (NSException *)createMailbox:(NSString *)_mailbox atURL:(NSURL *)_url - password:(NSString *)_pwd; -- (NSException *)deleteMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd; - -- (NSException *)moveMailboxAtURL:(NSURL *)_srcurl toURL:(NSURL *)_desturl - password:(NSString *)_pwd; - -- (NSDictionary *)aclForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd; -- (NSString *)myRightsForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd; - -- (NSException *)addFlags:(id)_f toAllMessagesInURL:(NSURL *)_u - password:(NSString *)_p; +- (NSException *) copyMailURL: (NSURL *) srcurl + toFolderURL: (NSURL *) desturl + password: (NSString *) pwd; @end diff --git a/SoObjects/Mailer/SOGoMailManager.m b/SoObjects/Mailer/SOGoMailManager.m index b9b42e23f..f88723318 100644 --- a/SoObjects/Mailer/SOGoMailManager.m +++ b/SoObjects/Mailer/SOGoMailManager.m @@ -41,292 +41,38 @@ NGImap4Client. */ -@implementation NGImap4ConnectionManager(SOGoMailManager) +@implementation NGImap4ConnectionManager (SOGoMailManager) -+ (id)defaultMailManager { - return [self defaultConnectionManager]; -} - - -- (NSException *)errorForMissingEntryAtURL:(NSURL *)_url { - // TODO: improve - return [NSException exceptionWithHTTPStatus:404 /* Not Found */ - reason:@"Did not find mail URL"]; -} - -/* client object */ - - -/* folder hierarchy */ - -- (NSArray *)subfoldersForURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - /* check connection cache */ - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return nil; - - return [entry subfoldersForURL:_url]; -} - -- (NSArray *)allFoldersForURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - /* check connection cache */ - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return nil; - - return [entry allFoldersForURL:_url]; -} - -/* messages */ - -- (NSArray *)fetchUIDsInURL:(NSURL *)_url qualifier:(id)_qualifier - sortOrdering:(id)_so password:(NSString *)_pwd -{ - /* - sortOrdering can be an NSString, an EOSortOrdering or an array of EOS. - */ - NGImap4Connection *entry; - - /* check connection cache */ - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return nil; - - return [entry fetchUIDsInURL:_url qualifier:_qualifier sortOrdering:_so]; -} - -- (NSArray *)fetchUIDs:(NSArray *)_uids inURL:(NSURL *)_url - parts:(NSArray *)_parts password:(NSString *)_pwd -{ - // currently returns a dict?! - /* - Allowed fetch keys: - UID - BODY.PEEK[
]<> - BODY [this is the bodystructure, supported] - BODYSTRUCTURE [not supported yet!] - ENVELOPE [this is a parsed header, but does not include type] - FLAGS - INTERNALDATE - RFC822 - RFC822.HEADER - RFC822.SIZE - RFC822.TEXT - */ - NGImap4Connection *entry; - - if (_uids == nil) - return nil; - if ([_uids count] == 0) - return nil; // TODO: might break empty folders?! return a dict! - - /* check connection cache */ - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return nil; - - return [entry fetchUIDs:_uids inURL:_url parts:_parts]; -} - -- (NSException *)expungeAtURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry expungeAtURL:_url]; -} - -- (id)fetchURL:(NSURL *)_url parts:(NSArray *)_parts password:(NSString *)_pwd{ - NGImap4Connection *entry; - - if (![_url isNotNull]) return nil; - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry fetchURL:_url parts:_parts]; -} - -- (NSData *)fetchContentOfBodyPart:(NSString *)_partId - atURL:(NSURL *)_url password:(NSString *)_pwd -{ - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return nil; // TODO: improve? - - return [entry fetchContentOfBodyPart:_partId atURL:_url]; -} - -- (NSException *)addOrRemove:(BOOL)_flag flags:(id)_f - toURL:(NSURL *)_url password:(NSString *)_p -{ - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_p]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry addOrRemove:_flag flags:_f toURL:_url]; -} -- (NSException *)addFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p { - return [self addOrRemove:YES flags:_f toURL:_u password:_p]; -} -- (NSException *)removeFlags:(id)_f toURL:(NSURL *)_u password:(NSString *)_p { - return [self addOrRemove:NO flags:_f toURL:_u password:_p]; -} - -- (NSException *)markURLDeleted:(NSURL *)_url password:(NSString *)_p { - return [self addOrRemove:YES flags:@"Deleted" toURL:_url password:_p]; -} - -- (NSException *)postData:(NSData *)_data flags:(id)_f - toFolderURL:(NSURL *)_url password:(NSString *)_p -{ - NGImap4Connection *entry; - - if (![_url isNotNull]) return nil; - - if ((entry = [self connectionForURL:_url password:_p]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry postData:_data flags:_f toFolderURL:_url]; -} - -- (NSException *)copyMailURL:(NSURL *)_srcurl toFolderURL:(NSURL *)_desturl - password:(NSString *)_pwd +- (NSException *) copyMailURL: (NSURL *) srcurl + toFolderURL: (NSURL *) desturl + password: (NSString *) pwd { NGImap4Connection *entry; NSNumber *destPort, *srcPort; + NSException *error; /* check connection cache */ - if ((entry = [self connectionForURL:_srcurl password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_srcurl]; - - /* check whether URLs are on different servers */ - srcPort = [_srcurl port]; - destPort = [_desturl port]; + entry = [self connectionForURL: srcurl password: pwd]; + if (entry) + { + /* check whether URLs are on different servers */ + srcPort = [srcurl port]; + destPort = [desturl port]; - if (!([[_desturl host] isEqualToString: [_srcurl host]] - && (srcPort == destPort - || [destPort isEqualToNumber: srcPort]))) { - // TODO: find a better error code - return [NSException exceptionWithHTTPStatus:502 /* Bad Gateway */ - reason:@"source and destination on different servers"]; - } + if ([[desturl host] isEqualToString: [srcurl host]] + && (srcPort == destPort + || [destPort isEqualToNumber: srcPort])) + error = [entry copyMailURL: srcurl toFolderURL: desturl]; + else + error = [NSException exceptionWithHTTPStatus: 502 /* Bad Gateway */ + reason: @"source and destination on different servers"]; + } + else + error = [NSException exceptionWithHTTPStatus: 404 /* Not Found */ + reason: @"Did not find mail URL"]; - return [entry copyMailURL:_srcurl toFolderURL:_desturl]; -} - -/* managing folders */ - -- (BOOL)isPermissionDeniedResult:(id)_result { - if ([[_result valueForKey:@"result"] intValue] != 0) - return NO; - - return [[_result valueForKey:@"reason"] - isEqualToString:@"Permission denied"]; -} - -- (BOOL)doesMailboxExistAtURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return NO; - - return [entry doesMailboxExistAtURL:_url]; -} - -- (id)infoForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry infoForMailboxAtURL:_url]; -} - -- (NSException *)createMailbox:(NSString *)_mailbox atURL:(NSURL *)_url - password:(NSString *)_pwd -{ - NGImap4Connection *entry; - - /* check connection cache */ - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry createMailbox:_mailbox atURL:_url]; -} - -- (NSException *)deleteMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - /* check connection cache */ - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry deleteMailboxAtURL:_url]; -} - -- (NSException *)moveMailboxAtURL:(NSURL *)_srcurl toURL:(NSURL *)_desturl - password:(NSString *)_pwd -{ - NGImap4Connection *entry; - - /* check connection cache */ - - if ((entry = [self connectionForURL:_srcurl password:_pwd]) == nil) - return [self errorForMissingEntryAtURL:_srcurl]; - - /* check whether URLs are on different servers */ - - if ([self connectionForURL:_desturl password:_pwd] != entry) { - // TODO: find a better error code - return [NSException exceptionWithHTTPStatus:502 /* Bad Gateway */ - reason:@"source and destination on different servers"]; - } - - return [entry moveMailboxAtURL:_srcurl toURL:_desturl]; -} - -- (NSDictionary *)aclForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd { - /* - Returns a mapping of uid => permission strings, eg: - guizmo.g = lrs; - root = lrswipcda; - */ - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return (id)[self errorForMissingEntryAtURL:_url]; - - return [entry aclForMailboxAtURL:_url]; -} - -- (NSString *)myRightsForMailboxAtURL:(NSURL *)_url password:(NSString *)_pwd { - NGImap4Connection *entry; - - if ((entry = [self connectionForURL:_url password:_pwd]) == nil) - return (id)[self errorForMissingEntryAtURL:_url]; - - return [entry myRightsForMailboxAtURL:_url]; -} - -/* bulk flag adding (eg used for empty/trash) */ - -- (NSException *)addFlags:(id)_f toAllMessagesInURL:(NSURL *)_url - password:(NSString *)_p -{ - NGImap4Connection *entry; - - if (![_url isNotNull]) return nil; - if (![_f isNotNull]) return nil; - - if ((entry = [self connectionForURL:_url password:_p]) == nil) - return [self errorForMissingEntryAtURL:_url]; - - return [entry addFlags:_f toAllMessagesInURL:_url]; + return error; } @end /* NGImap4ConnectionManager(SOGoMailManager) */ diff --git a/SoObjects/Mailer/SOGoMailObject.h b/SoObjects/Mailer/SOGoMailObject.h index e4f873bfa..2c5b6cf34 100644 --- a/SoObjects/Mailer/SOGoMailObject.h +++ b/SoObjects/Mailer/SOGoMailObject.h @@ -99,7 +99,6 @@ /* deletion */ - (BOOL) isDeletionAllowed; -- (NSException *) trashInContext:(id)_ctx; - (NSException *) copyToFolderNamed: (NSString *) folderName inContext: (id)_ctx; - (NSException *) moveToFolderNamed: (NSString *) folderName diff --git a/SoObjects/Mailer/SOGoMailObject.m b/SoObjects/Mailer/SOGoMailObject.m index 40648f05e..e39a4d554 100644 --- a/SoObjects/Mailer/SOGoMailObject.m +++ b/SoObjects/Mailer/SOGoMailObject.m @@ -975,50 +975,6 @@ static BOOL debugSoParts = NO; /* operations */ -- (NSException *) trashInContext: (id) _ctx -{ - /* - Trashing is three actions: - a) copy to trash folder - b) mark mail as deleted - c) expunge folder - - In case b) or c) fails, we can't do anything because IMAP4 doesn't tell us - the ID used in the trash folder. - */ - SOGoMailFolder *trashFolder; - NSException *error; - - // TODO: check for safe HTTP method - - trashFolder = [[self mailAccountFolder] trashFolderInContext: _ctx]; - if ([trashFolder isKindOfClass:[NSException class]]) - return (NSException *)trashFolder; - if (![trashFolder isNotNull]) { - return [NSException exceptionWithHTTPStatus:500 /* Server Error */ - reason: @"Did not find Trash folder!"]; - } - [trashFolder flushMailCaches]; - - /* a) copy */ - - error = [self davCopyToTargetObject:trashFolder - newName: @"fakeNewUnusedByIMAP4" /* autoassigned */ - inContext:_ctx]; - if (error) return error; - - /* b) mark deleted */ - - error = [[self imap4Connection] markURLDeleted: [self imap4URL]]; - if (error) return error; - - [container markForExpunge]; - - [self flushMailCaches]; - - return nil; -} - - (NSException *) copyToFolderNamed: (NSString *) folderName inContext: (id)_ctx { diff --git a/UI/MailerUI/UIxMailActions.m b/UI/MailerUI/UIxMailActions.m index c421815e9..2a9c3da6f 100644 --- a/UI/MailerUI/UIxMailActions.m +++ b/UI/MailerUI/UIxMailActions.m @@ -89,17 +89,6 @@ return [self redirectToLocation: newLocation]; } -- (id) trashAction -{ - id response; - - response = [[self clientObject] trashInContext: context]; - if (!response) - response = [self responseWith204]; - - return response; -} - - (id) moveAction { NSString *destinationFolder; diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index d52a19ee5..6e7f2b020 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -1,6 +1,6 @@ /* UIxMailFolderActions.m - this file is part of SOGo * - * Copyright (C) 2007 Inverse groupe conseil + * Copyright (C) 2007-2008 Inverse inc. * * Author: Wolfgang Sourdeau * @@ -185,12 +185,9 @@ - (WOResponse *) deleteMessagesAction { SOGoMailFolder *co; - SOGoMailObject *mail; WOResponse *response; NSArray *uids; - NSString *value, *uid; - NSException *error; - unsigned int i; + NSString *value; co = [self clientObject]; value = [[context request] formValueForKey: @"uid"]; @@ -199,25 +196,15 @@ if ([value length] > 0) { uids = [value componentsSeparatedByString: @","]; - for (i = 0; i < [uids count]; i++) - { - uid = [uids objectAtIndex: i]; - mail = [co lookupName: uid inContext: context acquire: NO]; - if (mail) - { - error = [mail trashInContext: context]; - if (error) - { - response = [self responseWithStatus: 500]; - [response appendContentString: [NSString stringWithFormat: @"Can't trash message %@/%@", [co nameInContainer], uid]]; - break; - } - } - } + response = [co deleteUIDs: uids inContext: context]; + if (!response) + response = [self responseWith204]; + } + else + { + response = [self responseWithStatus: 500]; + [response appendContentString: @"Missing 'uid' parameter."]; } - - if (response == nil) - response = [self responseWith204]; return response; } diff --git a/UI/MailerUI/product.plist b/UI/MailerUI/product.plist index fc50ed214..0bc397b63 100644 --- a/UI/MailerUI/product.plist +++ b/UI/MailerUI/product.plist @@ -216,11 +216,6 @@ actionClass = "UIxMailActions"; actionName = "copy"; }; - trash = { - protectedBy = "View"; - actionClass = "UIxMailActions"; - actionName = "trash"; - }; junk = { protectedBy = "View"; actionClass = "UIxMailActions";