X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=SOGo%2FSoObjects%2FMailer%2FSOGoMailAccount.m;h=bcb0ea6b74958530a92f0b7777a28b380031cdc2;hb=05a79cf31a57c2bb34309f93c50e12ff366f3148;hp=bc3c00317261064f64de49774a44f683fd710db8;hpb=9641cbf1e822893fbbca9a91b24742f2c0e53dd1;p=scalable-opengroupware.org diff --git a/SOGo/SoObjects/Mailer/SOGoMailAccount.m b/SOGo/SoObjects/Mailer/SOGoMailAccount.m index bc3c0031..bcb0ea6b 100644 --- a/SOGo/SoObjects/Mailer/SOGoMailAccount.m +++ b/SOGo/SoObjects/Mailer/SOGoMailAccount.m @@ -23,23 +23,82 @@ #include "SOGoMailFolder.h" #include "SOGoMailManager.h" #include "SOGoDraftsFolder.h" +#include #include "common.h" @implementation SOGoMailAccount -static NSString *draftsFolderName = @"Drafts"; -static NSString *sieveFolderName = @"Filters"; +static NSArray *rootFolderNames = nil; +static NSString *inboxFolderName = @"INBOX"; +static NSString *draftsFolderName = @"Drafts"; +static NSString *sieveFolderName = @"Filters"; +static NSString *sharedFolderName = @""; // TODO: add English default +static NSString *otherUsersFolderName = @""; // TODO: add English default +static BOOL useAltNamespace = NO; + ++ (int)version { + return [super version] + 0 /* v1 */; +} + ++ (void)initialize { + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + NSAssert2([super version] == 1, + @"invalid superclass (%@) version %i !", + NSStringFromClass([self superclass]), [super version]); + + useAltNamespace = [ud boolForKey:@"SOGoSpecialFoldersInRoot"]; + + sharedFolderName = [ud stringForKey:@"SOGoSharedFolderName"]; + otherUsersFolderName = [ud stringForKey:@"SOGoOtherUsersFolderName"]; + + NSLog(@"Note: using shared-folders name: '%@'", sharedFolderName); + NSLog(@"Note: using other-users-folders name: '%@'", otherUsersFolderName); + + if ([ud boolForKey:@"SOGoEnableSieveFolder"]) { + rootFolderNames = [[NSArray alloc] initWithObjects: + draftsFolderName, + sieveFolderName, + nil]; + } + else { + rootFolderNames = [[NSArray alloc] initWithObjects: + draftsFolderName, + nil]; + } +} + +/* shared accounts */ + +- (BOOL)isSharedAccount { + NSString *s; + NSRange r; + + s = [self nameInContainer]; + r = [s rangeOfString:@"@"]; + if (r.length == 0) /* regular HTTP logins are never a shared mailbox */ + return NO; + + s = [s substringToIndex:r.location]; + return [s rangeOfString:@".-."].length > 0 ? YES : NO; +} + +- (NSString *)sharedAccountName { + return nil; +} /* listing the available folders */ +- (NSArray *)additionalRootFolderNames { + return rootFolderNames; +} + - (NSArray *)toManyRelationshipKeys { - // TODO: hardcoded, if we want to support shared fldrs, this needs to change - static NSArray *accFolderNames = nil; - if (accFolderNames == nil) { - accFolderNames = [[NSArray alloc] initWithObjects: - @"INBOX", @"Drafts", @"Filters", nil]; - } - return accFolderNames; + NSArray *a, *b; + + a = [self additionalRootFolderNames]; + b = [[self imap4Connection] subfoldersForURL:[self imap4URL]]; + return [b count] > 0 ? [b arrayByAddingObjectsFromArray:a] : a; } /* hierarchy */ @@ -51,8 +110,7 @@ static NSString *sieveFolderName = @"Filters"; - (NSArray *)allFolderPathes { NSArray *pathes; - pathes = [[self mailManager] allFoldersForURL:[self imap4URL] - password:[self imap4Password]]; + pathes = [[self imap4Connection] allFoldersForURL:[self imap4URL] ]; pathes = [pathes sortedArrayUsingSelector:@selector(compare:)]; return pathes; } @@ -63,19 +121,46 @@ static NSString *sieveFolderName = @"Filters"; return NO; } -- (NSURL *)imap4URL { - /* imap://agenortest@mail.opengroupware.org/INBOX/withsubdirs/subdir1 */ +- (NSString *)imap4LoginFromHTTP { + WORequest *rq; + NSString *s; + NSArray *creds; + + rq = [[(WOApplication *)[WOApplication application] context] request]; + + s = [rq headerForKey:@"x-webobjects-remote-user"]; + if ([s length] > 0) + return s; + + if ((s = [rq headerForKey:@"authorization"]) == nil) { + /* no basic auth */ + return nil; + } + + creds = [SoHTTPAuthenticator parseCredentials:s]; + if ([creds count] < 2) + /* somehow invalid */ + return nil; + + return [creds objectAtIndex:0]; /* the user */ +} + +- (NSString *)imap4URLString { + /* private, overridden by SOGoSharedMailAccount */ NSString *s; NSRange r; - - if (self->imap4URL != nil) - return self->imap4URL; s = [self nameInContainer]; r = [s rangeOfString:@"@"]; if (r.length == 0) { - [self errorWithFormat:@"missing login in account folder name: %@", s]; - return nil; + NSString *u; + + u = [self imap4LoginFromHTTP]; + if ([u length] == 0) { + [self errorWithFormat:@"missing login in account folder name: %@", s]; + return nil; + } + s = [[u stringByAppendingString:@"@"] stringByAppendingString:s]; } if ([s hasSuffix:@":80"]) { // HACK [self logWithFormat:@"WARNING: incorrect value for IMAP4 URL: '%@'", s]; @@ -84,11 +169,27 @@ static NSString *sieveFolderName = @"Filters"; s = [([self useSSL] ? @"imaps://" : @"imap://") stringByAppendingString:s]; s = [s stringByAppendingString:@"/"]; + return s; +} + +- (NSURL *)imap4URL { + /* imap://agenortest@mail.opengroupware.org/ */ + NSString *s; + + if (self->imap4URL != nil) + return self->imap4URL; + + if ((s = [self imap4URLString]) == nil) + return nil; self->imap4URL = [[NSURL alloc] initWithString:s]; return self->imap4URL; } +- (NSString *)imap4Login { + return [[self imap4URL] user]; +} + /* name lookup */ - (id)lookupFolder:(NSString *)_key ofClassNamed:(NSString *)_cn @@ -106,8 +207,14 @@ static NSString *sieveFolderName = @"Filters"; } - (id)lookupImap4Folder:(NSString *)_key inContext:(id)_cx { - return [self lookupFolder:_key ofClassNamed:@"SOGoMailFolder" inContext:_cx]; + NSString *s; + + s = [_key isEqualToString:[self trashFolderNameInContext:_cx]] + ? @"SOGoTrashFolder" : @"SOGoMailFolder"; + + return [self lookupFolder:_key ofClassNamed:s inContext:_cx]; } + - (id)lookupDraftsFolder:(NSString *)_key inContext:(id)_ctx { return [self lookupFolder:_key ofClassNamed:@"SOGoDraftsFolder" inContext:_ctx]; @@ -142,12 +249,114 @@ static NSString *sieveFolderName = @"Filters"; return [NSException exceptionWithHTTPStatus:404 /* Not Found */]; } +/* special folders */ + +- (NSString *)inboxFolderNameInContext:(id)_ctx { + return inboxFolderName; /* cannot be changed in Cyrus ? */ +} +- (NSString *)draftsFolderNameInContext:(id)_ctx { + return draftsFolderName; /* SOGo managed folder */ +} +- (NSString *)sieveFolderNameInContext:(id)_ctx { + return sieveFolderName; /* SOGo managed folder */ +} +- (NSString *)sentFolderNameInContext:(id)_ctx { + /* OGo issue #1225 */ + static NSString *s = nil; + + if (s == nil) { + NSUserDefaults *ud; + + ud = [NSUserDefaults standardUserDefaults]; + s = [[ud stringForKey:@"SOGoSentFolderName"] copy]; + if ([s length] == 0) s = @"Sent"; + [self logWithFormat:@"Note: using SOGoSentFolderName: '%@'", s]; + } + return s; +} +- (NSString *)trashFolderNameInContext:(id)_ctx { + /* OGo issue #1225 */ + static NSString *s = nil; + + if (s == nil) { + NSUserDefaults *ud; + + ud = [NSUserDefaults standardUserDefaults]; + s = [[ud stringForKey:@"SOGoTrashFolderName"] copy]; + if ([s length] == 0) s = @"Trash"; + NSLog(@"Note: using SOGoTrashFolderName: '%@'", s); + } + return s; +} + +- (SOGoMailFolder *)inboxFolderInContext:(id)_ctx { + // TODO: use some profile to determine real location, use a -traverse lookup + SOGoMailFolder *folder; + + if (self->inboxFolder != nil) + return self->inboxFolder; + + folder = [self lookupName:[self inboxFolderNameInContext:_ctx] + inContext:_ctx acquire:NO]; + if ([folder isKindOfClass:[NSException class]]) return folder; + + return ((self->inboxFolder = [folder retain])); +} + +- (SOGoMailFolder *)sentFolderInContext:(id)_ctx { + // TODO: use some profile to determine real location, use a -traverse lookup + SOGoMailFolder *folder; + + if (self->sentFolder != nil) + return self->sentFolder; + + folder = useAltNamespace ? (id)self : [self inboxFolderInContext:_ctx]; + if ([folder isKindOfClass:[NSException class]]) return folder; + + folder = [folder lookupName:[self sentFolderNameInContext:_ctx] + inContext:_ctx acquire:NO]; + if ([folder isKindOfClass:[NSException class]]) return folder; + + if (![folder isNotNull]) { + return [NSException exceptionWithHTTPStatus:404 /* not found */ + reason:@"did not find Sent folder!"]; + } + + return ((self->sentFolder = [folder retain])); +} + +- (SOGoMailFolder *)trashFolderInContext:(id)_ctx { + // TODO: use some profile to determine real location + SOGoMailFolder *folder; + + if (self->trashFolder != nil) + return self->trashFolder; + + folder = useAltNamespace ? (id)self : [self inboxFolderInContext:_ctx]; + if ([folder isKindOfClass:[NSException class]]) return folder; + + folder = [folder lookupName:[self trashFolderNameInContext:_ctx] + inContext:_ctx acquire:NO]; + if ([folder isKindOfClass:[NSException class]]) return folder; + + if (![folder isNotNull]) { + return [NSException exceptionWithHTTPStatus:404 /* not found */ + reason:@"did not find Trash folder!"]; + } + + return ((self->trashFolder = [folder retain])); +} + /* WebDAV */ - (BOOL)davIsCollection { return YES; } +- (NSException *)davCreateCollection:(NSString *)_name inContext:(id)_ctx { + return [[self imap4Connection] createMailbox:_name atURL:[self imap4URL]]; +} + - (NSString *)shortTitle { NSString *s, *login, *host; NSRange r; @@ -171,7 +380,11 @@ static NSString *sieveFolderName = @"Filters"; if ([login length] == 0) return host; - return [NSString stringWithFormat:@"%@ (%@)", host, login]; + r = [login rangeOfString:@"."]; + if (r.length > 0) + login = [login substringToIndex:r.location]; + + return [NSString stringWithFormat:@"%@@%@", login, host]; } - (NSString *)davDisplayName {