#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
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;
}
- (void)dealloc {
[self->serverCache release];
[self->cnCache release];
+ [self->uidCache release];
+ [self->emailCache release];
[super dealloc];
}
return ldapConnection;
}
+
+/* private cache helpers */
+
- (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid {
[self->cnCache addObject:_cn forKey:_uid];
}
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.
_ 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
*/
- (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;
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];
}
}
+
+/* Servers, IMAP */
+
- (NSString *)getIMAPAccountStringForUID:(NSString *)_uid {
NSString *server;