libs-sqlclient/WebServerBundles.m
Richard Frith-Macdonald ef9ef50bdc Various minor improvements in handling incoming requests.
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/sqlclient/trunk@20362 72102866-910b-0410-8b05-ffd578937521
2004-11-19 14:46:42 +00:00

248 lines
5.8 KiB
Objective-C

/**
Copyright (C) 2004 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
Date: June 2004
This file is part of the SQLClient Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
$Date$ $Revision$
*/
#include <Foundation/Foundation.h>
#include "WebServer.h"
@implementation WebServerBundles
- (void) dealloc
{
RELEASE(_http);
RELEASE(_handlers);
[super dealloc];
}
- (BOOL) defaultsUpdate: (NSNotification *)aNotification
{
NSUserDefaults *defs = [aNotification object];
NSString *port;
NSDictionary *secure;
port = [defs stringForKey: @"WebServerPort"];
if ([port length] == 0)
{
return NO; // Can't make web server active.
}
secure = [defs dictionaryForKey: @"WebServerSecure"];
return [_http setPort: port secure: secure];
}
- (id) handlerForPath: (NSString*)path info: (NSString**)info
{
NSString *error = nil;
NSMutableDictionary *handlers;
id handler;
if (info != 0)
{
*info = path;
}
handlers = [self handlers];
handler = [handlers objectForKey: path];
if (handler == nil)
{
NSUserDefaults *defs;
NSDictionary *conf;
NSDictionary *byPath;
defs = [NSUserDefaults standardUserDefaults];
conf = [defs dictionaryForKey: @"WebServerBundles"];
byPath = [conf objectForKey: path];
if ([byPath isKindOfClass: [NSDictionary class]] == NO)
{
NSRange r;
r = [path rangeOfString: @"/" options: NSBackwardsSearch];
if (r.length > 0)
{
path = [path substringToIndex: r.location];
handler = [self handlerForPath: path info: info];
}
else
{
error = [NSString stringWithFormat:
@"Unable to find handler in Bundles config for '%@'", path];
}
}
else
{
NSString *name;
name = [byPath objectForKey: @"Name"];
if ([name length] == 0)
{
error = [NSString stringWithFormat:
@"Unable to find Name in Bundles config for '%@'", path];
}
else
{
NSBundle *mb = [NSBundle mainBundle];
NSString *p = [mb pathForResource: name ofType: @"bundle"];
NSBundle *b = [NSBundle bundleWithPath: p];
Class c = [b principalClass];
if (c == 0)
{
error = [NSString stringWithFormat:
@"Unable to find class in '%@' for '%@'", p, path];
}
else
{
handler = [c new];
[self registerHandler: handler forPath: path];
RELEASE(handler);
}
}
}
}
if (handler == nil && info != 0)
{
*info = error;
}
return handler;
}
- (NSMutableDictionary*) handlers
{
if (_handlers == nil)
{
_handlers = [NSMutableDictionary new];
}
return _handlers;
}
- (WebServer*) http
{
return _http;
}
- (id) init
{
return [self initAsDelegateOf: nil];
}
- (id) initAsDelegateOf: (WebServer*)http
{
if (http == nil)
{
DESTROY(self);
}
else
{
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
NSNotification *n;
ASSIGN(_http, http);
[_http setDelegate: self];
/*
* Watch for config changes, and set initial config by sending a
* faked change notification.
*/
[nc addObserver: self
selector: @selector(defaultsUpdate:)
name: NSUserDefaultsDidChangeNotification
object: defs];
n = [NSNotification
notificationWithName: NSUserDefaultsDidChangeNotification
object: defs
userInfo: nil];
if ([self defaultsUpdate: n] == NO)
{
DESTROY(self);
}
}
return self;
}
/**
* We handle the incoming requests here.
*/
- (BOOL) processRequest: (GSMimeDocument*)request
response: (GSMimeDocument*)response
for: (WebServer*)http
{
NSString *path;
NSString *info;
id handler;
path = [[request headerNamed: @"x-http-path"] value];
handler = [self handlerForPath: path info: &info];
if (handler == nil)
{
NSString *error = @"bad path";
/*
* Log the error message.
*/
[self webAlert: info for: (WebServer*)http];
/*
* Return status code 400 (Bad Request) with the informative error
*/
error = [NSString stringWithFormat: @"HTTP/1.0 400 %@", error];
[response setHeader: @"http" value: error parameters: nil];
return YES;
}
else
{
NSString *extra = [path substringFromIndex: [info length]];
/*
* Provide extra information about the exact path used to match
* the handler, and any remaining path information beyond it.
*/
[request setHeader: @"x-http-path-base"
value: info
parameters: nil];
[request setHeader: @"x-http-path-info"
value: extra
parameters: nil];
return [handler processRequest: request
response: response
for: http];
}
}
- (void) registerHandler: (id)handler forPath: (NSString*)path
{
if (handler == nil)
{
[[self handlers] removeObjectForKey: path];
}
else
{
[[self handlers] setObject: handler forKey: path];
}
}
- (void) webAlert: (NSString*)message for: (WebServer*)http
{
NSLog(@"%@", message);
}
@end