2005-03-25 Helge Hess <helge.hess@opengroupware.org>
-
+
+ * v0.9.83
+
+ * SOGoMailManager.m: properly select folder prior changing flags
+
+ * SOGoMailObject.m: added a special DELETEAction: for mails, it marks
+ a mail deleted and expunges the folder to ensure the mail is deleted
+ (this is different to the -delete method!)
+
* SOGoMailFolder.m: implemented content datasource for efficient WebDAV
listings (currently uses hardcoded parts and has inefficient DASL
support) (v0.9.82)
return [[[SOGoMailFolder alloc] initWithName:_key
inContainer:self] autorelease];
}
+
- (id)lookupImap4Message:(NSString *)_key inContext:(id)_ctx {
// TODO: we might want to check for existence prior controller creation
return [[[SOGoMailObject alloc] initWithName:_key
- (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;
if (![_url isNotNull]) return nil;
if (![_f isNotNull]) return nil;
+ if (![_f isKindOfClass:[NSArray class]])
+ _f = [NSArray arrayWithObjects:&_f count:1];
+
+ /* get client */
+
if ((client = [self imap4ClientForURL:_url password:_p]) == nil)
+ // TODO: return 401?
return nil;
- if (![_f isKindOfClass:[NSArray class]])
- _f = [NSArray arrayWithObjects:&_f count:1];
+ /* select folder */
+
+ if (![self selectFolder:[self imap4FolderNameForURL:_url removeFileName:YES]
+ inClient:client]) {
+ return [NSException exceptionWithHTTPStatus:404 /* server error */
+ reason:@"could not select IMAP4 folder"];
+ return nil;
+ }
+
+ /* store flags */
result = [client storeUid:[[[_url path] lastPathComponent] intValue]
add:[NSNumber numberWithBool:_flag]
reason:@"failed to store message to IMAP4 message"];
}
/* result contains 'fetch' key with the current flags */
+
+ // TODO: need to flush any caches?
+ return nil;
+}
+
+- (NSException *)copyMailURL:(NSURL *)_srcurl toFolderURL:(NSURL *)_desturl
+ password:(NSString *)_pwd
+{
+ SOGoMailConnectionEntry *entry;
+ NSString *srcname, *destname;
+ unsigned uid;
+ id result;
+
+ /* check connection cache */
+
+ if ((entry = [self entryForURL:_srcurl password:_pwd]) == nil) {
+ // TODO: better to use an auth exception?
+ return [NSException exceptionWithHTTPStatus:404 /* Not Found */
+ reason:@"did not find IMAP4 folder (no entry)"];
+ }
+
+ /* check whether URLs are on different servers */
+
+ if ([self entryForURL:_desturl password:_pwd] != entry) {
+ // TODO: find a better error code
+ return [NSException exceptionWithHTTPStatus:502 /* Bad Gateway */
+ reason:@"source and destination on different servers"];
+ }
+
+ /* names */
+
+ srcname = [self imap4FolderNameForURL:_srcurl removeFileName:YES];
+ uid = [[[_srcurl path] lastPathComponent] unsignedIntValue];
+ destname = [self imap4FolderNameForURL:_desturl];
+
+ /* select source folder */
+
+ if (![self selectFolder:srcname inClient:[entry client]]) {
+ return [NSException exceptionWithHTTPStatus:404 /* Not Found */
+ reason:@"did not find source folder"];
+ }
+
+ /* copy */
+
+ result = [[entry client] copyUid:uid toFolder:destname];
+ if (![[result valueForKey:@"result"] boolValue]) {
+ return [NSException exceptionWithHTTPStatus:500 /* Server Error */
+ reason:@"copy operation failed"];
+ }
+
return nil;
}
return [NSException exceptionWithHTTPStatus:501 /* Not Implemented */
reason:@"not implemented"];
}
+
- (NSException *)davCopyToTargetObject:(id)_target newName:(NSString *)_name
inContext:(id)_ctx
{
- [self logWithFormat:@"TODO: should copy mail as '%@' to: %@",
- _name, _target];
- return [NSException exceptionWithHTTPStatus:501 /* Not Implemented */
- reason:@"not implemented"];
+ /*
+ Note: this is special because we create SOGoMailObject's even if they do
+ not exist (for performance reasons).
+
+ Also: we cannot really take a target resource, the ID will be assigned by
+ the IMAP4 server.
+ TODO: return a 'location' header instead?
+ */
+ NSURL *destImap4URL;
+
+ destImap4URL = ([_name length] == 0)
+ ? [[_target container] imap4URL]
+ : [_target imap4URL];
+
+ return [[self mailManager] copyMailURL:[self imap4URL]
+ toFolderURL:destImap4URL
+ password:[self imap4Password]];
}
/* actions */
/* operations */
- (NSException *)delete {
+ /*
+ Note: delete is different to DELETEAction: for mails! The 'delete' runs
+ either flags a message as deleted or moves it to the Trash while
+ the DELETEAction: really deletes a message (by flagging it as
+ deleted _AND_ performing an expunge).
+ */
// TODO: copy to Trash folder
- return [[self mailManager] markURLDeleted:[self imap4URL]
- password:[self imap4Password]];
+ NSException *error;
+
+ error = [[self mailManager] markURLDeleted:[self imap4URL]
+ password:[self imap4Password]];
+ return error;
+}
+- (id)DELETEAction:(id)_ctx {
+ NSException *error;
+
+ error = [[self mailManager] markURLDeleted:[self imap4URL]
+ password:[self imap4Password]];
+ if (error != nil) return error;
+
+ error = [[self mailManager] expungeAtURL:[[self container] imap4URL]
+ password:[self imap4Password]];
+ if (error != nil) return error; // TODO: unflag as deleted?
+
+ return [NSNumber numberWithBool:YES]; /* delete was successful */
}
/* debugging */
# Version file
-SUBMINOR_VERSION:=82
+SUBMINOR_VERSION:=83
# v0.9.69 requires libNGMime v4.5.210
# v0.9.55 requires libNGExtensions v4.5.136