@end
+// TODO: add a timer to flush LRU caches every some hours
@implementation AgenorUserManager
*/
- (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 {
cnAttrs = [[NSArray alloc] initWithObjects:@"cn", nil];
q = [EOQualifier qualifierWithQualifierFormat:@"uid = %@", _uid];
-
+
conn = [self ldapConnection];
resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
qualifier:q
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) {
}
- (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
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 {
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 '%@', "
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;
}
--- /dev/null
+/*
+ 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;
+}