]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1052 d1b88da0-ebda-0310...
authorwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 9 May 2007 19:35:09 +0000 (19:35 +0000)
committerwolfgang <wolfgang@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 9 May 2007 19:35:09 +0000 (19:35 +0000)
99 files changed:
ChangeLog
SOPE/NGCards/versitCardsSaxDriver/ChangeLog
SOPE/NGCards/versitCardsSaxDriver/VSSaxDriver.m
Scripts/sogo [new file with mode: 0755]
Scripts/sogocron.sh [new file with mode: 0755]
Scripts/sogod-0.9 [new file with mode: 0755]
SoObjects/Appointments/GNUmakefile
SoObjects/Appointments/SOGoAppointmentFolder.m
SoObjects/Appointments/SOGoAppointmentObject.m
SoObjects/Appointments/SOGoAptMailEnglishInvitation.wo/SOGoAptMailEnglishInvitation.html
SoObjects/Appointments/SOGoCalendarComponent.h
SoObjects/Appointments/SOGoCalendarComponent.m
SoObjects/Appointments/SOGoFreeBusyObject.h
SoObjects/Appointments/SOGoFreeBusyObject.m
SoObjects/Appointments/SOGoTaskObject.m
SoObjects/Appointments/iCalEntityObject+LDAP.h [moved from SoObjects/Appointments/iCalEntityObject+Agenor.h with 100% similarity]
SoObjects/Appointments/iCalEntityObject+LDAP.m [moved from SoObjects/Appointments/iCalEntityObject+Agenor.m with 100% similarity]
SoObjects/Contacts/GNUmakefile
SoObjects/Contacts/NGLdapEntry+Contact.h [deleted file]
SoObjects/Contacts/NGLdapEntry+Contact.m [deleted file]
SoObjects/Contacts/SOGoContactFolder.h
SoObjects/Contacts/SOGoContactFolders.m
SoObjects/Contacts/SOGoContactGCSFolder.h
SoObjects/Contacts/SOGoContactGCSFolder.m
SoObjects/Contacts/SOGoContactLDAPFolder.h
SoObjects/Contacts/SOGoContactLDAPFolder.m
SoObjects/Contacts/product.plist
SoObjects/Mailer/SOGoDraftObject.m
SoObjects/Mailer/SOGoUser+Mail.m
SoObjects/SOGo/AgenorUserDefaults.m
SoObjects/SOGo/AgenorUserManager.h [deleted file]
SoObjects/SOGo/AgenorUserManager.m [deleted file]
SoObjects/SOGo/GNUmakefile
SoObjects/SOGo/LDAPSource.h [new file with mode: 0644]
SoObjects/SOGo/LDAPSource.m [new file with mode: 0644]
SoObjects/SOGo/LDAPUserManager.h [new file with mode: 0644]
SoObjects/SOGo/LDAPUserManager.m [new file with mode: 0644]
SoObjects/SOGo/SOGoAuthenticator.m
SoObjects/SOGo/SOGoFolder.h
SoObjects/SOGo/SOGoObject.h
SoObjects/SOGo/SOGoObject.m
SoObjects/SOGo/SOGoUser.h
SoObjects/SOGo/SOGoUser.m
UI/Common/Toolbars/SOGoAclOwner.toolbar
UI/Common/UIxAclEditor.m
UI/Common/UIxFolderActions.h
UI/Common/UIxFolderActions.m
UI/Common/UIxObjectActions.m
UI/Common/UIxUserRightsEditor.m
UI/Contacts/UIxContactEditor.m
UI/Contacts/UIxContactFoldersView.m
UI/Contacts/UIxContactsListViewContainer.m
UI/Contacts/product.plist
UI/GNUmakefile
UI/MailPartViewers/UIxMailPartICalViewer.m
UI/MailerUI/UIxMailEditor.m
UI/Scheduler/English.lproj/Localizable.strings
UI/Scheduler/GNUmakefile
UI/Scheduler/Toolbars/SOGoAppointmentFolder.toolbar
UI/Scheduler/UIxAppointmentEditor.m
UI/Scheduler/UIxAppointmentView.m
UI/Scheduler/UIxCalInlineAptView.m
UI/Scheduler/UIxCalView.m
UI/Scheduler/UIxCalendarSelector.m
UI/Scheduler/UIxComponent+Scheduler.h [moved from UI/Scheduler/UIxComponent+Agenor.h with 93% similarity]
UI/Scheduler/UIxComponent+Scheduler.m [moved from UI/Scheduler/UIxComponent+Agenor.m with 76% similarity]
UI/Scheduler/UIxComponentEditor.h
UI/Scheduler/UIxComponentEditor.m
UI/Scheduler/UIxTaskEditor.m
UI/Scheduler/UIxTaskView.m
UI/Templates/ContactsUI/UIxContactsListViewContainer.wox
UI/Templates/GNUmakefile
UI/Templates/MailerUI/UIxMailMainFrame.wox
UI/Templates/SchedulerUI/UIxAppointmentEditor.wox
UI/Templates/SchedulerUI/UIxCalMainView.wox
UI/Templates/SchedulerUI/UIxFreeBusyUserSelector.wox
UI/Templates/SchedulerUI/UIxFreeBusyUserSelectorTable.wox [deleted file]
UI/Templates/SchedulerUI/UIxTaskEditor.wox
UI/Templates/UIxAclEditor.wox
UI/WebServerResources/ContactsUI.css
UI/WebServerResources/ContactsUI.js
UI/WebServerResources/HTMLElement.js
UI/WebServerResources/MailerUI.css
UI/WebServerResources/MailerUI.js
UI/WebServerResources/SOGoDragAndDrop.js
UI/WebServerResources/SchedulerUI.css
UI/WebServerResources/SchedulerUI.js
UI/WebServerResources/UIxAclEditor.css
UI/WebServerResources/UIxAttendeesEditor.css
UI/WebServerResources/UIxAttendeesEditor.js
UI/WebServerResources/UIxCalUserRightsEditor.css
UI/WebServerResources/UIxComponentEditor.js
UI/WebServerResources/UIxContactEditor.css
UI/WebServerResources/UIxContactsUserFolders.css
UI/WebServerResources/UIxContactsUserFolders.js
UI/WebServerResources/UIxContactsUserRightsEditor.css
UI/WebServerResources/UIxMailEditor.css
UI/WebServerResources/generic.css
UI/WebServerResources/generic.js

index 11f9fae3af2c286c6f1648a9330fb4cba86b7895..ad7219dc27a1773fe854cf4c1201351f7f8f718d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,122 @@
+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"
index b264443602efa056cfeb99c2192ee7751cc0efbe..454e8397cdaa549f49e2e4070f4dbd406f5d2809 100644 (file)
@@ -1,3 +1,10 @@
+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)
index e59b7f0a8bed1567c732f6b97823227d2067fcf7..138df5e4a9adc047fb34b2298cf88dd9a345ac81 100644 (file)
@@ -184,9 +184,9 @@ static VSStringFormatter *stringFormatter = nil;
   commaCharSet =
     [[NSCharacterSet characterSetWithCharactersInString: @","] retain];
   colonAndSemicolonCharSet =
-    [[NSCharacterSet characterSetWithCharactersInString: @": ;"] retain];
+    [[NSCharacterSet characterSetWithCharactersInString: @":;"] retain];
   colonSemicolonAndDquoteCharSet =
-    [[NSCharacterSet characterSetWithCharactersInString: @": ;\""] retain];
+    [[NSCharacterSet characterSetWithCharactersInString: @":;\""] retain];
   whitespaceCharSet =
     [[NSCharacterSet whitespaceCharacterSet] retain];
 
diff --git a/Scripts/sogo b/Scripts/sogo
new file mode 100755 (executable)
index 0000000..5514064
--- /dev/null
@@ -0,0 +1,50 @@
+#! /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
diff --git a/Scripts/sogocron.sh b/Scripts/sogocron.sh
new file mode 100755 (executable)
index 0000000..1b1f87d
--- /dev/null
@@ -0,0 +1,36 @@
+#!/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 &
+
diff --git a/Scripts/sogod-0.9 b/Scripts/sogod-0.9
new file mode 100755 (executable)
index 0000000..c19d35a
--- /dev/null
@@ -0,0 +1,9 @@
+#!/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
+
index 57b4cb0f30ed12d1d1145c86b993367618e6ce43..c6effab6d6295ff4dd5fe64920aa42019e291d06 100644 (file)
@@ -11,7 +11,6 @@ Appointments_PRINCIPAL_CLASS = SOGoAppointmentsProduct
 Appointments_OBJC_FILES = \
        Product.m                       \
        NSArray+Appointments.m          \
-       iCalEntityObject+Agenor.m       \
        \
        SOGoCalendarComponent.m         \
        SOGoAppointmentObject.m         \
index 3ca862f15b600ae15e503f5662408c67a15235ef..f07b81bf6a59ba2006ce15cbe2e82446ca64d21b 100644 (file)
@@ -30,7 +30,7 @@
 
 // #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>
@@ -741,7 +741,7 @@ static NSNumber   *sharedYes = nil;
     privacySqlString = @"and (isopaque = 1)";
   else
     {
-      email = [activeUser email];
+      email = [activeUser primaryEmail];
       
       privacySqlString
         = [NSString stringWithFormat:
@@ -1092,7 +1092,7 @@ static NSNumber   *sharedYes = nil;
 {
   /* Note: can return NSNull objects in the array! */
   NSMutableArray    *uids;
-  AgenorUserManager *um;
+  LDAPUserManager *um;
   unsigned          i, count;
   
   if (_persons == nil)
@@ -1100,7 +1100,7 @@ static NSNumber   *sharedYes = nil;
 
   count = [_persons count];
   uids  = [NSMutableArray arrayWithCapacity:count + 1];
-  um    = [AgenorUserManager sharedUserManager];
+  um    = [LDAPUserManager sharedUserManager];
   
   for (i = 0; i < count; i++) {
     iCalPerson *person;
index ea76ffb2ba42c0c73b3d5139a889c2d7d5db94ee..691ed36edf2c743cde04d99540b2970e17856252 100644 (file)
 #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"
 
@@ -46,7 +44,7 @@
 /* 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];
         }
     }
index edb87f43a20fb59491558fa08ae4d01030439cc3..4d6bbab40ec64730ed528b8400b017355201f08f 100644 (file)
@@ -1,4 +1,4 @@
-<#IsSubject>Apt le <#AptStartDate /> at <#AptStartTime /></#IsSubject>
+<#IsSubject>Appointment on <#AptStartDate /> at <#AptStartTime /></#IsSubject>
 <#IsBody>
 You're invited by <#Organizer /> to a meeting.
 <#HasHomePageURL>
index 1f7299bc4d00480465c9810aeffcb01f4810577f..50a1cfa2a3c2d7b82d061bf11fd31b866e2197c8 100644 (file)
 @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
 
index e1a5f598689b5b4fdd99a08ac897bf39089d770b..9e8c841e6ceff9d91ddf780bc5985c9a77f36335 100644 (file)
@@ -29,7 +29,7 @@
 #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>
@@ -126,7 +126,7 @@ static BOOL sendEMailNotifications = NO;
           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]))
            {
@@ -201,9 +201,9 @@ static BOOL sendEMailNotifications = NO;
 
 - (iCalRepeatableEntityObject *) component: (BOOL) create
 {
-  return (iCalRepeatableEntityObject *)
-    [[self calendar: create]
-      firstChildWithTag: [self componentTag]];
+  return
+    (iCalRepeatableEntityObject *) [[self calendar: create]
+                                    firstChildWithTag: [self componentTag]];
 }
 
 - (BOOL) isNew
@@ -251,7 +251,7 @@ static BOOL sendEMailNotifications = NO;
       baseURL = @"http://localhost/";
       [self warnWithFormat:@"Unable to create baseURL from context!"];
     }
-  uid = [[AgenorUserManager sharedUserManager]
+  uid = [[LDAPUserManager sharedUserManager]
           getUIDForEmail: [_person rfc822Email]];
 
   return ((uid)
@@ -272,7 +272,7 @@ static BOOL sendEMailNotifications = NO;
   component = [self component: NO];
   if (component)
     {
-      myEMail = [[context activeUser] email];
+      myEMail = [[context activeUser] primaryEmail];
       p = [component findParticipantWithEmail: myEMail];
       if (p)
         {
@@ -314,9 +314,9 @@ static BOOL sendEMailNotifications = NO;
 {
   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
@@ -443,42 +443,7 @@ static BOOL sendEMailNotifications = NO;
     }
 }
 
-// - (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;
@@ -487,27 +452,83 @@ static BOOL sendEMailNotifications = NO;
   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
@@ -521,7 +542,7 @@ static BOOL sendEMailNotifications = NO;
   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])
index 6b5ea717995abbbb77fc1cfa74e0cca2029f243a..4b83b9dd8b9ea6d0c3da3f76b8f9b9b6eb828de4 100644 (file)
 
 /* 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
 
index 5edd59e4ce32ee6c9c1b2e64d426f22980ba1fed..4476c0e9d256786a921b93608f11be8e0a2f7eb6 100644 (file)
 
 #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]];
 
index 861b32c0ff8839999398039651924b5dc926b87f..cc15067f52d10ab2119914b68c31b5463f3c8955 100644 (file)
@@ -25,7 +25,7 @@
 #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>
@@ -66,7 +66,7 @@ static NSString                  *mailTemplateDefaultLanguage = nil;
 /* iCal handling */
 
 - (NSArray *)attendeeUIDsFromTask:(iCalToDo *)_task {
-  AgenorUserManager *um;
+  LDAPUserManager *um;
   NSMutableArray    *uids;
   NSArray  *attendees;
   unsigned i, count;
@@ -80,7 +80,7 @@ static NSString                  *mailTemplateDefaultLanguage = nil;
   count = [attendees count];
   uids = [NSMutableArray arrayWithCapacity:count + 1];
   
-  um = [AgenorUserManager sharedUserManager];
+  um = [LDAPUserManager sharedUserManager];
   
   /* add organizer */
   
@@ -221,7 +221,7 @@ static NSString                  *mailTemplateDefaultLanguage = nil;
      - delete in removed folders
      - send iMIP mail for all folders not found
   */
-//   AgenorUserManager *um;
+//   LDAPUserManager *um;
 //   iCalCalendar *calendar;
 //   iCalToDo *oldApt, *newApt;
 // //   iCalToDoChanges  *changes;
@@ -239,7 +239,7 @@ static NSString                  *mailTemplateDefaultLanguage = nil;
 //                     reason:@"got no iCalendar content to store!"];
 //   }
 
-//   um = [AgenorUserManager sharedUserManager];
+//   um = [LDAPUserManager sharedUserManager];
 
 //   /* handle old content */
   
index af94111fcc2b8f8808a9d60174994b4935df81f9..3c1711c11c21bda43ae6d66790c71880d97bf6a9 100644 (file)
@@ -12,10 +12,8 @@ Contacts_OBJC_FILES =                        \
        SOGoContactFolders.m            \
        SOGoContactGCSEntry.m           \
        SOGoContactGCSFolder.m          \
-       SOGoContactLDAPEntry.m          \
+       SOGoContactLDIFEntry.m          \
        SOGoContactLDAPFolder.m         \
-                                       \
-       NGLdapEntry+Contact.m           \
 
 Contacts_RESOURCE_FILES +=             \
        Version                         \
diff --git a/SoObjects/Contacts/NGLdapEntry+Contact.h b/SoObjects/Contacts/NGLdapEntry+Contact.h
deleted file mode 100644 (file)
index 0551e61..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-/* 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 */
diff --git a/SoObjects/Contacts/NGLdapEntry+Contact.m b/SoObjects/Contacts/NGLdapEntry+Contact.m
deleted file mode 100644 (file)
index 53e9fe4..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/* 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
index 28f180c61f373baa18f6d3b06fdda621b8bf67ac..904009d3aa5ac78c5b407e9fb83c1d9d519532ef 100644 (file)
                          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__ */
index d6c3f9db42500b52b13565a18523bc954081be18..bbe0c5f5988e3e93d7f800706911a6a42d78a068 100644 (file)
 #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"
@@ -71,7 +72,7 @@
   [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;
index 71113a6f803070360d55e701dd3e8252d13586ae..1dd91a53b608f2f74159468dd97db5b5e6aec09e 100644 (file)
 #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>
 {
index b050b7a43b717b33f4a16e839ecd1a30e4116fc7..42d966dc7665054e4f1988f314dcdb6fe800134a 100644 (file)
   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
index 88a89063fad354d273fc29ed900a644f414c3fe8..e6805070a9bc0b6558f3a2a09eab78c2dc221914 100644 (file)
 #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
 
index b15ed3033a7282628cc7cfbb3a024c5f17e8a118..75c198947765ad87e30cab1968d2dbbf013c0179 100644 (file)
  */
 
 #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)
index 349d27eca899976c31b1293abf34a738c83ef4e4..843eda8b9fa7e1e376f1c03b86fb66c93030df0c 100644 (file)
     };
 
     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>";
     };
   };
 }
index 8b9ad4c20beb8d98d38f4689d86ef3045cd206cb..2e913702799d47ae619354821c22f9b0c1acc8d9 100644 (file)
@@ -773,6 +773,25 @@ static NSString    *fromInternetSuffixPattern = nil;
   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;
@@ -781,7 +800,7 @@ static NSString    *fromInternetSuffixPattern = nil;
   /* 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!"];
index 2b3c6834fbab5d7ac018ac5fa4759d47f2d01dbe..00b5561ca99c9aeae6bbc8172f182872540566ee 100644 (file)
@@ -60,8 +60,8 @@
   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;
 }
index 1069645b787085f0cdc4ea9f308a658006e2dc7f..ff553d75dd32ee8cbdbd4200655fc5fdc95526c9 100644 (file)
@@ -104,7 +104,7 @@ static NSString *uidColumnName = @"uid";
 {
   GCSChannelManager *cm;
   EOAdaptorChannel *channel;
-  NSDictionary *row;
+  NSDictionary *row, *oldValues;
   NSException *ex;
   NSString *sql;
   NSArray *attrs;
@@ -122,15 +122,15 @@ static NSString *uidColumnName = @"uid";
                                         @" 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 */
@@ -142,14 +142,10 @@ static NSString *uidColumnName = @"uid";
          [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;
        }
diff --git a/SoObjects/SOGo/AgenorUserManager.h b/SoObjects/SOGo/AgenorUserManager.h
deleted file mode 100644 (file)
index 2ad6090..0000000
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
-  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_ */
diff --git a/SoObjects/SOGo/AgenorUserManager.m b/SoObjects/SOGo/AgenorUserManager.m
deleted file mode 100644 (file)
index 6b10fa3..0000000
+++ /dev/null
@@ -1,1222 +0,0 @@
-/*
-  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 */
index 15b792769c2a575f8dffe2eda61671aec63eb37b..3ad28ac9f3b0054c27e9e91728dc3124359696c7 100644 (file)
@@ -8,10 +8,10 @@ include $(GNUSTEP_MAKEFILES)/common.make
 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)
 
@@ -28,7 +28,8 @@ libSOGo_HEADER_FILES = \
        SOGoGroupFolder.h               \
        SOGoCustomGroupFolder.h         \
        \
-       AgenorUserManager.h             \
+       LDAPUserManager.h               \
+       LDAPSource.h                    \
        SOGoPermissions.h               \
        SOGoLRUCache.h                  \
        NSArray+Utilities.h             \
@@ -53,7 +54,8 @@ libSOGo_OBJC_FILES = \
        \
        SOGoPermissions.m               \
        SOGoLRUCache.m                  \
-       AgenorUserManager.m             \
+       LDAPUserManager.m               \
+       LDAPSource.m                    \
        NSObject+AptComparison.m        \
        WOContext+Agenor.m              \
        SOGoDAVRendererTypes.m          \
diff --git a/SoObjects/SOGo/LDAPSource.h b/SoObjects/SOGo/LDAPSource.h
new file mode 100644 (file)
index 0000000..2af0102
--- /dev/null
@@ -0,0 +1,71 @@
+/* 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 */
diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m
new file mode 100644 (file)
index 0000000..9b93906
--- /dev/null
@@ -0,0 +1,418 @@
+/* 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
diff --git a/SoObjects/SOGo/LDAPUserManager.h b/SoObjects/SOGo/LDAPUserManager.h
new file mode 100644 (file)
index 0000000..d7dd8fa
--- /dev/null
@@ -0,0 +1,64 @@
+/* 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 */
diff --git a/SoObjects/SOGo/LDAPUserManager.m b/SoObjects/SOGo/LDAPUserManager.m
new file mode 100644 (file)
index 0000000..6cfe52c
--- /dev/null
@@ -0,0 +1,474 @@
+/* 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
index be10f0c8c9e8e3267cccc3bc9b9582bfaa9e9bee..134dba0235f104ae0eef91ddfd45e4583481b28e 100644 (file)
 #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
 
@@ -50,9 +52,9 @@ static SOGoAuthenticator *auth = nil;
       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"];
        }
     }
 
@@ -87,11 +89,11 @@ static SOGoAuthenticator *auth = nil;
 - (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 */
@@ -105,7 +107,7 @@ static SOGoAuthenticator *auth = nil;
 
   if (!anonymous)
     anonymous
-      = [[SOGoUser alloc] initWithLogin:@"anonymous"
+      = [[SOGoUser alloc] initWithLogin: @"anonymous"
                          roles: [NSArray arrayWithObject: SoRole_Anonymous]];
   if (!freebusy)
     freebusy
@@ -124,9 +126,8 @@ static SOGoAuthenticator *auth = nil;
             user = anonymous;
         }
       else
-        user = [[[SOGoUser alloc] initWithLogin: login
-                                  roles: [self rolesForLogin: login]]
-                 autorelease];
+        user = [SOGoUser userWithLogin: login
+                        roles: [self rolesForLogin: login]];
     }
   else
     user = nil;
index f38fc61f758c213fe7e2f77e6702bcab3216ebd8..b5527d4988c6d468cf6e21f261dd2a2f518a4dcb 100644 (file)
 
 #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;
index 9d3f7a4feebc95793ab870396c97e51870b47f5c..5b4eeccec2d98ca23e412ed19208e334bdc9b996 100644 (file)
   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)
index fff695fc1a43ff62d65a2097eab19a1ab2ef00f1..1cfc050eb7365a6598014e956d9b61a2107b9a40 100644 (file)
@@ -39,7 +39,6 @@
 #import "SOGoUserFolder.h"
 
 #import "SOGoDAVRendererTypes.h"
-#import "AgenorUserManager.h"
 
 #import "SOGoObject.h"
 
index 3b87aa849d2f76fef1cce50261e810ba2a300f1e..6b52688a152c0bb9b951ab4e51acba9aa0bd3ab9 100644 (file)
 
 @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 */
 
@@ -79,7 +86,7 @@
 /* folders */
 
 - (id) homeFolderInContext: (id) _ctx;
-- (id) schedulingCalendarInContext: (id) _ctx;
+// - (id) schedulingCalendarInContext: (id) _ctx;
 
 - (NSArray *) rolesForObject: (NSObject *) object
                    inContext: (WOContext *) context;
index e6c5a498e1c77e4f4f444ba2f0aaefd90a7a742d..c91e7573c7ceec545fb1119e6ae0b23cd675cae8 100644 (file)
 #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)
 
@@ -45,20 +48,29 @@ static NSTimeZone *serverTimeZone = nil;
 + (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;
 
@@ -74,6 +86,27 @@ static NSTimeZone *serverTimeZone = nil;
     {
       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;
@@ -83,73 +116,115 @@ static NSTimeZone *serverTimeZone = nil;
 {
   [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 */
@@ -157,10 +232,9 @@ static NSTimeZone *serverTimeZone = nil;
 - (NSUserDefaults *) userDefaults
 {
   if (!userDefaults)
-    {
-      userDefaults = [[self userManager] getUserDefaultsForUID: [self login]];
-      [userDefaults retain];
-    }
+    userDefaults = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
+                                              uid: login
+                                              fieldName: @"defaults"];
 
   return userDefaults;
 }
@@ -168,10 +242,9 @@ static NSTimeZone *serverTimeZone = nil;
 - (NSUserDefaults *) userSettings
 {
   if (!userSettings)
-    {
-      userSettings = [[self userManager] getUserSettingsForUID: [self login]];
-      [userSettings retain];
-    }
+    userSettings = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
+                                              uid: login
+                                              fieldName: @"settings"];
 
   return userSettings;
 }
@@ -223,27 +296,27 @@ static NSTimeZone *serverTimeZone = nil;
   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
index e2d8f839e585e856236539857da4ca23bad68cd3..6af766a40a6843cf9f50b228a5a22bd35fc73dbb 100644 (file)
@@ -1,10 +1,5 @@
 ( /* 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();";
index 8c0e9df990fbbda3325e893de19294deeade8ca9..12a45f5031d0da07233b7eb9c5840de52339a9b1 100644 (file)
@@ -26,7 +26,7 @@
 #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;
index 5a08a684b230d8614b4cafd12c9ecc9df938e8ca..88126ad384b6387c599cea9d6ffe475d51dafe74 100644 (file)
 
 #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;
index 4f5ff9e6b62e28553e2af1bab2f6fb6dd03baa6e..25480d1b11ac8508cf9e29ad9ab1ffc3c41d1628 100644 (file)
 #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];
 
@@ -59,8 +61,8 @@
   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];
index 143f677fe14a3f0e79a79745285623cf2d245e20..277d1ac66a0f2f392dc024936ca5424829e31c44 100644 (file)
@@ -25,7 +25,7 @@
 #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"
@@ -38,7 +38,7 @@
   WORequest *request;
   NSString *uid, *email;
   unsigned int code;
-  AgenorUserManager *um;
+  LDAPUserManager *um;
   SOGoObject *clientObject;
 
   code = 403;
@@ -46,7 +46,7 @@
   uid = [request formValueForKey: @"uid"];
   if ([uid length] > 0)
     {
-      um = [AgenorUserManager sharedUserManager];
+      um = [LDAPUserManager sharedUserManager];
       email = [um getEmailForUID: uid];
       if ([email length] > 0)
         {
index d3792a23298cb0cdd41a5f3399885e8c76cb4272..35b697612dafb288a1520c3ac26c002bcff4ef67 100644 (file)
@@ -23,7 +23,7 @@
 #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"
 
@@ -54,9 +54,9 @@
 
 - (NSString *) userDisplayName
 {
-  AgenorUserManager *um;
+  LDAPUserManager *um;
   
-  um = [AgenorUserManager sharedUserManager];
+  um = [LDAPUserManager sharedUserManager];
 
   return [NSString stringWithFormat: @"%@ <%@>",
                   [um getCNForUID: uid],
@@ -67,7 +67,7 @@
 {
   BOOL response;
   NSString *newUID, *email;
-  AgenorUserManager *um;
+  LDAPUserManager *um;
   SOGoObject *clientObject;
 
   response = NO;
@@ -75,7 +75,7 @@
   newUID = [[context request] formValueForKey: @"uid"];
   if ([newUID length] > 0)
     {
-      um = [AgenorUserManager sharedUserManager];
+      um = [LDAPUserManager sharedUserManager];
       email = [um getEmailForUID: newUID];
       if ([email length] > 0)
        {
index 0b6dd7b7420601d050e977d5957d705451a84ca9..67d2d6b22487e7c1050183081332130cf08c5df4 100644 (file)
   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";
 
index 45e98dd1f201672d131907ac1a9f81a97f61cb94..de17b892a0b67df739159e0f03cb1ede0e02346b 100644 (file)
@@ -30,6 +30,7 @@
 #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
index 34fa3a32c691d29cf51ce6f82d84ec0dd259e133..2bf4f0c0999ee4fa909a49846e0fe3874344f245 100644 (file)
@@ -27,7 +27,6 @@
 #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];
index b1c4794824791607f46e17fd26a4106e70b88383..48d2d3c27e52544e365d47c73497cb0ca955dc1c 100644 (file)
@@ -28,7 +28,7 @@
               actionName  = "selectForMailer";
            };
            contactSearch = {
-              protectedBy = "View";
+              protectedBy = "<public>";
               pageName    = "UIxContactFoldersView";
               actionName  = "contactSearch";
            };
@@ -63,6 +63,8 @@
         };
      };
 
+/* 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 = {
index 4be5b3bde35786bbcef27209488592f951894f89..89d5e12bee652fef33ece900fc7d9150bc82fee0 100644 (file)
@@ -11,8 +11,6 @@ SUBPROJECTS += \
        Contacts        \
        MailerUI        \
        MailPartViewers \
-
-SUBPROJECTS += \
        Templates
 
 include $(GNUSTEP_MAKEFILES)/aggregate.make
index 5a3285e101c14244ea0024c70aa33cd817bb3cb1..494d21d427df57f044abbaa4cbefa011f566e633 100644 (file)
@@ -26,7 +26,7 @@
 */
 
 #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 {
index 64ea6cfd8a64b94f87113f4f44843a93271fd97f..cb4954e47b8a01378906a005d32c4187f0bf2b7d 100644 (file)
   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>
 
 /*
@@ -37,7 +59,7 @@
   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;
@@ -97,29 +108,29 @@ static NSArray      *infoKeys            = nil;
 }
 
 - (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 {
@@ -130,38 +141,38 @@ static NSArray      *infoKeys            = nil;
 }
 
 - (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 {
@@ -172,40 +183,41 @@ static NSArray      *infoKeys            = nil;
 }
 
 - (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 */
@@ -262,15 +274,15 @@ static NSArray      *infoKeys            = nil;
   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 {
@@ -284,7 +296,7 @@ static NSArray      *infoKeys            = nil;
   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"];
@@ -341,8 +353,8 @@ static NSArray      *infoKeys            = nil;
   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;
@@ -365,7 +377,7 @@ static NSArray      *infoKeys            = nil;
   
   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;
@@ -377,9 +389,9 @@ static NSArray      *infoKeys            = 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 {
@@ -433,13 +445,13 @@ static NSArray      *infoKeys            = nil;
 - (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;
index 68edabe864ffc4e658a83dd77b51a311c54ad1e9..62d233bf5c453b50bf2e93b92ffca1e47f672dcf 100644 (file)
@@ -391,7 +391,7 @@ validate_endbeforestart    = "Enddate is before startdate!";
 "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";
index 4250113d2c59b15fa2f29636483c7a0e74a565a6..66c045d8ef1ae6f69f26f5451afc88c0a6352c30 100644 (file)
@@ -18,7 +18,7 @@ SchedulerUI_OBJC_FILES =              \
        UIxCalDateSelector.m            \
        UIxCalUserRightsEditor.m        \
                                        \
-       UIxComponent+Agenor.m           \
+       UIxComponent+Scheduler.m        \
        UIxCalView.m                    \
        UIxCalAptListView.m             \
        UIxCalTasksListView.m           \
index 64353fe2018ac3c7ec97c2b206097fda49d6baab..296c30696a7de886d5d13ea7dce179811740c63f 100644 (file)
       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();";
index 3f1fa9b0718ed522d7410808ea1b2d783f9dfb93..3c4d20e9fb41dc0d95546b530b8fa6b53eb14cc0 100644 (file)
@@ -28,7 +28,6 @@
 #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
 {
index 8adb3a9b59ccb624c8cbd4bd22b996c630ff7974..4814f7140991a1d85984c011ac0bc9da6763794b 100644 (file)
 #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)
@@ -62,7 +63,7 @@
 - (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];
 }
index a0bc0d8226cbe82fae0538db3dcbfaae26ecaabf..9fd641ac3d7722d2c1fd6d52b4327d1025b46191 100644 (file)
   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])
     {
index 037a99f4a07ee1b0866065884ced445cb658b722..96ecf6f89d4af3100a63cab9f8f0a36aa7e73b09 100644 (file)
@@ -9,7 +9,7 @@
 #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>
@@ -113,7 +113,7 @@ static BOOL shouldDisplayWeekend = NO;
   {
     count = [_apts count];
     filtered = [[[NSMutableArray alloc] initWithCapacity: count] autorelease];
-    email = [self emailForUser];
+    email = [[context activeUser] primaryEmail];
 
     for (i = 0; i < count; i++)
       {
index 5903aecbf05d661e202e1545f1a94292a7e6dd88..7205bfec7fc58133807f284d3e11d46bfdaa194b 100644 (file)
@@ -28,7 +28,6 @@
 #import <NGExtensions/NGExtensions.h>
 #import <NGCards/iCalPerson.h>
 
-#import <SOGo/AgenorUserManager.h>
 #import <SOGo/SOGoUser.h>
 #import <SOGoUI/UIxComponent.h>
 #import <Appointments/SOGoAppointmentFolder.h>
similarity index 93%
rename from UI/Scheduler/UIxComponent+Agenor.h
rename to UI/Scheduler/UIxComponent+Scheduler.h
index 7db79e75ed5ffbec9e11dc4a17aff7c190491d29..aa11ea4d4110f356617709b5cd75ff8680a30d4a 100644 (file)
 
 - (NSArray *) getICalPersonsFromValue: (NSString *) selectorValue;
 
-/* email, cn */
-- (NSString *) emailForUser;
-- (NSString *) cnForUser;
-
 @end
 
 #endif /* __UIxComponent_Agenor_H_ */
similarity index 76%
rename from UI/Scheduler/UIxComponent+Agenor.m
rename to UI/Scheduler/UIxComponent+Scheduler.m
index 20aa370d02cde043bbaf18d4b24693085f27141e..46b92548c1358c16069cadd996fd0bb66024d193 100644 (file)
   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)
 
@@ -32,9 +34,9 @@
   NSMutableArray *persons;
   NSEnumerator *uids;
   NSString *uid;
-  AgenorUserManager *um;
+  SOGoCalendarComponent *component;
 
-  um = [AgenorUserManager sharedUserManager];
+  component = [self clientObject];
 
   persons = [NSMutableArray new];
   [persons autorelease];
@@ -46,7 +48,7 @@
       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) */
index 72bf704bac1d36a72ad6cc121058d13560ee09d5..087fc1f0f0b6119e637c7f3da9b2173b296d1823 100644 (file)
@@ -62,6 +62,7 @@
   NSString *attendeesEmails;
 }
 
+- (NSString *) toolbar;
 - (void) setComponent: (iCalRepeatableEntityObject *) newComponent;
 
 - (void) setSaveURL: (NSString *) newSaveURL;
index 9684e36b934d03f0a48fa56630a7b524716b3a71..910fc8dc60c1e9cd33798d7f74738c8aa40aeb6d 100644 (file)
@@ -40,7 +40,6 @@
 #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>
@@ -48,7 +47,7 @@
 #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
index 360cdf0196e99679604ed0aec03338798c63af49..607e0adf9117cb842f667add377ba150bac6749c 100644 (file)
@@ -28,7 +28,6 @@
 #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
 {
index 323034134b2841b476f773b5e36d6344ff9646ff..0af814079f4662cc437da457d21f804949d65d24 100644 (file)
 #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)
@@ -62,7 +63,7 @@
 - (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 {
index 45d90f3b5d388f73bcbe4a3986c43335679deafa..f53445b0df691f21bb0fbf334ca8a18f67868e50 100644 (file)
        <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>
 
@@ -28,7 +28,7 @@
        <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>
index 8b9813f662ae08eef1bbc8d6362fe9500dc98094..7a5acdd67a44d37aa3687861258f4de1d2d63938 100644 (file)
@@ -1,11 +1,22 @@
 # 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 ::
 
index 80925409b3cfccb6c6460a3c7e5b5c7e2bc6d283..1e7be00aebe69aa657376946ee48bffa011d311e 100644 (file)
@@ -9,66 +9,66 @@
     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"
@@ -79,7 +79,7 @@
     </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>
 
index 82a06b3076bfa0599a7f1a973195339aa83c2bf0..d918e7bd6b1d9f0cb0d2663c3228adcde1c26d50 100644 (file)
@@ -9,7 +9,6 @@
   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"
index a0c4675b826aacbf04ee9e3eb4e300baab646468..62d0d9c2554ed9d2d02d8c956ab6c45fd84ca422 100644 (file)
@@ -3,6 +3,7 @@
     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>
 
index a21b1d09bfa840f6f5191215b534f7adc7bf3251..cff7611f6a9430e26050a91a93303f3053943b74 100644 (file)
@@ -1,10 +1,10 @@
 <?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>
diff --git a/UI/Templates/SchedulerUI/UIxFreeBusyUserSelectorTable.wox b/UI/Templates/SchedulerUI/UIxFreeBusyUserSelectorTable.wox
deleted file mode 100644 (file)
index f384611..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<?xml version='1.0' standalone='yes'?>
index cd71c8cc97115f76a08c0a033320802dcd599ce6..a7a506ff254cff23cb2c316b13abfa5c266edfd4 100644 (file)
@@ -9,7 +9,6 @@
   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"
index 842726b06977d2b83213ddc8ea3c92a007e466dc..20d933583e9c2a13c6578a68205ae12376306338 100644 (file)
 
   <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">
index 2b98dc0779213dc08757d99623072f69ec451a59..e9e3ff35d88b87be7f970924c3646736c2fa9f86 100644 (file)
@@ -95,8 +95,8 @@ table.titletable td.titlecell SELECT
   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;
 }
 
@@ -141,8 +141,8 @@ UL#contactFolders
   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
@@ -324,7 +324,7 @@ DIV.contactSelection
   border-left: 0px;
   border-right: 0px;
   border-bottom: 0px;
-  -moz-border-top-colors: -moz-buttonhoverface;
+  -moz-border-top-colors: #efebe7;
 }
 
 DIV.contactSelection > DIV.calendar
index 99d1d0fe0b98c668f8563ea20c5f7c28c5cee514..5e4c664ececd0d69fec3743b47c38c8aefcd5803 100644 (file)
@@ -186,7 +186,7 @@ function contactLoadCallback(http) {
     div.innerHTML = content;
   }
   else
-    log ("ajax fuckage 2");
+    log ("ajax fuckage 2: " + http.status);
 }
 
 var rowSelectionCount = 0;
index 9b18e927544959bd131723ccd74cc2acd4bdcdb9..b59666eddc4949b51039929a50d20ead16e28b04 100644 (file)
@@ -10,15 +10,12 @@ HTMLElement.prototype.childNodesWithTag = function(tagName) {
   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;
 }
 
@@ -163,14 +160,10 @@ HTMLElement.prototype.onContextMenu = function(event) {
   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) {
index d8671249b9334626c7c9e071e8095eff8427c650..777636278773802ac7e6ddae8a4c9257d409fbfb 100644 (file)
@@ -78,8 +78,8 @@ DIV#folderTreeContent
   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;
@@ -188,8 +188,8 @@ table.titletable td.titlecell SELECT
   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;
 }
 
index 4c28bcea7afce86d00840397ee401267f731d69d..214be585c6b5e7fcda36a9052aab7c7fea83cd18 100644 (file)
@@ -193,14 +193,14 @@ function openMessageWindowsForSelection(action) {
     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;
@@ -376,10 +376,16 @@ function onMailboxTreeItemClick(event) {
   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) {
@@ -699,12 +705,19 @@ function deleteSelectedMails() {
 
 /* 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 */
index be68c9cb26f447cd7af91abef0c280dd78061cda..83adb8d3d2354dfecf9abeed90ee143b79dfc7d8 100644 (file)
@@ -23,33 +23,18 @@ var SOGODragAndDropSourceInterface = {
     }
   },
   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);
     }
   }
 }
@@ -94,10 +79,8 @@ document.DNDManager = {
     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);
@@ -113,7 +96,6 @@ document.DNDManager = {
     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
@@ -133,21 +115,14 @@ document.DNDManager = {
     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",
@@ -159,20 +134,14 @@ document.DNDManager = {
       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();
@@ -244,6 +213,8 @@ document.DNDOperation.prototype.chaseGhost = function() {
   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])
@@ -270,6 +241,8 @@ document.DNDOperation.prototype._chaseGhost = function() {
 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);
   }
index e11c28c7255ee4baac8f0e7f89b505b9b9392d5b..f5478271d97a1f385e0bc9b10cb195a4923fd2d2 100644 (file)
@@ -59,13 +59,15 @@ UL#tasksList, UL#calendarList
   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; }
 
index ffc2880b58546cb829904cad4b70c928742f3052..718df0f35153918e006a7a6465bc48a891768dbe 100644 (file)
@@ -371,7 +371,6 @@ function changeDateSelectorDisplay(day, keepCurrentDay) {
     if (!keepCurrentDay)
       currentDay = day;
 
-    log (backtrace());
     var month = day.substr(0, 6);
     if (cachedDateSelectors[month]) {
 //       log ("restoring cached selector for month: " + month);
index 9ed9f66c10b5373cd37e6ce0af0021fade576e12..c2f375a2a91883568ce7e76d0dc7ed54319ccc07 100644 (file)
@@ -1,23 +1,39 @@
 /* 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;
@@ -26,20 +42,11 @@ UL#userList
   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; }
index 865d314dd32ec0d67497e689c675278b88b6d462..6cc9a82a915a3d42e8ee68ce91131dbc1cd3b601 100644 (file)
@@ -17,8 +17,8 @@ DIV#freeBusyView
   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
index b7d97956658684b72d381bec56dde15d4e2c22e9..60f415943e1493c85cf3e74a43e02ccd81cb5bfb 100644 (file)
@@ -71,13 +71,14 @@ function updateResults(http) {
       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);
@@ -90,6 +91,20 @@ function updateResults(http) {
   }
 }
 
+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];
@@ -323,11 +338,9 @@ function onEditorOkClick(event) {
    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)
@@ -481,6 +494,8 @@ function prepareAttendees() {
       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);
@@ -492,9 +507,11 @@ function prepareAttendees() {
            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)
       }
index 783e47a643faf6ac9bb49eeabf193d7e32ca44e3..eaea5734bcfe88badbed627b021b8ec84a20a158 100644 (file)
@@ -24,8 +24,8 @@ DIV.calendarUserRights > TABLE
   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;
index 632d1f865cfd9a6b25fcce9c4fcd3aeb6f166d22..fb8725e03e855a5970010ee117128811a042910b 100644 (file)
@@ -127,7 +127,6 @@ function initializeDocumentHref() {
 
 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");
index ef23927ac85f65c1c11f669c0e5c79e5f6afb5e4..d0205082fbd5edc9ee4a7f428e1c920a37857fe5 100644 (file)
@@ -37,10 +37,10 @@ SPAN.caption
   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;
index b502613e1fd415402a8f96126adf4b702055c1f5..aeb110cfe11b9c793da58e04e6ef19bd8f4aaccb 100644 (file)
@@ -26,8 +26,8 @@ DIV#folders
   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; }
index 06906f520fe1a4fab3222a1853bb3ce7c01e4026..d5b527a16a5dbabd0f0b6d426c414c9117df27f5 100644 (file)
@@ -22,7 +22,8 @@ function addLineToTree(tree, parent, line) {
        || nodes.length > 1) {
       var parentNode = nodes[0];
       var userInfos = parentNode.split(":");
-      var email = userInfos[1].replace("<", "&lt;");
+      var email = userInfos[1] + " &lt;" + userInfos[2] + ">";
+      log ("email: " + email);
       tree.add(parent, 0, email, 0, '#', userInfos[0], 'person',
               '', '',
               ResourcesURL + '/abcard.gif',
index 783e47a643faf6ac9bb49eeabf193d7e32ca44e3..eaea5734bcfe88badbed627b021b8ec84a20a158 100644 (file)
@@ -24,8 +24,8 @@ DIV.calendarUserRights > TABLE
   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;
index b7863482bee55bf66de5c8e36a89685e1bf61ae4..5bfb95e27679fda1415cacd8ca9b73e5e9c76a70 100644 (file)
@@ -81,8 +81,8 @@ div#compose_attachments_list
   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
index 1af01b02e582161ecd464322a16001e2beab22e5..1ee7ce91fb628253ac37350a18c7b2b87b5bc619 100644 (file)
@@ -172,8 +172,8 @@ SELECT
   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; }
 
@@ -201,8 +201,8 @@ TEXTAREA, INPUT.textField
   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;
@@ -226,8 +226,8 @@ SPAN.toolbarSeparator
   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;
@@ -316,6 +316,9 @@ SPAN.toolbarButton:active
   width: auto;
   white-space: nowrap; }
 
+.menu LI.disabled
+{ color: #999; }
+
 .menu LI IMG
 { margin-left: -.8em;
   padding-right: .2em;
@@ -340,6 +343,9 @@ SPAN.toolbarButton:active
 .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; }
 
@@ -353,8 +359,8 @@ DIV#logConsole
   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;
@@ -384,8 +390,8 @@ TD.tbtv_navcell
   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;
@@ -491,10 +497,10 @@ DIV.javascriptMessagePseudoWindow
   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;
@@ -512,16 +518,16 @@ DIV.noJavascriptErrorMessage A
 
 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,
@@ -529,14 +535,15 @@ A[class~="_disabled"].button:hover,
 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; }
 
@@ -580,10 +587,10 @@ DIV.tabsContainer
   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;
@@ -604,16 +611,16 @@ DIV.tabsContainer > UL LI
   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;
index 976cad5051901a462bd33e5a2d70ba273b2a7b70..8efe056e9d0cfefbd17b11885eda6e6d26b5a12e 100644 (file)
@@ -956,6 +956,20 @@ function getUsersRightsWindowWidth() {
    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;