diff --git a/ChangeLog b/ChangeLog index 2c24f33a3..ce65914ed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,49 @@ +2009-11-28 Wolfgang Sourdeau + + * UI/PreferencesUI/UIxPreferences.m (-): "hours" is now a static + variable, rather than an ivar. + + * UI/MainUI/SOGoRootPage.m (+initialized): the supportedLanguages + are not available from the SOGoSystemDefaults + (SOGoDefaults.plist). + + * UI/MailerUI/UIxMailView.m (+initialize): we never used + "SOGoDontUseETagsForMailViewer". + + * UI/MailerUI/UIxMailEditor.m (+initialize): we never used + "SOGoShowInternetMarker" and "SOGoInternetMailHeaders". + + * SoObjects/Mailer/SOGoDraftObject.m (+initialize): + "TextPlainType" was never used. + + * SoObjects/SOGo/SOGoSystemDefaults.m: new class module handling + the getting of system (or "application") defaults, as well as + default values for users and domains. + + * SoObjects/SOGo/SOGoDomainDefaults.m: new class module handling + the getting of domain defaults, as well as default values for for + users belonging to the corresponding domain. + + * SoObjects/SOGo/SOGoUserDefaults.m: new class module handling + the setting and getting of user defaults. + + * SoObjects/SOGo/SOGoLDAPDefaults.h: new protocol module for the + handling of "recursive" ldap defaults. + + * SoObjects/SOGo/SOGoDefaultsSource.m: new module class acting as + a proxy between NSDictionary, NSUserDefaults and SOGoUserProfile, + enabling the possibility of hierarchy and fallbacks. + + * SoObjects/SOGo/SOGoUserProfile.m: new name for SOGoUserDefaults. + (-arrayForKey:, -stringForKey:, -dataForKey:, -boolForKey:) + (-floatForKey:): removed obsolete methods (as well as their setter + counterparts). + + * SoObjects/SOGo/SOGoSQLUserProfile.m: new class module for + handling the SQL backend of the SOGoUserProfile. + + * UI/SOGoUI/WOContext+UIx.m: removed obsolete class. + 2009-11-27 Wolfgang Sourdeau * SoObjects/SOGo/SOGoUserDefaults.m (-fetchJSONProfileFromDB): the diff --git a/Main/SOGo.m b/Main/SOGo.m index 99a62671e..15aa057a4 100644 --- a/Main/SOGo.m +++ b/Main/SOGo.m @@ -27,7 +27,6 @@ #import #import #import -#import #import #import @@ -45,71 +44,61 @@ #import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "build.h" #import "SOGoProductLoader.h" #import "NSException+Stacktrace.h" #import "SOGo.h" -#import "SOGoStartupLogger.h" @implementation SOGo -static unsigned int vMemSizeLimit = 0; -static BOOL doCrashOnSessionCreate = NO; -static BOOL hasCheckedTables = NO; -static BOOL debugRequests = NO; -static BOOL useRelativeURLs = NO; - +static unsigned int vMemSizeLimit; +static BOOL doCrashOnSessionCreate; +static BOOL hasCheckedTables; +static BOOL debugRequests; +static BOOL useRelativeURLs; static BOOL trustProxyAuthentication; #ifdef GNUSTEP_BASE_LIBRARY -static BOOL debugLeaks = NO; +static BOOL debugLeaks; #endif + (void) initialize { - NSUserDefaults *ud; + SOGoSystemDefaults *defaults; SoClassSecurityInfo *sInfo; NSArray *basicRoles; SOGoStartupLogger *logger; - id tmp; logger = [SOGoStartupLogger sharedLogger]; [logger logWithFormat: @"starting SOGo (build %@)", SOGoBuildDate]; - ud = [NSUserDefaults standardUserDefaults]; - if ([[ud persistentDomainForName: @"sogod"] count] == 0) - [logger warnWithFormat: @"No configuration found." - @" SOGo will not work properly."]; - - doCrashOnSessionCreate = [ud boolForKey:@"SOGoCrashOnSessionCreate"]; - debugRequests = [ud boolForKey: @"SOGoDebugRequests"]; + defaults = [SOGoSystemDefaults sharedSystemDefaults]; + doCrashOnSessionCreate = [defaults crashOnSessionCreate]; + debugRequests = [defaults debugRequests]; #ifdef GNUSTEP_BASE_LIBRARY - debugLeaks = [ud boolForKey: @"SOGoDebugLeaks"]; + debugLeaks = [defaults debugLeaks]; if (debugLeaks) [logger logWithFormat: @"activating leak debugging"]; #endif /* vMem size check - default is 384MB */ - tmp = [ud objectForKey: @"SxVMemLimit"]; - vMemSizeLimit = ((tmp != nil) ? [tmp intValue] : 384); + vMemSizeLimit = [defaults vmemLimit]; if (vMemSizeLimit > 0) [logger logWithFormat: @"vmem size check enabled: shutting down app when " - @"vmem > %d MB", vMemSizeLimit]; -#if LIB_FOUNDATION_LIBRARY - if ([ud boolForKey:@"SOGoEnableDoubleReleaseCheck"]) - [NSAutoreleasePool enableDoubleReleaseCheck: YES]; -#endif - + @"vmem > %d MB", vMemSizeLimit]; + /* SoClass security declarations */ sInfo = [self soClassSecurityInfo]; /* require View permission to access the root (bound to authenticated ...) */ @@ -125,8 +114,8 @@ static BOOL debugLeaks = NO; [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View]; [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess]; - trustProxyAuthentication = [ud boolForKey: @"SOGoTrustProxyAuthentication"]; - useRelativeURLs = [ud boolForKey: @"WOUseRelativeURLs"]; + trustProxyAuthentication = [defaults trustProxyAuthentication]; + useRelativeURLs = [defaults useRelativeURLs]; } - (id) init @@ -222,30 +211,17 @@ static BOOL debugLeaks = NO; NSString *urlStrings[] = {@"SOGoProfileURL", @"OCSFolderInfoURL", nil}; NSString **urlString; NSString *value; - NSUserDefaults *ud; + SOGoSystemDefaults *defaults; BOOL ok; - ud = [NSUserDefaults standardUserDefaults]; + defaults = [SOGoSystemDefaults sharedSystemDefaults]; ok = YES; cm = [GCSChannelManager defaultChannelManager]; urlString = urlStrings; while (ok && *urlString) { - value = [ud stringForKey: *urlString]; - if (!value & [*urlString isEqualToString: @"SOGoProfileURL"]) - { - value = [ud stringForKey: @"AgenorProfileURL"]; - if (value) - { - [ud setObject: value forKey: *urlString]; - [ud removeObjectForKey: @"AgenorProfileURL"]; - [ud synchronize]; - [self warnWithFormat: @"the user defaults key 'AgenorProfileURL'" - @" was renamed to 'SOGoProfileURL'"]; - } - } - + value = [defaults stringForKey: *urlString]; if (value) { [self _checkTableWithCM: cm tableURL: value andType: *urlString]; @@ -309,9 +285,8 @@ static BOOL debugLeaks = NO; user = [SOGoUser userWithLogin: _key roles: nil]; if (user) - userFolder = [$(@"SOGoUserFolder") - objectWithName: _key - inContainer: self]; + userFolder = [$(@"SOGoUserFolder") objectWithName: _key + inContainer: self]; else userFolder = nil; diff --git a/Main/sogod.m b/Main/sogod.m index 6b02d95ff..047a64623 100644 --- a/Main/sogod.m +++ b/Main/sogod.m @@ -1,5 +1,6 @@ /* Copyright (C) 2004-2005 SKYRIX Software AG + Copyright (C) 2006-2009 Inverse inc. This file is part of OpenGroupware.org. @@ -19,111 +20,38 @@ 02111-1307, USA. */ -#import -#import +#include +#include #import #import #import -#import #import -#if defined(LDAP_CONFIG) -#import -#endif -#import "SOGoStartupLogger.h" - -typedef void (*NSUserDefaultsInitFunction) (); - -#define DIR_SEP "/" - -static void -BootstrapNSUserDefaults () -{ - char *filename; - NSUserDefaultsInitFunction SOGoNSUserDefaultsBootstrap; - void *handle; - - filename = SOGO_LIBDIR DIR_SEP "libSOGoNSUserDefaults.so.1"; - handle = dlopen (filename, RTLD_NOW | RTLD_GLOBAL); - if (handle) - { - SOGoNSUserDefaultsBootstrap = dlsym (handle, - "SOGoNSUserDefaultsBootstrap"); - if (SOGoNSUserDefaultsBootstrap) - SOGoNSUserDefaultsBootstrap (); - } -} - -static void -prepareUserDefaults (NSUserDefaults *ud) -{ - NSString *redirectURL; - NSDictionary *domain; - SOGoStartupLogger *logger; - - logger = [SOGoStartupLogger sharedLogger]; - - domain = [ud persistentDomainForName: @"sogod"]; - if (![domain count]) - { - domain = [ud persistentDomainForName: @"sogod-0.9"]; - if ([domain count]) - { - [logger logWithFormat: @"migrating user defaults from sogod-0.9"]; - [ud setPersistentDomain: domain forName: @"sogod"]; - [ud removePersistentDomainForName: @"sogod-0.9"]; - [ud synchronize]; - } - } - - redirectURL = [ud stringForKey: @"WOApplicationRedirectURL"]; - if (redirectURL) - { - [logger warnWithFormat: - @"Using obsolete 'WOApplicationRedirectURL' user default."]; - [logger warnWithFormat: - @" Please configure the use of the x-webobjects-XXX headers" - @" with your webserver (see sample files)."]; - if ([redirectURL hasSuffix: @"/"]) - [ud setObject: [redirectURL substringToIndex: [redirectURL length] - 1] - forKey: @"WOApplicationRedirectURL"]; - } - [ud setBool: YES forKey: @"WOMessageUseUTF8"]; - [ud setBool: YES forKey: @"WOParsersUseUTF8"]; - [ud setBool: YES forKey: @"NGUseUTF8AsURLEncoding"]; -} +#import int main (int argc, char **argv, char **env) { - NSString *tzName; - NSUserDefaults *ud; NSAutoreleasePool *pool; + SOGoSystemDefaults *sd; int rc; pool = [NSAutoreleasePool new]; - BootstrapNSUserDefaults (); - - rc = -1; - if (getuid() > 0) { - ud = [NSUserDefaults standardUserDefaults]; - prepareUserDefaults (ud); - rc = 0; - tzName = [ud stringForKey: @"SOGoServerTimeZone"]; - if (!tzName) - tzName = @"UTC"; - [NSTimeZone setDefaultTimeZone: - [NSTimeZone timeZoneWithName: tzName]]; + sd = [SOGoSystemDefaults sharedSystemDefaults]; + [NSTimeZone setDefaultTimeZone: [sd timeZone]]; WOWatchDogApplicationMain (@"SOGo", argc, (void *) argv); } else - NSLog (@"Don't run SOGo as root!"); + { + rc = -1; + NSLog (@"Don't run SOGo as root!"); + } [pool release]; diff --git a/SOPE/GDLContentStore/GCSChannelManager.m b/SOPE/GDLContentStore/GCSChannelManager.m index bf0c6e93b..286272b5c 100644 --- a/SOPE/GDLContentStore/GCSChannelManager.m +++ b/SOPE/GDLContentStore/GCSChannelManager.m @@ -46,11 +46,6 @@ (eg missing release due to an exception) */ -#if defined(THREADSAFE) -static NSLock *channelLock; -static NSLock *adaptorLock; -#endif - @interface GCSChannelHandle : NSObject { @public @@ -89,11 +84,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; [[ud objectForKey: @"GCSChannelCollectionTimer"] intValue]; if (ChannelCollectionTimer < 1) ChannelCollectionTimer = 5*60; - -#if defined(THREADSAFE) - channelLock = [NSLock new]; - adaptorLock = [NSLock new]; -#endif } + (NSString *) adaptorNameForURLScheme: (NSString *) _scheme @@ -106,14 +96,8 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; { static GCSChannelManager *cm = nil; -#if defined(THREADSAFE) - [channelLock lock]; -#endif if (!cm) cm = [self new]; -#if defined(THREADSAFE) - [channelLock unlock]; -#endif return cm; } @@ -202,9 +186,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; { if ((key = [self databaseKeyForURL: _url])) { -#if defined(THREADSAFE) - [adaptorLock lock]; -#endif adaptor = [urlToAdaptor objectForKey: key]; if (adaptor) [self debugWithFormat: @"using cached adaptor: %@", adaptor]; @@ -236,9 +217,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; [urlToAdaptor setObject: adaptor forKey: key]; } -#if defined(THREADSAFE) - [adaptorLock unlock]; -#endif } } @@ -319,9 +297,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; /* look for cached handles */ -#if defined(THREADSAFE) - [channelLock lock]; -#endif handle = [self findAvailChannelHandleForURL: _url]; if (handle) { @@ -369,9 +344,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; } } } -#if defined(THREADSAFE) - [channelLock unlock]; -#endif return channel; } @@ -387,9 +359,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; GCSChannelHandle *handle; BOOL keepOpen; -#if defined(THREADSAFE) - [channelLock lock]; -#endif handle = [self findBusyChannelHandleForChannel: _channel]; if (handle) { @@ -430,9 +399,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; [_channel release]; } -#if defined(THREADSAFE) - [channelLock unlock]; -#endif } /* checking for tables */ @@ -481,9 +447,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; unsigned i, count; GCSChannelHandle *handle; -#if defined(THREADSAFE) - [channelLock lock]; -#endif count = [availableChannels count]; if (count) { @@ -518,9 +481,6 @@ static NSTimeInterval ChannelCollectionTimer = 5 * 60; [handlesToRemove release]; } -#if defined(THREADSAFE) - [channelLock unlock]; -#endif } /* debugging */ diff --git a/SOPE/GDLContentStore/GCSFolderManager.m b/SOPE/GDLContentStore/GCSFolderManager.m index 773e40974..ffe0fafab 100644 --- a/SOPE/GDLContentStore/GCSFolderManager.m +++ b/SOPE/GDLContentStore/GCSFolderManager.m @@ -75,10 +75,6 @@ static NSString *GCSGenericFolderTypeName = @"Container"; static const char *GCSPathColumnPattern = "c_path%i"; static NSCharacterSet *asciiAlphaNumericCS = nil; -#if defined(THREADSAFE) -static NSLock *lock; -#endif - + (void) initialize { NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; @@ -91,9 +87,6 @@ static NSLock *lock; debugOn = [ud boolForKey: @"GCSFolderManagerDebugEnabled"]; debugSQLGen = [ud boolForKey: @"GCSFolderManagerSQLDebugEnabled"]; emptyArray = [[NSArray alloc] init]; -#if defined(THREADSAFE) - lock = [NSLock new]; -#endif if (!asciiAlphaNumericCS) { asciiAlphaNumericCS @@ -109,9 +102,6 @@ static NSLock *lock; NSString *s; NSURL *url; -#if defined(THREADSAFE) - [lock lock]; -#endif if (!fm) { s = [[NSUserDefaults standardUserDefaults] stringForKey:@"OCSFolderInfoURL"]; @@ -133,9 +123,6 @@ static NSLock *lock; if (debugOn) [self debugWithFormat:@"Note: setup default manager at: %@", url]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif return fm; } diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.h b/SoObjects/Appointments/SOGoAppointmentFolder.h index 8b3d0ed68..94ccd2c14 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.h +++ b/SoObjects/Appointments/SOGoAppointmentFolder.h @@ -56,6 +56,9 @@ NSMutableDictionary *uidToFilename; NSMutableDictionary *aclMatrix; NSMutableArray *stripFields; + int davCalendarStartTimeLimit; + int davTimeLimitSeconds; + int davTimeHalfLimitSeconds; BOOL userCanAccessObjectsClassifiedAs[iCalAccessClassCount]; } diff --git a/SoObjects/Appointments/SOGoAppointmentFolder.m b/SoObjects/Appointments/SOGoAppointmentFolder.m index 15fbd6a43..e1c465207 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoAppointmentFolder.m @@ -25,7 +25,6 @@ #import #import #import -#import #import #import @@ -34,7 +33,6 @@ #import #import #import -#import #import #import #import @@ -55,14 +53,17 @@ #import #import +#import #import #import #import -#import -#import +#import #import #import +#import +#import #import +#import #import #import #import @@ -80,39 +81,17 @@ @implementation SOGoAppointmentFolder -static NGLogger *logger = nil; static NSNumber *sharedYes = nil; -static int davCalendarStartTimeLimit, davTimeLimitSeconds, - davTimeHalfLimitSeconds; + (void) initialize { - NGLoggerManager *lm; static BOOL didInit = NO; - NSUserDefaults *ud; - + if (!didInit) { didInit = YES; - - [iCalEntityObject initializeSOGoExtensions]; - - NSAssert2([super version] == 0, - @"invalid superclass (%@) version %i !", - NSStringFromClass([self superclass]), [super version]); - - lm = [NGLoggerManager defaultLoggerManager]; - logger = [lm loggerForDefaultKey: @"SOGoAppointmentFolderDebugEnabled"]; - sharedYes = [[NSNumber numberWithBool: YES] retain]; - - ud = [NSUserDefaults standardUserDefaults]; - davCalendarStartTimeLimit - = [ud integerForKey: @"SOGoDAVCalendarStartTimeLimit"]; - davTimeLimitSeconds = davCalendarStartTimeLimit * 86400; - /* 86400 / 2 = 43200. We hardcode that value in order to avoid - integer and float confusion. */ - davTimeHalfLimitSeconds = davCalendarStartTimeLimit * 43200; + [iCalEntityObject initializeSOGoExtensions]; } } @@ -250,14 +229,26 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (id) initWithName: (NSString *) name inContainer: (id) newContainer { + SOGoUser *user; if ((self = [super initWithName: name inContainer: newContainer])) { - timeZone = [[context activeUser] timeZone]; + user = [context activeUser]; + timeZone = [[user userDefaults] timeZone]; aclMatrix = [NSMutableDictionary new]; stripFields = nil; uidToFilename = nil; memset (userCanAccessObjectsClassifiedAs, NO, iCalAccessClassCount * sizeof (BOOL)); + + davCalendarStartTimeLimit + = [[user domainDefaults] davCalendarStartTimeLimit]; + davTimeLimitSeconds = davCalendarStartTimeLimit * 86400; + /* 86400 / 2 = 43200. We hardcode that value in order to avoid + integer and float confusion. */ + davTimeHalfLimitSeconds = davCalendarStartTimeLimit * 43200; + + davTimeLimitSeconds = 0; + davTimeHalfLimitSeconds = 0; } return self; @@ -288,9 +279,8 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (void) _setCalendarProperty: (id) theValue forKey: (NSString *) theKey { - NSUserDefaults *settings; - NSMutableDictionary *calendarSettings; - NSMutableDictionary *values; + SOGoUserSettings *settings; + NSMutableDictionary *calendarSettings, *values; settings = [[context activeUser] userSettings]; calendarSettings = [settings objectForKey: @"Calendar"]; @@ -325,7 +315,7 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (NSString *) calendarColor { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSDictionary *colors; NSString *color; @@ -351,7 +341,7 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (BOOL) showCalendarAlarms { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSDictionary *values; id test; BOOL show = YES; @@ -378,7 +368,7 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (BOOL) showCalendarTasks { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSDictionary *values; id test; BOOL show = YES; @@ -405,7 +395,7 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (NSString *) syncTag { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSDictionary *syncTags; NSString *syncTag; @@ -424,7 +414,7 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, if ([newSyncTag length]) { // Check for duplicated tags - NSUserDefaults *settings; + SOGoUserSettings *settings; NSMutableDictionary *calendarSettings; NSMutableDictionary *syncTags; NSEnumerator *keysList; @@ -463,7 +453,7 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, - (BOOL) synchronizeCalendar { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSDictionary *values; id test; BOOL synchronize = NO; @@ -488,13 +478,6 @@ static int davCalendarStartTimeLimit, davTimeLimitSeconds, forKey: @"FolderSynchronize"]; } -/* logging */ - -- (id) debugLogger -{ - return logger; -} - /* selection */ - (NSArray *) calendarUIDs @@ -1104,9 +1087,6 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir [fields addObjectUniquely: @"c_enddate"]; [fields addObjectUniquely: @"c_isallday"]; - if (logger) - [self debugWithFormat:@"should fetch (%@=>%@) ...", _startDate, endDate]; - if (canCycle) where = [NSString stringWithFormat: @"%@ %@ AND c_iscycle = 0", baseWhere, dateSqlString]; @@ -1121,9 +1101,6 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir { if (r) records = [self fixupRecords: records]; - if (logger) - [self debugWithFormat: @"fetched %i records: %@", - [records count], records]; ma = [NSMutableArray arrayWithArray: records]; } else @@ -1152,9 +1129,6 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir return nil; } - if (logger) - [self debugWithFormat:@"returning %i records", [ma count]]; - currentLogin = [[context activeUser] login]; if (![currentLogin isEqualToString: owner] && !_includeProtectedInformation) [self _fixupProtectedInformation: [ma objectEnumerator] @@ -1685,8 +1659,8 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir NSString *ownerTimeZone; ownerUser = [SOGoUser userWithLogin: [self ownerInContext: context]]; - ownerTimeZone = [[ownerUser timeZone] name]; - + ownerTimeZone = [[ownerUser userDefaults] timeZoneName]; + return [[iCalTimeZone timeZoneForName: ownerTimeZone] versitString]; } @@ -2702,7 +2676,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir - (BOOL) create { BOOL rc; - NSUserDefaults *userSettings; + SOGoUserSettings *userSettings; NSMutableDictionary *calendarSettings; SOGoUser *ownerUser; @@ -3077,7 +3051,7 @@ firstInstanceCalendarDateRange: (NGCalendarDateRange *) fir - (BOOL) isActive { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSArray *inactiveFolders; settings = [[context activeUser] userSettings]; diff --git a/SoObjects/Appointments/SOGoAppointmentFolders.m b/SoObjects/Appointments/SOGoAppointmentFolders.m index 082cad2c9..9e29baa44 100644 --- a/SoObjects/Appointments/SOGoAppointmentFolders.m +++ b/SoObjects/Appointments/SOGoAppointmentFolders.m @@ -278,7 +278,7 @@ - (NSArray *) webCalendarIds { - NSUserDefaults *us; + SOGoUserSettings *us; NSDictionary *tmp, *calendars; NSArray *rc; diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index cd4e39bfc..248f80697 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -1384,7 +1384,8 @@ if ([event isParticipant: [[delegate email] rfc822Email]]) ex = [NSException exceptionWithHTTPStatus: 403 reason: @"delegate is a participant"]; - else if ([SOGoGroup groupWithEmail: [[delegate email] rfc822Email]]) + else if ([SOGoGroup groupWithEmail: [[delegate email] rfc822Email] + inDomain: [ownerUser domain]]) ex = [NSException exceptionWithHTTPStatus: 403 reason: @"delegate is a group"]; } diff --git a/SoObjects/Appointments/SOGoAptMailICalReply.m b/SoObjects/Appointments/SOGoAptMailICalReply.m index 0fce741b1..bbd113809 100644 --- a/SoObjects/Appointments/SOGoAptMailICalReply.m +++ b/SoObjects/Appointments/SOGoAptMailICalReply.m @@ -32,8 +32,9 @@ #import #import -#import -#import +#import +#import +#import #import "iCalPerson+SOGo.h" #import "SOGoAptMailICalReply.h" @@ -146,10 +147,12 @@ static NSCharacterSet *wsSet = nil; { NSCalendarDate *date; SOGoUser *user; + NSTimeZone *tz; date = [apt startDate]; user = [[self context] activeUser]; - [date setTimeZone: [user timeZone]]; + tz = [[user userDefaults] timeZone]; + [date setTimeZone: tz]; return date; } diff --git a/SoObjects/Appointments/SOGoAptMailReceipt.m b/SoObjects/Appointments/SOGoAptMailReceipt.m index 0d8e8c5b5..cc43d83e4 100644 --- a/SoObjects/Appointments/SOGoAptMailReceipt.m +++ b/SoObjects/Appointments/SOGoAptMailReceipt.m @@ -92,11 +92,13 @@ static SOGoUserManager *um = nil; SOGoDateFormatter *formatter; NSCalendarDate *tzDate; SOGoUser *currentUser; + SOGoUserDefaults *ud; currentUser = [context activeUser]; + ud = [currentUser userDefaults]; tzDate = [date copy]; - [tzDate setTimeZone: [currentUser timeZone]]; + [tzDate setTimeZone: [ud timeZone]]; [tzDate autorelease]; formatter = [currentUser dateFormatterInContext: context]; diff --git a/SoObjects/Appointments/SOGoCalendarComponent.h b/SoObjects/Appointments/SOGoCalendarComponent.h index df6b8d33b..1f35fc2bc 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.h +++ b/SoObjects/Appointments/SOGoCalendarComponent.h @@ -58,7 +58,6 @@ - (void) saveComponent: (iCalRepeatableEntityObject *) newObject; /* mail notifications */ -- (BOOL) sendEMailNotifications; - (void) sendEMailUsingTemplateNamed: (NSString *) pageName forObject: (iCalRepeatableEntityObject *) object previousObject: (iCalRepeatableEntityObject *) previousObject diff --git a/SoObjects/Appointments/SOGoCalendarComponent.m b/SoObjects/Appointments/SOGoCalendarComponent.m index 184aa1a65..88b367914 100644 --- a/SoObjects/Appointments/SOGoCalendarComponent.m +++ b/SoObjects/Appointments/SOGoCalendarComponent.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -45,10 +44,12 @@ #import #import #import +#import #import #import #import #import +#import #import #import @@ -61,28 +62,8 @@ #import "SOGoCalendarComponent.h" #import "SOGoComponentOccurence.h" -static BOOL sendEMailNotifications = NO; -static BOOL sendEMailReceipts = NO; - @implementation SOGoCalendarComponent -+ (void) initialize -{ - NSUserDefaults *ud; - static BOOL didInit = NO; - - if (!didInit) - { - didInit = YES; - - ud = [NSUserDefaults standardUserDefaults]; - sendEMailNotifications - = [ud boolForKey: @"SOGoAppointmentSendEMailNotifications"]; - sendEMailReceipts - = [ud boolForKey: @"SOGoAppointmentSendEMailReceipts"]; - } -} - - (id) init { if ((self = [super init])) @@ -419,19 +400,21 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr { NSMutableArray *allAttendees; NSEnumerator *enumerator; - NSString *organizerEmail; + NSString *organizerEmail, *domain; iCalPerson *currentAttendee; SOGoGroup *group; BOOL doesIncludeGroup; unsigned int i; + domain = [[context activeUser] domain]; organizerEmail = [[theEvent organizer] rfc822Email]; doesIncludeGroup = NO; allAttendees = [NSMutableArray arrayWithArray: [theEvent attendees]]; enumerator = [[theEvent attendees] objectEnumerator]; while ((currentAttendee = [enumerator nextObject])) { - group = [SOGoGroup groupWithEmail: [currentAttendee rfc822Email]]; + group = [SOGoGroup groupWithEmail: [currentAttendee rfc822Email] + inDomain: domain]; if (group) { iCalPerson *person; @@ -581,18 +564,15 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr : nil); } -- (BOOL) sendEMailNotifications -{ - return sendEMailNotifications; -} - - (NSTimeZone *) timeZoneForUser: (NSString *) email { NSString *uid; + SOGoUserDefaults *ud; uid = [[SOGoUserManager sharedUserManager] getUIDForEmail: email]; + ud = [[SOGoUser userWithLogin: uid] userDefaults]; - return [[SOGoUser userWithLogin: uid] timeZone]; + return [ud timeZone]; } - (void) sendEMailUsingTemplateNamed: (NSString *) newPageName @@ -613,15 +593,17 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr NGMimeBodyPart *bodyPart; NGMimeMultipartBody *body; SOGoUser *ownerUser; + SOGoDomainDefaults *dd; - if (sendEMailNotifications - && [object isStillRelevant]) + ownerUser = [SOGoUser userWithLogin: owner]; + dd = [ownerUser domainDefaults]; + if ([dd appointmentSendEMailNotifications] && [object isStillRelevant]) { + language = [[ownerUser userDefaults] language]; count = [attendees count]; if (count) { /* sender */ - ownerUser = [SOGoUser userWithLogin: owner]; //currentUser = [context activeUser]; //shortSenderEmail = [[currentUser allEmails] objectAtIndex: 0]; // senderEmail = [NSString stringWithFormat: @"%@ <%@>", @@ -651,7 +633,6 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr recipient = [attendee mailAddress]; email = [attendee rfc822Email]; - language = [ownerUser language]; #warning this could be optimized in a class hierarchy common with the \ SOGoObject acl notification mechanism /* create page name */ @@ -722,7 +703,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr [body release]; /* send the damn thing */ - [[SOGoMailer sharedMailer] + [[SOGoMailer mailerWithDomainDefaults: dd] sendMimePart: msg toRecipients: [NSArray arrayWithObject: email] sender: shortSenderEmail]; @@ -747,24 +728,23 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr NGMimeBodyPart *bodyPart; NGMimeMultipartBody *body; NSData *bodyData; - SOGoUser *ownerUser; + SOGoDomainDefaults *dd; - if (sendEMailNotifications) + dd = [from domainDefaults]; + if ([dd appointmentSendEMailNotifications]) { /* get WOApplication instance */ app = [WOApplication application]; - //ownerUser = [SOGoUser userWithLogin: owner]; - ownerUser = from; - language = [ownerUser language]; + language = [[from userDefaults] language]; /* create page name */ - pageName - = [NSString stringWithFormat: @"SOGoAptMail%@ICalReply", language]; + pageName = [NSString stringWithFormat: @"SOGoAptMail%@ICalReply", + language]; /* construct message content */ p = [app pageWithName: pageName inContext: context]; [p setApt: event]; - attendee = [event findParticipant: ownerUser]; + attendee = [event findParticipant: from]; [p setAttendee: attendee]; /* construct message */ @@ -816,7 +796,7 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr /* send the damn thing */ email = [recipient rfc822Email]; - [[SOGoMailer sharedMailer] + [[SOGoMailer mailerWithDomainDefaults: dd] sendMimePart: msg toRecipients: [NSArray arrayWithObject: email] sender: [attendee rfc822Email]]; @@ -850,9 +830,12 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr NGMutableHashMap *headerMap; NGMimeMessage *msg; SOGoUser *currentUser; + SOGoDomainDefaults *dd; NSDictionary *identity; - if (sendEMailReceipts && [attendees count]) + currentUser = [context activeUser]; + if ([[currentUser userDefaults] appointmentSendEMailReceipts] + && [attendees count]) { pageName = [NSString stringWithFormat: @"SOGoAptMail%@Receipt", template]; @@ -861,7 +844,6 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr [page setApt: object]; [page setRecipients: attendees]; - currentUser = [context activeUser]; identity = [currentUser primaryIdentity]; /* construct message */ @@ -884,7 +866,8 @@ static inline BOOL _occurenceHasID (iCalRepeatableEntityObject *occurence, NSStr /* send the damn thing */ senderEmail = [identity objectForKey: @"email"]; - [[SOGoMailer sharedMailer] + dd = [currentUser domainDefaults]; + [[SOGoMailer mailerWithDomainDefaults: dd] sendMimePart: msg toRecipients: [NSArray arrayWithObject: senderEmail] sender: senderEmail]; diff --git a/SoObjects/Appointments/SOGoFreeBusyObject.m b/SoObjects/Appointments/SOGoFreeBusyObject.m index c711b48c4..724076f0f 100644 --- a/SoObjects/Appointments/SOGoFreeBusyObject.m +++ b/SoObjects/Appointments/SOGoFreeBusyObject.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -32,8 +31,10 @@ #import #import -#import +#import #import +#import +#import #import #import "SOGoAppointmentFolder.h" @@ -41,9 +42,6 @@ #import "SOGoFreeBusyObject.h" -static unsigned int freebusyRangeStart = 0; -static unsigned int freebusyRangeEnd = 0; - @interface SOGoFreeBusyObject (PrivateAPI) - (NSString *) iCalStringForFreeBusyInfos: (NSArray *) _infos from: (NSCalendarDate *) _startDate @@ -52,25 +50,6 @@ static unsigned int freebusyRangeEnd = 0; @implementation SOGoFreeBusyObject -+ (void) initialize -{ - NSArray *freebusyDateRange; - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - freebusyDateRange = [ud arrayForKey: @"SOGoFreeBusyDefaultInterval"]; - if (freebusyDateRange && [freebusyDateRange count] > 1) - { - freebusyRangeStart = [[freebusyDateRange objectAtIndex: 0] unsignedIntValue]; - freebusyRangeEnd = [[freebusyDateRange objectAtIndex: 1] unsignedIntValue]; - } - else - { - freebusyRangeStart = 7; - freebusyRangeEnd = 7; - } -} - - (iCalPerson *) iCalPersonWithUID: (NSString *) uid { iCalPerson *person; @@ -202,15 +181,31 @@ static unsigned int freebusyRangeEnd = 0; - (NSString *) contentAsString { NSCalendarDate *today, *startDate, *endDate; - NSTimeZone *timeZone; + SOGoUserDefaults *ud; + SOGoDomainDefaults *dd; + NSArray *interval; + unsigned int start, end; today = [[NSCalendarDate calendarDate] beginOfDay]; - timeZone = [[context activeUser] timeZone]; - [today setTimeZone: timeZone]; + ud = [[context activeUser] userDefaults]; + [today setTimeZone: [ud timeZone]]; - startDate = [today dateByAddingYears: 0 months: 0 days: -freebusyRangeStart + dd = [[context activeUser] domainDefaults]; + interval = [dd freeBusyDefaultInterval]; + if ([interval count] > 1) + { + start = [[interval objectAtIndex: 0] unsignedIntValue]; + end = [[interval objectAtIndex: 1] unsignedIntValue]; + } + else + { + start = 7; + end = 7; + } + + startDate = [today dateByAddingYears: 0 months: 0 days: -start hours: 0 minutes: 0 seconds: 0]; - endDate = [today dateByAddingYears: 0 months: 0 days: freebusyRangeEnd + endDate = [today dateByAddingYears: 0 months: 0 days: end hours: 0 minutes: 0 seconds: 0]; return [self contentAsStringFrom: startDate to: endDate]; @@ -278,7 +273,7 @@ static unsigned int freebusyRangeEnd = 0; - (id) GETAction: (id)_ctx { WOResponse *r; - NSData *contentData; + NSData *contentData; contentData = [[self contentAsString] dataUsingEncoding: NSUTF8StringEncoding]; diff --git a/SoObjects/Appointments/SOGoTaskObject.m b/SoObjects/Appointments/SOGoTaskObject.m index f89866252..33177c75c 100644 --- a/SoObjects/Appointments/SOGoTaskObject.m +++ b/SoObjects/Appointments/SOGoTaskObject.m @@ -20,7 +20,6 @@ */ #import -#import #import #import diff --git a/SoObjects/Appointments/SOGoWebAppointmentFolder.m b/SoObjects/Appointments/SOGoWebAppointmentFolder.m index fd9099412..9b0b7bfa6 100644 --- a/SoObjects/Appointments/SOGoWebAppointmentFolder.m +++ b/SoObjects/Appointments/SOGoWebAppointmentFolder.m @@ -78,7 +78,7 @@ - (NSException *) delete { NSException *error; - NSUserDefaults *settings; + SOGoUserSettings *settings; NSMutableDictionary *calSettings, *webCalendars; NSString *name; diff --git a/SoObjects/Appointments/iCalEntityObject+SOGo.m b/SoObjects/Appointments/iCalEntityObject+SOGo.m index afc6b5dd5..108f3b736 100644 --- a/SoObjects/Appointments/iCalEntityObject+SOGo.m +++ b/SoObjects/Appointments/iCalEntityObject+SOGo.m @@ -36,6 +36,7 @@ #import #import +#import #import "iCalPerson+SOGo.h" @@ -61,7 +62,8 @@ _computeAllDayOffset() application = [WOApplication application]; user = [[application context] activeUser]; - offset = utcOffset - [[user timeZone] secondsFromGMT]; + tz = [[user userDefaults] timeZone]; + offset = utcOffset - [tz secondsFromGMT]; return offset; } diff --git a/SoObjects/Contacts/SOGoContactFolders.m b/SoObjects/Contacts/SOGoContactFolders.m index 3bedcc759..105e6149e 100644 --- a/SoObjects/Contacts/SOGoContactFolders.m +++ b/SoObjects/Contacts/SOGoContactFolders.m @@ -32,7 +32,9 @@ #import #import -#import +#import +#import +#import #import "SOGoContactGCSFolder.h" #import "SOGoContactSourceFolder.h" @@ -54,11 +56,12 @@ { SOGoUserManager *um; NSEnumerator *sourceIDs; - NSString *currentSourceID, *srcDisplayName; + NSString *currentSourceID, *srcDisplayName, *domain; SOGoContactSourceFolder *currentFolder; + domain = [[context activeUser] domain]; um = [SOGoUserManager sharedUserManager]; - sourceIDs = [[um addressBookSourceIDs] objectEnumerator]; + sourceIDs = [[um addressBookSourceIDsInDomain: domain] objectEnumerator]; while ((currentSourceID = [sourceIDs nextObject])) { srcDisplayName = [um displayNameForSourceWithID: currentSourceID]; diff --git a/SoObjects/Contacts/SOGoContactLDIFEntry.m b/SoObjects/Contacts/SOGoContactLDIFEntry.m index e2d7008c0..259832734 100644 --- a/SoObjects/Contacts/SOGoContactLDIFEntry.m +++ b/SoObjects/Contacts/SOGoContactLDIFEntry.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -32,22 +31,8 @@ #import "SOGoContactGCSEntry.h" #import "SOGoContactLDIFEntry.h" -static NSString *sogoContactInfoAttribute = nil; - @implementation SOGoContactLDIFEntry -+ (void) initialize -{ - NSUserDefaults *ud; - - if (!sogoContactInfoAttribute) - { - ud = [NSUserDefaults standardUserDefaults]; - ASSIGN (sogoContactInfoAttribute, - [ud stringForKey: @"SOGoLDAPContactInfoAttribute"]); - } -} - + (SOGoContactLDIFEntry *) contactEntryWithName: (NSString *) newName withLDIFEntry: (NSDictionary *) newEntry inContainer: (id) newContainer @@ -126,7 +111,7 @@ static NSString *sogoContactInfoAttribute = nil; - (NGVCard *) vCard { - NSString *info, *surname, *streetAddress, *location, *key, *region, *postalCode, *country, *org, *orgunit; + NSString *info, *surname, *streetAddress, *location, *region, *postalCode, *country, *org, *orgunit; CardElement *element; unsigned int count; @@ -159,14 +144,12 @@ static NSString *sogoContactInfoAttribute = nil; if (info) [vcard setNickname: info]; - /* If SOGoLDAPContactInfoAttribute is defined, we set as the NOTE value - in order for Thunderbird (or any other CardDAV client) to display it. */ - if (sogoContactInfoAttribute) - key = [sogoContactInfoAttribute lowercaseString]; - else - key = @"description"; - info = [ldifEntry objectForKey: key]; - if (info) + /* If "c_info" is defined, we set as the NOTE value in order for + Thunderbird (or any other CardDAV client) to display it. */ + info = [ldifEntry objectForKey: @"c_info"]; + if (![info length]) + info = [ldifEntry objectForKey: @"description"]; + if ([info length]) [vcard setNote: info]; info = [ldifEntry objectForKey: @"mail"]; diff --git a/SoObjects/Contacts/SOGoContactSourceFolder.m b/SoObjects/Contacts/SOGoContactSourceFolder.m index 20cb37d7c..5b70fdf51 100644 --- a/SoObjects/Contacts/SOGoContactSourceFolder.m +++ b/SoObjects/Contacts/SOGoContactSourceFolder.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -199,10 +198,8 @@ NSEnumerator *oldRecords; NSDictionary *oldRecord; NSMutableDictionary *newRecord; - NSString *data, *contactInfo; - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; + NSString *data; + newRecords = [[NSMutableArray alloc] initWithCapacity: [records count]]; [newRecords autorelease]; @@ -257,12 +254,9 @@ if (data) [newRecord setObject: data forKey: @"isGroup"]; - contactInfo = [[ud stringForKey: @"SOGoLDAPContactInfoAttribute"] lowercaseString]; - if ([contactInfo length] > 0) { - data = [oldRecord objectForKey: contactInfo]; - if ([data length] > 0) - [newRecord setObject: data forKey: @"contactInfo"]; - } + data = [oldRecord objectForKey: @"c_info"]; + if ([data length] > 0) + [newRecord setObject: data forKey: @"contactInfo"]; [newRecords addObject: newRecord]; oldRecord = [oldRecords nextObject]; diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index 003d44d18..2c69d95d4 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -26,7 +26,6 @@ #import #import #import -#import #import #import @@ -54,11 +53,13 @@ #import #import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import #import "NSData+Mail.h" #import "NSString+Mail.h" @@ -77,25 +78,13 @@ static NSString *headerKeys[] = {@"subject", @"to", @"cc", @"bcc", @implementation SOGoDraftObject -static NGMimeType *TextPlainType = nil; static NGMimeType *MultiMixedType = nil; static NSString *userAgent = @"SOGoMail 1.0"; -static BOOL draftDeleteDisabled = NO; // for debugging -static BOOL debugOn = NO; -static BOOL showTextAttachmentsInline = NO; + (void) initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - /* Note: be aware of the charset issues before enabling this! */ - showTextAttachmentsInline = [ud boolForKey: @"SOGoShowTextAttachmentsInline"]; - - if ((draftDeleteDisabled = [ud boolForKey: @"SOGoNoDraftDeleteAfterSend"])) - NSLog(@"WARNING: draft delete is disabled! (SOGoNoDraftDeleteAfterSend)"); - - TextPlainType = [[NGMimeType mimeType: @"text" subType: @"plain"] copy]; - MultiMixedType = [[NGMimeType mimeType: @"multipart" subType: @"mixed"] copy]; + MultiMixedType = [NGMimeType mimeType: @"multipart" subType: @"mixed"]; + [MultiMixedType retain]; } - (id) init @@ -651,7 +640,7 @@ static BOOL showTextAttachmentsInline = NO; - (void) fetchMailForForwarding: (SOGoMailObject *) sourceMail { NSDictionary *info, *attachment; - SOGoUser *currentUser; + SOGoUserDefaults *ud; NSString *signature; [sourceMail fetchCoreInfos]; @@ -667,8 +656,8 @@ static BOOL showTextAttachmentsInline = NO; [self setSourceFlag: @"$Forwarded"]; /* attach message */ - currentUser = [context activeUser]; - if ([[currentUser messageForwarding] isEqualToString: @"inline"]) + ud = [[context activeUser] userDefaults]; + if ([[ud mailMessageForwarding] isEqualToString: @"inline"]) { [self setText: [sourceMail contentForInlineForward]]; [self _fetchAttachments: [sourceMail fetchFileAttachmentKeys] @@ -678,7 +667,7 @@ static BOOL showTextAttachmentsInline = NO; { // TODO: use subject for filename? // error = [newDraft saveAttachment:content withName:@"forward.eml"]; - signature = [currentUser signature]; + signature = [ud mailSignature]; if ([signature length]) [self setText: [NSString stringWithFormat: @"\n-- \n%@", signature]]; attachment = [NSDictionary dictionaryWithObjectsAndKeys: @@ -833,7 +822,7 @@ static BOOL showTextAttachmentsInline = NO; */ NGMutableHashMap *map; NGMimeBodyPart *bodyPart; - NSUserDefaults *ud; + SOGoUserDefaults *ud; ud = [[context activeUser] userDefaults]; @@ -845,8 +834,8 @@ static BOOL showTextAttachmentsInline = NO; [map setObject: @"text/plain" forKey: @"content-type"]; if (text) { - if ([[ud stringForKey: @"ComposeMessagesType"] isEqualToString: @"html"]) - [map setObject: htmlContentTypeValue + if ([[ud mailComposeMessageType] isEqualToString: @"html"]) + [map setObject: htmlContentTypeValue forKey: @"content-type"]; else [map setObject: contentTypeValue forKey: @"content-type"]; @@ -871,7 +860,7 @@ static BOOL showTextAttachmentsInline = NO; - (NGMimeMessage *) mimeMessageForContentWithHeaderMap: (NGMutableHashMap *) map { NGMimeMessage *message; - NSUserDefaults *ud; + SOGoUserDefaults *ud; // BOOL addSuffix; id body; @@ -883,7 +872,7 @@ static BOOL showTextAttachmentsInline = NO; { // if ([body isKindOfClass:[NSString class]]) /* Note: just 'utf8' is displayed wrong in Mail.app */ - if ([[ud stringForKey: @"ComposeMessagesType"] isEqualToString: @"html"]) + if ([[ud mailComposeMessageType] isEqualToString: @"html"]) [map setObject: htmlContentTypeValue forKey: @"content-type"]; else @@ -951,11 +940,15 @@ static BOOL showTextAttachmentsInline = NO; NSString *type; NSString *cdtype; NSString *cd; + SOGoDomainDefaults *dd; type = [self contentTypeForAttachmentWithName:_name]; - + if ([type hasPrefix: @"text/"]) - cdtype = showTextAttachmentsInline ? @"inline" : @"attachment"; + { + dd = [[context activeUser] domainDefaults]; + cdtype = [dd mailAttachTextDocumentsInline] ? @"inline" : @"attachment"; + } else if ([type hasPrefix: @"image/"] || [type hasPrefix: @"message"]) cdtype = @"inline"; else @@ -1366,7 +1359,8 @@ static BOOL showTextAttachmentsInline = NO; SOGoMailFolder *sentFolder; NSData *message; NSURL *sourceIMAP4URL; - + SOGoDomainDefaults *dd; + /* send mail */ sentFolder = [[self mailAccountFolder] sentFolderInContext: context]; if ([sentFolder isKindOfClass: [NSException class]]) @@ -1374,9 +1368,11 @@ static BOOL showTextAttachmentsInline = NO; else { message = [self mimeMessageAsData]; - error = [[SOGoMailer sharedMailer] sendMailData: message - toRecipients: [self allBareRecipients] - sender: [self sender]]; + dd = [[context activeUser] domainDefaults]; + error = [[SOGoMailer mailerWithDomainDefaults: dd] + sendMailData: message + toRecipients: [self allBareRecipients] + sender: [self sender]]; if (!error) { error = [sentFolder postData: message flags: @"seen"]; @@ -1390,7 +1386,7 @@ static BOOL showTextAttachmentsInline = NO; sourceIMAP4URL = [NSURL URLWithString: sourceURL]; [imap4 addFlags: sourceFlag toURL: sourceIMAP4URL]; } - if (!draftDeleteDisabled) + if (![dd mailKeepDraftsAfterSend]) error = [self delete]; } } @@ -1441,11 +1437,4 @@ static BOOL showTextAttachmentsInline = NO; return str; } -/* debugging */ - -- (BOOL) isDebuggingEnabled -{ - return debugOn; -} - @end /* SOGoDraftObject */ diff --git a/SoObjects/Mailer/SOGoDraftsFolder.m b/SoObjects/Mailer/SOGoDraftsFolder.m index 47078e920..140f4605e 100644 --- a/SoObjects/Mailer/SOGoDraftsFolder.m +++ b/SoObjects/Mailer/SOGoDraftsFolder.m @@ -22,7 +22,6 @@ #import #import -#import #import #import @@ -31,29 +30,11 @@ #import "SOGoDraftsFolder.h" -static NSString *spoolFolder = nil; - static NSTimeInterval lastNew = 0; static unsigned int newCount; @implementation SOGoDraftsFolder -+ (void) initialize -{ - NSUserDefaults *ud; - - if (!spoolFolder) - { - ud = [NSUserDefaults standardUserDefaults]; - spoolFolder = [ud stringForKey:@"SOGoMailSpoolPath"]; - if (![spoolFolder length]) - spoolFolder = @"/tmp/"; - [spoolFolder retain]; - - NSLog(@"Note: using SOGo mail spool folder: %@", spoolFolder); - } -} - - (NSString *) generateNameForNewDraft { NSString *newName, *login; @@ -102,5 +83,4 @@ static unsigned int newCount; return YES; } - @end diff --git a/SoObjects/Mailer/SOGoMailAccount.h b/SoObjects/Mailer/SOGoMailAccount.h index f6c87bd2b..b6112eb3a 100644 --- a/SoObjects/Mailer/SOGoMailAccount.h +++ b/SoObjects/Mailer/SOGoMailAccount.h @@ -41,6 +41,12 @@ #import "SOGoSentFolder.h" #import "SOGoTrashFolder.h" +typedef enum { + undefined = -1, + rfc2086 = 0, + rfc4314 +} SOGoIMAPAclStyle; + @interface SOGoMailAccount : SOGoMailBaseObject { NSString *accountName; @@ -48,17 +54,20 @@ SOGoDraftsFolder *draftsFolder; SOGoSentFolder *sentFolder; SOGoTrashFolder *trashFolder; + SOGoIMAPAclStyle imapAclStyle; } - (void) setAccountName: (NSString *) newAccountName; +- (SOGoIMAPAclStyle) imapAclStyle; +- (BOOL) imapAclConformsToIMAPExt; + - (BOOL) supportsQuotas; - (BOOL) updateFilters; /* folder pathes */ - (NSArray *) allFolderPaths; -- (NSArray *) additionalRootFolderNames; /* stuff like filters and drafts */ - (BOOL) isInDraftsFolder; /* shared accounts */ diff --git a/SoObjects/Mailer/SOGoMailAccount.m b/SoObjects/Mailer/SOGoMailAccount.m index 750edf6dc..b8d607515 100644 --- a/SoObjects/Mailer/SOGoMailAccount.m +++ b/SoObjects/Mailer/SOGoMailAccount.m @@ -21,9 +21,9 @@ */ #import +#import #import #import -#import #import #import @@ -38,8 +38,11 @@ #import #import -#import -#import +#import +#import +#import +#import +#import #import "SOGoDraftsFolder.h" #import "SOGoMailFolder.h" @@ -51,66 +54,9 @@ @implementation SOGoMailAccount -static NSArray *rootFolderNames = nil; static NSString *inboxFolderName = @"INBOX"; -static NSString *draftsFolderName = @"Drafts"; -static NSString *sentFolderName = nil; -static NSString *trashFolderName = nil; -static NSString *sharedFolderName = @""; // TODO: add English default -static NSString *otherUsersFolderName = @""; // TODO: add English default static NSString *sieveScriptName = @"sogo"; -static BOOL defaultShowSubscribedFoldersOnly = NO; -// this is temporary, until we allow users to manage their own accounts -static NSString *fallbackIMAP4Server = nil; - -+ (void) initialize -{ - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - NSString *cfgDraftsFolderName; - - sharedFolderName = [ud stringForKey:@"SOGoSharedFolderName"]; - otherUsersFolderName = [ud stringForKey:@"SOGoOtherUsersFolderName"]; - cfgDraftsFolderName = [ud stringForKey:@"SOGoDraftsFolderName"]; - if (!sentFolderName) - { - sentFolderName = [ud stringForKey: @"SOGoSentFolderName"]; - if (!sentFolderName) - sentFolderName = @"Sent"; - [sentFolderName retain]; - } - if (!trashFolderName) - { - trashFolderName = [ud stringForKey: @"SOGoTrashFolderName"]; - if (!trashFolderName) - trashFolderName = @"Trash"; - [trashFolderName retain]; - } - if ([cfgDraftsFolderName length] > 0) - { - ASSIGN (draftsFolderName, cfgDraftsFolderName); - NSLog(@"Note: using drafts folder named: '%@'", draftsFolderName); - } - - NSLog(@"Note: using shared-folders name: '%@'", sharedFolderName); - NSLog(@"Note: using other-users-folders name: '%@'", otherUsersFolderName); - - rootFolderNames = [[NSArray alloc] initWithObjects: - draftsFolderName, - nil]; - - if (!fallbackIMAP4Server) - { - fallbackIMAP4Server = [ud stringForKey: @"SOGoFallbackIMAP4Server"]; - if (fallbackIMAP4Server) - [fallbackIMAP4Server retain]; - else - fallbackIMAP4Server = @"localhost"; - } - - defaultShowSubscribedFoldersOnly = [ud boolForKey: @"SOGoMailShowSubscribedFoldersOnly"]; -} - - (id) init { if ((self = [super init])) @@ -120,6 +66,7 @@ static NSString *fallbackIMAP4Server = nil; sentFolder = nil; trashFolder = nil; accountName = nil; + imapAclStyle = undefined; } return self; @@ -163,11 +110,6 @@ static NSString *fallbackIMAP4Server = nil; /* listing the available folders */ -- (NSArray *) additionalRootFolderNames -{ - return rootFolderNames; -} - - (BOOL) isInDraftsFolder { return NO; @@ -181,7 +123,8 @@ static NSString *fallbackIMAP4Server = nil; folders = [NSMutableArray array]; imapFolders = [[self imap4Connection] subfoldersForURL: [self imap4URL]]; - additionalFolders = [self additionalRootFolderNames]; + additionalFolders + = [NSArray arrayWithObject: [self draftsFolderNameInContext: nil]]; if ([imapFolders count] > 0) [folders addObjectsFromArray: imapFolders]; if ([additionalFolders count] > 0) @@ -193,6 +136,31 @@ static NSString *fallbackIMAP4Server = nil; return [folders stringsWithFormat: @"folder%@"]; } +- (SOGoIMAPAclStyle) imapAclStyle +{ + SOGoDomainDefaults *dd; + + if (imapAclStyle == undefined) + { + dd = [[context activeUser] domainDefaults]; + if ([[dd imapAclStyle] isEqualToString: @"rfc2086"]) + imapAclStyle = rfc2086; + else + imapAclStyle = rfc4314; + } + + return imapAclStyle; +} + +- (BOOL) imapAclConformsToIMAPExt +{ + SOGoDomainDefaults *dd; + + dd = [[context activeUser] domainDefaults]; + + return [dd imapAclConformsToIMAPExt]; +} + - (BOOL) supportsQuotas { NGImap4Client *imapClient; @@ -209,13 +177,14 @@ static NSString *fallbackIMAP4Server = nil; NSMutableString *header, *script; NGInternetSocketAddress *address; NSDictionary *result, *values; - NSUserDefaults *ud; + SOGoUserDefaults *ud; + SOGoDomainDefaults *dd; NGSieveClient *client; NSString *v; BOOL b; - if (![[NSUserDefaults standardUserDefaults] boolForKey: @"SOGoVacationEnabled"] && - ![[NSUserDefaults standardUserDefaults] boolForKey: @"SOGoForwardEnabled"]) + dd = [[context activeUser] domainDefaults]; + if (!([dd vacationEnabled] || [dd forwardEnabled])) return YES; ud = [[context activeUser] userDefaults]; @@ -227,7 +196,7 @@ static NSString *fallbackIMAP4Server = nil; // Right now, we handle Sieve filters here and only for vacation // and forwards. Traditional filters support (for fileinto, for // example) will be added later. - values = [ud objectForKey: @"Vacation"]; + values = [ud vacationOptions]; // We handle vacation messages. // See http://ietfreport.isoc.org/idref/draft-ietf-sieve-vacation/ @@ -273,7 +242,7 @@ static NSString *fallbackIMAP4Server = nil; // We handle mail forward - values = [ud objectForKey: @"Forward"]; + values = [ud forwardOptions]; if (values && [[values objectForKey: @"enabled"] boolValue]) { @@ -356,17 +325,11 @@ static NSString *fallbackIMAP4Server = nil; { NSMutableArray *folderPaths; NSArray *rawFolders, *mainFolders; - NSUserDefaults *ud; - NSString *showSubscribedFoldersOnly; + SOGoUserDefaults *ud; ud = [[context activeUser] userDefaults]; - showSubscribedFoldersOnly = [ud stringForKey: @"showSubscribedFoldersOnly"]; - if (showSubscribedFoldersOnly) - rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL] - onlySubscribedFolders: [showSubscribedFoldersOnly boolValue]]; - else - rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL] - onlySubscribedFolders: defaultShowSubscribedFoldersOnly]; + rawFolders = [[self imap4Connection] allFoldersForURL: [self imap4URL] + onlySubscribedFolders: [ud mailShowSubscribedFoldersOnly]]; mainFolders = [[NSArray arrayWithObjects: [self inboxFolderNameInContext: context], @@ -428,14 +391,8 @@ static NSString *fallbackIMAP4Server = nil; escUsername = [[username stringByEscapingURL] stringByReplacingString: @"@" withString: @"%40"]; -#if 1 - // see comment about fallbackIMAP4Server above hostString = [NSString stringWithFormat: @"%@@%@", escUsername, - [mailAccount objectForKey: @"serverName"]]; -#else - hostString = [NSString stringWithFormat: @"%@@%@", escUsername, - fallbackIMAP4Server]; -#endif + [mailAccount objectForKey: @"serverName"]]; } else hostString = @"localhost"; @@ -519,54 +476,88 @@ static NSString *fallbackIMAP4Server = nil; return inboxFolderName; } +- (BOOL) _migrateFolderWithPurpose: (NSString *) purpose + withName: (NSString *) folderName +{ + SOGoUserDefaults *ud; + NSString *methodName; + SEL methodSel; + BOOL rc; + + ud = [[context activeUser] userDefaults]; + methodName = [NSString stringWithFormat: @"set%@FolderName:", purpose]; + methodSel = NSSelectorFromString (methodName); + if ([ud respondsToSelector: methodSel]) + { + [ud performSelector: methodSel withObject: folderName]; + [ud synchronize]; + rc = YES; + } + else + { + [self errorWithFormat: @"method '%@' not available with user defaults"@ + @" object, folder migration fails", methodName]; + rc = NO; + } + + return rc; +} + - (NSString *) _userFolderNameWithPurpose: (NSString *) purpose { - NSUserDefaults *ud; + SOGoUser *user; + SOGoUserSettings *us; + SOGoUserDefaults *ud; NSMutableDictionary *mailSettings; - NSString *folderName; + NSString *folderName, *key, *methodName; + SEL methodSel; folderName = nil; - ud = [[context activeUser] userSettings]; - mailSettings = [ud objectForKey: @"Mail"]; + + user = [context activeUser]; + /* migration part: */ + us = [user userSettings]; + mailSettings = [us objectForKey: @"Mail"]; if (mailSettings) - folderName - = [mailSettings objectForKey: [NSString stringWithFormat: @"%@Folder", - purpose]]; + { + key = [NSString stringWithFormat: @"%@Folder", purpose]; + folderName = [mailSettings objectForKey: key]; + if ([folderName length] + && [self _migrateFolderWithPurpose: purpose withName: folderName]) + { + [mailSettings removeObjectForKey: key]; + [us synchronize]; + folderName = nil; + } + } + else + folderName = nil; + + if (!folderName) + { + ud = [[context activeUser] userDefaults]; + methodName = [NSString stringWithFormat: @"%@FolderName", + [purpose lowercaseString]]; + methodSel = NSSelectorFromString (methodName); + folderName = [ud performSelector: methodSel]; + } return folderName; } - (NSString *) draftsFolderNameInContext: (id) _ctx { - NSString *folderName; - - folderName = [self _userFolderNameWithPurpose: @"Drafts"]; - if (!folderName) - folderName = draftsFolderName; - - return folderName; + return [self _userFolderNameWithPurpose: @"Drafts"]; } - (NSString *) sentFolderNameInContext: (id)_ctx { - NSString *folderName; - - folderName = [self _userFolderNameWithPurpose: @"Sent"]; - if (!folderName) - folderName = sentFolderName; - - return folderName; + return [self _userFolderNameWithPurpose: @"Sent"]; } - (NSString *) trashFolderNameInContext: (id)_ctx { - NSString *folderName; - - folderName = [self _userFolderNameWithPurpose: @"Trash"]; - if (!folderName) - folderName = trashFolderName; - - return folderName; + return [self _userFolderNameWithPurpose: @"Trash"]; } - (id) folderWithTraversal: (NSString *) traversal @@ -713,12 +704,20 @@ static NSString *fallbackIMAP4Server = nil; - (NSString *) sharedFolderName { - return sharedFolderName; + SOGoDomainDefaults *dd; + + dd = [[context activeUser] domainDefaults]; + + return [dd sharedFolderName]; } - (NSString *) otherUsersFolderName { - return otherUsersFolderName; + SOGoDomainDefaults *dd; + + dd = [[context activeUser] domainDefaults]; + + return [dd otherUsersFolderName]; } @end /* SOGoMailAccount */ diff --git a/SoObjects/Mailer/SOGoMailBodyPart.m b/SoObjects/Mailer/SOGoMailBodyPart.m index d94b69d49..b0c06e7e7 100644 --- a/SoObjects/Mailer/SOGoMailBodyPart.m +++ b/SoObjects/Mailer/SOGoMailBodyPart.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -50,18 +49,17 @@ static BOOL debugOn = NO; + (void) initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - if (![[ud objectForKey:@"SOGoMailDisableETag"] boolValue]) { - mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"", - UIX_MAILER_MAJOR_VERSION, - UIX_MAILER_MINOR_VERSION, - UIX_MAILER_SUBMINOR_VERSION]; - NSLog(@"Note(SOGoMailBodyPart): using constant etag for mail parts: '%@'", - mailETag); - } - else - NSLog(@"Note(SOGoMailBodyPart): etag caching disabled!"); + if (!mailETag) + { + /* The following disabled code should not be needed, except if we use + annotations (see davEntityTag below) */ + // if (![[ud objectForKey: @"SOGoMailDisableETag"] boolValue]) { + + mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"", + UIX_MAILER_MAJOR_VERSION, + UIX_MAILER_MINOR_VERSION, + UIX_MAILER_SUBMINOR_VERSION]; + } } - (id) init diff --git a/SoObjects/Mailer/SOGoMailFolder.h b/SoObjects/Mailer/SOGoMailFolder.h index 47278c3b8..35e75ca12 100644 --- a/SoObjects/Mailer/SOGoMailFolder.h +++ b/SoObjects/Mailer/SOGoMailFolder.h @@ -38,12 +38,6 @@ @class NGImap4MailboxInfo; @class WOResponse; -typedef enum { - undefined = -1, - rfc2086 = 0, - rfc4314 -} SOGoIMAPAclStyle; - @interface SOGoMailFolder : SOGoMailBaseObject { NSMutableArray *filenames; @@ -51,8 +45,6 @@ typedef enum { NSDictionary *mailboxACL; } -+ (SOGoIMAPAclStyle) imapAclStyle; - - (NSString *) absoluteImap4Name; /* messages */ diff --git a/SoObjects/Mailer/SOGoMailFolder.m b/SoObjects/Mailer/SOGoMailFolder.m index 4bd71ee62..e5b6dbe93 100644 --- a/SoObjects/Mailer/SOGoMailFolder.m +++ b/SoObjects/Mailer/SOGoMailFolder.m @@ -22,7 +22,6 @@ #import #import #import -#import #import #import @@ -48,8 +47,11 @@ #import #import #import +#import #import +#import #import +#import #import #import "EOQualifier+MailDAV.h" @@ -62,14 +64,6 @@ static NSString *defaultUserID = @"anyone"; -#warning this could be detected from the capabilities -static SOGoIMAPAclStyle aclStyle = undefined; -static BOOL aclUsernamesAreQuoted = NO; -/* http://www.tools.ietf.org/wg/imapext/draft-ietf-imapext-acl/ */ -static BOOL aclConformsToIMAPExt = NO; - -static NSString *spoolFolder = nil; - @interface NGImap4Connection (PrivateMethods) - (NSString *) imap4FolderNameForURL: (NSURL *) url; @@ -78,42 +72,6 @@ static NSString *spoolFolder = nil; @implementation SOGoMailFolder -+ (void) initialize -{ - NSUserDefaults *ud; - NSString *aclStyleStr; - - if (aclStyle == undefined) - { - ud = [NSUserDefaults standardUserDefaults]; - aclStyleStr = [ud stringForKey: @"SOGoIMAPAclStyle"]; - if ([aclStyleStr isEqualToString: @"rfc2086"]) - aclStyle = rfc2086; - else - aclStyle = rfc4314; - - aclUsernamesAreQuoted - = [ud boolForKey: @"SOGoIMAPAclUsernamesAreQuoted"]; - aclConformsToIMAPExt - = [ud boolForKey: @"SOGoIMAPAclConformsToIMAPExt"]; - } - - if (!spoolFolder) - { - spoolFolder = [ud stringForKey:@"SOGoMailSpoolPath"]; - if (![spoolFolder length]) - spoolFolder = @"/tmp/"; - [spoolFolder retain]; - - NSLog(@"Note: using SOGo mail spool folder: %@", spoolFolder); - } -} - -+ (SOGoIMAPAclStyle) imapAclStyle -{ - return aclStyle; -} - - (void) _adjustOwner { SOGoMailAccount *mailAccount; @@ -342,7 +300,7 @@ static NSString *spoolFolder = nil; } - (WOResponse *) archiveUIDs: (NSArray *) uids - inContext: (id) localContext + inContext: (id) localContext { NSException *error; NSFileManager *fm; @@ -357,20 +315,18 @@ static NSString *spoolFolder = nil; #warning this method should be rewritten according to our coding styles spoolPath = [self userSpoolFolderPath]; - if ( ![self ensureSpoolFolderPath] ) { + if (![self ensureSpoolFolderPath]) { + [self errorWithFormat: @"spool directory '%@' doesn't exist", spoolPath]; error = [NSException exceptionWithHTTPStatus: 500 - reason: @"spoolFolderPath doesn't exist"]; + reason: @"spool directory does not exist"]; return (WOResponse *)error; } - - zipPath = [[NSUserDefaults standardUserDefaults] stringForKey: @"SOGoZipPath"]; - if (![zipPath length]) - zipPath = [NSString stringWithString: @"/usr/bin/zip"]; + zipPath = [[SOGoSystemDefaults sharedSystemDefaults] zipPath]; fm = [NSFileManager defaultManager]; - if ( ![fm fileExistsAtPath: zipPath] ) { + if (![fm fileExistsAtPath: zipPath]) { error = [NSException exceptionWithHTTPStatus: 500 - reason: @"zip not available"]; + reason: @"zip not available"]; return (WOResponse *)error; } @@ -527,16 +483,16 @@ static NSString *spoolFolder = nil; - (void) markForExpunge { - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *mailSettings; NSString *urlString; - ud = [[context activeUser] userSettings]; - mailSettings = [ud objectForKey: @"Mail"]; + us = [[context activeUser] userSettings]; + mailSettings = [us objectForKey: @"Mail"]; if (!mailSettings) { mailSettings = [NSMutableDictionary dictionaryWithCapacity: 1]; - [ud setObject: mailSettings forKey: @"Mail"]; + [us setObject: mailSettings forKey: @"Mail"]; } urlString = [self imap4URLString]; @@ -544,20 +500,20 @@ static NSString *spoolFolder = nil; isEqualToString: urlString]) { [mailSettings setObject: [self imap4URLString] - forKey: @"folderForExpunge"]; - [ud synchronize]; + forKey: @"folderForExpunge"]; + [us synchronize]; } } - (void) expungeLastMarkedFolder { - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *mailSettings; NSString *expungeURL; NSURL *folderURL; - ud = [[context activeUser] userSettings]; - mailSettings = [ud objectForKey: @"Mail"]; + us = [[context activeUser] userSettings]; + mailSettings = [us objectForKey: @"Mail"]; if (mailSettings) { expungeURL = [mailSettings objectForKey: @"folderForExpunge"]; @@ -568,7 +524,7 @@ static NSString *spoolFolder = nil; if (![[self imap4Connection] expungeAtURL: folderURL]) { [mailSettings removeObjectForKey: @"folderForExpunge"]; - [ud synchronize]; + [us synchronize]; } } } @@ -823,6 +779,7 @@ static NSString *spoolFolder = nil; NSEnumerator *acls; NSString *currentAcl; char character; + SOGoIMAPAclStyle aclStyle; imapAcls = [NSMutableString string]; acls = [sogoAcls objectEnumerator]; @@ -845,6 +802,7 @@ static NSString *spoolFolder = nil; character = 'a'; else { + aclStyle = [[self mailAccountFolder] imapAclStyle]; if (aclStyle == rfc2086) character = [self _rfc2086StyleRight: currentAcl]; else if (aclStyle == rfc4314) @@ -860,26 +818,6 @@ static NSString *spoolFolder = nil; return imapAcls; } -- (void) _unquoteACLUsernames -{ - NSMutableDictionary *newIMAPAcls; - NSEnumerator *usernames; - NSString *username, *unquoted; - - newIMAPAcls = [NSMutableDictionary new]; - - usernames = [[mailboxACL allKeys] objectEnumerator]; - while ((username = [usernames nextObject])) - { - unquoted = [username substringFromRange: - NSMakeRange(1, [username length] - 2)]; - [newIMAPAcls setObject: [mailboxACL objectForKey: username] - forKey: unquoted]; - } - [mailboxACL release]; - mailboxACL = newIMAPAcls; -} - - (void) _removeIMAPExtUsernames { NSMutableDictionary *newIMAPAcls; @@ -907,9 +845,7 @@ static NSString *spoolFolder = nil; mailboxACL = [[self imap4Connection] aclForMailboxAtURL: [self imap4URL]]; [mailboxACL retain]; - if (aclUsernamesAreQuoted) - [self _unquoteACLUsernames]; - if (aclConformsToIMAPExt) + if ([[self mailAccountFolder] imapAclConformsToIMAPExt]) [self _removeIMAPExtUsernames]; } @@ -1093,12 +1029,15 @@ static NSString *spoolFolder = nil; - (NSString *) userSpoolFolderPath { - NSString *login; + NSString *login, *mailSpoolPath; + SOGoUser *currentUser; - login = [[context activeUser] login]; + currentUser = [context activeUser]; + login = [currentUser login]; + mailSpoolPath = [[currentUser domainDefaults] mailSpoolPath]; return [NSString stringWithFormat: @"%@/%@", - spoolFolder, login]; + mailSpoolPath, login]; } - (BOOL) ensureSpoolFolderPath @@ -1107,7 +1046,8 @@ static NSString *spoolFolder = nil; fm = [NSFileManager defaultManager]; - return ([fm createDirectoriesAtPath: [self userSpoolFolderPath] attributes:nil]); + return ([fm createDirectoriesAtPath: [self userSpoolFolderPath] + attributes: nil]); } - (NSString *) displayName diff --git a/SoObjects/Mailer/SOGoMailForward.m b/SoObjects/Mailer/SOGoMailForward.m index be2450393..f2a127f12 100644 --- a/SoObjects/Mailer/SOGoMailForward.m +++ b/SoObjects/Mailer/SOGoMailForward.m @@ -23,8 +23,9 @@ #import #import -#import -#import +#import +#import +#import #import "SOGoMailObject+Draft.h" #import "SOGoMailForward.h" @@ -35,7 +36,7 @@ { if ((self = [super init])) { - NSUserDefaults *ud; + SOGoUserDefaults *ud; ud = [[context activeUser] userDefaults]; htmlComposition = [[ud objectForKey: @"ComposeMessagesType"] isEqualToString: @"html"]; @@ -213,8 +214,10 @@ - (NSString *) signature { NSString *signature, *mailSignature; + SOGoUserDefaults *ud; - signature = [[context activeUser] signature]; + ud = [[context activeUser] userDefaults]; + signature = [ud mailSignature]; if ([signature length]) mailSignature = [NSString stringWithFormat: @"-- \n%@", signature]; else diff --git a/SoObjects/Mailer/SOGoMailObject+Draft.m b/SoObjects/Mailer/SOGoMailObject+Draft.m index 030b6bdff..7ac01e373 100644 --- a/SoObjects/Mailer/SOGoMailObject+Draft.m +++ b/SoObjects/Mailer/SOGoMailObject+Draft.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -33,6 +32,7 @@ #import #import +#import #import "NSString+Mail.h" #import "SOGoMailForward.h" @@ -43,20 +43,6 @@ @implementation SOGoMailObject (SOGoDraftObjectExtensions) -- (BOOL) useOutlookStyleReplies -{ - NSUserDefaults *ud; - static int useOutlookStyleReplies = -1; - - if (useOutlookStyleReplies == -1) - { - ud = [NSUserDefaults standardUserDefaults]; - useOutlookStyleReplies = [ud boolForKey: @"SOGoMailUseOutlookStyleReplies"]; - } - - return (useOutlookStyleReplies); -} - - (NSString *) subjectForReply { static NSString *replyPrefixes[] = { @@ -92,13 +78,11 @@ rawHtml: (BOOL) html { NSString *rc; - NSUserDefaults *ud; + SOGoUserDefaults *ud; BOOL htmlComposition; ud = [[context activeUser] userDefaults]; - htmlComposition = [[ud stringForKey: @"ComposeMessagesType"] - isEqualToString: @"html"]; - + htmlComposition = [[ud mailComposeMessageType] isEqualToString: @"html"]; if (html && !htmlComposition) rc = [raw htmlToText]; else if (!html && htmlComposition) @@ -164,19 +148,19 @@ - (NSString *) contentForReply { - SOGoUser *currentUser; NSString *pageName; SOGoMailReply *page; + SOGoUserDefaults *userDefaults; - currentUser = [context activeUser]; + userDefaults = [[context activeUser] userDefaults]; pageName = [NSString stringWithFormat: @"SOGoMail%@Reply", - [currentUser language]]; + [userDefaults language]]; page = [[WOApplication application] pageWithName: pageName inContext: context]; [page setSourceMail: self]; - [page setOutlookMode: [self useOutlookStyleReplies]]; - [page setReplyPlacement: [currentUser replyPlacement]]; - [page setSignaturePlacement: [currentUser signaturePlacement]]; + [page setOutlookMode: [userDefaults mailUseOutlookStyleReplies]]; + [page setReplyPlacement: [userDefaults mailReplyPlacement]]; + [page setSignaturePlacement: [userDefaults mailSignaturePlacement]]; return [[page generateResponse] contentAsString]; } @@ -229,13 +213,13 @@ - (NSString *) contentForInlineForward { - SOGoUser *currentUser; + SOGoUserDefaults *ud; NSString *pageName; SOGoMailForward *page; - currentUser = [context activeUser]; + ud = [[context activeUser] userDefaults]; pageName = [NSString stringWithFormat: @"SOGoMail%@Forward", - [currentUser language]]; + [ud language]]; page = [[WOApplication application] pageWithName: pageName inContext: context]; [page setSourceMail: self]; diff --git a/SoObjects/Mailer/SOGoMailObject.m b/SoObjects/Mailer/SOGoMailObject.m index 6c9b3c32f..9b8e5fd80 100644 --- a/SoObjects/Mailer/SOGoMailObject.m +++ b/SoObjects/Mailer/SOGoMailObject.m @@ -26,7 +26,6 @@ #import #import #import -#import #import #import @@ -43,11 +42,12 @@ #import #import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import #import "NSString+Mail.h" #import "NSData+Mail.h" @@ -64,48 +64,30 @@ static NSArray *coreInfoKeys = nil; static NSString *mailETag = nil; static BOOL heavyDebug = NO; -static BOOL fetchHeader = YES; static BOOL debugOn = NO; static BOOL debugBodyStructure = NO; static BOOL debugSoParts = NO; + (void) initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - if ((fetchHeader = ([ud boolForKey: @"SOGoDoNotFetchMailHeader"] ? NO : YES))) - NSLog(@"Note: fetching full mail header."); - else - NSLog(@"Note: not fetching full mail header: 'SOGoDoNotFetchMailHeader'"); - - /* Note: see SOGoMailManager.m for allowed IMAP4 keys */ - /* Note: "BODY" actually returns the structure! */ - if (fetchHeader) { - coreInfoKeys = [[NSArray alloc] initWithObjects: - @"FLAGS", @"ENVELOPE", @"BODYSTRUCTURE", - @"RFC822.SIZE", - @"RFC822.HEADER", - // not yet supported: @"INTERNALDATE", - nil]; - } - else { - coreInfoKeys = [[NSArray alloc] initWithObjects: - @"FLAGS", @"ENVELOPE", @"BODYSTRUCTURE", - @"RFC822.SIZE", - // not yet supported: @"INTERNALDATE", - nil]; - } + if (!coreInfoKeys) + { + /* Note: see SOGoMailManager.m for allowed IMAP4 keys */ + coreInfoKeys = [[NSArray alloc] initWithObjects: + @"FLAGS", @"ENVELOPE", @"BODYSTRUCTURE", + @"RFC822.SIZE", + @"RFC822.HEADER", + // not yet supported: @"INTERNALDATE", + nil]; - if (![[ud objectForKey: @"SOGoMailDisableETag"] boolValue]) { - mailETag = [[NSString alloc] initWithFormat: @"\"imap4url_%d_%d_%03d\"", - UIX_MAILER_MAJOR_VERSION, - UIX_MAILER_MINOR_VERSION, - UIX_MAILER_SUBMINOR_VERSION]; - NSLog(@"Note(SOGoMailObject): using constant etag for mail parts: '%@'", - mailETag); - } - else - NSLog(@"Note(SOGoMailObject): etag caching disabled!"); + /* The following disabled code should not be needed, except if we use + annotations (see davEntityTag below) */ + // if (![[ud objectForKey: @"SOGoMailDisableETag"] boolValue]) { + mailETag = [[NSString alloc] initWithFormat: @"\"imap4url_%d_%d_%03d\"", + UIX_MAILER_MAJOR_VERSION, + UIX_MAILER_MINOR_VERSION, + UIX_MAILER_SUBMINOR_VERSION]; + } } - (void) dealloc @@ -276,12 +258,12 @@ static BOOL debugSoParts = NO; - (NSCalendarDate *) date { - NSTimeZone *userTZ; + SOGoUserDefaults *ud; NSCalendarDate *date; - userTZ = [[context activeUser] timeZone]; + ud = [[context activeUser] userDefaults]; date = [[self envelope] date]; - [date setTimeZone: userTZ]; + [date setTimeZone: [ud timeZone]]; return date; } diff --git a/SoObjects/Mailer/SOGoMailReply.m b/SoObjects/Mailer/SOGoMailReply.m index ae3fefea8..e29485437 100644 --- a/SoObjects/Mailer/SOGoMailReply.m +++ b/SoObjects/Mailer/SOGoMailReply.m @@ -26,7 +26,6 @@ #import #import -#import #import "SOGoMailObject+Draft.h" #import "SOGoMailReply.h" diff --git a/SoObjects/SOGo/GNUmakefile b/SoObjects/SOGo/GNUmakefile index 6f359b925..a54b1e664 100644 --- a/SoObjects/SOGo/GNUmakefile +++ b/SoObjects/SOGo/GNUmakefile @@ -26,9 +26,10 @@ SOGo_HEADER_FILES = \ SOGoUserManager.h \ LDAPSource.h \ SQLSource.h \ - SOGoUserDefaults.h \ + SOGoUserProfile.h \ SOGoDateFormatter.h \ SOGoPermissions.h \ + SOGoStartupLogger.h \ iCalEntityObject+Utilities.h \ NSArray+DAV.h \ NSArray+Utilities.h \ @@ -75,12 +76,20 @@ SOGo_OBJC_FILES = \ SOGoParentFolder.m \ SOGoUserFolder.m \ \ + SOGoDefaultsSource.m \ + SOGoSystemDefaults.m \ + SOGoDomainDefaults.m \ + SOGoUserDefaults.m \ + SOGoUserSettings.m \ + \ SOGoDateFormatter.m \ SOGoPermissions.m \ + SOGoStartupLogger.m \ SOGoUserManager.m \ LDAPSource.m \ SQLSource.m \ - SOGoUserDefaults.m \ + SOGoUserProfile.m \ + SOGoSQLUserProfile.m \ iCalEntityObject+Utilities.m \ NSArray+DAV.m \ NSArray+Utilities.m \ @@ -115,6 +124,7 @@ SOGo_OBJC_FILES = \ WOContext+SOGo.m SOGo_RESOURCE_FILES = \ + SOGoDefaults.plist \ DAVReportMap.plist ifeq ($(ldap_config),yes) diff --git a/SoObjects/SOGo/GNUmakefile.preamble b/SoObjects/SOGo/GNUmakefile.preamble index 97419b750..7a088517f 100644 --- a/SoObjects/SOGo/GNUmakefile.preamble +++ b/SoObjects/SOGo/GNUmakefile.preamble @@ -2,6 +2,9 @@ SOGo_INCLUDE_DIRS += -I.. -I../.. -DSOGO_MAJOR_VERSION="\"$(MAJOR_VERSION)\"" -DSOGO_MINOR_VERSION="\"$(MINOR_VERSION)\"" +ADDITIONAL_CPPFLAGS += \ + -DSOGO_LIBDIR="\"$(SOGO_LIBDIR)\"" + SOGo_LIBRARIES_DEPEND_UPON += \ -L../../OGoContentStore/$(GNUSTEP_OBJ_DIR)/ \ -L../../SOPE/NGCards/$(GNUSTEP_OBJ_DIR)/ \ diff --git a/SoObjects/SOGo/LDAPSource.h b/SoObjects/SOGo/LDAPSource.h index 3868a5e7e..2cd3bdb13 100644 --- a/SoObjects/SOGo/LDAPSource.h +++ b/SoObjects/SOGo/LDAPSource.h @@ -34,6 +34,9 @@ @interface LDAPSource : NSObject { + int queryLimit; + int queryTimeout; + NSString *sourceID; NSString *bindDN; NSString *hostname; @@ -51,15 +54,15 @@ NSString *IMAPHostField; NSString *bindFields; + NSString *domain; + NSString *contactInfoAttribute; + NSString *domainAttribute; + NSDictionary *modulesConstraints; NSMutableArray *searchAttributes; } -+ (id) sourceFromUDSource: (NSDictionary *) udSource; - -- (id) initFromUDSource: (NSDictionary *) udSource; - - (void) setBindDN: (NSString *) newBindDN password: (NSString *) newBindPassword hostname: (NSString *) newBindHostname @@ -74,22 +77,13 @@ IMAPHostField: (NSString *) newIMAPHostField andBindFields: (NSString *) newBindFields; -- (BOOL) checkLogin: (NSString *) login - andPassword: (NSString *) password; - - (NSString *) lookupLoginByDN: (NSString *) theDN; -- (NSDictionary *) lookupContactEntry: (NSString *) theID; -- (NSDictionary *) lookupContactEntryWithUIDorEmail: (NSString *) entryID; - - (NGLdapEntry *) lookupGroupEntryByUID: (NSString *) theUID; - (NGLdapEntry *) lookupGroupEntryByEmail: (NSString *) theEmail; - (NGLdapEntry *) lookupGroupEntryByAttribute: (NSString *) theAttribute andValue: (NSString *) theValue; -- (NSArray *) allEntryIDs; -- (NSArray *) fetchContactsMatching: (NSString *) filter; -- (NSString *) sourceID; - (NSString *) baseDN; @end diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index 112fe2440..bf5fc8977 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -22,9 +22,7 @@ #import #import -#import #import -#import #import #import @@ -34,35 +32,21 @@ #import "NSArray+Utilities.h" #import "NSString+Utilities.h" +#import "SOGoDomainDefaults.h" +#import "SOGoSystemDefaults.h" #import "LDAPSource.h" #define SafeLDAPCriteria(x) [[x stringByReplacingString: @"\\" withString: @"\\\\"] \ stringByReplacingString: @"'" withString: @"\\'"] static NSArray *commonSearchFields; -static NSString *LDAPContactInfoAttribute = nil; -static int timeLimit; -static int sizeLimit; - -#if defined(THREADSAFE) -static NSLock *lock; -#endif @implementation LDAPSource + (void) initialize { - NSUserDefaults *ud; - if (!commonSearchFields) { - ud = [NSUserDefaults standardUserDefaults]; - LDAPContactInfoAttribute - = [ud stringForKey: @"SOGoLDAPContactInfoAttribute"]; - [LDAPContactInfoAttribute retain]; - sizeLimit = [ud integerForKey: @"SOGoLDAPQueryLimit"]; - timeLimit = [ud integerForKey: @"SOGoLDAPQueryTimeout"]; - commonSearchFields = [NSArray arrayWithObjects: @"title", @"company", @@ -134,18 +118,16 @@ static NSLock *lock; @"proxyaddresses", nil]; [commonSearchFields retain]; - -#if defined(THREADSAFE) - lock = [NSLock new]; -#endif } } + (id) sourceFromUDSource: (NSDictionary *) udSource + inDomain: (NSString *) domain { id newSource; - newSource = [[self alloc] initFromUDSource: udSource]; + newSource = [[self alloc] initFromUDSource: udSource + inDomain: domain]; [newSource autorelease]; return newSource; @@ -161,6 +143,7 @@ static NSLock *lock; encryption = nil; password = nil; sourceID = nil; + domain = nil; baseDN = nil; IDField = @"cn"; /* the first part of a user DN */ @@ -201,29 +184,77 @@ static NSLock *lock; } - (id) initFromUDSource: (NSDictionary *) udSource + inDomain: (NSString *) sourceDomain { - self = [self init]; + NSString *udDomainAttribute; + SOGoDomainDefaults *dd; + NSNumber *udQueryLimit, *udQueryTimeout; - ASSIGN (sourceID, [udSource objectForKey: @"id"]); + if ((self = [self init])) + { + ASSIGN (sourceID, [udSource objectForKey: @"id"]); - [self setBindDN: [udSource objectForKey: @"bindDN"] - password: [udSource objectForKey: @"bindPassword"] - hostname: [udSource objectForKey: @"hostname"] - port: [udSource objectForKey: @"port"] - encryption: [udSource objectForKey: @"encryption"]]; - [self setBaseDN: [udSource objectForKey: @"baseDN"] - IDField: [udSource objectForKey: @"IDFieldName"] - CNField: [udSource objectForKey: @"CNFieldName"] - UIDField: [udSource objectForKey: @"UIDFieldName"] - mailFields: [udSource objectForKey: @"MailFieldNames"] + [self setBindDN: [udSource objectForKey: @"bindDN"] + password: [udSource objectForKey: @"bindPassword"] + hostname: [udSource objectForKey: @"hostname"] + port: [udSource objectForKey: @"port"] + encryption: [udSource objectForKey: @"encryption"]]; + [self setBaseDN: [udSource objectForKey: @"baseDN"] + IDField: [udSource objectForKey: @"IDFieldName"] + CNField: [udSource objectForKey: @"CNFieldName"] + UIDField: [udSource objectForKey: @"UIDFieldName"] + mailFields: [udSource objectForKey: @"MailFieldNames"] IMAPHostField: [udSource objectForKey: @"IMAPHostFieldName"] andBindFields: [udSource objectForKey: @"bindFields"]]; - ASSIGN (modulesConstraints, - [udSource objectForKey: @"ModulesConstraints"]); - ASSIGN (_filter, [udSource objectForKey: @"filter"]); - ASSIGN (_scope, ([udSource objectForKey: @"scope"] - ? [udSource objectForKey: @"scope"] - : (id)@"sub")); + + udDomainAttribute = [udSource objectForKey: @"domainAttribute"]; + if ([sourceDomain length]) + { + if ([udDomainAttribute length]) + { + [self errorWithFormat: @"cannot define 'domainAttribute'" + @" for a domain-based source (%@)", sourceID]; + [self release]; + self = nil; + } + else + { + dd = [SOGoDomainDefaults defaultsForDomain: sourceDomain]; + ASSIGN (domain, sourceDomain); + } + } + else + { + if ([udDomainAttribute length]) + ASSIGN (domainAttribute, udDomainAttribute); + dd = [SOGoSystemDefaults sharedSystemDefaults]; + } + + contactInfoAttribute + = [udSource objectForKey: @"SOGoLDAPContactInfoAttribute"]; + if (!contactInfoAttribute) + contactInfoAttribute = [dd ldapContactInfoAttribute]; + [contactInfoAttribute retain]; + + udQueryLimit = [udSource objectForKey: @"SOGoLDAPQueryLimit"]; + if (udQueryLimit) + queryLimit = [udQueryLimit intValue]; + else + queryLimit = [dd ldapQueryLimit]; + + udQueryTimeout = [udSource objectForKey: @"SOGoLDAPQueryTimeout"]; + if (udQueryTimeout) + queryTimeout = [udQueryTimeout intValue]; + else + queryTimeout = [dd ldapQueryTimeout]; + + ASSIGN (modulesConstraints, + [udSource objectForKey: @"ModulesConstraints"]); + ASSIGN (_filter, [udSource objectForKey: @"filter"]); + ASSIGN (_scope, ([udSource objectForKey: @"scope"] + ? [udSource objectForKey: @"scope"] + : (id)@"sub")); + } return self; } @@ -300,10 +331,10 @@ static NSLock *lock; [ldapConnection bindWithMethod: @"simple" binddn: bindDN credentials: password]; - if (sizeLimit > 0) - [ldapConnection setQuerySizeLimit: sizeLimit]; - if (timeLimit > 0) - [ldapConnection setQueryTimeLimit: timeLimit]; + if (queryLimit > 0) + [ldapConnection setQuerySizeLimit: queryLimit]; + if (queryTimeout > 0) + [ldapConnection setQueryTimeLimit: queryTimeout]; } else ldapConnection = nil; @@ -318,6 +349,11 @@ static NSLock *lock; return ldapConnection; } +- (NSString *) domain +{ + return domain; +} + /* user management */ - (EOQualifier *) _qualifierForBindFilter: (NSString *) uid { @@ -379,10 +415,6 @@ static NSLock *lock; NSString *userDN; NGLdapConnection *bindConnection; -#if defined(THREADSAFE) - [lock lock]; -#endif - didBind = NO; if ([loginToCheck length] > 0) @@ -391,8 +423,8 @@ static NSLock *lock; port: port]; if (![encryption length] || [self _setupEncryption: bindConnection]) { - if (timeLimit > 0) - [bindConnection setQueryTimeLimit: timeLimit]; + if (queryTimeout > 0) + [bindConnection setQueryTimeLimit: queryTimeout]; if (bindFields) userDN = [self _fetchUserDNForLogin: loginToCheck]; else @@ -413,10 +445,6 @@ static NSLock *lock; [bindConnection release]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif - return didBind; } @@ -510,8 +538,11 @@ static NSLock *lock; [searchAttributes addObjectsFromArray: commonSearchFields]; // Add SOGoLDAPContactInfoAttribute from user defaults - if ([LDAPContactInfoAttribute length]) - [searchAttributes addObjectUniquely: LDAPContactInfoAttribute]; + if ([contactInfoAttribute length]) + [searchAttributes addObjectUniquely: contactInfoAttribute]; + + if ([domainAttribute length]) + [searchAttributes addObjectUniquely: domainAttribute]; // Add IMAP hostname from user defaults if ([IMAPHostField length]) @@ -530,10 +561,6 @@ static NSLock *lock; NSArray *attributes; NSMutableArray *ids; -#if defined(THREADSAFE) - [lock lock]; -#endif - ids = [NSMutableArray array]; ldapConnection = [self _ldapConnection]; @@ -559,10 +586,6 @@ static NSLock *lock; [ids addObject: value]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif - return ids; } @@ -697,6 +720,31 @@ static NSLock *lock; if (!value) value = @""; [contactEntry setObject: value forKey: @"c_cn"]; + + if (contactInfoAttribute) + { + value = [[ldapEntry attributeWithName: contactInfoAttribute] + stringValueAtIndex: 0]; + if (!value) + value = @""; + } + else + value = @""; + [contactEntry setObject: value forKey: @"c_info"]; + + if (domainAttribute) + { + value = [[ldapEntry attributeWithName: domainAttribute] + stringValueAtIndex: 0]; + if (!value) + value = @""; + } + else if (domain) + value = domain; + else + value = @""; + [contactEntry setObject: value forKey: @"c_domain"]; + [self _fillEmailsOfEntry: ldapEntry intoContactEntry: contactEntry]; [self _fillConstraints: ldapEntry forModule: @"Calendar" intoContactEntry: (NSMutableDictionary *) contactEntry]; @@ -715,10 +763,6 @@ static NSLock *lock; EOQualifier *qualifier; NSArray *attributes; -#if defined(THREADSAFE) - [lock lock]; -#endif - contacts = [NSMutableArray array]; if ([match length] > 0) @@ -744,10 +788,6 @@ static NSLock *lock; [self _convertLDAPEntryToContact: currentEntry]]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif - return contacts; } @@ -761,10 +801,6 @@ static NSLock *lock; NSString *s; NSDictionary *contactEntry; -#if defined(THREADSAFE) - [lock lock]; -#endif - contactEntry = nil; if ([theID length] > 0) @@ -793,10 +829,6 @@ static NSLock *lock; contactEntry = [self _convertLDAPEntryToContact: ldapEntry]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif - return contactEntry; } @@ -809,10 +841,6 @@ static NSLock *lock; NSArray *attributes; NSDictionary *contactEntry; -#if defined(THREADSAFE) - [lock lock]; -#endif - contactEntry = nil; if ([uid length] > 0) @@ -839,10 +867,6 @@ static NSLock *lock; contactEntry = [self _convertLDAPEntryToContact: ldapEntry]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif - return contactEntry; } @@ -887,10 +911,6 @@ static NSLock *lock; NGLdapConnection *ldapConnection; NGLdapEntry *ldapEntry; -#if defined(THREADSAFE) - [lock lock]; -#endif - if ([theValue length] > 0) { ldapConnection = [self _ldapConnection]; @@ -898,7 +918,7 @@ static NSLock *lock; s = [NSString stringWithFormat: @"(%@='%@')", theAttribute, SafeLDAPCriteria (theValue)]; qualifier = [EOQualifier qualifierWithQualifierFormat: s]; - + // We look for additional attributes - the ones related to group // membership attributes = [NSMutableArray arrayWithArray: [self _searchAttributes]]; @@ -925,10 +945,6 @@ static NSLock *lock; else ldapEntry = nil; -#if defined(THREADSAFE) - [lock unlock]; -#endif - return ldapEntry; } diff --git a/SoObjects/SOGo/NSString+Utilities.h b/SoObjects/SOGo/NSString+Utilities.h index 7b5b9d5ff..c3b37f2f3 100644 --- a/SoObjects/SOGo/NSString+Utilities.h +++ b/SoObjects/SOGo/NSString+Utilities.h @@ -62,6 +62,8 @@ - (BOOL) boolValue; #endif +- (int) timeValue; + // LDIF - (BOOL) _isLDIFSafe; diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m index 28720afce..e57202c16 100644 --- a/SoObjects/SOGo/NSString+Utilities.m +++ b/SoObjects/SOGo/NSString+Utilities.m @@ -385,6 +385,24 @@ static NSMutableCharacterSet *urlStartChars = nil; } #endif +- (int) timeValue +{ + int i, time; + + if ([self length] > 0) + { + i = [self rangeOfString: @":"].location; + if (i == NSNotFound) + time = [self intValue]; + else + time = [[self substringToIndex: i] intValue]; + } + else + time = -1; + + return time; +} + static NSMutableCharacterSet *safeLDIFChars = nil; static NSMutableCharacterSet *safeLDIFStartChars = nil; diff --git a/SoObjects/SOGo/SOGoCache.h b/SoObjects/SOGo/SOGoCache.h index 2c6177642..74ba8b152 100644 --- a/SoObjects/SOGo/SOGoCache.h +++ b/SoObjects/SOGo/SOGoCache.h @@ -41,12 +41,13 @@ NSMutableDictionary *localCache; NSMutableDictionary *cache; NSMutableDictionary *users; + float cleanupInterval; + NSString *memcachedServerName; @private memcached_server_st *servers; memcached_st *handle; } -+ (NSTimeInterval) cleanupInterval; + (SOGoCache *) sharedCache; - (void) killCache; diff --git a/SoObjects/SOGo/SOGoCache.m b/SoObjects/SOGo/SOGoCache.m index 8f99d2083..6ad80e953 100644 --- a/SoObjects/SOGo/SOGoCache.m +++ b/SoObjects/SOGo/SOGoCache.m @@ -36,95 +36,43 @@ #import #import #import -#import #import #import #import "SOGoObject.h" +#import "SOGoSystemDefaults.h" #import "SOGoUser.h" -#import "SOGoUserDefaults.h" +#import "SOGoUserProfile.h" #import "SOGoCache.h" -// We define the default value for cleaning up cached -// users' preferences. This value should be relatively -// high to avoid useless database calls. -static NSTimeInterval cleanupInterval = 0; -static NSString *memcachedServerName; - -#if defined(THREADSAFE) -static NSLock *lock; -#endif - @implementation SOGoCache -+ (void) initialize -{ - NSString *cleanupSetting; - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - // We fire our timer that will cleanup cache entries - cleanupSetting = [ud objectForKey: @"SOGoCacheCleanupInterval"]; - if (cleanupSetting && [cleanupSetting doubleValue] > 0.0) - cleanupInterval = [cleanupSetting doubleValue]; - if (cleanupInterval == 0.0) - cleanupInterval = 300; - - [self logWithFormat: @"Cache cleanup interval set every %f seconds for memcached", - cleanupInterval]; - - ASSIGN (memcachedServerName, [ud stringForKey: @"SOGoMemCachedHost"]); - if (!memcachedServerName) - memcachedServerName = @"localhost"; - [self logWithFormat: @"Using host '%@' as memcached server", - memcachedServerName]; - -#if defined(THREADSAFE) - lock = [NSLock new]; -#endif -} - -+ (NSTimeInterval) cleanupInterval -{ - return cleanupInterval; -} - + (SOGoCache *) sharedCache { static SOGoCache *sharedCache = nil; -#if defined(THREADSAFE) - [lock lock]; -#endif if (!sharedCache) sharedCache = [self new]; -#if defined(THREADSAFE) - [lock unlock]; -#endif return sharedCache; } - (void) killCache { -#if defined(THREADSAFE) - [lock lock]; -#endif [cache removeAllObjects]; // This is essential for refetching the cached values in case something has changed // accross various sogod processes [users removeAllObjects]; [localCache removeAllObjects]; -#if defined(THREADSAFE) - [lock unlock]; -#endif } - (id) init { + SOGoSystemDefaults *sd; + if ((self = [super init])) { memcached_return error; @@ -145,6 +93,19 @@ static NSLock *lock; { #warning We could also make the port number configurable and even make use \ of NGNetUtilities for that. + + sd = [SOGoSystemDefaults sharedSystemDefaults]; + // We define the default value for cleaning up cached users' + // preferences. This value should be relatively high to avoid + // useless database calls. + + cleanupInterval = [sd cacheCleanupInterval]; + ASSIGN (memcachedServerName, [sd memcachedHost]); + + [self logWithFormat: @"Cache cleanup interval set every %f seconds", + cleanupInterval]; + [self logWithFormat: @"Using host '%@' as server", + memcachedServerName]; servers = memcached_server_list_append(NULL, [memcachedServerName UTF8String], @@ -160,6 +121,7 @@ static NSLock *lock; { memcached_server_free(servers); memcached_free(handle); + [memcachedServerName release]; [cache release]; [users release]; [localCache release]; @@ -206,16 +168,10 @@ static NSLock *lock; inContainer: [container container]]; fullPath = [self _pathFromObject: container withName: name]; -#if defined(THREADSAFE) - [lock lock]; -#endif if (![cache objectForKey: fullPath]) { [cache setObject: object forKey: fullPath]; } -#if defined(THREADSAFE) - [lock unlock]; -#endif } } @@ -235,13 +191,7 @@ static NSLock *lock; - (void) registerUser: (SOGoUser *) user withName: (NSString *) userName { -#if defined(THREADSAFE) - [lock lock]; -#endif [users setObject: user forKey: userName]; -#if defined(THREADSAFE) - [lock unlock]; -#endif } - (id) userNamed: (NSString *) name diff --git a/SoObjects/SOGo/SOGoDAVAuthenticator.m b/SoObjects/SOGo/SOGoDAVAuthenticator.m index 665cc1cec..aaf2f1ceb 100644 --- a/SoObjects/SOGo/SOGoDAVAuthenticator.m +++ b/SoObjects/SOGo/SOGoDAVAuthenticator.m @@ -21,7 +21,6 @@ #import #import -#import #import #import diff --git a/SoObjects/SOGo/SOGoDateFormatter.m b/SoObjects/SOGo/SOGoDateFormatter.m index be1772a95..a31af79ee 100644 --- a/SoObjects/SOGo/SOGoDateFormatter.m +++ b/SoObjects/SOGo/SOGoDateFormatter.m @@ -19,9 +19,9 @@ 02111-1307, USA. */ -#import #import -#import +#import +#import /* for NSXXXFormatString, ... */ #import "SOGoDateFormatter.h" diff --git a/SoObjects/SOGo/SOGoDefaults.plist b/SoObjects/SOGo/SOGoDefaults.plist new file mode 100644 index 000000000..d57059a25 --- /dev/null +++ b/SoObjects/SOGo/SOGoDefaults.plist @@ -0,0 +1,64 @@ +{ + WOWorkersCount = 1; + SxVMemLimit = 384; + WOLogFile = "/var/log/sogo/sogo.log"; + WOPidFile = "/var/log/run/sogo.pid"; + + SOGoZipPath = "/usr/bin/zip"; + + WOUseRelativeURLs = YES; + WOMessageUseUTF8 = YES; + WOParsersUseUTF8 = YES; + NGUseUTF8AsURLEncoding = YES; + + SOGoCacheCleanupInterval = 300.0; + SOGoMemcachedHost = "localhost"; + + SOGoUIxDebugEnabled = NO; + + SOGoLDAPContactInfoAttribute = "description"; + + SOGoMailingMechanism = "sendmail"; + SOGoSMTPServer = "localhost"; + SOGoMailSpoolPath = "/tmp"; + + SOGoLoginModule = "Mail"; + SOGoLanguage = "English"; + SOGoSupportedLanguages = ( "Czech", "Welsh", "English", "Spanish", + "French", "German", "Italian", "Hungarian", + "Dutch", "BrazilianPortuguese", "Russian", + "Swedish"); + + SOGoTimeZone = "UTC"; + + SOGoDayStartTime = "8"; + SOGoDayEndTime = "18"; + SOGoTimeFormat = "%H:00"; + + SOGoIMAPServer = "localhost"; + SOGoFirstDayOfWeek = 0; + SOGoFirstWeekOfYear = "January1"; + + SOGoMailDomain = "localhost"; + SOGoMailMessageCheck = "manually"; + SOGoMailMessageForwarding = "inline"; + SOGoMailReplyPlacement = "below"; + SOGoMailSignaturePlacement = "below"; + SOGoMailPollingIntervals = ( 1, 2, 5, 10, 20, 30, 30 ); + SOGoMailComposeMessageType = "text"; + SOGoMailListViewColumnsOrder = ( "Flagged", "Attachment", "Subject", + "From", "Unread", "Date", "Priority", + "Size" ); + + SOGoSentFolderName = "Sent"; + SOGoDraftsFolderName = "Drafts"; + SOGoTrashFolderName = "Trash"; + SOGoOtherUsersFolderName = "Other Users"; + SOGoSharedFolderName = "Shared Folders"; + + SOGoCalendarShouldDisplayWeekend = YES; + SOGoFreeBusyDefaultInterval = ( 7, 7 ); + + SOGoReminderEnabled = YES; + SOGoRemindWithASound = YES; +} diff --git a/SoObjects/SOGo/SOGoDefaultsSource.h b/SoObjects/SOGo/SOGoDefaultsSource.h new file mode 100644 index 000000000..f2c0b9f95 --- /dev/null +++ b/SoObjects/SOGo/SOGoDefaultsSource.h @@ -0,0 +1,81 @@ +/* SOGoDefaultsSource.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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. + */ + +/* A proxy to a NSUserDefauts intance (or compatible) and to a parent + source. */ + +#ifndef SOGODEFAULTSSOURCE_H +#define SOGODEFAULTSSOURCE_H + +@class NSArray; +@class NSData; +@class NSDictionary; +@class NSString; + +extern NSString *SOGoDefaultsSourceInvalidSource; +extern NSString *SOGoDefaultsSourceUnmutableSource; + +@interface SOGoDefaultsSource : NSObject +{ + id source; + SOGoDefaultsSource *parentSource; + BOOL isMutable; +} + ++ (id) defaultsSourceWithSource: (id) newSource + andParentSource: (SOGoDefaultsSource *) newParentSource; + +- (void) setSource: (id) newSource; +- (id) source; + +- (void) setParentSource: (SOGoDefaultsSource *) newParentSource; + +/* db management */ +- (BOOL) migrate; +- (BOOL) migrateOldDefaultsWithDictionary: (NSDictionary *) migratedKeys; + +- (BOOL) synchronize; + +/* accessors */ +- (void) setObject: (id) value forKey: (NSString *) key; +- (id) objectForKey: (NSString *) objectKey; +- (void) removeObjectForKey: (NSString *) key; + +- (void) setBool: (BOOL) value forKey: (NSString *) key; +- (BOOL) boolForKey: (NSString *) key; + +- (void) setFloat: (float) value forKey: (NSString *) key; +- (float) floatForKey: (NSString *) key; + +- (NSArray *) arrayForKey: (NSString *) key; +- (NSArray *) stringArrayForKey: (NSString *) key; + +- (void) setInteger: (int) value forKey: (NSString *) key; +- (int) integerForKey: (NSString *) key; + +- (id) dictionaryForKey: (NSString *) key; +- (NSData *) dataForKey: (NSString *) key; +- (NSString *) stringForKey: (NSString *) key; + +@end + +#endif /* SOGODEFAULTSSOURCE_H */ diff --git a/SoObjects/SOGo/SOGoDefaultsSource.m b/SoObjects/SOGo/SOGoDefaultsSource.m new file mode 100644 index 000000000..2769af252 --- /dev/null +++ b/SoObjects/SOGo/SOGoDefaultsSource.m @@ -0,0 +1,248 @@ +/* SOGoDefaultsSource.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 +#import +#import +#import +#import + +#import + +#define NEEDS_DEFAULTS_SOURCE_INTERNAL 1 +#import "SOGoDefaultsSource.h" + +NSString *SOGoDefaultsSourceInvalidSource = @"SOGoDefaultsSourceInvalidSource"; +NSString *SOGoDefaultsSourceUnmutableSource = @"SOGoDefaultsSourceUnmutableSource"; + +@implementation SOGoDefaultsSource + ++ (id) defaultsSourceWithSource: (id) newSource + andParentSource: (SOGoDefaultsSource *) newParentSource +{ + SOGoDefaultsSource *sogoDefaultsSource; + + sogoDefaultsSource = [self new]; + [sogoDefaultsSource autorelease]; + [sogoDefaultsSource setSource: newSource]; + [sogoDefaultsSource setParentSource: newParentSource]; + + if ([sogoDefaultsSource migrate]) + [sogoDefaultsSource synchronize]; + + return sogoDefaultsSource; +} + +- (id) init +{ + if ((self = [super init])) + { + source = nil; + parentSource = nil; + isMutable = NO; + } + + return self; +} + +- (void) dealloc +{ + [source release]; + [parentSource release]; + [super dealloc]; +} + +- (void) setSource: (id) newSource +{ + if ([newSource respondsToSelector: @selector (objectForKey:)]) + { + ASSIGN (source, newSource); + isMutable = [source respondsToSelector: @selector (setObject:forKey:)]; + } + else + [NSException raise: SOGoDefaultsSourceInvalidSource + format: @"UserDefaults source '%@'" + @" does not respond to 'object:forKey:'", newSource]; +} + +- (id) source +{ + return source; +} + +- (void) setParentSource: (SOGoDefaultsSource *) newParentSource +{ + ASSIGN (parentSource, newParentSource); +} + +- (void) setObject: (id) value + forKey: (NSString *) key +{ + if (isMutable) + [source setObject: value forKey: key]; + else + [NSException raise: SOGoDefaultsSourceUnmutableSource + format: @"UserDefaults source '%@' is not mutable", source]; +} + +- (id) objectForKey: (NSString *) objectKey +{ + id objectForKey; + + objectForKey = [source objectForKey: objectKey]; + if (!objectForKey) + objectForKey = [parentSource objectForKey: objectKey]; + + return objectForKey; +} + +- (void) removeObjectForKey: (NSString *) key +{ + [source removeObjectForKey: key]; +} + +- (void) setBool: (BOOL) value + forKey: (NSString *) key +{ + [self setObject: [NSNumber numberWithBool: value] + forKey: key]; +} + +- (BOOL) boolForKey: (NSString *) key +{ + return [[self objectForKey: key] boolValue]; +} + +- (void) setFloat: (float) value + forKey: (NSString *) key +{ + [self setObject: [NSNumber numberWithFloat: value] + forKey: key]; +} + +- (float) floatForKey: (NSString *) key +{ + return [[self objectForKey: key] floatValue]; +} + +- (void) setInteger: (int) value + forKey: (NSString *) key +{ + [self setObject: [NSString stringWithFormat: @"%d", value] + forKey: key]; +} + +- (int) integerForKey: (NSString *) key +{ + return [[self objectForKey: key] intValue]; +} + +#warning TODO: type checking +- (NSArray *) arrayForKey: (NSString *) key +{ + return [self objectForKey: key]; +} + +- (NSArray *) stringArrayForKey: (NSString *) key +{ + return [self objectForKey: key]; +} + +- (NSData *) dataForKey: (NSString *) key +{ + return [self objectForKey: key]; +} + +- (NSString *) stringForKey: (NSString *) key +{ + return [self objectForKey: key]; +} + +/* Dictionaries are a special case for which we don't allow searches in the + parent source. Each level can thus have its own set of dictionary values. */ +- (id) dictionaryForKey: (NSString *) objectKey +{ + id objectForKey; + + objectForKey = [source objectForKey: objectKey]; + + return objectForKey; +} + +- (BOOL) migrate +{ + return NO; +} + +- (BOOL) migrateOldDefaultsWithDictionary: (NSDictionary *) migratedKeys +{ + NSArray *allKeys; + id currentValue, existingValue; + NSString *oldName, *newName; + int count, max; + BOOL requireSync; + + requireSync = NO; + + allKeys = [migratedKeys allKeys]; + max = [allKeys count]; + for (count = 0; count < max; count++) + { + oldName = [allKeys objectAtIndex: count]; + currentValue = [source objectForKey: oldName]; + if (currentValue) + { + newName = [migratedKeys objectForKey: oldName]; + existingValue = [source objectForKey: newName]; + if (existingValue) + [self errorWithFormat: @"both old and new defaults key" + @" '%@' '%@' exist. Migration skipped.", oldName, newName]; + else + { + requireSync = YES; + [source setObject: currentValue forKey: newName]; + [source removeObjectForKey: oldName]; + [self warnWithFormat: @"defaults key '%@' was renamed to '%@'", + oldName, newName]; + } + } + } + + return requireSync; +} + +- (BOOL) synchronize +{ + BOOL rc; + + if ([source respondsToSelector: @selector (synchronize)]) + rc = [source synchronize]; + else + { + [self errorWithFormat: @"current source cannot synchronize defaults"]; + rc = NO; + } + + return rc; +} + +@end diff --git a/SoObjects/SOGo/SOGoDomainDefaults.h b/SoObjects/SOGo/SOGoDomainDefaults.h new file mode 100644 index 000000000..98eb5bd07 --- /dev/null +++ b/SoObjects/SOGo/SOGoDomainDefaults.h @@ -0,0 +1,69 @@ +/* SOGoDomainDefaults.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 SOGODOMAINDEFAULTS_H +#define SOGODOMAINDEFAULTS_H + +#import +#import + +@interface SOGoDomainDefaults : SOGoUserDefaults + ++ (SOGoDomainDefaults *) defaultsForDomain: (NSString *) domainId; + +- (NSString *) profileURL; +- (NSString *) folderInfoURL; + +- (NSArray *) superUsernames; + +- (NSArray *) userSources; + +- (NSString *) mailDomain; +- (NSString *) imapServer; +- (NSString *) imapAclStyle; +- (BOOL) imapAclConformsToIMAPExt; +- (BOOL) forceIMAPLoginWithEmail; +- (BOOL) forwardEnabled; +- (BOOL) vacationEnabled; +- (NSString *) otherUsersFolderName; +- (NSString *) sharedFolderName; +- (NSString *) mailingMechanism; +- (NSString *) smtpServer; +- (NSString *) mailSpoolPath; +- (float) softQuotaRatio; +- (BOOL) mailKeepDraftsAfterSend; +- (BOOL) mailAttachTextDocumentsInline; +- (NSArray *) mailListViewColumnsOrder; + +- (BOOL) aclSendEMailNotifications; +- (BOOL) appointmentSendEMailNotifications; +- (BOOL) foldersSendEMailNotifications; +- (NSArray *) calendarDefaultRoles; +- (NSArray *) contactsDefaultRoles; +- (NSArray *) mailPollingIntervals; + +- (NSArray *) freeBusyDefaultInterval; +- (int) davCalendarStartTimeLimit; + +@end + +#endif /* SOGODOMAINDEFAULTS_H */ diff --git a/SoObjects/SOGo/SOGoDomainDefaults.m b/SoObjects/SOGo/SOGoDomainDefaults.m new file mode 100644 index 000000000..e038e9e04 --- /dev/null +++ b/SoObjects/SOGo/SOGoDomainDefaults.m @@ -0,0 +1,285 @@ +/* SOGoDomainDefaults.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 +#import +#import +#import +#import +#import + +#define NEEDS_DEFAULTS_SOURCE_INTERNAL 1 +#import "SOGoSystemDefaults.h" + +#import "SOGoDomainDefaults.h" + +@implementation SOGoDomainDefaults + ++ (SOGoDomainDefaults *) defaultsForDomain: (NSString *) domainId +{ + NSDictionary *domainValues; + SOGoSystemDefaults *systemDefaults; + SOGoDomainDefaults *domainDefaults; + + domainDefaults = nil; + + if ([domainId length]) + { + systemDefaults = [SOGoSystemDefaults sharedSystemDefaults]; + domainValues = [[systemDefaults dictionaryForKey: @"domains"] + objectForKey: domainId]; + if ([domainValues isKindOfClass: [NSDictionary class]]) + { + domainDefaults + = [SOGoDomainDefaults defaultsSourceWithSource: domainValues + andParentSource: systemDefaults]; + } + } + + return domainDefaults; +} + +- (BOOL) migrate +{ + static NSDictionary *migratedKeys = nil; + + if (!migratedKeys) + { + migratedKeys + = [NSDictionary dictionaryWithObjectsAndKeys: + @"SOGoIMAPServer", @"SOGoFallbackIMAP4Server", + @"SOGoMailDomain", @"SOGoDefaultMailDomain", + @"SOGoLDAPContactInfoAttribute", @"LDAPContactInfoAttribute", + @"SOGoUserSources", @"SOGoLDAPSources", + @"SOGoMailKeepDraftsAfterSend", @"SOGoNoDraftDeleteAfterSend", + @"SOGoMailAttachTextDocumentsInline", @"SOGoShowTextAttachmentsInline", + nil]; + [migratedKeys retain]; + } + + /* we must not use a boolean operation, otherwise subsequent migrations will + not even occur in the case where rc = YES. */ + return ([self migrateOldDefaultsWithDictionary: migratedKeys] + | [super migrate]); +} + +- (NSArray *) userSources +{ + return [source objectForKey: @"SOGoUserSources"]; +} + +/* System-/Domain-level */ + +// SOGoDontUseETagsForMailViewer + +- (NSString *) profileURL +{ + return [self stringForKey: @"SOGoProfileURL"]; +} + +- (NSString *) folderInfoURL +{ + return [self stringForKey: @"OCSFolderInfoURL"]; +} + +- (NSString *) mailDomain +{ + return [self stringForKey: @"SOGoMailDomain"]; +} + +- (NSString *) imapServer +{ + return [self stringForKey: @"SOGoIMAPServer"]; +} + +#warning should be removed when we make use of imap namespace +- (NSString *) imapAclStyle +{ + return [self stringForKey: @"SOGoIMAPAclStyle"]; +} + +#warning this should be determined from the capabilities +/* http://www.tools.ietf.org/wg/imapext/draft-ietf-imapext-acl/ */ +- (BOOL) imapAclConformsToIMAPExt +{ + return [self boolForKey: @"SOGoIMAPAclConformsToIMAPExt"]; +} + +- (BOOL) aclSendEMailNotifications +{ + return [self boolForKey: @"SOGoACLsSendEMailNotifications"]; +} + +- (BOOL) appointmentSendEMailNotifications +{ + return [self boolForKey: @"SOGoAppointmentSendEMailNotifications"]; +} + +- (BOOL) foldersSendEMailNotifications +{ + return [self boolForKey: @"SOGoFoldersSendEMailNotifications"]; +} + +- (NSArray *) calendarDefaultRoles +{ + return [self stringArrayForKey: @"SOGoCalendarDefaultRoles"]; +} + +- (NSArray *) contactsDefaultRoles +{ + return [self stringArrayForKey: @"SOGoContactsDefaultRoles"]; +} + +- (BOOL) forceIMAPLoginWithEmail +{ + return [self boolForKey: @"SOGoForceIMAPLoginWithEmail"]; +} + +- (BOOL) forwardEnabled +{ + return [self boolForKey: @"SOGoForceIMAPLoginWithEmail"]; +} + +- (BOOL) vacationEnabled +{ + return [self boolForKey: @"SOGoForceIMAPLoginWithEmail"]; +} + +- (NSString *) mailingMechanism +{ + NSString *mailingMechanism; + + mailingMechanism = [self stringForKey: @"SOGoMailingMechanism"]; + if (!([mailingMechanism isEqualToString: @"sendmail"] + || [mailingMechanism isEqualToString: @"smtp"])) + { + [self logWithFormat: @"mechanism '%@' is invalid and" + @" should be set to 'sendmail' or 'smtp' instead", + mailingMechanism]; + mailingMechanism = nil; + } + + return mailingMechanism; +} + +- (NSArray *) mailPollingIntervals +{ + return [self arrayForKey: @"SOGoMailPollingIntervals"]; +} + +- (NSString *) otherUsersFolderName +{ + return [self stringForKey: @"SOGoOtherUsersFolderName"]; +} + +- (NSString *) sharedFolderName +{ + return [self stringForKey: @"SOGoSharedFolderName"]; +} + +- (NSString *) smtpServer +{ + return [self stringForKey: @"SOGoSMTPServer"]; +} + +- (NSString *) mailSpoolPath +{ + return [self stringForKey: @"SOGoMailSpoolPath"]; +} + +- (float) softQuotaRatio +{ + return [self floatForKey: @"SOGoSoftQuotaRatio"]; +} + +- (BOOL) mailKeepDraftsAfterSend +{ + return [self boolForKey: @"SOGoMailKeepDraftsAfterSend"]; +} + +- (BOOL) mailAttachTextDocumentsInline +{ + return [self boolForKey: @"SOGoMailAttachTextDocumentsInline"]; +} + +- (NSArray *) mailListViewColumnsOrder +{ + return [self stringArrayForKey: @"SOGoMailListViewColumnsOrder"]; +} + +- (NSArray *) superUsernames +{ + return [self stringArrayForKey: @"SOGoSuperUsernames"]; +} + +/* System-/Domain-/LDAP-level */ + +- (int) ldapQueryLimit +{ + return [self integerForKey: @"SOGoLDAPQueryLimit"]; +} + +- (int) ldapQueryTimeout +{ + return [self integerForKey: @"SOGoLDAPQueryTimeout"]; +} + +- (NSString *) ldapContactInfoAttribute +{ + return [self stringForKey: @"SOGoLDAPContactInfoAttribute"]; +} + +- (NSArray *) freeBusyDefaultInterval +{ + return [self arrayForKey: @"SOGoFreeBusyDefaultInterval"]; +} + +- (int) davCalendarStartTimeLimit +{ + return [self integerForKey: @"SOGoDAVCalendarStartTimeLimit"]; +} + +/* overriden methods */ +- (NSString *) language +{ + NSArray *browserLanguages, *supportedLanguages; + NSString *language; + WOContext *context; + + /* When we end up here, which means the active user has no language set, we + fetch the list of languages that are accepted by his/her browser and we + take the first of those which is supported. This ensures that the + resulting languages is always available. If not, we fallback on the + language of the domain or SOGo. */ + context = [[WOApplication application] context]; + browserLanguages = [[context request] browserLanguages]; + supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults] + supportedLanguages]; + language = [browserLanguages + firstObjectCommonWithArray: supportedLanguages]; + if (!(language && [language isKindOfClass: [NSString class]])) + language = [self stringForKey: @"SOGoLanguage"]; + + return language; +} + +@end diff --git a/SoObjects/SOGo/SOGoGCSFolder.m b/SoObjects/SOGo/SOGoGCSFolder.m index 18d667110..33bed506f 100644 --- a/SoObjects/SOGo/SOGoGCSFolder.m +++ b/SoObjects/SOGo/SOGoGCSFolder.m @@ -29,7 +29,6 @@ #import #import #import -#import #import #import @@ -54,8 +53,8 @@ #import #import #import -#import "NSDictionary+Utilities.h" +#import "NSDictionary+Utilities.h" #import "NSArray+Utilities.h" #import "NSArray+DAV.h" #import "NSObject+DAV.h" @@ -65,10 +64,13 @@ #import "DOMNode+SOGo.h" #import "SOGoCache.h" #import "SOGoContentObject.h" +#import "SOGoDomainDefaults.h" #import "SOGoGroup.h" #import "SOGoParentFolder.h" #import "SOGoPermissions.h" #import "SOGoUser.h" +#import "SOGoUserDefaults.h" +#import "SOGoUserSettings.h" #import "SOGoWebDAVAclManager.h" #import "WORequest+SOGo.h" #import "WOResponse+SOGo.h" @@ -76,7 +78,6 @@ #import "SOGoGCSFolder.h" static NSString *defaultUserID = @""; -static BOOL sendFolderAdvisories = NO; static NSArray *childRecordFields = nil; @implementation SOGoGCSFolder @@ -139,11 +140,6 @@ static NSArray *childRecordFields = nil; + (void) initialize { - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - - sendFolderAdvisories = [ud boolForKey: @"SOGoFoldersSendEMailNotifications"]; if (!childRecordFields) { childRecordFields = [NSArray arrayWithObjects: @"c_name", @"c_version", @@ -389,12 +385,14 @@ static NSArray *childRecordFields = nil; NSString *pageName; SOGoUser *user; SOGoFolderAdvisory *page; + NSString *language; - if (sendFolderAdvisories) + user = [SOGoUser userWithLogin: [self ownerInContext: context]]; + if ([[user domainDefaults] foldersSendEMailNotifications]) { - user = [SOGoUser userWithLogin: [self ownerInContext: context]]; + language = [[user userDefaults] language]; pageName = [NSString stringWithFormat: @"SOGoFolder%@%@Advisory", - [user language], template]; + language, template]; page = [[WOApplication application] pageWithName: pageName inContext: context]; @@ -676,7 +674,7 @@ static NSArray *childRecordFields = nil; { NSMutableArray *folderSubscription, *tmpA; NSString *subscriptionPointer; - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *moduleSettings, *tmpD; SOGoUser *sogoUser; BOOL rc; @@ -684,13 +682,13 @@ static NSArray *childRecordFields = nil; sogoUser = [SOGoUser userWithLogin: subscribingUser roles: nil]; if (sogoUser) { - ud = [sogoUser userSettings]; - moduleSettings = [ud objectForKey: [container nameInContainer]]; + us = [sogoUser userSettings]; + moduleSettings = [us objectForKey: [container nameInContainer]]; if (!(moduleSettings && [moduleSettings isKindOfClass: [NSMutableDictionary class]])) { moduleSettings = [NSMutableDictionary dictionary]; - [ud setObject: moduleSettings forKey: [container nameInContainer]]; + [us setObject: moduleSettings forKey: [container nameInContainer]]; } folderSubscription @@ -731,7 +729,7 @@ static NSArray *childRecordFields = nil; [folderSubscription removeObject: subscriptionPointer]; } - [ud synchronize]; + [us synchronize]; rc = YES; } else @@ -1203,11 +1201,13 @@ static NSArray *childRecordFields = nil; { int count, max; NSDictionary *record; - NSString *currentUID; + NSString *currentUID, *domain; SOGoGroup *group; NSMutableArray *acls; acls = [NSMutableArray array]; +#warning should it be the domain of the ownerUser instead? + domain = [[context activeUser] domain]; max = [records count]; for (count = 0; count < max; count++) @@ -1216,7 +1216,8 @@ static NSArray *childRecordFields = nil; currentUID = [record valueForKey: @"c_uid"]; if ([currentUID hasPrefix: @"@"]) { - group = [SOGoGroup groupWithIdentifier: currentUID]; + group = [SOGoGroup groupWithIdentifier: currentUID + inDomain: domain]; if (group && [group hasMemberWithUID: uid]) [acls addObject: [record valueForKey: @"c_role"]]; } @@ -1268,8 +1269,9 @@ static NSArray *childRecordFields = nil; forObjectAtPath: (NSArray *) objectPathArray { NSArray *acls; - NSString *objectPath; + NSString *objectPath, *module; NSDictionary *aclsForObject; + SOGoDomainDefaults *dd; objectPath = [objectPathArray componentsJoinedByString: @"/"]; aclsForObject = [aclCache objectForKey: objectPath]; @@ -1286,18 +1288,18 @@ static NSArray *childRecordFields = nil; } if (!([acls count] || [uid isEqualToString: defaultUserID])) - acls = [self aclsForUser: defaultUserID - forObjectAtPath: objectPathArray]; + acls = [self aclsForUser: defaultUserID forObjectAtPath: objectPathArray]; // If we still don't have ACLs defined for this particular resource, - // let's go get the system-wide defaults, if any. + // let's go get the domain defaults, if any. if (![acls count]) { - if ([[container nameInContainer] isEqualToString: @"Calendar"] - || [[container nameInContainer] isEqualToString: @"Contacts"]) - acls = [[NSUserDefaults standardUserDefaults] - objectForKey: [NSString stringWithFormat: @"SOGo%@DefaultRoles", - [container nameInContainer]]]; + dd = [[context activeUser] domainDefaults]; + module = [container nameInContainer]; + if ([module isEqualToString: @"Calendar"]) + acls = [dd calendarDefaultRoles]; + else if ([module isEqualToString: @"Contacts"]) + acls = [dd contactsDefaultRoles]; } return acls; @@ -1307,7 +1309,7 @@ static NSArray *childRecordFields = nil; forObjectAtPath: (NSArray *) objectPathArray { EOQualifier *qualifier; - NSString *uid, *uids, *qs, *objectPath; + NSString *uid, *uids, *qs, *objectPath, *domain; NSMutableArray *usersAndGroups; NSMutableDictionary *aclsForObject; SOGoGroup *group; @@ -1315,6 +1317,7 @@ static NSArray *childRecordFields = nil; if ([users count] > 0) { + domain = [[context activeUser] domain]; usersAndGroups = [NSMutableArray arrayWithArray: users]; for (i = 0; i < [usersAndGroups count]; i++) { @@ -1322,7 +1325,7 @@ static NSArray *childRecordFields = nil; if (![uid hasPrefix: @"@"]) { // Prefix the UID with the character "@" when dealing with a group - group = [SOGoGroup groupWithIdentifier: uid]; + group = [SOGoGroup groupWithIdentifier: uid inDomain: domain]; if (group) [usersAndGroups replaceObjectAtIndex: i withObject: [NSString stringWithFormat: @"@%@", uid]]; @@ -1372,7 +1375,7 @@ static NSArray *childRecordFields = nil; forUser: (NSString *) uid forObjectAtPath: (NSArray *) objectPathArray { - NSString *objectPath, *aUID; + NSString *objectPath, *aUID, *domain; NSMutableArray *newRoles; SOGoGroup *group; @@ -1380,7 +1383,8 @@ static NSArray *childRecordFields = nil; if (![uid hasPrefix: @"@"]) { // Prefix the UID with the character "@" when dealing with a group - group = [SOGoGroup groupWithIdentifier: uid]; + domain = [[context activeUser] domain]; + group = [SOGoGroup groupWithIdentifier: uid inDomain: domain]; if (group) aUID = [NSString stringWithFormat: @"@%@", uid]; } diff --git a/SoObjects/SOGo/SOGoGroup.h b/SoObjects/SOGo/SOGoGroup.h index cd3a4988b..e8e5f4949 100644 --- a/SoObjects/SOGo/SOGoGroup.h +++ b/SoObjects/SOGo/SOGoGroup.h @@ -40,10 +40,13 @@ NSMutableArray *_members; } -+ (id) groupWithIdentifier: (NSString *) theID; -+ (id) groupWithEmail: (NSString *) theEmail; ++ (id) groupWithIdentifier: (NSString *) theID + inDomain: (NSString *) domain; ++ (id) groupWithEmail: (NSString *) theEmail + inDomain: (NSString *) domain; + (id) groupWithValue: (NSString *) theValue - andSourceSelector: (SEL) theSelector; + andSourceSelector: (SEL) theSelector + inDomain: (NSString *) domain; - (NSArray *) members; diff --git a/SoObjects/SOGo/SOGoGroup.m b/SoObjects/SOGo/SOGoGroup.m index a223a1a7a..fb3c4f654 100644 --- a/SoObjects/SOGo/SOGoGroup.m +++ b/SoObjects/SOGo/SOGoGroup.m @@ -50,7 +50,7 @@ #import #import -#include "LDAPSource.h" +#include "SOGoSource.h" #include "SOGoUserManager.h" #include "SOGoUser.h" @@ -61,7 +61,7 @@ @implementation SOGoGroup - (id) initWithIdentifier: (NSString *) theID - source: (LDAPSource *) theSource + source: (NSObject *) theSource entry: (NGLdapEntry *) theEntry { self = [super init]; @@ -88,19 +88,23 @@ } + (id) groupWithIdentifier: (NSString *) theID + inDomain: (NSString *) domain { NSString *uid; uid = [theID hasPrefix: @"@"] ? [theID substringFromIndex: 1] : theID; return [SOGoGroup groupWithValue: uid - andSourceSelector: @selector (lookupGroupEntryByUID:)]; + andSourceSelector: @selector (lookupGroupEntryByUID:) + inDomain: domain]; } + (id) groupWithEmail: (NSString *) theEmail + inDomain: (NSString *) domain { return [SOGoGroup groupWithValue: theEmail - andSourceSelector: @selector (lookupGroupEntryByEmail:)]; + andSourceSelector: @selector (lookupGroupEntryByEmail:) + inDomain: domain]; } // @@ -109,10 +113,11 @@ // + (id) groupWithValue: (NSString *) theValue andSourceSelector: (SEL) theSelector + inDomain: (NSString *) domain { NSArray *allSources; NGLdapEntry *entry; - LDAPSource *source; + NSObject *source; id o; int i; @@ -122,7 +127,8 @@ if (!theValue) return nil; - allSources = [[SOGoUserManager sharedUserManager] sourceIDs]; + allSources = [[SOGoUserManager sharedUserManager] + sourceIDsInDomain: domain]; entry = nil; o = nil; @@ -156,8 +162,8 @@ [classes containsObject: @"posixGroup"]) { o = [[self alloc] initWithIdentifier: theValue - source: source - entry: entry]; + source: source + entry: entry]; AUTORELEASE(o); } } diff --git a/SoObjects/SOGo/SOGoLDAPDefaults.h b/SoObjects/SOGo/SOGoLDAPDefaults.h new file mode 100644 index 000000000..1fe4db6ec --- /dev/null +++ b/SoObjects/SOGo/SOGoLDAPDefaults.h @@ -0,0 +1,34 @@ +/* SOGoLDAPDefaults.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 SOGOLDAPDEFAULTS_H +#define SOGOLDAPDEFAULTS_H + +@protocol SOGoLDAPDefaults + +- (int) ldapQueryLimit; +- (int) ldapQueryTimeout; +- (NSString *) ldapContactInfoAttribute; + +@end + +#endif /* SOGOLDAPDEFAULTS_H */ diff --git a/SoObjects/SOGo/SOGoLDAPUserDefaultsBootstrap.m b/SoObjects/SOGo/SOGoLDAPUserDefaultsBootstrap.m index 893fd51e7..c483a9860 100644 --- a/SoObjects/SOGo/SOGoLDAPUserDefaultsBootstrap.m +++ b/SoObjects/SOGo/SOGoLDAPUserDefaultsBootstrap.m @@ -1,4 +1,4 @@ -/* SOGoLDAPUserDefaultsBootstrap.m - this file is part of $PROJECT_NAME_HERE$ +/* SOGoLDAPUserDefaultsBootstrap.m - this file is part of SOGo * * Copyright (C) 2009 Inverse inc. * @@ -20,8 +20,6 @@ * Boston, MA 02111-1307, USA. */ -#import - #import "SOGoLDAPUserDefaults.h" void diff --git a/SoObjects/SOGo/SOGoMailer.h b/SoObjects/SOGo/SOGoMailer.h index b8c6dc899..52ca73cfa 100644 --- a/SoObjects/SOGo/SOGoMailer.h +++ b/SoObjects/SOGo/SOGoMailer.h @@ -23,10 +23,14 @@ #ifndef SOGOMAILER_H #define SOGOMAILER_H +#import + @class NSArray; @class NSException; @class NSString; +@class SOGoDomainDefaults; + @protocol NGMimePart; @interface SOGoMailer : NSObject @@ -35,7 +39,9 @@ NSString *smtpServer; } -+ (id) sharedMailer; ++ (SOGoMailer *) mailerWithDomainDefaults: (SOGoDomainDefaults *) dd; + +- (id) initWithDomainDefaults: (SOGoDomainDefaults *) dd; - (NSException *) sendMailData: (NSData *) data toRecipients: (NSArray *) recipients diff --git a/SoObjects/SOGo/SOGoMailer.m b/SoObjects/SOGo/SOGoMailer.m index bc1d677f2..d9d40d2b9 100644 --- a/SoObjects/SOGo/SOGoMailer.m +++ b/SoObjects/SOGo/SOGoMailer.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -33,65 +32,35 @@ #import #import "NSString+Utilities.h" -#import "SOGoMailer.h" +#import "SOGoDomainDefaults.h" +#import "SOGoSystemDefaults.h" -#define defaultMailingMechanism @"sendmail" -#define defaultSMTPServer @"localhost" +#import "SOGoMailer.h" @implementation SOGoMailer -+ (id) sharedMailer ++ (SOGoMailer *) mailerWithDomainDefaults: (SOGoDomainDefaults *) dd { - static id sharedMailer = nil; + return [[self alloc] initWithDomainDefaults: dd]; +} - if (!sharedMailer) - sharedMailer = [self new]; +- (id) initWithDomainDefaults: (SOGoDomainDefaults *) dd +{ + if ((self = [self init])) + { + ASSIGN (mailingMechanism, [dd mailingMechanism]); + ASSIGN (smtpServer, [dd smtpServer]); + } - return sharedMailer; + return self; } - (id) init { - NSUserDefaults *ud; - if ((self = [super init])) { - ud = [NSUserDefaults standardUserDefaults]; - mailingMechanism = [ud stringForKey: @"SOGoMailingMechanism"]; - if (mailingMechanism) - { - if (!([mailingMechanism isEqualToString: @"sendmail"] - || [mailingMechanism isEqualToString: @"smtp"])) - { - [self logWithFormat: @"mechanism '%@' is invalid and" - @" should be set to 'sendmail' or 'smtp' instead", - mailingMechanism]; - [self logWithFormat: @"falling back to default '%@' mechanism", - defaultMailingMechanism]; - mailingMechanism = defaultMailingMechanism; - } - } - else - { - [self logWithFormat: @"default mailing mechanism set to '%@'", - defaultMailingMechanism]; - mailingMechanism = defaultMailingMechanism; - } - [mailingMechanism retain]; - - if ([mailingMechanism isEqualToString: @"smtp"]) - { - smtpServer = [ud stringForKey: @"SOGoSMTPServer"]; - if (!smtpServer) - { - [self logWithFormat: @"default smtp server set to '%@'", - defaultSMTPServer]; - smtpServer = defaultSMTPServer; - } - [smtpServer retain]; - } - else - smtpServer = nil; + mailingMechanism = nil; + smtpServer = nil; } return self; diff --git a/SoObjects/SOGo/SOGoObject.m b/SoObjects/SOGo/SOGoObject.m index 000543baa..fee5dcea0 100644 --- a/SoObjects/SOGo/SOGoObject.m +++ b/SoObjects/SOGo/SOGoObject.m @@ -28,7 +28,6 @@ #import #import #import -#import #import #import @@ -58,18 +57,17 @@ #import "NSObject+Utilities.h" #import "NSString+Utilities.h" #import "SOGoCache.h" +#import "SOGoDomainDefaults.h" #import "SOGoPermissions.h" +#import "SOGoSystemDefaults.h" #import "SOGoUser.h" +#import "SOGoUserDefaults.h" #import "SOGoUserFolder.h" #import "SOGoWebDAVAclManager.h" #import "SOGoWebDAVValue.h" #import "SOGoObject.h" -static BOOL kontactGroupDAV = YES; -static BOOL sendACLAdvisories = NO; -static BOOL useRelativeURLs = NO; - static NSDictionary *reportMap = nil; static NSMutableDictionary *setterMap = nil; static NSMutableDictionary *getterMap = nil; @@ -172,15 +170,9 @@ SEL SOGoSelectorForPropertySetter (NSString *property) + (void) initialize { - NSUserDefaults *ud; NSString *filename; NSBundle *bundle; - ud = [NSUserDefaults standardUserDefaults]; - kontactGroupDAV = ![ud boolForKey:@"SOGoDisableKontact34GroupDAVHack"]; - sendACLAdvisories = [ud boolForKey: @"SOGoACLsSendEMailNotifications"]; - useRelativeURLs = [ud boolForKey: @"WOUseRelativeURLs"]; - if (!reportMap) { bundle = [NSBundle bundleForClass: self]; @@ -941,23 +933,6 @@ SEL SOGoSelectorForPropertySetter (NSString *property) return nil; /* one etag matches, so continue with request */ } - /* hack for Kontact 3.4 */ - - if (kontactGroupDAV) { - WEClientCapabilities *cc; - - cc = [[(WOContext *)_ctx request] clientCapabilities]; - if ([[cc userAgentType] isEqualToString:@"Konqueror"]) { - if ([cc majorVersion] == 3 && [cc minorVersion] == 4) { - [self logWithFormat: - @"WARNING: applying Kontact 3.4 GroupDAV hack" - @" - etag check is disabled!" - @" (can be enabled using 'ZSDisableKontact34GroupDAVHack')"]; - return nil; - } - } - } - // TODO: we might want to return the davEntityTag in the response [self debugWithFormat:@"etag '%@' does not match: %@", etag, [etags componentsJoinedByString:@","]]; @@ -1041,13 +1016,15 @@ SEL SOGoSelectorForPropertySetter (NSString *property) - (BOOL) addUserInAcls: (NSString *) uid { BOOL result; + SOGoDomainDefaults *dd; if ([uid length] && ![uid isEqualToString: [self ownerInContext: nil]]) { [self setRoles: [self aclsForUser: uid] forUser: uid]; - if (sendACLAdvisories) + dd = [[context activeUser] domainDefaults]; + if ([dd aclSendEMailNotifications]) [self sendACLAdditionAdvisoryToUser: uid]; result = YES; } @@ -1060,11 +1037,13 @@ SEL SOGoSelectorForPropertySetter (NSString *property) - (BOOL) removeUserFromAcls: (NSString *) uid { BOOL result; + SOGoDomainDefaults *dd; if ([uid length]) { [self removeAclsForUsers: [NSArray arrayWithObject: uid]]; - if (sendACLAdvisories) + dd = [[context activeUser] domainDefaults]; + if ([dd aclSendEMailNotifications]) [self sendACLRemovalAdvisoryToUser: uid]; result = YES; } @@ -1110,12 +1089,12 @@ SEL SOGoSelectorForPropertySetter (NSString *property) toUser: (NSString *) uid { NSString *language, *pageName; - SOGoUser *user; + SOGoUserDefaults *userDefaults; SOGoACLAdvisory *page; WOApplication *app; - user = [SOGoUser userWithLogin: uid roles: nil]; - language = [user language]; + userDefaults = [[SOGoUser userWithLogin: uid roles: nil] userDefaults]; + language = [userDefaults language]; pageName = [NSString stringWithFormat: @"SOGoACL%@%@Advisory", language, template]; @@ -1190,10 +1169,12 @@ SEL SOGoSelectorForPropertySetter (NSString *property) - (NSString *) davURLAsString { NSURL *davURL; + SOGoSystemDefaults *sd; davURL = [self davURL]; + sd = [SOGoSystemDefaults sharedSystemDefaults]; - return (useRelativeURLs ? [davURL path] : [davURL absoluteString]); + return ([sd useRelativeURLs] ? [davURL path] : [davURL absoluteString]); } - (NSURL *) soURL @@ -1250,19 +1231,22 @@ SEL SOGoSelectorForPropertySetter (NSString *property) NSMutableArray *languages; NSArray *browserLanguages; NSString *language; - NSUserDefaults *ud; + SOGoUser *user; +#warning the purpose of this method needs to be reviewed languages = [NSMutableArray array]; - language = [[context activeUser] language]; - [languages addObject: language]; - browserLanguages = [[context request] browserLanguages]; - [languages addObjectsFromArray: browserLanguages]; - ud = [NSUserDefaults standardUserDefaults]; - language = [ud stringForKey: @"SOGoDefaultLanguage"]; - if (language) - [languages addObject: language]; - [languages addObject: @"English"]; + user = [context activeUser]; + if ([user isKindOfClass: [SOGoUser class]]) + { + language = [[user userDefaults] language]; + [languages addObject: language]; + } + else + { + browserLanguages = [[context request] browserLanguages]; + [languages addObjectsFromArray: browserLanguages]; + } return languages; } diff --git a/SoObjects/SOGo/SOGoParentFolder.m b/SoObjects/SOGo/SOGoParentFolder.m index 69c161c08..258b76177 100644 --- a/SoObjects/SOGo/SOGoParentFolder.m +++ b/SoObjects/SOGo/SOGoParentFolder.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -266,7 +265,7 @@ static SoSecurityManager *sm = nil; - (NSException *) appendSubscribedSources { NSArray *subscribedReferences; - NSUserDefaults *settings; + SOGoUserSettings *settings; NSEnumerator *allKeys; NSString *currentKey; NSException *error; diff --git a/SoObjects/SOGo/SOGoProxyAuthenticator.m b/SoObjects/SOGo/SOGoProxyAuthenticator.m index b6ff638ba..447ee340e 100644 --- a/SoObjects/SOGo/SOGoProxyAuthenticator.m +++ b/SoObjects/SOGo/SOGoProxyAuthenticator.m @@ -22,7 +22,6 @@ #import #import -#import #import #import diff --git a/SoObjects/SOGo/SOGoSQLUserProfile.h b/SoObjects/SOGo/SOGoSQLUserProfile.h new file mode 100644 index 000000000..1a3b9d253 --- /dev/null +++ b/SoObjects/SOGo/SOGoSQLUserProfile.h @@ -0,0 +1,39 @@ +/* SOGoSQLUserProfile.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 SOGOSQLUSERPROFILE_H +#define SOGOSQLUSERPROFILE_H + +#import "SOGoUserProfile.h" + +@class NSURL; +@class NSString; + +@interface SOGoSQLUserProfile : SOGoUserProfile +{ + NSString *fieldName; +} + + +@end + +#endif /* SOGOSQLUSERPROFILE_H */ diff --git a/SoObjects/SOGo/SOGoSQLUserProfile.m b/SoObjects/SOGo/SOGoSQLUserProfile.m new file mode 100644 index 000000000..fe51966fd --- /dev/null +++ b/SoObjects/SOGo/SOGoSQLUserProfile.m @@ -0,0 +1,242 @@ +/* SOGoSQLUserProfile.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 +#import + +#import +#import +#import +#import +#import + +#import "SOGoSystemDefaults.h" + +#import "SOGoSQLUserProfile.h" + +static NSURL *tableURL = nil; +static NSString *uidColumnName = @"c_uid"; + +@implementation SOGoSQLUserProfile + ++ (void) initialize +{ + NSString *profileURL; + SOGoSystemDefaults *sd; + + if (!tableURL) + { + sd = [SOGoSystemDefaults sharedSystemDefaults]; + profileURL = [sd profileURL]; + if (profileURL) + tableURL = [[NSURL alloc] initWithString: profileURL]; + } +} + +- (id) init +{ + if ((self = [super init])) + { + fieldName = nil; + } + + return self; +} + +- (void) dealloc +{ + [fieldName release]; + [super dealloc]; +} + +- (void) setProfileType: (SOGoUserProfileType) newProfileType +{ + if (newProfileType == SOGoUserProfileTypeDefaults) + ASSIGN (fieldName, @"c_defaults"); + else if (newProfileType == SOGoUserProfileTypeSettings) + ASSIGN (fieldName, @"c_settings"); + else + [self errorWithFormat: @"unknown profile value: %d", newProfileType]; + + [super setProfileType: newProfileType]; +} + +- (NSString *) fetchJSONProfileFromDB +{ + GCSChannelManager *cm; + EOAdaptorChannel *channel; + NSDictionary *row; + NSException *ex; + NSString *sql, *value; + NSArray *attrs; + + value = nil; + + cm = [GCSChannelManager defaultChannelManager]; + channel = [cm acquireOpenChannelForURL: tableURL]; + if (channel) + { + /* generate SQL */ + defFlags.ready = YES; + sql = [NSString stringWithFormat: @"SELECT %@ FROM %@ WHERE %@ = '%@'", + fieldName, [tableURL gcsTableName], + uidColumnName, [self uid]]; + /* run SQL */ + ex = [channel evaluateExpressionX: sql]; + if (ex) + [self errorWithFormat:@"could not run SQL '%@': %@", sql, ex]; + else + { + /* fetch schema */ + attrs = [channel describeResults: NO /* don't beautify */]; + + /* fetch values */ + row = [channel fetchAttributes: attrs withZone: NULL]; + [channel cancelFetch]; + + /* the isNew flag depends on the presence of the row in the + database rather than on the existence of the value. */ + defFlags.isNew = (row == nil); + + value = [row objectForKey: fieldName]; + if ([value isNotNull]) + /* The following enables the restitution of coded unicode (\U1234) + characters with the Oracle adaptor. */ + value = [value stringByReplacingString: @"\\\\" + withString: @"\\"]; + else + value = nil; /* we discard any NSNull instance */ + } + + [cm releaseChannel: channel]; + } + else + { + defFlags.ready = NO; + [self errorWithFormat:@"failed to acquire channel for URL: %@", + tableURL]; + } + + return value; +} + +- (NSString *) _sqlJsonRepresentation: (NSString *) jsonRepresentation +{ + NSMutableString *sql; + + sql = [jsonRepresentation mutableCopy]; + [sql autorelease]; + [sql replaceString: @"\\" withString: @"\\\\"]; + [sql replaceString: @"'" withString: @"''"]; + + return sql; +} + +- (NSString *) generateSQLForInsert: (NSString *) jsonRepresentation +{ + NSString *sql; + + if ([jsonRepresentation length]) + sql = [NSString stringWithFormat: (@"INSERT INTO %@" + @" (%@, %@)" + @" VALUES ('%@', '%@')"), + [tableURL gcsTableName], uidColumnName, fieldName, + [self uid], + [self _sqlJsonRepresentation: jsonRepresentation]]; + else + sql = nil; + + return sql; +} + +- (NSString *) generateSQLForUpdate: (NSString *) jsonRepresentation +{ + NSString *sql; + + if ([jsonRepresentation length]) + sql = [NSString stringWithFormat: (@"UPDATE %@" + @" SET %@ = '%@'" + @" WHERE %@ = '%@'"), + [tableURL gcsTableName], + fieldName, + [self _sqlJsonRepresentation: jsonRepresentation], + uidColumnName, [self uid]]; + else + sql = nil; + + return sql; +} + +- (BOOL) storeJSONProfileInDB: (NSString *) jsonRepresentation +{ + GCSChannelManager *cm; + EOAdaptorChannel *channel; + EOAdaptorContext *context; + NSException *ex; + NSString *sql; + BOOL rc; + + rc = NO; + + sql = ((defFlags.isNew) + ? [self generateSQLForInsert: jsonRepresentation] + : [self generateSQLForUpdate: jsonRepresentation]); + cm = [GCSChannelManager defaultChannelManager]; + channel = [cm acquireOpenChannelForURL: tableURL]; + if (channel) + { + context = [channel adaptorContext]; + if ([context beginTransaction]) + { + defFlags.ready = YES; + ex = [channel evaluateExpressionX:sql]; + if (ex) + { + [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex]; + [context rollbackTransaction]; + } + else + { + rc = YES; + defFlags.modified = NO; + defFlags.isNew = NO; + [context commitTransaction]; + } + [cm releaseChannel: channel]; + } + else + { + defFlags.ready = NO; + [cm releaseChannel: channel immediately: YES]; + } + } + else + { + defFlags.ready = NO; + [self errorWithFormat: @"failed to acquire channel for URL: %@", + tableURL]; + } + + return rc; +} + +@end diff --git a/SoObjects/SOGo/SOGoSource.h b/SoObjects/SOGo/SOGoSource.h index d201e6d94..c831ee91d 100644 --- a/SoObjects/SOGo/SOGoSource.h +++ b/SoObjects/SOGo/SOGoSource.h @@ -30,9 +30,13 @@ @protocol SOGoSource -+ (id) sourceFromUDSource: (NSDictionary *) udSource; ++ (id) sourceFromUDSource: (NSDictionary *) udSource + inDomain: (NSString *) domain; -- (id) initFromUDSource: (NSDictionary *) udSource; +- (id) initFromUDSource: (NSDictionary *) udSource + inDomain: (NSString *) domain; + +- (NSString *) domain; - (BOOL) checkLogin: (NSString *) login andPassword: (NSString *) password; diff --git a/SoObjects/SOGo/SOGoSystemDefaults.h b/SoObjects/SOGo/SOGoSystemDefaults.h new file mode 100644 index 000000000..5c7bafa44 --- /dev/null +++ b/SoObjects/SOGo/SOGoSystemDefaults.h @@ -0,0 +1,61 @@ +/* SOGoSystemDefaults.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 SOGOSYSTEMDEFAULTS_H +#define SOGOSYSTEMDEFAULTS_H + +#import + +@interface SOGoSystemDefaults : SOGoDomainDefaults + ++ (SOGoSystemDefaults *) sharedSystemDefaults; + +- (NSArray *) domainIds; + +- (BOOL) crashOnSessionCreate; +- (BOOL) debugRequests; +- (BOOL) debugLeaks; +- (int) vmemLimit; +- (BOOL) trustProxyAuthentication; +- (BOOL) useRelativeURLs; + +- (NSString *) faviconRelativeURL; +- (NSString *) zipPath; +- (int) port; +- (int) workers; +- (NSString *) logFile; +- (NSString *) pidFile; + +- (NSTimeInterval) cacheCleanupInterval; +- (NSString *) memcachedHost; + +- (BOOL) userCanChangePassword; +- (BOOL) uixAdditionalPreferences; + +- (BOOL) uixDebugEnabled; + +- (NSArray *) supportedLanguages; +- (NSString *) loginSuffix; + +@end + +#endif /* SOGOSYSTEMDEFAULTS_H */ diff --git a/SoObjects/SOGo/SOGoSystemDefaults.m b/SoObjects/SOGo/SOGoSystemDefaults.m new file mode 100644 index 000000000..833066e34 --- /dev/null +++ b/SoObjects/SOGo/SOGoSystemDefaults.m @@ -0,0 +1,274 @@ +/* SOGoSystemDefaults.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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 +#import + +#import +#import +#import +#import + +#import + +#import "NSDictionary+Utilities.h" +#import "SOGoStartupLogger.h" + +#define NEEDS_DEFAULTS_SOURCE_INTERNAL 1 +#import "SOGoSystemDefaults.h" + +@implementation SOGoSystemDefaults + +#if defined(LDAP_CONFIG) +#import +#endif + +typedef void (*NSUserDefaultsInitFunction) (); + +#define DIR_SEP "/" + +static void +BootstrapNSUserDefaults () +{ + char *filename; + NSUserDefaultsInitFunction SOGoNSUserDefaultsBootstrap; + void *handle; + + filename = SOGO_LIBDIR DIR_SEP "libSOGoNSUserDefaults.so.1"; + handle = dlopen (filename, RTLD_NOW | RTLD_GLOBAL); + if (handle) + { + SOGoNSUserDefaultsBootstrap = dlsym (handle, + "SOGoNSUserDefaultsBootstrap"); + if (SOGoNSUserDefaultsBootstrap) + SOGoNSUserDefaultsBootstrap (); + } +} + ++ (void) injectSOGoDefaults: (NSUserDefaults *) ud +{ + NSBundle *bundle; + NSDictionary *baseSOGoDefaults; + NSString *filename; + + bundle = [NSBundle bundleForClass: self]; + filename = [bundle pathForResource: @"SOGoDefaults" ofType: @"plist"]; + if (filename + && [[NSFileManager defaultManager] fileExistsAtPath: filename]) + { + baseSOGoDefaults + = [[NSDictionary alloc] initWithContentsOfFile: filename]; + if (baseSOGoDefaults) + { + [ud registerDefaults: baseSOGoDefaults]; + [baseSOGoDefaults autorelease]; + } + else + [bundle errorWithFormat: @"Unable to deserialize SOGoDefaults.plist"]; + } + else + [bundle errorWithFormat: @"SOGoDefaults.plist not found"]; +} + ++ (void) prepareUserDefaults +{ + NSString *redirectURL; + NSDictionary *domain; + NSUserDefaults *ud; + SOGoStartupLogger *logger; + + logger = [SOGoStartupLogger sharedLogger]; + + ud = [NSUserDefaults standardUserDefaults]; + domain = [ud persistentDomainForName: @"sogod"]; + if (![domain count]) + { + domain = [ud persistentDomainForName: @"sogod-0.9"]; + if ([domain count]) + { + [logger logWithFormat: @"migrating user defaults from sogod-0.9"]; + [ud setPersistentDomain: domain forName: @"sogod"]; + [ud removePersistentDomainForName: @"sogod-0.9"]; + [ud synchronize]; + } + else + [logger warnWithFormat: @"No configuration found." + @" SOGo will not work properly."]; + } + [self injectSOGoDefaults: ud]; + + redirectURL = [ud stringForKey: @"WOApplicationRedirectURL"]; + if (redirectURL) + { + [logger warnWithFormat: + @"Using obsolete 'WOApplicationRedirectURL' user default."]; + [logger warnWithFormat: + @" Please configure the use of the x-webobjects-XXX headers" + @" with your webserver (see sample files)."]; + if ([redirectURL hasSuffix: @"/"]) + [ud setObject: [redirectURL substringToIndex: [redirectURL length] - 1] + forKey: @"WOApplicationRedirectURL"]; + } +} + ++ (void) initialize +{ + BootstrapNSUserDefaults (); + [self prepareUserDefaults]; +} + ++ (SOGoSystemDefaults *) sharedSystemDefaults +{ + static SOGoSystemDefaults *sharedSystemDefaults = nil; + NSUserDefaults *ud; + + if (!sharedSystemDefaults) + { + ud = [NSUserDefaults standardUserDefaults]; + sharedSystemDefaults = [self defaultsSourceWithSource: ud + andParentSource: nil]; + [sharedSystemDefaults retain]; + } + + return sharedSystemDefaults; +} + +- (BOOL) migrate +{ + static NSDictionary *migratedKeys = nil; + + if (!migratedKeys) + { + migratedKeys = [NSDictionary dictionaryWithObjectsAndKeys: + @"SOGoProfileURL", @"AgenorProfileURL", + @"SOGoTimeZone", @"SOGoServerTimeZone", + nil]; + [migratedKeys retain]; + } + + return ([self migrateOldDefaultsWithDictionary: migratedKeys] + | [super migrate]); +} + +- (NSArray *) domainIds +{ + return [[self dictionaryForKey: @"domains"] allKeys]; +} + +/* System-level only */ + +- (BOOL) crashOnSessionCreate +{ + return [self boolForKey: @"SOGoCrashOnSessionCreate"]; +} + +- (BOOL) debugRequests +{ + return [self boolForKey: @"SOGoDebugRequests"]; +} + +- (BOOL) debugLeaks; +{ + return [self boolForKey: @"SOGoDebugLeaks"]; +} + +- (int) vmemLimit +{ + return [self integerForKey: @"SxVMemLimit"]; +} + +- (BOOL) trustProxyAuthentication; +{ + return [self boolForKey: @"SOGoTrustProxyAuthentication"]; +} + +- (BOOL) useRelativeURLs +{ + return [self boolForKey: @"WOUseRelativeURLs"]; +} + +- (NSString *) faviconRelativeURL +{ + return [self stringForKey: @"SOGoFaviconRelativeURL"]; +} + +- (NSString *) zipPath +{ + return [self stringForKey: @"SOGoZipPath"]; +} + +- (int) port +{ + return [self integerForKey: @"WOPort"]; +} + +- (int) workers +{ + return [self integerForKey: @"WOWorkersCount"]; +} + +- (NSString *) logFile +{ + return [self stringForKey: @"WOLogFile"]; +} + +- (NSString *) pidFile +{ + return [self stringForKey: @"WOPidFile"]; +} + +- (NSTimeInterval) cacheCleanupInterval +{ + return [self floatForKey: @"SOGoCacheCleanupInterval"]; +} + +- (NSString *) memcachedHost +{ + return [self stringForKey: @"SOGoMemcachedHost"]; +} + +- (BOOL) uixDebugEnabled +{ + return [self boolForKey: @"SOGoUIxDebugEnabled"]; +} + +- (NSArray *) supportedLanguages +{ + return [self stringArrayForKey: @"SOGoSupportedLanguages"]; +} + +- (BOOL) userCanChangePassword +{ + return [self boolForKey: @"SOGoUIxUserCanChangePassword"]; +} + +- (BOOL) uixAdditionalPreferences +{ + return [self boolForKey: @"SOGoUIxAdditionalPreferences"]; +} + +- (NSString *) loginSuffix +{ + return [self stringForKey: @"SOGoLoginSuffix"]; +} + +@end diff --git a/SoObjects/SOGo/SOGoUser.h b/SoObjects/SOGo/SOGoUser.h index a1f1adf28..9f0083233 100644 --- a/SoObjects/SOGo/SOGoUser.h +++ b/SoObjects/SOGo/SOGoUser.h @@ -40,40 +40,41 @@ @class NSMutableArray; @class NSMutableDictionary; @class NSString; -@class NSTimeZone; @class NSURL; -@class NSUserDefaults; @class WOContext; @class SOGoAppointmentFolder; @class SOGoAppointmentFolders; @class SOGoDateFormatter; +@class SOGoDomainDefaults; @class SOGoUserDefaults; @class SOGoUserFolder; +@class SOGoUserProfile; +@class SOGoUserSettings; -extern NSString *SOGoWeekStartJanuary1; -extern NSString *SOGoWeekStartFirst4DayWeek; -extern NSString *SOGoWeekStartFirstFullWeek; +// @interface SoUser (SOGoExtension) -@interface SoUser (SOGoExtension) +// - (NSString *) language; -- (NSString *) language; - -@end +// @end @interface SOGoUser : SoUser { - SOGoUserDefaults *_defaults, *_settings; + SOGoUserDefaults *_defaults; + SOGoDomainDefaults *_domainDefaults; + SOGoUserSettings *_settings; SOGoUserFolder *homeFolder; NSString *currentPassword; + NSString *domainId; NSString *language; NSArray *allEmails; + NSArray *mailAccounts; NSString *cn; BOOL propagateCache; } -+ (NSString *) language; +// + (NSString *) language; + (SOGoUser *) userWithLogin: (NSString *) newLogin; @@ -94,32 +95,23 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (NSString *) currentPassword; /* properties */ +- (NSString *) domain; + - (NSArray *) allEmails; - (BOOL) hasEmail: (NSString *) email; - (NSString *) systemEmail; - (NSString *) cn; -- (NSURL *) freeBusyURL; - (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context; /* defaults */ -- (NSUserDefaults *) userDefaults; -- (NSUserDefaults *) userSettings; +- (SOGoUserDefaults *) userDefaults; +- (SOGoDomainDefaults *) domainDefaults; +- (SOGoUserSettings *) userSettings; -- (void) invalidateLanguage; -- (NSString *) language; -- (NSTimeZone *) timeZone; -- (NSTimeZone *) serverTimeZone; - -- (unsigned int) firstDayOfWeek; - (NSCalendarDate *) firstDayOfWeekForDate: (NSCalendarDate *) date; - (unsigned int) dayOfWeekForDate: (NSCalendarDate *) date; -- (unsigned int) dayStartHour; -- (unsigned int) dayEndHour; - -- (NSString *) timeFormat; - - (NSCalendarDate *) firstWeekOfYearForDate: (NSCalendarDate *) date; - (unsigned int) weekNumberForDate: (NSCalendarDate *) date; @@ -128,13 +120,6 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (NSArray *) allIdentities; - (NSDictionary *) primaryIdentity; - (NSMutableDictionary *) defaultIdentity; -- (NSString *) messageForwarding; - -- (NSString *) signature; -- (NSString *) replyPlacement; -- (NSString *) signaturePlacement; - -- (void) saveMailAccounts; - (BOOL) isSuperUser; @@ -152,8 +137,6 @@ extern NSString *SOGoWeekStartFirstFullWeek; - (NSArray *) rolesForObject: (NSObject *) object inContext: (WOContext *) context; -- (void) migrateSignature; - @end #endif /* __SOGoUser_H__ */ diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 30524ae9b..0ce6f1fda 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -26,7 +26,6 @@ #import #import #import -#import #import #import #import @@ -40,200 +39,52 @@ #import "NSArray+Utilities.h" #import "SOGoCache.h" #import "SOGoDateFormatter.h" +#import "SOGoDomainDefaults.h" #import "SOGoObject.h" #import "SOGoPermissions.h" +#import "SOGoSystemDefaults.h" #import "SOGoUserDefaults.h" #import "SOGoUserFolder.h" #import "SOGoUserManager.h" +#import "SOGoUserProfile.h" +#import "SOGoUserSettings.h" #import "../../Main/SOGo.h" #import "SOGoUser.h" -static NSTimeZone *serverTimeZone = nil; -static NSString *fallbackIMAP4Server = nil; -static BOOL fallbackIsConfigured = NO; -static NSString *defaultLanguage = nil; -static NSString *defaultReplyPlacement = nil; -static NSString *defaultSignaturePlacement = nil; -static NSString *defaultMessageForwarding = nil; -static NSString *defaultMessageCheck = nil; -static NSString *defaultTimeFormat = nil; -static NSArray *superUsernames = nil; -static NSURL *SOGoProfileURL = nil; -// static BOOL acceptAnyUser = NO; -static int sogoFirstDayOfWeek = -1; -static int defaultDayStartTime = -1; -static int defaultDayEndTime = -1; -static Class SOGoUserDefaultsKlass = Nil; - -NSString *SOGoWeekStartJanuary1 = @"January1"; -NSString *SOGoWeekStartFirst4DayWeek = @"First4DayWeek"; -NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; - -@interface NSObject (SOGoRoles) - -- (NSArray *) rolesOfUser: (NSString *) uid; - -@end - @implementation SoUser (SOGoExtension) -- (NSString *) language +- (SOGoDomainDefaults *) userDefaults { - return [SOGoUser language]; + return [SOGoSystemDefaults sharedSystemDefaults]; +} + +- (SOGoDomainDefaults *) domainDefaults +{ + return [SOGoSystemDefaults sharedSystemDefaults]; } @end @implementation SOGoUser -static int -_timeValue (NSString *key) -{ - int i, time; +// + (NSString *) language +// { +// NSArray *bLanguages; +// WOContext *context; +// NSString *lng; - if (key && [key length] > 0) - { - i = [key rangeOfString: @":"].location; - if (i != NSNotFound) - time = [[key substringToIndex: i] intValue]; - else - time = [key intValue]; - } - else - time = -1; - - return time; -} +// context = [[WOApplication application] context]; +// bLanguages = [[context request] browserLanguages]; +// if ([bLanguages count] > 0) +// lng = [bLanguages objectAtIndex: 0]; -+ (void) initialize -{ - NSString *tzName; - NSUserDefaults *ud; - NSString *profileURL; +// if (![lng length]) +// lng = defaultLanguage; - ud = [NSUserDefaults standardUserDefaults]; - if (!serverTimeZone) - { - tzName = [ud stringForKey: @"SOGoServerTimeZone"]; - if (!tzName) - tzName = @"UTC"; - serverTimeZone = [NSTimeZone timeZoneWithName: tzName]; - [serverTimeZone retain]; - } - if (sogoFirstDayOfWeek == -1) - sogoFirstDayOfWeek = [ud integerForKey: @"SOGoFirstDayOfWeek"]; - if (defaultDayStartTime == -1) - { - defaultDayStartTime - = _timeValue ([ud stringForKey: @"SOGoDayStartTime"]); - if (defaultDayStartTime == -1) - defaultDayStartTime = 8; - } - if (defaultDayEndTime == -1) - { - defaultDayEndTime - = _timeValue ([ud stringForKey: @"SOGoDayEndTime"]); - if (defaultDayEndTime == -1) - defaultDayEndTime = 18; - } - - if (!SOGoProfileURL) - { - profileURL = [ud stringForKey: @"SOGoProfileURL"]; - if (!profileURL) - { - profileURL = [ud stringForKey: @"AgenorProfileURL"]; - if (profileURL) - { - [ud setObject: profileURL forKey: @"SOGoProfileURL"]; - [ud removeObjectForKey: @"AgenorProfileURL"]; - [ud synchronize]; - [self warnWithFormat: @"the user defaults key 'AgenorProfileURL'" - @" was renamed to 'SOGoProfileURL'"]; - } - } - if (profileURL) - SOGoProfileURL = [[NSURL alloc] initWithString: profileURL]; - } - if (!fallbackIMAP4Server) - ASSIGN (fallbackIMAP4Server, - [ud stringForKey: @"SOGoFallbackIMAP4Server"]); - if (fallbackIMAP4Server) - fallbackIsConfigured = YES; - else - { - [self warnWithFormat: - @"no server specified for SOGoFallbackIMAP4Server," - @" value set to 'localhost'"]; - fallbackIMAP4Server = @"localhost"; - } - if (!defaultLanguage) - { - ASSIGN (defaultLanguage, [ud stringForKey: @"SOGoDefaultLanguage"]); - if (!defaultLanguage) - ASSIGN (defaultLanguage, @"English"); - } - if (!defaultReplyPlacement) - { - ASSIGN (defaultReplyPlacement, [ud stringForKey: @"SOGoMailReplyPlacement"]); - if (!defaultReplyPlacement) - ASSIGN (defaultReplyPlacement, @"below"); - } - if (!defaultSignaturePlacement) - { - ASSIGN (defaultSignaturePlacement, [ud stringForKey: @"SOGoMailSignaturePlacement"]); - if (!defaultSignaturePlacement) - ASSIGN (defaultSignaturePlacement, @"below"); - } - if (!defaultMessageForwarding) - { - ASSIGN (defaultMessageForwarding, [ud stringForKey: @"SOGoMailMessageForwarding"]); - if (!defaultMessageForwarding) - ASSIGN (defaultMessageForwarding, @"inline"); - } - if (!defaultMessageCheck) - { - ASSIGN (defaultMessageCheck, [ud stringForKey: @"SOGoMailMessageCheck"]); - if (!defaultMessageCheck) - ASSIGN (defaultMessageCheck, @"manually"); - } - if (!defaultTimeFormat) - { - ASSIGN (defaultTimeFormat, [ud stringForKey: @"SOGoTimeFormat"]); - if (!defaultTimeFormat) - ASSIGN (defaultTimeFormat, @"%H:00"); - } - - if (!superUsernames) - ASSIGN (superUsernames, [ud arrayForKey: @"SOGoSuperUsernames"]); - -// acceptAnyUser = ([[ud stringForKey: @"SOGoAuthentificationMethod"] -// isEqualToString: @"bypass"]); -} - -+ (NSString *) language -{ - NSArray *bLanguages; - WOContext *context; - NSString *lng; - - context = [[WOApplication application] context]; - bLanguages = [[context request] browserLanguages]; - if ([bLanguages count] > 0) - lng = [bLanguages objectAtIndex: 0]; - - if (![lng length]) - lng = defaultLanguage; - - return lng; -} - -+ (NSString *) fallbackIMAP4Server -{ - return fallbackIMAP4Server; -} +// return lng; +// } + (SOGoUser *) userWithLogin: (NSString *) newLogin { @@ -257,7 +108,7 @@ _timeValue (NSString *key) user = [cache userNamed: newLogin]; if (!user) { - user = [[self alloc] initWithLogin: newLogin roles: newRoles trust: b]; + user = [[self alloc] initWithLogin: newLogin roles: newRoles trust: b]; if (user) { [user autorelease]; @@ -302,6 +153,11 @@ _timeValue (NSString *key) allEmails = nil; currentPassword = nil; cn = nil; + _defaults = nil; + _domainDefaults = nil; + _settings = nil; + allEmails = nil; + mailAccounts = nil; } } else @@ -316,8 +172,10 @@ _timeValue (NSString *key) - (void) dealloc { [_defaults release]; + [_domainDefaults release]; [_settings release]; [allEmails release]; + [mailAccounts release]; [currentPassword release]; [cn release]; [language release]; @@ -326,12 +184,12 @@ _timeValue (NSString *key) - (void) setPrimaryRoles: (NSArray *) newRoles { - ASSIGN(roles, newRoles); + ASSIGN (roles, newRoles); } - (void) setCurrentPassword: (NSString *) newPassword { - ASSIGN(currentPassword, newPassword); + ASSIGN (currentPassword, newPassword); } - (NSString *) currentPassword @@ -363,6 +221,11 @@ _timeValue (NSString *key) } /* properties */ +- (NSString *) domain +{ + return [self _fetchFieldForUser: @"c_domain"]; +} + - (NSArray *) allEmails { if (!allEmails) @@ -411,197 +274,158 @@ _timeValue (NSString *key) return defaultIdentity; } -- (void) saveMailAccounts -{ - BOOL doSave; - - doSave = YES; - if (!fallbackIsConfigured) - { - [self logWithFormat: @"'SOGoFallbackIMAP4Server' is not set"]; - doSave = NO; - } - if (![SOGoUserManager defaultMailDomainIsConfigured]) - { - [self logWithFormat: @"'SOGoDefaultMailDomain' is not set"]; - doSave = NO; - } - doSave = NO; - if (doSave) - [[self userDefaults] setObject: [self mailAccounts] - forKey: @"MailAccounts"]; - else - [self logWithFormat: @"saving mail accounts is disabled until the" - @" variable(s) mentionned above are configured"]; -} - -- (NSURL *) freeBusyURL -{ - return nil; -} - - (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context { SOGoDateFormatter *dateFormatter; NSString *format; - NSUserDefaults *ud; + SOGoUserDefaults *ud; + NSDictionary *locale; dateFormatter = [SOGoDateFormatter new]; [dateFormatter autorelease]; - [dateFormatter setLocale: [[WOApplication application] localeForLanguageNamed: [self language]]]; ud = [self userDefaults]; - format = [ud stringForKey: @"ShortDateFormat"]; + locale = [[WOApplication application] localeForLanguageNamed: [ud language]]; + [dateFormatter setLocale: locale]; + format = [ud shortDateFormat]; if (format) [dateFormatter setShortDateFormat: format]; - format = [ud stringForKey: @"LongDateFormat"]; + format = [ud longDateFormat]; if (format) [dateFormatter setLongDateFormat: format]; - format = [ud stringForKey: @"TimeFormat"]; + format = [ud timeFormat]; if (format) [dateFormatter setTimeFormat: format]; return dateFormatter; } -- (NSString *) userDefaultsClassName -{ - return @"SOGoUserDefaults"; -} - -- (NSUserDefaults *) userDefaults +- (SOGoUserDefaults *) userDefaults { if (!_defaults) { - if (!SOGoUserDefaultsKlass) - SOGoUserDefaultsKlass - = NSClassFromString ([self userDefaultsClassName]); - _defaults = [[SOGoUserDefaultsKlass alloc] - initWithTableURL: SOGoProfileURL - uid: login - fieldName: @"c_defaults"]; - if (_defaults) - { - [_defaults fetchProfile]; - if ([_defaults values]) - { - BOOL b; - b = NO; - - if (![[_defaults stringForKey: @"MessageCheck"] length]) - { - [_defaults setObject: defaultMessageCheck forKey: @"MessageCheck"]; - b = YES; - } - if (![[_defaults stringForKey: @"TimeZone"] length]) - { - [_defaults setObject: [serverTimeZone name] forKey: @"TimeZone"]; - b = YES; - } - - if (b) - [_defaults synchronize]; - - - // See explanation in -language - [self invalidateLanguage]; - } - } + _defaults = [SOGoUserDefaults defaultsForUser: login + inDomain: [self domain]]; + [_defaults retain]; } //else // NSLog(@"User defaults cache hit for %@", login); - return (NSUserDefaults *) _defaults; + return _defaults; } -- (NSUserDefaults *) userSettings +- (SOGoDomainDefaults *) domainDefaults { - if (!_settings) + NSString *domain; + + if (!_domainDefaults) { - if (!SOGoUserDefaultsKlass) - SOGoUserDefaultsKlass - = NSClassFromString ([self userDefaultsClassName]); - _settings = [[SOGoUserDefaultsKlass alloc] - initWithTableURL: SOGoProfileURL - uid: login - fieldName: @"c_settings"]; - if (_settings) - { - [_settings fetchProfile]; - - // See explanation in -language - [self invalidateLanguage]; - } + domain = [self domain]; + if ([domain length]) + { + _domainDefaults = [SOGoDomainDefaults defaultsForDomain: domain]; + if (!_domainDefaults) + { + [self errorWithFormat: @"domain '%@' does not exist!", domain]; + _domainDefaults = [SOGoSystemDefaults sharedSystemDefaults]; + } + } + else + _domainDefaults = [SOGoSystemDefaults sharedSystemDefaults]; + [_domainDefaults retain]; } //else - // NSLog(@"User settings cache hit for %@", login); + // NSLog(@"User defaults cache hit for %@", login); - return (NSUserDefaults *) _settings; + return _domainDefaults; } -- (void) invalidateLanguage -{ - DESTROY(language); -} +// - (SOGoUserDefaults *) userDefaults +// { +// if (!_defaults) +// { +// [SOGoUserDefaults defaultsForUser: login +// inDomain: [self domainName]] +// if (!SOGoUserProfileKlass) +// SOGoUserProfileKlass +// = NSClassFromString ([self userProfileClassName]); +// _defaults = [SOGoUserProfileKlass +// userProfileWithType: SOGoUserProfileTypeDefaults +// forUID: login]; +// if (_defaults) +// { +// [_defaults retain]; +// [_defaults fetchProfile]; +// if ([_defaults values]) +// { +// BOOL b; +// b = NO; -- (NSString *) language +// if (![[_defaults stringForKey: @"MessageCheck"] length]) +// { +// [_defaults setObject: defaultMessageCheck forKey: @"MessageCheck"]; +// b = YES; +// } +// if (![[_defaults stringForKey: @"TimeZone"] length]) +// { +// [_defaults setObject: [serverTimeZone name] forKey: @"TimeZone"]; +// b = YES; +// } + +// if (b) +// [_defaults synchronize]; + + +// // See explanation in -language +// [self invalidateLanguage]; +// } +// } +// } +// //else +// // NSLog(@"User defaults cache hit for %@", login); + +// return _defaults; +// } + +- (SOGoUserSettings *) userSettings { - if (![language length]) + if (!_settings) { - language = [[self userDefaults] stringForKey: @"Language"]; - // This is a workaround until we handle the connection errors to the db - // in a better way. It enables us to avoid retrieving the userDefaults - // too many times when the DB is down, causing a huge delay. - if (![language length]) - language = [SOGoUser language]; - - [language retain]; + _settings = [SOGoUserSettings settingsForUser: login]; + [_settings retain]; } - return language; + return _settings; } -- (NSTimeZone *) timeZone -{ - NSTimeZone *userTimeZone; - NSString *timeZoneName; - - timeZoneName = [[self userDefaults] stringForKey: @"TimeZone"]; - userTimeZone = nil; +// - (void) invalidateLanguage +// { +// DESTROY(language); +// } - if ([timeZoneName length] > 0) - userTimeZone = [NSTimeZone timeZoneWithName: timeZoneName]; - if (!userTimeZone) - userTimeZone = serverTimeZone; - - return userTimeZone; -} +// - (NSString *) language +// { +// if (![language length]) +// { +// language = [[self userDefaults] stringForKey: @"Language"]; +// // This is a workaround until we handle the connection errors to the db +// // in a better way. It enables us to avoid retrieving the userDefaults +// // too many times when the DB is down, causing a huge delay. +// if (![language length]) +// language = [SOGoUser language]; -- (NSTimeZone *) serverTimeZone -{ - return serverTimeZone; -} +// [language retain]; +// } -- (unsigned int) firstDayOfWeek -{ - unsigned int firstDayOfWeek; - NSNumber *value; - - value = [[self userDefaults] objectForKey: @"WeekStartDay"]; - if (value) - firstDayOfWeek = [value unsignedIntValue]; - else - firstDayOfWeek = sogoFirstDayOfWeek; - - return firstDayOfWeek; -} +// return language; +// } - (NSCalendarDate *) firstDayOfWeekForDate: (NSCalendarDate *) date { int offset; NSCalendarDate *firstDay; - offset = ([self firstDayOfWeek] - [date dayOfWeek]); + offset = [[self userDefaults] firstDayOfWeek] - [date dayOfWeek]; if (offset > 0) offset -= 7; @@ -614,7 +438,7 @@ _timeValue (NSString *key) { unsigned int offset, baseDayOfWeek, dayOfWeek; - offset = [self firstDayOfWeek]; + offset = [[self userDefaults] firstDayOfWeek]; baseDayOfWeek = [date dayOfWeek]; if (offset > baseDayOfWeek) baseDayOfWeek += 7; @@ -624,46 +448,13 @@ _timeValue (NSString *key) return dayOfWeek; } -- (unsigned int) dayStartHour -{ - int limit; - - limit = _timeValue ([[self userDefaults] stringForKey: @"DayStartTime"]); - if (limit == -1) - limit = defaultDayStartTime; - - return limit; -} - -- (unsigned int) dayEndHour -{ - int limit; - - limit = _timeValue ([[self userDefaults] stringForKey: @"DayEndTime"]); - if (limit == -1) - limit = defaultDayEndTime; - - return limit; -} - -- (NSString *) timeFormat -{ - NSString *timeFormat; - - timeFormat = [[self userDefaults] stringForKey: @"TimeFormat"]; - if (!timeFormat) - timeFormat = defaultTimeFormat; - - return timeFormat; -} - - (NSCalendarDate *) firstWeekOfYearForDate: (NSCalendarDate *) date { NSString *firstWeekRule; NSCalendarDate *januaryFirst, *firstWeek; unsigned int dayOfWeek; - firstWeekRule = [[self userDefaults] objectForKey: @"FirstWeek"]; + firstWeekRule = [[self userDefaults] firstWeekOfYear]; januaryFirst = [NSCalendarDate dateWithYear: [date yearOfCommonEra] month: 1 day: 1 hour: 0 minute: 0 second: 0 @@ -712,61 +503,52 @@ _timeValue (NSString *key) } /* mail */ -- (NSArray *) _prepareDefaultMailAccounts +- (NSArray *) mailAccounts { NSMutableDictionary *mailAccount, *identity; - NSMutableArray *identities, *mailAccounts; + NSMutableArray *identities; NSString *name, *fullName, *imapLogin, *imapServer; NSArray *mails; unsigned int count, max; - imapLogin = [[SOGoUserManager sharedUserManager] getImapLoginForUID: login]; - imapServer = [self _fetchFieldForUser: @"c_imaphostname"]; - if (!imapServer) - imapServer = fallbackIMAP4Server; - mailAccount = [NSMutableDictionary dictionary]; - name = [NSString stringWithFormat: @"%@@%@", - imapLogin, imapServer]; - [mailAccount setObject: imapLogin forKey: @"userName"]; - [mailAccount setObject: imapServer forKey: @"serverName"]; - [mailAccount setObject: name forKey: @"name"]; - - identities = [NSMutableArray array]; - mails = [self allEmails]; - - max = [mails count]; - if (max > 1) - max--; - for (count = 0; count < max; count++) - { - identity = [NSMutableDictionary dictionary]; - fullName = [self cn]; - if (![fullName length]) - fullName = login; - [identity setObject: fullName forKey: @"fullName"]; - [identity setObject: [mails objectAtIndex: count] forKey: @"email"]; - [identities addObject: identity]; - } - [[identities objectAtIndex: 0] setObject: [NSNumber numberWithBool: YES] - forKey: @"isDefault"]; - - [mailAccount setObject: identities forKey: @"identities"]; - - mailAccounts = [NSMutableArray array]; - [mailAccounts addObject: mailAccount]; - - return mailAccounts; -} - -- (NSArray *) mailAccounts -{ - NSUserDefaults *ud; - NSArray *mailAccounts; - - ud = [self userDefaults]; - mailAccounts = [ud objectForKey: @"MailAccounts"]; if (!mailAccounts) - mailAccounts = [self _prepareDefaultMailAccounts]; + { + imapLogin = [[SOGoUserManager sharedUserManager] + getImapLoginForUID: login]; + imapServer = [self _fetchFieldForUser: @"c_imaphostname"]; + if (!imapServer) + imapServer = [[self domainDefaults] imapServer]; + mailAccount = [NSMutableDictionary dictionary]; + name = [NSString stringWithFormat: @"%@@%@", + imapLogin, imapServer]; + [mailAccount setObject: imapLogin forKey: @"userName"]; + [mailAccount setObject: imapServer forKey: @"serverName"]; + [mailAccount setObject: name forKey: @"name"]; + + identities = [NSMutableArray array]; + mails = [self allEmails]; + + max = [mails count]; + if (max > 1) + max--; + for (count = 0; count < max; count++) + { + identity = [NSMutableDictionary dictionary]; + fullName = [self cn]; + if (![fullName length]) + fullName = login; + [identity setObject: fullName forKey: @"fullName"]; + [identity setObject: [mails objectAtIndex: count] forKey: @"email"]; + [identities addObject: identity]; + } + [[identities objectAtIndex: 0] setObject: [NSNumber numberWithBool: YES] + forKey: @"isDefault"]; + + [mailAccount setObject: identities forKey: @"identities"]; + + mailAccounts = [NSArray arrayWithObject: mailAccount]; + [mailAccounts retain]; + } return mailAccounts; } @@ -861,66 +643,6 @@ _timeValue (NSString *key) return [[defaultAccount objectForKey: @"identities"] objectAtIndex: 0]; } -- (void) migrateSignature -{ - NSString *signature; - NSUserDefaults *ud; - - signature = [[self primaryIdentity] objectForKey: @"signature"]; - - if ([signature length]) - { - ud = [self userDefaults]; - [ud setObject: signature forKey: @"MailSignature"]; - [ud removeObjectForKey: @"MailAccounts"]; - [ud synchronize]; - } -} - -- (NSString *) signature -{ - [self migrateSignature]; - - return [[self userDefaults] stringForKey: @"MailSignature"]; -} - -- (NSString *) replyPlacement -{ - NSString *replyPlacement = [[self userDefaults] stringForKey: @"ReplyPlacement"]; - - if (!replyPlacement) - replyPlacement = defaultReplyPlacement; - - return replyPlacement; -} - -- (NSString *) signaturePlacement -{ - NSString *signaturePlacement; - - if ([[self replyPlacement] isEqualToString: @"below"]) - // When replying to an email, if the reply is below the quoted text, - // the signature must also be below the quoted text. - signaturePlacement = @"below"; - else - { - signaturePlacement = [[self userDefaults] stringForKey: @"SignaturePlacement"]; - if (!signaturePlacement) - signaturePlacement = defaultSignaturePlacement; - } - - return signaturePlacement; -} - -- (NSString *) messageForwarding -{ - NSString *messageForwarding = [[self userDefaults] stringForKey: @"MessageForwarding"]; - if (!messageForwarding) - messageForwarding = defaultMessageForwarding; - - return messageForwarding; -} - /* folders */ // TODO: those methods should check whether the traversal stack in the context @@ -1012,7 +734,9 @@ _timeValue (NSString *key) - (BOOL) isSuperUser { - return [superUsernames containsObject: login]; + [self domainDefaults]; + + return [[_domainDefaults superUsernames] containsObject: login]; } /* module access */ diff --git a/SoObjects/SOGo/SOGoUserDefaults.h b/SoObjects/SOGo/SOGoUserDefaults.h index b2e025a1f..a81255d34 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.h +++ b/SoObjects/SOGo/SOGoUserDefaults.h @@ -1,93 +1,151 @@ -/* - Copyright (C) 2008-2009 Inverse inc. - Copyright (C) 2005 SKYRIX Software AG +/* SOGoUserDefaults.h - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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. + */ - This file is part of SOGo. +#ifndef SOGOUSERDEFAULTS_H +#define SOGOUSERDEFAULTS_H - SOGo 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. +#import - SOGo 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. +@class NSArray; +@class NSMutableDictionary; +@class NSString; +@class NSTimeZone; - 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. -*/ +extern NSString *SOGoWeekStartJanuary1; +extern NSString *SOGoWeekStartFirst4DayWeek; +extern NSString *SOGoWeekStartFirstFullWeek; -#ifndef __SOGoUserDefaults_H_ -#define __SOGoUserDefaults_H_ +@interface SOGoUserDefaults : SOGoDefaultsSource -#import ++ (SOGoUserDefaults *) defaultsForUser: (NSString *) userId + inDomain: (NSString *) domainId; -/* - SOGoUserDefaults - - An object with the same API like NSUserDefaults which retrieves profile - information for users in the database. +- (void) setLoginModule: (NSString *) newLoginModule; +- (NSString *) loginModule; - It does NOT store values internally but rather uses an external - mutable dictionary for this (generally coming from SOGoCache) -*/ +- (void) setRememberLastModule: (BOOL) rememberLastModule; +- (BOOL) rememberLastModule; -@class NSString, NSURL, NSUserDefaults, NSArray, NSDictionary; -@class NSData, NSCalendarDate, NSMutableDictionary; +- (void) setAppointmentSendEMailReceipts: (BOOL) newPoil; +- (BOOL) appointmentSendEMailReceipts; -@interface SOGoUserDefaults : NSObject -{ - NSURL *url; - NSString *uid; - NSString *fieldName; - NSMutableDictionary *values; +- (void) setLongDateFormat: (NSString *) newFormat; +- (void) unsetLongDateFormat; +- (NSString *) longDateFormat; - struct - { - BOOL modified; - BOOL isNew; - BOOL ready; - } defFlags; -} +- (void) setShortDateFormat: (NSString *) newFormat; +- (void) unsetShortDateFormat; +- (NSString *) shortDateFormat; -- (id) initWithTableURL: (NSURL *) theURL - uid: (NSString *) theUID - fieldName: (NSString *) theFieldName; +- (void) setTimeFormat: (NSString *) newFormat; +- (void) unsetTimeFormat; +- (NSString *) timeFormat; -/* value access */ -- (void) setValues: (NSDictionary *) theValues; -- (NSDictionary *) values; +- (void) setDayStartTime: (NSString *) newValue; +- (NSString *) dayStartTime; +- (unsigned int) dayStartHour; -- (void) setObject: (id) value - forKey: (NSString *) key; -- (id) objectForKey: (NSString *) key; -- (void) removeObjectForKey: (NSString *) key; +- (void) setDayEndTime: (NSString *) newValue; +- (NSString *) dayEndTime; +- (unsigned int) dayEndHour; -/* typed accessors */ +- (void) setTimeZoneName: (NSString *) newValue; +- (NSString *) timeZoneName; -- (NSArray *) arrayForKey: (NSString *)key; -- (NSDictionary *) dictionaryForKey: (NSString *)key; -- (NSData *) dataForKey: (NSString *)key; -- (NSString *) stringForKey: (NSString *)key; -- (BOOL) boolForKey: (NSString *) key; -- (float) floatForKey: (NSString *) key; -- (int) integerForKey: (NSString *) key; +- (void) setTimeZone: (NSTimeZone *) newValue; +- (NSTimeZone *) timeZone; -- (void) setBool: (BOOL) value forKey: (NSString *) key; -- (void) setFloat: (float) value forKey: (NSString *) key; -- (void) setInteger: (int) value forKey: (NSString *) key; +- (void) setTimeFormat: (NSString *) newValue; +- (NSString *) timeFormat; -- (NSString *) jsonRepresentation; +- (void) setLanguage: (NSString *) newValue; +- (NSString *) language; -- (void) fetchProfile; +- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue; +- (BOOL) mailShowSubscribedFoldersOnly; -/* saving changes */ +- (void) setDraftsFolderName: (NSString *) newValue; +- (NSString *) draftsFolderName; -- (BOOL) synchronize; +- (void) setSentFolderName: (NSString *) newValue; +- (NSString *) sentFolderName; + +- (void) setTrashFolderName: (NSString *) newValue; +- (NSString *) trashFolderName; + +- (void) setFirstDayOfWeek: (int) newValue; +- (int) firstDayOfWeek; + +- (void) setFirstWeekOfYear: (NSString *) newValue; +- (NSString *) firstWeekOfYear; + +- (void) setMailListViewColumnsOrder: (NSArray *) newValue; +- (NSArray *) mailListViewColumnsOrder; + +- (void) setMailMessageCheck: (NSString *) newValue; +- (NSString *) mailMessageCheck; + +- (void) setMailComposeMessageType: (NSString *) newValue; +- (NSString *) mailComposeMessageType; + +- (void) setMailMessageForwarding: (NSString *) newValue; +- (NSString *) mailMessageForwarding; + +- (void) setMailReplyPlacement: (NSString *) newValue; +- (NSString *) mailReplyPlacement; + +- (void) setMailSignature: (NSString *) newValue; +- (NSString *) mailSignature; + +- (void) setMailSignaturePlacement: (NSString *) newValue; +- (NSString *) mailSignaturePlacement; + +- (void) setMailUseOutlookStyleReplies: (BOOL) newValue; +- (BOOL) mailUseOutlookStyleReplies; + +- (void) setCalendarCategories: (NSArray *) newValues; +- (NSArray *) calendarCategories; + +- (void) setCalendarCategoriesColors: (NSArray *) newValues; +- (NSArray *) calendarCategoriesColors; + +- (void) setCalendarShouldDisplayWeekend: (BOOL) newValue; +- (BOOL) calendarShouldDisplayWeekend; + +- (void) setReminderEnabled: (BOOL) newValue; +- (BOOL) reminderEnabled; + +- (void) setReminderTime: (NSString *) newValue; +- (NSString *) reminderTime; + +- (void) setRemindWithASound: (BOOL) newValue; +- (BOOL) remindWithASound; + +- (void) setVacationOptions: (NSMutableDictionary *) newValue; +- (NSMutableDictionary *) vacationOptions; + +- (void) setForwardOptions: (NSMutableDictionary *) newValue; +- (NSMutableDictionary *) forwardOptions; @end -#endif /* __SOGoUserDefaults_H__ */ +#endif /* SOGOUSERDEFAULTS_H */ diff --git a/SoObjects/SOGo/SOGoUserDefaults.m b/SoObjects/SOGo/SOGoUserDefaults.m index 960f5e66e..e39bacd43 100644 --- a/SoObjects/SOGo/SOGoUserDefaults.m +++ b/SoObjects/SOGo/SOGoUserDefaults.m @@ -1,554 +1,563 @@ -/* - Copyright (C) 2008-2009 Inverse inc. - Copyright (C) 2005 SKYRIX Software AG +/* SOGoUserDefaults.m - this file is part of SOGo + * + * Copyright (C) 2009 Inverse inc. + * + * Author: Wolfgang Sourdeau + * + * 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. + */ - This file is part of SOGo. +#import +#import +#import +#import - SOGo 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. - - SOGo 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. -*/ - -#import -#import -#import -#import - -#import -#import - -#import -#import -#import -#import -#import - -#import "NSObject+Utilities.h" #import "NSString+Utilities.h" +#define NEEDS_DEFAULTS_SOURCE_INTERNAL 1 +#import "SOGoDomainDefaults.h" +#import "SOGoSystemDefaults.h" +#import "SOGoUserProfile.h" -#import "NSDictionary+BSJSONAdditions.h" #import "SOGoUserDefaults.h" -#import "SOGoCache.h" + +static Class SOGoUserProfileKlass = Nil; + +NSString *SOGoWeekStartJanuary1 = @"January1"; +NSString *SOGoWeekStartFirst4DayWeek = @"First4DayWeek"; +NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek"; @implementation SOGoUserDefaults -static NSString *uidColumnName = @"c_uid"; - -- (id) initWithTableURL: (NSURL *) theURL - uid: (NSString *) theUID - fieldName: (NSString *) theFieldName ++ (NSString *) userProfileClassName { - if ((self = [self init])) - { - if (theURL && [theUID length] > 0 - && [theFieldName length] > 0) - { - ASSIGN (fieldName, theFieldName); - ASSIGN (url, theURL); - ASSIGN (uid, theUID); - defFlags.ready = NO; - defFlags.isNew = NO; - } - else - { - [self errorWithFormat: @"missing arguments"]; - [self release]; - self = nil; - } - } - - return self; + return @"SOGoSQLUserProfile"; } -- (void) dealloc ++ (void) initialize { - [values release]; - [url release]; - [uid release]; - [fieldName release]; - [super dealloc]; + if (!SOGoUserProfileKlass) + SOGoUserProfileKlass = NSClassFromString ([self userProfileClassName]); } -/* accessors */ - -- (NSURL *) tableURL ++ (SOGoUserDefaults *) defaultsForUser: (NSString *) userId + inDomain: (NSString *) domainId { - return url; -} + SOGoUserProfile *up; + SOGoUserDefaults *ud; + SOGoDefaultsSource *parentSource; -- (NSString *) uid -{ - return uid; -} + up = [SOGoUserProfileKlass userProfileWithType: SOGoUserProfileTypeDefaults + forUID: userId]; + [up fetchProfile]; + // if ([_defaults values]) + // { + // BOOL b; + // b = NO; -- (NSString *) fieldName -{ - return fieldName; -} - -/* operation */ - -- (NSString *) fetchJSONProfileFromDB -{ - GCSChannelManager *cm; - EOAdaptorChannel *channel; - NSDictionary *row; - NSException *ex; - NSString *sql, *value; - NSArray *attrs; - - value = nil; - - cm = [GCSChannelManager defaultChannelManager]; - channel = [cm acquireOpenChannelForURL: [self tableURL]]; - if (channel) - { - /* generate SQL */ - defFlags.ready = YES; - sql = [NSString stringWithFormat: @"SELECT %@ FROM %@ WHERE %@ = '%@'", - fieldName, [[self tableURL] gcsTableName], - uidColumnName, [self uid]]; - /* run SQL */ - ex = [channel evaluateExpressionX: sql]; - if (ex) - [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex]; - else - { - /* fetch schema */ - attrs = [channel describeResults: NO /* don't beautify */]; - - /* fetch values */ - row = [channel fetchAttributes: attrs withZone: NULL]; - [channel cancelFetch]; - - /* the isNew flag depends on the presence of the row in the - database rather than on the existence of the value. */ - defFlags.isNew = (row == nil); - - value = [row objectForKey: fieldName]; - if ([value isNotNull]) - /* The following enables the restitution of coded unicode - (\U1234) characters with the Oracle adaptor. */ - value = [value stringByReplacingString: @"\\\\" - withString: @"\\"]; - else - value = nil; /* we discard any NSNull instance */ - } - - [cm releaseChannel: channel]; - } - else - { - defFlags.ready = NO; - [self errorWithFormat:@"failed to acquire channel for URL: %@", - [self tableURL]]; - } - - return value; -} - -- (NSString *) _convertPListToJSON: (NSString *) plistValue -{ - NSData *plistData; - NSDictionary *plist; - NSString *jsonValue, *error; - - plistData = [plistValue dataUsingEncoding: NSUTF8StringEncoding]; - plist = [NSPropertyListSerialization propertyListFromData: plistData - mutabilityOption: NSPropertyListMutableContainers - format: NULL - errorDescription: &error]; - if (plist) - { - [self logWithFormat: @"database value for '%@'" - @" (uid: '%@') is a plist", fieldName, uid]; - jsonValue = [plist jsonStringValue]; - } - else - { - [self errorWithFormat: @"failed to parse property list value" - @" (error: %@): %@", error, plistValue]; - jsonValue = nil; - } - - if (!jsonValue) - jsonValue = @"{}"; - - return jsonValue; -} - -- (NSString *) jsonRepresentation -{ - SOGoCache *cache; - NSString *jsonValue; - - cache = [SOGoCache sharedCache]; - if ([fieldName isEqualToString: @"c_defaults"]) - jsonValue = [cache userDefaultsForLogin: uid]; - else - jsonValue = [cache userSettingsForLogin: uid]; - if ([jsonValue length]) - { - defFlags.ready = YES; - defFlags.isNew = NO; - } - else - { - jsonValue = [self fetchJSONProfileFromDB]; - if ([jsonValue length]) - { - if (![jsonValue isJSONString]) - jsonValue = [self _convertPListToJSON: jsonValue]; - if ([fieldName isEqualToString: @"c_defaults"]) - [cache setUserDefaults: jsonValue forLogin: uid]; - else - [cache setUserSettings: jsonValue forLogin: uid]; - } - else - jsonValue = @"{}"; - } - - return jsonValue; -} - -- (void) primaryFetchProfile -{ - NSString *jsonValue; - - defFlags.modified = NO; - [values release]; - jsonValue = [self jsonRepresentation]; - values = [NSMutableDictionary dictionaryWithJSONString: jsonValue]; - if (values) - [values retain]; - else - [self errorWithFormat: @"failure parsing json string: '%@'", jsonValue]; -} - -- (BOOL) _isReadyOrRetry -{ - BOOL rc; - - if (defFlags.ready) - rc = YES; - else - { - [self primaryFetchProfile]; - rc = defFlags.ready; - } - - return rc; -} - -- (NSString *) _sqlJsonRepresentation: (NSString *) jsonRepresentation -{ - NSMutableString *sql; - - sql = [jsonRepresentation mutableCopy]; - [sql autorelease]; - [sql replaceString: @"\\" withString: @"\\\\"]; - [sql replaceString: @"'" withString: @"''"]; - - return sql; -} - -- (NSString *) generateSQLForInsert: (NSString *) jsonRepresentation -{ - NSString *sql; - - if ([jsonRepresentation length]) - sql = [NSString stringWithFormat: (@"INSERT INTO %@" - @" (%@, %@)" - @" VALUES ('%@', '%@')"), - [[self tableURL] gcsTableName], uidColumnName, fieldName, - [self uid], - [self _sqlJsonRepresentation: jsonRepresentation]]; - else - sql = nil; - - return sql; -} - -- (NSString *) generateSQLForUpdate: (NSString *) jsonRepresentation -{ - NSString *sql; - - if ([jsonRepresentation length]) - sql = [NSString stringWithFormat: (@"UPDATE %@" - @" SET %@ = '%@'" - @" WHERE %@ = '%@'"), - [[self tableURL] gcsTableName], - fieldName, - [self _sqlJsonRepresentation: jsonRepresentation], - uidColumnName, [self uid]]; - else - sql = nil; - - return sql; -} - -- (BOOL) storeJSONProfileInDB: (NSString *) jsonRepresentation -{ - GCSChannelManager *cm; - EOAdaptorChannel *channel; - EOAdaptorContext *context; - NSException *ex; - NSString *sql; - BOOL rc; - - rc = NO; - - sql = ((defFlags.isNew) - ? [self generateSQLForInsert: jsonRepresentation] - : [self generateSQLForUpdate: jsonRepresentation]); - cm = [GCSChannelManager defaultChannelManager]; - channel = [cm acquireOpenChannelForURL: [self tableURL]]; - if (channel) - { - context = [channel adaptorContext]; - if ([context beginTransaction]) - { - defFlags.ready = YES; - ex = [channel evaluateExpressionX: sql]; - if (ex) - { - [self errorWithFormat: @"could not run SQL '%@': %@", sql, ex]; - [context rollbackTransaction]; - } - else - { - rc = YES; - defFlags.modified = NO; - defFlags.isNew = NO; - [context commitTransaction]; - } - [cm releaseChannel: channel]; - } - else - { - defFlags.ready = NO; - [cm releaseChannel: channel immediately: YES]; - } - } - else - { - defFlags.ready = NO; - [self errorWithFormat: @"failed to acquire channel for URL: %@", - [self tableURL]]; - } - - return rc; -} - -- (BOOL) primaryStoreProfile -{ - NSString *jsonRepresentation; - SOGoCache *cache; - BOOL rc; - - jsonRepresentation = [values jsonStringValue]; - if (jsonRepresentation) - { - rc = [self storeJSONProfileInDB: jsonRepresentation]; - if (rc) - { - cache = [SOGoCache sharedCache]; - if ([fieldName isEqualToString: @"c_defaults"]) - [cache setUserDefaults: jsonRepresentation - forLogin: uid]; - else - [cache setUserSettings: jsonRepresentation - forLogin: uid]; - } - } - else - { - [self errorWithFormat: @"Unable to convert (%@) to a JSON string for" - @" type: %@ and login: %@", values, fieldName, uid]; - rc = NO; - } - - return rc; -} - -- (void) fetchProfile -{ - if (!values) - [self primaryFetchProfile]; -} - -/* value access */ -- (void) setValues: (NSDictionary *) theValues -{ - if ([self _isReadyOrRetry]) - { - [values release]; - values = [[NSMutableDictionary alloc] init]; - [values addEntriesFromDictionary: theValues]; - defFlags.modified = YES; - } -} - -- (NSDictionary *) values -{ - NSDictionary *returnValues; - - if ([self _isReadyOrRetry]) - returnValues = values; - else - returnValues = nil; - - return returnValues; -} - -- (void) setObject: (id) value - forKey: (NSString *) key -{ - id old; - - if ([self _isReadyOrRetry]) - { - /* check whether the value is actually modified */ - if (!defFlags.modified) - { - old = [values objectForKey: key]; - if (old == value || [old isEqual: value]) /* value didn't change */ - return; - -#warning Note that this work-around only works for first-level objects. - /* we need to this because our typed accessors convert to strings */ - // TODO: especially problematic with bools - if ([value isKindOfClass: [NSString class]]) { - if (![old isKindOfClass: [NSString class]]) - if ([[old description] isEqualToString: value]) - return; - } - } - - /* set in hash and mark as modified */ - if (value) - [values setObject: value forKey: key]; - else - [values removeObjectForKey: key]; + // if (![[_defaults stringForKey: @"MessageCheck"] length]) + // { + // [_defaults setObject: defaultMessageCheck forKey: @"MessageCheck"]; + // b = YES; + // } + // if (![[_defaults stringForKey: @"TimeZone"] length]) + // { + // [_defaults setObject: [serverTimeZone name] forKey: @"TimeZone"]; + // b = YES; + // } - defFlags.modified = YES; - } + // if (b) + // [_defaults synchronize]; + + + // See explanation in -language + // [self invalidateLanguage]; + // } + + parentSource = [SOGoDomainDefaults defaultsForDomain: domainId]; + if (!parentSource) + parentSource = [SOGoSystemDefaults sharedSystemDefaults]; + + ud = [self defaultsSourceWithSource: up + andParentSource: parentSource]; + + return ud; } -- (id) objectForKey: (NSString *) key -{ - return [[self values] objectForKey: key]; -} - -- (void) removeObjectForKey: (NSString *) key -{ - [self setObject: nil forKey: key]; -} - -/* saving changes */ - -- (BOOL) synchronize +- (BOOL) _migrateLastModule { BOOL rc; -// if (!defFlags.modified) /* was not modified */ -// return YES; + NSString *loginModule; - rc = NO; - - /* ensure fetched data (more or less guaranteed by modified!=0) */ - [self fetchProfile]; - if (values) + loginModule = [source objectForKey: @"SOGoUIxLastModule"]; + if ([loginModule length]) { - /* store */ - if ([self primaryStoreProfile]) - { - rc = YES; - // /* refetch */ - // [self primaryFetchProfile]; - } - else - { - [self primaryFetchProfile]; - return NO; - } + rc = YES; + /* we need to use the old key, otherwise the migration will be blocked */ + [self setObject: loginModule forKey: @"SOGoUIxDefaultModule"]; + [self setRememberLastModule: YES]; + [self removeObjectForKey: @"SOGoUIxLastModule"]; } + else + rc = NO; return rc; } -/* typed accessors */ - -- (NSArray *) arrayForKey: (NSString *) key +- (BOOL) _migrateSignature { - return [self objectForKey: key]; + BOOL rc; + NSString *signature; + NSArray *mailAccounts, *identities; + NSDictionary *identity; + + mailAccounts = [self arrayForKey: @"MailAccounts"]; + if (mailAccounts) + { + rc = YES; + if ([mailAccounts count] > 0) + { + identities = [[mailAccounts objectAtIndex: 0] + objectForKey: @"identifies"]; + if ([identities count] > 0) + { + identity = [identities objectAtIndex: 0]; + signature = [identity objectForKey: @"signature"]; + if ([signature length]) + [self setObject: signature forKey: @"MailSignature"]; + } + } + [self removeObjectForKey: @"MailAccounts"]; + } + else + rc = NO; + + return rc; } -- (NSDictionary *) dictionaryForKey: (NSString *) key +- (BOOL) migrate { - return [self objectForKey: key]; + static NSDictionary *migratedKeys = nil; + + if (!migratedKeys) + { + migratedKeys + = [NSDictionary dictionaryWithObjectsAndKeys: + @"SOGoLoginModule", @"SOGoUIxDefaultModule", + @"SOGoTimeFormat", @"TimeFormat", + @"SOGoShortDateFormat", @"ShortDateFormat", + @"SOGoLongDateFormat", @"LongDateFormat", + @"SOGoDayStartTime", @"DayStartTime", + @"SOGoDayEndTime", @"DayEndTime", + @"SOGoFirstDayOfWeek", @"WeekStartDay", + @"SOGoFirstWeekOfYear", @"FirstWeek", + @"SOGoLanguage", @"SOGoDefaultLanguage", + @"SOGoLanguage", @"Language", + @"SOGoMailComposeMessageType", @"ComposeMessagesType", + @"SOGoMailMessageCheck", @"MessageCheck", + @"SOGoMailMessageForwarding", @"MessageForwarding", + @"SOGoMailSignature", @"MailSignature", + @"SOGoMailSignaturePlacement", @"SignaturePlacement", + @"SOGoMailReplyPlacement", @"ReplyPlacement", + @"SOGoTimeZone", @"TimeZone", + @"SOGoCalendarShouldDisplayWeekend", @"SOGoShouldDisplayWeekend", + @"SOGoMailShowSubscribedFoldersOnly", @"showSubscribedFoldersOnly", + @"SOGoReminderEnabled", @"ReminderEnabled", + @"SOGoReminderTime", @"ReminderTime", + @"SOGoRemindWithASound", @"RemindWithASound", + nil]; + [migratedKeys retain]; + } + + /* we must not use a boolean operation, otherwise subsequent migrations will + not be invoked in the case where rc = YES. */ + return ([self _migrateLastModule] + | [self _migrateSignature] + | [self migrateOldDefaultsWithDictionary: migratedKeys] + | [super migrate]); } -- (NSData *) dataForKey: (NSString *) key +- (void) setLoginModule: (NSString *) newLoginModule { - return [self objectForKey: key]; + [self setObject: newLoginModule forKey: @"SOGoLoginModule"]; } -- (NSString *) stringForKey: (NSString *) key +- (NSString *) loginModule { - return [self objectForKey: key]; + return [self stringForKey: @"SOGoLoginModule"]; } -- (BOOL) boolForKey: (NSString *) key +- (void) setRememberLastModule: (BOOL) rememberLastModule { - return [[self objectForKey: key] boolValue]; + [self setBool: rememberLastModule forKey: @"SOGoRememberLastModule"]; } -- (float) floatForKey: (NSString *) key +- (BOOL) rememberLastModule { - return [[self objectForKey: key] floatValue]; + return [self boolForKey: @"SOGoRememberLastModule"]; } -- (int) integerForKey: (NSString *) key +- (void) setAppointmentSendEMailReceipts: (BOOL) newValue { - return [[self objectForKey: key] intValue]; + [self setBool: newValue forKey: @"SOGoAppointmentSendEMailReceipts"]; } -- (void) setBool: (BOOL) value - forKey: (NSString *) key +- (BOOL) appointmentSendEMailReceipts { - // TODO: need special support here for int-DB fields - [self setObject: [NSNumber numberWithBool: value] - forKey: key]; + return [self boolForKey: @"SOGoAppointmentSendEMailReceipts"]; } -- (void) setFloat: (float) value - forKey: (NSString *) key +- (void) setDayStartTime: (NSString *) newValue { - [self setObject: [NSNumber numberWithFloat: value] - forKey: key]; + [self setObject: newValue forKey: @"SOGoDayStartTime"]; } -- (void) setInteger: (int) value - forKey: (NSString *) key +- (NSString *) dayStartTime { - [self setObject: [NSNumber numberWithInt: value] - forKey: key]; + return [self stringForKey: @"SOGoDayStartTime"]; } -- (NSString *) description +- (unsigned int) dayStartHour { - return [values description]; + return [[self dayStartTime] timeValue]; } -@end /* SOGoUserDefaults */ +- (void) setDayEndTime: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoDayEndTime"]; +} + +- (NSString *) dayEndTime +{ + return [self stringForKey: @"SOGoDayEndTime"]; +} + +- (unsigned int) dayEndHour +{ + return [[self dayEndTime] timeValue]; +} + +- (void) setTimeZoneName: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoTimeZone"]; +} + +- (NSString *) timeZoneName +{ + return [self stringForKey: @"SOGoTimeZone"]; +} + +- (void) setTimeZone: (NSTimeZone *) newValue +{ + [self setTimeZoneName: [newValue name]]; +} + +- (NSTimeZone *) timeZone +{ + return [NSTimeZone timeZoneWithName: [self timeZoneName]]; +} + +- (void) setLongDateFormat: (NSString *) newFormat +{ + [self setObject: newFormat forKey: @"SOGoLongDateFormat"]; +} + +- (void) unsetLongDateFormat +{ + [self removeObjectForKey: @"SOGoLongDateFormat"]; +} + +- (NSString *) longDateFormat +{ + return [self stringForKey: @"SOGoLongDateFormat"]; +} + +- (void) setShortDateFormat: (NSString *) newFormat; +{ + [self setObject: newFormat forKey: @"SOGoShortDateFormat"]; +} + +- (void) unsetShortDateFormat +{ + [self removeObjectForKey: @"SOGoShortDateFormat"]; +} + +- (NSString *) shortDateFormat; +{ + return [self stringForKey: @"SOGoShortDateFormat"]; +} + +- (void) setTimeFormat: (NSString *) newFormat +{ + [self setObject: newFormat forKey: @"SOGoTimeFormat"]; +} + +- (void) unsetTimeFormat +{ + [self removeObjectForKey: @"SOGoTimeFormat"]; +} + +- (NSString *) timeFormat +{ + return [self stringForKey: @"SOGoTimeFormat"]; +} + +- (void) setLanguage: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoLanguage"]; +} + +- (NSString *) language +{ + NSString *language; + + /* see SOGoDomainDefaults for the meaning of this */ + language = [source objectForKey: @"SOGoLanguage"]; + if (!(language && [language isKindOfClass: [NSString class]])) + language = [(SOGoDomainDefaults *) parentSource language]; + + return language; +} + +- (void) setMailShowSubscribedFoldersOnly: (BOOL) newValue +{ + [self setBool: newValue forKey: @"SOGoMailShowSubscribedFoldersOnly"]; +} + +- (BOOL) mailShowSubscribedFoldersOnly +{ + return [self boolForKey: @"SOGoMailShowSubscribedFoldersOnly"]; +} + +- (void) setDraftsFolderName: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoDraftsFolderName"]; +} + +- (NSString *) draftsFolderName +{ + return [self stringForKey: @"SOGoDraftsFolderName"]; +} + +- (void) setSentFolderName: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoSentFolderName"]; +} + +- (NSString *) sentFolderName +{ + return [self stringForKey: @"SOGoSentFolderName"]; +} + +- (void) setTrashFolderName: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoTrashFolderName"]; +} + +- (NSString *) trashFolderName +{ + return [self stringForKey: @"SOGoTrashFolderName"]; +} + +- (void) setFirstDayOfWeek: (int) newValue +{ + [self setInteger: newValue forKey: @"SOGoFirstDayOfWeek"]; +} + +- (int) firstDayOfWeek +{ + return [self integerForKey: @"SOGoFirstDayOfWeek"]; +} + +- (void) setFirstWeekOfYear: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoFirstWeekOfYear"]; +} + +- (NSString *) firstWeekOfYear +{ + return [self stringForKey: @"SOGoFirstWeekOfYear"]; +} + +- (void) setMailListViewColumnsOrder: (NSArray *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailListViewColumnsOrder"]; +} + +- (NSArray *) mailListViewColumnsOrder +{ + return [self stringArrayForKey: @"SOGoMailListViewColumnsOrder"]; +} + +- (void) setMailMessageCheck: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailMessageCheck"]; +} + +- (NSString *) mailMessageCheck +{ + return [self stringForKey: @"SOGoMailMessageCheck"]; +} + +- (void) setMailComposeMessageType: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailComposeMessageType"]; +} + +- (NSString *) mailComposeMessageType +{ + return [self stringForKey: @"SOGoMailComposeMessageType"]; +} + +- (void) setMailMessageForwarding: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailMessageForwarding"]; +} + +- (NSString *) mailMessageForwarding +{ + return [self stringForKey: @"SOGoMailMessageForwarding"]; +} + +- (void) setMailReplyPlacement: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailReplyPlacement"]; +} + +- (NSString *) mailReplyPlacement +{ + return [self stringForKey: @"SOGoMailReplyPlacement"]; +} + +- (void) setMailSignature: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailSignature"]; +} + +- (NSString *) mailSignature +{ + return [self stringForKey: @"SOGoMailSignature"]; +} + +- (void) setMailSignaturePlacement: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoMailSignaturePlacement"]; +} + +- (NSString *) mailSignaturePlacement +{ + NSString *signaturePlacement; + + if ([[self mailReplyPlacement] isEqualToString: @"below"]) + // When replying to an email, if the reply is below the quoted text, + // the signature must also be below the quoted text. + signaturePlacement = @"below"; + else + signaturePlacement = [self stringForKey: @"SOGoMailSignaturePlacement"]; + + return signaturePlacement; +} + +- (void) setMailUseOutlookStyleReplies: (BOOL) newValue +{ + [self setBool: newValue forKey: @"SOGoMailUseOutlookStyleReplies"]; +} + +- (BOOL) mailUseOutlookStyleReplies +{ + return [self boolForKey: @"SOGoMailUseOutlookStyleReplies"]; +} + +- (void) setCalendarCategories: (NSArray *) newValues +{ + [self setObject: newValues forKey: @"SOGoCalendarCategories"]; +} + +- (NSArray *) calendarCategories +{ + return [self stringArrayForKey: @"SOGoCalendarCategories"]; +} + +- (void) setCalendarCategoriesColors: (NSArray *) newValues +{ + [self setObject: newValues forKey: @"SOGoCalendarCategoriesColors"]; +} + +- (NSArray *) calendarCategoriesColors +{ + return [self stringArrayForKey: @"SOGoCalendarCategoriesColors"]; +} + +- (void) setCalendarShouldDisplayWeekend: (BOOL) newValue +{ + [self setBool: newValue forKey: @"SOGoCalendarShouldDisplayWeekend"]; +} + +- (BOOL) calendarShouldDisplayWeekend +{ + return [self boolForKey: @"SOGoCalendarShouldDisplayWeekend"]; +} + +- (void) setReminderEnabled: (BOOL) newValue +{ + [self setBool: newValue forKey: @"SOGoReminderEnabled"]; +} + +- (BOOL) reminderEnabled +{ + return [self boolForKey: @"SOGoReminderEnabled"]; +} + +- (void) setReminderTime: (NSString *) newValue +{ + [self setObject: newValue forKey: @"SOGoReminderTime"]; +} + +- (NSString *) reminderTime +{ + return [self stringForKey: @"SOGoReminderTime"]; +} + +- (void) setRemindWithASound: (BOOL) newValue +{ + [self setBool: newValue forKey: @"SOGoRemindWithASound"]; +} + +- (BOOL) remindWithASound +{ + return [self boolForKey: @"SOGoRemindWithASound"]; +} + +- (void) setVacationOptions: (NSMutableDictionary *) newValue +{ + [self setObject: newValue forKey: @"Vacation"]; +} + +- (NSMutableDictionary *) vacationOptions +{ + return [self dictionaryForKey: @"Vacation"]; +} + +- (void) setForwardOptions: (NSMutableDictionary *) newValue +{ + [self setObject: newValue forKey: @"Forward"]; +} + +- (NSMutableDictionary *) forwardOptions +{ + return [self dictionaryForKey: @"Forward"]; +} + +@end diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index 52ca6b177..ce178bd59 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -59,23 +58,8 @@ #import "SOGoUserFolder.h" -static NSString *LDAPContactInfoAttribute = nil; - @implementation SOGoUserFolder -+ (void) initialize -{ - NSUserDefaults *ud; - - if (!LDAPContactInfoAttribute) - { - ud = [NSUserDefaults standardUserDefaults]; - LDAPContactInfoAttribute - = [[ud stringForKey: @"SOGoLDAPContactInfoAttribute"] lowercaseString]; - [LDAPContactInfoAttribute retain]; - } -} - /* hierarchy */ - (NSArray *) toManyRelationshipKeys @@ -230,8 +214,7 @@ static NSString *LDAPContactInfoAttribute = nil; results = [NSMutableDictionary dictionary]; - contacts - = [[SOGoUserManager sharedUserManager] fetchUsersMatching: uid]; + contacts = [[SOGoUserManager sharedUserManager] fetchUsersMatching: uid]; enumerator = [contacts objectEnumerator]; while ((contact = [enumerator nextObject])) { @@ -424,13 +407,10 @@ static NSString *LDAPContactInfoAttribute = nil; field = [currentUser objectForKey: @"c_email"]; [fetch appendFormat: @"%@", [field stringByEscapingXMLString]]; - if (LDAPContactInfoAttribute) - { - field = [currentUser objectForKey: LDAPContactInfoAttribute]; - if ([field length]) - [fetch appendFormat: @"%@", - [field stringByEscapingXMLString]]; - } + field = [currentUser objectForKey: @"info"]; + if ([field length]) + [fetch appendFormat: @"%@", + [field stringByEscapingXMLString]]; [fetch appendString: @""]; } } diff --git a/SoObjects/SOGo/SOGoUserManager.h b/SoObjects/SOGo/SOGoUserManager.h index 0513b900f..44cd73a73 100644 --- a/SoObjects/SOGo/SOGoUserManager.h +++ b/SoObjects/SOGo/SOGoUserManager.h @@ -33,6 +33,8 @@ @class LDAPSource; +@protocol SOGoSource; + @interface SOGoUserManager : NSObject { @private @@ -42,17 +44,16 @@ + (id) sharedUserManager; -+ (BOOL) defaultMailDomainIsConfigured; - -- (NSArray *) sourceIDs; -- (NSDictionary *) metadataForSourceID: (NSString *) sourceID; +- (NSArray *) sourceIDsInDomain: (NSString *) domain; - (NSArray *) authenticationSourceIDs; -- (NSArray *) addressBookSourceIDs; +- (NSArray *) addressBookSourceIDsInDomain: (NSString *) domain; -- (LDAPSource *) sourceWithID: (NSString *) sourceID; +- (NSObject *) sourceWithID: (NSString *) sourceID; +- (NSDictionary *) metadataForSourceID: (NSString *) sourceID; - (NSString *) displayNameForSourceWithID: (NSString *) sourceID; - (NSDictionary *) contactInfosForUserWithUIDorEmail: (NSString *) uid; -- (NSArray *) fetchContactsMatching: (NSString *) match; +- (NSArray *) fetchContactsMatching: (NSString *) match + inDomain: (NSString *) domain; - (NSArray *) fetchUsersMatching: (NSString *) filter; - (NSString *) getCNForUID: (NSString *) uid; diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index dfb314ef4..586f3a566 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -25,13 +25,14 @@ #import #import #import -#import #import #import #import "NSDictionary+BSJSONAdditions.h" #import "NSArray+Utilities.h" +#import "SOGoDomainDefaults.h" #import "SOGoSource.h" +#import "SOGoSystemDefaults.h" #import "SOGoUserManager.h" #import "SOGoCache.h" #import "SOGoSource.h" @@ -39,75 +40,27 @@ #import "LDAPSource.h" #import "SQLSource.h" -static NSString *defaultMailDomain = nil; -static NSString *LDAPContactInfoAttribute = nil; -static BOOL defaultMailDomainIsConfigured = NO; -static BOOL forceImapLoginWithEmail = NO; - -#if defined(THREADSAFE) -static NSLock *lock = nil; -#endif - @implementation SOGoUserManager -+ (void) initialize -{ - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - if (!defaultMailDomain) - { - defaultMailDomain = [ud stringForKey: @"SOGoDefaultMailDomain"]; - [defaultMailDomain retain]; - defaultMailDomainIsConfigured = YES; - - if (!defaultMailDomain) - { - [self warnWithFormat: - @"no domain specified for SOGoDefaultMailDomain," - @" value set to 'localhost'"]; - defaultMailDomain = @"localhost"; - } - - LDAPContactInfoAttribute = [[ud stringForKey: @"SOGoLDAPContactInfoAttribute"] lowercaseString]; - [LDAPContactInfoAttribute retain]; - } - if (!forceImapLoginWithEmail) - forceImapLoginWithEmail = [ud boolForKey: @"SOGoForceIMAPLoginWithEmail"]; -#if defined(THREADSAFE) - lock = [NSLock new]; -#endif -} - -+ (BOOL) defaultMailDomainIsConfigured -{ - return defaultMailDomainIsConfigured; -} - + (id) sharedUserManager { static id sharedUserManager = nil; -#if defined(THREADSAFE) - [lock lock]; -#endif if (!sharedUserManager) sharedUserManager = [self new]; -#if defined(THREADSAFE) - [lock unlock]; -#endif return sharedUserManager; } - (void) _registerSource: (NSDictionary *) udSource + inDomain: (NSString *) domain { NSString *sourceID, *value, *type; NSMutableDictionary *metadata; - id ldapSource; + NSObject *ldapSource; BOOL isAddressBook; Class c; - + sourceID = [udSource objectForKey: @"id"]; if ([sourceID length] > 0) { @@ -118,13 +71,16 @@ static NSLock *lock = nil; else c = [SQLSource class]; - ldapSource = [c sourceFromUDSource: udSource]; + ldapSource = [c sourceFromUDSource: udSource + inDomain: domain]; if (sourceID) [_sources setObject: ldapSource forKey: sourceID]; else [self errorWithFormat: @"id field missing in an user source," @" check the SOGoUserSources defaults"]; metadata = [NSMutableDictionary dictionary]; + if (domain) + [metadata setObject: domain forKey: @"domain"]; value = [udSource objectForKey: @"canAuthenticate"]; if (value) [metadata setObject: value forKey: @"canAuthenticate"]; @@ -155,60 +111,51 @@ static NSLock *lock = nil; @" without id (skipped)"]; } -- (void) _prepareSourcesWithDefaults: (NSUserDefaults *) ud +- (int) _registerSourcesInDomain: (NSString *) domain { - id o, sources; + NSArray *userSources; unsigned int count, max; + SOGoDomainDefaults *dd; + + if (domain) + dd = [SOGoDomainDefaults defaultsForDomain: domain]; + else + dd = [SOGoSystemDefaults sharedSystemDefaults]; + + userSources = [dd userSources]; + max = [userSources count]; + for (count = 0; count < max; count++) + [self _registerSource: [userSources objectAtIndex: count] + inDomain: domain]; + + return max; +} + +- (void) _prepareSources +{ + NSArray *domains; + unsigned int count, max, total; _sources = [[NSMutableDictionary alloc] init]; _sourcesMetadata = [[NSMutableDictionary alloc] init]; - sources = [NSMutableArray array]; - o = [ud arrayForKey: @"SOGoLDAPSources"]; + total = [self _registerSourcesInDomain: nil]; + domains = [[SOGoSystemDefaults sharedSystemDefaults] domainIds]; + max = [domains count]; + for (count = 0; count < max; count++) + total += [self _registerSourcesInDomain: [domains objectAtIndex: count]]; - if (o) - { - [self errorWithFormat: @"Using depecrated SOGoLDAPSources default. You should now use SOGoUserSources."]; - - if ([o isKindOfClass: [NSArray class]]) - [sources addObjectsFromArray: o]; - else - [self errorWithFormat: @"SOGoLDAPSources is NOT an array. Check your defaults. You should now use SOGoUserSources nonetheless."]; - } - - o = [ud arrayForKey: @"SOGoUserSources"]; - - if (o) - { - if ([o isKindOfClass: [NSArray class]]) - [sources addObjectsFromArray: o]; - else - [self errorWithFormat: @"SOGoUserSources is NOT an array. Check your defaults."]; - } - - if ([sources count]) - { - max = [sources count]; - for (count = 0; count < max; count++) - [self _registerSource: [sources objectAtIndex: count]]; - } - else - { - [self errorWithFormat: @"No authentication sources defined - nobody will be able to login. Check your defaults."]; - } + if (!total) + [self errorWithFormat: @"No authentication sources defined - nobody will be able to login. Check your defaults."]; } - (id) init { - NSUserDefaults *ud; - if ((self = [super init])) { - ud = [NSUserDefaults standardUserDefaults]; - _sources = nil; _sourcesMetadata = nil; - [self _prepareSourcesWithDefaults: ud]; + [self _prepareSources]; } return self; @@ -221,31 +168,60 @@ static NSLock *lock = nil; [super dealloc]; } -- (NSArray *) sourceIDs +- (NSArray *) sourceIDsInDomain: (NSString *) domain { - return [_sources allKeys]; + NSMutableArray *sourceIDs; + NSArray *keys; + int count, max; + NSString *currentID, *sourceDomain; + NSObject *currentSource; + + keys = [_sources allKeys]; + max = [keys count]; + sourceIDs = [NSMutableArray arrayWithCapacity: max]; + for (count = 0; count < max; count++) + { + currentID = [keys objectAtIndex: count]; + currentSource = [_sources objectForKey: currentID]; + sourceDomain = [currentSource domain]; + if (!domain || [sourceDomain isEqualToString: domain]) + [sourceIDs addObject: currentID]; + } + + return sourceIDs; } - (NSArray *) _sourcesOfType: (NSString *) sourceType + inDomain: (NSString *) domain { NSMutableArray *sourceIDs; NSEnumerator *allIDs; NSString *currentID; - NSNumber *canAuthenticate; + NSNumber *typeValue; + NSDictionary *metadata; sourceIDs = [NSMutableArray array]; allIDs = [[_sources allKeys] objectEnumerator]; - while ((currentID = [allIDs nextObject])) + while ((currentID = [allIDs nextObject])) { - canAuthenticate = [[_sourcesMetadata objectForKey: currentID] - objectForKey: sourceType]; - if ([canAuthenticate boolValue]) - [sourceIDs addObject: currentID]; + metadata = [_sourcesMetadata objectForKey: currentID]; + if (!domain + || [[metadata objectForKey: @"domain"] isEqualToString: domain]) + { + typeValue = [metadata objectForKey: sourceType]; + if ([typeValue boolValue]) + [sourceIDs addObject: currentID]; + } } return sourceIDs; } +- (NSObject *) sourceWithID: (NSString *) sourceID +{ + return [_sources objectForKey: sourceID]; +} + - (NSDictionary *) metadataForSourceID: (NSString *) sourceID { return [_sourcesMetadata objectForKey: sourceID]; @@ -253,17 +229,12 @@ static NSLock *lock = nil; - (NSArray *) authenticationSourceIDs { - return [self _sourcesOfType: @"canAuthenticate"]; + return [self _sourcesOfType: @"canAuthenticate" inDomain: nil]; } -- (NSArray *) addressBookSourceIDs +- (NSArray *) addressBookSourceIDsInDomain: (NSString *) domain { - return [self _sourcesOfType: @"isAddressBook"]; -} - -- (LDAPSource *) sourceWithID: (NSString *) sourceID -{ - return [_sources objectForKey: sourceID]; + return [self _sourcesOfType: @"isAddressBook" inDomain: domain]; } - (NSString *) displayNameForSourceWithID: (NSString *) sourceID @@ -308,7 +279,18 @@ static NSLock *lock = nil; - (NSString *) getImapLoginForUID: (NSString *) uid { - return ((forceImapLoginWithEmail) ? [self getEmailForUID: uid] : uid); + NSDictionary *contactInfos; + NSString *domain; + SOGoDomainDefaults *dd; + + contactInfos = [self contactInfosForUserWithUIDorEmail: uid]; + domain = [contactInfos objectForKey: @"c_domain"]; + if ([domain length]) + dd = [SOGoDomainDefaults defaultsForDomain: domain]; + else + dd = [SOGoSystemDefaults sharedSystemDefaults]; + + return ([dd forceIMAPLoginWithEmail] ? [self getEmailForUID: uid] : uid); } - (NSString *) getUIDForEmail: (NSString *) email @@ -324,7 +306,7 @@ static NSLock *lock = nil; - (BOOL) _sourceCheckLogin: (NSString *) login andPassword: (NSString *) password { - id ldapSource; + NSObject *ldapSource; NSEnumerator *authIDs; NSString *currentID; BOOL checkOK; @@ -348,10 +330,6 @@ static NSLock *lock = nil; NSString *dictPassword, *jsonUser; BOOL checkOK; -#if defined(THREADSAFE) - [lock lock]; -#endif - jsonUser = [[SOGoCache sharedCache] userAttributesForLogin: login]; currentUser = [NSMutableDictionary dictionaryWithJSONString: jsonUser]; dictPassword = [currentUser objectForKey: @"password"]; @@ -378,23 +356,25 @@ static NSLock *lock = nil; else checkOK = NO; -#if defined(THREADSAFE) - [lock unlock]; -#endif - return checkOK; } - (void) _fillContactMailRecords: (NSMutableDictionary *) contact { - NSString *uid, *systemEmail; + NSString *uid, *domain, *systemEmail; NSMutableArray *emails; + SOGoDomainDefaults *dd; + domain = [contact objectForKey: @"c_domain"]; + if ([domain length]) + dd = [SOGoDomainDefaults defaultsForDomain: domain]; + else + dd = [SOGoSystemDefaults sharedSystemDefaults]; emails = [contact objectForKey: @"emails"]; uid = [contact objectForKey: @"c_uid"]; if ([uid rangeOfString: @"@"].location == NSNotFound) systemEmail - = [NSString stringWithFormat: @"%@@%@", uid, defaultMailDomain]; + = [NSString stringWithFormat: @"%@@%@", uid, [dd mailDomain]]; else systemEmail = uid; [emails addObject: systemEmail]; @@ -422,7 +402,8 @@ static NSLock *lock = nil; [currentUser setObject: [NSNumber numberWithBool: YES] forKey: @"MailAccess"]; - ldapSources = [[self authenticationSourceIDs] objectEnumerator]; + ldapSources = [[self authenticationSourceIDs] + objectEnumerator]; while ((sourceID = [ldapSources nextObject])) { currentSource = [_sources objectForKey: sourceID]; @@ -500,15 +481,13 @@ static NSLock *lock = nil; contactInfos = [NSMutableDictionary dictionary]; jsonUser = [[SOGoCache sharedCache] userAttributesForLogin: aUID]; currentUser = [NSMutableDictionary dictionaryWithJSONString: jsonUser]; -#if defined(THREADSAFE) - [lock lock]; -#endif if (!([currentUser objectForKey: @"emails"] && [currentUser objectForKey: @"cn"])) { - // We make sure that we either have no occurence of a cache entry or that - // we have an occurence with only a cached password. In the latter case, we - // update the entry with the remaining information and recache the value. + // We make sure that we either have no occurence of a cache entry or + // that we have an occurence with only a cached password. In the + // latter case, we update the entry with the remaining information + // and recache the value. if (!currentUser || ([currentUser count] == 1 && [currentUser objectForKey: @"password"])) { newUser = YES; @@ -528,10 +507,6 @@ static NSLock *lock = nil; currentUser = nil; } } - -#if defined(THREADSAFE) - [lock unlock]; -#endif } else currentUser = nil; @@ -545,7 +520,7 @@ static NSLock *lock = nil; NSDictionary *userEntry; NSArray *newContacts; NSMutableArray *emails; - NSString *uid, *email, *infoAttribute; + NSString *uid, *email, *info; compactContacts = [NSMutableDictionary dictionary]; while ((userEntry = [contacts nextObject])) @@ -581,16 +556,10 @@ static NSLock *lock = nil; email = [userEntry objectForKey: @"xmozillasecondemail"]; if (email && ![emails containsObject: email]) [emails addObject: email]; - if ([LDAPContactInfoAttribute length] - && ![[returnContact - objectForKey: LDAPContactInfoAttribute] length]) - { - infoAttribute - = [userEntry objectForKey: LDAPContactInfoAttribute]; - if ([infoAttribute length]) - [returnContact setObject: infoAttribute - forKey: LDAPContactInfoAttribute]; - } + info = [userEntry objectForKey: @"c_info"]; + if ([info length] > 0 + && ![[returnContact objectForKey: @"c_info"] length]) + [returnContact setObject: info forKey: @"c_info"]; [self _fillContactMailRecords: returnContact]; } } @@ -621,15 +590,17 @@ static NSLock *lock = nil; } - (NSArray *) fetchContactsMatching: (NSString *) filter + inDomain: (NSString *) domain { - return [self _fetchEntriesInSources: [self addressBookSourceIDs] - matching: filter]; + return [self + _fetchEntriesInSources: [self addressBookSourceIDsInDomain: domain] + matching: filter]; } - (NSArray *) fetchUsersMatching: (NSString *) filter { return [self _fetchEntriesInSources: [self authenticationSourceIDs] - matching: filter]; + matching: filter]; } - (NSString *) getLoginForDN: (NSString *) theDN diff --git a/SoObjects/SOGo/SOGoUserProfile.h b/SoObjects/SOGo/SOGoUserProfile.h new file mode 100644 index 000000000..d0248dc8f --- /dev/null +++ b/SoObjects/SOGo/SOGoUserProfile.h @@ -0,0 +1,88 @@ +/* + Copyright (C) 2008-2009 Inverse inc. + Copyright (C) 2005 SKYRIX Software AG + + This file is part of SOGo. + + SOGo 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. + + SOGo 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 __SOGoUserDefaults_H_ +#define __SOGoUserDefaults_H_ + +#import + +/* + SOGoUserDefaults + + An object with the same API like NSUserDefaults which retrieves profile + information for users in the database. + + It does NOT store values internally but rather uses an external + mutable dictionary for this (generally coming from SOGoCache) +*/ + +@class NSString, NSUserDefaults, NSArray, NSDictionary; +@class NSData, NSCalendarDate, NSMutableDictionary; + +typedef enum _SOGoUserProfileType { + SOGoUserProfileTypeDefaults, /* configurable user preferences */ + SOGoUserProfileTypeSettings /* user environment state */ +} SOGoUserProfileType; + +@interface SOGoUserProfile : NSObject +{ + NSString *uid; + NSMutableDictionary *values; + SOGoUserProfileType profileType; + + struct + { + BOOL modified; + BOOL isNew; + BOOL ready; + } defFlags; +} + ++ (id) userProfileWithType: (SOGoUserProfileType) newProfileType + forUID: (NSString *) theUID; + +- (void) setProfileType: (SOGoUserProfileType) newProfileType; +- (NSString *) profileTypeName; + +- (void) setUID: (NSString *) newUID; +- (NSString *) uid; + +/* value access */ +- (void) setValues: (NSDictionary *) theValues; +- (NSDictionary *) values; + +- (void) setObject: (id) value + forKey: (NSString *) key; +- (id) objectForKey: (NSString *) key; +- (void) removeObjectForKey: (NSString *) key; + +- (NSString *) jsonRepresentation; + +- (void) fetchProfile; + +/* saving changes */ + +- (BOOL) synchronize; + +@end + +#endif /* __SOGoUserDefaults_H__ */ diff --git a/SoObjects/SOGo/SOGoUserProfile.m b/SoObjects/SOGo/SOGoUserProfile.m new file mode 100644 index 000000000..a2ef7b5d8 --- /dev/null +++ b/SoObjects/SOGo/SOGoUserProfile.m @@ -0,0 +1,373 @@ +/* + Copyright (C) 2008-2009 Inverse inc. + Copyright (C) 2005 SKYRIX Software AG + + This file is part of SOGo. + + SOGo 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. + + SOGo 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. +*/ + +#import +#import +#import + +#import +#import + +#import "NSObject+Utilities.h" +#import "NSString+Utilities.h" + +#import "NSDictionary+BSJSONAdditions.h" +#import "SOGoCache.h" + +#import "SOGoUserProfile.h" + +@implementation SOGoUserProfile + ++ (id) userProfileWithType: (SOGoUserProfileType) newProfileType + forUID: (NSString *) newUID +{ + id userProfile; + + userProfile = [self new]; + [userProfile autorelease]; + [userProfile setProfileType: newProfileType]; + [userProfile setUID: newUID]; + + return userProfile; +} + +- (id) init +{ + if ((self = [super init])) + { + uid = nil; + values = nil; + defFlags.ready = NO; + defFlags.isNew = NO; + } + + return self; +} + +- (void) dealloc +{ + [values release]; + [uid release]; + [super dealloc]; +} + +/* accessors */ + +- (void) setProfileType: (SOGoUserProfileType) newProfileType +{ + profileType = newProfileType; +} + +- (NSString *) profileTypeName +{ + NSString *profileTypeName; + + switch (profileType) + { + case SOGoUserProfileTypeDefaults: + profileTypeName = @"defaults profile"; + break; + case SOGoUserProfileTypeSettings: + profileTypeName = @"settings profile"; + break; + default: + profileTypeName = @""; + } + + return profileTypeName; +} + +- (void) setUID: (NSString *) newUID +{ + ASSIGN (uid, newUID); +} + +- (NSString *) uid +{ + return uid; +} + +/* subclass methods */ + +- (BOOL) storeJSONProfileInDB: (NSString *) jsonRepresentation +{ + [self subclassResponsibility: _cmd]; + + return NO; +} + +- (NSString *) fetchJSONProfileFromDB +{ + [self subclassResponsibility: _cmd]; + + return nil; +} + +/* operation */ + +- (NSString *) _convertPListToJSON: (NSString *) plistValue +{ + NSData *plistData; + NSDictionary *plist; + NSString *jsonValue, *error; + + plistData = [plistValue dataUsingEncoding: NSUTF8StringEncoding]; + plist = [NSPropertyListSerialization propertyListFromData: plistData + mutabilityOption: NSPropertyListMutableContainers + format: NULL + errorDescription: &error]; + if (plist) + { + [self logWithFormat: @"database value for %@" + @" (uid: '%@') is a plist", [self profileTypeName], uid]; + jsonValue = [plist jsonStringValue]; + } + else + { + [self errorWithFormat: @"failed to parse property list value for %@" + @" (error: %@): %@", [self profileTypeName], error, plistValue]; + jsonValue = nil; + } + + if (!jsonValue) + jsonValue = @"{}"; + + return jsonValue; +} + +- (NSString *) jsonRepresentation +{ + SOGoCache *cache; + NSString *jsonValue; + + cache = [SOGoCache sharedCache]; + if (profileType == SOGoUserProfileTypeDefaults) + jsonValue = [cache userDefaultsForLogin: uid]; + else + jsonValue = [cache userSettingsForLogin: uid]; + if ([jsonValue length]) + { + defFlags.ready = YES; + defFlags.isNew = NO; + } + else + { + jsonValue = [self fetchJSONProfileFromDB]; + if ([jsonValue length]) + { + if (![jsonValue isJSONString]) + jsonValue = [self _convertPListToJSON: jsonValue]; + if (profileType == SOGoUserProfileTypeDefaults) + [cache setUserDefaults: jsonValue forLogin: uid]; + else + [cache setUserSettings: jsonValue forLogin: uid]; + } + else + jsonValue = @"{}"; + } + + return jsonValue; +} + +- (void) primaryFetchProfile +{ + NSString *jsonValue; + + defFlags.modified = NO; + [values release]; + jsonValue = [self jsonRepresentation]; + values = [NSMutableDictionary dictionaryWithJSONString: jsonValue]; + if (values) + [values retain]; + else + [self errorWithFormat: @"failure parsing json string: '%@'", jsonValue]; +} + +- (BOOL) _isReadyOrRetry +{ + BOOL rc; + + if (defFlags.ready) + rc = YES; + else + { + [self primaryFetchProfile]; + rc = defFlags.ready; + } + + return rc; +} + +- (NSString *) _sqlJsonRepresentation: (NSString *) jsonRepresentation +{ + NSMutableString *sql; + + sql = [jsonRepresentation mutableCopy]; + [sql autorelease]; + [sql replaceString: @"\\" withString: @"\\\\"]; + [sql replaceString: @"'" withString: @"''"]; + + return sql; +} + +- (BOOL) primaryStoreProfile +{ + NSString *jsonRepresentation; + SOGoCache *cache; + BOOL rc; + + jsonRepresentation = [values jsonStringValue]; + if (jsonRepresentation) + { + rc = [self storeJSONProfileInDB: jsonRepresentation]; + if (rc) + { + cache = [SOGoCache sharedCache]; + if (profileType == SOGoUserProfileTypeDefaults) + [cache setUserDefaults: jsonRepresentation + forLogin: uid]; + else + [cache setUserSettings: jsonRepresentation + forLogin: uid]; + } + } + else + { + [self errorWithFormat: @"Unable to convert (%@) to a JSON string for" + @" type: %@ and login: %@", values, [self profileTypeName], uid]; + rc = NO; + } + + return rc; +} + +- (void) fetchProfile +{ + if (!values) + [self primaryFetchProfile]; +} + +/* value access */ +- (void) setValues: (NSDictionary *) theValues +{ + if ([self _isReadyOrRetry]) + { + [values release]; + values = [[NSMutableDictionary alloc] init]; + [values addEntriesFromDictionary: theValues]; + defFlags.modified = YES; + } +} + +- (NSDictionary *) values +{ + NSDictionary *returnValues; + + if ([self _isReadyOrRetry]) + returnValues = values; + else + returnValues = nil; + + return returnValues; +} + +- (void) setObject: (id) value + forKey: (NSString *) key +{ + id old; + + if ([self _isReadyOrRetry]) + { + /* check whether the value is actually modified */ + if (!defFlags.modified) + { + old = [values objectForKey: key]; + if (old == value || [old isEqual: value]) /* value didn't change */ + return; + +#warning Note that this work-around only works for first-level objects. + /* we need to this because our typed accessors convert to strings */ + // TODO: especially problematic with bools + if ([value isKindOfClass: [NSString class]]) { + if (![old isKindOfClass: [NSString class]]) + if ([[old description] isEqualToString: value]) + return; + } + } + + /* set in hash and mark as modified */ + if (value) + [values setObject: value forKey: key]; + else + [values removeObjectForKey: key]; + + defFlags.modified = YES; + } +} + +- (void) removeObjectForKey: (NSString *) key +{ + [self setObject: nil forKey: key]; +} + +- (id) objectForKey: (NSString *) key +{ + return [[self values] objectForKey: key]; +} + +/* saving changes */ + +- (BOOL) synchronize +{ + BOOL rc; +// if (!defFlags.modified) /* was not modified */ +// return YES; + + rc = NO; + + /* ensure fetched data (more or less guaranteed by modified!=0) */ + [self fetchProfile]; + if (values) + { + /* store */ + if ([self primaryStoreProfile]) + { + rc = YES; + // /* refetch */ + // [self primaryFetchProfile]; + } + else + { + [self primaryFetchProfile]; + return NO; + } + } + + return rc; +} + +- (NSString *) description +{ + return [values description]; +} + +@end diff --git a/SoObjects/SOGo/SOGoWebAuthenticator.m b/SoObjects/SOGo/SOGoWebAuthenticator.m index 40c6ee314..f18417ee0 100644 --- a/SoObjects/SOGo/SOGoWebAuthenticator.m +++ b/SoObjects/SOGo/SOGoWebAuthenticator.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import diff --git a/SoObjects/SOGo/SQLSource.h b/SoObjects/SOGo/SQLSource.h index 625ababcc..fd1c384e5 100644 --- a/SoObjects/SOGo/SQLSource.h +++ b/SoObjects/SOGo/SQLSource.h @@ -35,6 +35,8 @@ @interface SQLSource : NSObject { NSString *_sourceID; + NSString *_domain; + NSString *_domainAttribute; NSArray *_mailFields; NSString *_userPasswordAlgorithm; NSURL *_viewURL; diff --git a/SoObjects/SOGo/SQLSource.m b/SoObjects/SOGo/SQLSource.m index ee25cfce5..8a9db9cb6 100644 --- a/SoObjects/SOGo/SQLSource.m +++ b/SoObjects/SOGo/SQLSource.m @@ -68,8 +68,10 @@ @implementation SQLSource + (id) sourceFromUDSource: (NSDictionary *) udSource + inDomain: (NSString *) domain { - return [[[self alloc] initFromUDSource: udSource] autorelease]; + return [[[self alloc] initFromUDSource: udSource + inDomain: domain] autorelease]; } - (id) init @@ -96,7 +98,10 @@ } - (id) initFromUDSource: (NSDictionary *) udSource + inDomain: (NSString *) sourceDomain { + NSString *udDomainAttribute; + self = [self init]; ASSIGN(_sourceID, [udSource objectForKey: @"id"]); @@ -108,7 +113,30 @@ if ([udSource objectForKey: @"viewURL"]) _viewURL = [[NSURL alloc] initWithString: [udSource objectForKey: @"viewURL"]]; - + +#warning this domain code has no effect yet + /* FIXME: the queries below do not setup c_domain. */ + udDomainAttribute = [udSource objectForKey: @"domainAttribute"]; + if ([sourceDomain length]) + { + if ([udDomainAttribute length]) + { + [self errorWithFormat: @"cannot define 'domainAttribute'" + @" for a domain-based source (%@)", _sourceID]; + [self autorelease]; + return nil; + } + else + { + ASSIGN (_domain, sourceDomain); + } + } + else + { + if ([udDomainAttribute length]) + ASSIGN (_domainAttribute, udDomainAttribute); + } + if (!_viewURL) { [self autorelease]; @@ -118,6 +146,11 @@ return self; } +- (NSString *) domain +{ + return _domain; +} + - (BOOL) _isPassword: (NSString *) plainPassword equalTo: (NSString *) encryptedPassword { diff --git a/SoObjects/SOGo/WOContext+SOGo.h b/SoObjects/SOGo/WOContext+SOGo.h index 69b4db760..f13bbcd0c 100644 --- a/SoObjects/SOGo/WOContext+SOGo.h +++ b/SoObjects/SOGo/WOContext+SOGo.h @@ -23,11 +23,11 @@ #ifndef WOCONTEXT_SOGo_H #define WOCONTEXT_SOGo_H -#import +#import @interface WOContext (SOGoSOPEUtilities) -- (NSArray *)resourceLookupLanguages; +- (NSArray *) resourceLookupLanguages; @end diff --git a/SoObjects/SOGo/WOContext+SOGo.m b/SoObjects/SOGo/WOContext+SOGo.m index cadcbaf3c..c1e4c9c6e 100644 --- a/SoObjects/SOGo/WOContext+SOGo.m +++ b/SoObjects/SOGo/WOContext+SOGo.m @@ -27,7 +27,8 @@ #import #import -#import +#import +#import #import "WOContext+SOGo.h" @@ -36,16 +37,32 @@ - (NSArray *) resourceLookupLanguages { NSMutableArray *languages; + NSArray *browserLanguages; + SOGoUser *user; + NSString *language; languages = [NSMutableArray array]; - - if (activeUser && [activeUser language]) - [languages addObject: [activeUser language]]; - - if ([self hasSession]) - [languages addObjectsFromArray: [[self session] languages]]; + user = [self activeUser]; + if ([user isKindOfClass: [SOGoUser class]]) + { + language = [[user userDefaults] language]; + [languages addObject: language]; + language = [[user domainDefaults] language]; + [languages addObject: language]; + } else - [languages addObjectsFromArray: [[self request] browserLanguages]]; + { + browserLanguages = [[self request] browserLanguages]; + [languages addObjectsFromArray: browserLanguages]; + } + + // if (activeUser && [activeUser language]) + // [languages addObject: [activeUser language]]; + + // if ([self hasSession]) + // [languages addObjectsFromArray: [[self session] languages]]; + // else + // [languages addObjectsFromArray: [[self request] browserLanguages]]; return languages; } diff --git a/SoObjects/SOGo/iCalEntityObject+Utilities.m b/SoObjects/SOGo/iCalEntityObject+Utilities.m index e6213c31a..3467c7e75 100644 --- a/SoObjects/SOGo/iCalEntityObject+Utilities.m +++ b/SoObjects/SOGo/iCalEntityObject+Utilities.m @@ -29,6 +29,8 @@ #import "iCalEntityObject+Utilities.h" +#warning we should move this into Appointments. + @implementation iCalEntityObject (SOGoAddition) - (iCalPerson *) findParticipant: (SOGoUser *) user diff --git a/Tools/SOGoToolBackup.m b/Tools/SOGoToolBackup.m index 6d45a3f9c..cabd1827f 100644 --- a/Tools/SOGoToolBackup.m +++ b/Tools/SOGoToolBackup.m @@ -37,7 +37,7 @@ #import #import #import -#import +#import #import "SOGoToolBackup.h" @@ -301,7 +301,7 @@ { NSEnumerator *ldapSources; NSString *sourceID; - LDAPSource *currentSource; + NSObject *currentSource; SOGoUserManager *lm; NSDictionary *userEntry; BOOL done; diff --git a/Tools/SOGoToolRestore.m b/Tools/SOGoToolRestore.m index ff2e26ff0..a9a3198a6 100644 --- a/Tools/SOGoToolRestore.m +++ b/Tools/SOGoToolRestore.m @@ -36,7 +36,7 @@ #import #import #import -#import +#import #import "SOGoToolRestore.h" @@ -527,7 +527,7 @@ - (BOOL) restoreUserPreferencesFromUserRecord: (NSDictionary *) userRecord { SOGoUser *sogoUser; - NSUserDefaults *storedPreferences; + SOGoUserProfile *up; NSArray *preferences; BOOL rc; @@ -537,13 +537,13 @@ rc = YES; sogoUser = [SOGoUser userWithLogin: userID roles: nil]; - storedPreferences = [sogoUser userDefaults]; - [storedPreferences setValues: [preferences objectAtIndex: 0]]; - [storedPreferences synchronize]; + up = [[sogoUser userDefaults] source]; + [up setValues: [preferences objectAtIndex: 0]]; + [up synchronize]; - storedPreferences = [sogoUser userSettings]; - [storedPreferences setValues: [preferences objectAtIndex: 1]]; - [storedPreferences synchronize]; + up = [[sogoUser userSettings] source]; + [up setValues: [preferences objectAtIndex: 1]]; + [up synchronize]; } else { diff --git a/UI/Common/UIxFolderActions.h b/UI/Common/UIxFolderActions.h index 57c174646..1a89752f8 100644 --- a/UI/Common/UIxFolderActions.h +++ b/UI/Common/UIxFolderActions.h @@ -26,18 +26,18 @@ #import @class NSString; -@class NSUserDefaults; @class NSMutableString; @class NSMutableDictionary; @class LDAPUserManager; @class SOGoGCSFolder; +@class SOGoUserSettings; @interface UIxFolderActions : WODirectAction { SOGoGCSFolder *clientObject; LDAPUserManager *um; - NSUserDefaults *ud; + SOGoUserSettings *us; NSString *owner; NSString *login; NSString *baseFolder; diff --git a/UI/Common/UIxFolderActions.m b/UI/Common/UIxFolderActions.m index 41977c43c..077b47475 100644 --- a/UI/Common/UIxFolderActions.m +++ b/UI/Common/UIxFolderActions.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -42,6 +41,7 @@ #import #import #import +#import #import "WODirectAction+SOGo.h" @@ -62,11 +62,11 @@ baseFolder = [[clientObject container] nameInContainer]; um = [SOGoUserManager sharedUserManager]; - ud = [activeUser userSettings]; - moduleSettings = [ud objectForKey: baseFolder]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: baseFolder]; if (!moduleSettings) moduleSettings = [NSMutableDictionary dictionary]; - [ud setObject: moduleSettings forKey: baseFolder]; + [us setObject: moduleSettings forKey: baseFolder]; mailInvitationParam = [[context request] formValueForKey: @"mail-invitation"]; @@ -174,7 +174,7 @@ else [folderSubscription addObjectUniquely: folderName]; - [ud synchronize]; + [us synchronize]; return [self responseWith204]; } diff --git a/UI/Common/UIxObjectActions.m b/UI/Common/UIxObjectActions.m index f5fa5f6be..4a6c540ac 100644 --- a/UI/Common/UIxObjectActions.m +++ b/UI/Common/UIxObjectActions.m @@ -22,7 +22,6 @@ #import #import -#import #import #import diff --git a/UI/Common/UIxPageFrame.m b/UI/Common/UIxPageFrame.m index ca65b128f..79c220eb0 100644 --- a/UI/Common/UIxPageFrame.m +++ b/UI/Common/UIxPageFrame.m @@ -1,3 +1,4 @@ + /* Copyright (C) 2004-2005 SKYRIX Software AG @@ -21,30 +22,21 @@ #import #import -#import #import +#import #import #import -#import +#import +#import +#import #import #import "UIxPageFrame.h" -static NSString *siteFavicon = nil; - @implementation UIxPageFrame -+ (void) initialize -{ - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - siteFavicon = [ud stringForKey: @"SOGoFaviconRelativeURL"]; - [siteFavicon retain]; -} - - (id) init { if ((self = [super init])) @@ -184,7 +176,14 @@ static NSString *siteFavicon = nil; - (NSString *) siteFavicon { - return (!siteFavicon ? [self urlForResourceFilename: @"sogo.ico"] : siteFavicon); + NSString *siteFavicon; + + siteFavicon = [[SOGoSystemDefaults sharedSystemDefaults] + faviconRelativeURL]; + + return (siteFavicon + ? siteFavicon + : [self urlForResourceFilename: @"sogo.ico"]); } /* page based JavaScript */ @@ -192,13 +191,13 @@ static NSString *siteFavicon = nil; - (NSString *) _stringsForFramework: (NSString *) framework { NSString *language, *frameworkName; + SOGoUserDefaults *ud; id table; frameworkName = [NSString stringWithFormat: @"%@.SOGo", (framework ? framework : [self frameworkName])]; - language = [[context activeUser] language]; - if (!language) - language = [SOGoUser language]; + ud = [[context activeUser] userDefaults]; + language = [ud language]; table = [[self resourceManager] stringTableWithName: @"Localizable" @@ -438,24 +437,21 @@ static NSString *siteFavicon = nil; - (NSString *) userLanguage { - NSString *language; + SOGoUserDefaults *ud; - language = [[context activeUser] language]; - if (!language) - language = [SOGoUser language]; + ud = [[context activeUser] userDefaults]; - return language; + return [ud language]; } - (NSString *) userSettings { - SOGoUserDefaults *userSettings; + SOGoUserSettings *us; NSString *jsonResult; - userSettings = (SOGoUserDefaults *)[[context activeUser] userSettings]; - if (userSettings) - jsonResult = [userSettings jsonRepresentation]; - else + us = [[context activeUser] userSettings]; + jsonResult = [[us source] jsonRepresentation]; + if (!jsonResult) jsonResult = @"{}"; return jsonResult; @@ -463,13 +459,12 @@ static NSString *siteFavicon = nil; - (NSString *) userDefaults { - SOGoUserDefaults *userDefaults; + SOGoUserDefaults *ud; NSString *jsonResult; - userDefaults = (SOGoUserDefaults *)[[context activeUser] userDefaults]; - if (userDefaults) - jsonResult = [userDefaults jsonRepresentation]; - else + ud = [[context activeUser] userDefaults]; + jsonResult = [[ud source] jsonRepresentation]; + if (!jsonResult) jsonResult = @"{}"; return jsonResult; diff --git a/UI/Common/UIxUserRightsEditor.m b/UI/Common/UIxUserRightsEditor.m index 2ce4d42d5..f937260c4 100644 --- a/UI/Common/UIxUserRightsEditor.m +++ b/UI/Common/UIxUserRightsEditor.m @@ -24,28 +24,19 @@ #import #import #import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import #import -#import #import "UIxUserRightsEditor.h" -static BOOL sendACLAdvisories = NO; - @implementation UIxUserRightsEditor -+ (void) initialize -{ - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - sendACLAdvisories = [ud boolForKey: @"SOGoACLsSendEMailNotifications"]; -} - - (id) init { if ((self = [super init])) @@ -93,7 +84,7 @@ static BOOL sendACLAdvisories = NO; - (BOOL) _initRights { BOOL response; - NSString *newUID; + NSString *newUID, *domain; SOGoUserManager *um; SOGoObject *clientObject; SOGoGroup *group; @@ -112,7 +103,8 @@ static BOOL sendACLAdvisories = NO; { if (![newUID hasPrefix: @"@"]) { - group = [SOGoGroup groupWithIdentifier: newUID]; + domain = [[context activeUser] domain]; + group = [SOGoGroup groupWithIdentifier: newUID inDomain: domain]; if (group) newUID = [NSString stringWithFormat: @"@%@", newUID]; } @@ -147,12 +139,12 @@ static BOOL sendACLAdvisories = NO; - (void) sendACLAdvisoryTemplateForObject: (id) theObject { NSString *language, *pageName; - SOGoUser *user; + SOGoUserDefaults *ud; SOGoACLAdvisory *page; WOApplication *app; - user = [SOGoUser userWithLogin: uid roles: nil]; - language = [user language]; + ud = [[SOGoUser userWithLogin: uid roles: nil] userDefaults]; + language = [ud language]; pageName = [NSString stringWithFormat: @"SOGoACL%@ModificationAdvisory", language]; @@ -166,6 +158,7 @@ static BOOL sendACLAdvisories = NO; - (id ) saveUserRightsAction { id response; + SOGoDomainDefaults *dd; if (![self _initRights]) response = [NSException exceptionWithHTTPStatus: 403 @@ -179,11 +172,10 @@ static BOOL sendACLAdvisories = NO; [self updateRights]; [[self clientObject] setRoles: userRights forUser: uid]; - if (![o isEqualToArray: userRights] && sendACLAdvisories) - { - [self sendACLAdvisoryTemplateForObject: [self clientObject]]; - } - + dd = [[context activeUser] domainDefaults]; + if (![o isEqualToArray: userRights] && [dd aclSendEMailNotifications]) + [self sendACLAdvisoryTemplateForObject: [self clientObject]]; + response = [self jsCloseWithRefreshMethod: nil]; } diff --git a/UI/Common/WODirectAction+SOGo.m b/UI/Common/WODirectAction+SOGo.m index ee6338da1..68564c152 100644 --- a/UI/Common/WODirectAction+SOGo.m +++ b/UI/Common/WODirectAction+SOGo.m @@ -28,6 +28,7 @@ #import #import #import +#import #import "WODirectAction+SOGo.h" @@ -88,12 +89,14 @@ NSArray *paths; NSBundle *bundle; NSDictionary *strings; + SOGoUserDefaults *ud; bundle = [NSBundle bundleForClass: [self class]]; if (!bundle) bundle = [NSBundle mainBundle]; - userLanguage = [[context activeUser] language]; + ud = [[context activeUser] userDefaults]; + userLanguage = [ud language]; paths = [bundle pathsForResourcesOfType: @"strings" inDirectory: [NSString stringWithFormat: @"%@.lproj", userLanguage] diff --git a/UI/Contacts/UIxContactFoldersView.h b/UI/Contacts/UIxContactFoldersView.h index bbe531c6c..945300d7b 100644 --- a/UI/Contacts/UIxContactFoldersView.h +++ b/UI/Contacts/UIxContactFoldersView.h @@ -28,7 +28,7 @@ @interface UIxContactFoldersView : UIxComponent { - NSUserDefaults *ud; + SOGoUserSettings *us; NSString *selectorComponentClass; NSMutableDictionary *moduleSettings; id currentFolder; diff --git a/UI/Contacts/UIxContactFoldersView.m b/UI/Contacts/UIxContactFoldersView.m index 98c3fcee6..ebcb4044e 100644 --- a/UI/Contacts/UIxContactFoldersView.m +++ b/UI/Contacts/UIxContactFoldersView.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -38,16 +37,17 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "UIxContactFoldersView.h" @@ -64,11 +64,11 @@ module = [clientObject nameInContainer]; - ud = [activeUser userSettings]; - moduleSettings = [ud objectForKey: module]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: module]; if (!moduleSettings) moduleSettings = [NSMutableDictionary dictionary]; - [ud setObject: moduleSettings forKey: module]; + [us setObject: moduleSettings forKey: module]; } - (id ) mailerContactsAction @@ -139,18 +139,14 @@ - (NSArray *) _responseForResults: (NSArray *) results { NSEnumerator *contacts; - NSString *email, *infoKey, *info; + NSString *email, *info; NSDictionary *contact; NSMutableArray *formattedContacts; NSMutableDictionary *formattedContact; - NSUserDefaults *sud; formattedContacts = [NSMutableArray arrayWithCapacity: [results count]]; - if ([results count] > 0) { - sud = [NSUserDefaults standardUserDefaults]; - infoKey = [[sud stringForKey: @"SOGoLDAPContactInfoAttribute"] lowercaseString]; contacts = [results objectEnumerator]; contact = [contacts nextObject]; while (contact) @@ -165,13 +161,10 @@ forKey: @"name"]; [formattedContact setObject: email forKey: @"email"]; - if ([infoKey length] > 0) - { - info = [contact objectForKey: infoKey]; - if (info != nil) - [formattedContact setObject: info - forKey: @"contactInfo"]; - } + info = [contact objectForKey: @"c_info"]; + if (info != nil) + [formattedContact setObject: info + forKey: @"contactInfo"]; [formattedContacts addObject: formattedContact]; } contact = [contacts nextObject]; @@ -276,7 +269,7 @@ { NSDictionary *data; NSArray *contacts; - NSString *searchText; + NSString *searchText, *domain; id result; SOGoUserManager *um; @@ -284,11 +277,14 @@ if ([searchText length] > 0) { um = [SOGoUserManager sharedUserManager]; + domain = [[context activeUser] domain]; contacts - = [self _responseForResults: [um fetchContactsMatching: searchText]]; - data = [NSDictionary dictionaryWithObjectsAndKeys: searchText, @"searchText", - contacts, @"contacts", - nil]; + = [self _responseForResults: [um fetchContactsMatching: searchText + inDomain: domain]]; + data = [NSDictionary dictionaryWithObjectsAndKeys: + searchText, @"searchText", + contacts, @"contacts", + nil]; result = [self responseWithStatus: 200]; [(WOResponse*)result appendContentString: [data jsonRepresentation]]; } @@ -367,18 +363,15 @@ - (void) checkDefaultModulePreference { - NSUserDefaults *clientUD; - NSString *pref; + SOGoUserDefaults *ud; if (![self isPopup]) { - clientUD = [[context activeUser] userDefaults]; - pref = [clientUD stringForKey: @"SOGoUIxDefaultModule"]; - - if (pref && [pref isEqualToString: @"Last"]) + ud = [[context activeUser] userDefaults]; + if ([ud rememberLastModule]) { - [clientUD setObject: @"Contacts" forKey: @"SOGoUIxLastModule"]; - [clientUD synchronize]; + [ud setLoginModule: @"Contacts"]; + [ud synchronize]; } } } @@ -392,7 +385,6 @@ { SOGoContactFolders *folderContainer; - [self checkDefaultModulePreference]; folderContainer = [self clientObject]; return [folderContainer subFolders]; @@ -436,9 +428,16 @@ else return [self responseWithStatus: 400]; - [ud synchronize]; + [us synchronize]; return [self responseWithStatus: 204]; } +- (id) defaultAction +{ + [self checkDefaultModulePreference]; + + return [super defaultAction]; +} + @end diff --git a/UI/MailPartViewers/UIxMailPartICalViewer.m b/UI/MailPartViewers/UIxMailPartICalViewer.m index d38da1518..af17f0f5a 100644 --- a/UI/MailPartViewers/UIxMailPartICalViewer.m +++ b/UI/MailPartViewers/UIxMailPartICalViewer.m @@ -37,14 +37,15 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "UIxMailPartICalViewer.h" @@ -167,11 +168,11 @@ - (NSCalendarDate *) startCalendarDate { NSCalendarDate *date; - NSTimeZone *timeZone; + SOGoUserDefaults *ud; date = [[self inEvent] startDate]; - timeZone = [[context activeUser] timeZone]; - [date setTimeZone: timeZone]; + ud = [[context activeUser] userDefaults]; + [date setTimeZone: [ud timeZone]]; return date; } @@ -189,11 +190,11 @@ - (NSCalendarDate *) endCalendarDate { NSCalendarDate *date; - NSTimeZone *timeZone; + SOGoUserDefaults *ud; date = [[self inEvent] endDate]; - timeZone = [[context activeUser] timeZone]; - [date setTimeZone: timeZone]; + ud = [[context activeUser] userDefaults]; + [date setTimeZone: [ud timeZone]]; return date; } diff --git a/UI/MailerUI/UIxMailAccountActions.m b/UI/MailerUI/UIxMailAccountActions.m index 6bb1ad1d6..954ee4a23 100644 --- a/UI/MailerUI/UIxMailAccountActions.m +++ b/UI/MailerUI/UIxMailAccountActions.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -34,13 +33,15 @@ #import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "../Common/WODirectAction+SOGo.h" @@ -189,13 +190,12 @@ SOGoMailFolder *inbox; NGImap4Client *client; NSString *inboxName; - NSUserDefaults *ud; + SOGoDomainDefaults *dd; id infos; - float quota; - ud = [NSUserDefaults standardUserDefaults]; - quota = [ud floatForKey: @"SOGoSoftQuotaRatio"]; + dd = [[context activeUser] domainDefaults]; + quota = [dd softQuotaRatio]; inbox = [co inboxFolderInContext: context]; inboxName = [NSString stringWithFormat: @"/%@", [inbox relativeImap4Name]]; client = [[inbox imap4Connection] client]; @@ -232,6 +232,7 @@ { SOGoDraftsFolder *drafts; SOGoDraftObject *newDraftMessage; + SOGoUserDefaults *ud; NSString *urlBase, *url, *value, *signature; NSArray *mailTo; NSMutableDictionary *headers; @@ -261,7 +262,8 @@ if (save) [newDraftMessage setHeaders: headers]; - signature = [[context activeUser] signature]; + ud = [[context activeUser] userDefaults]; + signature = [ud mailSignature]; if ([signature length]) { [newDraftMessage diff --git a/UI/MailerUI/UIxMailEditor.m b/UI/MailerUI/UIxMailEditor.m index 1b55cc3de..cdd3555d6 100644 --- a/UI/MailerUI/UIxMailEditor.m +++ b/UI/MailerUI/UIxMailEditor.m @@ -23,7 +23,6 @@ #import #import #import -#import #import #import @@ -78,30 +77,15 @@ @implementation UIxMailEditor -static BOOL showInternetMarker = NO; -static NSDictionary *internetMailHeaders = nil; static NSArray *infoKeys = nil; + (void) initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - infoKeys = [[NSArray alloc] initWithObjects: - @"subject", @"to", @"cc", @"bcc", - @"from", @"replyTo", @"inReplyTo", - @"priority", nil]; - - /* Internet mail settings */ - - showInternetMarker = [ud boolForKey:@"SOGoShowInternetMarker"]; - if (!showInternetMarker) - NSLog(@"Note: visual Internet marker on mail editor disabled " - @"(SOGoShowInternetMarker)"); - - internetMailHeaders = - [[ud dictionaryForKey:@"SOGoInternetMailHeaders"] copy]; - NSLog (@"Note: specified %d headers for mails send via the Internet.", - [internetMailHeaders count]); + if (!infoKeys) + infoKeys = [[NSArray alloc] initWithObjects: + @"subject", @"to", @"cc", @"bcc", + @"from", @"replyTo", @"inReplyTo", + @"priority", nil]; } - (id) init diff --git a/UI/MailerUI/UIxMailFolderActions.m b/UI/MailerUI/UIxMailFolderActions.m index ae3b71e83..34ded3258 100644 --- a/UI/MailerUI/UIxMailFolderActions.m +++ b/UI/MailerUI/UIxMailFolderActions.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import @@ -319,21 +318,21 @@ { SOGoMailFolder *co; WOResponse *response; - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *mailSettings; co = [self clientObject]; if ([NSStringFromClass ([co class]) isEqualToString: @"SOGoMailFolder"]) { - ud = [[context activeUser] userSettings]; - mailSettings = [ud objectForKey: @"Mail"]; + us = [[context activeUser] userSettings]; + mailSettings = [us objectForKey: @"Mail"]; if (!mailSettings) mailSettings = [NSMutableDictionary dictionary]; - [ud setObject: mailSettings forKey: @"Mail"]; + [us setObject: mailSettings forKey: @"Mail"]; [mailSettings setObject: [co traversalFromMailAccount] forKey: [NSString stringWithFormat: @"%@Folder", purpose]]; - [ud synchronize]; + [us synchronize]; response = [self responseWith204]; } else diff --git a/UI/MailerUI/UIxMailListView.h b/UI/MailerUI/UIxMailListView.h index f046a4918..4c404531e 100644 --- a/UI/MailerUI/UIxMailListView.h +++ b/UI/MailerUI/UIxMailListView.h @@ -32,7 +32,7 @@ { NSArray *sortedUIDs; /* we always need to retrieve all anyway! */ NSArray *messages; - NSMutableArray *userDefinedOrder; + NSArray *columnsOrder; unsigned firstMessageNumber; id message; EOQualifier *qualifier; diff --git a/UI/MailerUI/UIxMailListView.m b/UI/MailerUI/UIxMailListView.m index 92b91d0e4..5358165c1 100644 --- a/UI/MailerUI/UIxMailListView.m +++ b/UI/MailerUI/UIxMailListView.m @@ -32,7 +32,6 @@ #import #import #import -#import #import #import @@ -45,44 +44,22 @@ #import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "UIxMailListView.h" -static NSArray *defaultColumnOrder = nil; -static NSArray *udColumnOrder = nil; - #define messagesPerPage 50 @implementation UIxMailListView -+ (void) initialize -{ - if (!defaultColumnOrder) - { - defaultColumnOrder = [NSArray arrayWithObjects: @"Flagged", - @"Attachment", @"Subject", @"From", - @"Unread", @"Date", @"Priority", @"Size", - nil]; - [defaultColumnOrder retain]; - } - - if (!udColumnOrder) - { - udColumnOrder = [[NSUserDefaults standardUserDefaults] - arrayForKey: @"SOGoMailListViewColumnsOrder"]; - [udColumnOrder retain]; - } -} - - (id) init { SOGoUser *user; @@ -92,8 +69,8 @@ static NSArray *udColumnOrder = nil; qualifier = nil; user = [context activeUser]; ASSIGN (dateFormatter, [user dateFormatterInContext: context]); - ASSIGN (userTimeZone, [user timeZone]); - userDefinedOrder = nil; + ASSIGN (userTimeZone, [[user userDefaults] timeZone]); + columnsOrder = nil; folderType = 0; currentColumn = nil; } @@ -110,7 +87,7 @@ static NSArray *udColumnOrder = nil; [dateFormatter release]; [userTimeZone release]; [currentColumn release]; - [userDefinedOrder release]; + [columnsOrder release]; [super dealloc]; } @@ -504,21 +481,6 @@ static NSArray *udColumnOrder = nil; return 1; } -- (void) checkDefaultModulePreference -{ - NSUserDefaults *ud; - NSString *pref; - - ud = [[context activeUser] userDefaults]; - pref = [ud stringForKey: @"SOGoUIxDefaultModule"]; - - if (pref && [pref isEqualToString: @"Last"]) - { - [ud setObject: @"Mail" forKey: @"SOGoUIxLastModule"]; - [ud synchronize]; - } -} - - (NSArray *) messages { NSMutableArray *unsortedMsgs; @@ -529,8 +491,6 @@ static NSArray *udColumnOrder = nil; unsigned len, i, count; NSRange r; - [self checkDefaultModulePreference]; - if (!messages) { r = [self fetchBlock]; @@ -836,51 +796,53 @@ static NSArray *udColumnOrder = nil; - (NSArray *) columnsDisplayOrder { - NSMutableArray *testColumns; - NSArray *defaultsOrder; - NSUserDefaults *ud; + NSMutableArray *finalOrder, *invalid; + NSArray *available; + NSDictionary *metaData; + SOGoUserDefaults *ud; unsigned int i; - if (!userDefinedOrder) + if (!columnsOrder) { - ud = [[context activeUser] userSettings]; - defaultsOrder = [ud arrayForKey: @"SOGoMailListViewColumnsOrder"]; - if (![defaultsOrder count]) - { - defaultsOrder = udColumnOrder; - if (![defaultsOrder count]) - defaultsOrder = defaultColumnOrder; - } - userDefinedOrder = [defaultsOrder mutableCopy]; + ud = [[context activeUser] userDefaults]; + columnsOrder = [ud mailListViewColumnsOrder]; - testColumns = [userDefinedOrder mutableCopy]; - [testColumns removeObjectsInArray: defaultColumnOrder]; - if ([testColumns count] > 0) + metaData = [self columnsMetaData]; + + invalid = [columnsOrder mutableCopy]; + [invalid autorelease]; + available = [metaData allKeys]; + [invalid removeObjectsInArray: available]; + if ([invalid count] > 0) { - [self errorWithFormat: @"one or more column names specified in" + [self errorWithFormat: @"those column names specified in" @" SOGoMailListViewColumnsOrder are invalid: '%@'", - [testColumns componentsJoinedByString: @"', '"]]; + [invalid componentsJoinedByString: @"', '"]]; [self errorWithFormat: @" falling back on hardcoded column order"]; - userDefinedOrder = [defaultColumnOrder mutableCopy]; + columnsOrder = available; } - [testColumns release]; + finalOrder = [columnsOrder mutableCopy]; + [finalOrder autorelease]; if ([self showToAddress]) { - i = [userDefinedOrder indexOfObject: @"From"]; + i = [finalOrder indexOfObject: @"From"]; if (i != NSNotFound) - [userDefinedOrder replaceObjectAtIndex: i withObject: @"To"]; + [finalOrder replaceObjectAtIndex: i withObject: @"To"]; } else { - i = [userDefinedOrder indexOfObject: @"To"]; + i = [finalOrder indexOfObject: @"To"]; if (i != NSNotFound) - [userDefinedOrder replaceObjectAtIndex: i withObject: @"From"]; + [finalOrder replaceObjectAtIndex: i withObject: @"From"]; } + + columnsOrder = [[self columnsMetaData] objectsForKeys: finalOrder + notFoundMarker: @""]; + [columnsOrder retain]; } - return [[self columnsMetaData] objectsForKeys: userDefinedOrder - notFoundMarker: @""]; + return columnsOrder; } - (NSString *) columnsDisplayCount diff --git a/UI/MailerUI/UIxMailMainFrame.h b/UI/MailerUI/UIxMailMainFrame.h index 1b20fa470..450c8d458 100644 --- a/UI/MailerUI/UIxMailMainFrame.h +++ b/UI/MailerUI/UIxMailMainFrame.h @@ -27,7 +27,7 @@ @interface UIxMailMainFrame : UIxComponent { - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *moduleSettings; } diff --git a/UI/MailerUI/UIxMailMainFrame.m b/UI/MailerUI/UIxMailMainFrame.m index 4f8064cb1..1d2254178 100644 --- a/UI/MailerUI/UIxMailMainFrame.m +++ b/UI/MailerUI/UIxMailMainFrame.m @@ -22,7 +22,6 @@ #import #import -#import #import #import @@ -39,15 +38,16 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import #import "UIxMailMainFrame.h" @@ -60,7 +60,6 @@ @end - @implementation UIxMailMainFrame - (void) _setupContext @@ -75,12 +74,12 @@ module = [clientObject nameInContainer]; - ud = [activeUser userSettings]; - moduleSettings = [ud objectForKey: module]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: module]; if (!moduleSettings) { moduleSettings = [NSMutableDictionary dictionary]; - [ud setObject: moduleSettings forKey: module]; + [us setObject: moduleSettings forKey: module]; } } @@ -113,18 +112,11 @@ - (NSString *) defaultColumnsOrder { - NSArray *defaultColumnsOrder; - NSUserDefaults *sud; - - sud = [NSUserDefaults standardUserDefaults]; - defaultColumnsOrder = [NSArray arrayWithArray: [sud arrayForKey: @"SOGoMailListViewColumnsOrder"]]; - if ( [defaultColumnsOrder count] == 0 ) - { - defaultColumnsOrder = [NSArray arrayWithObjects: @"Flagged", @"Attachment", @"Subject", - @"From", @"Unread", @"Date", @"Priority", nil]; - } - - return [defaultColumnsOrder jsonRepresentation]; + SOGoDomainDefaults *dd; + + dd = [[context activeUser] domainDefaults]; + + return [[dd mailListViewColumnsOrder] jsonRepresentation]; } - (NSString *) pageFormURL @@ -372,7 +364,7 @@ else return [self responseWithStatus: 400]; - [ud synchronize]; + [us synchronize]; return [self responseWithStatus: 204]; } @@ -389,9 +381,23 @@ [moduleSettings setObject: expandedFolders forKey: @"ExpandedFolders"]; - [ud synchronize]; + [us synchronize]; return [self responseWithStatus: 204]; } +- (id) defaultAction +{ + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + if ([ud rememberLastModule]) + { + [ud setLoginModule: @"Mail"]; + [ud synchronize]; + } + + return [super defaultAction]; +} + @end /* UIxMailMainFrame */ diff --git a/UI/MailerUI/UIxMailUserRightsEditor.m b/UI/MailerUI/UIxMailUserRightsEditor.m index 135462908..bdd7b55e7 100644 --- a/UI/MailerUI/UIxMailUserRightsEditor.m +++ b/UI/MailerUI/UIxMailUserRightsEditor.m @@ -23,8 +23,9 @@ #import #import #import -#import -#import +#import +#import +#import #import "UIxMailUserRightsEditor.h" @@ -32,11 +33,11 @@ - (BOOL) conformsToRFC4314 { - SOGoMailFolder *co; + SOGoMailAccount *mailAccount; - co = [self clientObject]; + mailAccount = [[self clientObject] mailAccountFolder]; - return ([[co class] imapAclStyle] == rfc4314); + return ([mailAccount imapAclStyle] == rfc4314); } - (void) setUserCanReadMails: (BOOL) userCanReadMails diff --git a/UI/MailerUI/UIxMailView.m b/UI/MailerUI/UIxMailView.m index a0ab3f58d..604408348 100644 --- a/UI/MailerUI/UIxMailView.m +++ b/UI/MailerUI/UIxMailView.m @@ -20,7 +20,6 @@ */ #import -#import #import #import #import @@ -51,18 +50,11 @@ static NSString *mailETag = nil; + (void) initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - - if ([ud boolForKey:@"SOGoDontUseETagsForMailViewer"]) - NSLog(@"Note: usage of constant etag for mailer viewer is disabled."); - else - { - mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"", - UIX_MAILER_MAJOR_VERSION, - UIX_MAILER_MINOR_VERSION, - UIX_MAILER_SUBMINOR_VERSION]; - NSLog(@"Note: using constant etag for mail viewer: '%@'", mailETag); - } + mailETag = [[NSString alloc] initWithFormat:@"\"imap4url_%d_%d_%03d\"", + UIX_MAILER_MAJOR_VERSION, + UIX_MAILER_MINOR_VERSION, + UIX_MAILER_SUBMINOR_VERSION]; + NSLog(@"Note: using constant etag for mail viewer: '%@'", mailETag); } /* accessors */ @@ -146,33 +138,30 @@ static NSString *mailETag = nil; NSString *s; /* check etag to see whether we really must rerender */ - if (mailETag) + /* + Note: There is one thing which *can* change for an existing message, + those are the IMAP4 flags (and annotations, which we do not use). + Since we don't render the flags, it should be OK, if this changes + we must embed the flagging into the etag. + */ + s = [[context request] headerForKey: @"if-none-match"]; + if (s) { - /* - Note: There is one thing which *can* change for an existing message, - those are the IMAP4 flags (and annotations, which we do not use). - Since we don't render the flags, it should be OK, if this changes - we must embed the flagging into the etag. - */ - s = [[context request] headerForKey: @"if-none-match"]; - if (s) - { - if ([s rangeOfString:mailETag].length > 0) /* not perfectly correct */ - { - /* client already has the proper entity */ - // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag]; - - if (![[self clientObject] doesMailExist]) { - return [NSException exceptionWithHTTPStatus:404 /* Not Found */ - reason:@"message got deleted"]; - } + if ([s rangeOfString:mailETag].length > 0) /* not perfectly correct */ + { + /* client already has the proper entity */ + // [self logWithFormat:@"MATCH: %@ (tag %@)", s, mailETag]; + + if (![[self clientObject] doesMailExist]) { + return [NSException exceptionWithHTTPStatus:404 /* Not Found */ + reason:@"message got deleted"]; + } + + response = [context response]; + [response setStatus: 304 /* Not Modified */]; - response = [context response]; - [response setStatus: 304 /* Not Modified */]; - - return response; - } - } + return response; + } } if (![self message]) // TODO: redirect to proper error @@ -211,8 +200,7 @@ static NSString *mailETag = nil; request = [_ctx request]; - if (mailETag != nil) - [[_ctx response] setHeader:mailETag forKey:@"etag"]; + [[_ctx response] setHeader:mailETag forKey:@"etag"]; mctx = [[UIxMailRenderingContext alloc] initWithViewer: self context: _ctx]; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index 4a6acff79..fc7584f06 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -20,7 +20,6 @@ */ #import -#import #import #import @@ -33,13 +32,13 @@ #import #import -#import -#import +#import +#import +#import +#import #import "SOGoRootPage.h" -static NSArray *supportedLanguages = nil; - @interface SOGoRootPage (crashAdditions) - (void) segfault; @@ -48,12 +47,6 @@ static NSArray *supportedLanguages = nil; @implementation SOGoRootPage -+ (void) initialize -{ - if (!supportedLanguages) - supportedLanguages = [NSArray arrayWithObjects: @"Czech", @"Welsh", @"English", @"Spanish", @"French", @"German", @"Italian", @"Hungarian", @"Dutch", @"BrazilianPortuguese", @"Russian", @"Swedish", nil]; -} - /* accessors */ - (NSString *) connectURL @@ -68,9 +61,10 @@ static NSArray *supportedLanguages = nil; WORequest *request; WOCookie *authCookie; SOGoWebAuthenticator *auth; - SOGoUser *user; + SOGoUserDefaults *ud; NSString *cookieValue, *cookieString; NSString *userName, *password, *language; + NSArray *supportedLanguages; auth = [[WOApplication application] authenticatorInContext: context]; @@ -93,12 +87,14 @@ static NSArray *supportedLanguages = nil; [authCookie setIsSecure: YES]; */ [response addCookie: authCookie]; + supportedLanguages = [[SOGoSystemDefaults sharedSystemDefaults] + supportedLanguages]; if (language && [supportedLanguages containsObject: language]) { - user = [SOGoUser userWithLogin: userName roles: nil]; - [[user userDefaults] setObject: language forKey: @"Language"]; - [[user userDefaults] synchronize]; - [user invalidateLanguage]; + ud = [[SOGoUser userWithLogin: userName roles: nil] + userDefaults]; + [ud setLanguage: language]; + [ud synchronize]; } } else @@ -160,11 +156,7 @@ static NSArray *supportedLanguages = nil; - (NSString *) loginSuffix { - NSUserDefaults *ud; - - ud = [NSUserDefaults standardUserDefaults]; - - return [ud stringForKey: @"SOGoLoginSuffix"]; + return [[SOGoSystemDefaults sharedSystemDefaults] loginSuffix]; } - (BOOL) hasLoginSuffix @@ -184,13 +176,13 @@ static NSArray *supportedLanguages = nil; - (NSArray *) languages { - return supportedLanguages; + return [[SOGoSystemDefaults sharedSystemDefaults] supportedLanguages]; } -- (NSString *) language -{ - return [SOGoUser language]; -} +// - (NSString *) language +// { +// return [SOGoUser language]; +// } - (NSString *) languageText { @@ -213,5 +205,4 @@ static NSArray *supportedLanguages = nil; return aString; } - @end /* SOGoRootPage */ diff --git a/UI/MainUI/SOGoUserHomePage.m b/UI/MainUI/SOGoUserHomePage.m index ce8943799..28ca8767e 100644 --- a/UI/MainUI/SOGoUserHomePage.m +++ b/UI/MainUI/SOGoUserHomePage.m @@ -26,7 +26,6 @@ #import #import #import -#import #import #import #import @@ -36,74 +35,43 @@ #import #import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import #import #define intervalSeconds 900 /* 15 minutes */ -static NSString *defaultModule = nil; -static NSString *LDAPContactInfoAttribute = nil; - @interface SOGoUserHomePage : UIxComponent @end @implementation SOGoUserHomePage -+ (void) initialize -{ - NSUserDefaults *ud; - - if (!defaultModule) - { - ud = [NSUserDefaults standardUserDefaults]; - - defaultModule = [ud stringForKey: @"SOGoUIxDefaultModule"]; - if (defaultModule) - { - if (!([defaultModule isEqualToString: @"Calendar"] - || [defaultModule isEqualToString: @"Contacts"] - || [defaultModule isEqualToString: @"Mail"])) - { - [self logWithFormat: @"default module '%@' not accepted (must be" - @"'Calendar', 'Contacts' or 'Mail')", defaultModule]; - defaultModule = @"Calendar"; - } - } - else - defaultModule = @"Calendar"; - [self logWithFormat: @"default module set to '%@'", defaultModule]; - [defaultModule retain]; - - LDAPContactInfoAttribute = [ud stringForKey: @"SOGoLDAPContactInfoAttribute"]; - [LDAPContactInfoAttribute retain]; - } -} - - (id ) defaultAction { SOGoUserFolder *co; - NSUserDefaults *ud; - NSString *userDefinedModule; + NSString *loginModule; + SOGoUserDefaults *ud; NSURL *moduleURL; ud = [[context activeUser] userDefaults]; - userDefinedModule = [ud stringForKey: @"SOGoUIxDefaultModule"]; - if (userDefinedModule) + loginModule = [ud loginModule]; + if (!([loginModule isEqualToString: @"Calendar"] + || [loginModule isEqualToString: @"Contacts"] + || [loginModule isEqualToString: @"Mail"])) { - if ([userDefinedModule isEqualToString: @"Last"]) - userDefinedModule = [ud stringForKey: @"SOGoUIxLastModule"]; + [self errorWithFormat: @"login module '%@' not accepted (must be" + @"'Calendar', 'Contacts' or 'Mail')", loginModule]; + loginModule = @"Calendar"; } - if (!userDefinedModule) - userDefinedModule = defaultModule; co = [self clientObject]; - moduleURL = [NSURL URLWithString: userDefinedModule + moduleURL = [NSURL URLWithString: loginModule relativeToURL: [co soURL]]; return [self redirectToLocation: [moduleURL absoluteString]]; @@ -219,7 +187,7 @@ static NSString *LDAPContactInfoAttribute = nil; co = [self clientObject]; user = [context activeUser]; - uTZ = [user timeZone]; + uTZ = [[user userDefaults] timeZone]; queryDay = [self queryParameterForKey: @"sday"]; if ([queryDay length]) @@ -338,13 +306,8 @@ static NSString *LDAPContactInfoAttribute = nil; // We do NOT return the current authenticated user. if (![uid isEqualToString: login]) { - if ([LDAPContactInfoAttribute length]) - { - contactInfo = [contact objectForKey: [LDAPContactInfoAttribute lowercaseString]]; - if (!contactInfo) - contactInfo = @""; - } - else + contactInfo = [contact objectForKey: @"c_info"]; + if (!contactInfo) contactInfo = @""; [responseString appendFormat: @"%@:%@:%@:%@\n", uid, [contact objectForKey: @"cn"], @@ -359,7 +322,7 @@ static NSString *LDAPContactInfoAttribute = nil; - (id ) usersSearchAction { - NSString *contact; + NSString *contact, *domain; id result; SOGoUserManager *um; @@ -367,6 +330,7 @@ static NSString *LDAPContactInfoAttribute = nil; contact = [self queryParameterForKey: @"search"]; if ([contact length]) { + domain = [[context activeUser] domain]; result = [self _usersResponseForResults: [um fetchUsersMatching: contact]]; } diff --git a/UI/PreferencesUI/UIxJSONPreferences.m b/UI/PreferencesUI/UIxJSONPreferences.m index 1deb0ab0c..11bd05b36 100644 --- a/UI/PreferencesUI/UIxJSONPreferences.m +++ b/UI/PreferencesUI/UIxJSONPreferences.m @@ -20,47 +20,48 @@ * Boston, MA 02111-1307, USA. */ -#import - #import #import #import -#import -#import +#import +#import +#import +#import +#import #import "UIxJSONPreferences.h" @implementation UIxJSONPreferences -- (WOResponse *) _makeResponse: (NSUserDefaults *) defaults +- (WOResponse *) _makeResponse: (SOGoUserProfile *) profile { WOResponse *response; response = [context response]; [response setHeader: @"text/plain; charset=utf-8" forKey: @"content-type"]; - [response appendContentString: [defaults jsonRepresentation]]; + [response appendContentString: [profile jsonRepresentation]]; return response; } - (WOResponse *) jsonDefaultsAction { - NSUserDefaults *defaults; + SOGoUserDefaults *defaults; defaults = [[context activeUser] userDefaults]; - return [self _makeResponse: defaults]; + return [self _makeResponse: [defaults source]]; } - (WOResponse *) jsonSettingsAction { - NSUserDefaults *settings; + SOGoUserSettings *settings; settings = [[context activeUser] userSettings]; - return [self _makeResponse: settings]; + return [self _makeResponse: [settings source]]; } @end diff --git a/UI/PreferencesUI/UIxPreferences.h b/UI/PreferencesUI/UIxPreferences.h index 20190bf54..3e3100521 100644 --- a/UI/PreferencesUI/UIxPreferences.h +++ b/UI/PreferencesUI/UIxPreferences.h @@ -26,7 +26,7 @@ #import @class NSString; -@class NSUserDefaults; +@class SOGoUserDefaults; @class SOGoUser; @@ -35,9 +35,8 @@ id item; SOGoUser *user; NSDictionary *locale; - NSUserDefaults *userDefaults; + SOGoUserDefaults *userDefaults; NSCalendarDate *today; - NSMutableArray *hours; NSArray *daysOfWeek, *daysBetweenResponsesList; NSMutableDictionary *vacationOptions, *forwardOptions; BOOL hasChanged, composeMessageTypeHasChanged; diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index f26986909..f3049b56f 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -23,7 +23,7 @@ #import #import #import -#import +#import /* for locale strings */ #import #import @@ -32,12 +32,15 @@ #import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "../../Main/SOGo.h" #import "UIxPreferences.h" @@ -50,75 +53,48 @@ workweek = from -> to identities */ -static BOOL defaultsRead = NO; -static BOOL shouldDisplayPasswordChange = NO; -static BOOL shouldDisplayAdditionalPreferences = NO; -static BOOL defaultShowSubscribedFoldersOnly = NO; -static BOOL vacationEnabled = NO; -static BOOL forwardEnabled = NO; - @implementation UIxPreferences -+ (void) initialize -{ - NSUserDefaults *ud; - - if (!defaultsRead) - { - ud = [NSUserDefaults standardUserDefaults]; - shouldDisplayPasswordChange - = [ud boolForKey: @"SOGoUIxUserCanChangePassword"]; - shouldDisplayAdditionalPreferences - = [ud boolForKey: @"SOGoUIxAdditionalPreferences"]; - defaultShowSubscribedFoldersOnly - = [ud boolForKey: @"SOGoMailShowSubscribedFoldersOnly"]; - vacationEnabled - = [ud boolForKey: @"SOGoVacationEnabled"]; - forwardEnabled - = [ud boolForKey: @"SOGoForwardEnabled"]; - defaultsRead = YES; - } -} - - (id) init { //NSDictionary *locale; + SOGoDomainDefaults *dd; NSString *language; if ((self = [super init])) { - language = [[context activeUser] language]; - item = nil; - hours = nil; ASSIGN (user, [context activeUser]); ASSIGN (userDefaults, [user userDefaults]); ASSIGN (today, [NSCalendarDate date]); //locale = [context valueForKey: @"locale"]; - ASSIGN (locale, [[WOApplication application] localeForLanguageNamed: language]); - ASSIGN (daysOfWeek, - [locale objectForKey: NSWeekDayNameArray]); + language = [userDefaults language]; + + ASSIGN (locale, + [[WOApplication application] localeForLanguageNamed: language]); + ASSIGN (daysOfWeek, [locale objectForKey: NSWeekDayNameArray]); hasChanged = NO; composeMessageTypeHasChanged = NO; - if (vacationEnabled) + dd = [user domainDefaults]; + if ([dd vacationEnabled]) { - vacationOptions = [userDefaults objectForKey: @"Vacation"]; + vacationOptions = [userDefaults vacationOptions]; if (!vacationOptions) { vacationOptions = [NSMutableDictionary dictionary]; - [userDefaults setObject: vacationOptions forKey: @"Vacation"]; + [userDefaults setVacationOptions: vacationOptions]; } [vacationOptions retain]; } - if (forwardEnabled) + if ([dd forwardEnabled]) { - forwardOptions = [userDefaults objectForKey: @"Forward"]; + forwardOptions = [userDefaults forwardOptions]; if (!forwardOptions) { forwardOptions = [NSMutableDictionary dictionary]; - [userDefaults setObject: forwardOptions forKey: @"Forward"]; + [userDefaults setForwardOptions: forwardOptions]; } [forwardOptions retain]; } @@ -135,7 +111,6 @@ static BOOL forwardEnabled = NO; [userDefaults release]; [vacationOptions release]; [forwardOptions release]; - [hours release]; [daysOfWeek release]; [locale release]; [super dealloc]; @@ -169,12 +144,12 @@ static BOOL forwardEnabled = NO; - (NSString *) userTimeZone { - return [[user timeZone] timeZoneName]; + return [userDefaults timeZoneName]; } - (void) setUserTimeZone: (NSString *) newUserTimeZone { - [userDefaults setObject: newUserTimeZone forKey: @"TimeZone"]; + [userDefaults setTimeZoneName: newUserTimeZone]; } - (NSArray *) shortDateFormatsList @@ -225,22 +200,12 @@ static BOOL forwardEnabled = NO; - (NSString *) userShortDateFormat { - NSString *shortDateFormat; - - shortDateFormat = [userDefaults objectForKey: @"ShortDateFormat"]; - - if (!shortDateFormat) - shortDateFormat = @"default"; - - return shortDateFormat; + return [userDefaults shortDateFormat]; } - (void) setUserShortDateFormat: (NSString *) newFormat { - if ([newFormat isEqualToString: @"default"]) - [userDefaults removeObjectForKey: @"ShortDateFormat"]; - else - [userDefaults setObject: newFormat forKey: @"ShortDateFormat"]; + [userDefaults setShortDateFormat: newFormat]; } - (NSArray *) longDateFormatsList @@ -296,8 +261,7 @@ static BOOL forwardEnabled = NO; { NSString *longDateFormat; - longDateFormat = [userDefaults objectForKey: @"LongDateFormat"]; - + longDateFormat = [userDefaults longDateFormat]; if (!longDateFormat) longDateFormat = @"default"; @@ -307,9 +271,9 @@ static BOOL forwardEnabled = NO; - (void) setUserLongDateFormat: (NSString *) newFormat { if ([newFormat isEqualToString: @"default"]) - [userDefaults removeObjectForKey: @"LongDateFormat"]; + [userDefaults unsetLongDateFormat]; else - [userDefaults setObject: newFormat forKey: @"LongDateFormat"]; + [userDefaults setLongDateFormat: newFormat]; } - (NSArray *) timeFormatsList @@ -360,15 +324,15 @@ static BOOL forwardEnabled = NO; - (NSString *) userTimeFormat { - return [user timeFormat]; + return [userDefaults timeFormat]; } - (void) setUserTimeFormat: (NSString *) newFormat { if ([newFormat isEqualToString: @"default"]) - [userDefaults removeObjectForKey: @"TimeFormat"]; + [userDefaults unsetTimeFormat]; else - [userDefaults setObject: newFormat forKey: @"TimeFormat"]; + [userDefaults setTimeFormat: newFormat]; } - (NSArray *) daysList @@ -390,16 +354,17 @@ static BOOL forwardEnabled = NO; - (NSString *) userWeekStartDay { - return [NSString stringWithFormat: @"%d", [user firstDayOfWeek]]; + return [NSString stringWithFormat: @"%d", [userDefaults firstDayOfWeek]]; } - (void) setUserWeekStartDay: (NSString *) newDay { - [userDefaults setObject: newDay forKey: @"WeekStartDay"]; + [userDefaults setFirstDayOfWeek: [newDay intValue]]; } - (NSArray *) hoursList { + static NSMutableArray *hours = nil; unsigned int currentHour; if (!hours) @@ -415,22 +380,24 @@ static BOOL forwardEnabled = NO; - (NSString *) userDayStartTime { - return [NSString stringWithFormat: @"%02d:00", [user dayStartHour]]; + return [NSString stringWithFormat: @"%02d:00", + [userDefaults dayStartHour]]; } - (void) setUserDayStartTime: (NSString *) newTime { - [userDefaults setObject: newTime forKey: @"DayStartTime"]; + [userDefaults setDayStartTime: newTime]; } - (NSString *) userDayEndTime { - return [NSString stringWithFormat: @"%02d:00", [user dayEndHour]]; + return [NSString stringWithFormat: @"%02d:00", + [userDefaults dayEndHour]]; } - (void) setUserDayEndTime: (NSString *) newTime { - [userDefaults setObject: newTime forKey: @"DayEndTime"]; + [userDefaults setDayEndTime: newTime]; } - (NSArray *) firstWeekList @@ -450,49 +417,48 @@ static BOOL forwardEnabled = NO; - (NSString *) userFirstWeek { - return [userDefaults objectForKey: @"FirstWeek"]; + return [userDefaults firstWeekOfYear]; } - (void) setUserFirstWeek: (NSString *) newFirstWeek { - [userDefaults setObject: newFirstWeek forKey: @"FirstWeek"]; + [userDefaults setFirstWeekOfYear: newFirstWeek]; } -- (NSString *) reminderEnabled +- (BOOL) reminderEnabled { - NSString *reminderEnabled; - - reminderEnabled = [userDefaults objectForKey: @"ReminderEnabled"]; - - return ((!reminderEnabled || [reminderEnabled boolValue]) - ? @"YES" : @"NO"); + return [userDefaults reminderEnabled]; } -- (void) setReminderEnabled: (NSString *) newValue +- (void) setReminderEnabled: (BOOL) newValue { - [userDefaults setObject: newValue forKey: @"ReminderEnabled"]; + [userDefaults setReminderEnabled: newValue]; } -- (NSString *) remindWithASound +- (BOOL) remindWithASound { - NSString *remindWithASound; - - remindWithASound = [userDefaults objectForKey: @"RemindWithASound"]; - - return ((!remindWithASound || [remindWithASound boolValue]) - ? @"YES" : @"NO"); + return [userDefaults remindWithASound]; } -- (void) setRemindWithASound: (NSString *) newValue +- (void) setRemindWithASound: (BOOL) newValue { - [userDefaults setObject: newValue forKey: @"RemindWithASound"]; + [userDefaults setRemindWithASound: newValue]; } - (NSArray *) reminderTimesList { - return [NSArray arrayWithObjects: @"0000", @"0005", @"0010", @"0015", - @"0030", @"0100", @"0200", @"0400", @"0800", @"1200", - @"2400", @"4800", nil]; + static NSArray *reminderTimesList = nil; + + if (!reminderTimesList) + { + reminderTimesList = [NSArray arrayWithObjects: @"0000", @"0005", + @"0010", @"0015", @"0030", @"0100", + @"0200", @"0400", @"0800", @"1200", + @"2400", @"4800", nil]; + [reminderTimesList retain]; + } + + return reminderTimesList; } - (NSString *) itemReminderTimeText @@ -503,70 +469,56 @@ static BOOL forwardEnabled = NO; - (NSString *) userReminderTime { - return [userDefaults objectForKey: @"ReminderTime"]; + return [userDefaults reminderTime]; } - (void) setReminderTime: (NSString *) newTime { - [userDefaults setObject: newTime forKey: @"ReminderTime"]; + [userDefaults setReminderTime: newTime]; } /* Mailer */ - (void) setShowSubscribedFoldersOnly: (BOOL) showSubscribedFoldersOnly { - [userDefaults setBool: showSubscribedFoldersOnly forKey: @"showSubscribedFoldersOnly"]; // should be capitalized .. + [userDefaults setMailShowSubscribedFoldersOnly: showSubscribedFoldersOnly]; } - (BOOL) showSubscribedFoldersOnly { - NSString *showSubscribedFoldersOnly; - BOOL r; - - showSubscribedFoldersOnly = [userDefaults stringForKey: @"showSubscribedFoldersOnly"]; - if (showSubscribedFoldersOnly) - r = [showSubscribedFoldersOnly boolValue]; - else - r = defaultShowSubscribedFoldersOnly; - - return r; + return [userDefaults mailShowSubscribedFoldersOnly]; } - (NSArray *) messageCheckList { - NSArray *defaultList; - NSMutableArray *rc; - NSString *tmp; - int i, count; + NSArray *intervalsList; + NSMutableArray *messageCheckList; + NSString *value; + int count, max, interval; - defaultList = [NSMutableArray arrayWithArray: - [[NSUserDefaults standardUserDefaults] - arrayForKey: @"SOGoMailPollingIntervals"]]; - if ([defaultList count] > 0) + intervalsList = [[user domainDefaults] mailPollingIntervals]; + messageCheckList = [NSMutableArray arrayWithObjects: @"manually", nil]; + max = [intervalsList count]; + for (count = 0; count < max; count++) { - rc = [NSMutableArray arrayWithObjects: @"manually", nil]; - count = [defaultList count]; - for (i = 0; i < count; i++) + interval = [[intervalsList objectAtIndex: count] intValue]; + value = nil; + if (interval == 1) + value = @"every_minute"; + else if (interval == 60) + value = @"once_per_hour"; + else if (interval == 2 || interval == 5 || interval == 10 + || interval == 20 || interval == 30) + value = [NSString stringWithFormat: @"every_%d_minutes", interval]; + else { - int value = [[defaultList objectAtIndex: i] intValue]; - tmp = nil; - if (value == 1) - tmp = @"every_minute"; - else if (value == 60) - tmp = @"once_per_hour"; - else if (value == 2 || value == 5 || value == 10 - || value == 20 || value == 30) - tmp = [NSString stringWithFormat: @"every_%d_minutes", value]; - if (tmp) - [rc addObject: tmp]; + [self warnWithFormat: @"interval '%d' not handled", interval]; + value = nil; } + if (value) + [messageCheckList addObject: value]; } - else - rc = [NSArray arrayWithObjects: @"manually", @"every_minute", - @"every_2_minutes", @"every_5_minutes", @"every_10_minutes", - @"every_20_minutes", @"every_30_minutes", @"once_per_hour", - nil]; - return rc; + return messageCheckList; } - (NSString *) itemMessageCheckText @@ -577,12 +529,12 @@ static BOOL forwardEnabled = NO; - (NSString *) userMessageCheck { - return [userDefaults stringForKey: @"MessageCheck"]; + return [userDefaults mailMessageCheck]; } - (void) setUserMessageCheck: (NSString *) newMessageCheck { - [userDefaults setObject: newMessageCheck forKey: @"MessageCheck"]; + [userDefaults setMailMessageCheck: newMessageCheck]; } - (NSArray *) messageForwardingList @@ -598,14 +550,15 @@ static BOOL forwardEnabled = NO; - (NSString *) userMessageForwarding { - return [user messageForwarding]; + return [userDefaults mailMessageForwarding]; } - (void) setUserMessageForwarding: (NSString *) newMessageForwarding { - [userDefaults setObject: newMessageForwarding forKey: @"MessageForwarding"]; + [userDefaults setMailMessageForwarding: newMessageForwarding]; } +/* // @@ -622,17 +575,16 @@ static BOOL forwardEnabled = NO; - (NSString *) itemIdentityText { return [(NSDictionary *) item keysWithFormat: @"%{fullName} <%{email}>"]; -} + } */ - (NSString *) signature { - [user migrateSignature]; - return [userDefaults stringForKey: @"MailSignature"]; + return [userDefaults mailSignature]; } - (void) setSignature: (NSString *) newSignature { - [userDefaults setObject: newSignature forKey: @"MailSignature"]; + [userDefaults setMailSignature: newSignature]; } - (NSArray *) replyPlacementList @@ -648,17 +600,12 @@ static BOOL forwardEnabled = NO; - (NSString *) userReplyPlacement { - return [user replyPlacement]; + return [userDefaults mailReplyPlacement]; } - (void) setUserReplyPlacement: (NSString *) newReplyPlacement { - [userDefaults setObject: newReplyPlacement forKey: @"ReplyPlacement"]; -} - -- (NSArray *) signaturePlacementList -{ - return [NSArray arrayWithObjects: @"above", @"below", nil]; + [userDefaults setMailReplyPlacement: newReplyPlacement]; } - (NSString *) itemSignaturePlacementText @@ -667,9 +614,19 @@ static BOOL forwardEnabled = NO; [NSString stringWithFormat: @"signatureplacement_%@", item]]; } +- (NSArray *) signaturePlacementList +{ + return [NSArray arrayWithObjects: @"above", @"below", nil]; +} + +- (void) setUserSignaturePlacement: (NSString *) newSignaturePlacement +{ + [userDefaults setMailSignaturePlacement: newSignaturePlacement]; +} + - (NSString *) userSignaturePlacement { - return [user signaturePlacement]; + return [userDefaults mailSignaturePlacement]; } - (NSArray *) composeMessagesType @@ -679,46 +636,33 @@ static BOOL forwardEnabled = NO; - (NSString *) itemComposeMessagesText { - return [self labelForKey: [NSString stringWithFormat: @"composemessagestype_%@", item]]; + return [self labelForKey: [NSString stringWithFormat: + @"composemessagestype_%@", item]]; } - (NSString *) userComposeMessagesType { - NSString *userComposeMessagesType; - - userComposeMessagesType - = [userDefaults stringForKey: @"ComposeMessagesType"]; - if (!userComposeMessagesType) - userComposeMessagesType = @"text"; - - return userComposeMessagesType; + return [userDefaults mailComposeMessageType]; } - (void) setUserComposeMessagesType: (NSString *) newType { if (![[self userComposeMessagesType] isEqualToString: newType]) - { - composeMessageTypeHasChanged = YES; - [userDefaults setObject: newType forKey: @"ComposeMessagesType"]; - } -} - -- (void) setUserSignaturePlacement: (NSString *) newSignaturePlacement -{ - [userDefaults setObject: newSignaturePlacement forKey: @"SignaturePlacement"]; + composeMessageTypeHasChanged = YES; + [userDefaults setMailComposeMessageType: newType]; } /* mail autoreply (vacation) */ - (BOOL) isVacationEnabled { - return vacationEnabled; + return [[user domainDefaults] vacationEnabled]; } - (void) setEnableVacation: (BOOL) enableVacation { [vacationOptions setObject: [NSNumber numberWithBool: enableVacation] - forKey: @"enabled"]; + forKey: @"enabled"]; } - (BOOL) enableVacation @@ -728,8 +672,7 @@ static BOOL forwardEnabled = NO; - (void) setAutoReplyText: (NSString *) theText { - [vacationOptions setObject: theText - forKey: @"autoReplyText"]; + [vacationOptions setObject: theText forKey: @"autoReplyText"]; } - (NSString *) autoReplyText @@ -741,8 +684,8 @@ static BOOL forwardEnabled = NO; { NSArray *addresses; - addresses = [[theAddresses componentsSeparatedByString: @","] trimmedComponents]; - + addresses = [[theAddresses componentsSeparatedByString: @","] + trimmedComponents]; [vacationOptions setObject: addresses forKey: @"autoReplyEmailAddresses"]; } @@ -756,7 +699,7 @@ static BOOL forwardEnabled = NO; uniqueAddressesList = [NSMutableArray array]; addressesList = [NSMutableArray arrayWithArray: [user allEmails]]; - for (i = 0; i < [addressesList count]; i++) + for (i = 0; i < [addressesList count]; i++) { address = [addressesList objectAtIndex: i]; if (![uniqueAddressesList containsObject: address]) @@ -772,17 +715,19 @@ static BOOL forwardEnabled = NO; addressesList = [vacationOptions objectForKey: @"autoReplyEmailAddresses"]; - return (addressesList? - [addressesList componentsJoinedByString: @", "] : [self defaultEmailAddresses]); + return (addressesList + ? [addressesList componentsJoinedByString: @", "] + : [self defaultEmailAddresses]); } - (NSArray *) daysBetweenResponsesList { - static NSArray* daysBetweenResponses = nil; + static NSArray *daysBetweenResponses = nil; if (!daysBetweenResponses) { - daysBetweenResponses = [NSArray arrayWithObjects: @"1", @"2", @"3", @"5", @"7", @"14", @"21", @"30", nil]; + daysBetweenResponses = [NSArray arrayWithObjects: @"1", @"2", @"3", + @"5", @"7", @"14", @"21", @"30", nil]; [daysBetweenResponses retain]; } @@ -831,7 +776,7 @@ static BOOL forwardEnabled = NO; - (BOOL) isForwardEnabled { - return forwardEnabled; + return [[user domainDefaults] forwardEnabled]; } - (void) setEnableForward: (BOOL) enableForward @@ -871,18 +816,22 @@ static BOOL forwardEnabled = NO; - (NSArray *) availableModules { - NSMutableArray *rc, *modules; - int i, count; + NSMutableArray *availableModules, *modules; + NSString *module; + int count, max; modules = [NSMutableArray arrayWithObjects: @"Calendar", @"Mail", nil]; - rc = [NSMutableArray arrayWithObjects: @"Last", @"Contacts", nil]; - count = [modules count]; + availableModules = [NSMutableArray arrayWithObjects: @"Last", @"Contacts", + nil]; + max = [modules count]; + for (count = 0; count < max; count++) + { + module = [modules objectAtIndex: count]; + if ([user canAccessModule: module]) + [availableModules addObject: module]; + } - for (i = 0; i < count; i++) - if ([user canAccessModule: [modules objectAtIndex: i]]) - [rc addObject: [modules objectAtIndex: i]]; - - return rc; + return availableModules; } - (NSString *) itemModuleText @@ -892,17 +841,25 @@ static BOOL forwardEnabled = NO; - (NSString *) userDefaultModule { - NSUserDefaults *ud; - ud = [user userDefaults]; + NSString *userDefaultModule; - return [ud stringForKey: @"SOGoUIxDefaultModule"]; + if ([userDefaults rememberLastModule]) + userDefaultModule = @"Last"; + else + userDefaultModule = [userDefaults loginModule]; + + return userDefaultModule; } - (void) setUserDefaultModule: (NSString *) newValue { - NSUserDefaults *ud; - ud = [user userDefaults]; - [ud setObject: newValue forKey: @"SOGoUIxDefaultModule"]; + if ([newValue isEqualToString: @"Last"]) + [userDefaults setRememberLastModule: YES]; + else + { + [userDefaults setRememberLastModule: NO]; + [userDefaults setLoginModule: newValue]; + } } - (id ) defaultAction @@ -922,10 +879,10 @@ static BOOL forwardEnabled = NO; mailAccounts = [[[context activeUser] mailAccounts] objectAtIndex: 0]; folder = [[self clientObject] mailAccountsFolder: @"Mail" - inContext: context]; + inContext: context]; account = [folder lookupName: [[mailAccounts objectForKey: @"name"] asCSSIdentifier] - inContext: context - acquire: NO]; + inContext: context + acquire: NO]; [account updateFilters]; @@ -966,12 +923,14 @@ static BOOL forwardEnabled = NO; - (BOOL) shouldDisplayAdditionalPreferences { - return shouldDisplayAdditionalPreferences; + return [[SOGoSystemDefaults sharedSystemDefaults] + uixAdditionalPreferences]; } - (BOOL) shouldDisplayPasswordChange { - return shouldDisplayPasswordChange; + return [[SOGoSystemDefaults sharedSystemDefaults] + userCanChangePassword]; } - (NSString *) nameLabel @@ -987,26 +946,25 @@ static BOOL forwardEnabled = NO; - (NSArray *) categories { NSDictionary *element; - NSArray *k, *v, *names; - NSMutableArray *rc, *colors; + NSArray *k, *v, *names, *colors; + NSMutableArray *categories, *newColors; int i, count; - names = [userDefaults arrayForKey: @"CalendarCategories"]; + names = [userDefaults calendarCategories]; if (names) - colors = [NSMutableArray arrayWithArray: - [userDefaults arrayForKey: @"CalendarCategoriesColors"]]; + colors = [userDefaults calendarCategoriesColors]; else { names = [[self labelForKey: @"category_labels"] componentsSeparatedByString: @","]; - count = [names count]; - colors = [NSMutableArray arrayWithCapacity: count]; + newColors = [NSMutableArray arrayWithCapacity: count]; for (i = 0; i < count; i++) - [colors addObject: @"#F0F0F0"]; + [newColors addObject: @"#F0F0F0"]; + colors = newColors; } - rc = [NSMutableArray array]; + categories = [NSMutableArray array]; k = [NSArray arrayWithObjects: @"name", @"color", nil]; count = [names count]; @@ -1017,10 +975,10 @@ static BOOL forwardEnabled = NO; element = [NSDictionary dictionaryWithObjects: v forKeys: k]; - [rc addObject: element]; + [categories addObject: element]; } - return rc; + return categories; } @@ -1049,29 +1007,26 @@ static BOOL forwardEnabled = NO; } else { - [userDefaults setObject: [plist objectAtIndex: 0] - forKey: @"CalendarCategories"]; - [userDefaults setObject: [plist objectAtIndex: 1] - forKey: @"CalendarCategoriesColors"]; + [userDefaults setCalendarCategories: [plist objectAtIndex: 0]]; + [userDefaults setCalendarCategoriesColors: [plist objectAtIndex: 1]]; } } - (NSArray *) languages { - return [NSArray arrayWithObjects: @"Czech", @"Dutch", @"English", @"French", - @"German", @"Hungarian", @"Italian", @"BrazilianPortuguese", - @"Russian", @"Spanish", @"Welsh", nil]; + return [[SOGoSystemDefaults sharedSystemDefaults] + supportedLanguages]; } - (NSString *) language { - return [userDefaults objectForKey: @"Language"]; + return [userDefaults language]; } - (void) setLanguage: (NSString *) newLanguage { if ([[self languages] containsObject: newLanguage]) - [userDefaults setObject: newLanguage forKey: @"Language"]; + [userDefaults setLanguage: newLanguage]; } - (NSString *) languageText diff --git a/UI/SOGoUI/GNUmakefile b/UI/SOGoUI/GNUmakefile index eb688328b..385515bf5 100644 --- a/UI/SOGoUI/GNUmakefile +++ b/UI/SOGoUI/GNUmakefile @@ -16,8 +16,7 @@ libSOGoUI_HEADER_FILES += \ \ UIxJSClose.h \ UIxComponent.h \ - SOGoAptFormatter.h \ - WOContext+UIx.h \ + SOGoAptFormatter.h libSOGoUI_OBJC_FILES += \ \ @@ -25,7 +24,6 @@ libSOGoUI_OBJC_FILES += \ UIxComponent.m \ UIxModuleAccessDenied.m \ SOGoAptFormatter.m \ - WOContext+UIx.m \ SOGoACLAdvisory.m \ SOGoFolderAdvisory.m diff --git a/UI/SOGoUI/SOGoACLAdvisory.m b/UI/SOGoUI/SOGoACLAdvisory.m index 86935d9cd..1c66b9177 100644 --- a/UI/SOGoUI/SOGoACLAdvisory.m +++ b/UI/SOGoUI/SOGoACLAdvisory.m @@ -193,6 +193,7 @@ NGMutableHashMap *headerMap; NGMimeMessage *message; NGMimeMultipartBody *body; + SOGoMailer *mailer; SOGoUser *activeUser; NSDictionary *identity; NSString *from, *fullMail; @@ -222,9 +223,10 @@ [message setBody: body]; [body release]; - [[SOGoMailer sharedMailer] sendMimePart: message - toRecipients: [NSArray arrayWithObject: recipient] - sender: from]; + mailer = [SOGoMailer mailerWithDomainDefaults: [activeUser domainDefaults]]; + [mailer sendMimePart: message + toRecipients: [NSArray arrayWithObject: recipient] + sender: from]; } @end diff --git a/UI/SOGoUI/SOGoFolderAdvisory.m b/UI/SOGoUI/SOGoFolderAdvisory.m index 25887eca8..00fc813e2 100644 --- a/UI/SOGoUI/SOGoFolderAdvisory.m +++ b/UI/SOGoUI/SOGoFolderAdvisory.m @@ -172,6 +172,7 @@ NGMutableHashMap *headerMap; NGMimeMessage *message; NGMimeMultipartBody *body; + SOGoDomainDefaults *dd; SOGoUser *activeUser; NSDictionary *identity; NSString *from, *fullMail; @@ -201,9 +202,11 @@ [message setBody: body]; [body release]; - [[SOGoMailer sharedMailer] sendMimePart: message - toRecipients: [NSArray arrayWithObject: recipient] - sender: from]; + dd = [activeUser domainDefaults]; + [[SOGoMailer mailerWithDomainDefaults: dd] + sendMimePart: message + toRecipients: [NSArray arrayWithObject: recipient] + sender: from]; } @end diff --git a/UI/SOGoUI/UIxComponent.m b/UI/SOGoUI/UIxComponent.m index a087de476..a6b14a238 100644 --- a/UI/SOGoUI/UIxComponent.m +++ b/UI/SOGoUI/UIxComponent.m @@ -22,7 +22,6 @@ #import #import #import -#import #import #import #import @@ -39,14 +38,15 @@ #import #import -#import -#import -#import -#import -#import -#import -// #import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import "UIxJSClose.h" @@ -64,21 +64,15 @@ static NSMutableArray *abbrDayLabelKeys = nil; static NSMutableArray *monthLabelKeys = nil; static NSMutableArray *abbrMonthLabelKeys = nil; -static BOOL uixDebugEnabled = NO; - + (int)version { return [super version] + 0 /* v2 */; } + (void)initialize { - NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; - NSAssert2([super version] == 2, @"invalid superclass (%@) version %i !", NSStringFromClass([self superclass]), [super version]); - uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"]; - if (dayLabelKeys == nil) { dayLabelKeys = [[NSMutableArray alloc] initWithCapacity:7]; [dayLabelKeys addObject:@"Sunday"]; @@ -409,16 +403,16 @@ static BOOL uixDebugEnabled = NO; - (NSCalendarDate *) selectedDate { - NSTimeZone *userTimeZone; + SOGoUserDefaults *ud; if (!_selectedDate) { - userTimeZone = [[context activeUser] timeZone]; + ud = [[context activeUser] userDefaults]; _selectedDate = [NSCalendarDate dateFromShortDateString: [self queryParameterForKey: @"day"] andShortTimeString: [self queryParameterForKey: @"hm"] - inTimeZone: userTimeZone]; + inTimeZone: [ud timeZone]]; [_selectedDate retain]; } @@ -427,10 +421,10 @@ static BOOL uixDebugEnabled = NO; - (NSString *) dateStringForDate: (NSCalendarDate *) _date { - NSTimeZone *userTimeZone; + SOGoUserDefaults *ud; - userTimeZone = [[context activeUser] timeZone]; - [_date setTimeZone: userTimeZone]; + ud = [[context activeUser] userDefaults]; + [_date setTimeZone: [ud timeZone]]; return [_date descriptionWithCalendarFormat: @"%Y%m%d"]; } @@ -659,9 +653,13 @@ static BOOL uixDebugEnabled = NO; return SOGoBuildDate; } -- (BOOL)isUIxDebugEnabled +- (BOOL) isUIxDebugEnabled { - return uixDebugEnabled; + SOGoSystemDefaults *sd; + + sd = [SOGoSystemDefaults sharedSystemDefaults]; + + return [sd uixDebugEnabled]; } @end /* UIxComponent */ diff --git a/UI/SOGoUI/WOContext+UIx.h b/UI/SOGoUI/WOContext+UIx.h deleted file mode 100644 index b104d9d00..000000000 --- a/UI/SOGoUI/WOContext+UIx.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright (C) 2000-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 __SOGoUI_WOContext_UIx_H_ -#define __SOGoUI_WOContext_UIx_H_ - -#include - -@interface WOContext (UIx) - -- (BOOL)isUIxDebugEnabled; - -@end - -#endif /* __SOGoUI_WOContext_UIx_H_ */ diff --git a/UI/SOGoUI/WOContext+UIx.m b/UI/SOGoUI/WOContext+UIx.m deleted file mode 100644 index 36c2f9f43..000000000 --- a/UI/SOGoUI/WOContext+UIx.m +++ /dev/null @@ -1,44 +0,0 @@ -/* - Copyright (C) 2000-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. -*/ - -#import -#import - -#import "WOContext+UIx.h" - -@implementation WOContext (UIx) - -- (BOOL)isUIxDebugEnabled { - NSNumber *bv; - - if ((bv = [self objectForKey:@"_isUIxDebugEnabled"]) == nil) { - NSUserDefaults *ud; - BOOL uixDebugEnabled; - - ud = [NSUserDefaults standardUserDefaults]; - uixDebugEnabled = [ud boolForKey:@"SOGoUIxDebugEnabled"]; - bv = [NSNumber numberWithBool:uixDebugEnabled]; - [self setObject:bv forKey:@"_isUIxDebugEnabled"]; - } - return [bv boolValue]; -} - -@end diff --git a/UI/Scheduler/UIxAppointmentEditor.m b/UI/Scheduler/UIxAppointmentEditor.m index a378d6807..2f4ce85c2 100644 --- a/UI/Scheduler/UIxAppointmentEditor.m +++ b/UI/Scheduler/UIxAppointmentEditor.m @@ -43,17 +43,18 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import -#import +#import #import "UIxComponentEditor.h" #import "UIxAppointmentEditor.h" @@ -207,22 +208,22 @@ { NSCalendarDate *newStartDate, *now; NSTimeZone *timeZone; - SOGoUser *user; + SOGoUserDefaults *ud; int hour; unsigned int uStart, uEnd; newStartDate = [self selectedDate]; if (![[self queryParameterForKey: @"hm"] length]) { + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; now = [NSCalendarDate calendarDate]; - timeZone = [[context activeUser] timeZone]; [now setTimeZone: timeZone]; - user = [context activeUser]; - uStart = [user dayStartHour]; + uStart = [ud dayStartHour]; if ([now isDateOnSameDay: newStartDate]) { - uEnd = [user dayEndHour]; + uEnd = [ud dayEndHour]; hour = [now hourOfDay]; if (hour < uStart) newStartDate = [now hour: uStart minute: 0]; @@ -245,10 +246,13 @@ NSTimeZone *timeZone; unsigned int minutes; SOGoObject *co; + SOGoUserDefaults *ud; [self event]; co = [self clientObject]; - timeZone = [[context activeUser] timeZone]; + + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; if ([co isNew] && [co isKindOfClass: [SOGoCalendarComponent class]]) @@ -343,8 +347,13 @@ iCalRecurrenceRule *rule; NSEnumerator *rules; NSCalendarDate *untilDate; + SOGoUserDefaults *ud; + NSTimeZone *timeZone; rules = [[event recurrenceRules] objectEnumerator]; + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; + while ((rule = [rules nextObject])) { untilDate = [rule untilDate]; @@ -354,7 +363,7 @@ NSCalendarDate *date; date = [[event startDate] copy]; - [date setTimeZone: [[context activeUser] timeZone]]; + [date setTimeZone: timeZone]; untilDate = [untilDate dateByAddingYears:0 months:0 days:0 @@ -431,7 +440,7 @@ NSDictionary *data; NSCalendarDate *firstDate, *eventDate; NSTimeZone *timeZone; - SOGoUser *user; + SOGoUserDefaults *ud; SOGoCalendarComponent *co; iCalEvent *master; BOOL resetAlarm; @@ -440,8 +449,8 @@ [self event]; result = [self responseWithStatus: 200]; - user = [context activeUser]; - timeZone = [user timeZone]; + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; eventDate = [event startDate]; [eventDate setTimeZone: timeZone]; co = [self clientObject]; @@ -504,6 +513,7 @@ inContext: (WOContext *) _ctx { int nbrDays; + SOGoUserDefaults *ud; [self event]; @@ -526,8 +536,10 @@ if ([[self clientObject] isNew]) { iCalTimeZone *tz; + + ud = [[context activeUser] userDefaults]; - tz = [iCalTimeZone timeZoneForName: [[[context activeUser] timeZone] name]]; + tz = [iCalTimeZone timeZoneForName: [ud timeZoneName]]; [[event parent] addTimeZone: tz]; [(iCalDateTime *)[event uniqueChildWithTag: @"dtstart"] setTimeZone: tz]; [(iCalDateTime *)[event uniqueChildWithTag: @"dtend"] setTimeZone: tz]; diff --git a/UI/Scheduler/UIxAttendeesEditor.m b/UI/Scheduler/UIxAttendeesEditor.m index 8965286fb..8e679f967 100644 --- a/UI/Scheduler/UIxAttendeesEditor.m +++ b/UI/Scheduler/UIxAttendeesEditor.m @@ -23,7 +23,8 @@ #import #import -#import +#import +#import #import #import "UIxAttendeesEditor.h" @@ -79,12 +80,20 @@ - (unsigned int) dayStartHour { - return [[context activeUser] dayStartHour]; + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + + return [ud dayStartHour]; } - (unsigned int) dayEndHour { - return [[context activeUser] dayEndHour]; + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + + return [ud dayEndHour]; } @end diff --git a/UI/Scheduler/UIxCalDateSelector.m b/UI/Scheduler/UIxCalDateSelector.m index c85e9aedd..47305ccac 100644 --- a/UI/Scheduler/UIxCalDateSelector.m +++ b/UI/Scheduler/UIxCalDateSelector.m @@ -22,6 +22,8 @@ #import +#import +#import #import #import "UIxCalDateSelector.h" @@ -95,7 +97,11 @@ - (unsigned int) firstDayOfWeek { - return [[context activeUser] firstDayOfWeek]; + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + + return [ud firstDayOfWeek]; } /* labels */ diff --git a/UI/Scheduler/UIxCalDayTable.h b/UI/Scheduler/UIxCalDayTable.h index 1ef5abcfd..88ab136e8 100644 --- a/UI/Scheduler/UIxCalDayTable.h +++ b/UI/Scheduler/UIxCalDayTable.h @@ -43,7 +43,6 @@ NSMutableArray *hoursToDisplay; NSArray *weekDays; SOGoDateFormatter *dateFormatter; - NSUserDefaults *ud; NSString *timeFormat; } diff --git a/UI/Scheduler/UIxCalDayTable.m b/UI/Scheduler/UIxCalDayTable.m index 3945af985..a38c44860 100644 --- a/UI/Scheduler/UIxCalDayTable.m +++ b/UI/Scheduler/UIxCalDayTable.m @@ -25,14 +25,15 @@ #import #import #import -#import +#import /* for locale string constants */ #import #import #import -#import -#import +#import +#import +#import #import "../../Main/SOGo.h" @@ -44,12 +45,17 @@ - (id) init { + NSDictionary *locale; + NSString *language; + SOGoUser *user; + SOGoUserDefaults *ud; + if ((self = [super init])) { - NSDictionary *locale; - NSString *language; - - language = [[context activeUser] language]; + user = [context activeUser]; + ud = [user userDefaults]; + ASSIGN (timeFormat, [ud timeFormat]); + language = [ud language]; locale = [[WOApplication application] localeForLanguageNamed: language]; daysToDisplay = nil; @@ -60,10 +66,10 @@ currentTableHour = nil; weekDays = [locale objectForKey: NSShortWeekDayNameArray]; [weekDays retain]; - dateFormatter = [[context activeUser] dateFormatterInContext: context]; + dateFormatter = [user dateFormatterInContext: context]; [dateFormatter retain]; } - + return self; } @@ -75,6 +81,7 @@ [daysToDisplay release]; [hoursToDisplay release]; [dateFormatter release]; + [timeFormat release]; [super dealloc]; } @@ -120,9 +127,6 @@ { unsigned int currentHour, lastHour; - // For later in method currentTableHour - timeFormat = [[context activeUser] timeFormat]; - if (!hoursToDisplay) { hoursToDisplay = [NSMutableArray new]; @@ -333,14 +337,13 @@ { NSMutableString *cellClass; int hour; - SOGoUser *user; + SOGoUserDefaults *ud; cellClass = [NSMutableString string]; hour = [currentTableHour intValue]; - user = [context activeUser]; + ud = [[context activeUser] userDefaults]; [cellClass appendFormat: @"clickableHourCell clickableHourCell%d", hour]; - if (hour < [user dayStartHour] - || hour > [user dayEndHour] - 1) + if (hour < [ud dayStartHour] || hour > [ud dayEndHour] - 1) [cellClass appendString: @" outOfDay"]; return cellClass; diff --git a/UI/Scheduler/UIxCalFilterPanel.m b/UI/Scheduler/UIxCalFilterPanel.m index 9b7939450..4d5cd0648 100644 --- a/UI/Scheduler/UIxCalFilterPanel.m +++ b/UI/Scheduler/UIxCalFilterPanel.m @@ -24,7 +24,6 @@ #import #import #import -#import #import @@ -113,13 +112,13 @@ static NSArray *filters = nil; - (NSString *) selectedFilter { NSString *selectedFilter; - NSUserDefaults *ud; + SOGoUserSettings *us; selectedFilter = [self queryParameterForKey: @"filterpopup"]; if (![selectedFilter length]) { - ud = [[context activeUser] userDefaults]; - selectedFilter = [ud objectForKey: @"CalendarDefaultFilter"]; + us = [[context activeUser] userSettings]; + selectedFilter = [us objectForKey: @"CalendarDefaultFilter"]; } if (![selectedFilter length]) selectedFilter = @"view_today"; diff --git a/UI/Scheduler/UIxCalListingActions.m b/UI/Scheduler/UIxCalListingActions.m index d8c12f4a4..633c2c1ab 100644 --- a/UI/Scheduler/UIxCalListingActions.m +++ b/UI/Scheduler/UIxCalListingActions.m @@ -27,7 +27,6 @@ #import #import #import -#import #import #import @@ -40,15 +39,17 @@ #import #import -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import #import #import @@ -104,7 +105,7 @@ static NSArray *tasksFields = nil; ASSIGN (request, newRequest); user = [[self context] activeUser]; ASSIGN (dateFormatter, [user dateFormatterInContext: context]); - ASSIGN (userTimeZone, [user timeZone]); + ASSIGN (userTimeZone, [[user userDefaults] timeZone]); dayBasedView = NO; } @@ -193,17 +194,15 @@ static NSArray *tasksFields = nil; - (void) _setupContext { SOGoUser *user; - NSTimeZone *userTZ; NSString *param; user = [context activeUser]; userLogin = [user login]; - userTZ = [user timeZone]; param = [request formValueForKey: @"filterpopup"]; if ([param length]) { - [self _setupDatesWithPopup: param andUserTZ: userTZ]; + [self _setupDatesWithPopup: param andUserTZ: userTimeZone]; title = [request formValueForKey: @"search"]; } else @@ -212,7 +211,7 @@ static NSArray *tasksFields = nil; if ([param length] > 0) startDate = [[NSCalendarDate dateFromShortDateString: param andShortTimeString: nil - inTimeZone: userTZ] beginOfDay]; + inTimeZone: userTimeZone] beginOfDay]; else startDate = nil; @@ -220,7 +219,7 @@ static NSArray *tasksFields = nil; if ([param length] > 0) endDate = [[NSCalendarDate dateFromShortDateString: param andShortTimeString: nil - inTimeZone: userTZ] endOfDay]; + inTimeZone: userTimeZone] endOfDay]; else endDate = nil; @@ -462,16 +461,16 @@ static NSArray *tasksFields = nil; - (void) checkFilterValue { NSString *filter; - NSUserDefaults *ud; + SOGoUserSettings *us; filter = [[context request] formValueForKey: @"filterpopup"]; - if ([filter length] + if ([filter length] && ![filter isEqualToString: @"view_all"] && ![filter isEqualToString: @"view_future"]) { - ud = [[context activeUser] userDefaults]; - [ud setObject: filter forKey: @"CalendarDefaultFilter"]; - [ud synchronize]; + us = [[context activeUser] userSettings]; + [us setObject: filter forKey: @"CalendarDefaultFilter"]; + [us synchronize]; } } @@ -986,10 +985,10 @@ _computeBlocksPosition (NSArray *blocks) - (WOResponse *) tasksListAction { - NSUserDefaults *ud; + SOGoUserSettings *us; NSEnumerator *tasks; NSMutableArray *filteredTasks, *filteredTask; - BOOL showCompleted, setUserDefault; + BOOL showCompleted; NSArray *task; int statusCode; unsigned int endDateStamp; @@ -999,19 +998,17 @@ _computeBlocksPosition (NSArray *blocks) [self _setupContext]; +#warning see TODO in SchedulerUI.js about "setud" + showCompleted = [[request formValueForKey: @"show-completed"] intValue]; + if ([request formValueForKey: @"setud"]) + { + us = [[context activeUser] userSettings]; + [us setBool: showCompleted forKey: @"ShowCompletedTasks"]; + [us synchronize]; + } + tasks = [[self _fetchFields: tasksFields forComponentOfType: @"vtodo"] objectEnumerator]; - showCompleted = [[request formValueForKey: @"show-completed"] intValue]; - setUserDefault = [[request formValueForKey: @"setud"] intValue]; - if (setUserDefault) - { - ud = [[context activeUser] userDefaults]; - [ud setBool: showCompleted - forKey: @"ShowCompletedTasks"]; - [ud synchronize]; - } - - while ((task = [tasks nextObject])) { statusCode = [[task objectAtIndex: 2] intValue]; @@ -1256,7 +1253,7 @@ _computeBlocksPosition (NSArray *blocks) - (NSArray *) _loadScheduleLimitsForUsers: (NSArray *) users { - NSUserDefaults *ud; + SOGoUserDefaults *ud; NSCalendarDate *from, *to, *maxFrom, *maxTo; int count; @@ -1271,9 +1268,9 @@ _computeBlocksPosition (NSArray *blocks) roles: nil] userDefaults]; if (ud) { - from = [NSCalendarDate dateWithString: [ud objectForKey: @"DayStartTime"] + from = [NSCalendarDate dateWithString: [ud dayStartTime] calendarFormat: @"%H:%M"]; - to = [NSCalendarDate dateWithString: [ud objectForKey: @"DayEndTime"] + to = [NSCalendarDate dateWithString: [ud dayEndTime] calendarFormat: @"%H:%M"]; maxFrom = (NSCalendarDate *)[from laterDate: maxFrom]; maxTo = (NSCalendarDate *)[to earlierDate: maxTo]; diff --git a/UI/Scheduler/UIxCalMainActions.m b/UI/Scheduler/UIxCalMainActions.m index 965831bb3..e2efff4f5 100644 --- a/UI/Scheduler/UIxCalMainActions.m +++ b/UI/Scheduler/UIxCalMainActions.m @@ -27,15 +27,34 @@ #import #import -#import -#import -#import -#import +#import +#import +#import +#import +#import #import "UIxCalMainActions.h" @implementation UIxCalMainActions +- (NSString *) displayNameForUrl: (NSString *) calendarURL +{ + NSString *rc, *tmp; + + tmp = [calendarURL lastPathComponent]; + if (tmp) + { + if ([[tmp pathExtension] caseInsensitiveCompare: @"ics"] == NSOrderedSame) + rc = [tmp substringToIndex: [tmp length] - 4]; + else + rc = tmp; + } + else + rc = [self labelForKey: @"Web Calendar"]; + + return rc; +} + - (WOResponse *) addWebCalendarAction { WORequest *r; @@ -85,29 +104,10 @@ return response; } -- (NSString *) displayNameForUrl: (NSString *) calendarURL -{ - NSString *rc, *tmp; - - tmp = [calendarURL lastPathComponent]; - if (tmp) - { - if ([[tmp pathExtension] caseInsensitiveCompare: @"ics"] == NSOrderedSame) - rc = [tmp substringToIndex: [tmp length] - 4]; - else - rc = tmp; - } - else - rc = [self labelForKey: @"Web Calendar"]; - - - return rc; -} - - (void) saveUrl: (NSURL *) calendarURL forCalendar: (NSString *) calendarName { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSMutableDictionary *calSettings, *webCalendars; settings = [[context activeUser] userSettings]; @@ -124,7 +124,7 @@ - (WOResponse *) reloadWebCalendarsAction { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSMutableDictionary *calSettings, *webCalendars; NSArray *calendarIds; SOGoWebAppointmentFolder *folder; @@ -154,6 +154,4 @@ return [self responseWith204]; } - - @end diff --git a/UI/Scheduler/UIxCalMainView.h b/UI/Scheduler/UIxCalMainView.h index 26ad9b1bb..19c9ce389 100644 --- a/UI/Scheduler/UIxCalMainView.h +++ b/UI/Scheduler/UIxCalMainView.h @@ -33,7 +33,7 @@ { NSString *monthMenuItem; NSNumber *yearMenuItem; - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *moduleSettings; } diff --git a/UI/Scheduler/UIxCalMainView.m b/UI/Scheduler/UIxCalMainView.m index b1f5ea96b..9ccb05a53 100644 --- a/UI/Scheduler/UIxCalMainView.m +++ b/UI/Scheduler/UIxCalMainView.m @@ -25,7 +25,6 @@ #import #import #import -#import #import #import @@ -34,6 +33,7 @@ #import #import +#import #import @@ -45,17 +45,11 @@ - (void) checkDefaultModulePreference { - NSUserDefaults *userd; - NSString *pref; + SOGoUserDefaults *ud; - userd = [[context activeUser] userDefaults]; - pref = [userd stringForKey: @"SOGoUIxDefaultModule"]; - - if (pref && [pref isEqualToString: @"Last"]) - { - [userd setObject: @"Calendar" forKey: @"SOGoUIxLastModule"]; - [userd synchronize]; - } + ud = [[context activeUser] userDefaults]; + if ([ud rememberLastModule]) + [ud setLoginModule: @"Calendar"]; } - (void) _setupContext @@ -71,12 +65,12 @@ module = [clientObject nameInContainer]; - ud = [activeUser userSettings]; - moduleSettings = [ud objectForKey: module]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: module]; if (!moduleSettings) { moduleSettings = [NSMutableDictionary dictionary]; - [ud setObject: moduleSettings forKey: module]; + [us setObject: moduleSettings forKey: module]; } } @@ -84,7 +78,7 @@ { static NSMutableArray *monthMenuItems = nil; unsigned int count; - + if (!monthMenuItems) { monthMenuItems = [[NSMutableArray alloc] initWithCapacity: 12]; @@ -184,19 +178,27 @@ else return [self responseWithStatus: 400]; - [ud synchronize]; + [us synchronize]; return [self responseWithStatus: 204]; } - (unsigned int) firstDayOfWeek { - return [[context activeUser] firstDayOfWeek]; + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + + return [ud firstDayOfWeek]; } - (unsigned int) dayStartHour { - return [[context activeUser] dayStartHour]; + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + + return [ud dayStartHour]; } - (NSString *) currentView diff --git a/UI/Scheduler/UIxCalMulticolumnDayView.m b/UI/Scheduler/UIxCalMulticolumnDayView.m index 64915a9a2..f84a84f97 100644 --- a/UI/Scheduler/UIxCalMulticolumnDayView.m +++ b/UI/Scheduler/UIxCalMulticolumnDayView.m @@ -24,7 +24,6 @@ #import #import #import -#import #import #import diff --git a/UI/Scheduler/UIxCalView.h b/UI/Scheduler/UIxCalView.h index efb1640ed..0c17ba8e4 100644 --- a/UI/Scheduler/UIxCalView.h +++ b/UI/Scheduler/UIxCalView.h @@ -86,7 +86,6 @@ - (BOOL) showAMPMDates; - (unsigned) dayStartHour; - (unsigned) dayEndHour; -- (BOOL) shouldDisplayWeekend; - (BOOL) shouldDisplayRejectedAppointments; - (NSCalendarDate *) referenceDateForFormatter; diff --git a/UI/Scheduler/UIxCalView.m b/UI/Scheduler/UIxCalView.m index c43641cf1..fed974e4c 100644 --- a/UI/Scheduler/UIxCalView.m +++ b/UI/Scheduler/UIxCalView.m @@ -21,9 +21,9 @@ */ #import -#import -#import -#import +#import +#import +#import #import #import @@ -36,11 +36,12 @@ #import #import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import #import @@ -56,27 +57,15 @@ @implementation UIxCalView -static BOOL shouldDisplayWeekend = NO; - -+ (void) initialize -{ - static BOOL didInit = NO; - NSUserDefaults *ud; - - if (didInit) return; - - ud = [NSUserDefaults standardUserDefaults]; - shouldDisplayWeekend = [ud boolForKey: @"SOGoShouldDisplayWeekend"]; - didInit = YES; -} - - (id) init { + SOGoUserDefaults *ud; + self = [super init]; if (self) { - timeZone = [[context activeUser] timeZone]; - [timeZone retain]; + ud = [[context activeUser] userDefaults]; + ASSIGN (timeZone, [ud timeZone]); aptFormatter = [[SOGoAptFormatter alloc] initWithDisplayTimeZone: timeZone]; aptTooltipFormatter @@ -355,7 +344,7 @@ static BOOL shouldDisplayWeekend = NO; { SOGoUser *activeUser; NSString *module; - NSUserDefaults *ud; + SOGoUserSettings *us; NSMutableDictionary *moduleSettings; SOGoAppointmentFolders *clientObject; @@ -364,18 +353,18 @@ static BOOL shouldDisplayWeekend = NO; module = [clientObject nameInContainer]; - ud = [activeUser userSettings]; - moduleSettings = [ud objectForKey: module]; + us = [activeUser userSettings]; + moduleSettings = [us objectForKey: module]; if (!moduleSettings) { moduleSettings = [NSMutableDictionary dictionary]; - [ud setObject: moduleSettings forKey: module]; + [us setObject: moduleSettings forKey: module]; } if (![theView isEqualToString: (NSString*)[moduleSettings objectForKey: @"View"]]) { [moduleSettings setObject: theView forKey: @"View"]; - [ud synchronize]; + [us synchronize]; } } @@ -471,17 +460,6 @@ static BOOL shouldDisplayWeekend = NO; return 23; } -- (BOOL) shouldDisplayWeekend -{ - return shouldDisplayWeekend; -} - -- (BOOL) shouldHideWeekend -{ - return ![self shouldDisplayWeekend]; -} - - /* URLs */ - (NSString *) appointmentViewURL diff --git a/UI/Scheduler/UIxCalWeekView.m b/UI/Scheduler/UIxCalWeekView.m index 0a075929b..03b7c27d9 100644 --- a/UI/Scheduler/UIxCalWeekView.m +++ b/UI/Scheduler/UIxCalWeekView.m @@ -29,7 +29,8 @@ #import -#import +#import +#import #include "UIxCalWeekView.h" @@ -54,15 +55,17 @@ - (NSCalendarDate *) endDate { unsigned offset; - - if ([self shouldDisplayWeekend]) + SOGoUserDefaults *ud; + + ud = [[context activeUser] userDefaults]; + if ([ud calendarShouldDisplayWeekend]) offset = 7; else offset = 5; - return [[[self startDate] dateByAddingYears:0 months:0 days:offset - hours:0 minutes:0 seconds:0] - endOfDay]; + return [[[self startDate] dateByAddingYears: 0 months: 0 days: offset + hours: 0 minutes: 0 seconds: 0] + endOfDay]; } // - (NSArray *) appointments diff --git a/UI/Scheduler/UIxCalendarProperties.m b/UI/Scheduler/UIxCalendarProperties.m index bd2eb51ce..841faf414 100644 --- a/UI/Scheduler/UIxCalendarProperties.m +++ b/UI/Scheduler/UIxCalendarProperties.m @@ -25,8 +25,9 @@ #import -#import -#import +#import +#import +#import #import "UIxCalendarProperties.h" @@ -100,7 +101,7 @@ - (NSString *) allCalendarSyncTags { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSMutableDictionary *calendarSettings; NSMutableDictionary *syncTags; NSEnumerator *keysList; @@ -174,7 +175,7 @@ - (NSString *) webCalendarURL { - NSUserDefaults *settings; + SOGoUserSettings *settings; NSMutableDictionary *calendarSettings; NSMutableDictionary *webCalendars; NSString *rc; diff --git a/UI/Scheduler/UIxComponentEditor.m b/UI/Scheduler/UIxComponentEditor.m index 5707e881e..2bfe06b62 100644 --- a/UI/Scheduler/UIxComponentEditor.m +++ b/UI/Scheduler/UIxComponentEditor.m @@ -28,7 +28,6 @@ #import #import #import -#import #import #import @@ -55,12 +54,13 @@ #import #import #import -#import #import #import #import #import #import +#import +#import #import #import "../../Main/SOGo.h" @@ -315,6 +315,8 @@ iRANGE(2); - (void) _loadRRules { + SOGoUserDefaults *ud; + // We initialize our repeat ivars if ([component hasRecurrenceRules]) { @@ -421,7 +423,9 @@ iRANGE(2); repeat = @"CUSTOM"; date = [[rule untilDate] copy]; - [date setTimeZone: [[context activeUser] timeZone]]; + + ud = [[context activeUser] userDefaults]; + [date setTimeZone: [ud timeZone]]; [self setRange1: @"2"]; [self setRange2: [date descriptionWithCalendarFormat: dateFormat]]; [date release]; @@ -825,10 +829,10 @@ iRANGE(2); { NSMutableArray *categoryList; NSArray *categoryLabels; - NSUserDefaults *defaults; + SOGoUserDefaults *defaults; defaults = [[context activeUser] userDefaults]; - categoryLabels = [defaults arrayForKey: @"CalendarCategories"]; + categoryLabels = [defaults calendarCategories]; if (!categoryLabels) categoryLabels = [[self labelForKey: @"category_labels"] componentsSeparatedByString: @","]; @@ -1610,12 +1614,15 @@ RANGE(2); else if (range == 2) { NSCalendarDate *date; - SOGoUser *user; - - user = [context activeUser]; + SOGoUserDefaults *ud; + NSDictionary *locale; + + ud = [[context activeUser] userDefaults]; + locale = [[WOApplication application] + localeForLanguageNamed: [ud language]]; date = [NSCalendarDate dateWithString: [self range2] calendarFormat: dateFormat - locale: [[WOApplication application] localeForLanguageNamed: [user language]]]; + locale: locale]; [theRule setUntilDate: date]; } // No end date. diff --git a/UI/Scheduler/UIxTaskEditor.m b/UI/Scheduler/UIxTaskEditor.m index 2065d3ad2..ea37ed390 100644 --- a/UI/Scheduler/UIxTaskEditor.m +++ b/UI/Scheduler/UIxTaskEditor.m @@ -38,12 +38,13 @@ #import #import -#import -#import -#import -#import -#import -#import +#import +#import +#import +#import +#import +#import +#import #import "UIxComponentEditor.h" #import "UIxTaskEditor.h" @@ -255,22 +256,22 @@ { NSCalendarDate *newStartDate, *now; NSTimeZone *timeZone; - SOGoUser *user; + SOGoUserDefaults *ud; int hour; unsigned int uStart, uEnd; newStartDate = [self selectedDate]; if (![[self queryParameterForKey: @"hm"] length]) { + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; now = [NSCalendarDate calendarDate]; - timeZone = [[context activeUser] timeZone]; [now setTimeZone: timeZone]; - user = [context activeUser]; - uStart = [user dayStartHour]; + uStart = [ud dayStartHour]; if ([now isDateOnSameDay: newStartDate]) { - uEnd = [user dayEndHour]; + uEnd = [ud dayEndHour]; hour = [now hourOfDay]; if (hour < uStart) newStartDate = [now hour: uStart minute: 0]; @@ -291,12 +292,14 @@ NSCalendarDate *startDate, *dueDate; NSString *duration; NSTimeZone *timeZone; + SOGoUserDefaults *ud; unsigned int minutes; + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; [self todo]; if (todo) { - timeZone = [[context activeUser] timeZone]; startDate = [todo startDate]; dueDate = [todo due]; hasStartDate = (startDate != nil); @@ -430,14 +433,14 @@ NSDictionary *data; NSCalendarDate *startDate, *dueDate; NSTimeZone *timeZone; - SOGoUser *user; + SOGoUserDefaults *ud; BOOL resetAlarm; [self todo]; result = [self responseWithStatus: 200]; - user = [context activeUser]; - timeZone = [user timeZone]; + ud = [[context activeUser] userDefaults]; + timeZone = [ud timeZone]; startDate = [todo startDate]; [startDate setTimeZone: timeZone]; dueDate = [todo due]; @@ -489,6 +492,9 @@ - (void) takeValuesFromRequest: (WORequest *) _rq inContext: (WOContext *) _ctx { + SOGoUserDefaults *ud; + iCalTimeZone *tz; + [self todo]; [super takeValuesFromRequest: _rq inContext: _ctx]; @@ -523,9 +529,8 @@ if ([[self clientObject] isNew]) { - iCalTimeZone *tz; - - tz = [iCalTimeZone timeZoneForName: [[[context activeUser] timeZone] name]]; + ud = [[context activeUser] userDefaults]; + tz = [iCalTimeZone timeZoneForName: [ud timeZoneName]]; if (hasStartDate || hasDueDate) { diff --git a/UI/Scheduler/UIxTimeDateControl.m b/UI/Scheduler/UIxTimeDateControl.m index e4a3a8c8e..beb6eb23e 100644 --- a/UI/Scheduler/UIxTimeDateControl.m +++ b/UI/Scheduler/UIxTimeDateControl.m @@ -25,6 +25,8 @@ #import #import +#import +#import #import "UIxTimeDateControl.h" @@ -69,14 +71,14 @@ - (void) setDate: (NSCalendarDate *) _date { - NSTimeZone *timeZone; + SOGoUserDefaults *ud; int minuteValue; - timeZone = [[context activeUser] timeZone]; + ud = [[context activeUser] userDefaults]; if (!_date) _date = [NSCalendarDate date]; - [_date setTimeZone: timeZone]; + [_date setTimeZone: [ud timeZone]]; [self _setDate: _date]; @@ -248,9 +250,9 @@ { NSCalendarDate *d; unsigned _year, _month, _day, _hour, _minute, _second; - NSTimeZone *timeZone; + SOGoUserDefaults *ud; - timeZone = [[context activeUser] timeZone]; + ud = [[context activeUser] userDefaults]; /* call super, so that the form values are applied on the popups */ [super takeValuesFromRequest:_rq inContext:_ctx]; @@ -269,7 +271,7 @@ d = [NSCalendarDate dateWithYear: _year month:_month day:_day hour:_hour minute:_minute second:_second - timeZone: timeZone]; + timeZone: [ud timeZone]]; [self _setDate: d]; } } diff --git a/UI/WebServerResources/MailerUI.js b/UI/WebServerResources/MailerUI.js index dcc684400..a9385c76d 100644 --- a/UI/WebServerResources/MailerUI.js +++ b/UI/WebServerResources/MailerUI.js @@ -647,7 +647,7 @@ function messageListCallback(http) { var div = $('mailboxContent'); var table = $('messageList'); - var columnsOrder = UserSettings["SOGoMailListViewColumnsOrder"]; + var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"]; if ( typeof(columnsOrder) == "undefined" ) { columnsOrder = defaultColumnsOrder; } @@ -1524,7 +1524,7 @@ function configureMessageListBodyEvents(table) { // 4 => Unread // 5 => Date // 6 => Priority - var columnsOrder = UserSettings["SOGoMailListViewColumnsOrder"]; + var columnsOrder = UserDefaults["SOGoMailListViewColumnsOrder"]; if ( typeof(columnsOrder) == "undefined" ) { columnsOrder = defaultColumnsOrder; } @@ -1646,7 +1646,7 @@ function initMailer(event) { } function initMessageCheckTimer() { - var messageCheck = UserDefaults["MessageCheck"]; + var messageCheck = UserDefaults["SOGoMailMessageCheck"]; if (messageCheck && messageCheck != "manually") { var interval; if (messageCheck == "once_per_hour") diff --git a/UI/WebServerResources/SchedulerUI.js b/UI/WebServerResources/SchedulerUI.js index 715b459cd..88a4f1935 100644 --- a/UI/WebServerResources/SchedulerUI.js +++ b/UI/WebServerResources/SchedulerUI.js @@ -7,7 +7,7 @@ var listFilter = 'view_today'; var listOfSelection = null; var selectedCalendarCell; -var showCompletedTasks;; +var showCompletedTasks; var currentDay = ''; @@ -1402,6 +1402,10 @@ function refreshEvents() { function refreshTasks(setUserDefault) { var url = "taskslist?show-completed=" + showCompletedTasks; + /* TODO: the logic behind this should be reimplemented properly: + the "taskslist" method should save the status when the 'show-completed' + is set to true and revert to the current status when that parameter is + NOT passed via the url. */ if (setUserDefault == 1) url += "&setud=1"; refreshAlarms(); @@ -2100,7 +2104,7 @@ function onFolderSubscribeCB(folderData) { appendCalendar(folderData["folderName"], folderData["folder"]); refreshEvents(); refreshTasks(); - changeCalendarDisplay(); + changeCalendarDisplay(); } } @@ -2276,6 +2280,8 @@ function drawNowLine () { function initCalendars() { sorting["attribute"] = "start"; sorting["ascending"] = true; + /* FIXME: does this work at all? ShowCompletedTasks is in + UserSettings["Calendar"]... */ showCompletedTasks = UserDefaults['ShowCompletedTasks']; if (!$(document.body).hasClassName("popup")) { diff --git a/UI/WebServerResources/UIxMailEditor.js b/UI/WebServerResources/UIxMailEditor.js index 7b40e17de..2bf431c43 100644 --- a/UI/WebServerResources/UIxMailEditor.js +++ b/UI/WebServerResources/UIxMailEditor.js @@ -235,7 +235,7 @@ function onTextFocus(event) { if (MailEditor.textFirstFocus) { // On first focus, position the caret at the proper position var content = this.getValue(); - var replyPlacement = UserDefaults["ReplyPlacement"]; + var replyPlacement = UserDefaults["SOGoMailReplyPlacement"]; if (replyPlacement == "above" || !mailIsReply) { // for forwards, place caret at top unconditionally this.setCaretTo(0); } @@ -337,7 +337,7 @@ function initMailEditor() { if (sigLimit > -1) MailEditor.signatureLength = (textContent.length - sigLimit); } - if (UserDefaults["ReplyPlacement"] != "above") { + if (UserDefaults["SOGoMailReplyPlacement"] != "above") { textarea.scrollTop = textarea.scrollHeight; } textarea.observe("focus", onTextFocus); @@ -359,7 +359,7 @@ function initMailEditor() { initializePriorityMenu(); - var composeMode = UserDefaults["ComposeMessagesType"]; + var composeMode = UserDefaults["SOGoMailComposeMessageType"]; if (composeMode == "html") { CKEDITOR.replace('text', { @@ -470,7 +470,7 @@ function lineBreakCount(str){ function hasSignature() { try { - return(UserDefaults["MailSignature"].length > 0); + return(UserDefaults["SOGoMailSignature"].length > 0); } catch(e) { return false; } @@ -548,7 +548,7 @@ function onWindowResize(event) { textarea.setStyle({ 'top': hr.offsetTop + 'px' }); // Resize the textarea (message content) - var composeMode = UserDefaults["ComposeMessagesType"]; + var composeMode = UserDefaults["SOGoMailComposeMessageType"]; if (composeMode == "html") { var editor = $('cke_text'); if (editor == null) { diff --git a/configure b/configure index 9d314daab..c84dea1fd 100755 --- a/configure +++ b/configure @@ -23,7 +23,6 @@ ARG_GSMAKE=`gnustep-config --variable=GNUSTEP_MAKEFILES 2>/dev/null` ARG_CFGMAKE="$PWD/config.make" ARG_WITH_DEBUG=1 ARG_WITH_STRIP=0 -ARG_WITH_THREADS=0 ARG_WITH_LDAP_CONFIG=0 GNUSTEP_INSTALLATION_DOMAIN="LOCAL" @@ -64,7 +63,6 @@ Installation directories: --configmake=PATH path to the config file being created --enable-debug turn on debugging and compile time warnings --enable-strip turn on stripping of debug symbols - --enable-thread-safety turn on thread-safety --enable-ldap-config enable LDAP based configuration of SOGo @@ -90,11 +88,6 @@ printParas() { else echo " strip: no"; fi - if test $ARG_WITH_THREADS = 1; then - echo " thread-safe: yes"; - else - echo " thread-safe: no"; - fi if test $ARG_WITH_LDAP_CONFIG = 1; then echo " ldap-based configuration: yes"; else @@ -278,11 +271,6 @@ genConfigMake() { fi cfgwrite "" - if test $ARG_WITH_THREADS = 1; then - cfgwrite "# configured to produce thread-safe code"; - cfgwrite "ADDITIONAL_CPPFLAGS += -DTHREADSAFE=1" - fi - cfgwrite "# enforce shared libraries"; cfgwrite "shared:=yes" cfgwrite "" @@ -417,12 +405,6 @@ processOption() { "x--disable-strip") ARG_WITH_STRIP=0 ;; - "x--enable-thread-safety") - ARG_WITH_THREADS=1 - ;; - "x--disable-thread-safety") - ARG_WITH_THREADS=0 - ;; "x--enable-ldap-config") ARG_WITH_LDAP_CONFIG=1