]> err.no Git - scalable-opengroupware.org/commitdiff
fixed SOGo bug #1137
authorznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Mon, 24 Jan 2005 17:50:45 +0000 (17:50 +0000)
committerznek <znek@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Mon, 24 Jan 2005 17:50:45 +0000 (17:50 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@494 d1b88da0-ebda-0310-925b-ed51d893ca5b

SOGo/UI/Common/ChangeLog
SOGo/UI/Common/UIxPageFrame.wox
SOGo/UI/Common/Version
SOGoLogic/AgenorUserManager.h
SOGoLogic/AgenorUserManager.m
SOGoLogic/ChangeLog
SOGoLogic/Version

index 1dc76a11da3bf42b404636c2fe0be759efe5fd2e..b4b95637cfceeccd72abf78d1c89d7a1c31c540e 100644 (file)
@@ -1,3 +1,7 @@
+2005-01-24  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * UIxPageFrame.wox: additional debug output (v0.9.34)
+
 2005-01-21  Helge Hess <helge.hess@opengroupware.org>
 
        * UIxTabView.m: fixed an include of WEExtensions (v0.9.33)
index 97a0ba4506f7d6b94fad73fb71b935fe986263af..4678202ea60282a5b45afbe1006012d2a5777985 100644 (file)
                 <td valign="top">active user:</td>
                 <td valign="top"><var:string value="context.activeUser"/></td>
               </tr>
-            </table>
+              <tr>
+                <td valign="top">CN / email:</td>
+                <td valign="top">
+                  <var:string value="cnForUser"/>
+                  <var:entity const:name="lt"
+                  /><var:string value="emailForUser"
+                    /><var:entity const:name="gt"
+                  /></td>
+              </tr>            </table>
           </td>
         </tr>
       </var:if>
index fa1a5842b798149e304b5a71d89eaff8b0f046c4..7374c9b8995453db277418878622b6c0ad74f8d3 100644 (file)
@@ -1,5 +1,5 @@
 # Version file
 
-SUBMINOR_VERSION:=33
+SUBMINOR_VERSION:=34
 
 # v0.9.28 requires NGExtensions v4.5.136
index 0716a19995afa7d361884a509145d8668d6d6dc4..ce35647e74212344b2af62aaa1549b80d11c4153 100644 (file)
@@ -33,6 +33,8 @@
 {
   SOGoLRUCache *cnCache;
   SOGoLRUCache *serverCache;
+  SOGoLRUCache *uidCache;
+  SOGoLRUCache *emailCache;
 }
 
 + (id)sharedUserManager;
index 06f7c49139eb20a04eb84bf21a62671ba045c417..81563a2f83986caa8be009c31256d06cd6227b43 100644 (file)
@@ -22,6 +22,7 @@
 
 
 #include "AgenorUserManager.h"
+#include <NGExtensions/NGExtensions.h>
 #include <NGLdap/NGLdap.h>
 #include "SOGoLRUCache.h"
 
 - (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;
   
index a49b50e4bb16e68df9b458d8108a591ae632c7b3..aee920703992b0dabafa61f211adec536f440ec2 100644 (file)
@@ -1,3 +1,11 @@
+2005-01-24  Marcus Mueller  <znek@mulle-kybernetik.com>
+
+       * 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  <znek@mulle-kybernetik.com>
 
        * SOGoAppointment.m: transparency is supported by NGiCal, thus fixed
index 6e58687bb7866c5aea8db8a8d423ba57137f7022..2f55a6e4eb52d11da7ce9a03f5bcaa1ee2bed7af 100644 (file)
@@ -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