]> err.no Git - scalable-opengroupware.org/blob - Main/SOGo.m
git-svn-id: http://svn.opengroupware.org/SOGo/inverse/trunk@1089 d1b88da0-ebda-0310...
[scalable-opengroupware.org] / Main / SOGo.m
1 /*
2   Copyright (C) 2004-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 #include <NGObjWeb/SoApplication.h>
23
24 @interface SOGo : SoApplication
25 {
26     NSMutableDictionary *localeLUT;
27 }
28
29 - (NSDictionary *) currentLocaleConsideringLanguages:(NSArray *)_langs;
30 - (NSDictionary *) localeForLanguageNamed:(NSString *)_name;
31
32 @end
33
34 #include "SOGoProductLoader.h"
35 #include <WEExtensions/WEResourceManager.h>
36 #include <SOGo/SOGoAuthenticator.h>
37 #include <SOGo/SOGoUserFolder.h>
38 #include <SOGo/SOGoPermissions.h>
39 #include "common.h"
40
41 @implementation SOGo
42
43 static unsigned int vMemSizeLimit = 0;
44 static BOOL doCrashOnSessionCreate = NO;
45
46 #ifdef GNUSTEP_BASE_LIBRARY
47 static BOOL debugObjectAllocation = NO;
48 #endif
49
50 + (void) initialize
51 {
52   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
53   SoClassSecurityInfo *sInfo;
54   NSArray *basicRoles;
55   id tmp;
56   
57   doCrashOnSessionCreate = [ud boolForKey:@"SOGoCrashOnSessionCreate"];
58 #ifdef GNUSTEP_BASE_LIBRARY
59   debugObjectAllocation = [ud boolForKey: @"SOGoDebugObjectAllocation"];
60   if (debugObjectAllocation)
61     {
62       NSLog (@"activating stats on object allocation");
63       GSDebugAllocationActive (YES);
64     }
65 #endif
66
67   /* vMem size check - default is 200MB */
68     
69   tmp = [ud objectForKey: @"SxVMemLimit"];
70   vMemSizeLimit = ((tmp != nil) ? [tmp intValue] : 200);
71   if (vMemSizeLimit > 0)
72     NSLog(@"Note: vmem size check enabled: shutting down app when "
73           @"vmem > %d MB", vMemSizeLimit);
74 #if LIB_FOUNDATION_LIBRARY
75   if ([ud boolForKey:@"SOGoEnableDoubleReleaseCheck"])
76     [NSAutoreleasePool enableDoubleReleaseCheck: YES];
77 #endif
78
79   /* SoClass security declarations */
80   sInfo = [self soClassSecurityInfo];
81   /* require View permission to access the root (bound to authenticated ...) */
82   [sInfo declareObjectProtected: SoPerm_View];
83
84   /* to allow public access to all contained objects (subkeys) */
85   [sInfo setDefaultAccess: @"allow"];
86
87   basicRoles = [NSArray arrayWithObjects: SoRole_Authenticated,
88                         SOGoRole_FreeBusy, nil];
89
90   /* require Authenticated role for View and WebDAV */
91   [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View];
92   [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess];
93 }
94
95 - (id) init
96 {
97   if ((self = [super init]))
98     {
99       WOResourceManager *rm;
100
101       /* ensure core SoClass'es are setup */
102       [$(@"SOGoObject") soClass];
103       [$(@"SOGoContentObject") soClass];
104       [$(@"SOGoFolder") soClass];
105
106       /* setup locale cache */
107       localeLUT = [[NSMutableDictionary alloc] initWithCapacity:2];
108     
109       /* load products */
110       [[SOGoProductLoader productLoader] loadProducts];
111     
112       /* setup resource manager */
113       rm = [[WEResourceManager alloc] init];
114       [self setResourceManager:rm];
115     }
116
117   return self;
118 }
119
120 - (void) dealloc
121 {
122   [localeLUT release];
123   [super dealloc];
124 }
125
126 /* authenticator */
127
128 - (id) authenticatorInContext: (id) _ctx
129 {
130   return [$(@"SOGoAuthenticator") sharedSOGoAuthenticator];
131 }
132
133 /* name lookup */
134
135 - (BOOL) isUserName: (NSString *) _key
136           inContext: (id) _ctx
137 {
138   if ([_key length] < 1)
139     return NO;
140   
141   if (isdigit([_key characterAtIndex:0]))
142     return NO;
143
144   return YES;
145 }
146
147 - (id)lookupUser:(NSString *)_key inContext:(id)_ctx {
148   return [[[$(@"SOGoUserFolder") alloc] 
149             initWithName:_key inContainer:self] autorelease];
150 }
151
152 - (void) _setupLocaleInContext: (WOContext *) _ctx
153 {
154   NSArray      *langs;
155   NSDictionary *locale;
156   
157   if ([[_ctx valueForKey:@"locale"] isNotNull])
158     return;
159
160   langs = [[_ctx request] browserLanguages];
161   locale = [self currentLocaleConsideringLanguages:langs];
162   [_ctx takeValue:locale forKey:@"locale"];
163 }
164
165 - (id) lookupName: (NSString *) _key
166         inContext: (id) _ctx
167           acquire: (BOOL) _flag
168 {
169   id obj;
170
171 #ifdef GNUSTEP_BASE_LIBRARY
172   if (debugObjectAllocation)
173     NSLog(@"objects allocated\n%s", GSDebugAllocationList (YES));
174 #endif
175   /* put locale info into the context in case it's not there */
176   [self _setupLocaleInContext:_ctx];
177   
178   /* first check attributes directly bound to the application */
179   if ((obj = [super lookupName:_key inContext:_ctx acquire:_flag]))
180     return obj;
181   
182   /* 
183      The problem is, that at this point we still get request for resources,
184      eg 'favicon.ico'.
185      
186      Addition: we also get queries for various other methods, like "GET" if
187                no method was provided in the query path.
188   */
189   
190   if ([_key isEqualToString:@"favicon.ico"])
191     return nil;
192
193   if ([self isUserName:_key inContext:_ctx])
194     return [self lookupUser:_key inContext:_ctx];
195   
196   return nil;
197 }
198
199 /* WebDAV */
200
201 - (NSString *) davDisplayName
202 {
203   /* this is used in the UI, eg in the navigation */
204   return @"SOGo";
205 }
206
207 /* exception handling */
208
209 - (WOResponse *) handleException: (NSException *) _exc
210                        inContext: (WOContext *) _ctx
211 {
212   printf("EXCEPTION: %s\n", [[_exc description] cString]);
213   abort();
214 }
215
216 /* runtime maintenance */
217
218 - (void) checkIfDaemonHasToBeShutdown
219 {
220   unsigned int vmem;
221
222   if (vMemSizeLimit > 0)
223     {
224       vmem = [[NSProcessInfo processInfo] virtualMemorySize]/1048576;
225
226       if (vmem > vMemSizeLimit)
227         {
228           [self logWithFormat:
229                   @"terminating app, vMem size limit (%d MB) has been reached"
230                 @" (currently %d MB)",
231                 vMemSizeLimit, vmem];
232 //           if (debugObjectAllocation)
233 //             [self _dumpClassAllocation];
234           [self terminate];
235         }
236     }
237 }
238
239 - (WOResponse *) dispatchRequest: (WORequest *) _request
240 {
241   static NSArray *runLoopModes = nil;
242   WOResponse *resp;
243
244   resp = [super dispatchRequest: _request];
245
246   if (![self isTerminating])
247     {
248       if (!runLoopModes)
249         runLoopModes = [[NSArray alloc] initWithObjects: NSDefaultRunLoopMode, nil];
250   
251       // TODO: a bit complicated? (-perform:afterDelay: doesn't work?)
252       [[NSRunLoop currentRunLoop] performSelector:
253                                     @selector (checkIfDaemonHasToBeShutdown)
254                                   target: self argument: nil
255                                   order:1 modes:runLoopModes];
256     }
257
258   return resp;
259 }
260
261 /* session management */
262
263 - (id) createSessionForRequest: (WORequest *) _request
264 {
265   [self warnWithFormat: @"session creation requested!"];
266   if (doCrashOnSessionCreate)
267     abort();
268   return [super createSessionForRequest:_request];
269 }
270
271 /* localization */
272
273 - (NSDictionary *) currentLocaleConsideringLanguages: (NSArray *) langs
274 {
275   NSEnumerator *enumerator;
276   NSString *lname;
277   NSDictionary *locale;
278
279   enumerator = [langs objectEnumerator];
280   lname = nil;
281   locale = nil;
282   lname = [enumerator nextObject];
283   while (lname && !locale)
284     {
285       locale = [self localeForLanguageNamed: lname];
286       lname = [enumerator nextObject];
287     }
288
289   if (!locale)
290     locale = [self localeForLanguageNamed: @"English"];
291
292   /* no appropriate language, fallback to default */
293   return locale;
294 }
295
296 - (NSString *) pathToLocaleForLanguageNamed: (NSString *) _name
297 {
298   static Class MainProduct = Nil;
299   NSString *lpath;
300
301   lpath = [[self resourceManager] pathForResourceNamed: @"Locale"
302                                   inFramework: nil
303                                   languages: [NSArray arrayWithObject:_name]];
304   if (![lpath length])
305     {
306       if (!MainProduct)
307         {
308           MainProduct = $(@"MainUIProduct");
309           if (!MainProduct)
310             [self errorWithFormat: @"did not find MainUIProduct class!"];
311         }
312
313       lpath = [(id) MainProduct pathToLocaleForLanguageNamed: _name];
314       if (![lpath length])
315         lpath = nil;
316     }
317
318   return lpath;
319 }
320
321 - (NSDictionary *) localeForLanguageNamed: (NSString *) _name
322 {
323   NSString     *lpath;
324   id           data;
325   NSDictionary *locale;
326
327   locale = nil;
328   if ([_name length] > 0)
329     {
330       locale = [localeLUT objectForKey: _name];
331       if (!locale)
332         {
333           lpath = [self pathToLocaleForLanguageNamed:_name];
334           if (lpath)
335             {
336               data = [NSData dataWithContentsOfFile: lpath];
337               if (data)
338                 {
339                   data = [[[NSString alloc] initWithData: data
340                                             encoding: NSUTF8StringEncoding] autorelease];
341                   locale = [data propertyList];
342                   if (locale) 
343                     [localeLUT setObject: locale forKey: _name];
344                   else
345                     [self logWithFormat:@"%s couldn't load locale with name:%@",
346                           __PRETTY_FUNCTION__,
347                           _name];
348                 }
349               else
350                 [self logWithFormat:@"%s didn't find locale with name: %@",
351                       __PRETTY_FUNCTION__,
352                       _name];
353             }
354           else
355             [self errorWithFormat:@"did not find Locale for language: %@", _name];
356         }
357     }
358   else
359     [self errorWithFormat:@"%s: name parameter must not be nil!",
360           __PRETTY_FUNCTION__];
361
362   return locale;
363 }
364
365 /* name (used by the WEResourceManager) */
366
367 - (NSString *) name
368 {
369   return @"SOGo-0.9";
370 }
371
372 @end /* SOGo */