]> err.no Git - scalable-opengroupware.org/blob - Main/SOGo.m
moved SOGo files up
[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 <SOGo/SOGoAuthenticator.h>
36 #include <WEExtensions/WEResourceManager.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 #if LIB_FOUNDATION_LIBRARY
62   if ([ud boolForKey:@"SOGoEnableDoubleReleaseCheck"])
63     [NSAutoreleasePool enableDoubleReleaseCheck:YES];
64 #endif
65 }
66
67 - (id)init {
68   if ((self = [super init])) {
69     WOResourceManager *rm;
70     
71     self->localeLUT = [[NSMutableDictionary alloc] initWithCapacity:2];
72     [[SOGoProductLoader productLoader] loadProducts];
73     
74     rm = [[WEResourceManager alloc] init];
75     [self setResourceManager:rm];
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 [[[NSClassFromString(@"SOGoUserFolder") alloc] 
105             initWithName:_key inContainer:self] autorelease];
106 }
107
108 - (void)_setupLocaleInContext:(WOContext *)_ctx {
109   NSArray      *langs;
110   NSDictionary *locale;
111   
112   if ([[_ctx valueForKey:@"locale"] isNotNull])
113     return;
114
115   langs = [[(WOContext *)_ctx request] browserLanguages];
116   locale = [self currentLocaleConsideringLanguages:langs];
117   [_ctx takeValue:locale forKey:@"locale"];
118 }
119
120 - (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
121   id obj;
122
123   /* put locale info into the context in case it's not there */
124   [self _setupLocaleInContext:_ctx];
125   
126   /* first check attributes directly bound to the application */
127   if ((obj = [super lookupName:_key inContext:_ctx acquire:_flag]))
128     return obj;
129   
130   /* 
131      The problem is, that at this point we still get request for resources,
132      eg 'favicon.ico'.
133      
134      Addition: we also get queries for various other methods, like "GET" if
135                no method was provided in the query path.
136   */
137   
138   if ([_key isEqualToString:@"favicon.ico"])
139     return nil;
140
141   if ([self isUserName:_key inContext:_ctx])
142     return [self lookupUser:_key inContext:_ctx];
143   
144   return nil;
145 }
146
147 /* WebDAV */
148
149 - (NSString *)davDisplayName {
150   /* this is used in the UI, eg in the navigation */
151   return @"SOGo";
152 }
153
154 /* exception handling */
155
156 - (WOResponse *)handleException:(NSException *)_exc
157   inContext:(WOContext *)_ctx
158 {
159   printf("EXCEPTION: %s\n", [[_exc description] cString]);
160   abort();
161 }
162
163 /* runtime maintenance */
164
165 - (void)checkIfDaemonHasToBeShutdown {
166   unsigned int limit, vmem;
167   
168   if ((limit = vMemSizeLimit) == 0)
169     return;
170
171   vmem = [[NSProcessInfo processInfo] virtualMemorySize]/1048576;
172
173   if (vmem > limit) {
174     [self logWithFormat:
175           @"terminating app, vMem size limit (%d MB) has been reached"
176           @" (currently %d MB)",
177           limit, vmem];
178     [self terminate];
179   }
180 }
181
182 - (WOResponse *)dispatchRequest:(WORequest *)_request {
183   static NSArray *runLoopModes = nil;
184   WOResponse *resp;
185
186   resp = [super dispatchRequest:_request];
187
188   if ([self isTerminating])
189     return resp;
190
191   if (runLoopModes == nil)
192     runLoopModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, nil];
193   
194   // TODO: a bit complicated? (-perform:afterDelay: doesn't work?)
195   [[NSRunLoop currentRunLoop] performSelector:
196                                 @selector(checkIfDaemonHasToBeShutdown)
197                               target:self argument:nil
198                               order:1 modes:runLoopModes];
199   return resp;
200 }
201
202 /* session management */
203
204 - (WOSession *)createSessionForRequest:(WORequest *)_request {
205   [self warnWithFormat:@"session creation requested!"];
206   if (doCrashOnSessionCreate)
207     abort();
208   return [super createSessionForRequest:_request];
209 }
210
211 /* localization */
212
213 - (NSDictionary *)currentLocaleConsideringLanguages:(NSArray *)_langs {
214   unsigned i, count;
215
216   /* assume _langs is ordered by priority */
217   count = [_langs count];
218   for (i = 0; i < count; i++) {
219     NSString     *lname;
220     NSDictionary *locale;
221     
222     lname  = [_langs objectAtIndex:i];
223     locale = [self localeForLanguageNamed:lname];
224     if (locale != nil)
225       return locale;
226   }
227   /* no appropriate language, fallback to default */
228   return [self localeForLanguageNamed:@"English"];
229 }
230
231 - (NSString *)pathToLocaleForLanguageNamed:(NSString *)_name {
232   static Class MainProduct = Nil;
233   NSString *lpath;
234
235   lpath = [[self resourceManager] pathForResourceNamed:@"Locale"
236                                   inFramework:nil
237                                   languages:[NSArray arrayWithObject:_name]];
238   if ([lpath isNotNull])
239     return lpath;
240   
241   if (MainProduct == Nil) {
242     if ((MainProduct = NSClassFromString(@"MainUIProduct")) == Nil)
243       [self errorWithFormat:@"did not find MainUIProduct class!"];
244   }
245   
246   lpath = [(id)MainProduct pathToLocaleForLanguageNamed:_name];
247   if ([lpath isNotNull])
248     return lpath;
249   
250   return nil;
251 }
252
253 - (NSDictionary *)localeForLanguageNamed:(NSString *)_name {
254   NSString     *lpath;
255   id           data;
256   NSDictionary *locale;
257   
258   if (![_name isNotNull]) {
259     [self errorWithFormat:@"%s: name parameter must not be nil!",
260           __PRETTY_FUNCTION__];
261     return nil;
262   }
263   
264   if ((locale = [self->localeLUT objectForKey:_name]) != nil)
265     return locale;
266   
267   if ((lpath = [self pathToLocaleForLanguageNamed:_name]) == nil) {
268     [self errorWithFormat:@"did not find Locale for language: %@", _name];
269     return nil;
270   }
271   
272   if ((data = [NSData dataWithContentsOfFile:lpath]) == nil) {
273     [self logWithFormat:@"%s didn't find locale with name:%@",
274           __PRETTY_FUNCTION__,
275           _name];
276     return nil;
277   }
278   data = [[[NSString alloc] initWithData:data
279                             encoding:NSUTF8StringEncoding] autorelease];
280   locale = [data propertyList];
281   if (locale == nil) {
282     [self logWithFormat:@"%s couldn't load locale with name:%@",
283           __PRETTY_FUNCTION__,
284           _name];
285     return nil;
286   }
287   [self->localeLUT setObject:locale forKey:_name];
288   return locale;
289 }
290
291 /* name (used by the WEResourceManager) */
292
293 - (NSString *)name {
294   return @"SOGo-0.9";
295 }
296
297 @end /* SOGo */