From fa926075e82586ded49f135b457c9ac56d7935eb Mon Sep 17 00:00:00 2001 From: helge Date: Tue, 5 Jul 2005 14:21:13 +0000 Subject: [PATCH] added support for some ACL IMAP4 commands git-svn-id: http://svn.opengroupware.org/SOPE/trunk@866 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- sope-mime/ChangeLog | 5 + sope-mime/NGImap4/NGImap4Client.h | 9 ++ sope-mime/NGImap4/NGImap4Client.m | 70 ++++++++++- sope-mime/NGImap4/NGImap4ResponseNormalizer.h | 6 + sope-mime/NGImap4/NGImap4ResponseNormalizer.m | 64 +++++++++- sope-mime/NGImap4/NGImap4ResponseParser.m | 117 +++++++++++++++++- sope-mime/Version | 2 +- sope-mime/samples/ChangeLog | 4 + sope-mime/samples/GNUmakefile | 2 + sope-mime/samples/ImapQuotaTool.m | 1 - sope-mime/samples/imapacl.m | 75 +++++++++++ sope-mime/samples/imapquota.m | 2 +- 12 files changed, 344 insertions(+), 13 deletions(-) create mode 100644 sope-mime/samples/imapacl.m diff --git a/sope-mime/ChangeLog b/sope-mime/ChangeLog index 5f4a7380..9ec18c8b 100644 --- a/sope-mime/ChangeLog +++ b/sope-mime/ChangeLog @@ -1,3 +1,8 @@ +2005-07-05 Helge Hess + + * NGImap4ResponseNormalizer.[hm], NGImap4Client.[hm], + NGImap4ResponseParser.m: added some ACL related commands (v4.5.221) + 2005-04-24 Helge Hess * NGMime, NGImap4, NGMail: fixed gcc 4.0 warnings (v4.5.220) diff --git a/sope-mime/NGImap4/NGImap4Client.h b/sope-mime/NGImap4/NGImap4Client.h index e3e7e6a4..52106a3c 100644 --- a/sope-mime/NGImap4/NGImap4Client.h +++ b/sope-mime/NGImap4/NGImap4Client.h @@ -152,6 +152,15 @@ typedef enum { - (NSDictionary *)searchWithQualifier:(EOQualifier *)_qualifier; +/* ACLs */ + +- (NSDictionary *)getACL:(NSString *)_folder; +- (NSDictionary *)setACL:(NSString *)_folder rights:(NSString *)_r + uid:(NSString *)_uid; +- (NSDictionary *)deleteACL:(NSString *)_folder uid:(NSString *)_uid; +- (NSDictionary *)listRights:(NSString *)_folder uid:(NSString *)_uid; +- (NSDictionary *)myRights:(NSString *)_folder; + /* context accessors (DEPRECATED) */ - (void)setContext:(NGImap4Context *)_ctx; diff --git a/sope-mime/NGImap4/NGImap4Client.m b/sope-mime/NGImap4/NGImap4Client.m index 71bf137b..551678f2 100644 --- a/sope-mime/NGImap4/NGImap4Client.m +++ b/sope-mime/NGImap4/NGImap4Client.m @@ -1108,24 +1108,82 @@ static BOOL ImapDebugEnabled = NO; return [self->normer normalizeSearchResponse:[self processCommand:s]]; } +/* ACLs */ + +- (NSDictionary *)getACL:(NSString *)_folder { + NSString *cmd; + + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + + cmd = [NSString stringWithFormat:@"getacl \"%@\"", _folder]; + return [self->normer normalizeGetACLResponse:[self processCommand:cmd]]; +} + +- (NSDictionary *)setACL:(NSString *)_folder rights:(NSString *)_r + uid:(NSString *)_uid +{ + NSString *cmd; + + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + + cmd = [NSString stringWithFormat:@"setacl \"%@\" \"%@\" \"%@\"", + _folder, _uid, _r]; + return [self->normer normalizeResponse:[self processCommand:cmd]]; +} + +- (NSDictionary *)deleteACL:(NSString *)_folder uid:(NSString *)_uid { + NSString *cmd; + + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + + cmd = [NSString stringWithFormat:@"deleteacl \"%@\" \"%@\"", + _folder, _uid]; + return [self->normer normalizeResponse:[self processCommand:cmd]]; +} + +- (NSDictionary *)listRights:(NSString *)_folder uid:(NSString *)_uid { + NSString *cmd; + + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + + cmd = [NSString stringWithFormat:@"listrights \"%@\" \"%@\"", + _folder, _uid]; + return [self->normer normalizeListRightsResponse:[self processCommand:cmd]]; +} + +- (NSDictionary *)myRights:(NSString *)_folder { + NSString *cmd; + + if ((_folder = [self _folder2ImapFolder:_folder]) == nil) + return nil; + + cmd = [NSString stringWithFormat:@"myrights \"%@\"", _folder]; + return [self->normer normalizeMyRightsResponse:[self processCommand:cmd]]; +} + /* Private Methods */ - (NSException *)_processCommandParserException:(NSException *)_exception { - NSLog(@"ERROR(%s): catched IMAP4 parser exception %@: %@", - __PRETTY_FUNCTION__, [_exception name], [_exception reason]); + [self logWithFormat:@"ERROR(%s): catched IMAP4 parser exception %@: %@", + __PRETTY_FUNCTION__, [_exception name], [_exception reason]]; [self closeConnection]; [self->context setLastException:_exception]; return nil; } - (NSException *)_processUnknownCommandParserException:(NSException *)_ex { - NSLog(@"ERROR(%s): catched non-IMAP4 parsing exception %@: %@", - __PRETTY_FUNCTION__, [_ex name], [_ex reason]); + [self logWithFormat:@"ERROR(%s): catched non-IMAP4 parsing exception %@: %@", + __PRETTY_FUNCTION__, [_ex name], [_ex reason]]; return nil; } - (NSException *)_handleShutdownDuringCommandException:(NSException *)_ex { - NSLog(@"ERROR(%s): IMAP4 socket was shut down by server %@: %@", - __PRETTY_FUNCTION__, [_ex name], [_ex reason]); + [self logWithFormat: + @"ERROR(%s): IMAP4 socket was shut down by server %@: %@", + __PRETTY_FUNCTION__, [_ex name], [_ex reason]]; [self closeConnection]; [self->context setLastException:_ex]; return nil; diff --git a/sope-mime/NGImap4/NGImap4ResponseNormalizer.h b/sope-mime/NGImap4/NGImap4ResponseNormalizer.h index c0c5b5a8..d3bbc931 100644 --- a/sope-mime/NGImap4/NGImap4ResponseNormalizer.h +++ b/sope-mime/NGImap4/NGImap4ResponseNormalizer.h @@ -52,6 +52,12 @@ - (NSDictionary *)normalizeCapabilityRespone:(NGHashMap *)_map; - (NSDictionary *)normalizeQuotaResponse:(NGHashMap *)_map; +/* ACL */ + +- (NSDictionary *)normalizeGetACLResponse:(NGHashMap *)_map; +- (NSDictionary *)normalizeListRightsResponse:(NGHashMap *)_map; +- (NSDictionary *)normalizeMyRightsResponse:(NGHashMap *)_map; + @end #endif /* __NGImap4_NGImap4ResponseNormalizer_H__ */ diff --git a/sope-mime/NGImap4/NGImap4ResponseNormalizer.m b/sope-mime/NGImap4/NGImap4ResponseNormalizer.m index 8863cac1..ffff8b1b 100644 --- a/sope-mime/NGImap4/NGImap4ResponseNormalizer.m +++ b/sope-mime/NGImap4/NGImap4ResponseNormalizer.m @@ -150,7 +150,7 @@ static int LogImapEnabled = -1; result = [self normalizeResponse:_map]; - if ((obj = [[_map objectEnumeratorForKey:@"sort"] nextObject])) + if ((obj = [[_map objectEnumeratorForKey:@"sort"] nextObject]) != nil) [result setObject:obj forKey:@"sort"]; return result; @@ -642,4 +642,66 @@ _imapFlags2Flags(NGImap4ResponseNormalizer *self, NSArray *_flags) return result; } +/* ACL */ + +- (NSDictionary *)normalizeGetACLResponse:(NGHashMap *)_map { + /* + Raw Sample (Cyrus): + 21 GETACL INBOX + * ACL INBOX test.et.di.cete-lyon lrswipcda helge lrwip + 21 OK Completed + */ + NSMutableDictionary *result; + id obj; + + result = [self normalizeResponse:_map]; + if ((obj = [[_map objectEnumeratorForKey:@"acl"] nextObject]) != nil) + [result setObject:obj forKey:@"acl"]; + if ((obj = [[_map objectEnumeratorForKey:@"mailbox"] nextObject]) != nil) + [result setObject:obj forKey:@"mailbox"]; + return result; +} + +- (NSDictionary *)normalizeListRightsResponse:(NGHashMap *)_map { + /* + Raw Sample (Cyrus): + 16 listrights INBOX anyone + * LISTRIGHTS INBOX anyone "" l r s w i p c d a 0 1 2 3 4 5 6 7 8 9 + 16 OK Completed + */ + NSMutableDictionary *result; + id obj; + + result = [self normalizeResponse:_map]; + + if ((obj = [[_map objectEnumeratorForKey:@"listrights"] nextObject])) + [result setObject:obj forKey:@"listrights"]; + if ((obj = [[_map objectEnumeratorForKey:@"requiredRights"] nextObject])) + [result setObject:obj forKey:@"requiredRights"]; + + if ((obj = [[_map objectEnumeratorForKey:@"mailbox"] nextObject]) != nil) + [result setObject:obj forKey:@"mailbox"]; + if ((obj = [[_map objectEnumeratorForKey:@"uid"] nextObject]) != nil) + [result setObject:obj forKey:@"uid"]; + return result; +} + +- (NSDictionary *)normalizeMyRightsResponse:(NGHashMap *)_map { + /* + Raw Sample (Cyrus): + 18 myrights INBOX + * MYRIGHTS INBOX lrswipcda + 18 OK Completed + */ + NSMutableDictionary *result; + id obj; + + result = [self normalizeResponse:_map]; + if ((obj = [[_map objectEnumeratorForKey:@"myrights"] nextObject]) != nil) + [result setObject:obj forKey:@"myrights"]; + if ((obj = [[_map objectEnumeratorForKey:@"mailbox"] nextObject]) != nil) + [result setObject:obj forKey:@"mailbox"]; + return result; +} + @end /* NGImap4ResponseNormalizer */ diff --git a/sope-mime/NGImap4/NGImap4ResponseParser.m b/sope-mime/NGImap4/NGImap4ResponseParser.m index 270a59c6..dfa7a533 100644 --- a/sope-mime/NGImap4/NGImap4ResponseParser.m +++ b/sope-mime/NGImap4/NGImap4ResponseParser.m @@ -43,6 +43,9 @@ - (BOOL)_parseQuotaRootResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseStatusResponseIntoHashMap:(NGMutableHashMap *)result_; - (BOOL)_parseByeUntaggedResponseIntoHashMap:(NGMutableHashMap *)result_; +- (BOOL)_parseACLResponseIntoHashMap:(NGMutableHashMap *)result_; +- (BOOL)_parseMyRightsResponseIntoHashMap:(NGMutableHashMap *)result_; +- (BOOL)_parseListRightsResponseIntoHashMap:(NGMutableHashMap *)result_; - (NSArray *)_parseThread; @@ -538,6 +541,11 @@ static void _parseUntaggedResponse(NGImap4ResponseParser *self, l0 = _la(self, 0); switch (l0) { + case 'A': + if ([self _parseACLResponseIntoHashMap:result_]) + return; + break; + case 'B': l1 = _la(self, 1); if (l1 == 'A' && _parseBadUntaggedResponse(self, result_)) // la: 3 @@ -555,12 +563,21 @@ static void _parseUntaggedResponse(NGImap4ResponseParser *self, if (_parseFlagsUntaggedResponse(self, result_)) // la: 5 return; break; - + case 'L': + if (_matchesString(self, "LISTRIGHTS")) { + if ([self _parseListRightsResponseIntoHashMap:result_]) + return; + } if ([self _parseListOrLSubResponseIntoHashMap:result_]) // la: 4 return; break; + case 'M': + if ([self _parseMyRightsResponseIntoHashMap:result_]) + return; + break; + case 'N': if (_parseNoUntaggedResponse(self, result_)) // la: 2 return; @@ -615,6 +632,7 @@ static void _parseUntaggedResponse(NGImap4ResponseParser *self, // TODO: what if none matches? [self logWithFormat:@"%s: no matching tag specifier?", __PRETTY_FUNCTION__]; + [self logWithFormat:@" line: '%@'", _parseUntil(self, '\n')]; } - (void)_parseContinuationResponseIntoHashMap:(NGMutableHashMap *)result_ { @@ -700,6 +718,99 @@ static void _parseUntaggedResponse(NGImap4ResponseParser *self, return YES; } +- (BOOL)_parseACLResponseIntoHashMap:(NGMutableHashMap *)result_ { + /* + 21 GETACL INBOX + * ACL INBOX test.et.di.cete-lyon lrswipcda helge lrwip + */ + NSString *acls; + NSEnumerator *enumerator; + id obj; + NSMutableArray *uids; + NSMutableArray *rights; + NSDictionary *result; + + if (!_matchesString(self, "ACL ")) + return NO; + _consume(self, 4); + + if ((obj = _parseUntil(self, ' ')) != nil) + [result_ setObject:obj forKey:@"mailbox"]; + + acls = _parseUntil(self, '\n'); + + uids = [[NSMutableArray alloc] initWithCapacity:8]; + rights = [[NSMutableArray alloc] initWithCapacity:8]; + + enumerator = [[acls componentsSeparatedByString:@" "] objectEnumerator]; + while ((obj = [enumerator nextObject]) != nil) { + [uids addObject:obj]; + obj = [enumerator nextObject]; + [rights addObject:(obj ? obj : @"")]; + } + + result = [[NSDictionary alloc] initWithObjects:rights forKeys:uids]; + [result_ addObject:result forKey:@"acl"]; + + [uids release]; uids = nil; + [rights release]; rights = nil; + [result release]; result = nil; + return YES; +} + +- (BOOL)_parseMyRightsResponseIntoHashMap:(NGMutableHashMap *)result_ { + /* + Raw Sample (Cyrus): + 18 myrights INBOX + * MYRIGHTS INBOX lrswipcda + 18 OK Completed + */ + NSString *rights; + id obj; + + if (!_matchesString(self, "MYRIGHTS ")) + return NO; + _consume(self, 9); + + if ((obj = _parseUntil(self, ' ')) != nil) + [result_ setObject:obj forKey:@"mailbox"]; + + rights = _parseUntil(self, '\n'); + [result_ setObject:rights forKey:@"myrights"]; + return YES; +} + +- (BOOL)_parseListRightsResponseIntoHashMap:(NGMutableHashMap *)result_ { + /* + Raw Sample (Cyrus): + 22 LISTRIGHTS INBOX helge + * LISTRIGHTS INBOX helge "" l r s w i p c d a 0 1 2 3 4 5 6 7 8 9 + 22 OK Completed + */ + NSString *rights; + id obj; + + if (!_matchesString(self, "LISTRIGHTS ")) + return NO; + _consume(self, 11); + + if ((obj = _parseUntil(self, ' ')) != nil) + [result_ setObject:obj forKey:@"mailbox"]; + if ((obj = _parseUntil(self, ' ')) != nil) + [result_ setObject:obj forKey:@"uid"]; + + if ((obj = _parseUntil(self, ' ')) != nil) { + if ([obj isEqual:@"\"\""]) + obj = @""; + [result_ setObject:obj forKey:@"requiredRights"]; + } + + rights = _parseUntil(self, '\n'); + [result_ setObject:[rights componentsSeparatedByString:@" "] + forKey:@"listrights"]; + return YES; +} + - (BOOL)_parseSearchResponseIntoHashMap:(NGMutableHashMap *)result_ { NSMutableArray *msn = nil; @@ -749,8 +860,8 @@ static void _parseUntaggedResponse(NGImap4ResponseParser *self, _consume(self, 6); quota = [result_ objectForKey:@"quota"]; - - if (!quota) { + + if (quota == nil) { quota = [NSMutableDictionary dictionaryWithCapacity:2]; [result_ setObject:quota forKey:@"quota"]; } diff --git a/sope-mime/Version b/sope-mime/Version index 02b9ee5d..a2300f74 100644 --- a/sope-mime/Version +++ b/sope-mime/Version @@ -2,7 +2,7 @@ MAJOR_VERSION:=4 MINOR_VERSION:=5 -SUBMINOR_VERSION:=220 +SUBMINOR_VERSION:=221 # v4.5.214 requires libNGExtensions v4.5.146 # v4.2.149 requires libNGStreams v4.2.34 diff --git a/sope-mime/samples/ChangeLog b/sope-mime/samples/ChangeLog index 024ae5bd..51a889d0 100644 --- a/sope-mime/samples/ChangeLog +++ b/sope-mime/samples/ChangeLog @@ -1,3 +1,7 @@ +2005-07-05 Helge Hess + + * added imapacl tool to test ACL related IMAP4 commands + 2005-03-03 Helge Hess * ImapListTool.m: improved output with directories diff --git a/sope-mime/samples/GNUmakefile b/sope-mime/samples/GNUmakefile index 08a12f41..c6c22365 100644 --- a/sope-mime/samples/GNUmakefile +++ b/sope-mime/samples/GNUmakefile @@ -8,10 +8,12 @@ TOOL_NAME = \ imapls \ test_qpdecode \ imapquota \ + imapacl \ imap_tool \ sievetool imapquota_OBJC_FILES = ImapQuotaTool.m ImapTool.m imapquota.m +imapacl_OBJC_FILES = ImapQuotaTool.m ImapTool.m imapacl.m imapget_OBJC_FILES = ImapTool.m imapget.m imap_tool_OBJC_FILES = imap_tool.m mime2xml_OBJC_FILES = Mime2XmlTool.m mime2xml.m diff --git a/sope-mime/samples/ImapQuotaTool.m b/sope-mime/samples/ImapQuotaTool.m index 4a3d5584..bb4ec978 100644 --- a/sope-mime/samples/ImapQuotaTool.m +++ b/sope-mime/samples/ImapQuotaTool.m @@ -35,7 +35,6 @@ client = [[fm imapContext] client]; return [[client getQuotaRoot:_folder] objectForKey:@"quotas"]; - } @end /* ImapQuotaTool */ diff --git a/sope-mime/samples/imapacl.m b/sope-mime/samples/imapacl.m new file mode 100644 index 00000000..ebac621e --- /dev/null +++ b/sope-mime/samples/imapacl.m @@ -0,0 +1,75 @@ +/* + Copyright (C) 2000-2005 SKYRIX Software AG + + This file is part of SOPE. + + SOPE is free software; you can redistribute it and/or modify it under + the terms of the GNU Lesser General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + SOPE is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with SOPE; see the file COPYING. If not, write to the + Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. +*/ + +#include +#include +#include +#include "ImapQuotaTool.h" +#include "common.h" + +int main(int argc, char **argv, char **env) { + NSAutoreleasePool *pool; + ImapQuotaTool *tool; + int res = 0; + + pool = [NSAutoreleasePool new]; + +#if LIB_FOUNDATION_LIBRARY + [NSProcessInfo initializeWithArguments:argv count:argc environment:env]; +#endif + + tool = [[ImapQuotaTool alloc] init]; + + { + NGImap4Client *client; + NSString *mailbox; + + client = [[[tool fileManager] imapContext] client]; + + mailbox = [[NSUserDefaults standardUserDefaults] objectForKey:@"path"]; + NSLog(@"acl test on path: %@", mailbox); + NSLog(@" acl %@", [[client getACL:mailbox] valueForKey:@"acl"]); + + NSLog(@" set urks 'lr' %@", + [[client setACL:mailbox rights:@"lr" uid:@"urks"] + valueForKey:@"result"]); + NSLog(@" acl %@", [[client getACL:mailbox] valueForKey:@"acl"]); + + NSLog(@" rm urks %@", + [[client deleteACL:mailbox uid:@"urks"] valueForKey:@"result"]); + NSLog(@" acl %@", [[client getACL:mailbox] valueForKey:@"acl"]); + + + NSLog(@" my rights: '%@'", + [[client myRights:mailbox] valueForKey:@"myrights"]); + + NSLog(@" list rights: %@", + [[[client listRights:mailbox uid:@"urks"] + valueForKey:@"listrights"] componentsJoinedByString:@","]); + } + [tool release]; + + [pool release]; + exit(res); + /* static linking */ + [NGExtensions class]; + return res; +} diff --git a/sope-mime/samples/imapquota.m b/sope-mime/samples/imapquota.m index 31927143..76282de0 100644 --- a/sope-mime/samples/imapquota.m +++ b/sope-mime/samples/imapquota.m @@ -37,7 +37,7 @@ int main(int argc, char **argv, char **env) { { NSString *str; - + str = [[NSUserDefaults standardUserDefaults] objectForKey:@"path"]; NSLog(@"quota for path: %@", str); NSLog(@"result %@", [tool getQuotaRoot:str]); -- 2.39.5