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