]> err.no Git - scalable-opengroupware.org/blob - SoObjects/SOGo/SOGoUser.m
9488c1dd35e59bb3b5e8d81fb30ee80b8b56c81b
[scalable-opengroupware.org] / SoObjects / SOGo / SOGoUser.m
1 /*
2   Copyright (C) 2005 SKYRIX Software AG
3
4   This file is part of OpenGroupware.org.
5
6   OGo is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   OGo is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with OGo; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 #import <Foundation/NSArray.h>
23 #import <Foundation/NSNull.h>
24 #import <Foundation/NSTimeZone.h>
25 #import <Foundation/NSUserDefaults.h>
26 #import <Foundation/NSValue.h>
27 #import <NGObjWeb/WOApplication.h>
28 #import <NGObjWeb/WOContext.h>
29 #import <NGObjWeb/WORequest.h>
30 #import <NGObjWeb/SoObject.h>
31 #import <NGExtensions/NSNull+misc.h>
32
33 #import "AgenorUserDefaults.h"
34 #import "LDAPUserManager.h"
35 #import "SOGoDateFormatter.h"
36 #import "SOGoObject.h"
37 #import "SOGoPermissions.h"
38 #import "NSArray+Utilities.h"
39
40 #import "SOGoUser.h"
41
42 static NSTimeZone *serverTimeZone = nil;
43 static NSString *fallbackIMAP4Server = nil;
44 static NSString *defaultLanguage = nil;
45 static NSArray *superUsernames = nil;
46 static NSURL *AgenorProfileURL = nil;
47 static BOOL acceptAnyUser = NO;
48
49 NSString *SOGoWeekStartHideWeekNumbers = @"HideWeekNumbers";
50 NSString *SOGoWeekStartJanuary1 = @"January1";
51 NSString *SOGoWeekStartFirst4DayWeek = @"First4DayWeek";
52 NSString *SOGoWeekStartFirstFullWeek = @"FirstFullWeek";
53
54 @interface NSObject (SOGoRoles)
55
56 - (NSArray *) rolesOfUser: (NSString *) uid;
57
58 @end
59
60 @implementation SoUser (SOGoExtension)
61
62 - (NSString *) language
63 {
64   return [SOGoUser language];
65 }
66
67 @end
68
69 @implementation SOGoUser
70
71 + (void) initialize
72 {
73   NSString *tzName;
74   NSUserDefaults *ud;
75   NSString *profileURL;
76
77   ud = [NSUserDefaults standardUserDefaults];
78   if (!serverTimeZone)
79     {
80       tzName = [ud stringForKey: @"SOGoServerTimeZone"];
81       if (!tzName)
82         tzName = @"UTC";
83       serverTimeZone = [NSTimeZone timeZoneWithName: tzName];
84       [serverTimeZone retain];
85     }
86   if (!AgenorProfileURL)
87     {
88       profileURL = [ud stringForKey: @"AgenorProfileURL"];
89       AgenorProfileURL = [[NSURL alloc] initWithString: profileURL];
90     }
91   if (!fallbackIMAP4Server)
92     ASSIGN (fallbackIMAP4Server,
93             [ud stringForKey: @"SOGoFallbackIMAP4Server"]);
94   if (!defaultLanguage)
95     {
96       ASSIGN (defaultLanguage, [ud stringForKey: @"SOGoDefaultLanguage"]);
97       if (!defaultLanguage)
98         ASSIGN (defaultLanguage, @"English");
99     }
100   if (!superUsernames)
101     ASSIGN (superUsernames, [ud arrayForKey: @"SOGoSuperUsernames"]);
102
103   acceptAnyUser = ([[ud stringForKey: @"SOGoAuthentificationMethod"]
104                      isEqualToString: @"bypass"]);
105 }
106
107 + (NSString *) language
108 {
109   NSArray *bLanguages;
110   WOContext *context;
111   NSString *lng;
112
113   context = [[WOApplication application] context];
114   bLanguages = [[context request] browserLanguages];
115   if ([bLanguages count] > 0)
116     lng = [bLanguages objectAtIndex: 0];
117
118   if (![lng length])
119     lng = defaultLanguage;
120
121   return lng;
122 }
123
124 + (SOGoUser *) userWithLogin: (NSString *) newLogin
125                        roles: (NSArray *) newRoles
126 {
127   SOGoUser *user;
128
129   user = [[self alloc] initWithLogin: newLogin roles: newRoles];
130   [user autorelease];
131
132   return user;
133 }
134
135 - (id) init
136 {
137   if ((self = [super init]))
138     {
139       userDefaults = nil;
140       userSettings = nil;
141       allEmails = nil;
142       language = nil;
143       currentPassword = nil;
144       dateFormatter = nil;
145     }
146
147   return self;
148 }
149
150 - (id) initWithLogin: (NSString *) newLogin
151                roles: (NSArray *) newRoles
152 {
153   LDAPUserManager *um;
154   NSString *realUID;
155
156   if (acceptAnyUser
157       || [newLogin isEqualToString: @"anonymous"]
158       || [newLogin isEqualToString: @"freebusy"])
159     realUID = newLogin;
160   else
161     {
162       um = [LDAPUserManager sharedUserManager];
163       realUID = [[um contactInfosForUserWithUIDorEmail: newLogin]
164                   objectForKey: @"c_uid"];
165     }
166   self = [super initWithLogin: realUID roles: newRoles];
167
168   return self;
169 }
170
171 - (void) dealloc
172 {
173   [currentPassword release];
174   [userDefaults release];
175   [userSettings release];
176   [allEmails release];
177   [language release];
178   [dateFormatter release];
179   [super dealloc];
180 }
181
182 - (void) setCurrentPassword: (NSString *) newPassword
183 {
184   ASSIGN (currentPassword, newPassword);
185 }
186
187 - (NSString *) currentPassword
188 {
189   return currentPassword;
190 }
191
192 - (id) _fetchFieldForUser: (NSString *) field
193 {
194   NSDictionary *contactInfos;
195   LDAPUserManager *um;
196
197   um = [LDAPUserManager sharedUserManager];
198   contactInfos = [um contactInfosForUserWithUIDorEmail: login];
199
200   return [contactInfos objectForKey: field];
201 }
202
203 - (void) _fetchAllEmails
204 {
205   allEmails = [self _fetchFieldForUser: @"emails"];
206   [allEmails retain];
207 }
208
209 - (void) _fetchCN
210 {
211   cn = [self _fetchFieldForUser: @"cn"];
212   [cn retain];
213 }
214
215 /* properties */
216
217 // - (NSString *) fullEmail
218 // {
219 //   return [[LDAPUserManager sharedUserManager] getFullEmailForUID: login];
220 // }
221
222 // - (NSString *) primaryEmail
223 // {
224 //   if (!allEmails)
225 //     [self _fetchAllEmails];
226
227 //   return [allEmails objectAtIndex: 0];
228 // }
229
230 - (NSArray *) allEmails
231 {
232   if (!allEmails)
233     [self _fetchAllEmails];
234
235   return allEmails;  
236 }
237
238 - (NSString *) systemEmail
239 {
240   if (!allEmails)
241     [self _fetchAllEmails];
242
243   return [allEmails lastObject];
244 }
245
246 - (BOOL) hasEmail: (NSString *) email
247 {
248   if (!allEmails)
249     [self _fetchAllEmails];
250   
251   return [allEmails containsCaseInsensitiveString: email];
252 }
253
254 - (NSString *) cn
255 {
256   if (!cn)
257     [self _fetchCN];
258
259   return cn;
260 }
261
262 // - (NSString *) primaryMailServer
263 // {
264 //   return [[self userManager] getServerForUID: [self login]];
265 // }
266
267 // - (NSArray *) additionalIMAP4AccountStrings
268 // {
269 //   return [[self userManager]getSharedMailboxAccountStringsForUID: [self login]];
270 // }
271
272 // - (NSArray *) additionalEMailAddresses
273 // {
274 //   return [[self userManager] getSharedMailboxEMailsForUID: [self login]];
275 // }
276
277 // - (NSDictionary *) additionalIMAP4AccountsAndEMails
278 // {
279 //   return [[self userManager] getSharedMailboxesAndEMailsForUID: [self login]];
280 // }
281
282 - (NSURL *) freeBusyURL
283 {
284   return nil;
285 }
286
287 - (SOGoDateFormatter *) dateFormatterInContext: (WOContext *) context
288 {
289   NSString *format;
290   NSUserDefaults *ud;
291
292   if (!dateFormatter)
293     {
294       dateFormatter = [SOGoDateFormatter new];
295       [dateFormatter setLocale: [context valueForKey: @"locale"]];
296       ud = [self userDefaults];
297       format = [ud stringForKey: @"ShortDateFormat"];
298       if (format)
299         [dateFormatter setShortDateFormat: format];
300       format = [ud stringForKey: @"LongDateFormat"];
301       if (format)
302         [dateFormatter setLongDateFormat: format];
303       format = [ud stringForKey: @"TimeFormat"];
304       if (format)
305         [dateFormatter setTimeFormat: format];
306     }
307
308   return dateFormatter;
309 }
310
311 /* defaults */
312
313 - (NSUserDefaults *) userDefaults
314 {
315   if (!userDefaults)
316     userDefaults
317       = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
318                                     uid: login
319                                     fieldName: @"c_defaults"];
320
321   return userDefaults;
322 }
323
324 - (NSUserDefaults *) userSettings
325 {
326   if (!userSettings)
327     userSettings
328       = [[AgenorUserDefaults alloc] initWithTableURL: AgenorProfileURL
329                                     uid: login
330                                     fieldName: @"c_settings"];
331
332   return userSettings;
333 }
334
335 - (NSString *) language
336 {
337   if (!language)
338     {
339       language = [[self userDefaults] stringForKey: @"Language"];
340       if (![language length])
341         language = [SOGoUser language];
342       [language retain];
343     }
344
345   return language;
346 }
347
348 - (NSTimeZone *) timeZone
349 {
350   NSString *timeZoneName;
351
352   if (!userTimeZone)
353     {
354       timeZoneName = [[self userDefaults] stringForKey: @"TimeZone"];
355       if ([timeZoneName length] > 0)
356         userTimeZone = [NSTimeZone timeZoneWithName: timeZoneName];
357       if (!userTimeZone)
358         userTimeZone = serverTimeZone;
359       [userTimeZone retain];
360     }
361
362   return userTimeZone;
363 }
364
365 - (NSTimeZone *) serverTimeZone
366 {
367   return serverTimeZone;
368 }
369
370 /* mail */
371 - (void) _prepareDefaultMailAccounts
372 {
373   NSMutableDictionary *mailAccount, *identity;
374   NSMutableArray *identities;
375   NSString *name, *fullName;
376   NSArray *mails;
377   unsigned int count, max;
378
379   mailAccount = [NSMutableDictionary dictionary];
380   name = [NSString stringWithFormat: @"%@@%@",
381                    login, fallbackIMAP4Server];
382   [mailAccount setObject: login forKey: @"userName"];
383   [mailAccount setObject: fallbackIMAP4Server forKey: @"serverName"];
384   [mailAccount setObject: name forKey: @"name"];
385
386   identities = [NSMutableArray array];
387   mails = [self allEmails];
388
389   max = [mails count];
390   if (max > 1)
391     max--;
392   for (count = 0; count < max; count++)
393     {
394       identity = [NSMutableDictionary dictionary];
395       fullName = [self cn];
396       if (![fullName length])
397         fullName = login;
398       [identity setObject: fullName forKey: @"fullName"];
399       [identity setObject: [mails objectAtIndex: count] forKey: @"email"];
400       [identities addObject: identity];
401     }
402   [[identities objectAtIndex: 0] setObject: [NSNumber numberWithBool: YES]
403                                  forKey: @"isDefault"];
404
405   [mailAccount setObject: identities forKey: @"identities"];
406
407   mailAccounts = [NSMutableArray new];
408   [mailAccounts addObject: mailAccount];
409 }
410
411 - (NSArray *) mailAccounts
412 {
413   NSUserDefaults *ud;
414
415   if (!mailAccounts)
416     {
417       ud = [self userDefaults];
418       mailAccounts = [ud objectForKey: @"MailAccounts"];
419       if (mailAccounts)
420         [mailAccounts retain];
421       else
422         [self _prepareDefaultMailAccounts];
423     }
424
425   return mailAccounts;
426 }
427
428 /*
429 @interface SOGoMailIdentity : NSObject
430 {
431   NSString *name;
432   NSString *email;
433   NSString *replyTo;
434   NSString *organization;
435   NSString *signature;
436   NSString *vCard;
437   NSString *sentFolderName;
438   NSString *sentBCC;
439   NSString *draftsFolderName;
440   NSString *templatesFolderName;
441   struct
442   {
443     int composeHTML:1;
444     int reserved:31;
445   } idFlags;
446 }
447
448 - (void) setName: (NSString *) _value;
449 - (NSString *) name;
450
451 - (void) setEmail: (NSString *) _value;
452 - (NSString *) email;
453
454 - (void) setReplyTo: (NSString *) _value;
455 - (NSString *) replyTo;
456
457 - (void) setOrganization: (NSString *) _value;
458 - (NSString *) organization;
459
460 - (void) setSignature: (NSString *) _value;
461 - (NSString *) signature;
462 - (BOOL) hasSignature;
463
464 - (void) setVCard: (NSString *) _value;
465 - (NSString *) vCard;
466 - (BOOL) hasVCard;
467
468 - (void) setSentFolderName: (NSString *) _value;
469 - (NSString *) sentFolderName;
470
471 - (void) setSentBCC: (NSString *) _value;
472 - (NSString *) sentBCC;
473
474 - (void) setDraftsFolderName: (NSString *) _value;
475 - (NSString *) draftsFolderName;
476
477 - (void) setTemplatesFolderName: (NSString *) _value;
478 - (NSString *) templatesFolderName;
479
480 @end */
481
482 - (NSArray *) allIdentities
483 {
484   NSArray *identities;
485
486   [self mailAccounts];
487   identities = [mailAccounts objectsForKey: @"identities"];
488
489   return [identities flattenedArray];
490 }
491
492 - (NSDictionary *) primaryIdentity
493 {
494   NSDictionary *defaultAccount;
495
496   [self mailAccounts];
497   defaultAccount = [mailAccounts objectAtIndex: 0];
498
499   return [[defaultAccount objectForKey: @"identities"] objectAtIndex: 0];
500 }
501
502 - (NSString *) messageForwarding
503 {
504   NSString *messageForwarding;
505
506   messageForwarding
507     = [[self userDefaults] stringForKey: @"MessageForwarding"];
508   if (![messageForwarding length])
509     messageForwarding = @"attached";
510
511   return messageForwarding;
512 }
513
514 - (NSString *) messageCheck
515 {
516   NSString *messageCheck;
517
518   messageCheck
519     = [[self userDefaults] stringForKey: @"MessageCheck"];
520   if (![messageCheck length])
521     messageCheck = @"manually";
522
523   return messageCheck;
524 }
525
526 /* folders */
527
528 // TODO: those methods should check whether the traversal stack in the context
529 //       already contains proper folders to improve caching behaviour
530
531 - (id) homeFolderInContext: (id) _ctx
532 {
533   /* Note: watch out for cyclic references */
534   // TODO: maybe we should add an [activeUser reset] method to SOPE
535   id folder;
536   
537   folder = [(WOContext *)_ctx objectForKey:@"ActiveUserHomeFolder"];
538   if (folder != nil)
539     return [folder isNotNull] ? folder : nil;
540   
541   folder = [[WOApplication application] lookupName: [self login]
542                                         inContext: _ctx
543                                         acquire: NO];
544   if ([folder isKindOfClass:[NSException class]])
545     return folder;
546   
547   [(WOContext *)_ctx setObject: ((folder)
548                                  ? folder
549                                  : (id)[NSNull null])
550                 forKey: @"ActiveUserHomeFolder"];
551   return folder;
552 }
553
554 - (SOGoAppointmentFolders *) calendarsFolderInContext: (WOContext *) context
555 {
556   return [[self homeFolderInContext: context] lookupName: @"Calendar"
557                                               inContext: context
558                                               acquire: NO];
559 }
560
561 - (SOGoAppointmentFolder *)
562  personalCalendarFolderInContext: (WOContext *) context
563 {
564   return [[self calendarsFolderInContext: context] lookupName: @"personal"
565                                                    inContext: context
566                                                    acquire: NO];
567 }
568
569 // - (id) schedulingCalendarInContext: (id) _ctx
570 // {
571 //   /* Note: watch out for cyclic references */
572 //   id folder;
573
574 //   folder = [(WOContext *)_ctx objectForKey:@"ActiveUserCalendar"];
575 //   if (folder != nil)
576 //     return [folder isNotNull] ? folder : nil;
577
578 //   folder = [self homeFolderInContext:_ctx];
579 //   if ([folder isKindOfClass:[NSException class]])
580 //     return folder;
581   
582 //   folder = [folder lookupName:@"Calendar" inContext:_ctx acquire:NO];
583 //   if ([folder isKindOfClass:[NSException class]])
584 //     return folder;
585   
586 //   [(WOContext *)_ctx setObject:folder ? folder : [NSNull null] 
587 //                 forKey:@"ActiveUserCalendar"];
588 //   return folder;
589 // }
590
591 - (NSArray *) rolesForObject: (NSObject *) object
592                    inContext: (WOContext *) context
593 {
594   NSMutableArray *rolesForObject;
595   NSArray *sogoRoles;
596
597   rolesForObject = [NSMutableArray new];
598   [rolesForObject autorelease];
599
600   sogoRoles = [super rolesForObject: object inContext: context];
601   if (sogoRoles)
602     [rolesForObject addObjectsFromArray: sogoRoles];
603
604   if ((superUsernames && [superUsernames containsObject: login])
605       || [[object ownerInContext: context] isEqualToString: login])
606     [rolesForObject addObject: SoRole_Owner];
607   if ([object isKindOfClass: [SOGoObject class]])
608     {
609       sogoRoles = [(SOGoObject *) object aclsForUser: login];
610       if (sogoRoles)
611         [rolesForObject addObjectsFromArray: sogoRoles];
612     }
613
614   return rolesForObject;
615 }
616
617 @end /* SOGoUser */