From 11edee851a61ac6e8d61bf4252cad50bbbcff531 Mon Sep 17 00:00:00 2001 From: znek Date: Mon, 24 Jan 2005 17:50:45 +0000 Subject: [PATCH] fixed SOGo bug #1137 git-svn-id: http://svn.opengroupware.org/SOGo/trunk@494 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/UI/Common/ChangeLog | 4 + SOGo/UI/Common/UIxPageFrame.wox | 10 +- SOGo/UI/Common/Version | 2 +- SOGoLogic/AgenorUserManager.h | 2 + SOGoLogic/AgenorUserManager.m | 197 ++++++++++++++++++++++++++++---- SOGoLogic/ChangeLog | 8 ++ SOGoLogic/Version | 3 +- 7 files changed, 198 insertions(+), 28 deletions(-) diff --git a/SOGo/UI/Common/ChangeLog b/SOGo/UI/Common/ChangeLog index 1dc76a11..b4b95637 100644 --- a/SOGo/UI/Common/ChangeLog +++ b/SOGo/UI/Common/ChangeLog @@ -1,3 +1,7 @@ +2005-01-24 Marcus Mueller + + * UIxPageFrame.wox: additional debug output (v0.9.34) + 2005-01-21 Helge Hess * UIxTabView.m: fixed an include of WEExtensions (v0.9.33) diff --git a/SOGo/UI/Common/UIxPageFrame.wox b/SOGo/UI/Common/UIxPageFrame.wox index 97a0ba45..4678202e 100644 --- a/SOGo/UI/Common/UIxPageFrame.wox +++ b/SOGo/UI/Common/UIxPageFrame.wox @@ -112,7 +112,15 @@ active user: - + + CN / email: + + + + diff --git a/SOGo/UI/Common/Version b/SOGo/UI/Common/Version index fa1a5842..7374c9b8 100644 --- a/SOGo/UI/Common/Version +++ b/SOGo/UI/Common/Version @@ -1,5 +1,5 @@ # Version file -SUBMINOR_VERSION:=33 +SUBMINOR_VERSION:=34 # v0.9.28 requires NGExtensions v4.5.136 diff --git a/SOGoLogic/AgenorUserManager.h b/SOGoLogic/AgenorUserManager.h index 0716a199..ce35647e 100644 --- a/SOGoLogic/AgenorUserManager.h +++ b/SOGoLogic/AgenorUserManager.h @@ -33,6 +33,8 @@ { SOGoLRUCache *cnCache; SOGoLRUCache *serverCache; + SOGoLRUCache *uidCache; + SOGoLRUCache *emailCache; } + (id)sharedUserManager; diff --git a/SOGoLogic/AgenorUserManager.m b/SOGoLogic/AgenorUserManager.m index 06f7c491..81563a2f 100644 --- a/SOGoLogic/AgenorUserManager.m +++ b/SOGoLogic/AgenorUserManager.m @@ -22,6 +22,7 @@ #include "AgenorUserManager.h" +#include #include #include "SOGoLRUCache.h" @@ -32,6 +33,10 @@ - (NSString *)_cachedCNForUID:(NSString *)_uid; - (void)_cacheServer:(NSString *)_server forUID:(NSString *)_uid; - (NSString *)_cachedServerForUID:(NSString *)_uid; +- (void)_cacheEmail:(NSString *)_email forUID:(NSString *)_uid; +- (NSString *)_cachedEmailForUID:(NSString *)_uid; +- (void)_cacheUID:(NSString *)_uid forEmail:(NSString *)_email; +- (NSString *)_cachedUIDForEmail:(NSString *)_email; @end @@ -72,6 +77,8 @@ static NSString *ldapBaseDN = nil; if(self) { self->serverCache = [[SOGoLRUCache alloc] initWithCacheSize:10000]; self->cnCache = [[SOGoLRUCache alloc] initWithCacheSize:10000]; + self->uidCache = [[SOGoLRUCache alloc] initWithCacheSize:10000]; + self->emailCache = [[SOGoLRUCache alloc] initWithCacheSize:10000]; } return self; } @@ -79,6 +86,8 @@ static NSString *ldapBaseDN = nil; - (void)dealloc { [self->serverCache release]; [self->cnCache release]; + [self->uidCache release]; + [self->emailCache release]; [super dealloc]; } @@ -93,6 +102,9 @@ static NSString *ldapBaseDN = nil; return ldapConnection; } + +/* private cache helpers */ + - (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid { [self->cnCache addObject:_cn forKey:_uid]; } @@ -109,8 +121,31 @@ static NSString *ldapBaseDN = nil; return [self->serverCache objectForKey:_uid]; } +- (void)_cacheEmail:(NSString *)_email forUID:(NSString *)_uid { + [self->emailCache addObject:_email forKey:_uid]; +} + +- (NSString *)_cachedEmailForUID:(NSString *)_uid { + return [self->emailCache objectForKey:_uid]; +} + +- (void)_cacheUID:(NSString *)_uid forEmail:(NSString *)_email { + [self->uidCache addObject:_uid forKey:_email]; +} + +- (NSString *)_cachedUIDForEmail:(NSString *)_email { + return [self->uidCache objectForKey:_email]; +} + + +/* uid <-> email mapping */ /* + UPDATE: the email excerpt below has been marked by Maxime as being + wrong. This algorithm can not be expected to work, thus + the mapping has been replaced with an LDAP query. + + --- snip --- The uid field is in bijection this the email adress : this field can be construct from the email. Email are uniques. @@ -122,7 +157,8 @@ static NSString *ldapBaseDN = nil; _ if the email is not equipement.gouv.fr then the login is the full email adress where @ is change to . (dot) for example : fisrtName.lastName.subDomain.domain.tld - + --- snap --- + NOTE: mapping email -> uid is easy, but can also generate uid's not known to the system (i.e. for private addressbook entries, obvious). The reverse mapping can work _only_ if "firstName.lastname." is @@ -132,32 +168,139 @@ static NSString *ldapBaseDN = nil; */ - (NSString *)getUIDForEmail:(NSString *)_email { - NSRange r; - NSString *domain; - - if(!_email || [_email length] == 0) - return nil; + if(useLDAP) { + static NSArray *uidAttrs = nil; + NGLdapConnection *conn; + EOQualifier *q; + NSEnumerator *resultEnum; + NGLdapEntry *entry; + NGLdapAttribute *uidAttr; + NSString *uid; - r = [_email rangeOfString:@"@"]; - if(r.length == 0) - return nil; - domain = [_email substringFromIndex:NSMaxRange(r)]; - if(![domain isEqualToString:@"equipement.gouv.fr"]) + if(!uidAttrs) { + uidAttrs = [[NSArray alloc] initWithObjects:@"uid", nil]; + } + + if((uid = [self _cachedUIDForEmail:_email])) + return uid; + + q = [EOQualifier qualifierWithQualifierFormat:@"mail = %@", _email]; + + conn = [self ldapConnection]; + resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN + qualifier:q + attributes:uidAttrs]; + entry = [resultEnum nextObject]; + if(!entry) { + if(debugOn) { + [self logWithFormat:@"%s Didn't find LDAP entry for email '%@'!", + __PRETTY_FUNCTION__, + _email]; + } + return nil; + } + uidAttr = [entry attributeWithName:@"uid"]; + if (!uidAttr) + return nil; /* can happen, not unlikely */ + uid = [uidAttr stringValueAtIndex:0]; + [self _cacheUID:uid forEmail:_email]; + return uid; + } + else { + NSRange r; + NSString *domain; + + if(!_email || [_email length] == 0) + return nil; + + r = [_email rangeOfString:@"@"]; + if(r.length == 0) + return nil; + domain = [_email substringFromIndex:NSMaxRange(r)]; + if(![domain isEqualToString:@"equipement.gouv.fr"]) return _email; - return [_email substringToIndex:r.location]; + return [_email substringToIndex:r.location]; + } } - (NSString *)getEmailForUID:(NSString *)_uid { - NSRange r; - - if(!_uid || [_uid length] == 0) - return nil; - r = [_uid rangeOfString:@"@"]; - if(r.length > 0) + if(useLDAP) { + static NSArray *emailAttrs = nil; + NGLdapConnection *conn; + EOQualifier *q; + NSEnumerator *resultEnum; + NGLdapEntry *entry; + NGLdapAttribute *emailAttr; + NSString *email; + + if(!emailAttrs) { + emailAttrs = [[NSArray alloc] initWithObjects:@"mail", nil]; + } + + if((email = [self _cachedEmailForUID:_uid])) + return email; + + q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid]; + + conn = [self ldapConnection]; + resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN + qualifier:q + attributes:emailAttrs]; + entry = [resultEnum nextObject]; + if(!entry) { + if(debugOn) { + [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!", + __PRETTY_FUNCTION__, + _uid]; + } + return nil; + } + emailAttr = [entry attributeWithName:@"mail"]; + if (!emailAttr) { + return nil; /* shit happens */ + } + else { + unsigned count; + + email = nil; + count = [emailAttr count]; + if (count > 1) { + unsigned i; + + /* in case there are multiple email addresses, select the first + which doesn't have '@equipement.gouv.fr' in it */ + for (i = 0; i < count; i++) { + NSString *candidate; + + candidate = [emailAttr stringValueAtIndex:i]; + if (![candidate hasSuffix:@"@equipement.gouv.fr"]) { + email = candidate; + break; + } + } + } + if (email == nil && count > 0) { + email = [emailAttr stringValueAtIndex:0]; + } + [self _cacheEmail:email forUID:_uid]; + return email; + } + } + else { + NSRange r; + + if(!_uid || [_uid length] == 0) + return nil; + r = [_uid rangeOfString:@"@"]; + if(r.length > 0) return _uid; - return [NSString stringWithFormat:@"%@@equipement.gouv.fr", _uid]; + return [NSString stringWithFormat:@"%@@equipement.gouv.fr", _uid]; + } } + +/* CN */ + - (NSString *)getCNForUID:(NSString *)_uid { if(useLDAP) { static NSArray *cnAttrs = nil; @@ -184,17 +327,18 @@ static NSString *ldapBaseDN = nil; entry = [resultEnum nextObject]; if(!entry) { if(debugOn) { - NSLog(@"%s Didn't find LDAP entry for uid '%@'!", - __PRETTY_FUNCTION__, - _uid); + [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!", + __PRETTY_FUNCTION__, + _uid]; } return nil; } cnAttr = [entry attributeWithName:@"cn"]; if(!cnAttr && debugOn) { - NSLog(@"%s LDAP entry for uid '%@' has no common name?", - __PRETTY_FUNCTION__, - _uid); + [self logWithFormat:@"%s LDAP entry for uid '%@' has no common name?", + __PRETTY_FUNCTION__, + _uid]; + return nil; /* nothing we can do about it */ } cn = [cnAttr stringValueAtIndex:0]; [self _cacheCN:cn forUID:_uid]; @@ -217,6 +361,9 @@ static NSString *ldapBaseDN = nil; } } + +/* Servers, IMAP */ + - (NSString *)getIMAPAccountStringForUID:(NSString *)_uid { NSString *server; diff --git a/SOGoLogic/ChangeLog b/SOGoLogic/ChangeLog index a49b50e4..aee92070 100644 --- a/SOGoLogic/ChangeLog +++ b/SOGoLogic/ChangeLog @@ -1,3 +1,11 @@ +2005-01-24 Marcus Mueller + + * AgenorUserManager.[hm]: rewrote -getUIDForEmail: and -getEmailForUID: + to use LDAP lookups instead of the flawed algorithm used previously. + Both methods cache resolved values aggressively in order to minimize + the probable performance penalty. This solves SOGo Bug #1137. + (v0.9.34) + 2004-12-22 Marcus Mueller * SOGoAppointment.m: transparency is supported by NGiCal, thus fixed diff --git a/SOGoLogic/Version b/SOGoLogic/Version index 6e58687b..2f55a6e4 100644 --- a/SOGoLogic/Version +++ b/SOGoLogic/Version @@ -1,7 +1,8 @@ # Version file -SUBMINOR_VERSION:=33 +SUBMINOR_VERSION:=34 +# v0.9.34 requires libFoundation v1.0.67 # v0.9.32 requires NGiCal v4.5.37 # v0.9.31 requires NGiCal v4.5.36 # v0.9.26 requires NGExtensions v4.5.136 -- 2.39.5