]> err.no Git - scalable-opengroupware.org/blob - SOGo/Main/sogod.m
8088e2dc2c0d85a916e40ada471669777204cf0a
[scalable-opengroupware.org] / SOGo / Main / sogod.m
1 /*
2   Copyright (C) 2004 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 // $Id$
22
23 #include <NGObjWeb/SoApplication.h>
24
25 @interface SOGo : SoApplication
26 {
27     NSMutableDictionary *localeLUT;
28 }
29
30 - (NSDictionary *)currentLocaleConsideringLanguages:(NSArray *)_langs;
31 - (NSDictionary *)localeForLanguageNamed:(NSString *)_name;
32
33 @end
34
35 #include "SOGoAuthenticator.h"
36 #include "SOGoProductLoader.h"
37 #include <SOGo/SOGoUserFolder.h>
38 #include "common.h"
39
40 @implementation SOGo
41
42 static unsigned int vMemSizeLimit = 0;
43 static BOOL doCrashOnSessionCreate = NO;
44
45 + (void)initialize {
46   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
47   id tmp;
48   
49   doCrashOnSessionCreate = [ud boolForKey:@"SOGoCrashOnSessionCreate"];
50
51   /* vMem size check - default is 200MB */
52     
53   tmp = [ud objectForKey:@"SxVMemLimit"];
54   vMemSizeLimit = (tmp != nil)
55     ? [tmp intValue]
56     : 200;
57   if (vMemSizeLimit > 0) {
58     NSLog(@"Note: vmem size check enabled: shutting down app when "
59           @"vmem > %d MB", vMemSizeLimit);
60   }
61 }
62
63 - (id)init {
64   if ((self = [super init])) {
65     self->localeLUT = [[NSMutableDictionary alloc] initWithCapacity:2];
66     [[SOGoProductLoader productLoader] loadProducts];
67
68 #if 0 /* enable, if we added the value class */
69     /* setup some WebDAV type mappings required for Evolution */
70     [EOQualifier registerValueClass:NSClassFromString(@"dateTime")
71                  forTypeName:@"dateTime"];
72     [EOQualifier registerValueClass:NSClassFromString(@"dateTime")
73                  forTypeName:@"dateTime.tz"];
74 #endif
75     
76   }
77   return self;
78 }
79
80 - (void)dealloc {
81   [self->localeLUT release];
82   [super dealloc];
83 }
84
85 /* authenticator */
86
87 - (id)authenticatorInContext:(WOContext *)_ctx {
88   return [SOGoAuthenticator sharedSOGoAuthenticator];
89 }
90
91 /* name lookup */
92
93 - (BOOL)isUserName:(NSString *)_key inContext:(id)_ctx {
94   if ([_key length] < 1)
95     return NO;
96
97   if (isdigit([_key characterAtIndex:0]))
98     return NO;
99
100   return YES;
101 }
102
103 - (id)lookupUser:(NSString *)_key inContext:(id)_ctx {
104   return [[[SOGoUserFolder alloc] initWithName:_key inContainer:self]
105                            autorelease];
106 }
107
108 - (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
109   id obj;
110
111   /* put locale info into the context in case it's not there */
112   if (![_ctx valueForKey:@"locale"]) {
113       NSArray *langs;
114       NSDictionary *locale;
115       
116       langs = [[(WOContext *)_ctx request] browserLanguages];
117       locale = [self currentLocaleConsideringLanguages:langs];
118       [_ctx takeValue:locale forKey:@"locale"];
119   }
120   
121 #if 0 // znek: explain why you did that?
122   /* set SoRootURL */
123   if ([_ctx valueForKey:@"SoRootURL"] == nil) {
124       [_ctx takeValue:@"/sogod.woa/so/" forKey:@"SoRootURL"];
125   }
126 #endif
127   
128   /* first check attributes directly bound to the application */
129   if ((obj = [super lookupName:_key inContext:_ctx acquire:_flag]))
130     return obj;
131   
132   /* 
133      The problem is, that at this point we still get request for resources,
134      eg 'favicon.ico'.
135      The hack here is to check for a dot in the key, but we should find a way
136      to catch that in a more sensible way.
137      
138      One way to check for a valid key would be to check whether the key is a
139      valid hostname, but I would like to avoid that for performance reasons.
140      
141      Addition: we also get queries for various other methods, like "GET" if
142                no method was provided in the query path.
143   */
144   if ([self isUserName:_key inContext:_ctx])
145     return [self lookupUser:_key inContext:_ctx];
146   
147   return nil;
148 }
149
150 /* WebDAV */
151
152 - (NSString *)davDisplayName {
153   /* this is used in the UI, eg in the navigation */
154   return @"SOGo";
155 }
156
157 /* exception handling */
158
159 - (WOResponse *)handleException:(NSException *)_exc
160   inContext:(WOContext *)_ctx
161 {
162   printf("EXCEPTION: %s\n", [[_exc description] cString]);
163   abort();
164 }
165
166 /* runtime maintenance */
167
168 - (void)checkIfDaemonHasToBeShutdown {
169   unsigned int limit, vmem;
170   
171   if ((limit = vMemSizeLimit) == 0)
172     return;
173
174   vmem = [[NSProcessInfo processInfo] virtualMemorySize]/1048576;
175
176   if (vmem > limit) {
177     [self logWithFormat:
178           @"terminating app, vMem size limit (%d MB) has been reached"
179           @" (currently %d MB)",
180           limit, vmem];
181     [self terminate];
182   }
183 }
184
185 - (WOResponse *)dispatchRequest:(WORequest *)_request {
186   static NSArray *runLoopModes = nil;
187   WOResponse *resp;
188
189   resp = [super dispatchRequest:_request];
190
191   if ([self isTerminating])
192     return resp;
193
194   if (runLoopModes == nil)
195     runLoopModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, nil];
196   
197   // TODO: a bit complicated? (-perform:afterDelay: doesn't work?)
198   [[NSRunLoop currentRunLoop] performSelector:
199                                 @selector(checkIfDaemonHasToBeShutdown)
200                               target:self argument:nil
201                               order:1 modes:runLoopModes];
202   return resp;
203 }
204
205 /* session management */
206
207 - (WOSession *)createSessionForRequest:(WORequest *)_request {
208   [self logWithFormat:@"WARNING: session creation requested!"];
209   if (doCrashOnSessionCreate)
210     abort();
211   return [super createSessionForRequest:_request];
212 }
213
214 /* localization */
215
216 - (NSDictionary *)currentLocaleConsideringLanguages:(NSArray *)_langs {
217   unsigned i, count;
218
219   /* assume _langs is ordered by priority */
220   count = [_langs count];
221   for (i = 0; i < count; i++) {
222     NSString     *lname;
223     NSDictionary *locale;
224     
225     lname  = [_langs objectAtIndex:i];
226     locale = [self localeForLanguageNamed:lname];
227     if (locale)
228       return locale;
229   }
230   /* no appropriate language, fallback to default */
231   return [self localeForLanguageNamed:@"English"];
232 }
233
234 - (NSDictionary *)localeForLanguageNamed:(NSString *)_name {
235   NSString *lpath;
236   id data;
237   NSDictionary *locale;
238
239   NSAssert(_name != nil, @"_name MUST NOT be nil!");
240   if((locale = [self->localeLUT objectForKey:_name]) != nil)
241     return locale;
242   lpath = [[self resourceManager]
243     pathForResourceNamed:@"Locale"
244     inFramework:nil
245     languages:[NSArray arrayWithObject:_name]];
246
247   data = [NSData dataWithContentsOfFile:lpath];
248   if(data == nil) {
249     NSLog(@"%s didn't find locale with name:%@",
250       __PRETTY_FUNCTION__,
251       _name);
252     return nil;
253   }
254   data = [[[NSString alloc] initWithData:data
255                             encoding:NSUTF8StringEncoding] autorelease];
256   locale = [data propertyList];
257   if(locale == nil) {
258     NSLog(@"%s couldn't load locale with name:%@",
259       __PRETTY_FUNCTION__,
260       _name);
261     return nil;
262   }
263   [self->localeLUT setObject:locale forKey:_name];
264   return locale;
265 }
266
267 @end /* SOGo */
268
269
270 int main(int argc, char **argv, char **env) {
271   NSAutoreleasePool *pool;
272
273   pool = [[NSAutoreleasePool alloc] init];
274 #if LIB_FOUNDATION_LIBRARY
275   [NSProcessInfo initializeWithArguments:argv count:argc environment:env];
276 #endif
277   [NGBundleManager defaultBundleManager];
278   
279   WOWatchDogApplicationMain(@"SOGo", argc, (void*)argv);
280
281   [pool release];
282   return 0;
283 }