]> err.no Git - scalable-opengroupware.org/commitdiff
added shares discovery
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 7 Jul 2005 11:15:31 +0000 (11:15 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Thu, 7 Jul 2005 11:15:31 +0000 (11:15 +0000)
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@682 d1b88da0-ebda-0310-925b-ed51d893ca5b

SOGo/SoObjects/SOGo/AgenorUserManager.h
SOGo/SoObjects/SOGo/AgenorUserManager.m
SOGo/SoObjects/SOGo/ChangeLog
SOGo/SoObjects/SOGo/GNUmakefile
SOGo/SoObjects/SOGo/GNUmakefile.preamble
SOGo/SoObjects/SOGo/Version
SOGo/SoObjects/SOGo/agenor_email2uid.m
SOGo/SoObjects/SOGo/agenor_shares4uid.m [new file with mode: 0644]

index 5f59108290394159be8d2092d53aba2439154592..4aef5cd66700b87a4766858c419195b0449f5e40 100644 (file)
 #ifndef        __AgenorUserManager_H_
 #define        __AgenorUserManager_H_
 
-#import <Foundation/Foundation.h>
+#import <Foundation/NSObject.h>
 
+/*
+  AgenorUserManager
+
+  TODO: document
+*/
+
+@class NSString, NSArray, NSURL;
 @class SOGoLRUCache;
 
 @interface AgenorUserManager : NSObject
 
 /* i.e. BUTTO Hercule, CETE Lyon/DI/ET/TEST */
 - (NSString *)getCNForUID:(NSString *)_uid;
+
 /* i.e. hercule.butto@amelie-ida01.melanie2.i2 */
 - (NSString *)getIMAPAccountStringForUID:(NSString *)_uid;
+
 /* i.e. amelie-ida01.melanie2.i2 */
 - (NSString *)getServerForUID:(NSString *)_uid;
 
+- (NSArray *)getSharedMailboxAccountStringsForUID:(NSString *)_uid;
+
 - (NSURL *)getFreeBusyURLForUID:(NSString *)_uid;
 
 @end
index a71cf1779373c6f1da0f0d99a61cf42bd50284c2..109d8c0b6c4f790f1f0820cbe217d8bec9a85c1f 100644 (file)
@@ -38,6 +38,7 @@
   
 @end
 
+// TODO: add a timer to flush LRU caches every some hours
 
 @implementation AgenorUserManager
 
@@ -178,38 +179,37 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
 */
 
 - (NSString *)primaryGetAgenorUIDForEmail:(NSString *)_email {
-    static NSArray   *uidAttrs = nil;
-    NGLdapConnection *conn;
-    EOQualifier      *q;
-    NSEnumerator     *resultEnum;
-    NGLdapEntry      *entry;
-    NGLdapAttribute  *uidAttr;
-    NSString         *uid;
-
-    if(!uidAttrs) {
-      uidAttrs = [[NSArray alloc] initWithObjects:@"uid", nil];
-    }
+  static NSArray   *uidAttrs = nil;
+  NGLdapConnection *conn;
+  EOQualifier      *q;
+  NSEnumerator     *resultEnum;
+  NGLdapEntry      *entry;
+  NGLdapAttribute  *uidAttr;
+  NSString         *uid;
+
+  if (uidAttrs == nil)
+    uidAttrs = [[NSArray alloc] initWithObjects:@"uid", nil];
     
-    q = [EOQualifier qualifierWithQualifierFormat:@"mail = %@", _email];
+  q = [EOQualifier qualifierWithQualifierFormat:@"mail = %@", _email];
     
-    conn       = [self ldapConnection];
-    resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
-                       qualifier:q
-                       attributes:uidAttrs];
-    entry = [resultEnum nextObject];
-    if (entry == nil) {
-      if(debugOn) {
-        [self logWithFormat:@"%s Didn't find LDAP entry for email '%@'!",
-                              __PRETTY_FUNCTION__,
-                              _email];
-      }
-      return nil;
+  conn       = [self ldapConnection];
+  resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+                    qualifier:q
+                    attributes:uidAttrs];
+  entry = [resultEnum nextObject];
+  if (entry == nil) {
+    if(debugOn) {
+      [self logWithFormat:@"%s Didn't find LDAP entry for email '%@'!",
+           __PRETTY_FUNCTION__,
+           _email];
     }
-    uidAttr = [entry attributeWithName:@"uid"];
-    if (!uidAttr)
-      return nil; /* can happen, not unlikely */
-    uid = [uidAttr stringValueAtIndex:0];
-    return uid;
+    return nil;
+  }
+  uidAttr = [entry attributeWithName:@"uid"];
+  if (!uidAttr)
+    return nil; /* can happen, not unlikely */
+  uid = [uidAttr stringValueAtIndex:0];
+  return uid;
 }
 
 - (NSString *)getUIDForEmail:(NSString *)_email {
@@ -342,7 +342,7 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
     cnAttrs = [[NSArray alloc] initWithObjects:@"cn", nil];
   
   q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid];
-    
+  
   conn = [self ldapConnection];
   resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
                     qualifier:q
@@ -408,26 +408,33 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
   return [NSString stringWithFormat:@"%@@%@", _uid, server];
 }
 
-- (NGLdapEntry *)_fetchEntryForAgenorUID:(NSString *)_uid {
-  static NSArray   *attrs = nil;
-  NGLdapConnection *conn;
-  EOQualifier      *q;
-  NSEnumerator     *resultEnum;
-  NGLdapEntry      *entry;
-  
+- (NSArray *)mailServerDiscoveryAttributes {
+  static NSArray *attrs = nil;
+
   if (attrs == nil) {
     attrs = [[NSArray alloc] initWithObjects:
+                              @"uid", /* required for shares */
                               @"mineqMelRoutage", 
                               @"mineqMelServeurPrincipal",
                             nil];
   }
+  return attrs;
+}
+
+- (NGLdapEntry *)_fetchEntryForAgenorUID:(NSString *)_uid {
+  // TODO: badly named, this fetches the mail server discovery attributes
+  /* called by -primaryGetServerForAgenorUID: */
+  NGLdapConnection *conn;
+  EOQualifier      *q;
+  NSEnumerator     *resultEnum;
+  NGLdapEntry      *entry;
   
   q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid];
-
+  
   conn = [self ldapConnection];
   resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
                     qualifier:q
-                    attributes:attrs];
+                    attributes:[self mailServerDiscoveryAttributes]];
   /* we just expect one entry, thus drop the rest */
   entry = [resultEnum nextObject];
   if (entry == nil) {
@@ -442,45 +449,109 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
 }
 
 - (NSArray *)_serverCandidatesForMineqMelRoutage:(NGLdapAttribute *)attr {
+  /*
+    eg:
+      "Baluh.Hommes.Tests-Montee-En-Charge-Ogo%equipement.gouv.fr@\
+       amelie-01.ac.melanie2.i2"
+  */
   NSMutableArray *serverCandidates;
-
   unsigned i, count;
 
-  count = [attr count];
+  count            = [attr count];
   serverCandidates = [NSMutableArray arrayWithCapacity:count];
-  for(i = 0; i < count; i++) {
-    NSRange r;
+  for (i = 0; i < count; i++) {
+    NSRange  r;
     NSString *route;
-
+    unsigned length;
+    unsigned start;
+    NSRange  serverNameRange;
+    NSString *serverName;
+    
     route = [attr stringValueAtIndex:i];
+
+    /* check for melanie suffix and ignore other entries */
+    
     r = [route rangeOfString:@".melanie2.i2" options:NSBackwardsSearch];
-    if(r.length > 0) {
-      unsigned length;
-
-      /* be clever */
-      length = [route length];
-      r = NSMakeRange(0, length - r.length);
-      r = [route rangeOfString:@"@" options:NSBackwardsSearch range:r];
-      if(r.length > 0) {
-        unsigned start;
-        NSRange serverNameRange;
-        
-        start = NSMaxRange(r);
-        serverNameRange = NSMakeRange(start, length - start);
-        r = NSMakeRange(0, length - start);
-        r = [route rangeOfString:@"%" options:NSBackwardsSearch range:r];
-        if(r.length > 0) {
-          NSString *serverName;
-          
-          serverName = [route substringWithRange:serverNameRange];
-          [serverCandidates addObject:serverName];
-        }
-      }
+    if (r.length == 0) {
+#if 0
+      [self logWithFormat:@"found no melanie in route: '%@'", route];
+#endif
+      continue;
     }
+
+    /* check for @ inside the string, searching backwards (ignoring suffix) */
+    
+    // be clever: TODO: in what way is this clever?
+    length = [route length];
+    r = NSMakeRange(0, length - r.length); /* cut of suffix (.melanie2.i2) */
+    r = [route rangeOfString:@"@" options:NSBackwardsSearch range:r];
+    if (r.length == 0) {
+#if 0
+      [self logWithFormat:@"found no @ in route: '%@'", route];
+#endif
+      continue;
+    }
+    
+    /* check for percent sign */
+    
+    start = NSMaxRange(r); /* start behind the @ */
+    
+    /* this range covers everything after @: 'amelie-01.ac.melanie2.i2' */
+    serverNameRange = NSMakeRange(start, length - start);
+    
+    /* and this range covers everything to the @ */
+    r = NSMakeRange(0, start - 1);
+    r = [route rangeOfString:@"%" options:NSBackwardsSearch range:r];
+    if (r.length == 0) {
+#if 0
+      [self logWithFormat:@"found no %% in route: '%@' / '%@'", 
+           route, [route substringWithRange:NSMakeRange(0, length - start)]];
+#endif
+      continue;
+    }
+    
+    serverName = [route substringWithRange:serverNameRange];
+    [serverCandidates addObject:serverName];
   }
   return serverCandidates;
 }
 
+- (NSString *)serverFromEntry:(NGLdapEntry *)_entry {
+  NSString        *server;
+  NGLdapAttribute *attr;
+
+  server = nil;
+  
+  attr = [_entry attributeWithName:@"mineqMelRoutage"];
+  if (attr != nil) {
+    NSArray *serverCandidates;
+    
+    serverCandidates = [self _serverCandidatesForMineqMelRoutage:attr];
+    if ([serverCandidates count] > 0)
+      server = [serverCandidates objectAtIndex:0];
+    
+    if ([serverCandidates count] > 1) {
+      [self logWithFormat:
+             @"WARNING: more than one value for 'mineqMelRoutage': %@",
+             serverCandidates];
+    }
+  }
+  else {
+    [self debugWithFormat:
+           @"%s LDAP entry '%@' has no mineqMelRoutage entry?",
+           __PRETTY_FUNCTION__, [_entry dn]];
+  }
+  
+  /* last resort */
+  if (server == nil) {
+    attr = [_entry attributeWithName:@"mineqMelServeurPrincipal"];
+    if ([attr count] > 0)
+      server = [attr stringValueAtIndex:0];
+  }
+  
+  return server;
+}
+
 - (NSString *)primaryGetServerForAgenorUID:(NSString *)_uid {
   /*
    First of all : for a particular user IMAP and SMTP are served on the same
@@ -502,46 +573,21 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
    If the regex finds more than one servername when applied to the differents
    values, then the IMAP/SMTP server name is to be found in the
    mineqMelServeurPrincipal attribute of the user.
-   */
-  NSString        *server;
-  NGLdapEntry     *entry;
-  NGLdapAttribute *attr;
-
+  */
+  NSString    *server;
+  NGLdapEntry *entry;
+  
   if ((entry = [self _fetchEntryForAgenorUID:_uid]) == nil)
     return nil;
   
-  attr = [entry attributeWithName:@"mineqMelRoutage"];
-  if (attr != nil) {
-    NSArray *serverCandidates;
-    
-    serverCandidates = [self _serverCandidatesForMineqMelRoutage:attr];
-    
-    if ([serverCandidates count] > 0)
-      server = [serverCandidates objectAtIndex:0];
-  }
-  else {
-    [self debugWithFormat:
-           @"%s LDAP entry for uid '%@' has no mineqMelRoutage entry?",
-            __PRETTY_FUNCTION__,
-            _uid];
-  }
+  if ((server = [self serverFromEntry:entry]) != nil)
+    return server;
   
-  /* last resort */
-  if (server == nil) {
-      attr = [entry attributeWithName:@"mineqMelServeurPrincipal"];
-      if ([attr count] > 0)
-        server = [attr stringValueAtIndex:0];
-  }
-    
-  if (server == nil) {
-    [self debugWithFormat:
-             @"%s no chance of getting at server info for user '%@', "
-              @"tried everything. Sorry.",
-              __PRETTY_FUNCTION__,
-              _uid];
-    return nil;
-  }
-  return server;
+  [self debugWithFormat:
+         @"%s no chance of getting at server info for user '%@', "
+         @"tried everything. Sorry.",
+         __PRETTY_FUNCTION__, _uid];
+  return nil;
 }
 
 - (NSString *)getServerForUID:(NSString *)_uid {
@@ -555,7 +601,7 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
   
   if (useLDAP)
     server = [self primaryGetServerForAgenorUID:_uid];
-  else if (fallbackIMAP4Server)
+  else if (fallbackIMAP4Server != nil)
     server = fallbackIMAP4Server;
   else {
     [self logWithFormat:@"ERROR: could not get server for uid '%@', "
@@ -569,7 +615,84 @@ static NSString *defaultMailDomain   = @"equipement.gouv.fr";
   return server;
 }
 
+/* shared mailboxes */
+
+- (NSArray *)getSharedMailboxAccountStringsForUID:(NSString *)_uid {
+  /*
+    Sample:
+      "(&(mineqMelPartages=guizmo.g:*)(objectclass=mineqMelBoite))"
+      "guizmo.g" is the uid of the user
+
+    Login:
+      guizmo.g.-.baluh.hommes.tests-montee-en-charge-ogo
+      (uid + ".-." + share-uid)
+
+    Note: shared mailboxes can be on different hosts!
+  */
+  static NSString *shareLDAPClass      = @"mineqMelBoite";
+  static NSString *shareLoginSeparator = @".-.";
+  NSMutableArray   *shares = nil;
+  NGLdapConnection *conn;
+  EOQualifier  *q;
+  NSString     *sharePattern;
+  NSEnumerator *resultEnum;
+  NGLdapEntry  *entry;
+  
+  if ([_uid length] == 0)
+    return nil;
+  
+  if (!useLDAP) {
+    [self logWithFormat:
+           @"Note: LDAP access is disabled, returning no shared accounts."];
+    return nil;
+  }
+  
+  sharePattern = [_uid stringByAppendingString:@":*"];
+  
+  q = [EOQualifier qualifierWithQualifierFormat:
+                    @"(mineqMelPartages = %@) AND (objectclass = %@)",
+                    sharePattern, shareLDAPClass];
+  
+  conn = [self ldapConnection];
+
+  resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
+                    qualifier:q
+                    attributes:[self mailServerDiscoveryAttributes]];
+  
+  while ((entry = [resultEnum nextObject]) != nil) {
+    NSString *server, *shareLogin;
+    id shareUid;
+    
+    if ([(server = [self serverFromEntry:entry]) length] == 0) {
+      [self errorWithFormat:@"found no mail server host for share: %@",
+             [entry dn]];
+      continue;
+    }
+    
+    shareUid = [entry attributeWithName:@"uid"];
+    if ([shareUid count] < 1) {
+      [self errorWithFormat:@"found no 'uid' for share: %@", [entry dn]];
+      continue;
+    }
+    shareUid = [shareUid stringValueAtIndex:0];
+    
+    shareLogin = [_uid stringByAppendingString:shareLoginSeparator];
+    shareLogin = [shareLogin stringByAppendingString:shareUid];
+    
+    if (shares == nil)
+      shares = [NSMutableArray arrayWithCapacity:4];
+    
+    shareLogin = [shareLogin stringByAppendingString:@"@"];
+    shareLogin = [shareLogin stringByAppendingString:server];
+    [shares addObject:shareLogin];
+  }
+  return shares;
+}
+
+/* free busy */
+
 - (NSURL *)getFreeBusyURLForUID:(NSString *)_uid {
+  [self logWithFormat:@"TODO(%s): implement", __PRETTY_FUNCTION__];
   return nil;
 }
 
index 82084cda43a400b063f6c1def8b668fd456f8f97..c868afe2bd1e9a7e22c7ac65eb606ec619bb55ff 100644 (file)
@@ -1,3 +1,13 @@
+2005-07-07  Helge Hess  <helge.hess@opengroupware.org>
+       
+       * added agenor_shares4uid tool to check whether the uid=>shared mailbox
+         discovery in AgenorUserManager works
+       
+       * AgenorUserManager.m: fixed a major string scanning bug in
+         _serverCandidatesForMineqMelRoutage: method,
+         added -getSharedMailboxAccountStringsForUID: method to discover
+         shared IMAP4 accounts (v0.9.39)
+
 2005-07-07  Helge Hess  <helge.hess@opengroupware.org>
 
        * AgenorUserManager.m: added a simple -description method (v0.9.38)
index 1a00ae0288861c0009fac737474f5109a5f42658..e60ad52ce855a08f83fd9541d35b542f72bae16e 100644 (file)
@@ -6,7 +6,7 @@ include $(GNUSTEP_MAKEFILES)/common.make
 -include ./Version
 
 LIBRARY_NAME = libSOGo
-TOOL_NAME = agenor_email2uid
+TOOL_NAME = agenor_email2uid agenor_shares4uid
 
 libSOGo_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
 
@@ -50,6 +50,11 @@ agenor_email2uid_OBJC_FILES += \
        AgenorUserManager.m     \
        SOGoLRUCache.m          \
 
+agenor_shares4uid_OBJC_FILES += \
+       agenor_shares4uid.m     \
+       AgenorUserManager.m     \
+       SOGoLRUCache.m          \
+
 -include GNUmakefile.preamble
 include $(GNUSTEP_MAKEFILES)/library.make
 include $(GNUSTEP_MAKEFILES)/tool.make
index a5b5273616013c038d6224a97dbcb8762196e2d1..9ecfb2653d93f15b67e2b90cd5ad951cde348a86 100644 (file)
@@ -24,5 +24,5 @@ libSOGo_LIBRARIES_DEPEND_UPON += \
        -lXmlRpc -lDOM -lSaxObjC \
        -lNGLdap
 
-agenor_email2uid_TOOL_LIBS += \
-       -lNGLdap
+agenor_email2uid_TOOL_LIBS  += -lNGLdap
+agenor_shares4uid_TOOL_LIBS += -lNGLdap
index 4797ab0b967e893a82056992ca52d38d34ac8686..7638e7833552695acc3afde7cbdc84df08899f7a 100644 (file)
@@ -1,6 +1,6 @@
 # version file
 
-SUBMINOR_VERSION:=38
+SUBMINOR_VERSION:=39
 
 # v0.9.34 requires libGDLContentStore v4.5.26
 # v0.9.26 requires libOGoContentStore v0.9.13
index 09c36c3e4da237981d0748eef3a4209002b53251..056fda7900ef2f042428b5134716b01c2431a183 100644 (file)
@@ -38,7 +38,6 @@ static void doIt(NSArray *args) {
   }
   
   userManager = [AgenorUserManager sharedUserManager];
-  NSLog(@"We are using user manager: %@", userManager);
   
   e = [args objectEnumerator];
   [e nextObject]; /* consume the command name */
diff --git a/SOGo/SoObjects/SOGo/agenor_shares4uid.m b/SOGo/SoObjects/SOGo/agenor_shares4uid.m
new file mode 100644 (file)
index 0000000..eb95bce
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  Copyright (C) 2005 SKYRIX Software AG
+
+  This file is part of OpenGroupware.org.
+
+  OGo 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.
+
+  OGo 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 OGo; see the file COPYING.  If not, write to the
+  Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+  02111-1307, USA.
+*/
+
+#include "AgenorUserManager.h"
+#include "common.h"
+
+static void usage(NSArray *args) {
+  fprintf(stderr, "usage: %s <uid1> <uid2> <uid3>\n",
+         [[args objectAtIndex:0] cString]);
+}
+
+static void handleUID(NSString *uid, AgenorUserManager *userManager) {
+  NSArray  *shares;
+  unsigned i, count;
+  
+  shares = [userManager getSharedMailboxAccountStringsForUID:uid];
+  
+  printf("%s:", [uid cString]);
+  
+  if ((count = [shares count]) == 0) {
+    printf(" <no shares>\n");
+    return;
+  }
+  
+  puts("");
+  for (i = 0; i < count; i++)
+    printf("  %s\n", [[shares objectAtIndex:i] cString]);
+}
+
+static void doIt(NSArray *args) {
+  AgenorUserManager *userManager;
+  NSEnumerator *e;
+  NSString     *uid;
+  
+  if ([args count] < 2) {
+    usage(args);
+    return;
+  }
+  
+  userManager = [AgenorUserManager sharedUserManager];
+  
+  e = [args objectEnumerator];
+  [e nextObject]; /* consume the command name */
+  
+  while ((uid = [e nextObject]) != nil)
+    handleUID(uid, userManager);
+}
+
+int main(int argc, char **argv, char **env) {
+  NSAutoreleasePool *pool;
+  
+  pool = [[NSAutoreleasePool alloc] init];
+#if LIB_FOUNDATION_LIBRARY
+  [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
+#endif
+  
+  doIt([[NSProcessInfo processInfo] argumentsWithoutDefaults]);
+  
+  [pool release];
+  return 0;
+}