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 #include <NGObjWeb/SoApplication.h>
24 // @interface classtree : NSObject
30 // - (id) initWithTopClass: (Class) newTopClass;
31 // - (void) dumpSiblings: (Class) node;
35 // @implementation classtree
37 // + (id) newWithTopClass: (Class) newTopClass
41 // newTree = [[self alloc] initWithTopClass: newTopClass];
42 // [newTree autorelease];
47 // - (id) initWithTopClass: (Class) newTopClass
49 // if ((self = [self init]))
50 // topClass = newTopClass;
55 // #define indentGap 2
57 // - (NSString *) indentSpaces
61 // spaceString = malloc(sizeof (char *) * indentGap * indentLevel + 1);
62 // *(spaceString + indentGap * indentLevel) = 0;
63 // memset (spaceString, ' ', indentGap * indentLevel);
65 // return [[NSString alloc] initWithCStringNoCopy: spaceString
66 // length: indentGap * indentLevel
67 // freeWhenDone: YES];
70 // - (void) dumpNode: (Class) node
72 // Class currentSubclass;
73 // unsigned int count;
76 // currentSubclass = node->subclass_list;
77 // if (currentSubclass)
80 // [[self indentSpaces] autorelease], NSStringFromClass(node));
82 // [self dumpSiblings: currentSubclass];
86 // NSLog(@"%@%@", [self indentSpaces], NSStringFromClass(node));
89 // - (void) dumpSiblings: (Class) node
93 // currentNode = node;
94 // while (currentNode && currentNode->instance_size)
96 // [self dumpNode: currentNode];
97 // currentNode = currentNode->sibling_class;
105 // [self dumpSiblings: topClass];
110 @interface SOGo : SoApplication
112 NSMutableDictionary *localeLUT;
115 - (NSDictionary *) currentLocaleConsideringLanguages:(NSArray *)_langs;
116 - (NSDictionary *) localeForLanguageNamed:(NSString *)_name;
120 #include "SOGoProductLoader.h"
121 #include <WEExtensions/WEResourceManager.h>
122 #include <SOGo/SOGoAuthenticator.h>
123 #include <SOGo/SOGoUserFolder.h>
124 #include <SOGo/SOGoPermissions.h>
129 static unsigned int vMemSizeLimit = 0;
130 static BOOL doCrashOnSessionCreate = NO;
133 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
134 SoClassSecurityInfo *sInfo;
138 doCrashOnSessionCreate = [ud boolForKey:@"SOGoCrashOnSessionCreate"];
140 /* vMem size check - default is 200MB */
142 tmp = [ud objectForKey:@"SxVMemLimit"];
143 vMemSizeLimit = (tmp != nil)
146 if (vMemSizeLimit > 0) {
147 NSLog(@"Note: vmem size check enabled: shutting down app when "
148 @"vmem > %d MB", vMemSizeLimit);
150 #if LIB_FOUNDATION_LIBRARY
151 if ([ud boolForKey:@"SOGoEnableDoubleReleaseCheck"])
152 [NSAutoreleasePool enableDoubleReleaseCheck:YES];
155 /* SoClass security declarations */
156 sInfo = [self soClassSecurityInfo];
157 /* require View permission to access the root (bound to authenticated ...) */
158 [sInfo declareObjectProtected: SoPerm_View];
160 /* to allow public access to all contained objects (subkeys) */
161 [sInfo setDefaultAccess: @"allow"];
163 basicRoles = [NSArray arrayWithObjects: SoRole_Authenticated,
164 SOGoRole_FreeBusy, nil];
166 /* require Authenticated role for View and WebDAV */
167 [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_View];
168 [sInfo declareRoles: basicRoles asDefaultForPermission: SoPerm_WebDAVAccess];
172 if ((self = [super init])) {
173 WOResourceManager *rm;
175 /* ensure core SoClass'es are setup */
176 [$(@"SOGoObject") soClass];
177 [$(@"SOGoContentObject") soClass];
178 [$(@"SOGoFolder") soClass];
180 /* setup locale cache */
181 self->localeLUT = [[NSMutableDictionary alloc] initWithCapacity:2];
184 [[SOGoProductLoader productLoader] loadProducts];
186 /* setup resource manager */
187 rm = [[WEResourceManager alloc] init];
188 [self setResourceManager:rm];
194 [self->localeLUT release];
200 - (id)authenticatorInContext:(id)_ctx {
201 return [$(@"SOGoAuthenticator") sharedSOGoAuthenticator];
206 - (BOOL)isUserName:(NSString *)_key inContext:(id)_ctx {
207 if ([_key length] < 1)
210 if (isdigit([_key characterAtIndex:0]))
216 - (id)lookupUser:(NSString *)_key inContext:(id)_ctx {
217 return [[[$(@"SOGoUserFolder") alloc]
218 initWithName:_key inContainer:self] autorelease];
221 - (void)_setupLocaleInContext:(WOContext *)_ctx {
223 NSDictionary *locale;
225 if ([[_ctx valueForKey:@"locale"] isNotNull])
228 langs = [[(WOContext *)_ctx request] browserLanguages];
229 locale = [self currentLocaleConsideringLanguages:langs];
230 [_ctx takeValue:locale forKey:@"locale"];
233 - (id)lookupName:(NSString *)_key inContext:(id)_ctx acquire:(BOOL)_flag {
236 /* put locale info into the context in case it's not there */
237 [self _setupLocaleInContext:_ctx];
239 /* first check attributes directly bound to the application */
240 if ((obj = [super lookupName:_key inContext:_ctx acquire:_flag]))
244 The problem is, that at this point we still get request for resources,
247 Addition: we also get queries for various other methods, like "GET" if
248 no method was provided in the query path.
251 if ([_key isEqualToString:@"favicon.ico"])
254 if ([self isUserName:_key inContext:_ctx])
255 return [self lookupUser:_key inContext:_ctx];
262 - (NSString *)davDisplayName {
263 /* this is used in the UI, eg in the navigation */
267 /* exception handling */
269 - (WOResponse *)handleException:(NSException *)_exc
270 inContext:(WOContext *)_ctx
272 printf("EXCEPTION: %s\n", [[_exc description] cString]);
276 /* runtime maintenance */
278 // - (void) _dumpClassAllocation
282 // ct = [classtree newWithTopClass: [NSObject class]];
286 - (void)checkIfDaemonHasToBeShutdown {
287 unsigned int limit, vmem;
289 if ((limit = vMemSizeLimit) == 0)
292 vmem = [[NSProcessInfo processInfo] virtualMemorySize]/1048576;
296 @"terminating app, vMem size limit (%d MB) has been reached"
297 @" (currently %d MB)",
299 // [self _dumpClassAllocation];
304 - (WOResponse *)dispatchRequest:(WORequest *)_request {
305 static NSArray *runLoopModes = nil;
308 resp = [super dispatchRequest:_request];
310 if ([self isTerminating])
313 if (runLoopModes == nil)
314 runLoopModes = [[NSArray alloc] initWithObjects:NSDefaultRunLoopMode, nil];
316 // TODO: a bit complicated? (-perform:afterDelay: doesn't work?)
317 [[NSRunLoop currentRunLoop] performSelector:
318 @selector(checkIfDaemonHasToBeShutdown)
319 target:self argument:nil
320 order:1 modes:runLoopModes];
324 /* session management */
326 - (id)createSessionForRequest:(WORequest *)_request {
327 [self warnWithFormat:@"session creation requested!"];
328 if (doCrashOnSessionCreate)
330 return [super createSessionForRequest:_request];
335 - (NSDictionary *)currentLocaleConsideringLanguages:(NSArray *)_langs {
338 /* assume _langs is ordered by priority */
339 count = [_langs count];
340 for (i = 0; i < count; i++) {
342 NSDictionary *locale;
344 lname = [_langs objectAtIndex:i];
345 locale = [self localeForLanguageNamed:lname];
349 /* no appropriate language, fallback to default */
350 return [self localeForLanguageNamed:@"English"];
353 - (NSString *)pathToLocaleForLanguageNamed:(NSString *)_name {
354 static Class MainProduct = Nil;
357 lpath = [[self resourceManager] pathForResourceNamed:@"Locale"
359 languages:[NSArray arrayWithObject:_name]];
360 if ([lpath isNotNull])
363 if (MainProduct == Nil) {
364 if ((MainProduct = $(@"MainUIProduct")) == Nil)
365 [self errorWithFormat:@"did not find MainUIProduct class!"];
368 lpath = [(id)MainProduct pathToLocaleForLanguageNamed:_name];
369 if ([lpath isNotNull])
375 - (NSDictionary *)localeForLanguageNamed:(NSString *)_name {
378 NSDictionary *locale;
380 if (![_name isNotNull]) {
381 [self errorWithFormat:@"%s: name parameter must not be nil!",
382 __PRETTY_FUNCTION__];
386 if ((locale = [self->localeLUT objectForKey:_name]) != nil)
389 if ((lpath = [self pathToLocaleForLanguageNamed:_name]) == nil) {
390 [self errorWithFormat:@"did not find Locale for language: %@", _name];
394 if ((data = [NSData dataWithContentsOfFile:lpath]) == nil) {
395 [self logWithFormat:@"%s didn't find locale with name:%@",
400 data = [[[NSString alloc] initWithData:data
401 encoding:NSUTF8StringEncoding] autorelease];
402 locale = [data propertyList];
404 [self logWithFormat:@"%s couldn't load locale with name:%@",
409 [self->localeLUT setObject:locale forKey:_name];
413 /* name (used by the WEResourceManager) */