+2007-05-09 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * SoObjects/SOGo/SOGoUser.m ([SOGoUser -primaryEmail]): new name
+ for "mail" method.
+ ([SOGoUser -systemEmail]): returns the email formed from the
+ username and the default mail domain.
+ ([SOGoUser -hasEmail:email]): test whether the user has the
+ specified email, in a case-insensitive way.
+
+ * SoObjects/SOGo/SOGoAuthenticator.m ([SOGoAuthenticator
+ -LDAPCheckLogin:_loginpassword:_pwd]): use the user manager to
+ check login information.
+
+ * SoObjects/Contacts/SOGoContactLDAPFolder.m
+ ([SOGoContactLDAPFolder
+ +contactFolderWithName:aNameandDisplayName:aDisplayNameinContainer:aContainer]):
+ no longer manage LDAP connections. The requests are forwarded to
+ the relevant LDAPSource instead.
+
+ * SoObjects/Contacts/SOGoContactFolders.m ([SOGoContactFolders
+ -appendSystemSources]): pass LDAPSource objects to
+ SOGoContactLDAPFolder instances.
+
+ * SoObjects/Mailer/SOGoDraftObject.m: extract the raw email
+ address of the "from" field before sending the message. Otherwise,
+ sending the mail won't work.
+
+ * UI/MailerUI/UIxMailEditor.m ([UIxMailEditor -fromEMails]):
+ rewrote this method to request all the available email identities
+ for the current user. Also, the from field also contains the full
+ name of the user, not just his/her email address.
+
+ * SoObjects/Appointments/SOGoCalendarComponent.m
+ ([SOGoCalendarComponent -iCalPersonWithUID:uid]): new method taken
+ from the previous module iCalEntityObject+Agenor.
+ ([SOGoCalendarComponent -getUIDForICalPerson:person]): idem.
+ ([SOGoCalendarComponent -getUIDsForICalPersons:iCalPersons]):
+ idem.
+
+ * SoObjects/Contacts/SOGoContactLDIFEntry.[hm]: new class module
+ replacing the SOGoContactLDAPEntry module. It was renamed as such
+ because it now receives a dictionary instead of an NGLdapEntry.
+ It thus can now handle data from any source of LDIF data, not
+ only coming from LDAP.
+
+ * SoObjects/SOGo/LDAPUserManager.[hm]: new class module
+ implementing most of what used to be the AgenorUserManager class.
+ The difference is that users are cached in the forme of
+ dictionaries and many sources are used. Also, it can be used to
+ search LDAP contacts.
+
+ * SoObjects/SOGo/LDAPSource.[hm]: new class module implementing
+ the concept of "ldap source", to be used by all the classes
+ needing access to LDAP-provided information: addressbooks and the
+ user manager. Most the method thereing are transcriptions of
+ methods previously found in SOGoContactLDAPFolder. It also contain
+ utility methods for user matching and authentification.
+
+ * SoObjects/Appointments/iCalEntityObject+Agenor.[hm]: removed
+ module, rendered useless by code refactoring.
+
+ * SoObjects/SOGo/AgenorUserManager.[hm]: removed module, replaced
+ with the freshly written "LDAPUserManager".
+
+2007-05-08 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * SoObjects/Contacts/SOGoContactLDAPEntry.[hm]: renamed to
+ SOGOContactLDIFEntry.
+
+ * SoObjects/Contacts/NGLdapEntry+Contact.[hm]: removed class
+ module, obsoleted by code in SOGo/LDAPSource.[hm].
+
+2007-05-04 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * UI/Common/UIxAclEditor.m ([UIxAclEditor -currentUserIsOwner]):
+ new method with an explicit name.
+
+2007-05-03 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * SoObjects/Appointments/SOGoCalendarComponent.m
+ ([SOGoCalendarComponent -isOrganizerOrOwner:user]): new method
+ replacing "isOrganizer:orOwner:" by taking only one instance of
+ SOGoUser as parameter.
+ ([SOGoCalendarComponent -participant:user]): new method replacing
+ the previous "isParticipant" boolean method by returning the first
+ participant matching the user passed as parameter. This method is
+ used so that both the regular email address and the "system email
+ address" of the user are matched against the participants emails.
+
+ * SoObjects/SOGo/AgenorUserManager.m ([AgenorUserManager
+ -getSystemEMailForUID:uid]): new method that returns the email
+ formed with the user's uid and the default mail domain.
+
+ * SoObjects/Appointments/SOGoCalendarComponent.m
+ ([SOGoCalendarComponent -rolesOfUser:login]): removed method that
+ was previously commented out.
+
+ * SoObjects/SOGo/SOGoUser.m ([SOGoUser -systemEmail]): new method
+ forwared to [AgenorUserManager getSystemEmailForUID:].
+
+ * UI/Scheduler/UIxComponentEditor.m ([UIxComponentEditor
+ -toolbar]): method replacing the one with the same name in the
+ task and appointment editor classes. This method makes also use of
+ the new method "isOrganizerOrOwner:" and "participant:" in
+ SOGoCalendarComponent.
+
+ * UI/Scheduler/UIxAppointmentEditor.m ([UIxAppointmentEditor
+ -toolbar]): removed method, replaced with a method with the same
+ name in UIxComponentEditor.
+
+ * UI/Scheduler/UIxTaskEditor.m ([UIxTaskEditor -toolbar]): removed
+ method, replaced with a method with the same name in
+ UIxComponentEditor.
+
+ * SoObjects/SOGo/AgenorUserDefaults.m ([AgenorUserDefaults
+ -primaryFetchProfile]): the values returned from the database are
+ converted to a put dictionary first, since the dictionary returned
+ is actually an immutable one, which can cause a crash afterwards.
+
2007-04-27 Wolfgang Sourdeau <wsourdeau@inverse.ca>
* SoObjects/SOGo/SOGoPermissions.m: added "SOGoRole_ObjectViewer"
+2007-05-03 Wolfgang Sourdeau <wsourdeau@inverse.ca>
+
+ * VSSaxDriver.m ([VSSaxDriver +initialize]): removed the space
+ character from the colonAndSemicolonCharSet and
+ colonSemicolonAndDquoteCharSet so that fields which contain
+ attributes with values containing spaces don't get cut.
+
2006-07-04 Helge Hess <helge.hess@opengroupware.org>
* use %p for pointer formats, fixed gcc 4.1 warnings (v4.5.24)
commaCharSet =
[[NSCharacterSet characterSetWithCharactersInString: @","] retain];
colonAndSemicolonCharSet =
- [[NSCharacterSet characterSetWithCharactersInString: @": ;"] retain];
+ [[NSCharacterSet characterSetWithCharactersInString: @":;"] retain];
colonSemicolonAndDquoteCharSet =
- [[NSCharacterSet characterSetWithCharactersInString: @": ;\""] retain];
+ [[NSCharacterSet characterSetWithCharactersInString: @":;\""] retain];
whitespaceCharSet =
[[NSCharacterSet whitespaceCharacterSet] retain];
--- /dev/null
+#! /bin/sh
+
+PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
+
+DAEMON=/usr/local/sbin/sogod-0.9
+NAME=sogo
+DESC="Scalable OpenGroupware.Org"
+
+PIDFILE=/var/run/sogo/sogod.pid
+
+SOGO_ARGS=""
+
+if [ -f /etc/default/sogo ]; then
+ . /etc/default/sogo
+fi
+
+test -x $DAEMON || exit 0
+
+#set -e
+
+case "$1" in
+ start)
+ echo -n "Starting $DESC: "
+ start-stop-daemon -c sogo --pidfile $PIDFILE \
+ -b --start --quiet --exec $DAEMON
+ echo "$NAME."
+ ;;
+ stop)
+ echo -n "Stopping $DESC: "
+ killall sogod-0.9 2> /dev/null
+ rm -f $PIDFILE
+ echo "$NAME."
+ ;;
+ restart|force-reload)
+ echo -n "Restarting $DESC: "
+ killall sogod-0.9 2> /dev/null
+ rm -f $PIDFILE
+ sleep 1
+ start-stop-daemon -c sogo --pidfile $PIDFILE \
+ -b --start --quiet --exec $DAEMON
+ echo "$NAME."
+ ;;
+ *)
+ N=/etc/init.d/$NAME
+ echo "Usage: $N {start|stop|restart|force-reload}" >&2
+ exit 1
+ ;;
+esac
+
+exit 0
--- /dev/null
+#!/bin/sh
+
+export PATH=/usr/local/sbin:$PATH
+
+cd /root/SOGo
+# echo "Pulling monotone repository"
+
+oldversion=$(mtn status)
+mtn pull >& /dev/null
+mtn update >& /dev/null
+newversion=$(mtn status)
+
+if [ "$oldversion" == "$newversion" ]
+then
+ exit 0
+fi
+
+echo "SOGo mainsite updated at $(date)..."
+
+. /root/GNUstep/Library/Makefiles/GNUstep.sh >& /dev/null
+make distclean > /dev/null
+./configure --disable-strip --without-gnustep >& /dev/null
+make -s > /dev/null
+rm -rf /usr/local/lib/sogod-0.9
+make -s install > /dev/null
+# echo "Copying templates to /usr/local/share/sogo-0.9/templates"
+# rm -rf /usr/local/share/sogo-0.9/templates
+# cp -a UI/Templates /usr/local/share/sogo-0.9/templates
+# echo "Copying web resources to /usr/local/share/sogo-0.9/www"
+# cp -a UI/WebServerResources /usr/local/share/sogo-0.9/www
+# echo "Killing server"
+pkill sogod-0.9 >& /dev/null
+# echo "Starting sogod-0.9 (log in /var/log/sogod)"
+echo "Launching on $(date)" > /var/log/sogod
+sogod-0.9 >> /var/log/sogod 2>&1 &
+
--- /dev/null
+#!/bin/sh
+
+PIDFILE=/var/run/sogo/sogod.pid
+
+. /usr/local/lib/GNUstep-SOPE/Library/Makefiles/GNUstep.sh
+
+echo $$ > $PIDFILE
+exec $GNUSTEP_LOCAL_ROOT/Tools/sogod-0.9 >& /var/log/sogo/sogod.log
+
Appointments_OBJC_FILES = \
Product.m \
NSArray+Appointments.m \
- iCalEntityObject+Agenor.m \
\
SOGoCalendarComponent.m \
SOGoAppointmentObject.m \
// #import <NGObjWeb/SoClassSecurityInfo.h>
#import <SOGo/SOGoCustomGroupFolder.h>
-#import <SOGo/AgenorUserManager.h>
+#import <SOGo/LDAPUserManager.h>
#import <SOGo/SOGoPermissions.h>
#import <SOGo/NSString+Utilities.h>
#import <SOGo/SOGoUser.h>
privacySqlString = @"and (isopaque = 1)";
else
{
- email = [activeUser email];
+ email = [activeUser primaryEmail];
privacySqlString
= [NSString stringWithFormat:
{
/* Note: can return NSNull objects in the array! */
NSMutableArray *uids;
- AgenorUserManager *um;
+ LDAPUserManager *um;
unsigned i, count;
if (_persons == nil)
count = [_persons count];
uids = [NSMutableArray arrayWithCapacity:count + 1];
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
for (i = 0; i < count; i++) {
iCalPerson *person;
#import <NGCards/iCalEventChanges.h>
#import <NGCards/iCalPerson.h>
-#import <SOGo/AgenorUserManager.h>
-#import <SOGo/SOGoObject.h>
-#import <SOGo/SOGoPermissions.h>
-
-#import "iCalEntityObject+Agenor.h"
+#import <SoObjects/SOGo/LDAPUserManager.h>
+#import <SoObjects/SOGo/SOGoObject.h>
+#import <SoObjects/SOGo/SOGoPermissions.h>
#import "common.h"
/* iCal handling */
- (NSArray *) attendeeUIDsFromAppointment: (iCalEvent *) _apt
{
- AgenorUserManager *um;
+ LDAPUserManager *um;
NSMutableArray *uids;
NSArray *attendees;
unsigned i, count;
count = [attendees count];
uids = [NSMutableArray arrayWithCapacity:count + 1];
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
/* add organizer */
email = [[_apt organizer] rfc822Email];
if ([email isNotNull]) {
- uid = [um getUIDForEmail:email];
+ uid = [um getUIDForEmail: email];
if ([uid isNotNull]) {
[uids addObject:uid];
}
- delete in removed folders
- send iMIP mail for all folders not found
*/
- AgenorUserManager *um;
+ LDAPUserManager *um;
iCalEvent *oldApt, *newApt;
iCalEventChanges *changes;
iCalPerson *organizer;
return [NSException exceptionWithHTTPStatus: 400 /* Bad Request */
reason: @"got no iCalendar content to store!"];
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
/* handle old content */
/* diff */
changes = [iCalEventChanges changesFromEvent: oldApt toEvent: newApt];
- uids = [um getUIDsForICalPersons: [changes deletedAttendees]
- applyStrictMapping: NO];
+ uids = [self getUIDsForICalPersons: [changes deletedAttendees]];
removedUIDs = [NSMutableArray arrayWithArray: uids];
- uids = [um getUIDsForICalPersons: [newApt attendees]
- applyStrictMapping: NO];
+ uids = [self getUIDsForICalPersons: [newApt attendees]];
storeUIDs = [NSMutableArray arrayWithArray: uids];
props = [changes updatedProperties];
/* preserve organizer */
organizer = [newApt organizer];
- uid = [um getUIDForICalPerson: organizer];
+ uid = [self getUIDForICalPerson: organizer];
if (!uid)
uid = [self ownerInContext: nil];
if (uid) {
/* organizer might have changed completely */
if (oldApt && ([props containsObject: @"organizer"])) {
- uid = [um getUIDForICalPerson:[oldApt organizer]];
+ uid = [self getUIDForICalPerson:[oldApt organizer]];
if (uid) {
if (![storeUIDs containsObject:uid]) {
if (![removedUIDs containsObject:uid]) {
NSString *newContentString, *oldContentString;
iCalCalendar *eventCalendar;
iCalEvent *event;
+ iCalPerson *organizer;
NSArray *organizers;
oldContentString = [self contentAsString];
newContentString = contentString;
else
{
- [event setOrganizerWithUid: [[self container] ownerInContext: nil]];
+ organizer = [self iCalPersonWithUID: [self ownerInContext: context]];
+ [event setOrganizer: organizer];
newContentString = [eventCalendar versitString];
}
}
-<#IsSubject>Apt le <#AptStartDate /> at <#AptStartTime /></#IsSubject>
+<#IsSubject>Appointment on <#AptStartDate /> at <#AptStartTime /></#IsSubject>
<#IsBody>
You're invited by <#Organizer /> to a meeting.
<#HasHomePageURL>
@class NSString;
@class iCalCalendar;
+@class iCalPerson;
@class iCalRepeatableEntityObject;
+@class SOGoUser;
+
@interface SOGoCalendarComponent : SOGoContentObject
{
iCalCalendar *calendar;
andNewObject: (iCalRepeatableEntityObject *) _newObject
toAttendees: (NSArray *) _attendees;
-- (BOOL) isOrganizer: (NSString *) email
- orOwner: (NSString *) login;
-- (BOOL) isParticipant: (NSString *) email;
+- (BOOL) isOrganizerOrOwner: (SOGoUser *) user;
+- (iCalPerson *) participant: (SOGoUser *) user;
+
+- (iCalPerson *) iCalPersonWithUID: (NSString *) uid;
+- (NSString *) getUIDForICalPerson: (iCalPerson *) person;
+- (NSArray *) getUIDsForICalPersons: (NSArray *) iCalPersons;
@end
#import <NGMail/NGMail.h>
#import <NGMail/NGSendMail.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
tmpCalendar = [iCalCalendar parseSingleFromSource: tmpContent];
tmpComponent = (iCalRepeatableEntityObject *)
[tmpCalendar firstChildWithTag: [self componentTag]];
- email = [[context activeUser] email];
+ email = [[context activeUser] primaryEmail];
if (!([tmpComponent isOrganizer: email]
|| [tmpComponent isParticipant: email]))
{
- (iCalRepeatableEntityObject *) component: (BOOL) create
{
- return (iCalRepeatableEntityObject *)
- [[self calendar: create]
- firstChildWithTag: [self componentTag]];
+ return
+ (iCalRepeatableEntityObject *) [[self calendar: create]
+ firstChildWithTag: [self componentTag]];
}
- (BOOL) isNew
baseURL = @"http://localhost/";
[self warnWithFormat:@"Unable to create baseURL from context!"];
}
- uid = [[AgenorUserManager sharedUserManager]
+ uid = [[LDAPUserManager sharedUserManager]
getUIDForEmail: [_person rfc822Email]];
return ((uid)
component = [self component: NO];
if (component)
{
- myEMail = [[context activeUser] email];
+ myEMail = [[context activeUser] primaryEmail];
p = [component findParticipantWithEmail: myEMail];
if (p)
{
{
NSString *uid;
- uid = [[AgenorUserManager sharedUserManager] getUIDForEmail: email];
+ uid = [[LDAPUserManager sharedUserManager] getUIDForEmail: email];
- return [[SOGoUser userWithLogin: uid andRoles: nil] timeZone];
+ return [[SOGoUser userWithLogin: uid roles: nil] timeZone];
}
- (void) sendEMailUsingTemplateNamed: (NSString *) _pageName
}
}
-// - (NSArray *) rolesOfUser: (NSString *) login
-// {
-// AgenorUserManager *um;
-// iCalRepeatableEntityObject *component;
-// NSMutableArray *sogoRoles;
-// NSString *email;
-// SOGoUser *user;
-
-// sogoRoles = [NSMutableArray new];
-// [sogoRoles autorelease];
-
-// um = [AgenorUserManager sharedUserManager];
-// email = [um getEmailForUID: login];
-
-// component = [self component: NO];
-// if (component)
-// {
-// if ([component isOrganizer: email])
-// [sogoRoles addObject: SOGoCalendarRole_Organizer];
-// else if ([component isParticipant: email])
-// [sogoRoles addObject: SOGoCalendarRole_Participant];
-// else if ([[container ownerInContext: context] isEqualToString: login])
-// [sogoRoles addObject: SoRole_Owner];
-// }
-// else
-// {
-// user = [SOGoUser userWithLogin: login andRoles: nil];
-// [sogoRoles addObjectsFromArray: [user rolesForObject: container
-// inContext: context]];
-// }
-
-// return sogoRoles;
-// }
-
-- (BOOL) isOrganizer: (NSString *) email
- orOwner: (NSString *) login
+- (BOOL) isOrganizerOrOwner: (SOGoUser *) user
{
BOOL isOrganizerOrOwner;
iCalRepeatableEntityObject *component;
component = [self component: NO];
organizerEmail = [[component organizer] rfc822Email];
if (component && [organizerEmail length] > 0)
- isOrganizerOrOwner
- = ([organizerEmail caseInsensitiveCompare: email] == NSOrderedSame);
+ isOrganizerOrOwner = [user hasEmail: organizerEmail];
else
isOrganizerOrOwner
- = [[container ownerInContext: context] isEqualToString: login];
+ = [[container ownerInContext: context] isEqualToString: [user login]];
return isOrganizerOrOwner;
}
-- (BOOL) isParticipant: (NSString *) email
+- (iCalPerson *) participant: (SOGoUser *) user
{
- BOOL isParticipant;
- iCalRepeatableEntityObject *component;
+ iCalPerson *participant, *currentParticipant;
+ iCalEntityObject *component;
+ NSEnumerator *participants;
+ participant = nil;
component = [self component: NO];
if (component)
- isParticipant = [component isParticipant: email];
- else
- isParticipant = NO;
+ {
+ participants = [[component participants] objectEnumerator];
+ currentParticipant = [participants nextObject];
+ while (currentParticipant && !participant)
+ if ([user hasEmail: [currentParticipant rfc822Email]])
+ participant = currentParticipant;
+ else
+ currentParticipant = [participants nextObject];
+ }
+
+ return participant;
+}
+
+- (iCalPerson *) iCalPersonWithUID: (NSString *) uid
+{
+ iCalPerson *person;
+ LDAPUserManager *um;
+ NSDictionary *contactInfos;
+
+ um = [LDAPUserManager sharedUserManager];
+ contactInfos = [um contactInfosForUserWithUIDorEmail: uid];
+
+ person = [iCalPerson new];
+ [person autorelease];
+ [person setCn: [contactInfos objectForKey: @"cn"]];
+ [person setEmail: [contactInfos objectForKey: @"c_email"]];
+
+ return person;
+}
+
+- (NSString *) getUIDForICalPerson: (iCalPerson *) person
+{
+ LDAPUserManager *um;
+
+ um = [LDAPUserManager sharedUserManager];
+
+ return [um getUIDForEmail: [person rfc822Email]];
+}
+
+- (NSArray *) getUIDsForICalPersons: (NSArray *) iCalPersons
+{
+ iCalPerson *currentPerson;
+ NSEnumerator *persons;
+ NSMutableArray *uids;
+ NSString *email;
+ LDAPUserManager *um;
+
+ uids = [NSMutableArray array];
+
+ um = [LDAPUserManager sharedUserManager];
+ persons = [iCalPersons objectEnumerator];
+ currentPerson = [persons nextObject];
+ while (currentPerson)
+ {
+ email = [currentPerson rfc822Email];
+ [uids addObject: [um getUIDForEmail: email]];
+ currentPerson = [persons nextObject];
+ }
- return isParticipant;
+ return uids;
}
- (NSArray *) aclsForUser: (NSString *) uid
component = [self component: NO];
if (component)
{
- email = [[AgenorUserManager sharedUserManager] getEmailForUID: uid];
+ email = [[LDAPUserManager sharedUserManager] getEmailForUID: uid];
if ([component isOrganizer: email])
[roles addObject: SOGoCalendarRole_Organizer];
if ([component isParticipant: email])
/* accessors */
-- (NSString *)iCalString;
+- (NSString *) iCalString;
-- (NSString *)contentAsStringFrom:(NSCalendarDate *)_startDate
- to:(NSCalendarDate *)_endDate;
+- (NSString *) contentAsStringFrom: (NSCalendarDate *) _startDate
+ to: (NSCalendarDate *) _endDate;
-- (NSArray *)fetchFreeBusyInfosFrom:(NSCalendarDate *)_startDate
- to:(NSCalendarDate *)_endDate;
+- (NSArray *) fetchFreeBusyInfosFrom: (NSCalendarDate *) _startDate
+ to: (NSCalendarDate *) _endDate;
@end
#import <NGCards/iCalCalendar.h>
#import <NGCards/iCalFreeBusy.h>
+#import <NGCards/iCalPerson.h>
#import "common.h"
-#import <SOGo/AgenorUserManager.h>
+#import <SOGo/LDAPUserManager.h>
#import <SOGo/SOGoPermissions.h>
#import "SOGoFreeBusyObject.h"
return fbType;
}
+- (iCalPerson *) iCalPersonWithUID: (NSString *) uid
+{
+ iCalPerson *person;
+ LDAPUserManager *um;
+ NSDictionary *contactInfos;
+
+ um = [LDAPUserManager sharedUserManager];
+ contactInfos = [um contactInfosForUserWithUIDorEmail: uid];
+
+ person = [iCalPerson new];
+ [person autorelease];
+ [person setCn: [contactInfos objectForKey: @"cn"]];
+ [person setEmail: [contactInfos objectForKey: @"c_email"]];
+
+ return person;
+}
+
- (NSString *) iCalStringForFreeBusyInfos: (NSArray *) _infos
from: (NSCalendarDate *) _startDate
to: (NSCalendarDate *) _endDate
{
- AgenorUserManager *um;
NSString *uid;
NSEnumerator *events;
iCalCalendar *calendar;
NSDictionary *info;
iCalFreeBusyType type;
- um = [AgenorUserManager sharedUserManager];
uid = [[self container] login];
calendar = [iCalCalendar groupWithTag: @"vcalendar"];
[calendar setVersion: @"2.0"];
freebusy = [iCalFreeBusy groupWithTag: @"vfreebusy"];
- [freebusy addToAttendees: [um iCalPersonWithUid: uid]];
+ [freebusy addToAttendees: [self iCalPersonWithUID: uid]];
[freebusy setTimeStampAsDate: [NSCalendarDate calendarDate]];
[freebusy setStartDate: _startDate];
[freebusy setEndDate: _endDate];
/* ORGANIZER - strictly required but missing for now */
/* ATTENDEE */
-// person = [um iCalPersonWithUid: uid];
+// person = [self iCalPersonWithUid: uid];
// [person setTag: @"ATTENDEE"];
// [ms appendString: [person versitString]];
#import <NGCards/iCalToDo.h>
#import <NGCards/iCalEventChanges.h>
#import <NGCards/iCalPerson.h>
-#import <SOGo/AgenorUserManager.h>
+#import <SOGo/LDAPUserManager.h>
#import <NGMime/NGMime.h>
#import <NGMail/NGMail.h>
#import <NGMail/NGSendMail.h>
/* iCal handling */
- (NSArray *)attendeeUIDsFromTask:(iCalToDo *)_task {
- AgenorUserManager *um;
+ LDAPUserManager *um;
NSMutableArray *uids;
NSArray *attendees;
unsigned i, count;
count = [attendees count];
uids = [NSMutableArray arrayWithCapacity:count + 1];
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
/* add organizer */
- delete in removed folders
- send iMIP mail for all folders not found
*/
-// AgenorUserManager *um;
+// LDAPUserManager *um;
// iCalCalendar *calendar;
// iCalToDo *oldApt, *newApt;
// // iCalToDoChanges *changes;
// reason:@"got no iCalendar content to store!"];
// }
-// um = [AgenorUserManager sharedUserManager];
+// um = [LDAPUserManager sharedUserManager];
// /* handle old content */
SOGoContactFolders.m \
SOGoContactGCSEntry.m \
SOGoContactGCSFolder.m \
- SOGoContactLDAPEntry.m \
+ SOGoContactLDIFEntry.m \
SOGoContactLDAPFolder.m \
- \
- NGLdapEntry+Contact.m \
Contacts_RESOURCE_FILES += \
Version \
+++ /dev/null
-/* NGLdapEntry+Contact.h - this file is part of SOGo
- *
- * Copyright (C) 2006 Inverse groupe conseil
- *
- * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This file 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef NGLDAPENTRY_CONTACT_H
-#define NGLDAPENTRY_CONTACT_H
-
-#import <NGLdap/NGLdapEntry.h>
-
-@class NSArray;
-@class NSDictionary;
-@class NSString;
-
-@interface NGLdapEntry (SOGoContactExtension)
-
-- (NSString *) singleAttributeWithName: (NSString *) key;
-- (NSDictionary *) asDictionaryWithAttributeNames: (NSArray *) attributes
- withUID: (NSString *) uid
- andCName: (NSString *) cName;
-
-@end
-
-#endif /* NGLDAPENTRY_CONTACT_H */
+++ /dev/null
-/* NGLdapEntry+Contact.m - this file is part of SOGo
- *
- * Copyright (C) 2006 Inverse groupe conseil
- *
- * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This file 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#import <Foundation/NSArray.h>
-#import <Foundation/NSDictionary.h>
-#import <Foundation/NSString.h>
-
-#import <NGLdap/NGLdapAttribute.h>
-
-#import "NGLdapEntry+Contact.h"
-
-@implementation NGLdapEntry (SOGoContactExtension)
-
-- (NSString *) singleAttributeWithName: (NSString *) key
-{
- return [[self attributeWithName: key]
- stringValueAtIndex: 0];
-}
-
-- (NSDictionary *) asDictionaryWithAttributeNames: (NSArray *) attributeNames
- withUID: (NSString *) uid
- andCName: (NSString *) cName
-{
- NSMutableDictionary *valuesDict;
- NSEnumerator *attrEnum;
- NSString *attribute, *value;
-
- if (!attributeNames)
- attributeNames = [self attributeNames];
-
- valuesDict = [NSMutableDictionary dictionaryWithCapacity: [attributeNames count]];
- attrEnum = [attributeNames objectEnumerator];
- attribute = [attrEnum nextObject];
- while (attribute)
- {
- [valuesDict setObject: [self singleAttributeWithName: attribute]
- forKey: attribute];
- attribute = [attrEnum nextObject];
- }
- if (cName)
- {
- value = [self singleAttributeWithName: cName];
- if (!value)
- value = @"";
- NSLog (@"value for '%@' = '%@'", cName, value);
- [valuesDict setObject: value
- forKey: @"c_name"];
- }
- if (uid)
- {
- value = [self singleAttributeWithName: uid];
- if (!value)
- value = @"";
- NSLog (@"value for '%@' = '%@'", uid, value);
- [valuesDict setObject: value
- forKey: @"c_uid"];
- }
-
- return valuesDict;
-}
-
-@end
andDisplayName: (NSString *) aDisplayName
inContainer: (SOGoObject *) aContainer;
+- (NSString *) nameInContainer;
+- (NSString *) displayName;
-- (id <SOGoContactObject>) lookupContactWithId: (NSString *) recordId;
- (NSArray *) lookupContactsWithFilter: (NSString *) filter
sortBy: (NSString *) sortKey
ordering: (NSComparisonResult) sortOrdering;
-- (void) setDisplayName: (NSString *) aDisplayName;
-- (NSString *) displayName;
-
@end
#endif /* __Contacts_SOGoContactFolder_H__ */
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
+#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
+#import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/SoUser.h>
#import <GDLContentStore/GCSFolderManager.h>
#import <GDLAccess/EOAdaptorChannel.h>
#import <GDLContentStore/NSURL+GCS.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
-#import "common.h"
-
#import "SOGoContactGCSFolder.h"
#import "SOGoContactLDAPFolder.h"
#import "SOGoContactFolders.h"
[super dealloc];
}
-- (void) appendPersonalSourcesInContext: (WOContext *) context;
+- (void) appendPersonalSources
{
SOGoContactGCSFolder *ab;
GCSChannelManager *cm;
fc = [cm acquireOpenChannelForURL: folderLocation];
if (fc)
{
- sql
- = [NSString stringWithFormat: @"SELECT c_path4, c_foldername FROM %@"
- @" WHERE c_path2 = '%@' AND c_folder_type = 'Contact'",
- [folderLocation gcsTableName],
- [self ownerInContext: nil]];
+ sql = [NSString
+ stringWithFormat: (@"SELECT c_path4, c_foldername FROM %@"
+ @" WHERE c_path2 = '%@'"
+ @" AND c_folder_type = 'Contact'"),
+ [folderLocation gcsTableName], [self ownerInContext: context]];
[fc evaluateExpressionX: sql];
attrs = [fc describeResults: NO];
row = [fc fetchAttributes: attrs withZone: NULL];
}
}
+- (void) appendSystemSources
+{
+ LDAPUserManager *um;
+ NSEnumerator *sourceIDs;
+ NSString *currentSourceID, *displayName;
+ SOGoContactLDAPFolder *currentFolder;
+
+ um = [LDAPUserManager sharedUserManager];
+ sourceIDs = [[um addressBookSourceIDs] objectEnumerator];
+ currentSourceID = [sourceIDs nextObject];
+ while (currentSourceID)
+ {
+ displayName = [um displayNameForSourceWithID: currentSourceID];
+ currentFolder = [SOGoContactLDAPFolder contactFolderWithName: currentSourceID
+ andDisplayName: displayName
+ inContainer: self];
+ [currentFolder setLDAPSource: [um sourceWithID: currentSourceID]];
+ [contactFolders setObject: currentFolder forKey: currentSourceID];
+ currentSourceID = [sourceIDs nextObject];
+ }
+}
+
- (WOResponse *) newFolderWithName: (NSString *) name
{
SOGoContactGCSFolder *newFolder;
newFolder = [SOGoContactGCSFolder contactFolderWithName: name
andDisplayName: name
- inContainer: [self clientObject]];
+ inContainer: self];
if ([newFolder isKindOfClass: [NSException class]])
response = (WOResponse *) newFolder;
else
return response;
}
-- (void) appendSystemSourcesInContext: (WOContext *) context;
-{
- NSUserDefaults *ud;
- NSEnumerator *ldapABs;
- NSDictionary *udAB;
- SOGoContactLDAPFolder *ab;
-
- ud = [NSUserDefaults standardUserDefaults];
- ldapABs = [[ud objectForKey: @"SOGoLDAPAddressBooks"] objectEnumerator];
- udAB = [ldapABs nextObject];
- while (udAB)
- {
- ab = [SOGoContactLDAPFolder contactFolderWithName:
- [udAB objectForKey: @"id"]
- andDisplayName:
- [udAB objectForKey: @"displayName"]
- inContainer: self];
- [ab LDAPSetHostname: [udAB objectForKey: @"hostname"]
- setPort: [[udAB objectForKey: @"port"] intValue]
- setBindDN: [udAB objectForKey: @"bindDN"]
- setBindPW: [udAB objectForKey: @"bindPW"]
- setContactIdentifier: [udAB objectForKey: @"idField"]
- setUserIdentifier: [udAB objectForKey: @"userIdField"]
- setRootDN: [udAB objectForKey: @"rootDN"]];
- [contactFolders setObject: ab forKey: [udAB objectForKey: @"id"]];
- udAB = [ldapABs nextObject];
- }
-}
-
- (void) initContactSources
{
if (!contactFolders)
{
contactFolders = [NSMutableDictionary new];
- [self appendPersonalSourcesInContext: context];
- [self appendSystemSourcesInContext: context];
+ [self appendPersonalSources];
+ [self appendSystemSources];
}
}
acquire: (BOOL) acquire
{
id obj;
- id folder;
/* first check attributes directly bound to the application */
obj = [super lookupName: name inContext: lookupContext acquire: NO];
if (!contactFolders)
[self initContactSources];
- folder = [contactFolders objectForKey: name];
- obj = ((folder)
- ? folder
- : [NSException exceptionWithHTTPStatus: 404]);
+ obj = [contactFolders objectForKey: name];
+ if (!obj)
+ obj = [NSException exceptionWithHTTPStatus: 404];
}
return obj;
#ifndef __Contacts_SOGoContactGCSFolder_H__
#define __Contacts_SOGoContactGCSFolder_H__
-#import <SOGo/SOGoFolder.h>
+#import <SoObjects/SOGo/SOGoFolder.h>
+
#import "SOGoContactFolder.h"
-@class NSString, NSArray;
+@class NSArray;
+@class NSString;
@interface SOGoContactGCSFolder : SOGoFolder <SOGoContactFolder>
{
return folder;
}
-- (id <SOGoContactFolder>) initWithName: (NSString *) aName
- andDisplayName: (NSString *) aDisplayName
- inContainer: (SOGoObject *) aContainer
+- (void) dealloc
{
- if ((self = [self initWithName: aName
- inContainer: aContainer]))
- [self setDisplayName: aDisplayName];
-
- return self;
+ [displayName release];
+ [super dealloc];
}
-- (void) setDisplayName: (NSString *) aDisplayName
+- (id <SOGoContactFolder>) initWithName: (NSString *) newName
+ andDisplayName: (NSString *) newDisplayName
+ inContainer: (SOGoObject *) newContainer
{
- if (displayName)
- [displayName release];
- displayName = aDisplayName;
- if (displayName)
- [displayName retain];
+ if ((self = [self initWithName: newName
+ inContainer: newContainer]))
+ ASSIGN (displayName, newDisplayName);
+
+ return self;
}
- (NSString *) displayName
qualifier = [self _qualifierForFilter: filter];
records = [[self ocsFolder] fetchFields: fields
matchingQualifier: qualifier];
- if (records)
+ if ([records count] > 1)
{
ordering
= [EOSortOrdering sortOrderingWithKey: sortKey
#ifndef SOGOCONTACTLDAPFOLDER_H
#define SOGOCONTACTLDAPFOLDER_H
-#import <SOGo/SOGoObject.h>
#import "SOGoContactFolder.h"
-@class NSString, NSArray;
-@class NGLdapConnection;
+@class NSMutableDictionary;
+
+@class LDAPSource;
@interface SOGoContactLDAPFolder : SOGoObject <SOGoContactFolder>
{
- NGLdapConnection *connection;
- NSString *contactIdentifier;
- NSString *userIdentifier;
- NSString *rootDN;
+ NSString *name;
NSString *displayName;
+ id container;
+ LDAPSource *ldapSource;
NSMutableDictionary *entries;
}
-- (NGLdapConnection *) LDAPconnection;
-
-- (void) setDisplayName: (NSString *) aDisplayName;
-- (NSString *) displayName;
-
-- (void) LDAPSetHostname: (NSString *) aHostname
- setPort: (int) aPort
- setBindDN: (NSString *) aBindDN
- setBindPW: (NSString *) aBindPW
- setContactIdentifier: (NSString *) aCI
- setUserIdentifier: (NSString *) aUI
- setRootDN: (NSString *) aRootDN;
+- (id <SOGoContactFolder>) initWithName: (NSString *) newName
+ andDisplayName: (NSString *) newDisplayName
+ inContainer: (SOGoObject *) newContainer;
+- (void) setLDAPSource: (LDAPSource *) newLdapSource;
@end
*/
#import <Foundation/NSArray.h>
-#import <Foundation/NSString.h>
-
#import <Foundation/NSDictionary.h>
#import <Foundation/NSString.h>
+#import <NGObjWeb/NSException+HTTP.h>
+#import <NGObjWeb/SoObject.h>
#import <NGObjWeb/WOApplication.h>
#import <NGObjWeb/WOContext.h>
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/SoUser.h>
+#import <EOControl/EOSortOrdering.h>
-#import <NGLdap/NGLdapAttribute.h>
-#import <NGLdap/NGLdapConnection.h>
-#import <NGLdap/NGLdapEntry.h>
-
-#import "common.h"
-
-#import "NGLdapEntry+Contact.h"
-
-#import "SOGoContactLDAPEntry.h"
+#import <SoObjects/SOGo/LDAPSource.h>
+#import "SOGoContactLDIFEntry.h"
#import "SOGoContactLDAPFolder.h"
#define folderListingFields [NSArray arrayWithObjects: @"c_name", @"cn", \
{
if ((self = [super init]))
{
- connection = nil;
- contactIdentifier = nil;
- userIdentifier = nil;
- rootDN = nil;
+ name = nil;
+ displayName = nil;
+ container = nil;
entries = nil;
+ ldapSource = nil;
}
return self;
}
-- (id <SOGoContactFolder>) initWithName: (NSString *) aName
- andDisplayName: (NSString *) aDisplayName
- inContainer: (SOGoObject *) aContainer
+- (id <SOGoContactFolder>) initWithName: (NSString *) newName
+ andDisplayName: (NSString *) newDisplayName
+ inContainer: (SOGoObject *) newContainer
{
- if ((self = [self initWithName: aName
- inContainer: aContainer]))
- [self setDisplayName: aDisplayName];
-
+ self = [self init];
+
+ ASSIGN (name, newName);
+ ASSIGN (displayName, newDisplayName);
+ ASSIGN (container, newContainer);
+
return self;
}
- (void) dealloc
{
- [connection release];
- [contactIdentifier release];
- [userIdentifier release];
- [rootDN release];
+ [name release];
+ [displayName release];
+ [container release];
[entries release];
+ [ldapSource release];
[super dealloc];
}
-- (void) setDisplayName: (NSString *) aDisplayName
+- (void) setLDAPSource: (LDAPSource *) newLDAPSource
{
- if (displayName)
- [displayName release];
- displayName = aDisplayName;
- if (displayName)
- [displayName retain];
+ ASSIGN (ldapSource, newLDAPSource);
}
- (NSString *) displayName
return displayName;
}
-- (void) LDAPSetHostname: (NSString *) aHostname
- setPort: (int) aPort
- setBindDN: (NSString *) aBindDN
- setBindPW: (NSString *) aBindPW
- setContactIdentifier: (NSString *) aCI
- setUserIdentifier: (NSString *) aUI
- setRootDN: (NSString *) aRootDN;
-{
- connection = [[NGLdapConnection alloc] initWithHostName: aHostname
- port: aPort];
- [connection bindWithMethod: nil
- binddn: aBindDN
- credentials: aBindPW];
-
- if (rootDN)
- [rootDN release];
- rootDN = [aRootDN copy];
- if (contactIdentifier)
- [contactIdentifier release];
- contactIdentifier = [aCI copy];
- if (userIdentifier)
- [userIdentifier release];
- userIdentifier = [aUI copy];
-}
-
-- (NGLdapConnection *) LDAPconnection
+- (NSString *) nameInContainer
{
- return connection;
+ return name;
}
-- (NGLdapAttribute *) _attrWithName: (NSString *) aName
-{
- return [[[NGLdapAttribute alloc] initWithAttributeName: aName] autorelease];
-}
-
-- (NSArray *) _searchAttributes
-{
- return [NSArray arrayWithObjects:
- contactIdentifier,
- userIdentifier,
- @"title",
- @"company",
- @"o",
- @"displayName",
- @"modifytimestamp",
- @"mozillaHomeState",
- @"mozillaHomeUrl",
- @"homeurl",
- @"st",
- @"region",
- @"mozillaCustom2",
- @"custom2",
- @"mozillaHomeCountryName",
- @"description",
- @"notes",
- @"department",
- @"departmentnumber",
- @"ou",
- @"orgunit",
- @"mobile",
- @"cellphone",
- @"carphone",
- @"mozillaCustom1",
- @"custom1",
- @"mozillaNickname",
- @"xmozillanickname",
- @"mozillaWorkUrl",
- @"workurl",
- @"fax",
- @"facsimileTelephoneNumber",
- @"telephoneNumber",
- @"mozillaHomeStreet",
- @"mozillaSecondEmail",
- @"xmozillasecondemail",
- @"mozillaCustom4",
- @"custom4",
- @"nsAIMid",
- @"nscpaimscreenname",
- @"street",
- @"streetAddress",
- @"postOfficeBox",
- @"homePhone",
- @"cn",
- @"commonname",
- @"givenName",
- @"mozillaHomePostalCode",
- @"mozillaHomeLocalityName",
- @"mozillaWorkStreet2",
- @"mozillaUseHtmlMail",
- @"xmozillausehtmlmail",
- @"mozillaHomeStreet2",
- @"postalCode",
- @"zip",
- @"c",
- @"countryname",
- @"pager",
- @"pagerphone",
- @"mail",
- @"sn",
- @"surname",
- @"mozillaCustom3",
- @"custom3",
- @"l",
- @"locality",
- @"birthyear",
- @"serialNumber",
- @"calFBURL",
- nil];
-}
-
-- (void) _loadEntries: (NSString *) entryId
-{
- NSEnumerator *contacts;
- NGLdapEntry *entry;
- NSString *key;
-
- if (!entries)
- entries = [NSMutableDictionary new];
-
- if (entryId)
- {
- if (![entries objectForKey: entryId])
- {
- entry
- = [connection entryAtDN:
- [NSString stringWithFormat: @"%@=%@,%@",
- contactIdentifier, entryId, rootDN]
- attributes: [self _searchAttributes]];
- if (entry)
- [entries setObject: entry forKey: entryId];
- }
- }
- else
- {
- contacts = [connection deepSearchAtBaseDN: rootDN
- qualifier: nil
- attributes: [self _searchAttributes]];
- if (contacts)
- {
- entry = [contacts nextObject];
- while (entry)
- {
- key = [[entry attributeWithName: contactIdentifier]
- stringValueAtIndex: 0];
- if (key && ![entries objectForKey: key])
- [entries setObject: entry forKey: key];
- entry = [contacts nextObject];
- }
- }
- }
-}
-
-- (id) lookupName: (NSString *) name
+- (id) lookupName: (NSString *) objectName
inContext: (WOContext *) lookupContext
acquire: (BOOL) acquire
{
id obj;
- NGLdapEntry *entry;
+ NSDictionary *ldifEntry;
// NSLog (@"looking up name '%@'...", name);
/* first check attributes directly bound to the application */
- obj = [super lookupName: name inContext: lookupContext acquire: NO];
+ obj = [super lookupName: objectName inContext: lookupContext acquire: NO];
if (!obj)
{
- [self _loadEntries: name];
- entry = [entries objectForKey: name];
- obj = ((entry)
- ? [SOGoContactLDAPEntry contactEntryWithName: name
- withLDAPEntry: entry
- inContainer: self]
- : [NSException exceptionWithHTTPStatus: 404]);
+ ldifEntry = [ldapSource lookupContactEntry: objectName];
+ obj = ((ldifEntry)
+ ? [SOGoContactLDIFEntry contactEntryWithName: name
+ withLDIFEntry: ldifEntry
+ inContainer: self]
+ : [NSException exceptionWithHTTPStatus: 404]);
}
return obj;
- (NSArray *) toOneRelationshipKeys
{
- [self _loadEntries: nil];
-
- return [entries allKeys];
-}
-
-- (id <SOGoContactObject>) lookupContactWithId: (NSString *) recordId
-{
- NGLdapEntry *entry;
-
- [self _loadEntries: recordId];
-
- entry = [entries objectForKey: recordId];
- return ((entry)
- ? [SOGoContactLDAPEntry contactEntryWithName: recordId
- withLDAPEntry: entry
- inContainer: self]
- : nil);
-}
-
-- (EOQualifier *) _qualifierForFilter: (NSString *) filter
-{
- NSString *qs;
- EOQualifier *qualifier;
-
- if (filter && [filter length] > 0)
- {
- if ([filter isEqualToString: @"."])
- qs = @"(cn='*')";
- else
- qs = [NSString stringWithFormat:
- @"(cn='%@*')"
- @"OR (sn='%@*')"
- @"OR (displayName='%@*')"
- @"OR (mail='%@*')"
- @"OR (telephoneNumber='*%@*')",
- filter, filter, filter, filter, filter];
- qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
- }
- else
- qualifier = nil;
-
- return qualifier;
+ return [ldapSource allEntryIDs];
}
- (NSArray *) lookupContactsWithFilter: (NSString *) filter
sortBy: (NSString *) sortKey
ordering: (NSComparisonResult) sortOrdering
{
- NSMutableArray *records;
- NSArray *result;
- NGLdapEntry *entry;
- NSEnumerator *contacts;
+ NSArray *records, *result;
EOSortOrdering *ordering;
result = nil;
if (filter && [filter length] > 0)
{
- NSLog (@"%@: fetching records matching '%@', sorted by '%@'"
- @" in order %d",
- self, filter, sortKey, sortOrdering);
-
- records = [NSMutableArray new];
- [records autorelease];
-
- contacts = [connection deepSearchAtBaseDN: rootDN
- qualifier: [self _qualifierForFilter: filter]
- attributes: folderListingFields];
- entry = [contacts nextObject];
- while (entry)
- {
- [records addObject: [entry asDictionaryWithAttributeNames: nil
- withUID: userIdentifier
- andCName: contactIdentifier]];
- entry = [contacts nextObject];
- }
-
+ records = [ldapSource fetchContactsMatching: filter];
ordering
= [EOSortOrdering sortOrderingWithKey: sortKey
selector: ((sortOrdering == NSOrderedDescending)
};
SOGoContactGCSFolder = {
- superclass = "SOGoFolder";
+ superclass = "SOGoFolder";
};
SOGoContactGCSEntry = {
- superclass = "SOGoContentObject";
+ superclass = "SOGoContentObject";
defaultRoles = {
"View" = ( "Owner", "Delegate", "Organizer", "Authenticated" );
};
};
SOGoContactLDAPFolder = {
- superclass = "SOGoFolder";
+ superclass = "SOGoFolder";
+ defaultAccess = "allow";
+ protectedBy = "<public>";
};
- SOGoContactLDAPEntry = {
+ SOGoContactLDIFEntry = {
superclass = "SOGoContentObject";
- defaultRoles = {
- "View" = ( "Owner", "Delegate", "Organizer", "Authenticated" );
- };
+ defaultAccess = "allow";
+ protectedBy = "<public>";
};
};
}
return ma;
}
+- (NSString *) _rawSender
+{
+ NSString *startEmail, *rawSender;
+ NSRange delimiter;
+
+ startEmail = [self sender];
+ delimiter = [startEmail rangeOfString: @"<"];
+ if (delimiter.location == NSNotFound)
+ rawSender = startEmail;
+ else
+ {
+ rawSender = [startEmail substringFromIndex: NSMaxRange (delimiter)];
+ delimiter = [rawSender rangeOfString: @">"];
+ rawSender = [rawSender substringToIndex: delimiter.location];
+ }
+
+ return rawSender;
+}
+
- (NSException *)sendMimeMessageAtPath:(NSString *)_path {
static NGSendMail *mailer = nil;
NSArray *recipients;
/* validate */
recipients = [self allRecipients];
- from = [self sender];
+ from = [self _rawSender];
if ([recipients count] == 0) {
return [NSException exceptionWithHTTPStatus:500 /* server error */
reason:@"draft has no recipients set!"];
account = [self valueForKey:@"primaryIMAP4AccountString"];
identity = [[[SOGoMailIdentity alloc] init] autorelease];
- [identity setName:[self cn]];
- [identity setEmail:[self email]];
+ [identity setName: [self cn]];
+ [identity setEmail: [self primaryEmail]];
[identity setSentFolderName:[self agenorSentFolderForAccount:account]];
return identity;
}
{
GCSChannelManager *cm;
EOAdaptorChannel *channel;
- NSDictionary *row;
+ NSDictionary *row, *oldValues;
NSException *ex;
NSString *sql;
NSArray *attrs;
@" WHERE %@ = '%@'"),
fieldName, [[self tableURL] gcsTableName],
uidColumnName, [self uid]];
-
+
+ [values release];
+ values = [NSMutableDictionary new];
+
/* run SQL */
ex = [channel evaluateExpressionX: sql];
if (ex)
- {
- [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
- values = [NSMutableDictionary new];
- }
+ [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex];
else
{
/* fetch schema */
[channel cancelFetch];
/* remember values */
- [values release];
- values = [[row objectForKey: fieldName] propertyList];
- if (values)
- [values retain];
- else
- values = [NSMutableDictionary new];
+ oldValues = [[row objectForKey: fieldName] propertyList];
+ [values setDictionary: oldValues];
- ASSIGN(lastFetch, [NSCalendarDate date]);
+ ASSIGN (lastFetch, [NSCalendarDate date]);
defFlags.modified = NO;
rc = YES;
}
+++ /dev/null
-/*
- Copyright (C) 2004-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.
-*/
-
-#ifndef __AgenorUserManager_H_
-#define __AgenorUserManager_H_
-
-#import <Foundation/NSObject.h>
-
-/*
- AgenorUserManager
-
- TODO: document
-*/
-
-@class NSString, NSArray, NSURL, NSUserDefaults, NSMutableDictionary, NSTimer;
-@class NSDictionary;
-@class iCalPerson;
-
-@interface AgenorUserManager : NSObject
-{
- NSMutableDictionary *cnCache;
- NSMutableDictionary *serverCache;
- NSMutableDictionary *uidCache;
- NSMutableDictionary *emailCache;
- NSMutableDictionary *shareStoreCache;
- NSMutableDictionary *shareEMailCache;
- NSMutableDictionary *changeInternetAccessCache;
- NSMutableDictionary *internetAutoresponderFlagCache;
- NSMutableDictionary *intranetAutoresponderFlagCache;
- NSTimer *gcTimer;
-}
-
-+ (id)sharedUserManager;
-
-- (NSString *)getUIDForEmail:(NSString *)_email;
-- (NSString *)getEmailForUID:(NSString *)_uid;
-
-- (iCalPerson *) iCalPersonWithUid: (NSString *) uid;
-
-- (NSString *) getUIDForICalPerson: (iCalPerson *) _person;
-/* may insert NSNulls into returned array if _mapStrictly -> YES */
-- (NSArray *)getUIDsForICalPersons:(NSArray *)_persons
- applyStrictMapping:(BOOL)_mapStrictly;
-
-/* 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;
-- (NSArray *)getSharedMailboxEMailsForUID:(NSString *)_uid;
-- (NSDictionary *)getSharedMailboxesAndEMailsForUID:(NSString *)_uid;
-
-- (NSURL *)getFreeBusyURLForUID:(NSString *)_uid;
-
-- (NSUserDefaults *) getUserDefaultsForUID: (NSString *) uid;
-- (NSUserDefaults *) getUserSettingsForUID: (NSString *) uid;
-
-- (BOOL)isUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid;
-
-- (BOOL)isInternetAutoresponderEnabledForUser:(NSString *)_uid;
-- (BOOL)isIntranetAutoresponderEnabledForUser:(NSString *)_uid;
-
-@end
-
-#endif /* __AgenorUserManager_H_ */
+++ /dev/null
-/*
- Copyright (C) 2004-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 "AgenorUserDefaults.h"
-#include <NGExtensions/NGExtensions.h>
-#include <NGLdap/NGLdap.h>
-#include <NGCards/NGCards.h>
-#include "SOGoLRUCache.h"
-
-#warning we should rely on the LDAP sources instead...
-#define qualifierFormat @"uid = %@"
-
-@interface AgenorUserManager (PrivateAPI)
-- (NGLdapConnection *)ldapConnection;
-
-- (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid;
-- (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;
-
-- (BOOL)primaryIsUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid;
-
-- (BOOL)primaryIsInternetAutoresponderEnabledForUser:(NSString *)_uid;
-- (BOOL)primaryIsIntranetAutoresponderEnabledForUser:(NSString *)_uid;
-- (NGLdapAttribute *)primaryGetMailAutoresponderAttribute:(NSString *)_uid;
-- (BOOL)isAutoresponderEnabledForAttribute:(NGLdapAttribute *)_attr
- matchingPrefix:(NSString *)_prefix;
-@end
-
-// TODO: add a timer to flush LRU caches every some hours
-
-@implementation AgenorUserManager
-
-static BOOL debugOn = NO;
-static BOOL useLDAP = NO;
-static NSString *ldapHost = nil;
-static NSString *ldapBaseDN = nil;
-static NSNull *sharedNull = nil;
-static NSString *fallbackIMAP4Server = nil;
-static NSString *defaultMailDomain = nil;
-static NSString *shareLDAPClass = @"mineqMelBoite";
-static NSString *shareLoginSeparator = @".-.";
-static NSString *mailEmissionAttrName = @"mineqMelmailEmission";
-static NSString *changeInternetAccessAttrName = @"mineqOgoAccesInternet";
-static NSString *mailAutoresponderAttrName = @"mineqMelReponse"; /* sic! */
-static NSURL *AgenorProfileURL = nil;
-
-static NSArray *fromEMailAttrs = nil;
-
-static unsigned PoolScanInterval = 5 * 60 /* every five minutes */;
-
-+ (void) initialize
-{
- static BOOL didInit = NO;
- NSUserDefaults *ud;
- NSString *tmp;
-
- if (didInit) return;
- didInit = YES;
-
- ud = [NSUserDefaults standardUserDefaults];
- debugOn = [ud boolForKey:@"SOGoUserManagerDebugEnabled"];
-
- useLDAP = [ud boolForKey:@"SOGoUserManagerUsesLDAP"];
- if (useLDAP) {
- ldapHost = [[ud stringForKey:@"LDAPHost"] copy];
- ldapBaseDN = [[ud stringForKey:@"LDAPRootDN"] copy];
- NSLog(@"Note: using LDAP host to manage accounts: %@", ldapHost);
- }
- else
- NSLog(@"Note: LDAP access is disabled.");
-
- fallbackIMAP4Server = [[ud stringForKey:@"SOGoFallbackIMAP4Server"] copy];
- if ([fallbackIMAP4Server length] > 0)
- NSLog(@"Note: using fallback IMAP4 server: '%@'", fallbackIMAP4Server);
- else
- {
- if (fallbackIMAP4Server)
- [fallbackIMAP4Server release];
- fallbackIMAP4Server = nil;
- }
-
- defaultMailDomain = [[ud stringForKey:@"SOGoDefaultMailDomain"] copy];
- if ([defaultMailDomain length] == 0)
- {
- if (defaultMailDomain)
- [defaultMailDomain release];
- defaultMailDomain = nil;
- NSLog(@"WARNING: no default mail domain (please specify"
- " 'SOGoDefaultMailDomain' in the user default db)");
- }
-
- fromEMailAttrs =
- [[NSArray alloc] initWithObjects:mailEmissionAttrName, nil];
-
- sharedNull = [[NSNull null] retain];
-
- /* profile database URL */
-
- if ((tmp = [ud stringForKey:@"AgenorProfileURL"]) == nil)
- NSLog(@"ERROR: no 'AgenorProfileURL' database URL configured!");
- else if ((AgenorProfileURL = [[NSURL alloc] initWithString:tmp]) == nil)
- NSLog(@"ERROR: could not parse AgenorProfileURL: '%@'", tmp);
- else
- NSLog(@"Note: using profile at: %@", [AgenorProfileURL absoluteString]);
-
- if ((tmp = [ud stringForKey: @"SOGoDefaultMailDomain"]))
- {
- defaultMailDomain = [tmp copy];
- }
-
- PoolScanInterval = [[ud objectForKey:@"AgenorCacheCheckInterval"] intValue];
- if (PoolScanInterval == 0)
- PoolScanInterval = 60 * 60 /* every hour */;
- NSLog(@"AgenorUserManager: flushing caches every %d minutes "
- @"(AgenorCacheCheckInterval)",
- PoolScanInterval / 60);
-}
-
-+ (id)sharedUserManager {
- static AgenorUserManager *mgr = nil;
- if (mgr == nil)
- mgr = [[self alloc] init];
- return mgr;
-}
-
-- (id)init {
- self = [super init];
- if(self) {
- serverCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- cnCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- uidCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- emailCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- shareStoreCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- shareEMailCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- changeInternetAccessCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- internetAutoresponderFlagCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
- intranetAutoresponderFlagCache =
- [[NSMutableDictionary alloc] initWithCapacity:10000];
-
- gcTimer = [[NSTimer scheduledTimerWithTimeInterval:
- PoolScanInterval
- target:self selector:@selector(_garbageCollect:)
- userInfo:nil repeats:YES] retain];
- }
- return self;
-}
-
-- (void)dealloc {
- if (gcTimer) [gcTimer invalidate];
- [serverCache release];
- [cnCache release];
- [uidCache release];
- [emailCache release];
- [shareStoreCache release];
- [shareEMailCache release];
- [changeInternetAccessCache release];
- [internetAutoresponderFlagCache release];
- [intranetAutoresponderFlagCache release];
- [gcTimer release];
- [super dealloc];
-}
-
-/* cache */
-
-- (void)flush {
- [cnCache removeAllObjects];
- [serverCache removeAllObjects];
- [uidCache removeAllObjects];
- [emailCache removeAllObjects];
- [shareStoreCache removeAllObjects];
- [shareEMailCache removeAllObjects];
-
- [changeInternetAccessCache removeAllObjects];
- [internetAutoresponderFlagCache removeAllObjects];
- [intranetAutoresponderFlagCache removeAllObjects];
-}
-
-- (void)_garbageCollect:(NSTimer *)_timer {
- [self debugWithFormat:@"flushing caches."];
- [self flush];
-}
-
-/* LDAP */
-
-- (NGLdapConnection *)ldapConnection {
- static NGLdapConnection *ldapConnection = nil;
- if(!ldapConnection) {
- ldapConnection = [[NGLdapConnection alloc] initWithHostName: ldapHost];
-#if 0
- [ldapConnection setUseCache:YES];
-#endif
- }
- return ldapConnection;
-}
-
-
-/* private cache helpers */
-// TODO: this is really unnecessary, no?
-
-- (void)_cacheCN:(NSString *)_cn forUID:(NSString *)_uid {
- if (_cn == nil) return;
- [cnCache setObject:_cn forKey:_uid];
-}
-- (NSString *)_cachedCNForUID:(NSString *)_uid {
- return [cnCache objectForKey:_uid];
-}
-
-- (void)_cacheServer:(NSString *)_server forUID:(NSString *)_uid {
- if (_server == nil) return;
- [serverCache setObject:_server forKey:_uid];
-}
-- (NSString *)_cachedServerForUID:(NSString *)_uid {
- return [serverCache objectForKey:_uid];
-}
-
-- (void)_cacheEmail:(NSString *)_email forUID:(NSString *)_uid {
- if (_email == nil) return;
- [emailCache setObject:_email forKey:_uid];
-}
-- (NSString *)_cachedEmailForUID:(NSString *)_uid {
- return [emailCache objectForKey:_uid];
-}
-
-- (void)_cacheUID:(NSString *)_uid forEmail:(NSString *)_email {
- if (_uid == nil) return;
- [uidCache setObject:_uid forKey:_email];
-}
-- (NSString *)_cachedUIDForEmail:(NSString *)_email {
- return [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.
-
- So, we can use email adresse from identifier.
- The field is made like this :
- _ if the email is equipement.gouv.fr then the login
- is the part before the @
- for example : fisrtName.lastName
- _ 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
- guaranteed, because the second dot would be mapped to '@'. This
- is probably error prone.
- Only LDAP fetches would guarantee correctness in both cases.
-*/
-
-- (NSString *)primaryGetAgenorUIDForEmail:(NSString *)_email {
- 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];
-
- 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;
- }
- uidAttr = [entry attributeWithName:@"uid"];
- if (!uidAttr)
- return nil; /* can happen, not unlikely */
- uid = [uidAttr stringValueAtIndex:0];
- return uid;
-}
-
-- (NSString *) getUIDForEmail: (NSString *)_email
-{
- NSString *uid;
- NSRange r;
- NSString *domain;
-
- uid = nil;
- if ([_email length] > 0)
- {
- uid = [self _cachedUIDForEmail:_email];
- if (!uid)
- {
- if (useLDAP)
- uid = [self primaryGetAgenorUIDForEmail:_email];
-
- if (!uid)
- {
- r = [_email rangeOfString:@"@"];
- if (r.length == 0)
- return nil;
-
- domain = [_email substringFromIndex:NSMaxRange(r)];
- if (![domain isEqualToString:defaultMailDomain])
- uid = _email;
- else
- uid = [_email substringToIndex:r.location];
- }
- if (uid)
- [self _cacheUID:uid forEmail:_email];
- }
- }
-
- return uid;
-}
-
-#warning big ugly hack. LDAP lookup should be fixed
-- (NSString *) getUIDForICalPerson: (iCalPerson *) _person
-{
- NSString *domainString, *email, *uid;
-
- domainString = [NSString stringWithFormat: @"@%@", defaultMailDomain];
- email = [_person rfc822Email];
- if ([email hasSuffix: domainString])
- uid = [_person cn];
- else
- uid = [self getUIDForEmail: email];
-
- return uid;
-}
-
- /* may insert NSNulls into returned array */
-- (NSArray *)getUIDsForICalPersons:(NSArray *)_persons
- applyStrictMapping:(BOOL)_mapStrictly
-{
- NSMutableArray *ma;
- unsigned i, count;
-
- count = [_persons count];
- ma = [[[NSMutableArray alloc] initWithCapacity:count] autorelease];
- for (i = 0; i < count; i++) {
- iCalPerson *p;
- id uid;
-
- p = [_persons objectAtIndex:i];
- uid = [self getUIDForICalPerson:p];
- if (uid != nil)
- [ma addObject:uid];
- else if (uid == nil && _mapStrictly)
- [ma addObject:sharedNull];
- }
- return ma;
-}
-
-- (NSString *)primaryGetEmailForAgenorUID:(NSString *)_uid {
- NGLdapConnection *conn;
- EOQualifier *q;
- NSEnumerator *resultEnum;
- NGLdapEntry *entry;
- NGLdapAttribute *emailAttr;
- NSString *email;
- unsigned count;
-
- q = [EOQualifier qualifierWithQualifierFormat: qualifierFormat, _uid];
-
- conn = [self ldapConnection];
- resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
- qualifier:q
- attributes:fromEMailAttrs];
- entry = [resultEnum nextObject];
- if (entry == nil) {
- if(debugOn) {
- [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!",
- __PRETTY_FUNCTION__,
- _uid];
- }
- return nil;
- }
- emailAttr = [entry attributeWithName:mailEmissionAttrName];
- if (emailAttr == nil)
- return nil; /* shit happens */
-
- email = nil;
- count = [emailAttr count];
-#if 0 // TODO: explain why this is commented out!
- 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:defaultMailDomain]) {
- // TODO: also check for '@'
- email = candidate;
- break;
- }
- }
- }
-#endif
- if (email == nil && count > 0)
- email = [emailAttr stringValueAtIndex:0];
-
- return email;
-}
-
-- (NSString *)getEmailForUID:(NSString *)_uid
-{
- NSString *email;
- NSRange r;
-
- email = nil;
-
- if ([_uid length] > 0)
- {
- email = [self _cachedEmailForUID: _uid];
- if (!email)
- {
- if (useLDAP)
- email = [self primaryGetEmailForAgenorUID:_uid];
-
- if (!email)
- {
- r = [_uid rangeOfString:@"@"];
- email = ((r.length > 0)
- ? _uid
- : [[_uid stringByAppendingString:@"@"]
- stringByAppendingString: defaultMailDomain]);
- }
-
- if (email)
- [self _cacheEmail: email forUID: _uid];
- }
- }
-
- return email;
-}
-
-
-/* CN */
-
-- (NSString *)primaryGetCNForAgenorUID:(NSString *)_uid {
- static NSArray *cnAttrs = nil;
- NGLdapConnection *conn;
- EOQualifier *q;
- NSEnumerator *resultEnum;
- NGLdapEntry *entry;
- NGLdapAttribute *cnAttr;
- NSString *cn;
-
- if (cnAttrs == nil)
- cnAttrs = [[NSArray alloc] initWithObjects:@"cn", nil];
-
- q = [EOQualifier qualifierWithQualifierFormat: qualifierFormat, _uid];
-
- conn = [self ldapConnection];
- resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
- qualifier:q
- attributes:cnAttrs];
- entry = [resultEnum nextObject];
- if (entry == nil) {
- if(debugOn) {
- [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!",
- __PRETTY_FUNCTION__,
- _uid];
- }
- return nil;
- }
- cnAttr = [entry attributeWithName:@"cn"];
- if(cnAttr == nil && debugOn) {
- [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];
- return cn;
-}
-
-- (NSString *)getCNForUID:(NSString *)_uid {
- NSString *cn;
-
- if ((cn = [self _cachedCNForUID:_uid]) != nil)
- return cn;
-
- if (useLDAP) {
- cn = [self primaryGetCNForAgenorUID:_uid];
- }
- else {
- NSString *s;
- NSRange r;
-
- s = _uid;
- if ([s length] < 10)
- return s;
-
- // TODO: algorithm might be inappropriate, depends on the actual UID
- r = [s rangeOfString:@"."];
- if (r.length == 0)
- cn = s;
- else
- cn = [s substringToIndex:r.location];
- }
-
- [self _cacheCN:cn forUID:_uid];
- return cn;
-}
-
-
-/* Servers, IMAP */
-
-- (NSString *)getIMAPAccountStringForUID:(NSString *)_uid {
- NSString *server;
-
- server = [self getServerForUID:_uid];
- if (server == nil)
- return nil;
- return [NSString stringWithFormat:@"%@@%@", _uid, server];
-}
-
-- (NSArray *)mailServerDiscoveryAttributes {
- static NSArray *attrs = nil;
-
- if (attrs == nil) {
- attrs = [[NSArray alloc] initWithObjects:
- @"uid", /* required for shares */
- @"mineqMelRoutage",
- @"mineqMelServeurPrincipal",
- @"mineqMelPartages",
- mailEmissionAttrName,
- 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: qualifierFormat, _uid];
-
- conn = [self ldapConnection];
- resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
- qualifier:q
- attributes:[self mailServerDiscoveryAttributes]];
- /* we just expect one entry, thus drop the rest */
- entry = [resultEnum nextObject];
- if (entry == nil) {
- if(debugOn) {
- NSLog(@"%s Didn't find LDAP entry for uid '%@'!",
- __PRETTY_FUNCTION__,
- _uid);
- }
- return nil;
- }
- return entry;
-}
-
-- (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];
- serverCandidates = [NSMutableArray arrayWithCapacity:count];
- 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) {
-#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
- host.
-
- The name of the machine is determined by applying a regex on every values of
- the mineqMelRoutage LDAP attribute.
- The regex is : .*%.*@(.*\.melanie2\.i2$)
- It extracts the substring that follows '@', ends with 'melanie2', on
- adresses which have a '%' before the '@'
-
- Example: helge.hesse%opengroupware.org@servername1.melanie2.i2
- -> servername1.melanie2.i2
-
- If only one server name is found by applying the regex on every value of the
- attribute, then this name is the IMAP/SMTP server for that user.
- Note that this is the case when we got a unique (well formed) value for the
- attribute.
- 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;
-
- if ((entry = [self _fetchEntryForAgenorUID:_uid]) == nil)
- return nil;
-
- if ((server = [self serverFromEntry:entry]) != 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 {
- NSString *server;
-
- if (_uid == nil || [_uid length] == 0)
- return nil;
-
- if ((server = [self _cachedServerForUID:_uid]) != nil)
- return server;
-
- if (useLDAP)
- server = [self primaryGetServerForAgenorUID:_uid];
- else if (fallbackIMAP4Server != nil)
- server = fallbackIMAP4Server;
- else {
- [self logWithFormat:@"ERROR: could not get server for uid '%@', "
- @"neither LDAP (SOGoUserManagerUsesLDAP) nor "
- @"a fallback (SOGoFallbackIMAP4Server) is configured.",
- _uid];
- server = nil;
- }
-
- [self _cacheServer:server forUID:_uid];
- return server;
-}
-
-/* shared mailboxes */
-
-- (NSArray *)getSharedMailboxAccountStringsForUID:(NSString *)_uid {
- NSArray *k;
-
- k = [[self getSharedMailboxesAndEMailsForUID:_uid] allKeys];
-
- /* ensure that ordering is always the same */
- return [k sortedArrayUsingSelector:@selector(compare:)];
-}
-
-- (NSString *)emissionEMailFromEntry:(NGLdapEntry *)_entry {
- id emissionAttr;
-
- emissionAttr = [_entry attributeWithName:mailEmissionAttrName];
- if ([emissionAttr count] == 0) {
- [self logWithFormat:@"WARNING: share has no %@ attr: %@",
- mailEmissionAttrName, [_entry dn]];
- return nil;
- }
-
- if ([emissionAttr count] > 1) {
- [self logWithFormat:
- @"WARNING: share has more than one value in %@ attr: %@",
- mailEmissionAttrName, [_entry dn]];
- return nil;
- }
-
- return [emissionAttr stringValueAtIndex:0];
-}
-
-- (NSArray *)getSharedMailboxEMailsForUID:(NSString *)_uid {
- NSMutableArray *shares = nil;
- NGLdapConnection *conn;
- EOQualifier *q;
- NSString *gPattern, *cPattern;
- NSEnumerator *resultEnum;
- NGLdapEntry *entry;
-
- if ([_uid length] == 0)
- return nil;
-
- if (!useLDAP) {
- [self logWithFormat:
- @"Note: LDAP access is disabled, returning no shared froms."];
- return nil;
- }
-
- /* check cache */
- if ((shares = [shareEMailCache objectForKey:_uid]) != nil)
- return shares;
-
- /* G and C mean "emission access" */
- gPattern = [_uid stringByAppendingString:@":G"];
- cPattern = [_uid stringByAppendingString:@":C"];
-
- q = [EOQualifier qualifierWithQualifierFormat:
- @"((mineqMelPartages = %@) OR (mineqMelPartages = %@)) "
- @"AND (objectclass = %@)",
- gPattern, cPattern, shareLDAPClass];
-
- conn = [self ldapConnection];
-
- resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
- qualifier:q
- attributes:fromEMailAttrs];
-
- while ((entry = [resultEnum nextObject]) != nil) {
- NSString *emissionAttr;
-
- if ((emissionAttr = [self emissionEMailFromEntry:entry]) == nil)
- continue;
-
- if (shares == nil) shares = [NSMutableArray arrayWithCapacity:4];
- [shares addObject:emissionAttr];
- }
-
- /* ensure that ordering is always the same */
- [shares sortUsingSelector:@selector(compare:)];
-
- /* cache */
- shares = (shares == nil) ? [NSArray array] : [[shares copy] autorelease];
- [shareEMailCache setObject:shares forKey:_uid];
- return shares;
-}
-
-/* identities */
-
-- (BOOL)hasUser:(NSString *)_uid partageAccess:(char *)_rightset
- inEntry:(NGLdapEntry *)_entry
-{
- NGLdapAttribute *attr;
- unsigned i, count;
-
- attr = [_entry attributeWithName:@"mineqMelPartages"];
- if ((count = [attr count]) == 0) {
- [self logWithFormat:@"WARNING: share has no 'mineqMelPartages' attr: %@",
- [_entry dn]];
- return NO;
- }
-
- for (i = 0; i < count; i++) {
- NSString *p;
- NSRange r;
- unichar c;
- register unsigned j;
-
- p = [attr stringValueAtIndex:i];
- r = [p rangeOfString:@":"];
- if (r.length == 0) {
- [self errorWithFormat:@"Invalid mineqMelPartages value: '%@'", p];
- continue;
- }
-
- /* check whether prefix matches, eg: "helian.h:G" */
- if (r.location != [_uid length]) /* check length */
- continue;
- if (![p hasPrefix:_uid])
- continue;
-
- c = [p characterAtIndex:(r.location + r.length)];
-
- /* check whether permissions match */
- for (j = 0; _rightset[j] != '\0'; j++) {
- if (c == _rightset[j])
- return YES;
- }
- }
- return NO;
-}
-
-- (NSDictionary *)getSharedMailboxesAndEMailsForUID:(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!
-
- This returns a dictionary where the keys are the IMAP4 connect strings
- while the values are the emitter addresses for the box or NSNull if the
- uid is not allowed to emit for this box.
- */
- NSMutableDictionary *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;
- }
-
- /* check cache */
- if ((shares = [shareStoreCache objectForKey:_uid]) != nil)
- return shares;
-
- 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, emitterAddress;
-
- /* calculate server connect string */
-
- 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 = [NSMutableDictionary dictionaryWithCapacity:4];
-
- shareLogin = [shareLogin stringByAppendingString:@"@"];
- shareLogin = [shareLogin stringByAppendingString:server];
-
- /* calculate emitter address (check for proper access right) */
-
- if ([self hasUser:_uid partageAccess:"GC" inEntry:entry])
- emitterAddress = [self emissionEMailFromEntry:entry];
- else
- emitterAddress = [NSNull null];
-
- /* set value */
-
- [shares setObject: emitterAddress
- forKey: shareLogin];
- }
-
- /* cache */
- shares = (shares == nil)
- ? [NSDictionary dictionary]
- : [[shares copy] autorelease];
- [shareStoreCache setObject:shares forKey:_uid];
- return shares;
-}
-
-/* free busy */
-
-- (NSURL *)getFreeBusyURLForUID:(NSString *)_uid {
- [self logWithFormat:@"TODO(%s): implement", __PRETTY_FUNCTION__];
- return nil;
-}
-
-/* defaults */
-
-- (NSUserDefaults *) _getUserDefaultsForUID: (NSString *) uid
- fieldName: (NSString *) fieldName
-{
- id defaults;
-
- if (AgenorProfileURL)
- {
- /* Note: do not cache, otherwise updates can be quite tricky */
- defaults = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
- uid: uid fieldName: fieldName];
- [defaults autorelease];
- }
- else
- {
- [self warnWithFormat:
- @"no profile configured, cannot retrieve defaults for user: '%@'",
- uid];
- return defaults = nil;
- }
-
- return defaults;
-}
-
-- (NSUserDefaults *) getUserDefaultsForUID: (NSString *) uid
-{
- return [self _getUserDefaultsForUID: uid fieldName: @"defaults"];
-}
-
-- (NSUserDefaults *) getUserSettingsForUID: (NSString *) uid
-{
- return [self _getUserDefaultsForUID: uid fieldName: @"settings"];
-}
-
-/* internet access lock */
-
-- (BOOL)isUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid {
- NSNumber *bv;
-
- bv = [changeInternetAccessCache objectForKey:_uid];
- if (!bv) {
- BOOL value;
-
- value = [self primaryIsUserAllowedToChangeSOGoInternetAccess:_uid];
- bv = [NSNumber numberWithBool:value];
- [changeInternetAccessCache setObject:bv forKey:_uid];
- }
- return [bv boolValue];
-}
-
-- (BOOL)primaryIsUserAllowedToChangeSOGoInternetAccess:(NSString *)_uid {
- static NSArray *attrs = nil;
- NGLdapConnection *conn;
- EOQualifier *q;
- NSEnumerator *resultEnum;
- NGLdapEntry *entry;
- NGLdapAttribute *attr;
- NSString *value;
-
- if (attrs == nil)
- attrs = [[NSArray alloc] initWithObjects:changeInternetAccessAttrName, nil];
-
- q = [EOQualifier qualifierWithQualifierFormat: qualifierFormat, _uid];
-
- conn = [self ldapConnection];
- resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
- qualifier:q
- attributes:attrs];
- entry = [resultEnum nextObject];
- if (entry == nil) {
- if(debugOn) {
- [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!",
- __PRETTY_FUNCTION__,
- _uid];
- }
- return NO;
- }
- attr = [entry attributeWithName:changeInternetAccessAttrName];
- if(attr == nil && debugOn) {
- [self logWithFormat:@"%s LDAP entry for uid '%@' "
- @"has no mineqOgoAccesInternet attribute?",
- __PRETTY_FUNCTION__,
- _uid];
- return NO; /* nothing we can do about it */
- }
- value = [attr stringValueAtIndex:0];
- return [value boolValue];
-}
-
-- (BOOL) isInternetAutoresponderEnabledForUser: (NSString *) _uid
-{
- NSNumber *bv;
- BOOL value;
-
- bv = [internetAutoresponderFlagCache objectForKey:_uid];
- if (!bv) {
- value = [self primaryIsInternetAutoresponderEnabledForUser:_uid];
- bv = [NSNumber numberWithBool:value];
- [internetAutoresponderFlagCache setObject:bv forKey:_uid];
- }
- return [bv boolValue];
-}
-
-- (BOOL) primaryIsInternetAutoresponderEnabledForUser: (NSString *) _uid
-{
- NGLdapAttribute *attr;
-
- attr = [self primaryGetMailAutoresponderAttribute:_uid];
- if (!attr) return NO;
-
- return [self isAutoresponderEnabledForAttribute: attr
- matchingPrefix: @"60~"];
-}
-
-- (BOOL) isIntranetAutoresponderEnabledForUser: (NSString *) _uid
-{
- NSNumber *bv;
- BOOL value;
-
- bv = [intranetAutoresponderFlagCache objectForKey:_uid];
- if (!bv)
- {
- value = [self primaryIsIntranetAutoresponderEnabledForUser:_uid];
- bv = [NSNumber numberWithBool:value];
- [intranetAutoresponderFlagCache setObject:bv forKey:_uid];
- }
-
- return [bv boolValue];
-}
-
-- (BOOL) primaryIsIntranetAutoresponderEnabledForUser: (NSString *) _uid
-{
- NGLdapAttribute *attr;
-
- attr = [self primaryGetMailAutoresponderAttribute:_uid];
- if (!attr) return NO;
- return [self isAutoresponderEnabledForAttribute:attr matchingPrefix:@"50~"];
-}
-
-- (BOOL) isAutoresponderEnabledForAttribute: (NGLdapAttribute *)_attr
- matchingPrefix: (NSString *)_prefix
-{
- unsigned i, count;
-
- count = [_attr count];
- for (i = 0; i < count; i++) {
- NSString *value;
-
- value = [_attr stringValueAtIndex:i];
- if ([value hasPrefix:_prefix]) {
- if ([value rangeOfString:@"DFIN:0"].length > 0)
- return NO;
- return YES;
- }
- }
-
- return NO;
-}
-
-- (NGLdapAttribute *) primaryGetMailAutoresponderAttribute: (NSString *) _uid
-{
- static NSArray *attrs = nil;
- NGLdapConnection *conn;
- EOQualifier *q;
- NSEnumerator *resultEnum;
- NGLdapEntry *entry;
- NGLdapAttribute *attr;
-
- if (attrs == nil)
- attrs = [[NSArray alloc] initWithObjects:mailAutoresponderAttrName, nil];
-
- q = [EOQualifier qualifierWithQualifierFormat: qualifierFormat, _uid];
-
- conn = [self ldapConnection];
- resultEnum = [conn deepSearchAtBaseDN:ldapBaseDN
- qualifier:q
- attributes:attrs];
- entry = [resultEnum nextObject];
- if (entry == nil) {
- if(debugOn) {
- [self logWithFormat:@"%s Didn't find LDAP entry for uid '%@'!",
- __PRETTY_FUNCTION__,
- _uid];
- }
- return nil;
- }
- attr = [entry attributeWithName:mailAutoresponderAttrName];
- return attr;
-}
-
-- (iCalPerson *) iCalPersonWithUid: (NSString *) uid
-{
- iCalPerson *person;
-
- person = [iCalPerson new];
- [person autorelease];
- [person setCn: [self getCNForUID: uid]];
- [person setEmail: [self getEmailForUID: uid]];
-
- return person;
-}
-
-/* debugging */
-
-- (BOOL)isDebuggingEnabled {
- return debugOn;
-}
-
-@end /* AgenorUserManager */
LIBRARY_NAME = libSOGo
TOOL_NAME = \
- agenor_email2uid \
- agenor_shares4uid \
- agenor_emails4uid \
- agenor_defaults
+# agenor_email2uid \
+# agenor_shares4uid \
+# agenor_emails4uid \
+# agenor_defaults
libSOGo_SOVERSION=$(MAJOR_VERSION).$(MINOR_VERSION)
SOGoGroupFolder.h \
SOGoCustomGroupFolder.h \
\
- AgenorUserManager.h \
+ LDAPUserManager.h \
+ LDAPSource.h \
SOGoPermissions.h \
SOGoLRUCache.h \
NSArray+Utilities.h \
\
SOGoPermissions.m \
SOGoLRUCache.m \
- AgenorUserManager.m \
+ LDAPUserManager.m \
+ LDAPSource.m \
NSObject+AptComparison.m \
WOContext+Agenor.m \
SOGoDAVRendererTypes.m \
--- /dev/null
+/* LDAPSource.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef LDAPSOURCE_H
+#define LDAPSOURCE_H
+
+#import <Foundation/NSObject.h>
+
+@class NSDictionary;
+@class NSString;
+@class NGLdapConnection;
+
+@interface LDAPSource : NSObject
+{
+ NSString *bindDN;
+ NSString *hostname;
+ unsigned int port;
+ NSString *password;
+
+ NSString *baseDN;
+ NSString *IDField; /* the first part of a user DN */
+ NSString *CNField;
+ NSString *UIDField;
+
+ NGLdapConnection *ldapConnection;
+ NSMutableArray *searchAttributes;
+}
+
++ (id) sourceFromUDSource: (NSDictionary *) udSource;
+
+- (id) initFromUDSource: (NSDictionary *) udSource;
+
+- (void) setBindDN: (NSString *) newBindDN
+ hostname: (NSString *) newBindHostname
+ port: (NSString *) newBindPort
+ andPassword: (NSString *) newBindPassword;
+- (void) setBaseDN: (NSString *) newBaseDN
+ IDField: (NSString *) newIDField
+ CNField: (NSString *) newCNField
+ andUIDField: (NSString *) newUIDField;
+
+- (BOOL) checkLogin: (NSString *) login
+ andPassword: (NSString *) password;
+
+- (NSDictionary *) lookupContactEntry: (NSString *) entryID;
+- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) entryID;
+- (NSArray *) allEntryIDs;
+- (NSArray *) fetchContactsMatching: (NSString *) filter;
+
+@end
+
+#endif /* LDAPSOURCE_H */
--- /dev/null
+/* LDAPSource.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSString.h>
+
+#import <EOControl/EOControl.h>
+#import <NGLdap/NGLdapConnection.h>
+#import <NGLdap/NGLdapAttribute.h>
+#import <NGLdap/NGLdapEntry.h>
+
+#import "LDAPSource.h"
+
+static NSArray *commonSearchFields;
+
+@implementation LDAPSource
+
++ (void) initialize
+{
+ if (!commonSearchFields)
+ {
+ commonSearchFields = [NSArray arrayWithObjects:
+ @"title",
+ @"company",
+ @"o",
+ @"displayName",
+ @"modifytimestamp",
+ @"mozillaHomeState",
+ @"mozillaHomeUrl",
+ @"homeurl",
+ @"st",
+ @"region",
+ @"mozillaCustom2",
+ @"custom2",
+ @"mozillaHomeCountryName",
+ @"description",
+ @"notes",
+ @"department",
+ @"departmentnumber",
+ @"ou",
+ @"orgunit",
+ @"mobile",
+ @"cellphone",
+ @"carphone",
+ @"mozillaCustom1",
+ @"custom1",
+ @"mozillaNickname",
+ @"xmozillanickname",
+ @"mozillaWorkUrl",
+ @"workurl",
+ @"fax",
+ @"facsimileTelephoneNumber",
+ @"telephoneNumber",
+ @"mozillaHomeStreet",
+ @"mozillaSecondEmail",
+ @"xmozillasecondemail",
+ @"mozillaCustom4",
+ @"custom4",
+ @"nsAIMid",
+ @"nscpaimscreenname",
+ @"street",
+ @"streetAddress",
+ @"postOfficeBox",
+ @"homePhone",
+ @"cn",
+ @"commonname",
+ @"givenName",
+ @"mozillaHomePostalCode",
+ @"mozillaHomeLocalityName",
+ @"mozillaWorkStreet2",
+ @"mozillaUseHtmlMail",
+ @"xmozillausehtmlmail",
+ @"mozillaHomeStreet2",
+ @"postalCode",
+ @"zip",
+ @"c",
+ @"countryname",
+ @"pager",
+ @"pagerphone",
+ @"mail",
+ @"sn",
+ @"surname",
+ @"mozillaCustom3",
+ @"custom3",
+ @"l",
+ @"locality",
+ @"birthyear",
+ @"serialNumber",
+ @"calFBURL",
+ nil];
+ [commonSearchFields retain];
+ }
+}
+
++ (id) sourceFromUDSource: (NSDictionary *) udSource
+{
+ id newSource;
+
+ newSource = [[self alloc] initFromUDSource: udSource];
+ [newSource autorelease];
+
+ return newSource;
+}
+
+- (id) init
+{
+ if ((self = [super init]))
+ {
+ bindDN = nil;
+ hostname = nil;
+ port = 389;
+ password = nil;
+
+ baseDN = nil;
+ IDField = @"cn"; /* the first part of a user DN */
+ CNField = @"cn";
+ UIDField = @"uid";
+
+ ldapConnection = nil;
+ searchAttributes = nil;
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [bindDN release];
+ [hostname release];
+ [password release];
+ [baseDN release];
+ [IDField release];
+ [CNField release];
+ [UIDField release];
+ [ldapConnection release];
+ [super dealloc];
+}
+
+- (id) initFromUDSource: (NSDictionary *) udSource
+{
+ self = [self init];
+
+ [self setBindDN: [udSource objectForKey: @"bindDN"]
+ hostname: [udSource objectForKey: @"hostname"]
+ port: [udSource objectForKey: @"port"]
+ andPassword: [udSource objectForKey: @"bindPassword"]];
+ [self setBaseDN: [udSource objectForKey: @"baseDN"]
+ IDField: [udSource objectForKey: @"IDFieldName"]
+ CNField: [udSource objectForKey: @"CNFieldName"]
+ andUIDField: [udSource objectForKey: @"UIDFieldName"]];
+
+ return self;
+}
+
+- (void) setBindDN: (NSString *) newBindDN
+ hostname: (NSString *) newBindHostname
+ port: (NSString *) newBindPort
+ andPassword: (NSString *) newBindPassword
+{
+ ASSIGN (bindDN, newBindDN);
+ ASSIGN (hostname, newBindHostname);
+ if (newBindPort)
+ port = [newBindPort intValue];
+ ASSIGN (password, newBindPassword);
+}
+
+- (void) setBaseDN: (NSString *) newBaseDN
+ IDField: (NSString *) newIDField
+ CNField: (NSString *) newCNField
+ andUIDField: (NSString *) newUIDField
+{
+ ASSIGN (baseDN, newBaseDN);
+ if (newIDField)
+ ASSIGN (IDField, newIDField);
+ if (CNField)
+ ASSIGN (CNField, newCNField);
+ if (UIDField)
+ ASSIGN (UIDField, newUIDField);
+}
+
+- (void) _initLDAPConnection
+{
+ ldapConnection = [[NGLdapConnection alloc] initWithHostName: hostname
+ port: port];
+ [ldapConnection bindWithMethod: @"simple"
+ binddn: bindDN
+ credentials: password];
+}
+
+/* user management */
+- (BOOL) checkLogin: (NSString *) loginToCheck
+ andPassword: (NSString *) passwordToCheck
+{
+ BOOL didBind;
+ NSString *userDN;
+ NGLdapConnection *bindConnection;
+
+ bindConnection = [[NGLdapConnection alloc] initWithHostName: hostname
+ port: port];
+ userDN = [NSString stringWithFormat: @"%@=%@,%@",
+ IDField, loginToCheck, baseDN];
+ NS_DURING
+ didBind = [bindConnection bindWithMethod: @"simple" binddn: userDN
+ credentials: passwordToCheck];
+ NS_HANDLER
+ didBind = NO;
+ NS_ENDHANDLER
+
+ [bindConnection release];
+
+ return didBind;
+}
+
+/* contact management */
+- (EOQualifier *) _qualifierForFilter: (NSString *) filter
+{
+ NSString *qs;
+ EOQualifier *qualifier;
+
+ if (filter && [filter length] > 0)
+ {
+ if ([filter isEqualToString: @"."])
+ qs = @"(cn='*')";
+ else
+ qs = [NSString stringWithFormat:
+ @"(cn='%@*')"
+ @"OR (sn='%@*')"
+ @"OR (displayName='%@*')"
+ @"OR (mail='%@*')"
+ @"OR (telephoneNumber='*%@*')",
+ filter, filter, filter, filter, filter];
+ qualifier = [EOQualifier qualifierWithQualifierFormat: qs];
+ }
+ else
+ qualifier = nil;
+
+ return qualifier;
+}
+
+- (EOQualifier *) _qualifierForUIDFilter: (NSString *) uid
+{
+ NSString *qs;
+
+ qs = [NSString stringWithFormat: (@"(%@='%@') OR (mail='%@')"
+ @" OR (mozillaSecondEmail='%@')"
+ @" OR (xmozillasecondemail='%@')"),
+ UIDField, uid, uid, uid, uid];
+
+ return [EOQualifier qualifierWithQualifierFormat: qs];
+}
+
+- (NSArray *) _searchAttributes
+{
+ if (!searchAttributes)
+ {
+ searchAttributes = [NSMutableArray new];
+ if (CNField)
+ [searchAttributes addObject: CNField];
+ if (UIDField)
+ [searchAttributes addObject: UIDField];
+ [searchAttributes addObjectsFromArray: commonSearchFields];
+ }
+
+ return searchAttributes;
+}
+
+- (NSArray *) allEntryIDs
+{
+ NSMutableArray *ids;
+ NSEnumerator *entries;
+ NGLdapEntry *currentEntry;
+ NSString *value;
+
+ ids = [NSMutableArray array];
+
+ if (!ldapConnection)
+ [self _initLDAPConnection];
+ entries = [ldapConnection deepSearchAtBaseDN: baseDN
+ qualifier: nil
+ attributes: [NSArray arrayWithObject: IDField]];
+ if (entries)
+ {
+ currentEntry = [entries nextObject];
+ while (currentEntry)
+ {
+ value = [[currentEntry attributeWithName: IDField]
+ stringValueAtIndex: 0];
+ if ([value length] > 0)
+ [ids addObject: value];
+ currentEntry = [entries nextObject];
+ }
+ }
+
+ return ids;
+}
+
+- (NSDictionary *) _convertLDAPEntryToContact: (NGLdapEntry *) ldapEntry
+{
+ NSMutableDictionary *contactEntry;
+ NSEnumerator *attributes;
+ NSString *currentAttribute, *value;
+
+ contactEntry = [NSMutableDictionary dictionary];
+ attributes = [[self _searchAttributes] objectEnumerator];
+ currentAttribute = [attributes nextObject];
+ while (currentAttribute)
+ {
+ value = [[ldapEntry attributeWithName: currentAttribute]
+ stringValueAtIndex: 0];
+ if (value)
+ [contactEntry setObject: value forKey: currentAttribute];
+ currentAttribute = [attributes nextObject];
+ }
+ value = [[ldapEntry attributeWithName: IDField] stringValueAtIndex: 0];
+ if (!value)
+ value = @"";
+ [contactEntry setObject: value forKey: @"c_name"];
+ value = [[ldapEntry attributeWithName: UIDField] stringValueAtIndex: 0];
+ if (!value)
+ value = @"";
+ [contactEntry setObject: value forKey: @"c_uid"];
+ value = [[ldapEntry attributeWithName: CNField] stringValueAtIndex: 0];
+ if (!value)
+ value = @"";
+ [contactEntry setObject: value forKey: @"c_cn"];
+
+ return contactEntry;
+}
+
+- (NSArray *) fetchContactsMatching: (NSString *) match
+{
+ NSMutableArray *contacts;
+ NGLdapEntry *currentEntry;
+ NSEnumerator *entries;
+
+ contacts = [NSMutableArray array];
+
+ if (!ldapConnection)
+ [self _initLDAPConnection];
+ entries = [ldapConnection deepSearchAtBaseDN: baseDN
+ qualifier: [self _qualifierForFilter: match]
+ attributes: [self _searchAttributes]];
+ if (entries)
+ {
+ currentEntry = [entries nextObject];
+ while (currentEntry)
+ {
+ [contacts addObject:
+ [self _convertLDAPEntryToContact: currentEntry]];
+ currentEntry = [entries nextObject];
+ }
+ }
+
+ return contacts;
+}
+
+- (NSDictionary *) lookupContactEntry: (NSString *) entryID;
+{
+ NSDictionary *contactEntry;
+ NGLdapEntry *ldapEntry;
+
+ if (!ldapConnection)
+ [self _initLDAPConnection];
+ ldapEntry
+ = [ldapConnection entryAtDN: [NSString stringWithFormat: @"%@=%@,%@",
+ IDField, entryID, baseDN]
+ attributes: [self _searchAttributes]];
+ if (ldapEntry)
+ contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
+ else
+ contactEntry = nil;
+
+ return contactEntry;
+}
+
+- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) uid;
+{
+ NSDictionary *contactEntry;
+ NGLdapEntry *ldapEntry;
+ NSEnumerator *entries;
+ EOQualifier *qualifier;
+
+ if (!ldapConnection)
+ [self _initLDAPConnection];
+ qualifier = [self _qualifierForUIDFilter: uid];
+ entries = [ldapConnection deepSearchAtBaseDN: baseDN
+ qualifier: qualifier
+ attributes: [self _searchAttributes]];
+ ldapEntry = [entries nextObject];
+ if (ldapEntry)
+ contactEntry = [self _convertLDAPEntryToContact: ldapEntry];
+ else
+ contactEntry = nil;
+
+ return contactEntry;
+}
+
+@end
--- /dev/null
+/* LDAPUserManager.h - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef LDAPUSERMANAGER_H
+#define LDAPUSERMANAGER_H
+
+#import <Foundation/NSObject.h>
+
+@class NSDictionary;
+@class NSMutableDictionary;
+@class NSString;
+@class NSTimer;
+
+@class LDAPSource;
+
+@interface LDAPUserManager : NSObject
+{
+ NSMutableDictionary *sources;
+ NSMutableDictionary *sourcesMetadata;
+ NSTimeInterval cleanupInterval;
+ NSTimer *cleanupTimer;
+ NSMutableDictionary *users;
+}
+
++ (id) sharedUserManager;
+
+- (NSArray *) sourceIDs;
+- (NSArray *) authenticationSourceIDs;
+- (NSArray *) addressBookSourceIDs;
+
+- (LDAPSource *) sourceWithID: (NSString *) sourceID;
+- (NSString *) displayNameForSourceWithID: (NSString *) sourceID;
+- (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid;
+- (NSArray *) fetchContactsMatching: (NSString *) match;
+
+- (NSString *) getCNForUID: (NSString *) uid;
+- (NSString *) getEmailForUID: (NSString *) uid;
+- (NSString *) getUIDForEmail: (NSString *) email;
+
+- (BOOL) checkLogin: (NSString *) login
+ andPassword: (NSString *) password;
+
+@end
+
+#endif /* LDAPUSERMANAGER_H */
--- /dev/null
+/* LDAPUserManager.m - this file is part of SOGo
+ *
+ * Copyright (C) 2007 Inverse groupe conseil
+ *
+ * Author: Wolfgang Sourdeau <wsourdeau@inverse.ca>
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This file 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#import <Foundation/NSArray.h>
+#import <Foundation/NSDictionary.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSTimer.h>
+#import <Foundation/NSUserDefaults.h>
+#import <Foundation/NSValue.h>
+
+#import "LDAPSource.h"
+#import "LDAPUserManager.h"
+
+static NSString *defaultMailDomain = nil;
+
+@implementation LDAPUserManager
+
++ (void) initialize
+{
+ NSUserDefaults *ud;
+
+ ud = [NSUserDefaults standardUserDefaults];
+ if (!defaultMailDomain)
+ {
+ defaultMailDomain = [ud stringForKey: @"SOGoDefaultMailDomain"];
+ [defaultMailDomain retain];
+ }
+}
+
++ (id) sharedUserManager
+{
+ static id sharedUserManager = nil;
+
+ if (!sharedUserManager)
+ sharedUserManager = [self new];
+
+ return sharedUserManager;
+}
+
+- (void) _registerSource: (NSDictionary *) udSource
+{
+ NSMutableDictionary *metadata;
+ LDAPSource *ldapSource;
+ NSString *sourceID, *value;
+
+ sourceID = [udSource objectForKey: @"id"];
+ ldapSource = [LDAPSource sourceFromUDSource: udSource];
+ [sources setObject: ldapSource forKey: sourceID];
+ metadata = [NSMutableDictionary dictionary];
+ value = [udSource objectForKey: @"canAuthenticate"];
+ if (value)
+ [metadata setObject: value forKey: @"canAuthenticate"];
+ value = [udSource objectForKey: @"isAddressBook"];
+ if (value)
+ [metadata setObject: value forKey: @"isAddressBook"];
+ value = [udSource objectForKey: @"displayName"];
+ if (value)
+ [metadata setObject: value forKey: @"displayName"];
+ [sourcesMetadata setObject: metadata forKey: sourceID];
+}
+
+- (void) _prepareLDAPSourcesWithDefaults: (NSUserDefaults *) ud
+{
+ NSArray *udSources;
+ unsigned int count, max;
+
+ sources = [NSMutableDictionary new];
+ sourcesMetadata = [NSMutableDictionary new];
+
+ udSources = [ud arrayForKey: @"SOGoLDAPSources"];
+ max = [udSources count];
+ for (count = 0; count < max; count++)
+ [self _registerSource: [udSources objectAtIndex: count]];
+}
+
+- (id) init
+{
+ NSUserDefaults *ud;
+
+ if ((self = [super init]))
+ {
+ ud = [NSUserDefaults standardUserDefaults];
+
+ sources = nil;
+ sourcesMetadata = nil;
+ users = [NSMutableDictionary new];
+ cleanupInterval
+ = [ud integerForKey: @"SOGOLDAPUserManagerCleanupInterval"];
+ if (cleanupInterval)
+ cleanupTimer = [NSTimer timerWithTimeInterval: cleanupInterval
+ target: self
+ selector: @selector (cleanupUsers)
+ userInfo: nil
+ repeats: YES];
+ [self _prepareLDAPSourcesWithDefaults: ud];
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [sources release];
+ [users release];
+ [super dealloc];
+}
+
+- (NSArray *) sourceIDs
+{
+ return [sources allKeys];
+}
+
+- (NSArray *) _sourcesOfType: (NSString *) sourceType
+{
+ NSMutableArray *sourceIDs;
+ NSEnumerator *allIDs;
+ NSString *currentID;
+ NSNumber *canAuthenticate;
+
+ sourceIDs = [NSMutableArray array];
+ allIDs = [[sources allKeys] objectEnumerator];
+ currentID = [allIDs nextObject];
+ while (currentID)
+ {
+ canAuthenticate = [[sourcesMetadata objectForKey: currentID]
+ objectForKey: sourceType];
+ if ([canAuthenticate boolValue])
+ [sourceIDs addObject: currentID];
+ currentID = [allIDs nextObject];
+ }
+
+ return sourceIDs;
+}
+
+- (NSArray *) authenticationSourceIDs
+{
+ return [self _sourcesOfType: @"canAuthenticate"];
+}
+
+- (NSArray *) addressBookSourceIDs
+{
+ return [self _sourcesOfType: @"isAddressBook"];
+}
+
+- (LDAPSource *) sourceWithID: (NSString *) sourceID
+{
+ return [sources objectForKey: sourceID];
+}
+
+- (NSString *) displayNameForSourceWithID: (NSString *) sourceID
+{
+ NSDictionary *metadata;
+
+ metadata = [sourcesMetadata objectForKey: sourceID];
+
+ return [metadata objectForKey: @"displayName"];
+}
+
+- (NSString *) getCNForUID: (NSString *) uid
+{
+ NSDictionary *contactInfos;
+
+ contactInfos = [self contactInfosForUserWithUIDorEmail: uid];
+
+ return [contactInfos objectForKey: @"cn"];
+}
+
+- (NSString *) getEmailForUID: (NSString *) uid
+{
+ NSDictionary *contactInfos;
+
+ contactInfos = [self contactInfosForUserWithUIDorEmail: uid];
+
+ return [contactInfos objectForKey: @"c_email"];
+}
+
+- (NSString *) getUIDForEmail: (NSString *) email
+{
+ NSDictionary *contactInfos;
+
+ contactInfos = [self contactInfosForUserWithUIDorEmail: email];
+
+ return [contactInfos objectForKey: @"c_uid"];
+}
+
+- (BOOL) _ldapCheckLogin: (NSString *) login
+ andPassword: (NSString *) password
+{
+ BOOL checkOK;
+ LDAPSource *ldapSource;
+ NSEnumerator *authIDs;
+ NSString *currentID;
+
+ checkOK = NO;
+
+ authIDs = [[self authenticationSourceIDs] objectEnumerator];
+ currentID = [authIDs nextObject];
+ while (currentID && !checkOK)
+ {
+ ldapSource = [sources objectForKey: currentID];
+ checkOK = [ldapSource checkLogin: login andPassword: password];
+ if (!checkOK)
+ currentID = [authIDs nextObject];
+ }
+
+ return checkOK;
+}
+
+- (BOOL) checkLogin: (NSString *) login
+ andPassword: (NSString *) password
+{
+ BOOL checkOK;
+ NSDate *cleanupDate;
+ NSMutableDictionary *currentUser;
+ NSString *dictPassword;
+
+ currentUser = [users objectForKey: login];
+ dictPassword = [currentUser objectForKey: @"password"];
+ if (currentUser && dictPassword)
+ checkOK = ([dictPassword isEqualToString: password]);
+ else if ([self _ldapCheckLogin: login andPassword: password])
+ {
+ checkOK = YES;
+ if (!currentUser)
+ {
+ currentUser = [NSMutableDictionary dictionary];
+ [users setObject: currentUser forKey: login];
+ }
+ [currentUser setObject: password forKey: @"password"];
+ }
+ else
+ checkOK = NO;
+
+ if (cleanupInterval)
+ {
+ cleanupDate = [[NSDate date] addTimeInterval: cleanupInterval];
+ [currentUser setObject: cleanupDate forKey: @"cleanupDate"];
+ }
+
+ return checkOK;
+}
+
+- (void) _fillContactMailRecords: (NSMutableDictionary *) contact
+{
+ NSMutableArray *emails;
+ NSString *uid;
+
+ emails = [contact objectForKey: @"emails"];
+ uid = [contact objectForKey: @"c_uid"];
+ [emails addObject:
+ [NSString stringWithFormat: @"%@@%@", uid, defaultMailDomain]];
+ [contact setObject: [emails objectAtIndex: 0] forKey: @"c_email"];
+}
+
+- (void) _fillContactInfosForUser: (NSMutableDictionary *) currentUser
+ withUIDorEmail: (NSString *) uid
+{
+ NSMutableArray *emails;
+ NSDictionary *userEntry;
+ NSEnumerator *ldapSources;
+ LDAPSource *currentSource;
+ NSString *cn, *email, *c_uid;
+
+ emails = [NSMutableArray array];
+ cn = nil;
+ c_uid = nil;
+
+ ldapSources = [sources objectEnumerator];
+ currentSource = [ldapSources nextObject];
+ while (currentSource)
+ {
+ userEntry = [currentSource lookupContactEntryWithUIDorEmail: uid];
+ if (userEntry)
+ {
+ if (!cn)
+ cn = [userEntry objectForKey: @"c_cn"];
+ if (!c_uid)
+ c_uid = [userEntry objectForKey: @"c_uid"];
+ email = [userEntry objectForKey: @"mail"];
+ if (email && ![emails containsObject: email])
+ [emails addObject: email];
+ email = [userEntry objectForKey: @"mozillaSecondEmail"];
+ if (email && ![emails containsObject: email])
+ [emails addObject: email];
+ email = [userEntry objectForKey: @"xmozillasecondemail"];
+ if (email && ![emails containsObject: email])
+ [emails addObject: email];
+ }
+ currentSource = [ldapSources nextObject];
+ }
+
+ if (!cn)
+ cn = @"";
+ if (!c_uid)
+ c_uid = @"";
+
+ [currentUser setObject: emails forKey: @"emails"];
+ [currentUser setObject: cn forKey: @"cn"];
+ [currentUser setObject: c_uid forKey: @"c_uid"];
+ [self _fillContactMailRecords: currentUser];
+}
+
+- (void) _retainUser: (NSDictionary *) newUser
+{
+ NSString *key;
+ NSEnumerator *emails;
+
+ key = [newUser objectForKey: @"c_uid"];
+ if (key)
+ [users setObject: newUser forKey: key];
+ emails = [[newUser objectForKey: @"emails"] objectEnumerator];
+ key = [emails nextObject];
+ while (key)
+ {
+ [users setObject: newUser forKey: key];
+ key = [emails nextObject];
+ }
+}
+
+- (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid
+{
+ NSMutableDictionary *currentUser, *contactInfos;
+ NSDate *cleanupDate;
+ BOOL newUser;
+
+ contactInfos = [NSMutableDictionary dictionary];
+ currentUser = [users objectForKey: uid];
+ if (!([currentUser objectForKey: @"emails"]
+ && [currentUser objectForKey: @"cn"]))
+ {
+ if (!currentUser)
+ {
+ newUser = YES;
+ currentUser = [NSMutableDictionary dictionary];
+ }
+ else
+ newUser = NO;
+ [self _fillContactInfosForUser: currentUser
+ withUIDorEmail: uid];
+ if (newUser)
+ [self _retainUser: currentUser];
+ }
+
+ if (cleanupInterval)
+ {
+ cleanupDate = [[NSDate date] addTimeInterval: cleanupInterval];
+ [currentUser setObject: cleanupDate forKey: @"cleanupDate"];
+ }
+
+ return currentUser;
+}
+
+- (void) _fillContactsMailRecords: (NSEnumerator *) contacts
+{
+ NSMutableDictionary *currentContact;
+
+ currentContact = [contacts nextObject];
+ while (currentContact)
+ {
+ [self _fillContactMailRecords: currentContact];
+ currentContact = [contacts nextObject];
+ }
+}
+
+- (NSArray *) _compactAndCompleteContacts: (NSEnumerator *) contacts
+{
+ NSMutableDictionary *compactContacts, *returnContact;
+ NSDictionary *userEntry;
+ NSArray *newContacts;
+ NSMutableArray *emails;
+ NSString *uid, *email;
+
+ compactContacts = [NSMutableDictionary dictionary];
+ userEntry = [contacts nextObject];
+ while (userEntry)
+ {
+ uid = [userEntry objectForKey: @"c_uid"];
+ returnContact = [compactContacts objectForKey: uid];
+ if (!returnContact)
+ {
+ returnContact = [NSMutableDictionary dictionary];
+ [returnContact setObject: uid forKey: @"c_uid"];
+ [compactContacts setObject: returnContact forKey: uid];
+ }
+ if (![[returnContact objectForKey: @"c_name"] length])
+ [returnContact setObject: [userEntry objectForKey: @"c_name"]
+ forKey: @"c_name"];
+ if (![[returnContact objectForKey: @"cn"] length])
+ [returnContact setObject: [userEntry objectForKey: @"c_cn"]
+ forKey: @"cn"];
+ emails = [returnContact objectForKey: @"emails"];
+ if (!emails)
+ {
+ emails = [NSMutableArray array];
+ [returnContact setObject: emails forKey: @"emails"];
+ }
+ email = [userEntry objectForKey: @"mail"];
+ if (email && ![emails containsObject: email])
+ [emails addObject: email];
+ email = [userEntry objectForKey: @"mozillaSecondEmail"];
+ if (email && ![emails containsObject: email])
+ [emails addObject: email];
+ email = [userEntry objectForKey: @"xmozillasecondemail"];
+ if (email && ![emails containsObject: email])
+ [emails addObject: email];
+
+ userEntry = [contacts nextObject];
+ }
+ newContacts = [compactContacts allValues];
+ [self _fillContactsMailRecords: [newContacts objectEnumerator]];
+
+ return newContacts;
+}
+
+- (NSArray *) fetchContactsMatching: (NSString *) filter
+{
+ NSMutableArray *contacts;
+ NSEnumerator *ldapSources;
+ LDAPSource *currentSource;
+
+ contacts = [NSMutableArray array];
+
+ ldapSources = [sources objectEnumerator];
+ currentSource = [ldapSources nextObject];
+ while (currentSource)
+ {
+ [contacts addObjectsFromArray:
+ [currentSource fetchContactsMatching: filter]];
+ currentSource = [ldapSources nextObject];
+ }
+
+ return [self _compactAndCompleteContacts: [contacts objectEnumerator]];
+}
+
+- (void) cleanupSources
+{
+ NSEnumerator *userIDs;
+ NSString *currentID;
+ NSDictionary *currentUser;
+ NSDate *now;
+
+ now = [NSDate date];
+ userIDs = [[users allKeys] objectEnumerator];
+ currentID = [userIDs nextObject];
+ while (currentID)
+ {
+ currentUser = [users objectForKey: currentID];
+ if ([now earlierDate:
+ [currentUser objectForKey: @"cleanupDate"]] == now)
+ [users removeObjectForKey: currentID];
+ currentID = [userIDs nextObject];
+ }
+}
+
+@end
#import <NGLdap/NGLdapConnection.h>
#import "SOGoPermissions.h"
-#include "SOGoAuthenticator.h"
-#include "SOGoUser.h"
-#include "common.h"
+#import "LDAPUserManager.h"
+
+#import "SOGoAuthenticator.h"
+#import "SOGoUser.h"
+#import "common.h"
@implementation SOGoAuthenticator
authMethod = [[ud stringForKey:@"AuthentificationMethod"] retain];
if ([authMethod isEqualToString: @"LDAP"])
{
- LDAPBaseDN = [[ud stringForKey:@"LDAPRootDN"] retain];
- LDAPHost = [[ud stringForKey:@"LDAPHost"] retain];
- LDAPPort = [ud integerForKey:@"LDAPPort"];
+// LDAPBaseDN = [[ud stringForKey:@"LDAPRootDN"] retain];
+// LDAPHost = [[ud stringForKey:@"LDAPHost"] retain];
+// LDAPPort = [ud integerForKey:@"LDAPPort"];
}
}
- (BOOL) LDAPCheckLogin: (NSString *) _login
password: (NSString *) _pwd
{
- return [NGLdapConnection checkPassword: _pwd
- ofLogin: _login
- atBaseDN: LDAPBaseDN
- onHost: LDAPHost
- port: LDAPPort];
+ LDAPUserManager *um;
+
+ um = [LDAPUserManager sharedUserManager];
+
+ return [um checkLogin: _login andPassword: _pwd];
}
/* create SOGoUser */
if (!anonymous)
anonymous
- = [[SOGoUser alloc] initWithLogin:@"anonymous"
+ = [[SOGoUser alloc] initWithLogin: @"anonymous"
roles: [NSArray arrayWithObject: SoRole_Anonymous]];
if (!freebusy)
freebusy
user = anonymous;
}
else
- user = [[[SOGoUser alloc] initWithLogin: login
- roles: [self rolesForLogin: login]]
- autorelease];
+ user = [SOGoUser userWithLogin: login
+ roles: [self rolesForLogin: login]];
}
else
user = nil;
#import "SOGoObject.h"
-@class NSString, NSArray, NSDictionary;
+@class NSArray;
+@class NSDictionary;
+@class NSMutableDictionary;
+@class NSString;
+
@class GCSFolder;
/*
cyclic references.
*/
-@class NSString;
-@class GCSFolder;
-@class NSMutableDictionary;
-
@interface SOGoFolder : SOGoObject
{
NSString *ocsPath;
lookup.
*/
-@class NSString, NSArray, NSMutableString, NSException, NSTimeZone;
-@class GCSFolderManager, GCSFolder;
-@class SOGoUserFolder, SOGoGroupsFolder;
+#import <NGObjWeb/SoObject.h>
+
+@class NSString;
+@class NSArray;
+@class NSMutableString;
+@class NSException;
+@class NSTimeZone;
+
@class WOContext;
+@class GCSFolderManager;
+@class GCSFolder;
+
+@class SOGoUserFolder;
+@class SOGoGroupsFolder;
@class SOGoDAVSet;
#define $(class) NSClassFromString(class)
#import "SOGoUserFolder.h"
#import "SOGoDAVRendererTypes.h"
-#import "AgenorUserManager.h"
#import "SOGoObject.h"
@interface SOGoUser : SoUser
{
- NSString *cn;
- NSString *email;
+ NSString *cn;
+ NSArray *allEmails;
NSUserDefaults *userDefaults;
NSUserDefaults *userSettings;
NSTimeZone *userTimeZone;
}
+ (SOGoUser *) userWithLogin: (NSString *) login
- andRoles: (NSArray *) roles;
+ roles: (NSArray *) roles;
/* properties */
-- (NSString *) email;
+- (NSString *) primaryEmail;
+- (NSString *) systemEmail;
+- (NSArray *) allEmails;
+
+- (BOOL) hasEmail: (NSString *) email;
+
- (NSString *) cn;
- (NSURL *) freeBusyURL;
/* shares and identities */
- (NSString *) primaryIMAP4AccountString;
-- (NSString *) primaryMailServer;
-- (NSArray *) additionalIMAP4AccountStrings;
-- (NSArray *) additionalEMailAddresses;
-- (NSDictionary *) additionalIMAP4AccountsAndEMails;
+
+// - (NSString *) primaryIMAP4AccountString;
+// - (NSString *) primaryMailServer;
+// - (NSArray *) additionalIMAP4AccountStrings;
+// - (NSArray *) additionalEMailAddresses;
+// - (NSDictionary *) additionalIMAP4AccountsAndEMails;
/* defaults */
/* folders */
- (id) homeFolderInContext: (id) _ctx;
-- (id) schedulingCalendarInContext: (id) _ctx;
+// - (id) schedulingCalendarInContext: (id) _ctx;
- (NSArray *) rolesForObject: (NSObject *) object
inContext: (WOContext *) context;
#import <NGObjWeb/SoObject.h>
#import <NGExtensions/NSNull+misc.h>
-#import "AgenorUserManager.h"
+#import "AgenorUserDefaults.h"
+#import "LDAPUserManager.h"
#import "SOGoContentObject.h"
#import "SOGoUser.h"
#import "SOGoPermissions.h"
static NSTimeZone *serverTimeZone = nil;
+static NSString *fallbackIMAP4Server = nil;
+static NSURL *AgenorProfileURL = nil;
@interface NSObject (SOGoRoles)
+ (void) initialize
{
NSString *tzName;
+ NSUserDefaults *ud;
+ NSString *profileURL;
+ ud = [NSUserDefaults standardUserDefaults];
if (!serverTimeZone)
{
- tzName = [[NSUserDefaults standardUserDefaults]
- stringForKey: @"SOGoServerTimeZone"];
+ tzName = [ud stringForKey: @"SOGoServerTimeZone"];
if (!tzName)
tzName = @"Canada/Eastern";
serverTimeZone = [NSTimeZone timeZoneWithName: tzName];
[serverTimeZone retain];
}
+ if (!AgenorProfileURL)
+ {
+ profileURL = [ud stringForKey: @"AgenorProfileURL"];
+ AgenorProfileURL = [[NSURL alloc] initWithString: profileURL];
+ }
+ if (!fallbackIMAP4Server)
+ ASSIGN (fallbackIMAP4Server, [ud stringForKey: @"SOGoFallbackIMAP4Server"]);
}
+ (SOGoUser *) userWithLogin: (NSString *) login
- andRoles: (NSArray *) roles
+ roles: (NSArray *) roles
{
SOGoUser *user;
{
userDefaults = nil;
userSettings = nil;
+ allEmails = nil;
+ }
+
+ return self;
+}
+
+- (id) initWithLogin: (NSString *) newLogin
+ roles: (NSArray *) newRoles
+{
+ LDAPUserManager *um;
+ NSDictionary *user;
+
+ if ([newLogin isEqualToString: @"anonymous"]
+ || [newLogin isEqualToString: @"freebusy"])
+ self = [super initWithLogin: newLogin roles: newRoles];
+ else
+ {
+ um = [LDAPUserManager sharedUserManager];
+ user = [um contactInfosForUserWithUIDorEmail: newLogin];
+ self = [super initWithLogin: [user objectForKey: @"c_uid"]
+ roles: newRoles];
}
return self;
{
[userDefaults release];
[userSettings release];
- [cn release];
- [email release];
[super dealloc];
}
-/* internals */
+- (id) _fetchFieldForUser: (NSString *) field
+{
+ NSDictionary *contactInfos;
+ LDAPUserManager *um;
+
+ um = [LDAPUserManager sharedUserManager];
+ contactInfos = [um contactInfosForUserWithUIDorEmail: login];
-- (AgenorUserManager *) userManager
+ return [contactInfos objectForKey: field];
+}
+
+- (void) _fetchAllEmails
{
- static AgenorUserManager *um = nil;
- if (um == nil) um = [[AgenorUserManager sharedUserManager] retain];
+ allEmails = [self _fetchFieldForUser: @"emails"];
+ [allEmails retain];
+}
- return um;
+- (void) _fetchCN
+{
+ cn = [self _fetchFieldForUser: @"cn"];
+ [cn retain];
}
/* properties */
-- (NSString *) email
+- (NSString *) primaryEmail
{
- if (email == nil)
- {
- email = [[self userManager] getEmailForUID: [self login]];
- [email retain];
- }
+ if (!allEmails)
+ [self _fetchAllEmails];
- return email;
+ return [allEmails objectAtIndex: 0];
}
-- (NSString *) cn
+- (NSString *) systemEmail
{
- if (cn == nil)
- {
- cn = [[self userManager] getCNForUID: [self login]];
- [cn retain];
- }
+ if (!allEmails)
+ [self _fetchAllEmails];
- return cn;
+ return [allEmails lastObject];
}
-- (NSString *) primaryIMAP4AccountString
+- (NSArray *) allEmails
{
- return [[self userManager] getIMAPAccountStringForUID: [self login]];
-}
+ if (!allEmails)
+ [self _fetchAllEmails];
-- (NSString *) primaryMailServer
-{
- return [[self userManager] getServerForUID: [self login]];
+ return allEmails;
}
-- (NSArray *) additionalIMAP4AccountStrings
+- (BOOL) hasEmail: (NSString *) email
{
- return [[self userManager]getSharedMailboxAccountStringsForUID: [self login]];
+ BOOL hasEmail;
+ NSString *currentEmail, *cmpEmail;
+ NSEnumerator *emails;
+
+ hasEmail = NO;
+ if (!allEmails)
+ [self _fetchAllEmails];
+ cmpEmail = [email lowercaseString];
+ emails = [allEmails objectEnumerator];
+ currentEmail = [emails nextObject];
+ while (currentEmail && !hasEmail)
+ if ([[currentEmail lowercaseString] isEqualToString: cmpEmail])
+ hasEmail = YES;
+ else
+ currentEmail = [emails nextObject];
+
+ return hasEmail;
}
-- (NSArray *) additionalEMailAddresses
+- (NSString *) cn
{
- return [[self userManager] getSharedMailboxEMailsForUID: [self login]];
+ if (!cn)
+ [self _fetchCN];
+
+ return cn;
}
-- (NSDictionary *) additionalIMAP4AccountsAndEMails
+- (NSString *) primaryIMAP4AccountString
{
- return [[self userManager] getSharedMailboxesAndEMailsForUID: [self login]];
+ return [NSString stringWithFormat: @"%@@%@", login, fallbackIMAP4Server];
}
+// - (NSString *) primaryMailServer
+// {
+// return [[self userManager] getServerForUID: [self login]];
+// }
+
+// - (NSArray *) additionalIMAP4AccountStrings
+// {
+// return [[self userManager]getSharedMailboxAccountStringsForUID: [self login]];
+// }
+
+// - (NSArray *) additionalEMailAddresses
+// {
+// return [[self userManager] getSharedMailboxEMailsForUID: [self login]];
+// }
+
+// - (NSDictionary *) additionalIMAP4AccountsAndEMails
+// {
+// return [[self userManager] getSharedMailboxesAndEMailsForUID: [self login]];
+// }
+
- (NSURL *) freeBusyURL
{
- return [[self userManager] getFreeBusyURLForUID: [self login]];
+ return nil;
}
/* defaults */
- (NSUserDefaults *) userDefaults
{
if (!userDefaults)
- {
- userDefaults = [[self userManager] getUserDefaultsForUID: [self login]];
- [userDefaults retain];
- }
+ userDefaults = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
+ uid: login
+ fieldName: @"defaults"];
return userDefaults;
}
- (NSUserDefaults *) userSettings
{
if (!userSettings)
- {
- userSettings = [[self userManager] getUserSettingsForUID: [self login]];
- [userSettings retain];
- }
+ userSettings = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
+ uid: login
+ fieldName: @"settings"];
return userSettings;
}
return folder;
}
-- (id) schedulingCalendarInContext: (id) _ctx
-{
- /* Note: watch out for cyclic references */
- id folder;
+// - (id) schedulingCalendarInContext: (id) _ctx
+// {
+// /* Note: watch out for cyclic references */
+// id folder;
- folder = [(WOContext *)_ctx objectForKey:@"ActiveUserCalendar"];
- if (folder != nil)
- return [folder isNotNull] ? folder : nil;
+// folder = [(WOContext *)_ctx objectForKey:@"ActiveUserCalendar"];
+// if (folder != nil)
+// return [folder isNotNull] ? folder : nil;
- folder = [self homeFolderInContext:_ctx];
- if ([folder isKindOfClass:[NSException class]])
- return folder;
+// folder = [self homeFolderInContext:_ctx];
+// if ([folder isKindOfClass:[NSException class]])
+// return folder;
- folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
- if ([folder isKindOfClass:[NSException class]])
- return folder;
+// folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
+// if ([folder isKindOfClass:[NSException class]])
+// return folder;
- [(WOContext *)_ctx setObject:folder ? folder : [NSNull null]
- forKey:@"ActiveUserCalendar"];
- return folder;
-}
+// [(WOContext *)_ctx setObject:folder ? folder : [NSNull null]
+// forKey:@"ActiveUserCalendar"];
+// return folder;
+// }
- (NSArray *) rolesForObject: (NSObject *) object
inContext: (WOContext *) context
( /* the toolbar groups -*-cperl-*- */
( { link = "#";
- isSafe = NO;
- label = "Save";
- onclick = "return saveAcls(this);";
- image = "tb-compose-save-flat-24x24.png"; },
- { link = "#";
isSafe = NO;
label = "Close";
onclick = "window.close();";
#import <NGObjWeb/SoUser.h>
#import <NGObjWeb/WORequest.h>
#import <NGCards/iCalPerson.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/SOGoContentObject.h>
#import <SoObjects/SOGo/SOGoPermissions.h>
- (NSString *) _displayNameForUID: (NSString *) uid
{
- AgenorUserManager *um;
+ LDAPUserManager *um;
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
return [NSString stringWithFormat: @"%@ <%@>",
- [um getCNForUID: uid],
- [um getEmailForUID: uid]];
+ [um getCNForUID: uid], [um getEmailForUID: uid]];
}
- (NSString *) ownerName
return [self jsCloseWithRefreshMethod: nil];
}
+- (BOOL) currentUserIsOwner
+{
+ SOGoObject *clientObject;
+ NSString *currentUserLogin, *ownerLogin;
+
+ clientObject = [self clientObject];
+ ownerLogin = [clientObject ownerInContext: context];
+ currentUserLogin = [[context activeUser] login];
+
+ return [ownerLogin isEqualToString: currentUserLogin];
+}
+
// - (id <WOActionResults>) addUserInAcls
// {
// SOGoObject *clientObject;
#import <NGObjWeb/WODirectAction.h>
-@class SOGoFolder;
@class NSString;
@class NSUserDefaults;
@class NSMutableString;
@class NSMutableDictionary;
+@class LDAPUserManager;
+@class SOGoFolder;
+
@interface UIxFolderActions : WODirectAction
{
SOGoFolder *clientObject;
- AgenorUserManager *um;
+ LDAPUserManager *um;
NSUserDefaults *ud;
NSString *owner;
NSString *login;
#import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/SoSecurityManager.h>
-#import <SOGo/AgenorUserManager.h>
-#import <SOGo/SOGoUser.h>
-#import <SOGo/SOGoObject.h>
-#import <SOGo/SOGoPermissions.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
+#import <SoObjects/SOGo/SOGoUser.h>
+#import <SoObjects/SOGo/SOGoObject.h>
+#import <SoObjects/SOGo/SOGoPermissions.h>
#import "UIxFolderActions.h"
- (void) _setupContext
{
NSString *clientClass;
+ SOGoUser *activeUser;
- login = [[context activeUser] login];
+ activeUser = [context activeUser];
+ login = [activeUser login];
clientObject = [self clientObject];
owner = [clientObject ownerInContext: nil];
else
baseFolder = nil;
- um = [AgenorUserManager sharedUserManager];
- ud = [um getUserSettingsForUID: login];
+ um = [LDAPUserManager sharedUserManager];
+ ud = [activeUser userSettings];
moduleSettings = [ud objectForKey: baseFolder];
if (!moduleSettings)
{
[self _setupContext];
email = [NSString stringWithFormat: @"%@ <%@>",
- [um getCNForUID: owner], [um getEmailForUID: owner]];
+ [um getCNForUID: owner],
+ [um getEmailForUID: owner]];
if ([baseFolder isEqualToString: @"Contacts"])
folderName = [NSString stringWithFormat: @"%@ (%@)",
[clientObject nameInContainer], email];
#import <NGObjWeb/WOContext+SoObjects.h>
#import <NGObjWeb/WORequest.h>
#import <NGObjWeb/WOResponse.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/SOGoObject.h>
#import "UIxObjectActions.h"
WORequest *request;
NSString *uid, *email;
unsigned int code;
- AgenorUserManager *um;
+ LDAPUserManager *um;
SOGoObject *clientObject;
code = 403;
uid = [request formValueForKey: @"uid"];
if ([uid length] > 0)
{
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
email = [um getEmailForUID: uid];
if ([email length] > 0)
{
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WOResponse.h>
#import <NGObjWeb/WORequest.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
#import "UIxUserRightsEditor.h"
- (NSString *) userDisplayName
{
- AgenorUserManager *um;
+ LDAPUserManager *um;
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
return [NSString stringWithFormat: @"%@ <%@>",
[um getCNForUID: uid],
{
BOOL response;
NSString *newUID, *email;
- AgenorUserManager *um;
+ LDAPUserManager *um;
SOGoObject *clientObject;
response = NO;
newUID = [[context request] formValueForKey: @"uid"];
if ([newUID length] > 0)
{
- um = [AgenorUserManager sharedUserManager];
+ um = [LDAPUserManager sharedUserManager];
email = [um getEmailForUID: newUID];
if ([email length] > 0)
{
02111-1307, USA.
*/
-#import <NGCards/NGVCard.h>
-#import <NGCards/NSArray+NGCards.h>
+#import <Foundation/NSString.h>
+#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/SoObject.h>
+#import <NGObjWeb/WORequest.h>
+#import <NGExtensions/NSNull+misc.h>
+
+#import <NGCards/NGVCard.h>
+#import <NGCards/NSArray+NGCards.h>
#import <Contacts/SOGoContactObject.h>
#import <Contacts/SOGoContactFolder.h>
-#import "common.h"
#import "UIxContactEditor.h"
- (id) writeAction
{
- NSString *email, *url;
+ NSString *email, *cn, *url;
+ NSMutableString *address;
card = [[self clientObject] vCard];
[self initSnapshot];
email = [snapshot objectForKey: @"workMail"];
if (email)
- url = [NSString stringWithFormat: @"Mail/compose?mailto=%@", email];
+ {
+ address = [NSMutableString string];
+ cn = [card fn];
+ if ([cn length] > 0)
+ [address appendFormat: @"%@ <%@>", cn, email];
+ else
+ [address appendString: email];
+
+ url = [NSString stringWithFormat: @"Mail/compose?mailto=%@", address];
+ }
else
url = @"Mail/compose";
#import <GDLContentStore/GCSFolder.h>
#import <GDLContentStore/GCSFolderManager.h>
+#import <SoObjects/SOGo/LDAPUserManager.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/NSString+Utilities.h>
#import <SoObjects/Contacts/SOGoContactFolders.h>
return [self _selectActionForApplication: @"mailer-contacts"];
}
-- (NSArray *) _searchResults: (NSString *) contact
- ldapFoldersOnly: (BOOL) ldapFoldersOnly
+- (void) _fillResults: (NSMutableDictionary *) results
+ inFolder: (id <SOGoContactFolder>) folder
+ withSearchOn: (NSString *) contact
{
- NSMutableArray *results;
+ NSEnumerator *folderResults;
+ NSDictionary *currentContact;
+ NSString *uid;
+
+ folderResults = [[folder lookupContactsWithFilter: contact
+ sortBy: @"cn"
+ ordering: NSOrderedAscending] objectEnumerator];
+ currentContact = [folderResults nextObject];
+ while (currentContact)
+ {
+ uid = [currentContact objectForKey: @"c_uid"];
+ if (uid && ![results objectForKey: uid])
+ [results setObject: currentContact
+ forKey: uid];
+ currentContact = [folderResults nextObject];
+ }
+}
+
+- (NSDictionary *) _searchResults: (NSString *) contact
+ ldapFoldersOnly: (BOOL) ldapOnly
+{
+ NSMutableDictionary *results;
SOGoContactFolders *topFolder;
NSEnumerator *sogoContactFolders;
id <SOGoContactFolder> currentFolder;
- results = [NSMutableArray new];
- [results autorelease];
-
+ results = [NSMutableDictionary dictionary];
topFolder = [self clientObject];
sogoContactFolders = [[topFolder contactFolders] objectEnumerator];
currentFolder = [sogoContactFolders nextObject];
while (currentFolder)
{
- if (!ldapFoldersOnly
- || [currentFolder isKindOfClass: [SOGoContactLDAPFolder class]])
- [results addObjectsFromArray: [currentFolder
- lookupContactsWithFilter: contact
- sortBy: @"cn"
- ordering: NSOrderedAscending]];
+ if (!ldapOnly || [currentFolder isKindOfClass: [SOGoContactLDAPFolder class]])
+ [self _fillResults: results inFolder: currentFolder
+ withSearchOn: contact];
currentFolder = [sogoContactFolders nextObject];
}
[topFolder release];
return email;
}
-- (NSDictionary *) _nextResultWithUid: (NSEnumerator *) results
-{
- NSDictionary *result, *possibleResult;
-
- result = nil;
- possibleResult = [results nextObject];
- while (possibleResult && !result)
- if ([[possibleResult objectForKey: @"c_uid"] length])
- result = possibleResult;
- else
- possibleResult = [results nextObject];
-
- return result;
-}
-
-- (WOResponse *) _responseForResults: (NSArray *) results
+- (WOResponse *) _responseForResults: (NSDictionary *) results
{
WOResponse *response;
- NSString *email, *responseString, *uid;
+ NSEnumerator *uids;
+ NSString *responseString, *uid, *cn, *mail;
NSDictionary *result;
response = [context response];
if ([results count])
{
- result = [self _nextResultWithUid: [results objectEnumerator]];
- if (!result)
- result = [results objectAtIndex: 0];
- email = [self _emailForResult: result];
- uid = [result objectForKey: @"c_uid"];
- if ([uid length] == 0)
- uid = @"";
- responseString = [NSString stringWithFormat: @"%@:%@",
- uid, email];
- [response setStatus: 200];
- [response setHeader: @"text/plain; charset=iso-8859-1"
- forKey: @"Content-Type"];
- [response appendContentString: responseString];
+ uids = [[results allKeys] objectEnumerator];
+ uid = [uids nextObject];
+ while (uid)
+ {
+ result = [results objectForKey: uid];
+ cn = [result objectForKey: @"displayName"];
+ if (![cn length])
+ cn = [result objectForKey: @"cn"];
+ mail = [result objectForKey: @"mail"];
+ responseString = [NSString stringWithFormat: @"%@:%@:%@",
+ uid, cn, mail];
+ [response setStatus: 200];
+ [response setHeader: @"text/plain; charset=iso-8859-1"
+ forKey: @"Content-Type"];
+ [response appendContentString: responseString];
+ uid = [uids nextObject];
+ }
}
else
[response setStatus: 404];
WOResponse *response;
NSString *uid, *foldersString;
NSMutableString *responseString;
- NSDictionary *result;
- NSEnumerator *resultsEnum;
+ NSDictionary *contact;
+ NSEnumerator *contacts;
NSArray *folders;
response = [context response];
if ([results count])
{
[response setStatus: 200];
- [response setHeader: @"text/plain; charset=iso-8859-1"
+ [response setHeader: @"text/plain; charset=utf-8"
forKey: @"Content-Type"];
responseString = [NSMutableString new];
- resultsEnum = [results objectEnumerator];
- result = [resultsEnum nextObject];
- while (result)
+ contacts = [results objectEnumerator];
+ contact = [contacts nextObject];
+ while (contact)
{
- uid = [result objectForKey: @"c_uid"];
- folders = [self _foldersForUID: uid ofType: folderType];
- foldersString
- = [self _foldersStringForFolders: [folders objectEnumerator]];
- [responseString appendFormat: @"%@:%@%@\n",
- uid, [self _emailForResult: result], foldersString];
- result = [resultsEnum nextObject];
+ uid = [contact objectForKey: @"c_uid"];
+ if ([uid length] > 0)
+ {
+ folders = [self _foldersForUID: uid ofType: folderType];
+ foldersString
+ = [self _foldersStringForFolders: [folders objectEnumerator]];
+ [responseString appendFormat: @"%@:%@:%@%@\n", uid,
+ [contact objectForKey: @"cn"],
+ [contact objectForKey: @"c_email"],
+ foldersString];
+ }
+ contact = [contacts nextObject];
}
[response appendContentString: responseString];
[responseString release];
{
NSString *contact, *folderType;
id <WOActionResults> result;
- BOOL ldapOnly;
+ LDAPUserManager *um;
+ um = [LDAPUserManager sharedUserManager];
contact = [self queryParameterForKey: @"search"];
if ([contact length] > 0)
{
- ldapOnly = [[self queryParameterForKey: @"ldap-only"] boolValue];
folderType = [self queryParameterForKey: @"type"];
- result = [self _foldersResponseForResults:
- [self _searchResults: contact
- ldapFoldersOnly: ldapOnly]
- withType: folderType];
+ result
+ = [self _foldersResponseForResults: [um fetchContactsMatching: contact]
+ withType: folderType];
}
else
result = [NSException exceptionWithHTTPStatus: 400
#import <NGObjWeb/SoObjects.h>
#import <NGExtensions/NSObject+Values.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/Contacts/SOGoContactFolder.h>
- (NSString *) currentContactFolderName
{
- return [self labelForKey: [currentFolder displayName]];
+ return [currentFolder displayName];
}
- (NSArray *) additionalFolders
{
- AgenorUserManager *um;
NSUserDefaults *ud;
- NSString *login;
if (!additionalFolders)
{
- um = [AgenorUserManager sharedUserManager];
- login = [[context activeUser] login];
- ud = [um getUserSettingsForUID: login];
+ ud = [[context activeUser] userSettings];
additionalFolders
= [[ud objectForKey: @"Contacts"] objectForKey: @"SubscribedFolders"];
[additionalFolders retain];
actionName = "selectForMailer";
};
contactSearch = {
- protectedBy = "View";
+ protectedBy = "<public>";
pageName = "UIxContactFoldersView";
actionName = "contactSearch";
};
};
};
+/* both following class should be "reparented" so as to only have
+ SOGoContactFolder here... */
SOGoContactGCSFolder = {
slots = {
toolbar = {
};
methods = {
view = {
- protectedBy = "View";
+ protectedBy = "<public>";
pageName = "UIxContactsListView";
};
new = {
- protectedBy = "View";
+ protectedBy = "<public>";
pageName = "UIxContactEditor";
actionName = "new";
};
mailer-contacts = {
- protectedBy = "View";
+ protectedBy = "<public>";
pageName = "UIxContactsListView";
actionName = "mailerContacts";
};
canAccessContent = {
- protectedBy = "View";
+ protectedBy = "<public>";
pageName = "UIxContactsListView";
actionName = "canAccessContent";
};
};
};
- SOGoContactLDAPEntry = {
+ SOGoContactLDIFEntry = {
methods = {
view = {
- protectedBy = "View";
+ protectedBy = "<public>";
pageName = "UIxContactView";
};
delete = {
Contacts \
MailerUI \
MailPartViewers \
-
-SUBPROJECTS += \
Templates
include $(GNUSTEP_MAKEFILES)/aggregate.make
*/
#import <SOGoUI/SOGoDateFormatter.h>
-#import <SOGo/SOGoUser.h>
+#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoAppointmentObject.h>
#import <SoObjects/Mailer/SOGoMailObject.h>
- (id)calendarFolder {
/* return scheduling calendar of currently logged-in user */
- return [[[self context] activeUser] schedulingCalendarInContext:
- [self context]];
+ SOGoUser *user;
+ id folder;
+
+ user = [context activeUser];
+ folder = [[user homeFolderInContext: context] lookupName: @"Calendar"
+ inContext: context
+ acquire: NO];
+
+ return folder;
}
- (id)storedEventObject {
/* organizer tracking */
- (NSString *)loggedInUserEMail {
- return [[[self context] activeUser] email];
+ return [[[self context] activeUser] primaryEmail];
}
- (iCalEvent *)authorativeEvent {
02111-1307, USA.
*/
+#import <Foundation/NSFileManager.h>
+#import <Foundation/NSKeyValueCoding.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSUserDefaults.h>
+
+#import <NGObjWeb/WORequest.h>
+#import <NGMail/NGMimeMessage.h>
+#import <NGMail/NGMimeMessageGenerator.h>
+#import <NGObjWeb/SoSubContext.h>
+#import <NGObjWeb/NSException+HTTP.h>
+#import <NGExtensions/NSNull+misc.h>
+#import <NGExtensions/NSObject+Logs.h>
+#import <NGExtensions/NSString+misc.h>
+#import <NGExtensions/NSException+misc.h>
+
+#import <SoObjects/Mailer/SOGoDraftObject.h>
+#import <SoObjects/Mailer/SOGoMailFolder.h>
+#import <SoObjects/Mailer/SOGoMailAccount.h>
+#import <SoObjects/Mailer/SOGoMailAccounts.h>
+#import <SoObjects/Mailer/SOGoMailIdentity.h>
+#import <SoObjects/SOGo/SOGoUser.h>
+#import <SoObjects/SOGo/WOContext+Agenor.h>
#import <SOGoUI/UIxComponent.h>
/*
NSArray *bcc;
NSString *subject;
NSString *text;
- NSArray *fromEMails;
+ NSMutableArray *fromEMails;
NSString *from;
SOGoMailFolder *sentFolder;
@end
-#import <SoObjects/Mailer/SOGoDraftObject.h>
-#import <SoObjects/Mailer/SOGoMailFolder.h>
-#import <SoObjects/Mailer/SOGoMailAccount.h>
-#import <SoObjects/Mailer/SOGoMailAccounts.h>
-#import <SoObjects/Mailer/SOGoMailIdentity.h>
-#import <SoObjects/SOGo/WOContext+Agenor.h>
-#import <NGMail/NGMimeMessage.h>
-#import <NGMail/NGMimeMessageGenerator.h>
-#import <NGObjWeb/SoSubContext.h>
-#import "common.h"
-
@implementation UIxMailEditor
static BOOL keepMailTmpFile = NO;
}
- (void)dealloc {
- [self->sentFolder release];
- [self->fromEMails release];
- [self->from release];
- [self->text release];
- [self->subject release];
- [self->to release];
- [self->cc release];
- [self->bcc release];
-
- [self->attachmentName release];
- [self->attachmentNames release];
+ [sentFolder release];
+ [fromEMails release];
+ [from release];
+ [text release];
+ [subject release];
+ [to release];
+ [cc release];
+ [bcc release];
+
+ [attachmentName release];
+ [attachmentNames release];
[super dealloc];
}
/* accessors */
- (void)setFrom:(NSString *)_value {
- ASSIGNCOPY(self->from, _value);
+ ASSIGNCOPY(from, _value);
}
- (NSString *)from {
- if (![self->from isNotEmpty])
- return [[[self context] activeUser] email];
- return self->from;
+ if (![from isNotEmpty])
+ return [[[self context] activeUser] primaryEmail];
+ return from;
}
- (void)setReplyTo:(NSString *)_ignore {
}
- (void)setSubject:(NSString *)_value {
- ASSIGNCOPY(self->subject, _value);
+ ASSIGNCOPY(subject, _value);
}
- (NSString *)subject {
- return self->subject ? self->subject : @"";
+ return subject ? subject : @"";
}
- (void)setText:(NSString *)_value {
- ASSIGNCOPY(self->text, _value);
+ ASSIGNCOPY(text, _value);
}
- (NSString *)text {
- return [self->text isNotNull] ? self->text : @"";
+ return [text isNotNull] ? text : @"";
}
- (void)setTo:(NSArray *)_value {
- ASSIGNCOPY(self->to, _value);
+ ASSIGNCOPY(to, _value);
}
- (NSArray *)to {
- return [self->to isNotNull] ? self->to : [NSArray array];
+ return [to isNotNull] ? to : [NSArray array];
}
- (void)setCc:(NSArray *)_value {
- ASSIGNCOPY(self->cc, _value);
+ ASSIGNCOPY(cc, _value);
}
- (NSArray *)cc {
- return [self->cc isNotNull] ? self->cc : [NSArray array];
+ return [cc isNotNull] ? cc : [NSArray array];
}
- (void)setBcc:(NSArray *)_value {
- ASSIGNCOPY(self->bcc, _value);
+ ASSIGNCOPY(bcc, _value);
}
- (NSArray *)bcc {
- return [self->bcc isNotNull] ? self->bcc : [NSArray array];
+ return [bcc isNotNull] ? bcc : [NSArray array];
}
- (BOOL)hasOneOrMoreRecipients {
}
- (void)setAttachmentName:(NSString *)_attachmentName {
- ASSIGN(self->attachmentName, _attachmentName);
+ ASSIGN(attachmentName, _attachmentName);
}
- (NSString *)attachmentName {
- return self->attachmentName;
+ return attachmentName;
}
/* from addresses */
-- (NSArray *)fromEMails {
- NSString *primary, *uid;
- NSArray *shares;
-
- if (self->fromEMails != nil)
- return self->fromEMails;
-
- uid = [[self user] login];
- primary = [[[self context] activeUser] email];
- if (![[self context] isAccessFromIntranet]) {
- self->fromEMails = [[NSArray alloc] initWithObjects:&primary count:1];
- return self->fromEMails;
- }
-
- shares =
- [[[self context] activeUser] valueForKey:@"additionalEMailAddresses"];
- if ([shares count] == 0)
- self->fromEMails = [[NSArray alloc] initWithObjects:&primary count:1];
- else {
- id tmp;
+- (NSArray *) fromEMails
+{
+ NSEnumerator *emails;
+ SOGoUser *activeUser;
+ NSString *cn, *fullMail, *email;
+
+ if (!fromEMails)
+ {
+ fromEMails = [NSMutableArray new];
+ activeUser = [context activeUser];
+ cn = [activeUser cn];
+ if ([cn length] == 0)
+ cn = nil;
+ emails = [[activeUser allEmails] objectEnumerator];
+ email = [emails nextObject];
+ while (email)
+ {
+ if (cn)
+ fullMail = [NSString stringWithFormat: @"%@ <%@>", cn, email];
+ else
+ fullMail = email;
+ [fromEMails addObject: fullMail];
+ email = [emails nextObject];
+ }
+ }
- tmp = [[NSArray alloc] initWithObjects:&primary count:1];
- self->fromEMails = [[tmp arrayByAddingObjectsFromArray:shares] copy];
- [tmp release]; tmp = nil;
- }
- return self->fromEMails;
+ return fromEMails;
}
/* title */
SOGoMailAccount *account;
SOGoMailFolder *folder;
- if (self->sentFolder != nil)
- return [self->sentFolder isNotNull] ? self->sentFolder : nil;;
+ if (sentFolder != nil)
+ return [sentFolder isNotNull] ? sentFolder : nil;;
account = [[self clientObject] mailAccountFolder];
if ([account isKindOfClass:[NSException class]]) return account;
folder = [account sentFolderInContext:[self context]];
if ([folder isKindOfClass:[NSException class]]) return folder;
- return ((self->sentFolder = [folder retain]));
+ return ((sentFolder = [folder retain]));
}
- (void)_presetFromBasedOnAccountsQueryParameter {
if (useLocationBasedSentFolder) /* from will be based on location */
return;
- if ([self->from isNotEmpty]) /* a from is already set */
+ if ([from isNotEmpty]) /* a from is already set */
return;
accountID = [[[self context] request] formValueForKey:@"account"];
NSArray *sentFolderPath;
NSException *error = nil;
- if (self->sentFolder != nil)
- return [self->sentFolder isNotNull] ? self->sentFolder : nil;;
+ if (sentFolder != nil)
+ return [sentFolder isNotNull] ? sentFolder : nil;;
identity = [self selectedMailIdentity];
if ([identity isKindOfClass:[NSException class]]) return identity;
ctx = [[SoSubContext alloc] initWithParentContext:[self context]];
- self->sentFolder = [[accounts traversePathArray:sentFolderPath
+ sentFolder = [[accounts traversePathArray:sentFolderPath
inContext:ctx error:&error
acquire:NO] retain];
[ctx release]; ctx = nil;
#if 0
[self logWithFormat:@"Sent-Folder: %@", sentFolderName];
- [self logWithFormat:@" object: %@", self->sentFolder];
+ [self logWithFormat:@" object: %@", sentFolder];
#endif
- return self->sentFolder;
+ return sentFolder;
}
- (NSException *)storeMailInSentFolder:(NSString *)_path {
- (NSArray *)attachmentNames {
NSArray *a;
- if (self->attachmentNames != nil)
- return self->attachmentNames;
+ if (attachmentNames != nil)
+ return attachmentNames;
a = [[self clientObject] fetchAttachmentNames];
a = [a sortedArrayUsingSelector:@selector(compare:)];
- self->attachmentNames = [a copy];
- return self->attachmentNames;
+ attachmentNames = [a copy];
+ return attachmentNames;
}
- (BOOL)hasAttachments {
return [[self attachmentNames] count] > 0 ? YES : NO;
"Start" = "Start";
"End" = "End";
"Location" = "Location";
-"(Private Event)" = "(Événement privé)";
+"(Private Event)" = "(Private Event)";
"closeThisWindowMessage" = "Thank you! You may now close this window.";
"Multicolumn Day View" = "Multicolumn Day View";
UIxCalDateSelector.m \
UIxCalUserRightsEditor.m \
\
- UIxComponent+Agenor.m \
+ UIxComponent+Scheduler.m \
UIxCalView.m \
UIxCalAptListView.m \
UIxCalTasksListView.m \
label="Day View";
onclick = "return onDayOverview();";
image = "day-view.png"; },
- { link = "dayoverview";
+/* disabled until we fix the view */
+/* { link = "dayoverview";
label="Multicolumn Day View";
onclick = "return onMulticolumnDayOverview();";
- image = "day-view-multicolumn.png"; },
+ image = "day-view-multicolumn.png"; }, */
{ link = "weekoverview";
label="Week View";
onclick = "return onWeekOverview();";
#import <NGCards/iCalEvent.h>
#import <NGCards/iCalPerson.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoContentObject.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
[[self clientObject] baseURL]];
}
-- (NSString *) _toolbarForCalObject
-{
- SOGoUser *currentUser;
- SOGoAppointmentObject *clientObject;
- NSString *filename, *email;
- iCalPerson *person;
- iCalPersonPartStat participationStatus;
-
- clientObject = [self clientObject];
- currentUser = [[self context] activeUser];
- email = [currentUser email];
- if ([clientObject isOrganizer: email
- orOwner: [currentUser login]])
- filename = @"SOGoAppointmentObject.toolbar";
- else
- {
- if ([clientObject isParticipant: email])
- {
- person = [[clientObject component: NO] findParticipantWithEmail: email];
- participationStatus = [person participationStatus];
- if (participationStatus == iCalPersonPartStatAccepted)
- filename = @"SOGoAppointmentObjectDecline.toolbar";
- else if (participationStatus == iCalPersonPartStatDeclined)
- filename = @"SOGoAppointmentObjectAccept.toolbar";
- else
- filename = @"SOGoAppointmentObjectAcceptOrDecline.toolbar";
- }
- else
- filename = @"SOGoComponentClose.toolbar";
- }
-
- return filename;
-}
-
-- (NSString *) toolbar
-{
- return ([self _toolbarForCalObject]);
-}
-
/* icalendar values */
- (BOOL) isAllDay
{
#import "UIxAppointmentView.h"
#import <NGCards/NGCards.h>
#import <SOGo/WOContext+Agenor.h>
+#import <SOGo/SOGoUser.h>
#import <Appointments/SOGoAppointmentObject.h>
#import <SOGoUI/SOGoDateFormatter.h>
-#import "UIxComponent+Agenor.h"
+#import "UIxComponent+Scheduler.h"
#import "common.h"
@interface UIxAppointmentView (PrivateAPI)
- (BOOL)isAttendeeActiveUser {
NSString *email, *attEmail;
- email = [[[self context] activeUser] email];
+ email = [[[self context] activeUser] primaryEmail];
attendee = [self attendee];
attEmail = [attendee rfc822Email];
NSString *email;
iCalPerson *organizer;
- email = [[[self context] activeUser] email];
+ email = [[[self context] activeUser] primaryEmail];
organizer = [[self appointment] organizer];
if (!organizer) return YES; // assume this is correct to do, right?
return [[organizer rfc822Email] isEqualToString:email];
return YES;
/* can access it if I'm invited :-) */
- email = [[[self context] activeUser] email];
+ email = [[[self context] activeUser] primaryEmail];
partMails = [[[self appointment] participants] valueForKey:@"rfc822Email"];
return [partMails containsObject:email];
}
if ((prio = [appointment valueForKey:@"priority"])) {
[ms appendFormat:@" apt_prio%@", prio];
}
- email = [[[self context] activeUser] email];
+ email = [[context activeUser] primaryEmail];
s = [appointment valueForKey:@"orgmail"];
if ([s isNotNull])
{
#import <NGCards/NGCards.h>
#import <SOGoUI/SOGoAptFormatter.h>
-#import "UIxComponent+Agenor.h"
+#import "UIxComponent+Scheduler.h"
#import "SoObjects/Appointments/SOGoAppointmentFolder.h"
#import <SOGo/NSArray+Utilities.h>
{
count = [_apts count];
filtered = [[[NSMutableArray alloc] initWithCapacity: count] autorelease];
- email = [self emailForUser];
+ email = [[context activeUser] primaryEmail];
for (i = 0; i < count; i++)
{
#import <NGExtensions/NGExtensions.h>
#import <NGCards/iCalPerson.h>
-#import <SOGo/AgenorUserManager.h>
#import <SOGo/SOGoUser.h>
#import <SOGoUI/UIxComponent.h>
#import <Appointments/SOGoAppointmentFolder.h>
- (NSArray *) getICalPersonsFromValue: (NSString *) selectorValue;
-/* email, cn */
-- (NSString *) emailForUser;
-- (NSString *) cnForUser;
-
@end
#endif /* __UIxComponent_Agenor_H_ */
02111-1307, USA.
*/
-#include "UIxComponent+Agenor.h"
-#include <SOGo/AgenorUserManager.h>
-#include <SOGo/WOContext+Agenor.h>
-#include <SOGo/SOGoUser.h>
-#include "common.h"
+#import <Foundation/NSArray.h>
+#import <Foundation/NSEnumerator.h>
+#import <Foundation/NSString.h>
+
+#import <SoObjects/Appointments/SOGoCalendarComponent.h>
+
+#import "UIxComponent+Scheduler.h"
@implementation UIxComponent(Agenor)
NSMutableArray *persons;
NSEnumerator *uids;
NSString *uid;
- AgenorUserManager *um;
+ SOGoCalendarComponent *component;
- um = [AgenorUserManager sharedUserManager];
+ component = [self clientObject];
persons = [NSMutableArray new];
[persons autorelease];
uid = [uids nextObject];
while (uid)
{
- [persons addObject: [um iCalPersonWithUid: uid]];
+ [persons addObject: [component iCalPersonWithUID: uid]];
uid = [uids nextObject];
}
}
return persons;
}
-- (NSString *) emailForUser
-{
- return [[context activeUser] email];
-}
-
-- (NSString *) cnForUser
-{
- return [[context activeUser] cn];
-}
-
@end /* UIxComponent(Agenor) */
NSString *attendeesEmails;
}
+- (NSString *) toolbar;
- (void) setComponent: (iCalRepeatableEntityObject *) newComponent;
- (void) setSaveURL: (NSString *) newSaveURL;
#import <NGObjWeb/NSException+HTTP.h>
#import <NGObjWeb/WORequest.h>
-#import <SOGo/AgenorUserManager.h>
#import <SOGo/SOGoUser.h>
#import <SOGoUI/SOGoDateFormatter.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
#import <SoObjects/Appointments/SOGoTaskObject.h>
#import <SoObjects/SOGo/NSString+Utilities.h>
-#import "UIxComponent+Agenor.h"
+#import "UIxComponent+Scheduler.h"
#import "UIxComponentEditor.h"
- (BOOL) isMyComponent
{
- // TODO: this should check a set of emails against the SoUser
- return ([[organizer rfc822Email] isEqualToString: [self emailForUser]]);
+ return ([[context activeUser] hasEmail: [organizer rfc822Email]]);
}
- (BOOL) canEditComponent
- (void) _handleOrganizer
{
NSString *organizerEmail;
+ SOGoUser *activeUser;
organizerEmail = [[component organizer] email];
if ([organizerEmail length] == 0)
if ([[component attendees] count] > 0)
{
ASSIGN (organizer, [iCalPerson elementWithTag: @"organizer"]);
- [organizer setCn: [self cnForUser]];
- [organizer setEmail: [self emailForUser]];
+ activeUser = [context activeUser];
+ [organizer setCn: [activeUser cn]];
+ [organizer setEmail: [activeUser primaryEmail]];
[component setOrganizer: organizer];
}
}
[component setLastModified: now];
}
+- (NSString *) toolbar
+{
+ SOGoUser *currentUser;
+ SOGoCalendarComponent *clientObject;
+ NSString *toolbarFilename;
+ iCalPerson *person;
+ iCalPersonPartStat participationStatus;
+
+ clientObject = [self clientObject];
+ currentUser = [[self context] activeUser];
+ if ([clientObject isOrganizerOrOwner: currentUser])
+ {
+ if ([[clientObject componentTag] isEqualToString: @"vevent"])
+ toolbarFilename = @"SOGoAppointmentObject.toolbar";
+ else
+ toolbarFilename = @"SOGoTaskObject.toolbar";
+ }
+ else
+ {
+ /* Lightning does not manage participation status within tasks */
+ person = [clientObject participant: currentUser];
+ if (person)
+ {
+ participationStatus = [person participationStatus];
+ if (participationStatus == iCalPersonPartStatAccepted)
+ toolbarFilename = @"SOGoAppointmentObjectDecline.toolbar";
+ else if (participationStatus == iCalPersonPartStatDeclined)
+ toolbarFilename = @"SOGoAppointmentObjectAccept.toolbar";
+ else
+ toolbarFilename = @"SOGoAppointmentObjectAcceptOrDecline.toolbar";
+ }
+ else
+ toolbarFilename = @"SOGoComponentClose.toolbar";
+ }
+
+ return toolbarFilename;
+}
+
@end
#import <NGCards/iCalToDo.h>
#import <NGCards/iCalPerson.h>
-#import <SoObjects/SOGo/AgenorUserManager.h>
#import <SoObjects/SOGo/SOGoUser.h>
#import <SoObjects/SOGo/SOGoContentObject.h>
#import <SoObjects/Appointments/SOGoAppointmentFolder.h>
[[self clientObject] baseURL]];
}
-- (NSString *) _toolbarForCalObject
-{
- SOGoUser *currentUser;
- SOGoTaskObject *clientObject;
- NSString *filename, *email;
- iCalPerson *person;
- iCalPersonPartStat participationStatus;
-
- clientObject = [self clientObject];
- currentUser = [[self context] activeUser];
- email = [currentUser email];
- if ([clientObject isOrganizer: email
- orOwner: [currentUser login]])
- filename = @"SOGoTaskObject.toolbar";
- else
- {
- if ([clientObject isParticipant: email])
- {
- person = [[clientObject component: NO] findParticipantWithEmail: email];
- participationStatus = [person participationStatus];
- if (participationStatus == iCalPersonPartStatAccepted)
- filename = @"SOGoTaskObjectDecline.toolbar";
- else if (participationStatus == iCalPersonPartStatDeclined)
- filename = @"SOGoTaskObjectAccept.toolbar";
- else
- filename = @"SOGoTaskObjectAcceptOrDecline.toolbar";
- }
- else
- filename = @"SOGoComponentClose.toolbar";
- }
-
- return filename;
-}
-
-- (NSString *) toolbar
-{
- return ([self _toolbarForCalObject]);
-}
-
/* icalendar values */
- (void) setTaskStartDate: (NSCalendarDate *) newTaskStartDate
{
#import "UIxTaskView.h"
#import <NGCards/NGCards.h>
#import <SOGo/WOContext+Agenor.h>
+#import <SOGo/SOGoUser.h>
#import <Appointments/SOGoTaskObject.h>
#import <SOGoUI/SOGoDateFormatter.h>
-#import "UIxComponent+Agenor.h"
+#import "UIxComponent+Scheduler.h"
#import "common.h"
@interface UIxTaskView (PrivateAPI)
- (BOOL)isAttendeeActiveUser {
NSString *email, *attEmail;
- email = [[[self context] activeUser] email];
+ email = [[[self context] activeUser] primaryEmail];
attendee = [self attendee];
attEmail = [attendee rfc822Email];
NSString *email;
iCalPerson *organizer;
- email = [[[self context] activeUser] email];
+ email = [[[self context] activeUser] primaryEmail];
organizer = [[self task] organizer];
if (!organizer) return YES; // assume this is correct to do, right?
return [[organizer rfc822Email] isEqualToString:email];
return YES;
/* can access it if I'm invited :-) */
- email = [[[self context] activeUser] email];
+ email = [[[self context] activeUser] primaryEmail];
partMails = [[[self task] participants] valueForKey:@"rfc822Email"];
- return [partMails containsObject:email];
+ return [partMails containsObject: email];
}
- (BOOL)canEditApt {
<li><var:string label:value="Modify" /></li>
<li id="accessRightsMenuEntry"><var:string label:value="Access Rights..." /></li>
<li class="separator"></li>
- <li><var:string label:value="New Card" /></li>
- <li><var:string label:value="New List" /></li>
+ <li class="disabled"><var:string label:value="New Card" /></li>
+ <li class="disabled"><var:string label:value="New List" /></li>
<li class="separator"></li>
- <li><var:string label:value="Delete" /></li>
+ <li class="disabled"><var:string label:value="Delete" /></li>
</ul>
</div>
<li id="modifyContactMenuEntry" onmouseup="return onMenuEditContact(event, this);"><var:string label:value="Modify" /></li>
<li class="separator"></li>
<li id="writeToContactMenuEntry" onmouseup="return onMenuWriteToContact(event, this);"><var:string label:value="Write" /></li>
- <li id="imContactMenuEntry"><var:string label:value="Instant Message" /></li>
+ <li class="disabled" id="imContactMenuEntry"><var:string label:value="Instant Message" /></li>
<li class="separator"></li>
<li id="deleteContactMenuEntry" onmouseup="return onMenuDeleteContact(event, this);"><var:string label:value="Delete" /></li>
</ul>
# GNUstep makefile
-validate-wox:
- xmllint --noout *.wox
-
+XMLLINT = xmllint
+XMLLINT-BIN = $(shell which $(XMLLINT))
+ifeq ($(XMLLINT-BIN),)
+all ::
+ @echo Utility \"$(XMLLINT)\" not found. Skipping validation.
+else
all :: validate-wox
+endif
+
+WOXS = $(shell find . -name '*.wox' -type f)
+
+validate-wox:
+ for wox in $(WOXS); \
+ do $(XMLLINT-BIN) --noout $$wox || exit 1; \
+ done;
-install :: all
+install ::
clean ::
popup="isPopup"
>
<div class="menu" id="accountIconMenu">
- <ul id="sourceList">
- <li><var:string label:value="Subscribe..." /></li>
- <li><var:string label:value="Get Messages for Account" /></li>
- <li><var:string label:value="New Folder..." /></li>
+ <ul>
+ <li class="disabled"><var:string label:value="Subscribe..." /></li>
+ <li class="disabled"><var:string label:value="Get Messages for Account" /></li>
+ <li class="disabled"><var:string label:value="New Folder..." /></li>
<li class="separator"></li>
- <li><var:string label:value="Search Messages..." /></li>
- <li><var:string label:value="Properties..." /></li>
+ <li class="disabled"><var:string label:value="Search Messages..." /></li>
+ <li class="disabled"><var:string label:value="Properties..." /></li>
</ul>
</div>
<div class="menu" id="inboxIconMenu">
- <ul id="sourceList">
- <li><var:string label:value="Open in New Mail Window" /></li>
- <li><var:string label:value="Copy Folder Location" /></li>
- <li><var:string label:value="Subscribe..." /></li>
+ <ul>
+ <li class="disabled"><var:string label:value="Open in New Mail Window" /></li>
+ <li class="disabled"><var:string label:value="Copy Folder Location" /></li>
+ <li class="disabled"><var:string label:value="Subscribe..." /></li>
<li class="separator"></li>
- <li><var:string label:value="Mark Folder Read..." /></li>
- <li><var:string label:value="New Folder..." /></li>
+ <li class="disabled"><var:string label:value="Mark Folder Read..." /></li>
+ <li class="disabled"><var:string label:value="New Folder..." /></li>
<li><var:string label:value="Compact This Folder" /></li>
<li class="separator"></li>
- <li><var:string label:value="Search Messages..." /></li>
- <li><var:string label:value="Properties..." /></li>
+ <li class="disabled"><var:string label:value="Search Messages..." /></li>
+ <li class="disabled"><var:string label:value="Properties..." /></li>
</ul>
</div>
<div class="menu" id="trashIconMenu">
- <ul id="sourceList">
- <li><var:string label:value="Open in New Mail Window" /></li>
- <li><var:string label:value="Copy Folder Location" /></li>
- <li><var:string label:value="Subscribe..." /></li>
+ <ul>
+ <li class="disabled"><var:string label:value="Open in New Mail Window" /></li>
+ <li class="disabled"><var:string label:value="Copy Folder Location" /></li>
+ <li class="disabled"><var:string label:value="Subscribe..." /></li>
<li class="separator"></li>
- <li><var:string label:value="Mark Folder Read..." /></li>
- <li><var:string label:value="New Subfolder..." /></li>
- <li><var:string label:value="Compact This Folder" /></li>
- <li><var:string label:value="Empty Trash" /></li>
+ <li class="disabled"><var:string label:value="Mark Folder Read..." /></li>
+ <li class="disabled"><var:string label:value="New Subfolder..." /></li>
+ <li class="disabled"><var:string label:value="Compact This Folder" /></li>
+ <li class="disabled"><var:string label:value="Empty Trash" /></li>
<li class="separator"></li>
- <li><var:string label:value="Search Messages..." /></li>
- <li><var:string label:value="Properties..." /></li>
+ <li class="disabled"><var:string label:value="Search Messages..." /></li>
+ <li class="disabled"><var:string label:value="Properties..." /></li>
</ul>
</div>
<div class="menu" id="mailboxIconMenu">
- <ul id="sourceList">
- <li><var:string label:value="Open in New Mail Window" /></li>
- <li><var:string label:value="Copy Folder Location" /></li>
- <li><var:string label:value="Subscribe..." /></li>
+ <ul>
+ <li class="disabled"><var:string label:value="Open in New Mail Window" /></li>
+ <li class="disabled"><var:string label:value="Copy Folder Location" /></li>
+ <li class="disabled"><var:string label:value="Subscribe..." /></li>
<li class="separator"></li>
- <li><var:string label:value="Mark Folder Read..." /></li>
- <li><var:string label:value="New Subfolder..." /></li>
- <li><var:string label:value="Rename Folder..." /></li>
- <li><var:string label:value="Compact This Folder" /></li>
- <li><var:string label:value="Delete Folder" /></li>
+ <li class="disabled"><var:string label:value="Mark Folder Read..." /></li>
+ <li class="disabled"><var:string label:value="New Subfolder..." /></li>
+ <li class="disabled"><var:string label:value="Rename Folder..." /></li>
+ <li class="disabled"><var:string label:value="Compact This Folder" /></li>
+ <li class="disabled"><var:string label:value="Delete Folder" /></li>
<li class="separator"></li>
- <li><var:string label:value="Search Messages..." /></li>
- <li><var:string label:value="Properties..." /></li>
+ <li class="disabled"><var:string label:value="Search Messages..." /></li>
+ <li class="disabled"><var:string label:value="Properties..." /></li>
</ul>
</div>
<div class="menu" id="addressMenu">
- <ul id="sourceList">
+ <ul>
<li id="add_to_addressbook"
onmouseup="newContactFromEmail(this);"><var:string label:value="Add to Address Book..."/></li>
<li id="compose_mailto"
</div>
<div class="menu" id="messageListMenu">
- <ul id="sourceList">
+ <ul>
<li
onmouseup="onMenuOpenMessage(event);"><var:string label:value="Open Message In New Window"/></li>
<li class="separator"></li>
onmouseup="onMenuReplyToAll(event);"><var:string label:value="Reply to All"/></li>
<li
onmouseup="onMenuForwardMessage(event);"><var:string label:value="Forward"/></li>
- <li
+ <li class="disabled"
onmouseup="onMenuEditMessageAsNew(event);"><var:string label:value="Edit As New..."/></li>
<li class="separator"></li>
<li
- class="submenu"
+ class="disabled submenu"
mailboxaction="move"
submenu="mailboxes-menu"
- onmouseover="dropDownSubmenu(event);"><var:string label:value="Move To"/></li>
+ onmouseoverx="dropDownSubmenu(event);"><var:string label:value="Move To"/></li>
<li
- class="submenu"
+ class="disabled submenu"
mailboxaction="copy"
submenu="mailboxes-menu"
- onmouseover="dropDownSubmenu(event);"><var:string label:value="Copy To"/></li>
+ onmouseoverx="dropDownSubmenu(event);"><var:string label:value="Copy To"/></li>
<li
- class="submenu"
+ class="disabled submenu"
submenu="label-menu"
- onmouseover="dropDownSubmenu(event);"><var:string label:value="Label"/></li>
+ onmouseoverx="dropDownSubmenu(event);"><var:string label:value="Label"/></li>
<li
- class="submenu"
+ class="disabled submenu"
submenu="mark-menu"
- onmouseover="dropDownSubmenu(event);"><var:string label:value="Mark"/></li>
+ onmouseoverx="dropDownSubmenu(event);"><var:string label:value="Mark"/></li>
<li class="separator"></li>
- <li
+ <li class="disabled"
onmouseup="onMenuSaveMessageAs(event);"><var:string label:value="Save As..."/></li>
- <li
+ <li class="disabled"
onmouseup="onMenuPreviewPrintMessage(event);"><var:string label:value="Print Preview"/></li>
- <li
+ <li class="disabled"
onmouseup="onMenuPrintMessage(event);"><var:string label:value="Print..."/></li>
<li
onmouseup="onMenuDeleteMessage(event);"><var:string label:value="Delete Message"/></li>
<li onmouseup="onMenuLabelMessage(event, 'work');"><var:string label:value="Work" /></li>
<li onmouseup="onMenuLabelMessage(event, 'personal');"><var:string label:value="Personal" /></li>
<li onmouseup="onMenuLabelMessage(event, 'todo');"><var:string label:value="To Do" /></li>
- <li onmouseup="onMenuLab-elMessage(event, 'later');"><var:string label:value="Later" /></li>
+ <li onmouseup="onMenuLabelMessage(event, 'later');"><var:string label:value="Later" /></li>
</ul>
</div>
xmlns:label="OGo:label"
className="UIxComponentEditor"
var:component="event"
- var:toolbar="toolbar"
var:saveURL="saveURL">
<!-- <label><span id="allDay" class="content"><input class="checkBox"
type="checkbox" var:selection="isAllDay"
xmlns:var="http://www.skyrix.com/od/binding"
xmlns:const="http://www.skyrix.com/od/constant"
xmlns:uix="OGo:uix"
+ xmlns:rsrc="OGo:url"
xmlns:label="OGo:label"
className="UIxPageFrame"
title="title"
<div class="menu" id="calendarsMenu">
<ul>
- <li id="newCalendarMenuEntry"><var:string label:value="New Calendar..."/></li>
- <li id="deleteCalendarMenuEntry"><var:string label:value="Delete Calendar"/></li>
+ <li class="disabled" id="newCalendarMenuEntry"><var:string label:value="New Calendar..."/></li>
+ <li class="disabled" id="deleteCalendarMenuEntry"><var:string label:value="Delete Calendar"/></li>
<li id="accessRightsMenuEntry"><var:string label:value="Access Rights..." /></li>
<li class="separator"></li>
- <li id="exportCalendarMenuEntry"><var:string label:value="Export Calendar..."/></li>
- <li id="publishCalendarMenuEntry"><var:string label:value="Publish Calendar..."/></li>
+ <li class="disabled" id="exportCalendarMenuEntry"><var:string label:value="Export Calendar..."/></li>
+ <li class="disabled" id="publishCalendarMenuEntry"><var:string label:value="Publish Calendar..."/></li>
<li class="separator"></li>
- <li id="publishCalendarMenuEntry"><var:string label:value="Reload Remote Calendars"/></li>
+ <li class="disabled" id="publishCalendarMenuEntry"><var:string label:value="Reload Remote Calendars"/></li>
<li class="separator"></li>
- <li id="calendarPropertiesMenuEntry"><var:string label:value="Properties"/></li>
+ <li class="disabled" id="calendarPropertiesMenuEntry"><var:string label:value="Properties"/></li>
</ul>
</div>
<?xml version='1.0' standalone='yes'?>
-<!DOCTYPE var:component>
- <container
- xmlns="http://www.w3.org/1999/xhtml"
- xmlns:var="http://www.skyrix.com/od/binding"
- xmlns:const="http://www.skyrix.com/od/constant"
- xmlns:uix="OGo:uix"
- xmlns:rsrc="OGo:url"
- xmlns:label="OGo:label">
- </container>
+<!DOCTYPE container>
+<container
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:var="http://www.skyrix.com/od/binding"
+ xmlns:const="http://www.skyrix.com/od/constant"
+ xmlns:uix="OGo:uix"
+ xmlns:rsrc="OGo:url"
+ xmlns:label="OGo:label">
+</container>
+++ /dev/null
-<?xml version='1.0' standalone='yes'?>
xmlns:label="OGo:label"
className="UIxComponentEditor"
var:component="todo"
- var:toolbar="toolbar"
var:saveURL="saveURL">
<span class="checkBoxList"><var:string label:value="Start:" />
<span class="content"><input var:checked="hasStartDate"
<form id="aclForm" const:href="saveAcls">
<div class="acls">
- <input type="hidden" name="action" value="saveAcls"/>
- <input type="hidden" id="userUIDS" name="userUIDS"
- var:value="userUIDS"/>
- <label><var:string label:value="Owner:"/><br/>
- <span class="value"><strong><var:string value="ownerName"/></strong></span></label><br/>
-
+ <div id="userSelectorHeader">
+ <input type="hidden" name="action" value="saveAcls"/>
+ <input type="hidden" id="userUIDS" name="userUIDS"
+ var:value="userUIDS"/>
+ <label><var:string label:value="Owner:"/><br/>
+ <span class="value"><strong><var:string value="ownerName"/></strong></span></label><br/>
+ </div>
<div class="userSelector" id="userRoles">
- <span id="userSelectorButtons">
- <a href="#"
- class="button"><img rsrc:src="add-contact.gif"
- label:title="Add..."
- /></a>
- <a href="#"
- class="button"><img rsrc:src="remove-contact.gif"
- label:title="Remove"
- /></a>
- </span>
+ <var:if condition="currentUserIsOwner">
+ <span id="userSelectorButtons">
+ <a href="#"
+ class="button"><img rsrc:src="add-contact.gif"
+ label:title="Add..."
+ /></a>
+ <a href="#"
+ class="button"><img rsrc:src="remove-contact.gif"
+ label:title="Remove"
+ /></a>
+ </span>
+ </var:if>
<ul id="userList" multiselect="yes">
<var:foreach list="usersForObject" item="currentUser"
><li var:id="currentUser">
border-left: 1px solid #fff;
border-right: 2px solid #222;
border-bottom: 2px solid #222;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent;
+ -moz-border-bottom-colors: #000 #9c9a94 transparent;
+ -moz-border-right-colors: #000 #9c9a94 transparent;
background: #DCDAD5;
}
border-left: 2px solid #222;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
+ -moz-border-top-colors: #9c9a94 #000;
+ -moz-border-left-colors: #9c9a94 #000;
overflow: auto; }
UL#contactFolders LI.denied
border-left: 0px;
border-right: 0px;
border-bottom: 0px;
- -moz-border-top-colors: -moz-buttonhoverface;
+ -moz-border-top-colors: #efebe7;
}
DIV.contactSelection > DIV.calendar
div.innerHTML = content;
}
else
- log ("ajax fuckage 2");
+ log ("ajax fuckage 2: " + http.status);
}
var rowSelectionCount = 0;
var tagName = tagName.toUpperCase();
for (var i = 0; i < this.childNodes.length; i++) {
-// log("(" + tagName + ") childNodes " + i + " = " + this.childNodes[i]);
if (typeof(this.childNodes[i]) == "object"
&& this.childNodes[i].tagName
&& this.childNodes[i].tagName.toUpperCase() == tagName)
matchingNodes.push(this.childNodes[i]);
}
-// log ("matching: " + matchingNodes.length);
-
return matchingNodes;
}
popup.style.top = menuTop + "px;";
popup.style.left = menuLeft + "px;";
popup.style.visibility = "visible;";
-// setupMenuTarget(popup, event.target);
bodyOnClick = "" + document.body.getAttribute("onclick");
document.body.setAttribute("onclick", "onBodyClick(event);");
document.currentPopupMenu = popup;
-
-// event.cancelBubble = true;
-// event.returnValue = false;
}
HTMLElement.prototype.attachMenu = function(menuName) {
border-left: 2px solid #222;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow;
+ -moz-border-top-colors: #9c9a94 #000;
+ -moz-border-left-colors: #9c9a94 #000;
position: absolute;
color: #000;
background: #fff;
border-left: 1px solid #fff;
border-right: 2px solid #222;
border-bottom: 2px solid #222;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent;
+ -moz-border-bottom-colors: #000 #9c9a94 transparent;
+ -moz-border-right-colors: #000 #9c9a94 transparent;
background: #dcdad5;
}
win = openMessageWindow(window.messageId,
window.messageURL + "/" + action /* url */);
else {
- var messageList = $("messageList");
- var rows = messageList.getSelectedRowsId();
- var idset = "";
- for (var i = 0; i < rows.length; i++)
- win = openMessageWindow(rows[i].substr(4) /* msguid */,
- ApplicationBaseURL + currentMailbox
- + "/" + rows[i].substr(4)
- + "/" + action /* url */);
+ var messageList = $("messageList");
+ var rows = messageList.getSelectedRowsId();
+ var idset = "";
+ for (var i = 0; i < rows.length; i++)
+ win = openMessageWindow(rows[i].substr(4) /* msguid */,
+ ApplicationBaseURL + currentMailbox
+ + "/" + rows[i].substr(4)
+ + "/" + action /* url */);
}
return false;
event.preventDefault();
}
-function refreshMailbox() {
- openMailbox(currentMailbox, true);
+function _refreshWindowMailbox() {
+ openMailbox(currentMailbox, true);
+}
- return false;
+function refreshMailbox() {
+ var topWindow = getTopWindow();
+ if (topWindow)
+ topWindow._refreshWindowMailbox();
+
+ return false;
}
function openMailbox(mailbox, reload) {
/* message menu entries */
function onMenuOpenMessage(event) {
- var node = getParentMenu(event.target).menuTarget.parentNode;
- var msgId = node.getAttribute('id').substr(4);
+ return openMessageWindowsForSelection('popupview');
+}
+
+function onMenuReplyToSender(event) {
+ return openMessageWindowsForSelection('reply');
+}
+
+function onMenuReplyToAll(event) {
+ return openMessageWindowsForSelection('replyall');
+}
- return openMessageWindow(msgId,
- ApplicationBaseURL + currentMailbox
- + "/" + msgId + "/view");
+function onMenuForwardMessage(event) {
+ return openMessageWindowsForSelection('forward');
}
/* contacts */
}
},
dragGestureMouseUpHandler: function (event) {
-// log("mouseup");
document._currentMouseGestureObject._removeGestureHandlers();
},
dragGestureMouseMoveHandler: function (event) {
-// log("source mouse move (target: " + event.target + ")");
var deltaX = event.clientX - document._dragGestureStartPoint[0];
var deltaY = event.clientY - document._dragGestureStartPoint[1];
if (Math.sqrt((deltaX * deltaX) + (deltaY * deltaY)) > 10) {
-// log("event: " + event);
-// event.stopPropagation();
-// event.preventDefault();
event.returnValue = true;
event.cancelBubble = true;
var object = document._currentMouseGestureObject;
var point = document._dragGestureStartPoint;
document.DNDManager.startDragging(object, point);
document._currentMouseGestureObject._removeGestureHandlers();
-// var mouseup = document.createEvent("MouseEvent");
-// mouseup.initEvent("mouseup", true, true);
-// event.target.dispatchEvent(mouseup);
-// var dragStart = document.createEvent("MouseEvents");
-// dragStart.initMouseEvent("draggesture-hack", true, true, window,
-// event.detail, event.screenX, event.screenY,
-// event.clientX, event.clientY, event.ctrlKey,
-// event.altKey, event.shiftKey, event.metaKey,
-// event.button, null);
-// this.dispatchEvent(dragStart);
}
}
}
return destination;
},
startDragging: function (object, point) {
-// log("source gesture intercepted (source: " + object + ")");
var source = document.DNDManager._lookupSource (object);
if (source) {
-// log("source known");
document.DNDManager.currentDndOperation = new document.DNDOperation(source, point);
window.addEventListener("mouseup",
document.DNDManager.destinationDrop, false);
var operation = document.DNDManager.currentDndOperation;
var destination = document.DNDManager._lookupDestination (event.target);
if (operation && destination && destination.dndAcceptType) {
-// log("enter: " + event.target);
operation.type = null;
var i = 0;
while (operation.type == null
var operation = document.DNDManager.currentDndOperation;
if (operation
&& operation.destination == event.target) {
-// log("exit: " + event.target);
if (operation.destination.dndExit)
event.target.dndExit();
operation.setDestination(null);
}
},
destinationOver: function (event) {
-// log("over: " + event.target);
-// var operation = document.DNDManager.currentDndOperation;
-// if (operation
-// && operation.destination == event.target)
-// log("over: " + event.target);
},
destinationDrop: function (event) {
-// log ("drop...");
var operation = document.DNDManager.currentDndOperation;
if (operation) {
window.removeEventListener("mouseup",
window.removeEventListener("mouseout",
document.DNDManager.destinationExit, false);
if (operation.destination == event.target) {
-// log("drag / drop: " + operation.source + " to " + operation.destination);
if (operation.destination.dndExit) {
-// log ("destination.dndExit...");
operation.destination.dndExit();
}
if (operation.destination.dndDrop) {
-// log ("destination.dndDrop...");
var data = null;
-// log ("optype: " + operation.type);
if (operation.source.dndDataForType)
data = operation.source.dndDataForType(operation.type);
-// log ("data: " + data);
var result = operation.destination.dndDrop(data);
-// log ("result: " + result);
if (operation.ghost) {
if (result)
operation.bustGhost();
document.removeEventListener("mousemove", this.moveGhost, false);
this.ghost.bustStep = 25;
this.ghost.chaseStep = 25;
+ this.ghost.style.overflow = "hidden;"
+ this.ghost.style.whiteSpace = "nowrap;";
this.ghost.chaseDeltaX = ((this.ghost.cascadeLeftOffset() - this.startPoint[0])
/ this.ghost.chaseStep);
this.ghost.chaseDeltaY = ((this.ghost.cascadeTopOffset() - this.startPoint[1])
document.DNDOperation.prototype._fadeGhost = function() {
if (this.ghost.bustStep) {
this.ghost.style.MozOpacity = (0.1 * this.ghost.bustStep);
+ this.ghost.style.width = (this.ghost.offsetWidth * .7) + "px;";
+ this.ghost.style.height = (this.ghost.offsetHeight * .7) + "px;";
this.ghost.bustStep--;
setTimeout("document._dyingOperation._fadeGhost();", 50);
}
margin: .25em;
padding: 0px;
overflow: auto;
+ overflow-x: hidden;
+ overflow-y: auto;
border-bottom: 1px solid #fff;
border-right: 1px solid #fff;
border-top: 2px solid #222;
border-left: 2px solid #222;
background: #fff;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent;
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent;
list-style-type: none;
list-style-image: none; }
if (!keepCurrentDay)
currentDay = day;
- log (backtrace());
var month = day.substr(0, 6);
if (cachedDateSelectors[month]) {
// log ("restoring cached selector for month: " + month);
/* test */
DIV.acls
-{ padding: 1em; }
+{ position: absolute;
+ top: 4em;
+ left: 0px;
+ right: 0px;
+ bottom: 0px;
+ padding: 0px;
+ border: 0px;
+ margin: 0px; }
DIV.acls LABEL
{ white-space: nowrap;
width: 100%; }
-DIV.acls UL
-{ height: 100%;
- width: 100%; }
+DIV#userSelectorHeader
+{ margin: 1em; }
DIV#userRoles
-{ height: 8em;
- padding-bottom: 2em; }
+{ position: absolute;
+ padding: 0px;
+ margin: 0px;
+ left: 1em;
+ top: 5em;
+ right: 1em;
+ bottom: 0px; }
UL#userList
-{ cursor: default;
- margin: .25em;
+{ position: absolute;
+ top: 1.5em;
+ bottom: 0px;
+ left: 0px;
+ right: 0px;
+ width: 100%;
+ cursor: default;
padding: 0px;
white-space: nowrap;
overflow: auto;
border-top: 2px solid #222;
border-left: 2px solid #222;
background: #fff;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent;
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent;
list-style-type: none;
list-style-image: none; }
UL#userList > LI._selected
{ background: #4b6983 !important;
color: #fff !important; }
-
-SELECT#userRoleDropDown
-{ visibility: hidden;
- margin-top: 1em;
- margin-left: 2em; }
-
-SPAN.legend
-{ margin-left: 1em;
- font-size: smaller; }
border-left: 2px solid #222;
border-right: 1px solid #fff;
border-bottom: 1px solid #fff;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow; }
+ -moz-border-top-colors: #9c9a94 #000;
+ -moz-border-left-colors: #9c9a94 #000; }
TABLE#freeBusy TD,
TABLE#freeBusy TH
else
searchField.uid = null;
searchField.hasfreebusy = false;
+ var completeEmail = text[1] + " <" + text[2] + ">";
if (text[1].substring(0, searchField.value.length).toUpperCase()
== searchField.value.toUpperCase())
- searchField.value = text[1];
+ searchField.value = completeEmail;
else {
- searchField.value += ' >> ' + text[1];
+ searchField.value += ' >> ' + completeEmail;
}
- searchField.confirmedValue = text[1];
+ searchField.confirmedValue = completeEmail;
if (searchField.focussed) {
var end = searchField.value.length;
searchField.setSelectionRange(start, end);
}
}
+function UIDLookupCallback(http) {
+ if (http.readyState == 4) {
+ if (http.status == 200) {
+ var searchField = http.callbackData;
+ var start = searchField.value.length;
+ var text = http.responseText.split(":");
+ if (text[0].length > 0)
+ searchField.uid = text[0];
+ else
+ searchField.uid = null;
+ }
+ }
+}
+
function resetFreeBusyZone() {
var table = $("freeBusy");
var row = table.tHead.rows[2];
var table = $("freeBusy");
var inputs = table.getElementsByTagName("input");
for (var i = 0; i < inputs.length - 2; i++) {
- var name = inputs[i].uid;
- if (!(name && name.length > 0)) {
- name = extractEmailName(inputs[i].value);
- log ("name: " + name);
- }
+ var name = extractEmailName(inputs[i].value);
+ if (!(name && name.length > 0))
+ name = inputs[i].uid;
var email = extractEmailAddress(inputs[i].value);
var pos = attendeesEmails.indexOf(email);
if (pos == -1)
attendeesNames = parent$("attendeesNames").value.split(",");
attendeesEmails = parent$("attendeesEmails").value.split(",");
+ var baseUrl = UserFolderURL + "Contacts/contactSearch?search=";
+
var body = $("freeBusy").tBodies[0];
for (var i = 0; i < attendeesNames.length; i++) {
var tr = body.insertRow(i);
value += attendeesNames[i] + " ";
value += "<" + attendeesEmails[i] + ">";
input.value = value;
- input.setAttribute("uid", attendeesNames[i]);
input.addClassName("textField");
input.setAttribute("modified", "0");
+ triggerAjaxRequest(baseUrl + attendeesEmails[i],
+ UIDLookupCallback, input);
+ input.setAttribute("uid", attendeesNames[i]);
tr.appendChild(td)
td.appendChild(input)
}
border-right: 1px solid #fff;
border-top: 2px solid #222;
border-left: 2px solid #222;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent; }
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent; }
DIV.calendarUserRights > TABLE TR.permissions TH
{ color: #00f;
function initializePrivacyMenu() {
var privacy = $("privacy").value.toUpperCase();
- log("privacy: " + privacy);
if (privacy.length > 0) {
var privacyMenu = $("privacy-menu").childNodesWithTag("ul")[0];
var menuEntries = privacyMenu.childNodesWithTag("li");
border-bottom: 2px solid #888;
border-right: 2px solid #888;
background-color: #d4d0c8;
- -moz-border-top-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-left-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent; }
+ -moz-border-top-colors: #efebe7 #fff;
+ -moz-border-left-colors: #efebe7 #fff;
+ -moz-border-bottom-colors: #000 #9c9a94 transparent;
+ -moz-border-right-colors: #000 #9c9a94 transparent; }
DIV#buttons
{ visibility: visible;
border-right: 1px solid #fff;
border-top: 2px solid #222;
border-left: 2px solid #222;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent; }
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent; }
DIV#folders DIV
{ width: auto; }
|| nodes.length > 1) {
var parentNode = nodes[0];
var userInfos = parentNode.split(":");
- var email = userInfos[1].replace("<", "<");
+ var email = userInfos[1] + " <" + userInfos[2] + ">";
+ log ("email: " + email);
tree.add(parent, 0, email, 0, '#', userInfos[0], 'person',
'', '',
ResourcesURL + '/abcard.gif',
border-right: 1px solid #fff;
border-top: 2px solid #222;
border-left: 2px solid #222;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent; }
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent; }
DIV.calendarUserRights > TABLE TR.permissions TH
{ color: #00f;
border-right: 1px solid #fff;
border-top: 2px solid #222;
border-left: 2px solid #222;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent;
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent;
}
TEXTAREA
border-top: 2px solid #222;
border-left: 2px solid #222;
vertical-align: middle;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent;
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent;
margin: 2px;
padding-right: 1px; }
border-right: 1px solid #fff;
border-top: 2px solid #222;
border-left: 2px solid #222;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow transparent;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow transparent; }
+ -moz-border-top-colors: #9c9a94 #000 transparent;
+ -moz-border-left-colors: #9c9a94 #000 transparent; }
INPUT.textField
{ line-height: 2em;
float: left;
height: 3.8em;
vertical-align: middle;
- border-right : 1px solid ThreeDHighlight;
- border-left : 1px solid ThreeDShadow;
+ border-right : 1px solid #fff;
+ border-left : 1px solid #9c9a94;
margin: 0px .25em;
margin-top: 0.125em;
width: 0px;
width: auto;
white-space: nowrap; }
+.menu LI.disabled
+{ color: #999; }
+
.menu LI IMG
{ margin-left: -.8em;
padding-right: .2em;
.menu LI.submenu
{ background-image: url('submenu.gif'); }
+.menu LI[class~="disabled"].submenu
+{ background-image: url('submenu-disabled.gif') !important; }
+
.menu LI.submenu:hover, .menu LI.submenu-selected
{ background-image: url('submenu-active.gif') !important; }
border-left: 2px solid #fff;
border-right: 2px solid #999;
border-bottom: 2px solid #999;
- -moz-border-top-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-left-colors: ThreeDDarkShadow ThreeDShadow transparent;
+ -moz-border-top-colors: #000 #9c9a94 transparent;
+ -moz-border-left-colors: #000 #9c9a94 transparent;
font-family: monospace;
font-weight: bold;
background-color: #000;
border-left: 1px solid #fff;
border-right: 2px solid #222;
border-bottom: 2px solid #222;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent; }
+ -moz-border-bottom-colors: #000 #9c9a94 transparent;
+ -moz-border-right-colors: #000 #9c9a94 transparent; }
TD.tbtv_headercell:active
{ background-color: #DCDAD5;
border-left: 2px solid #fff;
border-bottom: 2px solid #888;
border-right: 2px solid #888;
- -moz-border-top-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-left-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent;
+ -moz-border-top-colors: #efebe7 #fff;
+ -moz-border-left-colors: #efebe7 #fff;
+ -moz-border-bottom-colors: #000 #9c9a94 transparent;
+ -moz-border-right-colors: #000 #9c9a94 transparent;
padding: 1em;
margin: 0px auto;
-moz-opacity: 1.0;
A.button:hover
{ color: inherit;
- background: -moz-buttonhoverface; }
+ background: #efebe7; }
INPUT.button:active,
A.button:active
{ color: -moz-buttonhovertext;
background-color: #c4c2bd;
- -moz-border-bottom-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-right-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-top-colors: ThreeDShadow ThreeDDarkShadow;
- -moz-border-left-colors: ThreeDShadow ThreeDDarkShadow; }
+ -moz-border-bottom-colors: #efebe7 #fff;
+ -moz-border-right-colors: #efebe7 #fff;
+ -moz-border-top-colors: #9c9a94 #000;
+ -moz-border-left-colors: #9c9a94 #000; }
INPUT.button,
A.button,
A[class~="_disabled"].button:active
{ cursor: default;
padding: 1px .5em;
+ background-color: #d4d0c8;
border-top: 2px solid #fff;
border-left: 2px solid #fff;
border-bottom: 2px solid #888;
border-right: 2px solid #888;
- -moz-border-top-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-left-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent;
+ -moz-border-top-colors: #efebe7 #fff;
+ -moz-border-left-colors: #efebe7 #fff;
+ -moz-border-bottom-colors: #000 #9c9a94 transparent;
+ -moz-border-right-colors: #000 #9c9a94 transparent;
text-decoration: none;
color: inherit; }
border-left: 2px solid #fff;
border-right: 2px solid #888;
border-bottom: 2px solid #888;
- -moz-border-top-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-left-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow transparent; }
+ -moz-border-top-colors: #efebe7 #fff;
+ -moz-border-left-colors: #efebe7 #fff;
+ -moz-border-right-colors: #000 #9c9a94 transparent;
+ -moz-border-bottom-colors: #000 #9c9a94 transparent; }
DIV.tabsContainer > UL
{ cursor: default;
border-bottom: 0px solid #fff;
border-right: 2px solid #888;
padding-bottom: 1px;
- -moz-border-top-colors: -moz-buttonhoverface ThreeDHighlight;
- -moz-border-right-colors: ThreeDDarkShadow ThreeDShadow transparent;
- -moz-border-bottom-colors: -moz-buttonhoverface ThreeDHighlight;
+ -moz-border-top-colors: #efebe7 #fff;
+ -moz-border-right-colors: #000 #9c9a94 transparent;
+ -moz-border-bottom-colors: #efebe7 #fff;
color: #000; }
DIV.tabsContainer > UL LI.first,
DIV.tabsContainer > UL LI.active
{ border-left: 2px solid #fff;
margin-left: -2px;
- -moz-border-left-colors: -moz-buttonhoverface ThreeDHighlight; }
+ -moz-border-left-colors: #efebe7 #fff; }
DIV.tabsContainer > UL LI.active
{ z-index: 5;
return usersRightsWindowWidth;
}
+function getTopWindow() {
+ var topWindow = null;
+ var currentWindow = window;
+ while (!topWindow) {
+ if (currentWindow.document.body.hasClassName("popup")
+ && currentWindow.opener)
+ currentWindow = currentWindow.opener;
+ else
+ topWindow = currentWindow;
+ }
+
+ return topWindow;
+}
+
function onTabClick(event) {
var node = event.target;