Monotone-Parent: 6b7485d7999f592e4a4b077024f47c2323c3fdbc

Monotone-Revision: d47c52bbe608df33a336ba2d63dad8b7524aa9d7

Monotone-Author: wsourdeau@inverse.ca
Monotone-Date: 2008-09-22T21:31:42
Monotone-Branch: ca.inverse.sogo
maint-2.0.2
Wolfgang Sourdeau 2008-09-22 21:31:42 +00:00
parent ffffac624a
commit 4371dba9a1
10 changed files with 107 additions and 415 deletions

View File

@ -1,3 +1,23 @@
2008-09-22 Ludovic Marcotte <lmarcotte@inverse.ca>
* 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 <wsourdeau@inverse.ca>
* SoObjects/Appointments/SOGoAppointmentFolder.m

View File

@ -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;

View File

@ -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

View File

@ -22,8 +22,6 @@
#ifndef __Mailer_SOGoMailManager_H__
#define __Mailer_SOGoMailManager_H__
#import <Foundation/NSObject.h>
#import <Foundation/NSRange.h>
#include <NGImap4/NGImap4ConnectionManager.h>
/*
@ -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

View File

@ -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[<section>]<<partial>>
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) */

View File

@ -99,7 +99,6 @@
/* deletion */
- (BOOL) isDeletionAllowed;
- (NSException *) trashInContext:(id)_ctx;
- (NSException *) copyToFolderNamed: (NSString *) folderName
inContext: (id)_ctx;
- (NSException *) moveToFolderNamed: (NSString *) folderName

View File

@ -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
{

View File

@ -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;

View File

@ -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 <wsourdeau@inverse.ca>
*
@ -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;
}

View File

@ -216,11 +216,6 @@
actionClass = "UIxMailActions";
actionName = "copy";
};
trash = {
protectedBy = "View";
actionClass = "UIxMailActions";
actionName = "trash";
};
junk = {
protectedBy = "View";
actionClass = "UIxMailActions";