2 Copyright (C) 2004-2005 SKYRIX Software AG
4 This file is part of OpenGroupware.org.
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
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.
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
22 #import <Foundation/NSDebug.h>
23 #import <Foundation/NSData.h>
24 #import <Foundation/NSProcessInfo.h>
25 #import <Foundation/NSRunLoop.h>
26 #import <Foundation/NSURL.h>
27 #import <Foundation/NSUserDefaults.h>
29 #import <GDLAccess/EOAdaptorChannel.h>
30 #import <GDLContentStore/GCSChannelManager.h>
32 #import <NGObjWeb/SoApplication.h>
33 #import <NGObjWeb/SoClassSecurityInfo.h>
34 #import <NGObjWeb/WOContext.h>
35 #import <NGObjWeb/WORequest.h>
37 #import <NGExtensions/NGBundleManager.h>
38 #import <NGExtensions/NSNull+misc.h>
39 #import <NGExtensions/NSObject+Logs.h>
40 #import <NGExtensions/NSProcessInfo+misc.h>
42 #import <WEExtensions/WEResourceManager.h>
44 #import <SoObjects/SOGo/SOGoAuthenticator.h>
45 #import <SoObjects/SOGo/SOGoUserFolder.h>
46 #import <SoObjects/SOGo/SOGoUser.h>
47 #import <SoObjects/SOGo/SOGoPermissions.h>
50 #import "SOGoProductLoader.h"
52 @interface SOGo : SoApplication
54 NSMutableDictionary *localeLUT;
57 - (NSDictionary *) currentLocaleConsideringLanguages:(NSArray *)_langs;
58 - (NSDictionary *) localeForLanguageNamed:(NSString *)_name;
64 static unsigned int vMemSizeLimit = 0;
65 static BOOL doCrashOnSessionCreate = NO;
66 static BOOL hasCheckedTables = NO;
68 #ifdef GNUSTEP_BASE_LIBRARY
69 static BOOL debugObjectAllocation = NO;
74 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
75 SoClassSecurityInfo *sInfo;
79 NSLog (@"starting SOGo (build %@)", SOGoBuildDate);
81 doCrashOnSessionCreate = [ud boolForKey:@"SOGoCrashOnSessionCreate"];
82 #ifdef GNUSTEP_BASE_LIBRARY
83 debugObjectAllocation = [ud boolForKey: @"SOGoDebugObjectAllocation"];
84 if (debugObjectAllocation)
86 NSLog (@"activating stats on object allocation");
87 GSDebugAllocationActive (YES);
91 /* vMem size check - default is 200MB */
93 tmp = [ud objectForKey: @"SxVMemLimit"];
94 vMemSizeLimit = ((tmp != nil) ? [tmp intValue] : 200);
95 if (vMemSizeLimit > 0)
96 NSLog(@"Note: vmem size check enabled: shutting down app when "
97 @"vmem > %d MB", vMemSizeLimit);
98 #if LIB_FOUNDATION_LIBRARY
99 if ([ud boolForKey:@"SOGoEnableDoubleReleaseCheck"])
100 [NSAutoreleasePool enableDoubleReleaseCheck: YES];
103 /* SoClass security declarations */
104 sInfo = [self soClassSecurityInfo];
105 /* require View permission to access the root (bound to authenticated ...) */
106 [sInfo declareObjectProtected: SoPerm_View];
108 /* to allow public access to all contained objects (subkeys) */
109 [sInfo setDefaultAccess: @"allow"];
111 basicRoles = [NSArray arrayWithObjects: SoRole_Authenticated,
112 SOGoRole_FreeBusy, nil];
114 /* require Authenticated role for View and WebDAV */
115 [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View];
116 [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess];
121 if ((self = [super init]))
123 WOResourceManager *rm;
125 /* ensure core SoClass'es are setup */
126 [$(@"SOGoObject") soClass];
127 [$(@"SOGoContentObject") soClass];
128 [$(@"SOGoFolder") soClass];
130 /* setup locale cache */
131 localeLUT = [[NSMutableDictionary alloc] initWithCapacity:2];
134 [[SOGoProductLoader productLoader] loadProducts];
136 /* setup resource manager */
137 rm = [[WEResourceManager alloc] init];
138 [self setResourceManager:rm];
150 - (void) _checkTableWithCM: (GCSChannelManager *) cm
151 tableURL: (NSString *) url
152 andType: (NSString *) tableType
154 NSString *tableName, *descFile;
155 EOAdaptorChannel *tc;
160 bm = [NGBundleManager defaultBundleManager];
162 tc = [cm acquireOpenChannelForURL: [NSURL URLWithString: url]];
164 tableName = [url lastPathComponent];
165 if ([tc evaluateExpressionX:
166 [NSString stringWithFormat: @"SELECT count(*) FROM %@", tableName]])
168 bundle = [bm bundleWithName: @"MainUI" type: @"SOGo"];
169 length = [tableType length] - 3;
170 descFile = [bundle pathForResource: [tableType substringToIndex: length]
172 if (![tc evaluateExpressionX:
173 [NSString stringWithContentsOfFile: descFile]])
174 [self logWithFormat: @"table '%@' successfully created!", tableName];
179 [cm releaseChannel: tc];
182 - (BOOL) _checkMandatoryTables
184 GCSChannelManager *cm;
185 NSString *urlStrings[] = {@"AgenorProfileURL", @"OCSFolderInfoURL", nil};
186 NSString **urlString;
191 ud = [NSUserDefaults standardUserDefaults];
193 cm = [GCSChannelManager defaultChannelManager];
195 urlString = urlStrings;
196 while (ok && *urlString)
198 value = [ud stringForKey: *urlString];
201 [self _checkTableWithCM: cm tableURL: value andType: *urlString];
206 NSLog (@"No value specified for '%@'", *urlString);
216 if (!hasCheckedTables)
218 hasCheckedTables = YES;
219 [self _checkMandatoryTables];
226 - (id) authenticatorInContext: (id) _ctx
228 return [$(@"SOGoAuthenticator") sharedSOGoAuthenticator];
233 - (BOOL) isUserName: (NSString *) _key
236 if ([_key length] < 1)
239 if (isdigit([_key characterAtIndex:0]))
245 - (id) lookupUser: (NSString *) _key
251 user = [SOGoUser userWithLogin: _key roles: nil];
253 userFolder = [$(@"SOGoUserFolder") objectWithName: _key
261 - (void) _setupLocaleInContext: (WOContext *) _ctx
264 NSDictionary *locale;
266 if ([[_ctx valueForKey:@"locale"] isNotNull])
269 langs = [[_ctx request] browserLanguages];
270 locale = [self currentLocaleConsideringLanguages:langs];
271 [_ctx takeValue:locale forKey:@"locale"];
274 - (id) lookupName: (NSString *) _key
276 acquire: (BOOL) _flag
280 #ifdef GNUSTEP_BASE_LIBRARY
281 if (debugObjectAllocation)
282 NSLog(@"objects allocated\n%s", GSDebugAllocationList (YES));
284 /* put locale info into the context in case it's not there */
285 [self _setupLocaleInContext:_ctx];
287 /* first check attributes directly bound to the application */
288 if ((obj = [super lookupName:_key inContext:_ctx acquire:_flag]))
292 The problem is, that at this point we still get request for resources,
295 Addition: we also get queries for various other methods, like "GET" if
296 no method was provided in the query path.
299 if ([_key isEqualToString:@"favicon.ico"])
302 if ([self isUserName:_key inContext:_ctx])
303 return [self lookupUser:_key inContext:_ctx];
310 - (NSString *) davDisplayName
312 /* this is used in the UI, eg in the navigation */
316 /* exception handling */
318 - (WOResponse *) handleException: (NSException *) _exc
319 inContext: (WOContext *) _ctx
321 printf("EXCEPTION: %s\n", [[_exc description] cString]);
325 /* runtime maintenance */
327 - (void) checkIfDaemonHasToBeShutdown
331 if (vMemSizeLimit > 0)
333 vmem = [[NSProcessInfo processInfo] virtualMemorySize]/1048576;
335 if (vmem > vMemSizeLimit)
338 @"terminating app, vMem size limit (%d MB) has been reached"
339 @" (currently %d MB)",
340 vMemSizeLimit, vmem];
341 // if (debugObjectAllocation)
342 // [self _dumpClassAllocation];
348 - (WOResponse *) dispatchRequest: (WORequest *) _request
350 static NSArray *runLoopModes = nil;
353 resp = [super dispatchRequest: _request];
355 if (![self isTerminating])
358 runLoopModes = [[NSArray alloc] initWithObjects: NSDefaultRunLoopMode, nil];
360 // TODO: a bit complicated? (-perform:afterDelay: doesn't work?)
361 [[NSRunLoop currentRunLoop] performSelector:
362 @selector (checkIfDaemonHasToBeShutdown)
363 target: self argument: nil
364 order:1 modes:runLoopModes];
370 /* session management */
372 - (id) createSessionForRequest: (WORequest *) _request
374 [self warnWithFormat: @"session creation requested!"];
375 if (doCrashOnSessionCreate)
377 return [super createSessionForRequest:_request];
382 - (NSDictionary *) currentLocaleConsideringLanguages: (NSArray *) langs
384 NSEnumerator *enumerator;
386 NSDictionary *locale;
388 enumerator = [langs objectEnumerator];
391 lname = [enumerator nextObject];
392 while (lname && !locale)
394 locale = [self localeForLanguageNamed: lname];
395 lname = [enumerator nextObject];
399 locale = [self localeForLanguageNamed: @"English"];
401 /* no appropriate language, fallback to default */
405 - (NSString *) pathToLocaleForLanguageNamed: (NSString *) _name
407 static Class MainProduct = Nil;
410 lpath = [[self resourceManager] pathForResourceNamed: @"Locale"
412 languages: [NSArray arrayWithObject:_name]];
417 MainProduct = $(@"MainUIProduct");
419 [self errorWithFormat: @"did not find MainUIProduct class!"];
422 lpath = [(id) MainProduct pathToLocaleForLanguageNamed: _name];
430 - (NSDictionary *) localeForLanguageNamed: (NSString *) _name
434 NSDictionary *locale;
437 if ([_name length] > 0)
439 locale = [localeLUT objectForKey: _name];
442 lpath = [self pathToLocaleForLanguageNamed:_name];
445 data = [NSData dataWithContentsOfFile: lpath];
448 data = [[[NSString alloc] initWithData: data
449 encoding: NSUTF8StringEncoding] autorelease];
450 locale = [data propertyList];
452 [localeLUT setObject: locale forKey: _name];
454 [self logWithFormat:@"%s couldn't load locale with name:%@",
459 [self logWithFormat:@"%s didn't find locale with name: %@",
464 [self errorWithFormat:@"did not find Locale for language: %@", _name];
468 [self errorWithFormat:@"%s: name parameter must not be nil!",
469 __PRETTY_FUNCTION__];
474 /* name (used by the WEResourceManager) */