]> err.no Git - sope/commitdiff
added mod_objc
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Wed, 16 Nov 2005 13:26:01 +0000 (13:26 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Wed, 16 Nov 2005 13:26:01 +0000 (13:26 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@1175 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

85 files changed:
Recycler/ApacheWO/.cvsignore [new file with mode: 0644]
Recycler/ApacheWO/20040608 [new file with mode: 0644]
Recycler/ApacheWO/AWODirectoryConfig.h [new file with mode: 0644]
Recycler/ApacheWO/AWODirectoryConfig.m [new file with mode: 0644]
Recycler/ApacheWO/AWOServerConfig.h [new file with mode: 0644]
Recycler/ApacheWO/AWOServerConfig.m [new file with mode: 0644]
Recycler/ApacheWO/AliasMap.h [new file with mode: 0644]
Recycler/ApacheWO/AliasMap.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheCommands.plist [new file with mode: 0644]
Recycler/ApacheWO/ApacheHandlers.plist [new file with mode: 0644]
Recycler/ApacheWO/ApacheResourceManager.h [new file with mode: 0644]
Recycler/ApacheWO/ApacheResourceManager.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO+Echo.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO+Echo2.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO+RequestHandler.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO+hooks.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO+woxpage.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO.h [new file with mode: 0644]
Recycler/ApacheWO/ApacheWO.m [new file with mode: 0644]
Recycler/ApacheWO/ApacheWOTransaction.h [new file with mode: 0644]
Recycler/ApacheWO/ApacheWOTransaction.m [new file with mode: 0644]
Recycler/ApacheWO/ChangeLog [new file with mode: 0644]
Recycler/ApacheWO/GNUmakefile [new file with mode: 0644]
Recycler/ApacheWO/README [new file with mode: 0644]
Recycler/ApacheWO/TestApp/GNUmakefile [new file with mode: 0644]
Recycler/ApacheWO/TestApp/TestApp.m [new file with mode: 0644]
Recycler/ApacheWO/WOComponent+Apache.m [new file with mode: 0644]
Recycler/ApacheWO/WORequest+Apache.h [new file with mode: 0644]
Recycler/ApacheWO/WORequest+Apache.m [new file with mode: 0644]
Recycler/ApacheWO/WORequestHandler+Apache.h [new file with mode: 0644]
Recycler/ApacheWO/WORequestHandler+Apache.m [new file with mode: 0644]
Recycler/ApacheWO/WOResponse+Apache.h [new file with mode: 0644]
Recycler/ApacheWO/WOResponse+Apache.m [new file with mode: 0644]
Recycler/ApacheWO/common.h [new file with mode: 0644]
Recycler/ApacheWO/docs/Embed.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/Frame.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/Page2.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/Page3.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/RqInfo.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/SSIPage.shtml [new file with mode: 0644]
Recycler/ApacheWO/docs/SlowMarket.gif [new file with mode: 0644]
Recycler/ApacheWO/docs/Table.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.html [new file with mode: 0644]
Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.js [new file with mode: 0644]
Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.wod [new file with mode: 0644]
Recycler/ApacheWO/docs/bigimg.gif [new file with mode: 0644]
Recycler/ApacheWO/docs/imgs/SlowMarket.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/renameme-.htaccess [new file with mode: 0644]
Recycler/ApacheWO/docs/requests.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/subdir/renameme-.htaccess [new file with mode: 0644]
Recycler/ApacheWO/docs/subdir/test.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/test.html [new file with mode: 0644]
Recycler/ApacheWO/docs/test.wox [new file with mode: 0644]
Recycler/ApacheWO/docs/wa.rqh [new file with mode: 0644]
Recycler/ApacheWO/docs/xmlrpc.rqh [new file with mode: 0644]
Recycler/ApacheWO/httpd.conf [new file with mode: 0644]
Recycler/ApacheWO/httpd.sh [new file with mode: 0755]
Recycler/mod_objc/ApModuleBaseClass+Callbacks.m [new file with mode: 0644]
Recycler/mod_objc/ApModuleBaseClass+Cmds.m [new file with mode: 0644]
Recycler/mod_objc/ApModuleBaseClass+Handler.m [new file with mode: 0644]
Recycler/mod_objc/ApModuleBaseClass.h [new file with mode: 0644]
Recycler/mod_objc/ApModuleBaseClass.m [new file with mode: 0644]
Recycler/mod_objc/ApTest.m [new file with mode: 0644]
Recycler/mod_objc/ApacheCmdParms.h [new file with mode: 0644]
Recycler/mod_objc/ApacheCmdParms.m [new file with mode: 0644]
Recycler/mod_objc/ApacheConnection.h [new file with mode: 0644]
Recycler/mod_objc/ApacheConnection.m [new file with mode: 0644]
Recycler/mod_objc/ApacheModule.h [new file with mode: 0644]
Recycler/mod_objc/ApacheModule.m [new file with mode: 0644]
Recycler/mod_objc/ApacheObject.h [new file with mode: 0644]
Recycler/mod_objc/ApacheObject.m [new file with mode: 0644]
Recycler/mod_objc/ApacheRequest.h [new file with mode: 0644]
Recycler/mod_objc/ApacheRequest.m [new file with mode: 0644]
Recycler/mod_objc/ApacheResourcePool.h [new file with mode: 0644]
Recycler/mod_objc/ApacheResourcePool.m [new file with mode: 0644]
Recycler/mod_objc/ApacheServer.h [new file with mode: 0644]
Recycler/mod_objc/ApacheServer.m [new file with mode: 0644]
Recycler/mod_objc/ApacheTable.h [new file with mode: 0644]
Recycler/mod_objc/ApacheTable.m [new file with mode: 0644]
Recycler/mod_objc/GNUmakefile [new file with mode: 0644]
Recycler/mod_objc/GSBundleModule.m [new file with mode: 0644]
Recycler/mod_objc/README [new file with mode: 0644]
Recycler/mod_objc/genApacheModule.sh [new file with mode: 0755]
Recycler/mod_objc/mod_gsbundle.m [new file with mode: 0644]
Recycler/mod_objc/test.conf [new file with mode: 0644]

diff --git a/Recycler/ApacheWO/.cvsignore b/Recycler/ApacheWO/.cvsignore
new file mode 100644 (file)
index 0000000..e0d38cd
--- /dev/null
@@ -0,0 +1,4 @@
+*.apache
+*_module_structure.m
+logs
+shared_debug_obj
diff --git a/Recycler/ApacheWO/20040608 b/Recycler/ApacheWO/20040608
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/Recycler/ApacheWO/AWODirectoryConfig.h b/Recycler/ApacheWO/AWODirectoryConfig.h
new file mode 100644 (file)
index 0000000..567bffc
--- /dev/null
@@ -0,0 +1,27 @@
+// $Id: AWODirectoryConfig.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __AWODirectoryConfig_H__
+#define __AWODirectoryConfig_H__
+
+#import <Foundation/NSObject.h>
+
+@class WOApplication, WORequestHandler;
+@class ApacheResourcePool, ApacheCmdParms;
+
+@interface AWODirectoryConfig : NSObject
+{
+  WOApplication    *application;
+  WORequestHandler *rqHandler;
+}
+
+/* configuration */
+
+- (void)setApplication:(WOApplication *)_app;
+- (WOApplication *)application;
+
+- (void)setRequestHandler:(WORequestHandler *)_handler;
+- (WORequestHandler *)requestHandler;
+
+@end
+
+#endif /* __AWODirectoryConfig_H__ */
diff --git a/Recycler/ApacheWO/AWODirectoryConfig.m b/Recycler/ApacheWO/AWODirectoryConfig.m
new file mode 100644 (file)
index 0000000..33eb745
--- /dev/null
@@ -0,0 +1,137 @@
+// $Id: AWODirectoryConfig.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "AWODirectoryConfig.h"
+#include "ApacheWO.h"
+#include <ApacheAPI/ApacheResourcePool.h>
+#include <NGObjWeb/WOApplication.h>
+#include <NGObjWeb/WORequestHandler.h>
+#include "common.h"
+
+@implementation AWODirectoryConfig
+
+- (id)init {
+  return self;
+}
+
+- (id)initWithConfig:(AWODirectoryConfig *)_cfg {
+  if ((self = [self init])) {
+    self->application = [_cfg->application retain];
+    self->rqHandler   = [_cfg->rqHandler   retain];
+  }
+  return self;
+}
+
+- (id)initWithBaseConfig:(AWODirectoryConfig *)_base
+  andConfig:(AWODirectoryConfig *)_new
+{
+  if ((self = [self initWithConfig:_base])) {
+    if (_new->application)
+      ASSIGN(self->application, _new->application);
+    if (_new->rqHandler)
+      ASSIGN(self->rqHandler, _new->rqHandler);
+  }
+  return self;
+}
+
+- (void)dealloc {
+  RELEASE(self->application);
+  RELEASE(self->rqHandler);
+  [super dealloc];
+}
++ (id)mergeBaseConfig:(AWODirectoryConfig *)_base
+  withNewConfig:(AWODirectoryConfig *)_new
+{
+  return [[[self alloc] initWithBaseConfig:_base andConfig:_new] autorelease];
+}
+
+- (NSString *)stringValue {
+  return [self description];
+}
+- (NSString *)description {
+  NSMutableString *ms;
+  id tmp;
+  
+  ms = [NSMutableString stringWithCapacity:64];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  
+  if ((tmp = [self application]))
+    [ms appendFormat:@" app=%@(0x%08X)", [(WOApplication *)tmp name], tmp];
+  if ((tmp = [self requestHandler]))
+    [ms appendFormat:@" rqh=%@", tmp];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+/* configuration */
+
+- (void)setApplication:(WOApplication *)_app {
+  ASSIGN(self->application, _app);
+}
+- (WOApplication *)application {
+  return self->application;
+}
+
+- (void)setRequestHandler:(WORequestHandler *)_handler {
+  ASSIGN(self->rqHandler, _handler);
+}
+- (WORequestHandler *)requestHandler {
+  return self->rqHandler;
+}
+
+/* commands */
+
+- (id)SetSxApplication:(NSString *)_key {
+  WOApplication *app;
+
+  if ((app = [self application])) {
+    [self logWithFormat:@"application already set !"];
+  }
+  
+  if ((app = [ApacheWO applicationForKey:_key className:nil]) == nil) {
+    [self logWithFormat:@"got no application for key '%@'", _key];
+  }
+  else {
+    [self setApplication:app];
+  }
+  
+  return nil /* nil means 'no error' */;
+}
+
+- (id)SetSxRequestHandler:(NSString *)_className {
+  WORequestHandler *rqh;
+  Class rqhClazz;
+  
+  if ((rqh = [self requestHandler])) {
+    [self logWithFormat:@"requestHandler already set !"];
+  }
+  
+  if ((rqhClazz = NSClassFromString(_className)) == Nil) {
+    return [NSString stringWithFormat:
+                       @"did not find request handler for class '%@'",
+                       _className];
+  }
+  
+  if ((rqh = [[rqhClazz alloc] init]) == nil) {
+    return [NSString stringWithFormat:
+                       @"could not allocate request handler of class '%@'",
+                       _className];
+  }
+
+  [self setRequestHandler:rqh];
+  RELEASE(rqh);
+  
+  return nil /* nil means 'no error' */;
+}
+
+- (id)LogText:(NSString *)_txt {
+  if ([_txt length] == 0)
+    /* return an error text */
+    return @"missing echo text !";
+  
+  //[self appendString:_txt];
+  
+  return nil /* nil means 'no error' */;
+}
+
+@end /* AWODirectoryConfig */
diff --git a/Recycler/ApacheWO/AWOServerConfig.h b/Recycler/ApacheWO/AWOServerConfig.h
new file mode 100644 (file)
index 0000000..bf968e9
--- /dev/null
@@ -0,0 +1,22 @@
+// $Id: AWOServerConfig.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __AWOServerConfig_H__
+#define __AWOServerConfig_H__
+
+#import <Foundation/NSObject.h>
+
+@class AliasMap;
+@class NSMutableDictionary, NSMutableArray;
+@class WOApplication, WORequestHandler;
+@class ApacheResourcePool, ApacheServer, ApacheCmdParms;
+
+@interface AWOServerConfig : NSObject
+{
+@public
+  AliasMap *appAlias;
+  AliasMap *handlerAlias;
+}
+
+@end
+
+#endif /* __AWOServerConfig_H__ */
diff --git a/Recycler/ApacheWO/AWOServerConfig.m b/Recycler/ApacheWO/AWOServerConfig.m
new file mode 100644 (file)
index 0000000..9b2f20e
--- /dev/null
@@ -0,0 +1,104 @@
+// $Id: AWOServerConfig.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "AWOServerConfig.h"
+#include "AliasMap.h"
+#include <ApacheAPI/ApacheResourcePool.h>
+#include <ApacheAPI/ApacheServer.h>
+#include <ApacheAPI/ApacheCmdParms.h>
+#include <NGObjWeb/WOApplication.h>
+#include <NGObjWeb/WORequestHandler.h>
+#include "common.h"
+
+@implementation AWOServerConfig
+
+- (id)initWithServer:(ApacheServer *)_server {
+  //NSLog(@"%s: init with server: %@", __PRETTY_FUNCTION__, _server);
+  self->appAlias     = [[AliasMap alloc] initWithCapacity:8];
+  self->handlerAlias = [[AliasMap alloc] initWithCapacity:8];
+  return self;
+}
+
+- (id)initWithConfig:(AWOServerConfig *)_cfg {
+  if ((self = [self init])) {
+    self->appAlias = [[AliasMap alloc] initWithAliasMap:_cfg->appAlias];
+    self->handlerAlias = 
+      [[AliasMap alloc] initWithAliasMap:_cfg->handlerAlias];
+  }
+  return self;
+}
+
+- (id)initWithBaseConfig:(AWOServerConfig *)_base
+  andConfig:(AWOServerConfig *)_new
+{
+  if ((self = [self initWithConfig:_base])) {
+    [self->appAlias addEntriesFromAliasMap:_new->appAlias];
+    [self->handlerAlias addEntriesFromAliasMap:_new->handlerAlias];
+  }
+  return self;
+}
+
+- (void)dealloc {
+  RELEASE(self->appAlias);
+  RELEASE(self->handlerAlias);
+  [super dealloc];
+}
+
++ (id)mergeBaseConfig:(AWOServerConfig *)_base
+  withNewConfig:(AWOServerConfig *)_new
+{
+  return [[[self alloc] initWithBaseConfig:_base andConfig:_new] autorelease];
+}
+
+- (NSString *)stringValue {
+  return [self description];
+}
+- (NSString *)description {
+  NSMutableString *ms;
+  
+  ms = [NSMutableString stringWithCapacity:64];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  
+  [ms appendFormat:@" appAlias=%@", self->appAlias];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+/* commands */
+
+- (id)SxApplicationAlias:(NSString *)_name:(NSString *)_uri {
+  NSString *tmp;
+  
+  if ((tmp = [self->appAlias uriForKey:_name baseURI:@"/"])) {
+    return [NSString stringWithFormat:@"app %@ already mapped to %@",
+                      _name, tmp];
+  }
+  
+  //[self logWithFormat:@"aliasing app %@ to %@", _name, _uri];
+  
+  [self->appAlias mapKey:_name toURI:_uri];
+  
+  return nil /* nil means 'no error' */;
+}
+
+- (id)SxHandlerAlias:(NSString *)_handler:(NSString *)_uri {
+  NSString *tmp;
+  
+  if ((tmp = [self->handlerAlias uriForKey:_handler baseURI:@"/"])) {
+    return [NSString stringWithFormat:@"handler %@ already mapped to %@",
+                      _handler, tmp];
+  }
+  
+  //[self logWithFormat:@"aliasing handler %@ to %@", _handler, _uri];
+  
+  [self->handlerAlias mapKey:_handler toURI:_uri];
+  
+  return nil /* nil means 'no error' */;
+}
+
+- (id)LoadBundle:(NSString *)_bundleName {
+  [self logWithFormat:@"should load bundle %@", _bundleName];
+  return nil;
+}
+
+@end /* AWOServerConfig */
diff --git a/Recycler/ApacheWO/AliasMap.h b/Recycler/ApacheWO/AliasMap.h
new file mode 100644 (file)
index 0000000..0cb9225
--- /dev/null
@@ -0,0 +1,40 @@
+// $Id: AliasMap.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __AliasMap_H__
+#define __AliasMap_H__
+
+#import <Foundation/NSObject.h>
+
+/*
+  An alias-map maps some kind of key to a URI. During lookups the
+  URI is processed to find the longest matching prefix.
+  
+  Note: a URI may be mapped to only one key, but a key can be mapped
+  to multiple URIs ! (key<->URI is 1:n)
+*/
+
+@class NSMutableDictionary, NSMutableArray;
+
+@interface AliasMap : NSObject < NSCopying >
+{
+  NSMutableArray      *uris;
+  NSMutableDictionary *uri2key;
+  NSMutableDictionary *key2uris;
+}
+
+- (id)initWithCapacity:(unsigned)_capacity;
+- (id)initWithAliasMap:(AliasMap *)_map;
+
+/* modification */
+
+- (BOOL)mapKey:(id)_key toURI:(NSString *)_uri;
+- (BOOL)addEntriesFromAliasMap:(AliasMap *)_map;
+
+/* query */
+
+- (id)keyForURI:(NSString *)_uri;
+- (NSString *)uriForKey:(id)_key baseURI:(NSString *)_uri;
+
+@end
+
+#endif /* __AliasMap_H__ */
diff --git a/Recycler/ApacheWO/AliasMap.m b/Recycler/ApacheWO/AliasMap.m
new file mode 100644 (file)
index 0000000..31e1689
--- /dev/null
@@ -0,0 +1,139 @@
+// $Id: AliasMap.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "AliasMap.h"
+#include "common.h"
+
+@implementation AliasMap
+
+- (id)initWithCapacity:(unsigned)_capacity {
+  self->uri2key  = [[NSMutableDictionary alloc] initWithCapacity:_capacity];
+  self->key2uris = [[NSMutableDictionary alloc] initWithCapacity:_capacity];
+  self->uris     = [[NSMutableArray alloc] initWithCapacity:_capacity];
+  return self;
+}
+- (id)initWithAliasMap:(AliasMap *)_map {
+  self->uri2key  = [_map->uri2key  mutableCopy];
+  self->key2uris = [_map->key2uris mutableCopy];
+  self->uris     = [_map->uris     mutableCopy];
+  return self;
+}
+
+- (id)init {
+  return [self initWithCapacity:16];
+}
+
+- (void)dealloc {
+  RELEASE(self->key2uris);
+  RELEASE(self->uri2key);
+  RELEASE(self->uris);
+  [super dealloc];
+}
+
+/* modification */
+
+- (BOOL)mapKey:(id)_key toURI:(NSString *)_uri {
+  id tmp;
+  NSMutableArray *kuris;
+  
+  if (_uri == nil) return NO;
+  if (_key == nil) return NO;
+  
+  if ((tmp = [self->uri2key objectForKey:_uri]))
+    /* already mapped !!! */
+    return NO;
+  
+  [self->uri2key setObject:_key forKey:_uri];
+  [self->uris    addObject:_uri];
+  
+  if ((kuris = [self->key2uris objectForKey:_key]) == nil)
+    kuris = [[NSMutableArray alloc] initWithCapacity:4];
+  else
+    kuris = [kuris mutableCopy];
+  
+  [kuris addObject:_uri];
+  
+  [self->key2uris setObject:kuris forKey:_key];
+  RELEASE(kuris);
+  
+  return YES;
+}
+
+- (BOOL)addEntriesFromAliasMap:(AliasMap *)_map {
+  [self->uri2key  addEntriesFromDictionary:_map->uri2key];
+  [self->key2uris addEntriesFromDictionary:_map->key2uris];
+  [self->uris     addObjectsFromArray:_map->uris];
+  return YES;
+}
+
+/* query */
+
+- (NSString *)longestMatchingURIForURI:(NSString *)_uri
+  fromArray:(NSArray *)_baseSet  
+{
+  NSEnumerator *e;
+  NSString     *auri, *longest = nil;
+  unsigned     max = 0, len;
+  
+  if ((len = [_uri length]) == 0)
+    return nil;
+  
+  /* foreach registered URI */
+  e = [_baseSet objectEnumerator];
+  
+  while ((auri = [e nextObject])) {
+    unsigned l = [auri length];
+    
+    /* quick precondition: prefix can't be longer than the string .. */
+    if (l > len) 
+      continue; 
+    
+    if ([_uri hasPrefix:auri]) {
+      if (len == l) /* found an exact match */
+       return auri;
+      
+      if (l > max) { /* found a new longer uri ... */
+       longest = auri;
+       max = len;
+      }
+    }
+  }
+  
+  return longest;
+}
+
+- (id)keyForURI:(NSString *)_uri {
+  NSString *aliasURI;
+  
+  aliasURI = [self longestMatchingURIForURI:_uri fromArray:self->uris];
+  if ([aliasURI length] == 0)
+    return nil;
+  
+  return [self->uri2key objectForKey:aliasURI];
+}
+
+- (NSString *)uriForKey:(id)_key baseURI:(NSString *)_uri {
+  NSArray  *kuris;
+  NSString *aliasURI;
+  unsigned kcount;
+  
+  kuris = [self->key2uris objectForKey:_key];
+  if ((kcount = [kuris count] == 0))
+    return nil;
+  
+  if (kcount == 1) /* only one possibility */
+    aliasURI = [kuris objectAtIndex:0];
+  else {
+    aliasURI = [self longestMatchingURIForURI:_uri fromArray:kuris];
+    NSAssert(aliasURI != nil, @"no matching URI in structure ???");
+  }
+  
+  return aliasURI;
+}
+
+/* copying */
+
+- (id)copyWithZone:(NSZone *)_zone {
+  return [[AliasMap alloc] initWithAliasMap:self];
+}
+
+@end /* AliasMap */
diff --git a/Recycler/ApacheWO/ApacheCommands.plist b/Recycler/ApacheWO/ApacheCommands.plist
new file mode 100644 (file)
index 0000000..4956966
--- /dev/null
@@ -0,0 +1,46 @@
+{
+  DirectoryConfigClass = "AWODirectoryConfig";
+  ServerConfigClass    = "AWOServerConfig";
+  
+  /* directory config */
+  SetSxApplication = {
+    selector = "SetSxApplication:";
+    overrides = ( ACCESS_CONF, OR_OPTIONS );
+    argspec   = "TAKE1";
+    usage     = "usage: SetSxApplication <appname>";
+  };
+  SetSxRequestHandler = {
+    selector = "SetSxRequestHandler:";
+    overrides = ( ACCESS_CONF, OR_OPTIONS );
+    argspec   = "TAKE1";
+    usage     = "usage: SetSxRequestHandler <rqhandlerclass>";
+  };
+  LogText = {
+    selector = "LogText:";
+    overrides = ( ACCESS_CONF, OR_OPTIONS );
+    argspec   = "TAKE1";
+    usage     = "usage: LogText <sometext>";
+  };
+
+  /* server config */
+
+  LoadBundle = {
+    selector = "LoadBundle:";
+    overrides = ( RSRC_CONF );
+    argspec   = "TAKE1";
+    usage     = "usage: LoadBundle <bundleName|bundlePath>";
+  };
+
+  SxApplicationAlias = {
+    selector = "SxApplicationAlias::";
+    overrides = ( RSRC_CONF );
+    argspec   = "TAKE2";
+    usage     = "usage: SxApplicationAlias <appkey> <baseuri>";
+  };
+  SxHandlerAlias = {
+    selector = "SxHandlerAlias::";
+    overrides = ( RSRC_CONF );
+    argspec   = "TAKE2";
+    usage     = "usage: SxHandlerAlias <handlerkey> <baseuri>";
+  };
+}
diff --git a/Recycler/ApacheWO/ApacheHandlers.plist b/Recycler/ApacheWO/ApacheHandlers.plist
new file mode 100644 (file)
index 0000000..2b42d6d
--- /dev/null
@@ -0,0 +1,20 @@
+{
+  CVSID="$Id: ApacheHandlers.plist,v 1.1 2004/06/08 11:06:00 helge Exp $";
+  
+  /* Note: only lowercase letters are allowed in handler names ! */
+  
+  Name2Selector = {
+    "objc-echo"        = "performObjcEchoRequest:";
+    "sx-handler"       = "performSxHandlerRequest:config:";
+    "wox-page"         = "performWoxPageRequest:";
+    "sx-alias-handler" = "performSxAliasHandlerRequest:";
+  };
+  
+  MimeType2Selector = {
+    "application/x-httpd-wox" = "performWoxPageRequest:";
+    "application/x-httpd-wo"  = "handleApplicationXHttpdWoRequest:config:";
+    "httpd/unix-directory"    = "handleDirectoryRequest:config:";
+    "skyrix/request-handler"  = "handleSkyrixRqHandler:config:";
+//  "*/*"                     = "handleGenericRequest:config:";
+  };
+}
diff --git a/Recycler/ApacheWO/ApacheResourceManager.h b/Recycler/ApacheWO/ApacheResourceManager.h
new file mode 100644 (file)
index 0000000..89ed51e
--- /dev/null
@@ -0,0 +1,26 @@
+// $Id: ApacheResourceManager.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __ApacheResourceManager_H__
+#define __ApacheResourceManager_H__
+
+#include <NGObjWeb/WOResourceManager.h>
+
+@class NSMutableDictionary;
+@class ApacheRequest;
+@class AWODirectoryConfig;
+@class WOComponent;
+
+@interface ApacheResourceManager : WOResourceManager
+{
+  ApacheRequest       *request;
+  AWODirectoryConfig  *config;
+  NSMutableDictionary *nameToURL;
+  WOComponent         *component; /* non-retained */
+}
+
+- (id)initWithApacheRequest:(ApacheRequest *)_rq
+  config:(AWODirectoryConfig *)_cfg;
+
+@end
+
+#endif /* __ApacheResourceManager_H__ */
diff --git a/Recycler/ApacheWO/ApacheResourceManager.m b/Recycler/ApacheWO/ApacheResourceManager.m
new file mode 100644 (file)
index 0000000..5967f92
--- /dev/null
@@ -0,0 +1,227 @@
+// $Id: ApacheResourceManager.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheResourceManager.h"
+#include "AWODirectoryConfig.h"
+#include <ApacheAPI/ApacheRequest.h>
+#include <ApacheAPI/ApacheServer.h>
+#include <ApacheAPI/ApacheTable.h>
+#include <NGObjWeb/WOComponent.h>
+#include <NGObjWeb/WOApplication.h>
+#include <NGObjWeb/WOContext.h>
+#include "common.h"
+
+@interface NSObject(UsedARPrivates)
+
+- (void)setComponentClass:(Class)_class;
+
+- (id)_definitionWithName:(NSString *)_name
+  url:(NSURL *)_url
+  baseURL:(NSURL *)_burl
+  frameworkName:(NSString *)_fwname;
+
+@end
+
+@implementation ApacheResourceManager
+
+static NSMutableDictionary *md = nil;
+
+- (id)initWithURI:(NSString *)_uri {
+  return self;
+}
++ (id)resourceManagerForURI:(NSString *)_uri {
+  ApacheResourceManager *rm;
+  NSRange r;
+  
+  if ([_uri length] > 1) {
+    r = [_uri rangeOfString:@"/" options:NSBackwardsSearch];
+    if (r.length == 0) {
+      NSLog(@"%s: strange uri: %@", __PRETTY_FUNCTION__, _uri);
+      return nil;
+    }
+    
+    _uri = [_uri substringToIndex:(r.location + r.length)];
+  }
+  
+  if ((rm = [md objectForKey:_uri]))
+    return rm;
+  
+  if ((rm = [[ApacheResourceManager alloc] initWithURI:_uri]) == nil)
+    return nil;
+  
+  if (md == nil)
+    md = [[NSMutableDictionary alloc] init];
+  [md setObject:rm forKey:_uri];
+  return AUTORELEASE(rm);
+}
+
+- (id)initWithApacheRequest:(ApacheRequest *)_rq
+  config:(AWODirectoryConfig *)_cfg
+{
+  self->request = [_rq retain];
+  self->config  = [_cfg retain];
+  return self;
+}
+- (void)dealloc {
+  RELEASE(self->nameToURL);
+  RELEASE(self->request);
+  RELEASE(self->config);
+  [super dealloc];
+}
+
+/* URLs */
+
+- (NSURL *)refererURL {
+  id rurl;
+  
+  if ((rurl = [[self->request headersIn] objectForKey:@"Referer"]))
+    rurl = [NSURL URLWithString:rurl];
+  return rurl;
+}
+
+- (NSURL *)requestURL {
+  ApacheServer *srv = [self->request server];
+  id rurl;
+  
+  rurl = [NSString stringWithFormat:@"http://%@:%i%@",
+                    [srv serverHostName],
+                    [srv port],
+                    [self->request uri]];
+  rurl = [NSURL URLWithString:rurl];
+  return rurl;
+}
+
+/* operations */
+
+- (NSURL *)_templateBaseURLForComponentNamed:(id)_name {
+  ApacheRequest *srq;
+  NSURL *url = nil;
+  
+  if (_name == nil || [_name isEqual:[self->request uri]])
+    return [self requestURL];
+  
+  if ([_name isKindOfClass:[NSURL class]]) {
+    srq = [self->request subRequestLookupURI:[_name uri]];
+  }
+  else {
+    if ([[_name pathExtension] length] == 0)
+      _name = [_name stringByAppendingPathExtension:@"wox"];
+    
+    srq = [self->request subRequestLookupURI:_name];
+  }
+  
+  if ([srq doesFileExist]) {
+    url = [[[NSURL alloc] initWithString:[srq uri] 
+                         relativeToURL:[self requestURL]] 
+                         autorelease];
+  }
+  else {
+    [self logWithFormat:@"file does not exist: %@ (%@)",
+            [srq filename], [srq fileType]];
+  }
+  return url;
+}
+
+- (id)definitionForComponent:(id)_name
+  languages:(NSArray *)_languages
+{
+  id    cdef;
+  NSURL *url, *baseURL;
+  
+  if ((baseURL = [self->nameToURL objectForKey:_name]) == nil) {
+    //[self logWithFormat:@"def for component: %@)", _name];
+    
+    if ((baseURL = [self _templateBaseURLForComponentNamed:_name]) == nil) {
+      [self logWithFormat:@"did not find template URL for component %@",_name];
+      return nil;
+    }
+    
+    if (self->nameToURL == nil)
+      self->nameToURL = [[NSMutableDictionary alloc] initWithCapacity:16];
+    
+    [self->nameToURL setObject:baseURL forKey:_name];
+  }
+  
+  /* lookup file for URI */
+  
+  if (baseURL == nil)
+    return nil;
+  else if ([baseURL isFileURL]) {
+    [self logWithFormat:@"baseURL(%@) cannot be a file URL !", baseURL];
+#if DEBUG
+    exit(1);
+#endif
+  }
+  else {
+    ApacheRequest *srq;
+    NSString *fn;
+    
+    fn = [baseURL path];
+#if DEBUG
+    if ([fn indexOfString:@"INTERNALLY GENERATED"] != NSNotFound) {
+      [self logWithFormat:@"baseURL(%@) broken !", baseURL];
+      exit(2);
+    }
+#endif
+    
+    //[self logWithFormat:@"LOOKUP: %@", fn];
+    srq = [self->request subRequestLookupURI:[baseURL path] method:@"HEAD"];
+    
+    fn = [srq filename];
+    //[self logWithFormat:@"File: %@", fn];
+    
+    url = [[[NSURL alloc] initFileURLWithPath:fn] autorelease];
+    
+    //NSLog(@"mapped:\n  base %@\n  content %@", baseURL, url);
+  }
+  
+  /* create definition */
+  
+  cdef = [self _definitionWithName:_name
+               url:url
+               baseURL:baseURL
+               frameworkName:nil];
+  
+  [cdef setComponentClass:[WOComponent class]];
+  
+  return cdef;
+}
+
+- (NSString *)urlForResourceNamed:(NSString *)_name
+  inFramework:(NSString *)_frameworkName
+  languages:(NSArray *)_languages
+  request:(WORequest *)_request
+{
+  NSURL *compURL, *rURL;
+  
+  //[self logWithFormat:@"URL for resource named %@", _name];
+  
+  if ((compURL = [self->component baseURL]) == nil) {
+    compURL = [[[[WOApplication application] context] component] baseURL];
+    
+    if (compURL) {
+#if 0
+      [self logWithFormat:@"use current component URL: %@", 
+             [compURL absoluteString]];
+#endif
+    }
+  }
+  
+  if (compURL == nil) {
+    compURL = [[[WOApplication application] context] baseURL];
+    if (self->component)
+      [self logWithFormat:@"component has no base, using context: %@",
+             [compURL absoluteString]];
+    else
+      [self logWithFormat:@"using component URL as base: %@",
+             [compURL absoluteString]];
+  }
+  
+  //[self logWithFormat:@"  relative to %@", [compURL absoluteString]];
+  
+  rURL = [NSURL URLWithString:_name relativeToURL:compURL];
+  //[self logWithFormat:@"  URL: %@", [rURL absoluteString]];
+  
+  return [rURL absoluteString];
+}
+
+@end /* ApacheResourceManager */
diff --git a/Recycler/ApacheWO/ApacheWO+Echo.m b/Recycler/ApacheWO/ApacheWO+Echo.m
new file mode 100644 (file)
index 0000000..d156523
--- /dev/null
@@ -0,0 +1,61 @@
+// $Id: ApacheWO+Echo.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheWO.h"
+#include "common.h"
+#include <ApacheAPI/ApacheAPI.h>
+
+@implementation ApacheWO(EchoHandler)
+
+- (int)performObjcEchoRequest:(ApacheRequest *)_rq {
+  NSAutoreleasePool *pool;
+  id cfg;
+  NSString *s;
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  
+  /* get directory specific info ! */
+  cfg = [self configForDirectory:_rq];
+  
+  [self performWoxPageRequest:_rq];
+  
+  NSLog(@"CFG: %@", cfg);
+  
+  /* setup header */
+  [_rq setContentType:@"text/html"];
+
+  /* send header to client */
+  [_rq sendHttpHeader];
+  
+  /* send body to client */
+  [_rq rputs:"<h3>\n"];
+  [_rq rputs:"echo !"];
+  [_rq rputs:"</h3>\n"];
+  
+  s = [cfg stringValue];
+  if ([s length] > 0)
+    [_rq rputs:[s cString]];
+  [_rq rputs:"<br />\n\n"];
+  
+  [_rq rputs:"<b>URI:</b><pre>"];
+  [_rq rputs:[[_rq uri] cString]];
+  [_rq rputs:"</pre>\n"];
+  
+  [_rq rputs:"<b>description:</b><pre>"];
+  [_rq rputs:[[_rq description] cString]];
+  [_rq rputs:"</pre>\n"];
+
+  [_rq rputs:"<b>headers-in:</b><pre>"];
+  [_rq rputs:[[[_rq headersIn] description] cString]];
+  [_rq rputs:"</pre>\n"];
+
+  [_rq rputs:"<b>headers-in-dict:</b><pre>"];
+  [_rq rputs:[[[[_rq headersIn] asDictionary] description] cString]];
+  [_rq rputs:"</pre>\n"];
+
+  RELEASE(pool);
+  
+  /* say we are done ... */
+  return ApacheHandledRequest;
+}
+
+@end /* ApacheWO(EchoHandler) */
diff --git a/Recycler/ApacheWO/ApacheWO+Echo2.m b/Recycler/ApacheWO/ApacheWO+Echo2.m
new file mode 100644 (file)
index 0000000..97db9ee
--- /dev/null
@@ -0,0 +1,65 @@
+// $Id: ApacheWO+Echo2.m,v 1.1 2004/06/14 15:02:00 helge Exp $
+
+#include "ApacheWO.h"
+#include "AWODirectoryConfig.h"
+#include "ApacheResourceManager.h"
+#include "WORequest+Apache.h"
+#include "WOResponse+Apache.h"
+#include <ApacheAPI/ApacheRequest.h>
+#include "common.h"
+
+@implementation ApacheWO(Echo2Handler)
+
+- (WOResponse *)echoResponseForRequest:(WORequest *)woRequest
+  apacheRequest:(ApacheRequest *)_rq
+  config:(id)cfg
+{
+  WOResponse *woResponse;
+  
+  [self logWithFormat:@"generated response was <nil> .."];
+  woResponse = [[[WOResponse alloc] initWithRequest:woRequest] autorelease];
+  
+  /* construct response */
+  
+  [woResponse setHeader:@"text/html" forKey:@"content-type"];
+  [woResponse appendContentString:@"<h3>WOResponse Content</h3>"];
+  
+  [woResponse appendContentHTMLString:[cfg stringValue]];
+  [woResponse appendContentString:@"<br />\n\n"];
+  
+  [woResponse appendContentString:@"<b>URI:</b><pre>"];
+  [woResponse appendContentHTMLString:[woRequest uri]];
+  [woResponse appendContentString:@"</pre>\n"];
+  
+  [woResponse appendContentString:@"<b>Description:</b><pre>"];
+  [woResponse appendContentHTMLString:[woRequest description]];
+  [woResponse appendContentString:@"</pre>\n"];
+  
+  [woResponse appendContentString:@"<b>Request Headers:</b><pre>"];
+  [woResponse appendContentHTMLString:[[woRequest headers] description]];
+  [woResponse appendContentString:@"</pre>\n"];
+
+  [woResponse appendApacheResponseInfo:
+                [_rq subRequestLookupURI:@"/docs/subdir/test.wox"]];
+  [woResponse appendContentString:@"<br />"];
+  
+  [woResponse appendApacheResponseInfo:
+                [_rq subRequestLookupFile:@"test.wox"]];
+  [woResponse appendContentString:@"<br />"];
+  
+  [woResponse appendApacheResponseInfo:
+                [_rq subRequestLookupURI:@"/docs/subdir/non_existent.wox"]];
+  [woResponse appendContentString:@"<br />"];
+
+  [woResponse appendApacheResponseInfo:
+                [_rq subRequestLookupURI:@"/docs/subdir/"]];
+  [woResponse appendContentString:@"<br />"];
+  
+  [woResponse appendApacheResponseInfo:
+                [_rq subRequestLookupURI:@"/docs/bigimg.gif"]];
+  [woResponse appendContentString:@"<br />"];
+
+  return woResponse;
+}
+
+@end /* ApacheWO(Echo2Handler) */
diff --git a/Recycler/ApacheWO/ApacheWO+RequestHandler.m b/Recycler/ApacheWO/ApacheWO+RequestHandler.m
new file mode 100644 (file)
index 0000000..3c84f8b
--- /dev/null
@@ -0,0 +1,83 @@
+// $Id: ApacheWO+RequestHandler.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheWO.h"
+#include "AWODirectoryConfig.h"
+#include "ApacheResourceManager.h"
+#include "WORequest+Apache.h"
+#include "WOResponse+Apache.h"
+#include "common.h"
+#include <NGObjWeb/WOApplication.h>
+#include <NGObjWeb/WORequestHandler.h>
+#include <ApacheAPI/ApacheAPI.h>
+
+/*
+  implements a WORequestHandler "dispatcher"
+  
+  All WORequestHandler classes are registered in the ApacheHandlers.plist
+  with the single dispatchRequest: selector. This method creates an object
+  of the request handler class and let it dispatch the request.
+*/
+
+@implementation ApacheWO(RequestHandler)
+
+- (int)dispatchRequest:(ApacheRequest *)_rq
+  usingHandlerNamed:(NSString *)_hname
+  inApplication:(WOApplication *)_app
+{
+  WORequestHandler *handler;
+  WORequest  *woRequest;
+  WOResponse *woResponse;
+  int        result;
+  
+  if ((handler = [_app requestHandlerForKey:_hname]) == nil) {
+    [self logWithFormat:@"did not find request handler for key '%@'", 
+           _hname];
+    return ApacheDeclineRequest;
+  }
+  
+  woRequest = [[[WORequest alloc] initWithApacheRequest:_rq] autorelease];
+  
+  woResponse = [_app dispatchRequest:woRequest usingHandler:handler];
+  
+  /* send response */
+  
+  if (woResponse)
+    result = [woResponse sendResponseUsingApacheRequest:_rq];
+  else
+    result = 500;
+
+  return result;
+}
+
+- (int)dispatchRequestHandler:(ApacheRequest *)_rq {
+  NSAutoreleasePool  *pool;
+  AWODirectoryConfig *cfg;
+  WOApplication    *app;
+  int result;
+  
+  if (_rq == NULL)
+    return ApacheDeclineRequest;
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  
+  /* get directory specific info (app, request-handler) ! */
+  
+  cfg = [self configForDirectory:_rq];
+  
+  if ((app = [cfg application]) == nil) {
+    [self logWithFormat:@"missing app .."];
+    goto done;
+  }
+  
+  result = [self dispatchRequest:_rq
+                usingHandlerNamed:[_rq handler]
+                inApplication:app];
+  
+ done:
+  RELEASE(pool);
+  
+  /* say we are done ... */
+  return result;
+}
+
+@end /* ApacheWO(WoxPageHandler) */
diff --git a/Recycler/ApacheWO/ApacheWO+hooks.m b/Recycler/ApacheWO/ApacheWO+hooks.m
new file mode 100644 (file)
index 0000000..7072cf9
--- /dev/null
@@ -0,0 +1,76 @@
+// $Id: ApacheWO+hooks.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheWO.h"
+#include "AliasMap.h"
+#include "AWOServerConfig.h"
+#include <ApacheAPI/ApacheRequest.h>
+#include <ApacheAPI/ApacheTable.h>
+#include "common.h"
+
+@implementation ApacheWO(Hooks)
+
+- (int)handleTranslationForRequest:(ApacheRequest *)_rq {
+  AWOServerConfig *cfg;
+  NSString *uri = [_rq uri];
+  NSString *app, *rqh;
+  
+  cfg = [self configForServer:_rq];
+  
+  //[self logWithFormat:@"translate URI '%@' (cfg=%@) ...", uri, cfg];
+  
+  /* check handler aliases */
+  
+  if ((rqh = [cfg->handlerAlias keyForURI:uri])) {
+    NSString *prefix;
+    
+    prefix = [cfg->handlerAlias uriForKey:rqh baseURI:uri];
+    //[self logWithFormat:@"found handler: %@ (prefix=%@)", rqh, prefix];
+    
+    [_rq setFilename:prefix];
+    [_rq setPathInfo:[uri substringFromIndex:[prefix length]]];
+    [_rq setHandler:@"sx-alias-handler"];
+    return ApacheHandledRequest;
+  }
+  
+  /* check app aliases */
+  
+  if ((app = [cfg->appAlias keyForURI:uri])) {
+    NSString *prefix;
+    
+    prefix = [cfg->appAlias uriForKey:app baseURI:uri];
+    [self logWithFormat:@"found app: %@ (prefix=%@)", app, prefix];
+    
+    [_rq setFilename:prefix];
+    [_rq setPathInfo:[uri substringFromIndex:[prefix length]]];
+    [_rq setHandler:@"sx-application"];
+    return ApacheHandledRequest;
+  }
+  
+  return ApacheDeclineRequest;
+}
+
+#if 0
+- (int)checkUserIdFromRequest:(ApacheRequest *)_req {
+  [self logWithFormat:@"check uid for URI '%@' ...", [_req uri]];
+  return ApacheDeclineRequest;
+}
+#endif
+
+- (int)checkTypeForRequest:(ApacheRequest *)_req {
+  /* do not process .wo directories as simple directories .. */
+  
+  //[self logWithFormat:@"check type for URI '%@' ...", [_req uri]];
+  
+  if ([_req isDirectory]) {
+    NSString *fext;
+    
+    fext = [[[_req filename] lastPathComponent] pathExtension];
+    if ([fext isEqualToString:@"wo"]) {
+      [_req setContentType:@"application/x-httpd-wo"];
+      return ApacheHandledRequest;
+    }
+  }
+  return ApacheDeclineRequest;
+}
+
+@end /* ApacheWO(Hooks) */
diff --git a/Recycler/ApacheWO/ApacheWO+woxpage.m b/Recycler/ApacheWO/ApacheWO+woxpage.m
new file mode 100644 (file)
index 0000000..a106a7d
--- /dev/null
@@ -0,0 +1,144 @@
+// $Id: ApacheWO+woxpage.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheWO.h"
+#include "AliasMap.h"
+#include "WORequestHandler+Apache.h"
+#include "AWODirectoryConfig.h"
+#include "AWOServerConfig.h"
+#include "ApacheWOTransaction.h"
+#include "ApacheResourceManager.h"
+#include "WORequest+Apache.h"
+#include "WOResponse+Apache.h"
+#include "common.h"
+#include <NGObjWeb/WOApplication.h>
+#include <NGObjWeb/WORequestHandler.h>
+#include <ApacheAPI/ApacheAPI.h>
+
+@interface WORequest(UsedPrivatesApache)
+- (void)setRequestHandlerPath:(NSString *)_path;
+- (ApacheRequest *)apacheRequest;
+@end
+
+@interface ApacheWO(EchoResponseE)
+- (WOResponse *)echoResponseForRequest:(WORequest *)woRequest
+  apacheRequest:(ApacheRequest *)_rq
+  config:(id)cfg;
+@end
+
+@implementation ApacheWO(WoxPageHandler)
+
+- (int)performSxApplicationRequest:(ApacheRequest *)_rq {
+  AWOServerConfig   *cfg;
+  NSString          *uri = [_rq uri];
+  NSString          *appKey;
+  WOApplication     *app;
+  WORequest         *woRequest;
+  WOResponse        *woResponse;
+  int result;
+  
+  if (uri == nil)
+    return ApacheDeclineRequest;
+  
+  woRequest = [[[WORequest alloc] initWithApacheRequest:_rq] autorelease];
+  
+  cfg    = [self configForServer:_rq];
+  appKey = [cfg->appAlias keyForURI:uri];
+  app    = [ApacheWO applicationForKey:appKey className:nil];
+  
+  [self logWithFormat:@"performSxApplicationRequest on app %@ ...", app];
+  woResponse = [app dispatchRequest:woRequest];
+  
+  /* send response */
+  
+  if (woResponse)
+    result = [woResponse sendResponseUsingApacheRequest:_rq];
+  else
+    result = 500;
+  
+  return result;
+}
+
+- (int)performSxHandlerRequest:(ApacheRequest *)_rq
+  config:(AWODirectoryConfig *)cfg 
+{
+  WORequestHandler *handler;
+  
+  if ((handler = [cfg requestHandler]) == nil) {
+    handler = [[cfg application] defaultRequestHandler];
+    [self logWithFormat:@"using default request handler ..."];
+  }
+  
+  return [[self currentWOTransaction] dispatchUsingHandler:handler];
+}
+
+- (int)performSxAliasHandlerRequest:(ApacheRequest *)_rq {
+  ApacheWOTransaction *tx;
+  WORequestHandler *handler;
+  NSString *key;
+  
+  tx      = [self currentWOTransaction];
+  key     = [tx->serverConfig->handlerAlias keyForURI:[_rq uri]];
+  handler = [[tx application] requestHandlerForKey:key];
+  
+  return [tx dispatchUsingHandler:handler];
+}
+
+- (int)performWoxPageRequest:(ApacheRequest *)_rq {
+  WORequestHandler *rh;
+  WORequest *woRq;
+  
+  rh = [[[NSClassFromString(@"WOPageRequestHandler") alloc] init] autorelease];
+  if (rh == nil)
+    [self logWithFormat:@"couldn't allocate page request handler  .."];
+  
+  /* fill request special vars */
+  woRq = [[self currentWOTransaction] request];
+  [woRq setHeader: [woRq uri] forKey:@"x-httpd-pagename"];
+  [woRq setRequestHandlerPath:[[woRq uri] lastPathComponent]];
+  
+  return [[self currentWOTransaction] dispatchUsingHandler:rh];
+}
+
+- (int)handleApplicationXHttpdWoRequest:(ApacheRequest *)_rq config:_cfg {
+  NSString *uri = [_rq uri];
+  
+  [self logWithFormat:@"handleApplicationXHttpdWoxRequest (uri=%@) ...",uri];
+  
+  /* remove the slash of .wo directories, deny access to contents .. */
+  if ([uri hasSuffix:@".wo/"]) {
+    uri = [uri substringToIndex:([uri length] - 1)];
+    [self logWithFormat:@"redirect to %@...", uri];
+    
+    [[_rq headersOut] setObject:uri forKey:@"location"];
+    [_rq setStatus:302];
+    [_rq sendHttpHeader];
+    return ApacheHandledRequest; /* redirect */
+  }
+  
+  return [self performWoxPageRequest:_rq];
+}
+
+- (int)handleSkyrixRqHandler:(ApacheRequest *)_rq config:(id)_cfg {
+  NSDictionary     *plist;
+  WORequestHandler *rh;
+  
+  plist = [NSDictionary dictionaryWithContentsOfFile:[_rq filename]];
+  [self logWithFormat:@"plist: %@", plist];
+  
+  if ((rh = [WORequestHandler requestHandlerForConfig:plist]) == nil)
+    return ApacheDeclineRequest;
+  
+  return [[self currentWOTransaction] dispatchUsingHandler:rh];
+}
+
+- (int)handleDirectoryRequest:(ApacheRequest *)_rq config:(id)_cfg {
+  [self logWithFormat:@"check directory: %@", [_rq filename]];
+  return ApacheDeclineRequest;
+}
+- (int)handleGenericRequest:(ApacheRequest *)_rq config:(id)_cfg {
+  [self logWithFormat:@"(generic) check file: %@ (%@)", 
+         [_rq filename], [_rq contentType]];
+  return ApacheDeclineRequest;
+}
+
+@end /* ApacheWO(WoxPageHandler) */
diff --git a/Recycler/ApacheWO/ApacheWO.h b/Recycler/ApacheWO/ApacheWO.h
new file mode 100644 (file)
index 0000000..5ddbb85
--- /dev/null
@@ -0,0 +1,30 @@
+// $Id: ApacheWO.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __ApacheWOMod_H__
+#define __ApacheWOMod_H__
+
+#include <ApacheAPI/ApacheModule.h>
+
+@class NSString, NSMutableArray;
+@class WOApplication;
+@class ApacheWOTransaction;
+
+@interface ApacheWO : ApacheModule
+{
+  NSMutableArray *woTxStack;
+}
+
+/* WO transactions */
+
+- (ApacheWOTransaction *)currentWOTransaction;
+
+/* application management */
+
++ (WOApplication *)applicationForKey:(NSString *)_key
+  className:(NSString *)_className;
+
+@end
+
+#include "ApacheWOTransaction.h"
+
+#endif /* __ApacheWOMod_H__ */
diff --git a/Recycler/ApacheWO/ApacheWO.m b/Recycler/ApacheWO/ApacheWO.m
new file mode 100644 (file)
index 0000000..9e69d6b
--- /dev/null
@@ -0,0 +1,115 @@
+// $Id: ApacheWO.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheWO.h"
+#include "common.h"
+#include <ApacheAPI/ApacheAPI.h>
+#include <NGObjWeb/WOApplication.h>
+#include <NGObjWeb/WORequestHandler.h>
+
+@interface WOApplication(UsedPrivates)
+- (id)initWithName:(NSString *)_name;
+@end
+
+@implementation ApacheWO
+
+- (id)init {
+  if ((self = [super init])) {
+    self->woTxStack = [[NSMutableArray alloc] initWithCapacity:4];
+  }
+  return self;
+}
+- (void)dealloc {
+  RELEASE(self->woTxStack);
+  [super dealloc];
+}
+
+/* transactions */
+
+- (ApacheWOTransaction *)currentWOTransaction {
+  if ([self->woTxStack count] == 0) return nil;
+  return [self->woTxStack lastObject];
+}
+
+- (BOOL)willDispatchRequest:(ApacheRequest *)_rq {
+  /* this is called before a handler is invoked */
+  ApacheWOTransaction *tx;
+  
+  if (![super willDispatchRequest:_rq])
+    return NO;
+  
+  tx = [[ApacheWOTransaction alloc] 
+        initWithApacheRequest:_rq 
+        config:[self configForDirectory:_rq]
+        serverConfig:[self configForServer:_rq]];
+  if (tx == nil)
+    return NO;
+  
+  //[self logWithFormat:@"pushing WO transaction: %@", tx];
+  
+  [self->woTxStack addObject:tx];
+  
+  [tx activate];
+  
+  RELEASE(tx);
+  return YES;
+}
+
+- (void)didDispatchRequest:(ApacheRequest *)_rq {
+  /* this is called after a handler was invoked */
+  unsigned idx;
+  ApacheWOTransaction *tx;
+  
+  if ((idx = [self->woTxStack count]) == 0) {
+    [self logWithFormat:
+           @"tx stack broken, tried to pop tx from empty stack !"];
+    return;
+  }
+  idx--;
+  
+  tx = RETAIN([self->woTxStack objectAtIndex:idx]);
+  //[self logWithFormat:@"popping WO transaction: %@.", tx];
+  [tx deactivate];
+  [self->woTxStack removeObjectAtIndex:idx];
+  RELEASE(tx);
+}
+
+/* application management */
+
++ (WOApplication *)applicationForKey:(NSString *)_key
+  className:(NSString *)_className
+{
+  static NSMutableDictionary *keyToApp = nil; // THREAD
+  WOApplication *app;
+  Class clazz;
+  
+  if (keyToApp == nil)
+    keyToApp = [[NSMutableDictionary alloc] initWithCapacity:16];
+  
+  if ((app = [keyToApp objectForKey:_key]))
+    return app;
+  
+  if (_className == nil) _className = @"WOApplication";
+  if ((clazz = NSClassFromString(_className)) == nil) {
+    [self logWithFormat:@"did not find class named '%@'", _className];
+    return nil;
+  }
+  
+  if ((app = [[clazz alloc] initWithName:_key]) == nil) {
+    [self logWithFormat:
+            @"couldn't create instance for application of class %@",
+            clazz];
+    return nil;
+  }
+
+  /* resource managers are request dependend with our Apache module :-) */
+  [app setResourceManager:nil];
+  
+  //[self logWithFormat:@"added application %@ for key %@", app, _key];
+  
+  [keyToApp setObject:app forKey:_key];
+  RELEASE(app);
+  
+  return app;
+}
+
+@end /* ApacheWO */
diff --git a/Recycler/ApacheWO/ApacheWOTransaction.h b/Recycler/ApacheWO/ApacheWOTransaction.h
new file mode 100644 (file)
index 0000000..d8d6299
--- /dev/null
@@ -0,0 +1,47 @@
+// $Id: ApacheWOTransaction.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __ApacheWOTransaction_H__
+#define __ApacheWOTransaction_H__
+
+#import <Foundation/NSObject.h>
+
+@class ApacheRequest;
+@class WORequest, WOResponse, WOApplication, WORequestHandler;
+@class AWODirectoryConfig, AWOServerConfig;
+@class ApacheResourceManager;
+
+@interface ApacheWOTransaction : NSObject
+{
+@public
+  ApacheRequest         *request;
+  WORequest             *woRequest;
+  WOResponse            *woResponse;
+  AWODirectoryConfig    *config;
+  AWOServerConfig       *serverConfig;
+  WOApplication         *application;
+  ApacheResourceManager *resourceManager;
+}
+
+- (id)initWithApacheRequest:(ApacheRequest *)_rq 
+  config:(AWODirectoryConfig *)_cfg
+  serverConfig:(AWOServerConfig *)_srvcfg;
+
+/* accessors */
+
+- (WORequest *)request;
+- (WOResponse *)response;
+- (WOApplication *)application;
+- (ApacheRequest *)apacheRequest;
+
+/* activation */
+
+- (void)activate;
+- (void)deactivate;
+
+/* dispatch */
+
+- (int)dispatchUsingHandler:(WORequestHandler *)_handler;
+
+@end
+
+#endif /* __ApacheWOTransaction_H__ */
diff --git a/Recycler/ApacheWO/ApacheWOTransaction.m b/Recycler/ApacheWO/ApacheWOTransaction.m
new file mode 100644 (file)
index 0000000..1f8b234
--- /dev/null
@@ -0,0 +1,116 @@
+// $Id: ApacheWOTransaction.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "ApacheWOTransaction.h"
+#include "common.h"
+
+#include "AWODirectoryConfig.h"
+#include "AWOServerConfig.h"
+#include "ApacheResourceManager.h"
+#include "WORequest+Apache.h"
+#include "WOResponse+Apache.h"
+#include <ApacheAPI/ApacheRequest.h>
+#include <NGObjWeb/WORequest.h>
+#include <NGObjWeb/WOResponse.h>
+#include <NGObjWeb/WOApplication.h>
+
+@implementation ApacheWOTransaction
+
+- (id)initWithApacheRequest:(ApacheRequest *)_rq
+  config:(AWODirectoryConfig *)_cfg 
+  serverConfig:(AWOServerConfig *)_srvcfg
+{
+  if (_rq == nil) {
+    RELEASE(self);
+    return nil;
+  }
+  self->config       = RETAIN(_cfg);
+  self->serverConfig = RETAIN(_srvcfg);
+  self->request      = RETAIN(_rq);
+  
+  if ((self->woRequest = [[WORequest alloc] initWithApacheRequest:_rq])==nil) {
+    NSLog(@"%s: could not create WO request ...", __PRETTY_FUNCTION__);
+    RELEASE(self);
+    return nil;
+  }
+  
+  if ((self->application = [[_cfg application] retain]) == nil) {
+    NSLog(@"%s: no app is configured ...", __PRETTY_FUNCTION__);
+    RELEASE(self);
+    return nil;
+  }
+  
+  self->resourceManager =
+    [[ApacheResourceManager alloc] initWithApacheRequest:_rq config:_cfg];
+  
+  if (self->resourceManager == nil) {
+    NSLog(@"%s: could not create resource manager ...", __PRETTY_FUNCTION__);
+    RELEASE(self);
+    return nil;
+  }
+  
+  return self;
+}
+
+- (void)dealloc {
+  RELEASE(self->resourceManager);
+  RELEASE(self->woRequest);
+  RELEASE(self->woResponse);
+  RELEASE(self->application);
+  RELEASE(self->serverConfig);
+  RELEASE(self->config);
+  RELEASE(self->request);
+  [super dealloc];
+}
+
+/* accessors */
+
+- (WOApplication *)application {
+  return [self->config application];
+}
+- (WORequest *)request {
+  return self->woRequest;
+}
+- (WOResponse *)response {
+  return self->woResponse;
+}
+
+- (ApacheRequest *)apacheRequest {
+  return self->request;
+}
+
+/* activation */
+
+- (void)activate {
+  [self->application activateApplication];
+  // should use stack ??
+  [self->application setResourceManager:self->resourceManager];
+}
+- (void)deactivate {
+  [self->application setResourceManager:nil];
+  [self->application deactivateApplication];
+}
+
+/* dispatch */
+
+- (int)dispatchUsingHandler:(WORequestHandler *)_handler {
+  WOResponse *response;
+  
+  response = [self->application
+                 dispatchRequest:self->woRequest
+                 usingHandler:_handler];
+  return [response sendResponseUsingApacheRequest:self->request];
+}
+
+/* description */
+
+- (NSString *)description {
+  NSMutableString *ms;
+  
+  ms = [NSMutableString stringWithCapacity:64];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  [ms appendFormat:@" uri=%@", [[self request] uri]];
+  [ms appendString:@">"];
+  return ms;
+}
+
+@end /* ApacheWOTransaction */
diff --git a/Recycler/ApacheWO/ChangeLog b/Recycler/ApacheWO/ChangeLog
new file mode 100644 (file)
index 0000000..0c05d7e
--- /dev/null
@@ -0,0 +1,5 @@
+2004-06-14  Helge Hess  <helge.hess@skyrix.com>
+
+       * created ChangeLog
+
+
diff --git a/Recycler/ApacheWO/GNUmakefile b/Recycler/ApacheWO/GNUmakefile
new file mode 100644 (file)
index 0000000..d38c8ef
--- /dev/null
@@ -0,0 +1,46 @@
+# $Id: GNUmakefile,v 1.2 2004/06/14 15:02:00 helge Exp $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+BUNDLE_NAME = ApacheWO
+
+ApacheWO_PRINCIPAL_CLASS = ApacheWO
+BUNDLE_EXTENSION         = .apache
+
+# NOTE: Ordering seems to be important !!! (sometimes the ObjC runtime
+# doesn't find all categories ?!)
+ApacheWO_OBJC_FILES += \
+       ApacheWO+Echo.m                 \
+       ApacheWO+woxpage.m              \
+       ApacheWO+Echo2.m                \
+       ApacheWO+hooks.m                \
+       ApacheWO+RequestHandler.m       \
+       ApacheWO.m                      \
+       AWODirectoryConfig.m            \
+       AWOServerConfig.m               \
+       WORequest+Apache.m              \
+       WOResponse+Apache.m             \
+       WOComponent+Apache.m            \
+       WORequestHandler+Apache.m       \
+       ApacheResourceManager.m         \
+       AliasMap.m                      \
+       ApacheWOTransaction.m           \
+
+ApacheWO_BUNDLE_LIBS += \
+       -lApacheAPI     \
+       -lNGExtensions  \
+       -lNGObjWeb      \
+
+ApacheWO_RESOURCE_FILES = ApacheCommands.plist ApacheHandlers.plist
+
+# auto info
+
+ApacheWO_OBJC_FILES += ApacheWO_module_structure.m
+
+ApacheWO_module_structure.m :
+       $(GNUSTEP_MAKEFILES)/genApacheModule.sh ApacheWO $@
+
+after-clean ::
+       rm -f ApacheWO_module_structure.m
+
+include $(GNUSTEP_MAKEFILES)/bundle.make
diff --git a/Recycler/ApacheWO/README b/Recycler/ApacheWO/README
new file mode 100644 (file)
index 0000000..3e9fb93
--- /dev/null
@@ -0,0 +1,17 @@
+last change:
+20040608?
+
+How to start
+============
+
+First you need to tweek httpd.conf to reflect you pathes ...
+Important: you probably need to *install* the bundle before it works,
+Apache doesn't search for the bundle in the current directory ...
+
+The easiest way to start it is to invoke:
+
+# httpd -X -f $PWD/httpd.conf
+
+The -X option starts Apache in single-process mode (no children are
+forked) and the -f specifies the local server config file. Note that
+the server config file needs to be specified as an absolute path.
diff --git a/Recycler/ApacheWO/TestApp/GNUmakefile b/Recycler/ApacheWO/TestApp/GNUmakefile
new file mode 100644 (file)
index 0000000..5cc2241
--- /dev/null
@@ -0,0 +1,12 @@
+# $Id: GNUmakefile,v 1.1 2004/06/14 14:59:26 helge Exp $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+BUNDLE_NAME = TestApp
+
+TestApp_OBJC_FILES = \
+       TestApp.m       \
+
+TestApp_RESOURCE_FILES = \
+
+include $(GNUSTEP_MAKEFILES)/bundle.make
diff --git a/Recycler/ApacheWO/TestApp/TestApp.m b/Recycler/ApacheWO/TestApp/TestApp.m
new file mode 100644 (file)
index 0000000..2b7fbb7
--- /dev/null
@@ -0,0 +1,9 @@
+// $Id: TestApp.m,v 1.1 2004/06/14 14:59:26 helge Exp $
+
+#include <NGObjWeb/WOApplication.h>
+
+@interface TestApp : WOApplication
+@end
+
+@implementation TestApp
+@end
diff --git a/Recycler/ApacheWO/WOComponent+Apache.m b/Recycler/ApacheWO/WOComponent+Apache.m
new file mode 100644 (file)
index 0000000..149e813
--- /dev/null
@@ -0,0 +1,35 @@
+// $Id: WOComponent+Apache.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include <NGObjWeb/WOComponent.h>
+#include <NGObjWeb/WOContext.h>
+#include <NGObjWeb/WORequest.h>
+#include <ApacheAPI/ApacheRequest.h>
+#include "common.h"
+
+@interface WOContext(Apache)
+- (ApacheRequest *)apacheRequest;
+@end
+
+@implementation WOContext(Apache)
+
+- (ApacheRequest *)apacheRequest {
+  return [[[self  request] userInfo] objectForKey:@"ApacheRequest"];
+}
+
+- (id)_jsprop_apacheRequest {
+  return [self apacheRequest];
+}
+
+@end /* WOContext(Apache) */
+
+@implementation WOComponent(Apache)
+
+- (ApacheRequest *)apacheRequest {
+  return [[self context] apacheRequest];
+}
+
+- (id)_jsprop_apacheRequest {
+  return [self apacheRequest];
+}
+
+@end /* WOComponent(Apache) */
diff --git a/Recycler/ApacheWO/WORequest+Apache.h b/Recycler/ApacheWO/WORequest+Apache.h
new file mode 100644 (file)
index 0000000..91c6407
--- /dev/null
@@ -0,0 +1,16 @@
+// $Id: WORequest+Apache.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __WORequest_Apache_H__
+#define __WORequest_Apache_H__
+
+#include <NGObjWeb/WORequest.h>
+
+@class ApacheRequest;
+
+@interface WORequest(Apache)
+
+- (id)initWithApacheRequest:(ApacheRequest *)_rq;
+
+@end /* WORequest(Apache) */
+
+#endif /* __WORequest_Apache_H__ */
diff --git a/Recycler/ApacheWO/WORequest+Apache.m b/Recycler/ApacheWO/WORequest+Apache.m
new file mode 100644 (file)
index 0000000..ef8c538
--- /dev/null
@@ -0,0 +1,117 @@
+// $Id: WORequest+Apache.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "WORequest+Apache.h"
+#include <ApacheAPI/ApacheRequest.h>
+#include <ApacheAPI/ApacheTable.h>
+#include <ApacheAPI/ApacheConnection.h>
+#include "common.h"
+
+@interface WORequest(ApachePrivates)
+
+- (NSData *)readDataFromApacheRequest:(ApacheRequest *)_rq;
+
+@end
+
+@implementation WORequest(Apache)
+
+- (id)initWithApacheRequest:(ApacheRequest *)_rq {
+  NSMutableDictionary *headers;
+  NSAutoreleasePool *pool;
+  NSString     *httpVersion = nil;
+  NSData       *contentData;
+  NSDictionary *ui;
+  NGHashMap    *form;
+  
+  if (_rq == nil) {
+    RELEASE(self);
+    return nil;
+  }
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  headers = [[NSMutableDictionary alloc] initWithCapacity:32];
+  
+  /* the values need to be parsed ! */
+  {
+    ApacheTable  *hin;
+    NSEnumerator *keys;
+    NSString     *key;
+    
+    hin = [_rq headersIn];
+    keys = [hin keyEnumerator];
+    while ((key = [keys nextObject])) {
+      NSString *value;
+      
+      if ((value = [hin objectForKey:key]) == nil) {
+        [self logWithFormat:@"got no value for key '%@' ..", key];
+        continue;
+      }
+      
+      /* NGObjWeb expects all keys to be lowercase .. */
+      key = [key lowercaseString];
+      [headers setObject:value forKey:key];
+    }
+  }
+  
+  /* setup "special" headers */
+  {
+    ApacheConnection *con = [_rq connection];
+    NSString *tmp;
+    
+    if ((tmp = [headers objectForKey:@"host"])) {
+      tmp = [@"http://" stringByAppendingString:tmp];
+      [headers setObject:tmp forKey:@"x-webobjects-server-url"];
+    }
+    if ([(tmp = [con remoteHost]) length] > 0)
+      [headers setObject:tmp forKey:@"x-webobjects-remote-host"];
+    if ([(tmp = [con user]) length] > 0)
+      [headers setObject:tmp forKey:@"x-webobjects-remote-user"];
+    if ([(tmp = [con authorizationType]) length] > 0)
+      [headers setObject:tmp forKey:@"x-webobjects-auth-type"];
+  }
+  
+  /* content, this is to be done ... (libapr ?, hm) */
+  contentData = [self readDataFromApacheRequest:_rq];
+  
+  /* userinfo */
+  
+  ui = [NSDictionary dictionaryWithObject:_rq forKey:@"ApacheRequest"];
+  
+  /* form values */
+  
+  {
+    const char *cstr = [[_rq unparsedURI] cString];
+    const char *pos  = index(cstr, '?');
+    
+    if (pos) {
+      pos++;
+      form = NGDecodeUrlFormParameters(pos, strlen(pos));
+    }
+    else
+      form = nil;
+  }
+  
+  /* construct */
+  
+  self = [self initWithMethod:[_rq method]
+               uri:[_rq uri]
+               httpVersion:httpVersion
+               headers:headers
+               content:contentData
+               userInfo:ui];
+  ASSIGN(self->formContent, form);
+  
+  RELEASE(headers);
+  RELEASE(pool);
+  return self;
+}
+
+- (NSData *)readDataFromApacheRequest:(ApacheRequest *)_rq {
+#warning read request content if available ...
+  return nil;
+}
+
+- (ApacheRequest *)apacheRequest {
+  return [[self userInfo] objectForKey:@"ApacheRequest"];
+}
+
+@end /* WORequest(Apache) */
diff --git a/Recycler/ApacheWO/WORequestHandler+Apache.h b/Recycler/ApacheWO/WORequestHandler+Apache.h
new file mode 100644 (file)
index 0000000..2af89dc
--- /dev/null
@@ -0,0 +1,17 @@
+// $Id: WORequestHandler+Apache.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __WORequestHandler_ApacheExt_H__
+#define __WORequestHandler_ApacheExt_H__
+
+#include <NGObjWeb/WORequestHandler.h>
+
+@class NSDictionary;
+
+@interface WORequestHandler(ApacheExt)
+
++ (WORequestHandler *)requestHandlerForConfig:(NSDictionary *)_plist;
+- (id)initWithConfig:(NSDictionary *)_cfg;
+
+@end
+
+#endif /* __WORequestHandler_ApacheExt_H__ */
diff --git a/Recycler/ApacheWO/WORequestHandler+Apache.m b/Recycler/ApacheWO/WORequestHandler+Apache.m
new file mode 100644 (file)
index 0000000..0c9096b
--- /dev/null
@@ -0,0 +1,28 @@
+// $Id: WORequestHandler+Apache.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "WORequestHandler+Apache.h"
+#include "common.h"
+
+@implementation WORequestHandler(ApacheExt)
+
+- (id)initWithConfig:(NSDictionary *)_cfg {
+  return [self init];
+}
+
++ (WORequestHandler *)requestHandlerForConfig:(NSDictionary *)_plist {
+  NSString *className;
+  Class    clazz;
+  
+  className = [_plist objectForKey:@"class"];
+  if ([className length] == 0)
+    return nil;
+  
+  if ((clazz = NSClassFromString(className)) == Nil) {
+    [self logWithFormat:@"did not find request handler class %@", className];
+    return nil;
+  }
+  
+  return [[[clazz alloc] initWithConfig:_plist] autorelease];
+}
+
+@end /* WORequestHandler(ApacheExt) */
diff --git a/Recycler/ApacheWO/WOResponse+Apache.h b/Recycler/ApacheWO/WOResponse+Apache.h
new file mode 100644 (file)
index 0000000..28eda79
--- /dev/null
@@ -0,0 +1,20 @@
+// $Id: WOResponse+Apache.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#ifndef __WOResponse_Apache_H__
+#define __WOResponse_Apache_H__
+
+#include <NGObjWeb/WOResponse.h>
+
+@class ApacheRequest;
+
+@interface WOResponse(Apache)
+
+- (int)sendResponseUsingApacheRequest:(ApacheRequest *)_rq;
+
+@end /* WOResponse(Apache) */
+
+@interface WOResponse(ApacheInfo)
+- (void)appendApacheResponseInfo:(ApacheRequest *)_request;
+@end
+
+#endif /* __WOResponse_Apache_H__ */
diff --git a/Recycler/ApacheWO/WOResponse+Apache.m b/Recycler/ApacheWO/WOResponse+Apache.m
new file mode 100644 (file)
index 0000000..48f201c
--- /dev/null
@@ -0,0 +1,146 @@
+// $Id: WOResponse+Apache.m,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#include "WOResponse+Apache.h"
+#include <ApacheAPI/ApacheRequest.h>
+#include <ApacheAPI/ApacheModule.h>
+#include <ApacheAPI/ApacheTable.h>
+#include "common.h"
+
+@implementation WOResponse(Apache)
+
+- (BOOL)applyHeadersOnApacheRequest:(ApacheRequest *)_rq {
+  static NSMutableSet *ignoredHeaders = nil;
+  ApacheTable  *apHeaders;
+  NSString     *ctype;
+  NSEnumerator *keys;
+  NSString     *key;
+  
+  if (_rq == nil)
+    return NO;
+  
+  if (ignoredHeaders == nil) {
+    ignoredHeaders = [[NSMutableSet alloc] initWithObjects:
+                                            @"content-type",
+                                            nil];
+  }
+  
+  if ((ctype = [self headerForKey:@"content-type"]))
+    [_rq setContentType:ctype];
+  
+  /* apply all headers ... */
+  
+  apHeaders = [_rq headersOut];
+  
+  keys = [[self headerKeys] objectEnumerator];
+  while ((key = [keys nextObject])) {
+    NSString *svalue;
+    
+    if ([ignoredHeaders containsObject:key])
+      continue;
+    
+    svalue = [[self headersForKey:key] componentsJoinedByString:@", "];
+    [apHeaders setObject:svalue forKey:key];
+  }
+  return YES;
+}
+
+- (int)sendContentUsingApacheRequest:(ApacheRequest *)_rq {
+  return [_rq rwriteData:[self content]];
+}
+
+- (int)sendResponseUsingApacheRequest:(ApacheRequest *)_rq {
+  NSAutoreleasePool *pool;
+  int result;
+  
+  result = [self status];
+  
+  pool = [[NSAutoreleasePool alloc] init];
+
+  [_rq setStatus:[self status]];
+  
+  if (![self applyHeadersOnApacheRequest:_rq])
+    result = 500;
+  else {
+#if DONT_SEND_CONTENT_IN_SUBREQUESTS
+    if ([_rq mainRequest]) {
+      [self logWithFormat:@"is subrequest (no content is send) ..."];
+    }
+    else {
+#endif
+      [_rq sendHttpHeader];
+      
+      if (![_rq isHeadRequest])
+       result = [self sendContentUsingApacheRequest:_rq];
+#if DONT_SEND_CONTENT_IN_SUBREQUESTS
+    }
+#endif
+  }
+  
+  RELEASE(pool);
+  return ApacheHandledRequest;
+}
+
+@end /* WOResponse(Apache) */
+
+@implementation WOResponse(ApacheAppend)
+
+- (void)appendApacheResponseInfo:(ApacheRequest *)_request {
+  [self appendContentString:@"<table border='1' width=\"100%\">"];
+
+#if 0
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>Description:</td><td><pre>"];
+  [self appendContentHTMLString:[_request description]];
+  [self appendContentString:@"</pre></td></tr>"];
+#endif
+
+  [self appendContentString:
+          @"<tr><td width='25%' valign='top' align='right'>Status:</td><td>"];
+  [self appendContentHTMLString:[NSString stringWithFormat:@"%i",[_request status]]];
+  [self appendContentString:@"</td></tr>"];
+  
+  [self appendContentString:
+          @"<tr><td width='25%' valign='top' align='right'>unparsed URI:</td><td>"];
+  [self appendContentHTMLString:[_request unparsedURI]];
+  [self appendContentString:@"</td></tr>"];
+  
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>URI:</td><td>"];
+  [self appendContentHTMLString:[_request uri]];
+  [self appendContentString:@"</td></tr>"];
+  
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>filename:</td><td>"];
+  [self appendContentHTMLString:[_request filename]];
+  [self appendContentString:@"</td></tr>"];
+
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>filetype:</td><td>"];
+  [self appendContentHTMLString:[_request fileType]];
+  [self appendContentString:@"</td></tr>"];
+
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>content-type:</td><td>"];
+  [self appendContentHTMLString:[_request contentType]];
+  [self appendContentString:@"</td></tr>"];
+  
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>queryargs:</td><td>"];
+  [self appendContentHTMLString:[_request queryArgs]];
+  [self appendContentString:@"</td></tr>"];
+  
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>pathinfo:</td><td>"];
+  [self appendContentHTMLString:[_request pathInfo]];
+  [self appendContentString:@"</td></tr>"];
+
+  [self appendContentString:
+          @"<tr><td valign='top' align='right'>Headers:</td><td><pre>"];
+  [self appendContentHTMLString:
+          [[[_request headersOut] asDictionary] description]];
+  [self appendContentString:@"</pre></td></tr>"];
+  
+  [self appendContentString:@"</table>"];
+}
+
+@end /* WOResponse(ApacheAppend) */
diff --git a/Recycler/ApacheWO/common.h b/Recycler/ApacheWO/common.h
new file mode 100644 (file)
index 0000000..dc5d269
--- /dev/null
@@ -0,0 +1,4 @@
+// $Id: common.h,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+#import <Foundation/Foundation.h>
+#include <NGExtensions/NGExtensions.h>
diff --git a/Recycler/ApacheWO/docs/Embed.wox b/Recycler/ApacheWO/docs/Embed.wox
new file mode 100644 (file)
index 0000000..700ede6
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<span xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:var="http://www.skyrix.com/od/binding"
+      xmlns:const="http://www.skyrix.com/od/constant">
+  I'm a reusable component.
+</span>
diff --git a/Recycler/ApacheWO/docs/Frame.wox b/Recycler/ApacheWO/docs/Frame.wox
new file mode 100644 (file)
index 0000000..47ab859
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:var="http://www.skyrix.com/od/binding"
+      xmlns:const="http://www.skyrix.com/od/constant">
+  <head>
+    <title>Page: <var:string value="context.page.name"/></title>
+  </head>
+  <body bgcolor="#BBBBBB">
+    <b><var:string value="context.page.name"/></b>
+    <hr/>
+    
+    <var:component-content/>
+
+    <hr/>
+
+    <a href=".">docs</a> |
+    <a href="test.wox">test</a> |
+    <a href="requests.wox">requests</a> |
+    <a href="Page2.wox">Page2</a> |
+    <a href="Page3.wox">Page3</a> |
+    <a href="WoPage1.wo">WoPage1</a>
+  </body>
+  
+  <var:script><![CDATA[
+    var title = "<no title>";
+  ]]></var:script>
+</html>
diff --git a/Recycler/ApacheWO/docs/Page2.wox b/Recycler/ApacheWO/docs/Page2.wox
new file mode 100644 (file)
index 0000000..9c0f919
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+<var:component className="Frame" title="name"
+           xmlns="http://www.w3.org/1999/xhtml"
+           xmlns:var="http://www.skyrix.com/od/binding"
+           xmlns:const="http://www.skyrix.com/od/constant">
+  Seite 2 ...
+
+  Zur Index-Seite: <a href="/docs/">/docs</a><br/>
+  Zu test.wox: <a href="test.wox">test.wox</a><br/>
+  <br/>
+  Embed: |<var:component className="Embed"/>|
+  <br/>
+  <br/>
+  <img src="SlowMarket.gif" alt="bigimg.gif"/>
+  <hr/>
+  <img filename="SlowMarket.gif" alt="bigimg.gif"/>
+  <hr/>
+  <var:component className="imgs/SlowMarket.wox"/>
+</var:component>
diff --git a/Recycler/ApacheWO/docs/Page3.wox b/Recycler/ApacheWO/docs/Page3.wox
new file mode 100644 (file)
index 0000000..0b6c625
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version='1.0' standalone='yes'?>
+<var:component className="Frame" title="name"
+           xmlns="http://www.w3.org/1999/xhtml"
+           xmlns:var="http://www.skyrix.com/od/binding"
+           xmlns:js="http://www.skyrix.com/od/javascript"
+           xmlns:const="http://www.skyrix.com/od/constant">
+  
+  <form href="Page3.wox/add" method="post">
+    <input type="text" name="a" var:value="a"/><br/>
+    <input type="text" name="b" var:value="b"/><br/>
+    <input type="submit" name="ok" value="ok"/><br/>
+    <var:string value="c"/>
+  </form>
+  
+  <var:script><![CDATA[
+    var a = 3;
+    var b = 10;
+    var c = 0;
+    
+    function addAction() {
+      c = a + b;
+      return this;
+    }
+    function calcC() {
+      return a + b;
+    }
+  ]]></var:script>
+
+  a: <var:string value="a"/><br/>
+  b: <var:string value="b"/><br/>
+  c: <var:string value="calcC"/><br/>
+</var:component>
diff --git a/Recycler/ApacheWO/docs/RqInfo.wox b/Recycler/ApacheWO/docs/RqInfo.wox
new file mode 100644 (file)
index 0000000..425bda3
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0"?>
+<span xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:var="http://www.skyrix.com/od/binding"
+      xmlns:js="http://www.skyrix.com/od/javascript"
+      xmlns:const="http://www.skyrix.com/od/constant">
+
+  <table style="font-size: 10">
+    <tr>
+      <td colspan="6" bgcolor="#CCCCCC">
+       Info on <var:string value="rq.uri"/></td>
+    </tr>
+    
+    <tr>
+      <td valign="top" width="20%">filename</td>
+      <td colspan="5">
+       <var:string value="rq.filename"/> 
+       (<var:string value="rq.fileType"/>)
+        <var:if js:condition="rq.pathInfo.length > 0">
+         [<var:string value="rq.pathInfo"/>]
+       </var:if>
+      </td>
+    </tr>
+    <tr>
+      <td valign="top">method</td>
+      <td><var:string value="rq.method"/></td>
+      <td valign="top">status</td>
+      <td><var:string value="rq.status"/></td>
+      <td valign="top">content-type</td>
+      <td><var:string value="rq.contentType"/></td>
+    </tr>
+    <tr>
+      <td valign="top">headers-in</td>
+      <td colspan="5">
+       <table border="0" style="font-size: 8">
+        <var:foreach-key dictionary="rq.headersIn" key="header" item="value">
+         <tr>
+           <td valign="top"><var:string value="header"/></td>
+           <td><var:foreach const:count="3" js:list="value.split(',')" item="valuePart"><var:string value="valuePart"/><br/></var:foreach></td>
+         </tr>
+        </var:foreach-key>
+       </table>
+      </td>
+    </tr>
+<!--
+    <tr>
+      <td valign="top">headers-out</td>
+      <td colspan="3">
+        <var:foreach-key dictionary="rq.headersOut" key="header" item="value">
+          <li><var:string value="header"/>: <var:string value="value"/></li>
+        </var:foreach-key></td>
+    </tr>
+-->
+  </table>
+
+  <var:script>
+    var rq, value;
+    var value="";
+  </var:script>
+</span>
diff --git a/Recycler/ApacheWO/docs/SSIPage.shtml b/Recycler/ApacheWO/docs/SSIPage.shtml
new file mode 100644 (file)
index 0000000..cc0afc2
--- /dev/null
@@ -0,0 +1,17 @@
+<html>
+  <head>
+    <title>Server Side Include</title>
+  </head>
+
+  <body>
+    <h3>Server Side Include</h3>
+
+    Today is <!--#echo var="DATE_LOCAL" -->
+    <br/>
+    <br/>
+    Inluded .wox page:
+    <table border="1" width="100%"><tr><td>
+    <!--#include virtual="Page2.wox" -->
+    </td></tr></table>
+  </body>
+</html>
diff --git a/Recycler/ApacheWO/docs/SlowMarket.gif b/Recycler/ApacheWO/docs/SlowMarket.gif
new file mode 100644 (file)
index 0000000..32e5c48
Binary files /dev/null and b/Recycler/ApacheWO/docs/SlowMarket.gif differ
diff --git a/Recycler/ApacheWO/docs/Table.wox b/Recycler/ApacheWO/docs/Table.wox
new file mode 100644 (file)
index 0000000..c6e2f2e
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version='1.0' standalone='yes'?>
+<var:component className="Frame" title="name"
+           xmlns="http://www.w3.org/1999/xhtml"
+           xmlns:var="http://www.skyrix.com/od/binding"
+           xmlns:const="http://www.skyrix.com/od/constant">
+   
+   <var:table maxColumns="maxColumns" col="col" row="row" 
+              index="index" item="item"
+              list="listAsArray" horizontal="horizontal"
+              border="border">
+      (<var:string value="row"/>/<var:string value="col"/>)
+      = <var:string value="index"/>
+      <b><var:string value="item"/></b>
+   </var:table>
+   
+   <var:table maxColumns="maxColumns" col="col" row="row" 
+              index="index" item="item"
+              list="listAsArray" horizontal="horizontal"
+              border="border"
+              const:hasOwnTDs="4" width="100%">
+      <td><var:string value="row"/></td>
+      <td><var:string value="col"/></td>
+      <td><var:string value="index"/></td>
+      <td><b><var:string value="item"/></b></td>
+   </var:table>
+
+   <form var:action="self">
+     <hr/>
+     <table border="0">
+       <tr><td><i>Config Bindings</i></td></tr>
+       <tr>
+         <td>MaxColumns:</td>
+         <td><input type="text" var:value="maxColumns" size="4"/></td>
+       </tr>
+       <tr>
+         <td>Horizontal:</td>
+         <td><input type="checkbox" var:checked="horizontal"/></td>
+       </tr>
+     </table>
+     <input type="submit" var:action="self" value="apply"/>
+   </form>
+</var:component>
diff --git a/Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.html b/Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.html
new file mode 100644 (file)
index 0000000..d722e4c
--- /dev/null
@@ -0,0 +1,9 @@
+<WEBOBJECT NAME="Frame">
+  .wo based page
+
+  a: <WEBOBJECT NAME="a"></WEBOBJECT><br />
+  b: <WEBOBJECT NAME="b"></WEBOBJECT><br />
+  c: <WEBOBJECT NAME="AddAB"></WEBOBJECT><br />
+
+  Action Link to Page2: <WEBOBJECT NAME="Page2">Page2</WEBOBJECT>
+</WEBOBJECT>
diff --git a/Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.js b/Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.js
new file mode 100644 (file)
index 0000000..074205e
--- /dev/null
@@ -0,0 +1,19 @@
+
+print("setup WoPage1 ...");
+
+var a = 3;
+var b = 5;
+var c = 0;
+var txt = "Hello World !"
+
+function addAB() {
+  c = a + b;
+  return c;
+}
+
+function gotoPage2() {
+  print("goto page 2 ...");
+  var page = pageWithName("Page2");
+  print("  page: " + page);
+  return page;
+}
diff --git a/Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.wod b/Recycler/ApacheWO/docs/WoPage1.wo/WoPage1.wod
new file mode 100644 (file)
index 0000000..6c761f8
--- /dev/null
@@ -0,0 +1,18 @@
+Frame: Frame {
+  title = name;
+}
+
+AddAB: WOString {
+  value = addAB;
+}
+
+a: WOString {
+  value = a;
+}
+b: WOString {
+  value = b;
+}
+
+Page2: WOHyperlink {
+  action = gotoPage2;
+}
diff --git a/Recycler/ApacheWO/docs/bigimg.gif b/Recycler/ApacheWO/docs/bigimg.gif
new file mode 100644 (file)
index 0000000..425efe1
Binary files /dev/null and b/Recycler/ApacheWO/docs/bigimg.gif differ
diff --git a/Recycler/ApacheWO/docs/imgs/SlowMarket.wox b/Recycler/ApacheWO/docs/imgs/SlowMarket.wox
new file mode 100644 (file)
index 0000000..496eaab
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<span xmlns="http://www.w3.org/1999/xhtml"
+      xmlns:var="http://www.skyrix.com/od/binding"
+      xmlns:const="http://www.skyrix.com/od/constant">
+  <img width="220" height="65" filename="../SlowMarket.gif" alt="bigimg.gif"/>
+</span>
diff --git a/Recycler/ApacheWO/docs/renameme-.htaccess b/Recycler/ApacheWO/docs/renameme-.htaccess
new file mode 100644 (file)
index 0000000..ae03b60
--- /dev/null
@@ -0,0 +1,25 @@
+# $Id: .htaccess,v 1.1 2004/06/14 14:59:38 helge Exp $
+
+Options FollowSymLinks Indexes Includes
+
+AddIcon /icons/image2.gif .gif
+AddIcon /icons/image1.gif .wox
+AddIcon /icons/dir.gif    ^^DIRECTORY^^
+
+AddDescription "SKYRiX XML template"    .wox
+AddDescription "SKYRiX WO template"     .wo
+AddDescription "GIF Image"              .gif
+AddDescription "Server Side Include"    .shtml
+AddDescription "SKYRiX Request Handler" .rqh
+
+FancyIndexing on
+IndexOptions  FoldersFirst
+
+#IconHeight 16
+#IconWidth  16
+
+SetSxApplication app1
+
+AddType    text/html              .shtml
+AddHandler server-parsed          .shtml
+AddType    skyrix/request-handler .rqh
diff --git a/Recycler/ApacheWO/docs/requests.wox b/Recycler/ApacheWO/docs/requests.wox
new file mode 100644 (file)
index 0000000..95c46ce
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<var:component className="Frame" title="name"
+           xmlns="http://www.w3.org/1999/xhtml"
+           xmlns:var="http://www.skyrix.com/od/binding"
+           xmlns:js="http://www.skyrix.com/od/javascript"
+           xmlns:const="http://www.skyrix.com/od/constant">
+    <h3>Check Apache Internal Subrequests ..</h3>
+    
+    <table border="0">
+      <tr>
+        <td valign="top">Filename: </td>
+        <td><var:string value="apacheRequest.filename"/></td>
+      </tr>
+      <tr>
+        <td valign="top">Pathinfo: </td>
+        <td><var:string value="apacheRequest.pathInfo"/></td>
+      </tr>
+      <tr>
+        <td valign="top">ApacheRequest:</td>
+        <td><code><var:string value="apacheRequest"/></code></td>
+      </tr>
+      <tr>
+        <td valign="top">ApacheConnection:</td>
+        <td><code><var:string value="apacheRequest.connection"/></code></td>
+      </tr>
+
+      <tr>
+        <td valign="top">test.wox:</td>
+        <td><var:component className="RqInfo" rq="testRq"/></td>
+      </tr>
+      <tr>
+        <td valign="top">test.wox (file):</td>
+        <td><var:component className="RqInfo" rq="testRqFile"/></td>
+      </tr>
+      <tr>
+        <td valign="top">test.wox/add:</td>
+        <td><var:component className="RqInfo" rq="testRqAdd"/></td>
+      </tr>
+      <tr>
+        <td valign="top">WoPage1.wo:</td>
+        <td><var:component className="RqInfo" rq="testWO"/></td>
+      </tr>
+      <tr>
+        <td valign="top">blah.wo/:</td>
+        <td><var:component className="RqInfo" rq="testNo"/></td>
+      </tr>
+      <tr>
+        <td valign="top">SSIPage.shtml:</td>
+        <td><var:component className="RqInfo" rq="testSSI"/></td>
+      </tr>
+      <tr>
+        <td valign="top">/docs/:</td>
+        <td><var:component className="RqInfo" rq="docs"/></td>
+      </tr>
+      <tr>
+        <td valign="top">/docs/manage:</td>
+        <td>
+         <i>Note:</i> pathInfo doesn't work on directories :-(<br/>
+         <var:component className="RqInfo" rq="docsMg"/>
+       </td>
+      </tr>
+    </table>
+    
+    <var:script><![CDATA[
+      var rq = this.apacheRequest;
+      
+      print("run requests setup ...");
+      var testRq     = rq.subRequestLookupURI('test.wox',   'HEAD');
+      var testRqAdd  = rq.subRequestLookupURI('test.wox/add',   'HEAD');
+      var testRqFile = rq.subRequestLookupFile('test.wox');
+      var testWO     = rq.subRequestLookupURI('WoPage1.wo', 'HEAD');
+      var testNo     = rq.subRequestLookupURI('blah.wo/',   'HEAD');
+      var testSSI    = rq.subRequestLookupURI('SSIPage.shtml','HEAD');
+      var docs       = rq.subRequestLookupURI('/docs/',       'HEAD');
+      var docsMg     = rq.subRequestLookupURI('/docs/manage', 'HEAD');
+      
+      if (0) {
+        print("run test.wox as subreq ...");
+        var res = testRq.runSubRequest();
+        print("  result: " + res);
+      }
+    ]]></var:script>
+
+</var:component>
diff --git a/Recycler/ApacheWO/docs/subdir/renameme-.htaccess b/Recycler/ApacheWO/docs/subdir/renameme-.htaccess
new file mode 100644 (file)
index 0000000..e55df2c
--- /dev/null
@@ -0,0 +1,3 @@
+# $Id: .htaccess,v 1.1 2004/06/14 14:59:48 helge Exp $
+
+LogText "configured in docs/subdir/.htaccess"
diff --git a/Recycler/ApacheWO/docs/subdir/test.wox b/Recycler/ApacheWO/docs/subdir/test.wox
new file mode 100644 (file)
index 0000000..d2eb60c
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <body bgcolor="red">
+
+in subdir ...
+
+  </body>
+</html>
diff --git a/Recycler/ApacheWO/docs/test.html b/Recycler/ApacheWO/docs/test.html
new file mode 100644 (file)
index 0000000..44e1d91
--- /dev/null
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+  <head>
+    <title>My HTML Page</title>
+  </head>
+
+  <body>
+    <h1>My HTML Page</h1>
+
+
+
+    <hr>
+    <address><a href="mailto:helge.hess@skyrix.com">Helge Hess</a></address>
+<!-- Created: Mon Jun 17 21:10:15 CEST 2002 -->
+<!-- hhmts start -->
+Last modified: Mon Jun 17 21:10:16 CEST 2002
+<!-- hhmts end -->
+  </body>
+</html>
diff --git a/Recycler/ApacheWO/docs/test.wox b/Recycler/ApacheWO/docs/test.wox
new file mode 100644 (file)
index 0000000..3ac794a
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0"?>
+<var:component className="Frame" title="name"
+           xmlns="http://www.w3.org/1999/xhtml"
+           xmlns:var="http://www.skyrix.com/od/binding"
+           xmlns:js="http://www.skyrix.com/od/javascript"
+           xmlns:const="http://www.skyrix.com/od/constant">
+    <h3>Apache served .wox page</h3>
+    
+    <table border="0">
+      <tr>
+        <td>ComponentName: </td>
+        <td><var:string value="name"/></td>
+      </tr>
+      <tr>
+        <td>Filename: </td>
+        <td><var:string value="context.request.userInfo.ApacheRequest.filename"/></td>
+      </tr>
+      <tr>
+        <td>Pathinfo: </td>
+        <td><var:string value="context.request.userInfo.ApacheRequest.pathInfo"/></td>
+      </tr>
+      <tr>
+        <td>Context:</td>
+        <td><var:string value="context"/></td>
+      </tr>
+      <tr>
+        <td>Request:</td>
+        <td><var:string value="context.request"/></td>
+      </tr>
+      <tr>
+        <td>FormValues Keys:</td>
+        <td><var:string value="context.request.formValueKeys"/></td>
+      </tr>
+      <tr>
+        <td>ApacheRequest:</td>
+        <td><var:string value="context.request.userInfo.ApacheRequest"/></td>
+      </tr>
+      <tr>
+        <td>ApacheConnection:</td>
+        <td><var:string value="context.request.userInfo.ApacheRequest.connection"/></td>
+      </tr>
+    </table>
+
+    <!-- var:script>print('init test');</var:script -->
+
+</var:component>
diff --git a/Recycler/ApacheWO/docs/wa.rqh b/Recycler/ApacheWO/docs/wa.rqh
new file mode 100644 (file)
index 0000000..3eef00e
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  class = "WODirectActionRequestHandler";
+}
diff --git a/Recycler/ApacheWO/docs/xmlrpc.rqh b/Recycler/ApacheWO/docs/xmlrpc.rqh
new file mode 100644 (file)
index 0000000..b5d4a93
--- /dev/null
@@ -0,0 +1,3 @@
+{
+  class = "XmlRpcRequestHandler";
+}
diff --git a/Recycler/ApacheWO/httpd.conf b/Recycler/ApacheWO/httpd.conf
new file mode 100644 (file)
index 0000000..81a4a16
--- /dev/null
@@ -0,0 +1,77 @@
+# $Id: httpd.conf,v 1.1 2004/06/08 11:06:00 helge Exp $
+
+# globals
+ServerType           standalone
+ServerRoot           "/HOME/helge/mdev/SkyrixRoot"
+PidFile              /HOME/helge/mdev/SkyrixRoot/logs/httpd8090.pid
+ScoreBoardFile       /HOME/helge/mdev/SkyrixRoot/logs/httpd8090.scoreboard
+DocumentRoot         "/HOME/helge/mdev/SkyrixRoot/Library/WebServer/Documents"
+ErrorLog             /HOME/helge/mdev/SkyrixRoot/logs/error8090_log
+AccessFileName       .htaccess
+Timeout              300
+KeepAlive            On
+MaxKeepAliveRequests 100
+KeepAliveTimeout     15
+MinSpareServers      1
+MaxSpareServers      1
+StartServers         1
+MaxClients           150
+MaxRequestsPerChild  0
+ExtendedStatus       On
+Port                 8090
+User                 helge
+Group                dev
+ServerAdmin          helge.hess@skyrix.com
+HostnameLookups      Off
+ServerSignature      On
+
+# load Objective-C bundle loader ...
+
+LoadModule gsbundle_module \
+        Libraries/ix86/linux-gnu/apache/mod_gsbundle.so
+#AddModule  mod_gsbundle.c
+
+# load a bundle
+
+LoadApacheBundle  ApacheWO.apache
+#LoadSxApplication Test.sxa
+
+AddType application/x-httpd-wox .wox
+
+<Directory />
+    Options FollowSymLinks
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+</Directory>
+
+Alias /docs/ "/HOME/helge/mdev/helge/ApacheWO/docs/"
+
+<Directory "/HOME/helge/mdev/helge/ApacheWO/docs/">
+  # This may also be "None", "All", or any combination of "Indexes",
+  # "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
+  Options FollowSymLinks
+  AllowOverride All
+</Directory>
+
+<Files ".htaccess">
+  order allow,deny
+  deny from all
+</Files>
+
+<LocationMatch "^.*/CVS/$">
+  order allow,deny
+  deny from all
+</LocationMatch>
+
+<LocationMatch "/sx*">
+  SetSxApplication    lapp
+  SetSxRequestHandler WODirectActionRequestHandler
+  SetHandler sx-handler
+</LocationMatch>
+
+# Directory-Index could help ... ?
+#<LocationMatch "^.*/[a-z][a-z0-9_]*.wox/$">
+#  ForceType  application/x-httpd-wox
+#  SetHandler wox-page
+#</LocationMatch>
diff --git a/Recycler/ApacheWO/httpd.sh b/Recycler/ApacheWO/httpd.sh
new file mode 100755 (executable)
index 0000000..2fe4954
--- /dev/null
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+rm -f core
+httpd -X -f $PWD/httpd.conf 
+
diff --git a/Recycler/mod_objc/ApModuleBaseClass+Callbacks.m b/Recycler/mod_objc/ApModuleBaseClass+Callbacks.m
new file mode 100644 (file)
index 0000000..a69a718
--- /dev/null
@@ -0,0 +1,396 @@
+// $Id: ApModuleBaseClass+Callbacks.m,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#include "ApModuleBaseClass.h"
+#include <httpd.h>
+#include "http_config.h"
+#import <Foundation/NSBundle.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSAutoreleasePool.h>
+#include "ApacheServer.h"
+#include "ApacheResourcePool.h"
+#include "ApacheModule.h"
+#include "ApacheRequest.h"
+
+@implementation ApModuleBaseClass(BasicModuleCallbacks)
+
++ (void)_moduleInit:(void *)s pool:(void *)p {
+  NSAutoreleasePool *pool;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return;
+  }
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheServer       *os;
+    ApacheResourcePool *op;
+    
+    os = [[ApacheServer alloc] initWithHandle:s];
+    op = [[ApacheResourcePool alloc] initWithHandle:p];
+    [bundleHandler initializeModuleForServer:os inPool:op];
+    RELEASE(op); op = nil;
+    RELEASE(os); os = nil;
+  }
+  RELEASE(pool);
+}
+
++ (void *)_perDirConfCreate:(void *)dirspec pool:(void *)p {
+  NSAutoreleasePool *pool;
+  id result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return NULL;
+  }
+  
+  result = nil;
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheResourcePool *op;
+    
+    op = [[ApacheResourcePool alloc] initWithHandle:p];
+
+    result = [bundleHandler createPerDirectoryConfigInPool:op];
+    if (result) {
+      /* let apache release config ... */
+      RETAIN(result);
+      [op releaseObject:result];
+    }
+    
+    RELEASE(op); op = nil;
+  }
+  RELEASE(pool);
+  return result;
+}
+
++ (void *)_perDirConfMerge:(void *)baseCconf with:(void *)newCconf
+  pool:(void *)p
+{
+  NSAutoreleasePool *pool;
+  id result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return NULL;
+  }
+
+  result = nil;
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheResourcePool *op;
+    
+    op = [[ApacheResourcePool alloc] initWithHandle:p];
+
+    result = [bundleHandler mergePerDirectoryBaseConfig:baseCconf
+                            withNewConfig:newCconf
+                            inPool:op];
+    if (result) {
+      /* let apache release config ... */
+      RETAIN(result);
+      [op releaseObject:result];
+    }
+    
+    RELEASE(op); op = nil;
+  }
+  RELEASE(pool);
+  return result;
+}
+
++ (void *)_perServerConfCreate:(void *)s pool:(void *)p {
+  NSAutoreleasePool *pool;
+  id result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return NULL;
+  }
+  
+  result = nil;
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheServer       *os;
+    ApacheResourcePool *op;
+    
+    os = [[ApacheServer       alloc] initWithHandle:s];
+    op = [[ApacheResourcePool alloc] initWithHandle:p];
+
+    result = [bundleHandler createPerServerConfig:os inPool:op];
+    if (result) {
+      /* let apache release config ... */
+      RETAIN(result);
+      [op releaseObject:result];
+    }
+    
+    RELEASE(op); op = nil;
+    RELEASE(os); os = nil;
+  }
+  RELEASE(pool);
+  return result;
+}
++ (void *)_perServerConfMerge:(void *)baseConf with:(void *)newConf
+  pool:(void *)p
+{
+  NSAutoreleasePool *pool;
+  id result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return NULL;
+  }
+
+  result = nil;
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheResourcePool *op;
+    
+    op = [[ApacheResourcePool alloc] initWithHandle:p];
+    
+    result = [bundleHandler mergePerServerBaseConfig:baseConf
+                            withNewConfig:newConf
+                            inPool:op];
+    if (result) {
+      /* let apache release config ... */
+      RETAIN(result);
+      [op releaseObject:result];
+    }
+    
+    RELEASE(op); op = nil;
+  }
+  RELEASE(pool);
+  return result;
+}
+
++ (int)_translateHandler:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler handleTranslationForRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_apCheckUserId:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler checkUserIdFromRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_authChecker:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler checkAuthForRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_accessChecker:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler checkAccessForRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_typeChecker:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler checkTypeForRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_fixerUpper:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler fixupRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_logger:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler logRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
++ (int)_headerParser:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler parseHeadersOfRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
+
++ (void)_childInit:(void *)_server pool:(void *)_pool {
+  NSAutoreleasePool *pool;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return;
+  }
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheResourcePool *op;
+    ApacheServer       *sr;
+    
+    op = [[ApacheResourcePool alloc] initWithHandle:_pool];
+    sr = [[ApacheServer       alloc] initWithHandle:_server];
+    [bundleHandler initializeChildProcessWithServer:sr inPool:op];
+    RELEASE(sr);
+    RELEASE(op);
+  }
+  RELEASE(pool);
+}
++ (void)_childExit:(void *)_server pool:(void *)_pool {
+  NSAutoreleasePool *pool;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return;
+  }
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheResourcePool *op;
+    ApacheServer       *sr;
+    
+    op = [[ApacheResourcePool alloc] initWithHandle:_pool];
+    sr = [[ApacheServer       alloc] initWithHandle:_server];
+    [bundleHandler exitChildProcessWithServer:sr inPool:op];
+    RELEASE(sr);
+    RELEASE(op);
+  }
+  RELEASE(pool);
+}
+
++ (int)_postReadRequest:(void *)_request {
+  NSAutoreleasePool *pool;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return DECLINED;
+  }
+  
+  pool = [[NSAutoreleasePool alloc] init];
+  {
+    ApacheRequest *or;
+    or = [[ApacheRequest alloc] initWithHandle:_request];
+    result = [bundleHandler postProcessRequest:or];
+    RELEASE(or);
+  }
+  RELEASE(pool);
+  return result;
+}
+
+@end /* ApModuleBaseClass(BasicModuleCallbacks) */
diff --git a/Recycler/mod_objc/ApModuleBaseClass+Cmds.m b/Recycler/mod_objc/ApModuleBaseClass+Cmds.m
new file mode 100644 (file)
index 0000000..9a6684e
--- /dev/null
@@ -0,0 +1,864 @@
+// $Id: ApModuleBaseClass+Cmds.m,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#include "ApModuleBaseClass.h"
+#include <httpd.h>
+#include "http_config.h"
+#import <Foundation/NSBundle.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSAutoreleasePool.h>
+#include "ApacheServer.h"
+#include "ApacheResourcePool.h"
+#include "ApacheModule.h"
+#include "ApacheCmdParms.h"
+
+@implementation ApModuleBaseClass(ConfigCommands)
+
+static const char *configStubRaw(cmd_parms *p, void *d, char *a0);
+static const char *configStubFlag(cmd_parms *p, void *d, int flag);
+static const char *configStubTake0(cmd_parms *p, void *d);
+static const char *configStubTake1(cmd_parms *p, void *d, char *a0);
+static const char *configStubTake2(cmd_parms *p, void *d, char *a0, char *a1);
+static const char *configStubTake12(cmd_parms *p, void *d, char *a0, char *a1);
+static const char *
+  configStubTake3(cmd_parms *p, void *d, char *a0, char *a1, char *a3);
+static const char *
+  configStubTake123(cmd_parms *p, void *d, char *a0, char *a1, char *a3);
+
+static const char *
+  configStubIterate(cmd_parms *p, void *d, char *a0);
+static const char *
+  configStubIterate2(cmd_parms *p, void *d, char *a0, char *a1);
+
+static const char *serverConfigStubRaw(cmd_parms *p, void *d, char *a0);
+static const char *serverConfigStubFlag(cmd_parms *p, void *d, int flag);
+static const char *serverConfigStubTake0(cmd_parms *p, void *d);
+static const char *serverConfigStubTake1(cmd_parms *p, void *d, char *a0);
+static const char *
+  serverConfigStubTake2(cmd_parms *p, void *d, char *a0, char *a1);
+static const char *
+  serverConfigStubTake12(cmd_parms *p, void *d, char *a0, char *a1);
+static const char *
+  serverConfigStubTake3(cmd_parms *p, void *d, char *a0, char *a1, char *a3);
+static const char *
+  serverConfigStubTake123(cmd_parms *p, void *d, char *a0, char *a1, char *a3);
+
+static const char *
+  serverConfigStubIterate(cmd_parms *p, void *d, char *a0);
+static const char *
+  serverConfigStubIterate2(cmd_parms *p, void *d, char *a0, char *a1);
+
+typedef struct _ObjCmdDispatchInfo {
+  Class        moduleClass;
+  SEL          sel;
+  const char   *methodName;
+  const char   *command;
+  enum cmd_how argsHow;
+  int          location;
+  BOOL         isIterate;
+  BOOL         isFlag;
+  BOOL         isRaw;
+} ApObjCCmdDispatchInfo;
+
++ (BOOL)logConfigCommandRegistration {
+  return NO;
+}
+
++ (command_rec *)apacheCommandTable {
+  /*
+    How to map selectors to commands ?
+
+      All command selectors start with 'configure', eg:
+       
+        paras TAKE2, location ACCESS_CONF
+        - configureDirectory_ScriptAlias:(NSString *)_fake:(NSString *)_real
+          directoryConfig:(id)_cfg
+          parameters:(ApacheCmdParms *)_params;
+        
+        paras TAKE2, location RSRC_CONF
+        - configureServer_ScriptAlias:(NSString *)_fake:(NSString *)_real
+          parameters:(ApacheCmdParms *)_params;
+
+        paras TAKE1, location OR_FILEINFO
+        - configureFileInfo_PassEnv:(NSString *)_arg
+          directoryConfig:(id)_cfg
+          parameters:(ApacheCmdParms *)_params;
+        
+        paras FLAG, location OR_FILEINFO
+        - configureFileInfo_PassEnvFlag:(BOOL)_flag
+          directoryConfig:(id)_cfg
+          parameters:(ApacheCmdParms *)_params;
+        
+        paras ITERATE, location OR_INDEXES
+        - configureIndexes_DirectoryIndexIterate:(NSString *)_dir
+          directoryConfig:(id)_cfg
+          parameters:(ApacheCmdParms *)_params;
+
+      Allowed Prefixes:
+        configureDirectory_
+        configureServer_
+        configureFileInfo_
+        configureIndexes_
+    
+    Parameters:
+      RAW_ARGS,                        // cmd_func parses command line itself
+      TAKE1,                   // one argument only
+      TAKE2,                   // two arguments only
+      ITERATE,                 // one argument, occuring multiple times
+                               // (e.g., IndexIgnore)
+      ITERATE2,                        // two arguments, 2nd occurs multiple times
+                               // (e.g., AddIcon)
+      FLAG,                    // One of 'On' or 'Off'
+      NO_ARGS,                 // No args at all, e.g. </Directory>
+      TAKE12,                  // one or two arguments
+      TAKE3,                   // three arguments only
+      TAKE23,                  // two or three arguments
+      TAKE123,                 // one, two or three arguments
+      TAKE13                   // one or three arguments
+    
+    Request Overrides
+    * The allowed locations for a configuration directive are the union of
+    * those indicated by each set bit in the req_override mask.
+    *
+    * (req_override & RSRC_CONF)   => *.conf outside <Directory> or <Location>
+    * (req_override & ACCESS_CONF) => *.conf inside <Directory> or <Location>
+    * (req_override & OR_AUTHCFG)  => *.conf inside <Directory> or <Location>
+    *                                 and .htaccess when AllowOverride
+    *                                 AuthConfig
+    * (req_override & OR_LIMIT)    => *.conf inside <Directory> or <Location>
+    *                                 and .htaccess when AllowOverride Limit
+    * (req_override & OR_OPTIONS)  => *.conf anywhere
+    *                                 and .htaccess when AllowOverride Options
+    * (req_override & OR_FILEINFO) => *.conf anywhere
+    *                                 and .htaccess when AllowOverride FileInfo
+    * (req_override & OR_INDEXES)  => *.conf anywhere
+    *                                 and .htaccess when AllowOverride Indexes
+    
+    typedef struct command_struct {
+      const char *name;                // Name of this command 
+      const char *(*func) ();  // Function invoked 
+      void *cmd_data;          // Extra data, for functions which
+                               // implement multiple commands...
+      int req_override;                // What overrides need to be allowed to
+                               // enable this command.
+      enum cmd_how args_how;   // What the command expects as arguments
+
+      const char *errmsg; // 'usage' message, in case of syntax errors
+    } command_rec;
+  */
+  ApacheModule *bundleHandler = [self bundleHandler];
+  command_rec *cmdtable;
+
+  unsigned    count, capacity;
+  Class c;
+  
+  if (bundleHandler == nil)
+    return NULL;
+  
+  count    = 0;
+  capacity = 16;
+  cmdtable = calloc(capacity + 1, sizeof(command_rec));
+  
+#if GNU_RUNTIME
+  /* for the class and each superclass ... */
+  for (c = [bundleHandler class]; c != Nil; c = c->super_class) {
+    struct objc_method_list *cm;
+    
+    /* for each method list of the class */
+    for (cm = c->methods; cm != NULL; cm = cm->method_next) {
+      register unsigned i;
+      
+      /* for each method in the list */
+      for (i = 0; i < cm->method_count; i++) {
+        const char   *methodName;
+        const char   *tmp;
+        char         *tmp2, *tmp3;
+        unsigned     len, argumentCount;
+        char         *configName;
+        int          reqOverride = 0;
+        enum cmd_how argsHow = 0;
+        BOOL hasParametersArg;
+        BOOL hasDirConfigArg;
+        BOOL isIterate;
+        BOOL isFlag;
+        BOOL isRaw;
+        
+        if ((methodName = sel_get_name(cm->method_list[i].method_name))==NULL)
+          continue;
+        if (methodName[0] != 'c')
+          /* quick check for 'configure' prefix */
+          continue;
+        
+        if (strstr(methodName, "configure") != methodName)
+          /* long check for 'configure' prefix */
+          continue;
+        
+        tmp = methodName + 9;
+
+        /* search for start of config name, eg _PassEnv */
+        
+        if ((tmp2 = index(tmp, '_')) == NULL)
+          continue;
+        tmp2++; // skip underscore
+        
+        /* search for end of config name, copy config name */
+        
+        if ((tmp3 = index(tmp2, ':')) == NULL)
+          continue;
+        if ((len = (tmp3 - tmp2)) < 3)
+          /* config name to short ... */
+          continue;
+        
+        configName = malloc(len + 2);
+        memcpy(&(configName[0]), tmp2, len);
+        configName[len] = '\0';
+        
+        /* count args */
+        
+        for (argumentCount = 0; *tmp3 == ':'; tmp3++)
+          argumentCount++;
+        tmp3 = NULL;
+        
+        if (argumentCount == 0 || argumentCount > 3) {
+          printf("ERROR(%s): flag and raw configuration selectors "
+                 "only take exactly one argument (sel=%s, command=%s) !!!\n",
+                 __PRETTY_FUNCTION__, methodName, configName);
+          continue;
+        }
+        
+        /* check suffix (Iterate, Flag) */
+
+        isIterate = NO;
+        isFlag    = NO;
+        isRaw     = NO;
+        if ((tmp3 = rindex(configName, 'I'))) {
+          if (strcmp(tmp3, "Iterate") == 0) {
+            *tmp3 = '\0';
+            isIterate = YES;
+          }
+        }
+        if ((tmp3 = rindex(configName, 'F'))) {
+          if (strcmp(tmp3, "Flag") == 0) {
+            *tmp3 = '\0';
+            isFlag = YES;
+          }
+        }
+        if ((tmp3 = rindex(configName, 'R'))) {
+          if (strcmp(tmp3, "Raw") == 0) {
+            *tmp3 = '\0';
+            isRaw = YES;
+          }
+        }
+        
+        /* derive argument style info */
+        
+        if ((isFlag || isRaw) && (argumentCount != 1)) {
+          if (argumentCount != 1) {
+            printf("ERROR(%s): flag and raw configuration selectors "
+                   "only take exactly one argument (sel=%s, command=%s) !!!\n",
+                   __PRETTY_FUNCTION__, methodName, configName);
+            continue;
+          }
+        }
+        
+        if (isFlag) {
+          argsHow = FLAG;
+        }
+        else if (isIterate) {
+          if (argumentCount == 1)
+            argsHow = ITERATE;
+          else if (argumentCount == 2)
+            argsHow = ITERATE2;
+          else {
+            printf("ERROR(%s): iterate configuration selectors "
+                   "only take one or two arguments (sel=%s, command=%s) !!!\n",
+                   __PRETTY_FUNCTION__, methodName, configName);
+            continue;
+          }
+        }
+        else if (isRaw) {
+          argsHow = RAW_ARGS;
+        }
+        else {
+          switch (argumentCount) {
+            case 0:
+              argsHow = NO_ARGS;
+              break;
+            case 1:
+              argsHow = TAKE1;
+              break;
+            case 2:
+              argsHow = TAKE2;
+              break;
+            case 3:
+              argsHow = TAKE3;
+              break;
+            default:
+              printf("ERROR(%s): configuration selectors "
+                     "only take 1-3 arguments (sel=%s, command=%s) !!!\n",
+                     __PRETTY_FUNCTION__, methodName, configName);
+              continue;
+          }
+        }
+        
+        /* search for standard parameters */
+        
+        hasParametersArg = strstr(tmp2, "parameters:")      != NULL ? YES : NO;
+        hasDirConfigArg  = strstr(tmp2, "directoryConfig:") != NULL ? YES : NO;
+
+        if ([self logConfigCommandRegistration]) {
+          printf("Found config selector '%s', command '%s' (%i args) ...\n",
+                 methodName, configName, argumentCount);
+        }
+        
+        /* check allowed location */
+        
+        switch (tmp[0]) {
+          case 'D':
+            if (strstr(tmp, "Directory") == tmp) {
+              reqOverride = ACCESS_CONF;
+              break;
+            }
+          case 'S':
+            if (strstr(tmp, "Server") == tmp) {
+              reqOverride = RSRC_CONF;
+              break;
+            }
+          case 'I':
+            if (strstr(tmp, "Indexes") == tmp) {
+              reqOverride = OR_INDEXES;
+              break;
+            }
+          case 'F':
+            if (strstr(tmp, "FileInfo") == tmp) {
+              reqOverride = OR_FILEINFO;
+              break;
+            }
+          case 'O':
+            if (strstr(tmp, "Options") == tmp) {
+              reqOverride = OR_OPTIONS;
+              break;
+            }
+          case 'L':
+            if (strstr(tmp, "Limit") == tmp) {
+              reqOverride = OR_OPTIONS;
+              break;
+            }
+          case 'A':
+            if (strstr(tmp, "AuthConfig") == tmp) {
+              reqOverride = OR_AUTHCFG;
+              break;
+            }
+          default:
+            printf("%s:  invalid directory location in selector '%s' !\n",
+                   __PRETTY_FUNCTION__, methodName);
+            continue;
+        }
+        
+        /* should check for duplicate entries */
+        {
+          int i;
+          
+          for (i = 0; i < count; i++) {
+            if (strcmp(cmdtable[i].name, configName) == 0) {
+              /* this should check for alternate argument counts */
+              printf("WARNING(%s): found duplicate entry '%s' ...\n",
+                     __PRETTY_FUNCTION__, configName);
+              i = -1;
+              break;
+            }
+          }
+          if (i == -1) continue;
+        }
+        
+        /* check command table capacity */
+        
+        if (count >= capacity) {
+          /* resize command table ... */
+          command_rec *old = cmdtable;
+          unsigned oldCapacity = capacity;
+          
+          capacity *= 2;
+          cmdtable = calloc(capacity + 1,sizeof(command_rec));
+          memcpy(cmdtable, old, oldCapacity * sizeof(command_rec));
+          if (old) free(old);
+        }
+
+        /* fill command table entry */
+        
+        cmdtable[count].name         = configName /* malloced */;
+        cmdtable[count].args_how     = argsHow;
+        cmdtable[count].req_override = reqOverride;
+
+        {
+          NSString *err;
+          
+          err = [bundleHandler usageForConfigSelector:
+                                 cm->method_list[i].method_name];
+          
+          cmdtable[count].errmsg = [err length] > 0
+            ? strdup([err cString])
+            : NULL;
+        }
+
+        {
+          ApObjCCmdDispatchInfo *info;
+          
+          info = calloc(1, sizeof(ApObjCCmdDispatchInfo));
+          info->moduleClass = self;
+          info->sel         = cm->method_list[i].method_name;
+          info->methodName  = methodName;
+          info->command     = configName;
+          info->argsHow     = cmdtable[count].args_how;
+          info->location    = cmdtable[count].req_override;
+          info->isRaw       = isRaw;
+          info->isIterate   = isIterate;
+          info->isFlag      = isFlag;
+          
+          cmdtable[count].cmd_data = info;
+        }
+
+        {
+          void *func;
+          
+          func = NULL;
+          if (reqOverride != RSRC_CONF) {
+            switch (cmdtable[count].args_how) {
+              case NO_ARGS:  func = configStubTake0;    break;
+              case RAW_ARGS: func = configStubRaw;      break;
+              case TAKE1:    func = configStubTake1;    break;
+              case ITERATE:  func = configStubIterate;  break;
+              case TAKE2:    func = configStubTake2;    break;
+              case TAKE12:   func = configStubTake12;   break;
+              case ITERATE2: func = configStubIterate2; break;
+              case TAKE3:    func = configStubTake3;    break;
+              case TAKE23:   break;
+              case TAKE123:  func = configStubTake123;  break;
+              case TAKE13:   break;
+              case FLAG:     func = configStubFlag;     break;
+              
+              default:
+                printf("ERROR(%s): unknown argument style %i !!\n",
+                       __PRETTY_FUNCTION__, cmdtable[count].args_how);
+                break;
+            }
+          }
+          else {
+            switch (cmdtable[count].args_how) {
+              case NO_ARGS:  func = serverConfigStubTake0;    break;
+              case RAW_ARGS: func = serverConfigStubRaw;      break;
+              case TAKE1:    func = serverConfigStubTake1;    break;
+              case ITERATE:  func = serverConfigStubIterate;  break;
+              case TAKE2:    func = serverConfigStubTake2;    break;
+              case TAKE12:   func = serverConfigStubTake12;   break;
+              case ITERATE2: func = serverConfigStubIterate2; break;
+              case TAKE3:    func = serverConfigStubTake3;    break;
+              case TAKE23:   break;
+              case TAKE123:  func = serverConfigStubTake123;  break;
+              case TAKE13:   break;
+              case FLAG:     func = serverConfigStubFlag;     break;
+              
+              default:
+                printf("ERROR(%s): unknown argument style %i !!\n",
+                       __PRETTY_FUNCTION__, cmdtable[count].args_how);
+                break;
+            }
+          }          
+          cmdtable[count].func = func;
+        }
+        if (cmdtable[count].func)
+          count++;
+        else {
+          printf("ERROR(%s): internal error during cmd table setup ...\n",
+                 __PRETTY_FUNCTION__);
+        }
+      }
+    }
+  }
+#else
+#  warning not ported to this runtime yet ...
+#endif
+  
+  if (count == 0) {
+    /* found no commands ... */
+    if (cmdtable) {
+      free(cmdtable);
+      cmdtable = NULL;
+    }
+  }
+#if 0
+  printf("found %i commands ...\n", count);
+#endif
+  return cmdtable;
+}
+
+#define OBJC_CONFIG_BEGIN \
+  NSAutoreleasePool     *pool;\
+  ApObjCCmdDispatchInfo *info;\
+  ApacheCmdParms        *paras;\
+  ApacheModule *bundleHandler;\
+  const char *ares;\
+  if ((info = p->info) == NULL)\
+    return ap_pstrdup(p->pool, "missing Objective-C dispatch info !");\
+  pool = [[NSAutoreleasePool alloc] init];\
+  paras = [[ApacheCmdParms alloc] initWithHandle:p];\
+  bundleHandler = [[info->moduleClass bundleHandler] retain];\
+  { id result; result = nil;
+
+#define OBJC_CONFIG_END \
+    if (result == nil) ares = NULL;\
+    else ares = ap_pstrdup(p->pool, [[result description] cString]);\
+  }\
+  RELEASE(bundleHandler);\
+  RELEASE(paras);\
+  RELEASE(pool); \
+  return ares;
+
+static const char *configStubRaw(cmd_parms *p, void *d, char *a0) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, id, ApacheCmdParms *);
+    NSString *s0;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char *configStubFlag(cmd_parms *p, void *d, int flag) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, BOOL, id, ApacheCmdParms *);
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, flag?YES:NO, d, paras);
+    else
+      result = @"did not find method for config call ..";
+  }
+  OBJC_CONFIG_END;
+}
+static const char *configStubTake1(cmd_parms *p, void *d, char *a0) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, id, ApacheCmdParms *);
+    NSString *s0;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *configStubIterate(cmd_parms *p, void *d, char *a0) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, id, ApacheCmdParms *);
+    NSString *s0;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char
+  *configStubIterate2(cmd_parms *p, void *d, char *a0, char *a1)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, id, ApacheCmdParms *);
+    NSString *s0, *s1;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *configStubTake0(cmd_parms *p, void *d) {
+  return NULL;
+}
+
+static const char *configStubTake2(cmd_parms *p, void *d, char *a0, char *a1) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, id, ApacheCmdParms *);
+    NSString *s0, *s1;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *configStubTake12(cmd_parms *p, void *d, char *a0, char *a1){
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, id, ApacheCmdParms *);
+    NSString *s0, *s1;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char *
+  configStubTake3(cmd_parms *p, void *d, char *a0, char *a1, char *a2)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, NSString *,id, ApacheCmdParms *);
+    NSString *s0, *s1, *s2;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    s2 = a2 ? [[NSString alloc] initWithCString:a2] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, s2, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s2);
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char *
+  configStubTake123(cmd_parms *p, void *d, char *a0, char *a1, char *a2)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, NSString *,id, ApacheCmdParms *);
+    NSString *s0, *s1, *s2;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    s2 = a2 ? [[NSString alloc] initWithCString:a2] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, s2, d, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s2);
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+/* server stubs */
+
+static const char *serverConfigStubRaw(cmd_parms *p, void *d, char *a0) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, ApacheCmdParms *);
+    NSString *s0;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char *serverConfigStubFlag(cmd_parms *p, void *d, int flag) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, BOOL, ApacheCmdParms *);
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, flag?YES:NO, paras);
+    else
+      result = @"did not find method for config call ..";
+  }
+  OBJC_CONFIG_END;
+}
+static const char *serverConfigStubTake1(cmd_parms *p, void *d, char *a0) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, ApacheCmdParms *);
+    NSString *s0;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *serverConfigStubIterate(cmd_parms *p, void *d, char *a0) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, ApacheCmdParms *);
+    NSString *s0;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char
+  *serverConfigStubIterate2(cmd_parms *p, void *d, char *a0, char *a1)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, ApacheCmdParms *);
+    NSString *s0, *s1;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *serverConfigStubTake0(cmd_parms *p, void *d) {
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, ApacheCmdParms *);
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, paras);
+    else
+      result = @"did not find method for config call ..";
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *
+serverConfigStubTake2(cmd_parms *p, void *d, char *a0, char *a1)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, ApacheCmdParms *);
+    NSString *s0, *s1;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+static const char *
+serverConfigStubTake12(cmd_parms *p, void *d, char *a0, char *a1)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, ApacheCmdParms *);
+    NSString *s0, *s1;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, paras);
+    else
+      result = @"did not find method for config call ..";
+    
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char *
+  serverConfigStubTake3(cmd_parms *p, void *d, char *a0, char *a1, char *a2)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, NSString *, ApacheCmdParms *);
+    NSString *s0, *s1, *s2;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    s2 = a2 ? [[NSString alloc] initWithCString:a2] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, s2, paras);
+    else
+      result = @"did not find method for config call ..";
+
+    RELEASE(s2);
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+static const char *
+  serverConfigStubTake123(cmd_parms *p, void *d, char *a0, char *a1, char *a2)
+{
+  OBJC_CONFIG_BEGIN {
+    id (*m)(id, SEL, NSString *, NSString *, NSString *, ApacheCmdParms *);
+    NSString *s0, *s1, *s2;
+    
+    s0 = a0 ? [[NSString alloc] initWithCString:a0] : nil;
+    s1 = a1 ? [[NSString alloc] initWithCString:a1] : nil;
+    s2 = a2 ? [[NSString alloc] initWithCString:a2] : nil;
+    
+    if ((m = (void *)[bundleHandler methodForSelector:info->sel]))
+      result = m(bundleHandler, info->sel, s0, s1, s2, paras);
+    else
+      result = @"did not find method for config call ..";
+
+    RELEASE(s2);
+    RELEASE(s1);
+    RELEASE(s0);
+  }
+  OBJC_CONFIG_END;
+}
+
+@end /* ApModuleBaseClass(ConfigCommands) */
diff --git a/Recycler/mod_objc/ApModuleBaseClass+Handler.m b/Recycler/mod_objc/ApModuleBaseClass+Handler.m
new file mode 100644 (file)
index 0000000..9a59f53
--- /dev/null
@@ -0,0 +1,359 @@
+// $Id: ApModuleBaseClass+Handler.m,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#include "ApModuleBaseClass.h"
+#include <httpd.h>
+#include "http_config.h"
+#import <Foundation/NSBundle.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSAutoreleasePool.h>
+#include "ApacheServer.h"
+#include "ApacheResourcePool.h"
+#include "ApacheModule.h"
+#include "ApacheRequest.h"
+
+@implementation ApModuleBaseClass(HandlerCallback)
+
++ (BOOL)logHandlerRegistration {
+  return NO;
+}
+
++ (handler_rec *)apacheHandlerTable {
+  /*
+    KNOWN problem: this method produces memory leaks !!
+    
+    How to map selectors to handlers ?
+
+    There are two-kinds, content-type handlers and named handlers:
+    
+       text/plain ->
+         - (int)handleTextPlainRequest:(ApacheRequest *)_rq;
+       ngobjweb-adaptor ->
+         - (int)performNgobjwebAdaptorRequest:(ApacheRequest *)_rq;
+    
+    // This structure records the existence of handlers in a module...
+
+    typedef struct {
+      const char *content_type;        // MUST be all lower case
+      int (*handler) (request_rec *);
+    } handler_rec;
+  */
+  ApacheModule *bundleHandler = [self bundleHandler];
+  handler_rec *handlerTable = NULL;
+  unsigned    count, capacity;
+  Class c;
+
+  if (bundleHandler == nil)
+    return NULL;
+  
+  count        = 0;
+  capacity     = 16;
+  handlerTable = calloc(capacity + 1, sizeof(handler_rec));
+  
+#if GNU_RUNTIME
+  /* for the class and each superclass ... */
+  for (c = [bundleHandler class]; c != Nil; c = c->super_class) {
+    struct objc_method_list *cm;
+    
+    /* for each method list of the class */
+    for (cm = c->methods; cm != NULL; cm = cm->method_next) {
+      register unsigned i;
+      
+      /* for each method in the list */
+      for (i = 0; i < cm->method_count; i++) {
+        const char *methodName;
+        
+        if ((methodName = sel_get_name(cm->method_list[i].method_name))) {
+          if (strstr(methodName, "handle") == methodName) {
+            /* could be a MIME-type handler ... */
+            const unsigned char *rq, *spec;
+            unsigned j, len, n, bufLen;
+            unsigned char *buf;
+            
+            if ((rq = strstr(methodName, "Request:")) == NULL)
+              continue;
+            
+            spec = methodName + 6; /* skip 'handle' */
+            if ((len = (rq - spec)) == 0) {
+              /* type spec too long or too short ... */
+              continue;
+            }
+
+            bufLen = len * 2 + 2;
+            buf = malloc(bufLen);
+            
+            buf[0] = tolower(spec[0]);
+            for (j = 1, n = 1; j < len; j++) {
+              if (isupper(spec[j])) {
+                buf[n] = '/';
+                n++;
+                buf[n] = tolower(spec[j]);
+                n++;
+              }
+              else {
+                buf[n] = spec[j];
+                n++;
+              }
+            }
+            buf[n] = '\0';
+
+            if (count >= capacity) {
+              /* resize handler table ... */
+              handler_rec *old = handlerTable;
+              unsigned oldCapacity = capacity;
+              
+              capacity *= 2;
+              handlerTable = calloc(capacity + 1,sizeof(handler_rec));
+              memcpy(handlerTable, old, oldCapacity * sizeof(handler_rec));
+              if (old) free(old);
+            }
+
+            /* memory dup'ed is currently never freed ! */
+            
+            handlerTable[count].content_type = buf;
+            handlerTable[count].handler = [self handleRequestStubFunction];
+            count++;
+            
+            if ([self logHandlerRegistration]) {
+              printf("%s: found method '%s' for MIME handler '%s' ...\n",
+                     __PRETTY_FUNCTION__, methodName, buf);
+            }
+          }
+          else if (strstr(methodName, "perform") == methodName) {
+            /* could be a named handler ... */
+            const unsigned char *rq, *spec;
+            unsigned j, len, n, bufLen;
+            unsigned char *buf;
+            
+            if ((rq = strstr(methodName, "Request:")) == NULL)
+              continue;
+            spec = methodName + 7; /* skip 'perform' */
+            if ((len = (rq - spec)) == 0) {
+              /* type spec too long or too short ... */
+              continue;
+            }
+            
+            bufLen = len * 2 + 2;
+            buf = malloc(bufLen);
+            
+            buf[0] = tolower(spec[0]);
+            for (j = 1, n = 1; j < len; j++) {
+              if (isupper(spec[j])) {
+                buf[n] = '-';
+                n++;
+                buf[n] = tolower(spec[j]);
+                n++;
+              }
+              else {
+                buf[n] = spec[j];
+                n++;
+              }
+            }
+            buf[n] = '\0';
+            
+            if (count >= capacity) {
+              /* resize handler table ... */
+              handler_rec *old = handlerTable;
+              unsigned oldCapacity = capacity;
+              
+              capacity *= 2;
+              handlerTable = calloc(capacity + 1,sizeof(handler_rec));
+              memcpy(handlerTable, old, oldCapacity * sizeof(handler_rec));
+              if (old) free(old);
+            }
+            
+            /* memory dup'ed is currently never freed ! */
+            
+            handlerTable[count].content_type = buf;
+            handlerTable[count].handler = [self handleRequestStubFunction];
+            count++;
+            
+            if ([self logHandlerRegistration]) {
+              printf("%s: found method '%s' for named handler '%s' ...\n",
+                     __PRETTY_FUNCTION__, methodName, buf);
+            }
+          }
+        }
+      }
+    }
+  }
+  
+#else
+#  warning not ported to this runtime yet ...
+#endif
+  
+  if (count == 0) {
+    /* found no handlers ... */
+    if (handlerTable) {
+      free(handlerTable);
+      handlerTable = NULL;
+    }
+  }
+#if 0
+  printf("found %i handlers ...\n", count);
+#endif
+  return handlerTable;
+}
+
+/* the request dispatcher */
+
++ (int)_handleRequest:(void *)_request {
+  request_rec *req = _request;
+  int result;
+  ApacheModule *bundleHandler = [self bundleHandler];
+  
+  if (bundleHandler == nil) {
+    printf("%s: missing bundle handler !!!\n", __PRETTY_FUNCTION__);
+    return 500;
+  }
+  
+  result = DECLINED;
+  
+  if (req->handler) {
+    /* dispatch based on handler set ... */
+    unsigned len;
+    
+    if ((len = strlen(req->handler)) > 0) {
+      unsigned char *buf;
+      unsigned i, j;
+      int (*h)(id,SEL,id);
+      SEL  sel;
+      BOOL nextUpper;
+      
+      buf = calloc(len + 64, sizeof(char));
+      strcpy(buf, "perform");
+      for (i = 0, j = strlen(buf), nextUpper = YES; i < len; i++) {
+        if (req->handler[i] == '-') {
+          /* skip dash and add next char in uppercase */
+          nextUpper = YES;
+        }
+        else {
+          buf[j] = (nextUpper)
+            ? toupper(req->handler[i])
+            : req->handler[i];
+          j++;
+          nextUpper = NO;
+        }
+      }
+      buf[j] = '\0';
+      strcat(buf, "Request:");
+      sel = sel_get_any_uid(buf);
+      free(buf);
+      buf = NULL;
+
+#if 0
+      printf("CALL: %s\n", sel_get_name(sel));
+      fflush(stdout);
+#endif
+      
+      if (sel == NULL) {
+        fprintf(stderr,
+                "%s: did not find selector for handler '%s' !\n",
+                __PRETTY_FUNCTION__, req->handler);
+        result = 500;
+      }
+      else if ((h = (void *)[bundleHandler methodForSelector:sel])) {
+        NSAutoreleasePool *pool;
+        ApacheRequest *or;
+        
+        pool = [[NSAutoreleasePool alloc] init];
+        or   = [[ApacheRequest alloc] initWithHandle:_request];
+        
+        result = h(bundleHandler, sel, or);
+        
+        if (result == ApacheDeclineRequest)
+          result = DECLINED;
+        else if (result == ApacheHandledRequest)
+          result = OK;
+        
+        RELEASE(or);
+        RELEASE(pool);
+      }
+      else {
+        fprintf(stderr,
+                "%s: did not find handler method '%s' for name '%s' !\n",
+                __PRETTY_FUNCTION__, sel_get_name(sel), req->handler);
+        result = 500;
+      }
+    }
+  }
+  else if (req->content_type) {
+    /* dispatch based on MIME-type ... */
+    unsigned len;
+    
+    if ((len = strlen(req->content_type)) > 0) {
+      unsigned char *buf;
+      unsigned i, j;
+      int (*h)(id,SEL,id);
+      SEL  sel;
+      BOOL nextUpper;
+      
+      buf = calloc(len + 64, sizeof(char));
+      strcpy(buf, "handle");
+      for (i = 0, j = strlen(buf), nextUpper = YES; i < len; i++) {
+        if (req->content_type[i] == '/') {
+          /* skip slash and add next char in uppercase */
+          nextUpper = YES;
+        }
+        else {
+          buf[j] = (nextUpper)
+            ? toupper(req->content_type[i])
+            : req->content_type[i];
+          j++;
+          nextUpper = NO;
+        }
+      }
+      buf[j] = '\0';
+      strcat(buf, "Request:");
+      sel = sel_get_any_uid(buf);
+      free(buf);
+      buf = NULL;
+      
+#if 0
+      printf("CALL: %s\n", sel_get_name(sel));
+      fflush(stdout);
+#endif
+      
+      if (sel == NULL) {
+        fprintf(stderr,
+                "%s: did not find selector for mime type '%s' !\n",
+                __PRETTY_FUNCTION__, req->content_type);
+        result = 500;
+      }
+      else if ((h = (void *)[bundleHandler methodForSelector:sel])) {
+        NSAutoreleasePool *pool;
+        ApacheRequest *or;
+        
+        pool = [[NSAutoreleasePool alloc] init];
+        or   = [[ApacheRequest alloc] initWithHandle:_request];
+        
+        result = h(bundleHandler, sel, or);
+        
+        if (result == ApacheDeclineRequest)
+          result = DECLINED;
+        else if (result == ApacheHandledRequest)
+          result = OK;
+        
+        RELEASE(or);
+        RELEASE(pool);
+      }
+      else {
+        fprintf(stderr,
+                "%s: did not find handler method '%s' for mime type '%s' !\n",
+                __PRETTY_FUNCTION__, sel ? sel_get_name(sel) : "<NULL>",
+                req->content_type);
+        result = 500;
+      }
+    }
+  }
+  else {
+    /* nothing to dispatch on ... */
+    fprintf(stderr,
+            "%s: found nothing to dispatch on "
+            "(neither handler type nor name) !\n",
+            __PRETTY_FUNCTION__);
+    result = DECLINED;
+  }
+  return result;
+}
+
+@end /* ApModuleBaseClass(HandlerCallback) */
diff --git a/Recycler/mod_objc/ApModuleBaseClass.h b/Recycler/mod_objc/ApModuleBaseClass.h
new file mode 100644 (file)
index 0000000..f5c3ba1
--- /dev/null
@@ -0,0 +1,66 @@
+// $Id: ApModuleBaseClass.h,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#ifndef __ApModuleBaseClass_H__
+#define __ApModuleBaseClass_H__
+
+#import <Foundation/NSObject.h>
+
+@class ApacheModule;
+
+@interface ApModuleBaseClass : NSObject
+
++ (void)setBundleHandler:(ApacheModule *)_handler;
++ (ApacheModule *)bundleHandler;
+
+/* return an initialized Apache module structure ... */
++ (void *)apacheModule;
+
+@end
+
+@interface ApModuleBaseClass(SubclassOverrides)
+
+/* return an Apache module structure with all callback wrappers set ... */
++ (void *)apacheTemplateModule;
+
+/* return the uninitialized Apache module structure */
++ (void *)apacheModuleStructure;
+
+/* the stub to dispatch handlers (placed in the handler_rec structure) */
++ (void *)handleRequestStubFunction;
+
+@end
+
+@interface ApModuleBaseClass(BasicModuleCallbacks)
+
++ (void)_moduleInit:(void *)s pool:(void *)p;
+
++ (void *)_perDirConfCreate:(void *)dirspec pool:(void *)p;
++ (void *)_perDirConfMerge:(void *)baseCconf with:(void *)newCconf
+  pool:(void *)p;
++ (void *)_perServerConfCreate:(void *)s pool:(void *)p;
++ (void *)_perServerConfMerge:(void *)baseConf with:(void *)newConf
+  pool:(void *)p;
+
++ (int)_translateHandler:(void *)_request;
++ (int)_apCheckUserId:(void *)_request;
++ (int)_authChecker:(void *)_request;
++ (int)_accessChecker:(void *)_request;
++ (int)_typeChecker:(void *)_request;
++ (int)_fixerUpper:(void *)_request;
++ (int)_logger:(void *)_request;
++ (int)_headerParser:(void *)_request;
+
++ (void)_childInit:(void *)_server pool:(void *)_pool;
++ (void)_childExit:(void *)_server pool:(void *)_pool;
+
++ (int)_postReadRequest:(void *)_request;
+
+@end
+
+@interface ApModuleBaseClass(HandlerCallback)
+
++ (int)_handleRequest:(void *)_request;
+
+@end
+
+#endif /* ApModuleBaseClass */
diff --git a/Recycler/mod_objc/ApModuleBaseClass.m b/Recycler/mod_objc/ApModuleBaseClass.m
new file mode 100644 (file)
index 0000000..3919907
--- /dev/null
@@ -0,0 +1,129 @@
+// $Id: ApModuleBaseClass.m,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#include "ApModuleBaseClass.h"
+#include <httpd.h>
+#include "http_config.h"
+#import <Foundation/NSBundle.h>
+#import <Foundation/NSString.h>
+#import <Foundation/NSAutoreleasePool.h>
+#include "ApacheServer.h"
+#include "ApacheResourcePool.h"
+#include "ApacheModule.h"
+#include "ApacheRequest.h"
+
+@interface ApModuleBaseClass(Privates)
+
++ (handler_rec *)apacheHandlerTable;
++ (command_rec *)apacheCommandTable;
+
+@end
+
+@implementation ApModuleBaseClass
+
++ (void)setBundleHandler:(ApacheModule *)_handler {
+  [self subclassResponsibility:_cmd];
+}
++ (ApacheModule *)bundleHandler {
+  return [self subclassResponsibility:_cmd];
+}
+
++ (void *)apacheModule {
+  ApacheModule *bundleHandler = [self bundleHandler];
+  module *mod, *tmpl;
+  
+  if (bundleHandler == nil) {
+    NSLog(@"%s: missing bundle handler !!!", __PRETTY_FUNCTION__);
+    return NULL;
+  }
+  
+  mod  = [self apacheModuleStructure];
+  tmpl = [self apacheTemplateModule];
+  
+  mod->cmds     = [self apacheCommandTable];
+  mod->handlers = [self apacheHandlerTable];
+  
+  /* fill module based on handler reflection ... */
+  
+  mod->init =
+    [bundleHandler respondsToSelector:
+                     @selector(initializeModuleForServer:inPool:)]
+    ? tmpl->init : NULL;
+
+  mod->create_dir_config =
+    [bundleHandler respondsToSelector:
+         @selector(createPerDirectoryConfigInPool:)]
+    ? tmpl->create_dir_config : NULL;
+
+  mod->merge_dir_config =
+    [bundleHandler respondsToSelector:
+         @selector(mergePerDirectoryBaseConfig:withNewConfig:inPool:)]
+    ? tmpl->merge_dir_config : NULL;
+
+  mod->create_server_config =
+    [bundleHandler respondsToSelector:
+                     @selector(createPerServerConfig:inPool:)]
+    ? tmpl->create_server_config : NULL;
+
+  mod->merge_server_config =
+    [bundleHandler respondsToSelector:
+         @selector(mergePerServerBaseConfig:withNewConfig:inPool:)]
+    ? tmpl->merge_server_config : NULL;
+  
+  mod->translate_handler =
+    [bundleHandler respondsToSelector:@selector(handleTranslationForRequest:)]
+    ? tmpl->translate_handler : NULL;
+  mod->ap_check_user_id =
+    [bundleHandler respondsToSelector:@selector(checkUserIdFromRequest:)]
+    ? tmpl->ap_check_user_id : NULL;
+  mod->auth_checker =
+    [bundleHandler respondsToSelector:@selector(checkAuthForRequest:)]
+    ? tmpl->auth_checker : NULL;
+  mod->access_checker =
+    [bundleHandler respondsToSelector:@selector(checkAccessForRequest:)]
+    ? tmpl->access_checker : NULL;
+  mod->type_checker =
+    [bundleHandler respondsToSelector:@selector(checkTypeForRequest:)]
+    ? tmpl->type_checker : NULL;
+  mod->logger =
+    [bundleHandler respondsToSelector:@selector(logRequest:)]
+    ? tmpl->logger : NULL;
+    
+  mod->fixer_upper =
+    [bundleHandler respondsToSelector:@selector(fixupRequest:)]
+    ? tmpl->fixer_upper : NULL;
+  
+  mod->header_parser =
+    [bundleHandler respondsToSelector:@selector(parseHeadersOfRequest:)]
+    ? tmpl->header_parser : NULL;
+
+  mod->post_read_request =
+    [bundleHandler respondsToSelector:@selector(postProcessRequest:)]
+    ? tmpl->post_read_request : NULL;
+
+  mod->child_init =
+    [bundleHandler respondsToSelector:
+      @selector(initializeChildProcessWithServer:inPool:)]
+    ? tmpl->child_init : NULL;
+  mod->child_exit =
+    [bundleHandler respondsToSelector:
+      @selector(exitChildProcessWithServer:inPool:)]
+    ? tmpl->child_exit : NULL;
+  
+  return mod;
+}
+
+@end /* ApModuleBaseClass */
+
+@implementation ApModuleBaseClass(SubclassOverrides)
+
++ (void *)apacheTemplateModule {
+  return [self subclassResponsibility:_cmd];
+}
++ (void *)apacheModuleStructure {
+  return [self subclassResponsibility:_cmd];
+}
++ (void *)handleRequestStubFunction {
+  return [self subclassResponsibility:_cmd];
+}
+
+@end /* ApModuleBaseClass(SubclassOverrides) */
diff --git a/Recycler/mod_objc/ApTest.m b/Recycler/mod_objc/ApTest.m
new file mode 100644 (file)
index 0000000..3940a2a
--- /dev/null
@@ -0,0 +1,101 @@
+// $Id: ApTest.m,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#include "ApacheModule.h"
+#import <Foundation/Foundation.h>
+
+@interface ApTest : ApacheModule
+@end
+
+#include "ApacheResourcePool.h"
+
+@implementation ApTest
+
+- (id)init {
+  //printf("INIT 0x%08X ..\n", (unsigned int)self);
+  return self;
+}
+- (void)dealloc {
+  //printf("DEALLOC 0x%08X ..\n", (unsigned int)self);
+  [super dealloc];
+}
+
+/* config commands */
+
+- (id)configureDirectory_MyDirAlias:(NSString *)_fake:(NSString *)_real
+  directoryConfig:(id)_cfg
+  parameters:(ApacheCmdParms *)_params
+{
+  [self logWithFormat:@"MyDirAlias(%@,%@,config=%@)", _fake, _real, _cfg];
+  [_cfg setObject:_real forKey:_fake];
+  return nil;
+}
+- (id)configureServer_MyServerAlias:(NSString *)_fake:(NSString *)_real
+  parameters:(ApacheCmdParms *)_params
+{
+  [self logWithFormat:@"MyServerAlias(%@,%@)", _fake, _real];
+  return nil;
+}
+
+- (id)configureDirectory_PrintDirConfig:(NSString *)_fake
+  directoryConfig:(id)_cfg
+  parameters:(ApacheCmdParms *)_params
+{
+  [self logWithFormat:@"DIR: %@", _cfg];
+  return nil;
+}
+
+/* handlers */
+
+- (int)handleTextHtmlRequest:(ApacheRequest *)_rq {
+  printf("%s ...\n", __PRETTY_FUNCTION__);
+  return ApacheDeclineRequest;
+}
+- (int)performApTestRequest:(ApacheRequest *)_rq {
+  printf("%s ...\n", __PRETTY_FUNCTION__);
+  return ApacheDeclineRequest;
+}
+
+/* callbacks */
+
+#if 0
+- (void)initializeModuleForServer:(ApacheServer *)_server
+  inPool:(ApacheResourcePool *)_pool
+{
+  [self debugWithFormat:@"init module for server %@", _server];
+}
+#endif
+
+- (id)createPerDirectoryConfigInPool:(ApacheResourcePool *)_pool {
+  NSMutableDictionary *md;
+  
+  md = [[NSMutableDictionary alloc] initWithCapacity:128];
+  [_pool releaseObject:md];
+  return md;
+}
+- (id)mergePerDirectoryBaseConfig:(id)_base withNewConfig:(id)_new
+  inPool:(ApacheResourcePool *)_pool
+{
+  [self debugWithFormat:@"merge dir config %@ with %@ ..",
+          _base, _new];
+  return _base;
+}
+
+- (id)createPerServerConfig:(ApacheServer *)_server
+  inPool:(ApacheResourcePool *)_pool
+{
+  return [NSMutableDictionary dictionaryWithCapacity:128];
+}
+- (id)mergePerServerBaseConfig:(id)_base withNewConfig:(id)_new
+  inPool:(ApacheResourcePool *)_pool
+{
+  [self debugWithFormat:@"merge server config %@ with %@ ..",
+          _base, _new];
+  return nil;
+}
+
+- (int)logRequest:(ApacheRequest *)_rq {
+  [self logWithFormat:@"REQUEST: %@", _rq];
+  return ApacheDeclineRequest;
+}
+
+@end /* ApTest */
diff --git a/Recycler/mod_objc/ApacheCmdParms.h b/Recycler/mod_objc/ApacheCmdParms.h
new file mode 100644 (file)
index 0000000..433b52f
--- /dev/null
@@ -0,0 +1,33 @@
+// $Id: ApacheCmdParms.h,v 1.1 2004/06/08 11:15:58 helge Exp $
+
+#ifndef __ApacheCmdParms_H__
+#define __ApacheCmdParms_H__
+
+#include <ApacheAPI/ApacheObject.h>
+
+@class ApacheResourcePool, ApacheServer;
+
+@interface ApacheCmdParms : ApacheObject
+{
+}
+
+/* accessors */
+
+- (void *)userInfo;
+
+/* Pool to allocate new storage in */
+- (ApacheResourcePool *)pool;
+
+/*
+  Pool for scratch memory; persists during
+  configuration, but wiped before the first
+  request is served...
+*/
+- (ApacheResourcePool *)temporaryPool;
+
+/* Server_rec being configured for */
+- (ApacheServer *)server;
+
+@end
+
+#endif /* __ApacheCmdParms_H__ */
diff --git a/Recycler/mod_objc/ApacheCmdParms.m b/Recycler/mod_objc/ApacheCmdParms.m
new file mode 100644 (file)
index 0000000..e88d454
--- /dev/null
@@ -0,0 +1,66 @@
+// $Id: ApacheCmdParms.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheCmdParms.h"
+#include "ApacheResourcePool.h"
+#include "httpd.h"
+#include "http_config.h"
+#import <Foundation/Foundation.h>
+
+@implementation ApacheCmdParms
+
+#define AP_HANDLE ((cmd_parms *)self->handle)
+
+- (void *)userInfo {
+  /* Argument to command from cmd_table */
+  return AP_HANDLE->info;
+}
+
+- (ApacheResourcePool *)pool {
+  ApacheResourcePool *pool;
+  
+  pool = [[ApacheResourcePool alloc]
+                              initWithHandle:AP_HANDLE->pool freeWhenDone:NO];
+  return AUTORELEASE(pool);
+}
+- (ApacheResourcePool *)temporaryPool {
+  ApacheResourcePool *pool;
+  
+  pool = [[ApacheResourcePool alloc]
+                              initWithHandle:AP_HANDLE->temp_pool
+                              freeWhenDone:NO];
+  return AUTORELEASE(pool);
+}
+
+- (ApacheServer *)server {
+  return [[[ApacheServer alloc] initWithHandle:AP_HANDLE->server] autorelease];
+}
+
+- (NSString *)path {
+  const unsigned char *c;
+  
+  if ((c = AP_HANDLE->path) == NULL)
+    return nil;
+  return [[[NSString alloc] initWithCString:c] autorelease];
+}
+
+/* description */
+
+- (NSString *)description {
+  NSMutableString *ms;
+  id tmp;
+
+  ms = [NSMutableString stringWithCapacity:256];
+  [ms appendFormat:@"<0x%08X[%@]: ", self, NSStringFromClass([self class])];
+
+  [ms appendFormat:@" 0x%08X ui=0x%08X", self->handle, [self userInfo]];
+  
+  if ((tmp = [self path]))
+    [ms appendFormat:@" path=%@", tmp];
+  if ((tmp = [self server]))
+    [ms appendFormat:@" server=%@", tmp];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+@end /* ApacheCmdParms */
diff --git a/Recycler/mod_objc/ApacheConnection.h b/Recycler/mod_objc/ApacheConnection.h
new file mode 100644 (file)
index 0000000..f2e8f61
--- /dev/null
@@ -0,0 +1,46 @@
+// $Id: ApacheConnection.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheConnection_H__
+#define __ApacheConnection_H__
+
+#include "ApacheObject.h"
+
+@class NSString;
+@class ApacheResourcePool, ApacheServer;
+
+@interface ApacheConnection : ApacheObject
+
+/* accessors */
+
+- (ApacheResourcePool *)connectionPool;
+- (ApacheServer *)server;
+- (ApacheServer *)baseServer;
+
+/* Information about the connection itself */
+
+- (int)childNumber;
+
+/* Who is the client? */
+
+- (NSString *)remoteIP;
+- (NSString *)remoteHost;
+- (NSString *)remoteLogName;
+- (NSString *)user;
+- (NSString *)authorizationType;
+
+- (NSString *)localIP;
+- (NSString *)localHost;
+
+- (BOOL)isAborted;
+
+- (BOOL)usesKeepAlive;
+- (BOOL)doesNotUseKeepAlive;
+- (BOOL)didUseKeepAlive;
+- (int)numberOfKeepAlives;
+
+- (BOOL)isValidDoubleReverseDNS;
+- (BOOL)isInvalidDoubleReverseDNS;
+
+@end
+
+#endif /* __ApacheConnection_H__ */
diff --git a/Recycler/mod_objc/ApacheConnection.m b/Recycler/mod_objc/ApacheConnection.m
new file mode 100644 (file)
index 0000000..b7b102b
--- /dev/null
@@ -0,0 +1,110 @@
+// $Id: ApacheConnection.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheConnection.h"
+#import <Foundation/NSString.h>
+#include "httpd.h"
+
+@implementation ApacheConnection
+#define AP_HANDLE ((conn_rec *)self->handle)
+
+/* accessors */
+
+- (ApacheResourcePool *)connectionPool {
+  return [ApacheResourcePool objectWithHandle:AP_HANDLE->pool];
+}
+- (ApacheServer *)server {
+  return [ApacheServer objectWithHandle:AP_HANDLE->server];
+}
+- (ApacheServer *)baseServer {
+  return [ApacheServer objectWithHandle:AP_HANDLE->base_server];
+}
+
+/* Information about the connection itself */
+
+- (int)childNumber {
+  return AP_HANDLE->child_num;
+}
+
+/* Who is the client? */
+
+// struct sockaddr_in local_addr;
+// struct sockaddr_in remote_addr;
+- (NSString *)remoteIP {
+  return [NSString stringWithCString:AP_HANDLE->remote_ip];
+}
+- (NSString *)remoteHost {
+  return [NSString stringWithCString:AP_HANDLE->remote_host];
+}
+- (NSString *)remoteLogName {
+  return [NSString stringWithCString:AP_HANDLE->remote_logname];
+}
+- (NSString *)user {
+  return [NSString stringWithCString:AP_HANDLE->user];
+}
+- (NSString *)authorizationType {
+  return [NSString stringWithCString:AP_HANDLE->ap_auth_type];
+}
+
+- (NSString *)localIP {
+  return [NSString stringWithCString:AP_HANDLE->local_ip];
+}
+- (NSString *)localHost {
+  return [NSString stringWithCString:AP_HANDLE->local_host];
+}
+
+- (BOOL)isAborted {
+  return AP_HANDLE->aborted ? YES : NO;
+}
+- (BOOL)usesKeepAlive {
+  return AP_HANDLE->keepalive == 1 ? YES : NO;
+}
+- (BOOL)doesNotUseKeepAlive {
+  return AP_HANDLE->keepalive == -1 ? YES : NO;
+}
+- (BOOL)didUseKeepAlive {
+  return AP_HANDLE->keptalive ? YES : NO;
+}
+
+- (int)numberOfKeepAlives {
+  return AP_HANDLE->keepalives;
+}
+
+- (BOOL)isValidDoubleReverseDNS {
+  return AP_HANDLE->double_reverse == 1 ? YES : NO;
+}
+- (BOOL)isInvalidDoubleReverseDNS {
+  return AP_HANDLE->double_reverse == -1 ? YES : NO;
+}
+
+#undef AP_HANDLE
+
+
+- (NSString *)description {
+  NSMutableString *ms;
+  id tmp;
+  
+  ms = [NSMutableString stringWithCapacity:128];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  [ms appendFormat:@" 0x%08X", self->handle];
+
+  if ([self isAborted])       [ms appendString:@" aborted"];
+  if ([self usesKeepAlive])   [ms appendString:@" keepalive"];
+  if ([self didUseKeepAlive]) [ms appendString:@" did-keepalive"];
+
+  if ([self numberOfKeepAlives] > 0)
+    [ms appendFormat:@" #keepalives=%i", [self numberOfKeepAlives]];
+  
+  tmp = [self remoteIP];
+  if ([tmp length] > 0) [ms appendFormat:@" remoteIP=%@", tmp];
+  
+  tmp = [self user];
+  if ([tmp length] > 0) [ms appendFormat:@" user=%@", tmp];
+
+  tmp = [self authorizationType];
+  if ([tmp length] > 0) [ms appendFormat:@" auth=%@", tmp];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+@end /* ApacheConnection */
diff --git a/Recycler/mod_objc/ApacheModule.h b/Recycler/mod_objc/ApacheModule.h
new file mode 100644 (file)
index 0000000..cb3402d
--- /dev/null
@@ -0,0 +1,116 @@
+// $Id: ApacheModule.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheModule_H__
+#define __ApacheModule_H__
+
+#import <Foundation/NSObject.h>
+
+@class NSString;
+@class ApacheCmdParms, ApacheResourcePool, ApacheServer;
+
+@interface ApacheModule : NSObject
+
+/* return the usage string for config commands */
+- (NSString *)usageForConfigSelector:(SEL)_selector;
+
+/* logging */
+
+- (void)logWithFormat:(NSString *)_format, ...;
+- (void)debugWithFormat:(NSString *)_format, ...;
+
+@end
+
+@class ApacheRequest;
+
+/*
+  Note: Modules should not rely on the order in which create_server_config
+  and create_dir_config are called.
+*/
+
+@interface ApacheModule(ConfigOperations)
+
+- (id)createPerDirectoryConfigInPool:(ApacheResourcePool *)_pool;
+- (id)mergePerDirectoryBaseConfig:(id)_base withNewConfig:(id)_new
+  inPool:(ApacheResourcePool *)_pool;
+
+- (id)createPerServerConfig:(ApacheServer *)_server
+  inPool:(ApacheResourcePool *)_pool;
+- (id)mergePerServerBaseConfig:(id)_base withNewConfig:(id)_new
+  inPool:(ApacheResourcePool *)_pool;
+
+/*
+  -initializeModuleForServer:inPool: occurs after config parsing, but
+  before any children are forked.
+*/
+- (void)initializeModuleForServer:(ApacheServer *)_server
+  inPool:(ApacheResourcePool *)_pool;
+
+@end
+
+/* Hooks for getting into the middle of server ops ... */
+
+extern int ApacheDeclineRequest;
+extern int ApacheHandledRequest;
+
+@interface ApacheModule(ServerOperations)
+
+/* translate_handler --- translate URI to filename */
+- (int)handleTranslationForRequest:(ApacheRequest *)_req;
+
+/*
+  access_checker --- check access by host address, etc.   All of these
+                     run; if all decline, that's still OK.
+*/
+- (int)checkAccessForRequest:(ApacheRequest *)_req;
+
+/* check_user_id --- get and validate user id from the HTTP request */
+- (int)checkUserIdFromRequest:(ApacheRequest *)_req;
+
+/*
+  auth_checker --- see if the user (from check_user_id) is OK *here*.
+                   If all of *these* decline, the request is rejected
+                   (as a SERVER_ERROR, since the module which was
+                   supposed to handle this was configured wrong).
+*/
+- (int)checkAuthForRequest:(ApacheRequest *)_req;
+
+/*
+  type_checker --- Determine MIME type of the requested entity;
+                   sets content_type, _encoding and _language fields.
+*/
+- (int)checkTypeForRequest:(ApacheRequest *)_req;
+
+/* logger --- log a transaction. */
+- (int)logRequest:(ApacheRequest *)_req;
+
+- (int)fixupRequest:(ApacheRequest *)_req;
+- (int)parseHeadersOfRequest:(ApacheRequest *)_req;
+
+/*
+  post_read_request --- run right after read_request or internal_redirect,
+                        and not run during any subrequests.
+*/
+- (int)postProcessRequest:(ApacheRequest *)_req;
+
+@end
+
+/* Regardless of the model the server uses for managing "units of
+ * execution", i.e. multi-process, multi-threaded, hybrids of those,
+ * there is the concept of a "heavy weight process".  That is, a
+ * process with its own memory space, file spaces, etc.  This method,
+ * child_init, is called once for each heavy-weight process before
+ * any requests are served.  Note that no provision is made yet for
+ * initialization per light-weight process (i.e. thread).  The
+ * parameters passed here are the same as those passed to the global
+ * init method above.
+ */
+@interface ApacheModule(ForkOperations)
+
+- (void)initializeChildProcessWithServer:(ApacheServer *)_server
+  inPool:(ApacheResourcePool *)_pool;
+- (void)exitChildProcessWithServer:(ApacheServer *)_server
+  inPool:(ApacheResourcePool *)_pool;
+
+@end
+
+#endif /* __ApacheModule_H__ */
diff --git a/Recycler/mod_objc/ApacheModule.m b/Recycler/mod_objc/ApacheModule.m
new file mode 100644 (file)
index 0000000..76e254a
--- /dev/null
@@ -0,0 +1,59 @@
+// $Id: ApacheModule.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheModule.h"
+#include "ApacheCmdParms.h"
+#include "ApacheResourcePool.h"
+#import <Foundation/Foundation.h>
+#include "httpd.h"
+
+int ApacheDeclineRequest = DECLINED;
+int ApacheHandledRequest = OK;
+
+@implementation ApacheModule
+
+- (NSString *)usageForConfigSelector:(SEL)_selector {
+  return nil;
+}
+
+/* logging */
+
+- (void)logWithFormat:(NSString *)_format, ... {
+  NSString *value = nil;
+  va_list  ap;
+
+  va_start(ap, _format);
+  value = [NSString stringWithFormat:_format arguments:ap];
+  va_end(ap);
+  
+#if DEBUG
+  printf("|0x%08X| %s\n", (unsigned int)self, [[value description] cString]);
+#else
+  NSLog(@"|0x%08X| %@", self, value);
+#endif
+}
+- (void)debugWithFormat:(NSString *)_format, ... {
+  static char showDebug = 2;
+  NSString *value = nil;
+  va_list  ap;
+  
+  if (showDebug == 2) {
+#if 0
+    showDebug = [WOApplication isDebuggingEnabled] ? 1 : 0;
+#endif
+  }
+  
+  if (showDebug) {
+    va_start(ap, _format);
+    value = [NSString stringWithFormat:_format arguments:ap];
+    va_end(ap);
+    
+#if DEBUG
+    printf("|0x%08X|D %s\n", (unsigned int)self,
+           [[value description] cString]);
+#else
+    NSLog(@"|0x%08X|D %@", self, value);
+#endif
+  }
+}
+
+@end /* ApacheModule */
diff --git a/Recycler/mod_objc/ApacheObject.h b/Recycler/mod_objc/ApacheObject.h
new file mode 100644 (file)
index 0000000..93f1df7
--- /dev/null
@@ -0,0 +1,27 @@
+// $Id: ApacheObject.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheObject_H__
+#define __ApacheObject_H__
+
+#import <Foundation/NSObject.h>
+
+@interface ApacheObject : NSObject
+{
+  void *handle;
+  BOOL freeWhenDone; // if yes, call destroyHandle in -dealloc
+}
+
++ (id)objectWithHandle:(void *)_handle;
+
+- (id)initWithHandle:(void *)_handle freeWhenDone:(BOOL)_flag; // designated
+- (id)initWithHandle:(void *)_handle; // freeWhenDone:NO
+
+/* destroy a handle (needs to be overidden by subclasses) */
+- (void)destroyHandle;
+
+/* accessors */
+- (void *)handle;
+
+@end
+
+#endif /* __ApacheObject_H__ */
diff --git a/Recycler/mod_objc/ApacheObject.m b/Recycler/mod_objc/ApacheObject.m
new file mode 100644 (file)
index 0000000..53a40c1
--- /dev/null
@@ -0,0 +1,79 @@
+// $Id: ApacheObject.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheObject.h"
+#import <Foundation/Foundation.h>
+
+@implementation ApacheObject
+
+static NSMapTable *proxyRegistry = NULL; // THREAD
+
++ (void)initialize {
+  if (proxyRegistry == NULL) {
+    proxyRegistry = NSCreateMapTable(NSNonOwnedPointerMapKeyCallBacks,
+                                     NSNonOwnedPointerMapValueCallBacks,
+                                     128);
+  }
+}
+
++ (id)objectWithHandle:(void *)_handle {
+  id proxy;
+  
+  if (_handle == NULL) return nil;
+  
+  if ((proxy = NSMapGet(proxyRegistry, _handle)))
+    return proxy;
+  
+  return [[[self alloc] initWithHandle:_handle freeWhenDone:NO] autorelease];
+}
+
+- (id)initWithHandle:(void *)_handle freeWhenDone:(BOOL)_flag {
+  if (_handle == NULL) {
+    RELEASE(self);
+    return nil;
+  }
+  
+  self->handle = _handle;
+  self->freeWhenDone = _flag;
+  
+  NSMapInsert(proxyRegistry, _handle, self);
+  
+  return self;
+}
+- (id)initWithHandle:(void *)_handle {
+  return [self initWithHandle:_handle freeWhenDone:NO];
+}
+- (id)init {
+  return [self initWithHandle:NULL freeWhenDone:NO];
+}
+
+- (void)dealloc {
+  if (self->handle) {
+    NSMapRemove(proxyRegistry, self->handle);
+    
+    if (self->freeWhenDone) {
+      [self destroyHandle];
+      self->handle = NULL;
+    }
+  }
+  [super dealloc];
+}
+
+- (void)destroyHandle {
+  [self subclassResponsibility:_cmd];
+}
+
+/* accessors */
+
+- (void *)handle {
+  return self->handle;
+}
+
+/* description */
+
+- (NSString *)description {
+  return [NSString stringWithFormat:@"<0x%08X[%@]: apache=0x%08X>",
+                     self, NSStringFromClass([self class]),
+                     self->handle];
+}
+
+@end /* ApacheObject */
diff --git a/Recycler/mod_objc/ApacheRequest.h b/Recycler/mod_objc/ApacheRequest.h
new file mode 100644 (file)
index 0000000..c981906
--- /dev/null
@@ -0,0 +1,200 @@
+// $Id: ApacheRequest.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheRequest_H__
+#define __ApacheRequest_H__
+
+#include "ApacheObject.h"
+#include <stdio.h>
+
+@class NSString, NSDate, NSData;
+@class ApacheResourcePool, ApacheConnection, ApacheServer;
+@class ApacheTable;
+
+/*
+  An Objective-C wrapper for the Apache request structure.
+
+  Note: the Apache request itself is allocated from it's
+  request resource pool !
+*/
+
+@interface ApacheRequest : ApacheObject
+{
+}
+
+/* accessors */
+
+- (ApacheResourcePool *)requestPool;
+- (ApacheConnection   *)connection;
+- (ApacheServer       *)server;
+
+/* requests */
+
+/*
+  If we wind up getting redirected, pointer to the request we redirected to.
+*/
+- (ApacheRequest *)redirectToRequest;
+
+/* If this is an internal redirect, pointer to where we redirected *from*. */
+- (ApacheRequest *)redirectFromRequest;
+
+/*
+  If this is a sub_request (see request.h) pointer back to the main request.
+*/
+- (ApacheRequest *)mainRequest;
+
+/*
+  Info about the request itself... we begin with stuff that only
+  protocol.c should ever touch...
+*/
+- (NSString *)firstRequestLine;
+- (BOOL)isBackwards;
+- (BOOL)isHeadRequest;
+- (NSString *)protocol;
+- (int)protocolNumber;
+- (NSString *)hostName;
+- (NSDate *)requestTime;
+- (NSString *)statusLine;
+- (int)status;
+
+/*
+  Request method, two ways; also, protocol, etc..  Outside of protocol.c,
+  look, but don't touch.
+*/
+- (NSString *)method;
+- (int)methodNumber;
++ (int)numberForMethod:(NSString *)_method;
+
+/* modifying the allowed-method set */
+- (void)allowMethodNumber:(int)_num;
+- (BOOL)isMethodNumberAllowed:(int)_num;
+
+- (unsigned int)bytesSent;
+- (NSDate *)lastModified;
+
+/* HTTP/1.1 connection-level features */
+
+- (BOOL)isChunkedSending;
+- (int)byteRangeCount;
+- (NSString *)byteRangeBoundary;
+- (NSString *)range;
+- (unsigned int)contentLength;
+
+- (unsigned int)numberOfRemainingBytes;
+- (unsigned int)numberOfReadBytes;
+- (BOOL)isChunkedReceiving;
+- (BOOL)isExpecting100;
+
+/* MIME tables */
+
+- (ApacheTable *)headersIn;
+- (ApacheTable *)headersOut;
+- (ApacheTable *)errorHeadersOut;
+- (ApacheTable *)subprocessEnvironment;
+- (ApacheTable *)notes;
+
+/* content-info */
+
+- (void)setContentType:(NSString *)_ctype;
+- (NSString *)contentType;
+- (void)setContentEncoding:(NSString *)_cencoding;
+- (NSString *)contentEncoding;
+- (void)setContentLanguage:(NSString *)_clanguage;
+- (NSString *)contentLanguage;
+- (NSArray *)contentLanguages;
+- (NSString *)vlistValidator;
+
+- (void)setHandler:(NSString *)_value;
+- (NSString *)handler;
+
+- (BOOL)noCache;
+- (BOOL)noLocalCopy;
+
+/*
+  What object is being requested (either directly, or via include
+  or content-negotiation mapping).
+*/
+- (NSString *)unparsedURI;
+- (NSString *)uri;
+- (NSString *)filename;
+- (NSString *)pathInfo;
+- (NSString *)queryArgs;
+- (NSString *)casePreservedFilename;
+
+- (void)parseURI:(NSString *)_uri;
+
+/* sub-requests */
+
+- (ApacheRequest *)subRequestLookupURI:(NSString *)_newfile;
+- (ApacheRequest *)subRequestLookupURI:(NSString *)_newfile
+  method:(NSString *)_method;
+- (ApacheRequest *)subRequestLookupFile:(NSString *)_newfile;
+
+/* operations */
+
+- (int)runSubRequest;
+- (void)destroySubRequest;
+
+- (void)internalRedirect:(NSString *)_uri;
+- (void)internalRedirectHandler:(NSString *)_uri;
+
+- (int)someAuthorizationRequired;
+- (BOOL)isInitialRequest;
+
+- (NSDate *)updateModificationTime:(NSDate *)_date;
+
+/* sending headers */
+
+- (void)sendBasicHttpHeader;
+- (void)sendHttpHeader;
+- (int)sendHttpTrace;
+- (int)sendHttpOptions;
+
+/* Finish up stuff after a request */
+- (void)finalizeRequestProtocol;
+
+- (void)sendErrorResponse;
+- (void)sendErrorResponseWithRecursiveFailStatus:(int)_state;
+
+/* modifying headers */
+
+- (int)setContentLength:(unsigned int)_len;
+- (int)setKeepAlive;
+- (NSDate *)rationalizeModificationTime:(NSDate *)_mtime;
+- (NSString *)makeETag:(BOOL)_forceWeak;
+- (void)setETag;
+- (void)setLastModified;
+- (int)meetsConditions;
+
+/* sending content */
+
+- (long)sendFile:(FILE *)_file;
+- (long)sendFile:(FILE *)_file length:(long)_len;
+- (unsigned int)sendMMap:(void *)_mm
+  offset:(unsigned int)_off length:(unsigned int)_len;
+
+- (int)rputc:(int)_c;
+- (int)rputs:(const char *)_cstr;
+- (int)rwrite:(const void *)_buf length:(unsigned int)_len;
+- (int)rflush;
+- (int)rwriteData:(NSData *)_data;
+
+/* Reading a block of data from the client connection (e.g., POST arg) */
+
+- (int)setupClientBlock:(int)_readPolicy;
+- (int)shouldClientBlock;
+- (long)getClientBlock:(char *)_buffer length:(int)_bufsiz;
+- (int)discardRequestBody;
+
+/* Sending a byterange */
+
+- (int)setByteRange;
+
+/* basic authentication */
+
+- (void)noteAuthFailure;
+- (void)noteBasicAuthFailure;
+- (int)getBasicAuthPassword:(const char **)_pwd;
+
+@end
+
+#endif /* __ApacheRequest_H__ */
diff --git a/Recycler/mod_objc/ApacheRequest.m b/Recycler/mod_objc/ApacheRequest.m
new file mode 100644 (file)
index 0000000..c4d17cd
--- /dev/null
@@ -0,0 +1,457 @@
+// $Id: ApacheRequest.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheRequest.h"
+#import <Foundation/Foundation.h>
+#include "httpd.h"
+#include "http_request.h"
+#include "http_protocol.h"
+
+#define ApCharSetAccessor(_field, _val_) \
+  {\
+    char *val;\
+    unsigned len;\
+    \
+    len = [_val_ cStringLength];\
+    val = ap_palloc(AP_HANDLE->pool, len + 1);\
+    [_val_ getCString:val];\
+    val[len] = '\0';\
+    \
+    AP_HANDLE->_field = val;\
+  }
+
+@implementation ApacheRequest
+#define AP_HANDLE ((request_rec *)self->handle)
+
+/* accessors */
+
+- (ApacheResourcePool *)requestPool {
+  return [ApacheResourcePool objectWithHandle:AP_HANDLE->pool];
+}
+- (ApacheConnection *)connection {
+  return [ApacheConnection objectWithHandle:AP_HANDLE->connection];
+}
+- (ApacheServer *)server {
+  return [ApacheServer objectWithHandle:AP_HANDLE->server];
+}
+
+/* requests */
+
+- (ApacheRequest *)redirectToRequest {
+  return [ApacheRequest objectWithHandle:AP_HANDLE->next];
+}
+- (ApacheRequest *)redirectFromRequest {
+  return [ApacheRequest objectWithHandle:AP_HANDLE->prev];
+}
+- (ApacheRequest *)mainRequest {
+  return [ApacheRequest objectWithHandle:AP_HANDLE->main];
+}
+
+/*
+  Info about the request itself... we begin with stuff that only
+  protocol.c should ever touch...
+*/
+
+- (NSString *)firstRequestLine {
+  return [NSString stringWithCString:AP_HANDLE->the_request];
+}
+- (BOOL)isBackwards {
+  return AP_HANDLE->assbackwards ? YES : NO;
+}
+/* proxy ? */
+- (BOOL)isHeadRequest {
+  return AP_HANDLE->header_only ? YES : NO;
+}
+
+- (NSString *)protocol {
+  return [NSString stringWithCString:AP_HANDLE->protocol];
+}
+- (int)protocolNumber {
+  return AP_HANDLE->proto_num;
+}
+
+- (NSString *)hostName {
+  return [NSString stringWithCString:AP_HANDLE->hostname];
+}
+
+- (NSDate *)requestTime {
+  return [NSDate dateWithTimeIntervalSince1970:AP_HANDLE->request_time];
+}
+
+- (NSString *)statusLine {
+  return [NSString stringWithCString:AP_HANDLE->status_line];
+}
+- (int)status {
+  return AP_HANDLE->status;
+}
+
+/*
+  Request method, two ways; also, protocol, etc..  Outside of protocol.c,
+  look, but don't touch.
+*/
+- (NSString *)method {
+  return [NSString stringWithCString:AP_HANDLE->method];
+}
+- (int)methodNumber {
+  return AP_HANDLE->method_number;
+}
++ (int)numberForMethod:(NSString *)_method {
+  return ap_method_number_of([_method cString]);
+}
+
+- (void)allowMethodNumber:(int)_num {
+  AP_HANDLE->allowed |= (1 << _num);
+}
+- (BOOL)isMethodNumberAllowed:(int)_num {
+  return (AP_HANDLE->allowed & (1 << _num)) ? YES : NO;
+}
+
+- (unsigned int)bytesSent {
+  return AP_HANDLE->bytes_sent;
+}
+- (NSDate *)lastModified {
+  return [NSDate dateWithTimeIntervalSince1970:AP_HANDLE->mtime];
+}
+
+/* HTTP/1.1 connection-level features */
+
+- (BOOL)isChunkedSending {
+  return AP_HANDLE->chunked ? YES : NO;
+}
+- (int)byteRangeCount {
+  return AP_HANDLE->byterange;
+}
+- (NSString *)byteRangeBoundary {
+  return [NSString stringWithCString:AP_HANDLE->boundary];
+}
+- (NSString *)range {
+  return [NSString stringWithCString:AP_HANDLE->range];
+}
+- (unsigned int)contentLength {
+  return AP_HANDLE->clength;
+}
+
+- (unsigned int)numberOfRemainingBytes {
+  return AP_HANDLE->remaining;
+}
+- (unsigned int)numberOfReadBytes {
+  return AP_HANDLE->read_length;
+}
+- (BOOL)isChunkedReceiving {
+  return AP_HANDLE->read_chunked ? YES : NO;
+}
+- (BOOL)isExpecting100 {
+  return AP_HANDLE->expecting_100 ? YES : NO;
+}
+
+/*
+  MIME header environments, in and out.  Also, an array containing
+  environment variables to be passed to subprocesses, so people can
+  write modules to add to that environment.
+
+  The difference between headers_out and err_headers_out is that the
+  latter are printed even on error, and persist across internal redirects
+  (so the headers printed for ErrorDocument handlers will have them).
+
+  The 'notes' table is for notes from one module to another, with no
+  other set purpose in mind...
+*/
+
+- (ApacheTable *)headersIn {
+  return [ApacheTable objectWithHandle:AP_HANDLE->headers_in];
+}
+- (ApacheTable *)headersOut {
+  return [ApacheTable objectWithHandle:AP_HANDLE->headers_out];
+}
+- (ApacheTable *)errorHeadersOut {
+  return [ApacheTable objectWithHandle:AP_HANDLE->err_headers_out];
+}
+- (ApacheTable *)subprocessEnvironment {
+  return [ApacheTable objectWithHandle:AP_HANDLE->subprocess_env];
+}
+- (ApacheTable *)notes {
+  return [ApacheTable objectWithHandle:AP_HANDLE->notes];
+}
+
+/*
+  content_type, handler, content_encoding, content_language, and all
+  content_languages MUST be lowercased strings.  They may be pointers
+  to static strings; they should not be modified in place.
+*/
+
+- (void)setContentType:(NSString *)_ctype {
+  _ctype = [_ctype lowercaseString];
+  ApCharSetAccessor(content_type, _ctype);
+}
+- (NSString *)contentType {
+  return [NSString stringWithCString:AP_HANDLE->content_type];
+}
+
+- (void)setContentEncoding:(NSString *)_cencoding {
+  _cencoding = [_cencoding lowercaseString];
+  ApCharSetAccessor(content_encoding, _cencoding);
+}
+- (NSString *)contentEncoding {
+  return [NSString stringWithCString:AP_HANDLE->content_encoding];
+}
+
+- (void)setContentLanguage:(NSString *)_clanguage {
+  _clanguage = [_clanguage lowercaseString];
+  ApCharSetAccessor(content_language, _clanguage);
+}
+- (NSString *)contentLanguage {
+  return [NSString stringWithCString:AP_HANDLE->content_language];
+}
+
+- (NSString *)vlistValidator {
+  return [NSString stringWithCString:AP_HANDLE->vlist_validator];
+}
+
+- (NSArray *)contentLanguages {
+  // array_header *content_languages;  /* array of (char*) */
+  
+  return [self notImplemented:_cmd];
+}
+
+- (void)setHandler:(NSString *)_value {
+  ApCharSetAccessor(handler, _value);
+}
+- (NSString *)handler {
+  return [NSString stringWithCString:AP_HANDLE->handler];
+}
+
+- (BOOL)noCache {
+  return AP_HANDLE->no_cache ? YES : NO;
+}
+- (BOOL)noLocalCopy {
+  return AP_HANDLE->no_local_copy ? YES : NO;
+}
+
+/*
+  What object is being requested (either directly, or via include
+  or content-negotiation mapping).
+*/
+- (NSString *)unparsedURI {
+  return [NSString stringWithCString:AP_HANDLE->unparsed_uri];
+}
+- (NSString *)uri {
+  return [NSString stringWithCString:AP_HANDLE->uri];
+}
+- (NSString *)filename {
+  return [NSString stringWithCString:AP_HANDLE->filename];
+}
+- (NSString *)pathInfo {
+  return [NSString stringWithCString:AP_HANDLE->path_info];
+}
+- (NSString *)queryArgs {
+  return [NSString stringWithCString:AP_HANDLE->args];
+}
+// finfo, parse_uri
+
+- (NSString *)casePreservedFilename {
+  return [NSString stringWithCString:AP_HANDLE->case_preserved_filename];
+}
+
+- (void)parseURI:(NSString *)_uri {
+  ap_parse_uri(AP_HANDLE, [_uri cString]);
+}
+
+/* sub-requests */
+
+- (ApacheRequest *)subRequestLookupURI:(NSString *)_newfile {
+  request_rec *sr;
+  sr = ap_sub_req_lookup_uri([_newfile cString], AP_HANDLE);
+  return [ApacheRequest objectWithHandle:sr];
+}
+- (ApacheRequest *)subRequestLookupURI:(NSString *)_newfile
+  method:(NSString *)_method
+{
+  request_rec *sr;
+  sr = ap_sub_req_method_uri([_method cString], [_newfile cString], AP_HANDLE);
+  return [ApacheRequest objectWithHandle:sr];
+}
+- (ApacheRequest *)subRequestLookupFile:(NSString *)_newfile {
+  request_rec *sr;
+  sr = ap_sub_req_lookup_file([_newfile cString], AP_HANDLE);
+  return [ApacheRequest objectWithHandle:sr];
+}
+
+/* operations */
+
+- (int)runSubRequest {
+  return ap_run_sub_req(AP_HANDLE);
+}
+- (void)destroySubRequest {
+  ap_destroy_sub_req(AP_HANDLE);
+}
+
+- (void)internalRedirect:(NSString *)_uri {
+  ap_internal_redirect([_uri cString], AP_HANDLE);
+}
+- (void)internalRedirectHandler:(NSString *)_uri {
+  ap_internal_redirect_handler([_uri cString], AP_HANDLE);
+}
+
+- (int)someAuthorizationRequired {
+  return ap_some_auth_required(AP_HANDLE);
+}
+- (BOOL)isInitialRequest {
+  return ap_is_initial_req(AP_HANDLE);
+}
+
+- (NSDate *)updateModificationTime:(NSDate *)_date {
+  return [NSDate dateWithTimeIntervalSince1970:
+                   ap_update_mtime(AP_HANDLE, [_date timeIntervalSince1970])];
+}
+
+/* sending headers */
+
+- (void)sendBasicHttpHeader {
+  ap_basic_http_header(AP_HANDLE);
+}
+- (void)sendHttpHeader {
+  ap_send_http_header(AP_HANDLE);
+}
+- (int)sendHttpTrace {
+  return ap_send_http_trace(AP_HANDLE);
+}
+- (int)sendHttpOptions {
+  return ap_send_http_options(AP_HANDLE);
+}
+
+- (void)finalizeRequestProtocol {
+  ap_finalize_request_protocol(AP_HANDLE);
+}
+
+- (void)sendErrorResponse {
+  [self sendErrorResponseWithRecursiveFailStatus:500];
+}
+- (void)sendErrorResponseWithRecursiveFailStatus:(int)_state {
+  ap_send_error_response(AP_HANDLE, _state);
+}
+
+/* modifying headers */
+
+- (int)setContentLength:(unsigned int)_len {
+  return ap_set_content_length(AP_HANDLE, _len);
+}
+- (int)setKeepAlive {
+  return ap_set_keepalive(AP_HANDLE);
+}
+- (NSDate *)rationalizeModificationTime:(NSDate *)_mtime {
+  time_t t;
+  t = ap_rationalize_mtime(AP_HANDLE, [_mtime timeIntervalSince1970]);
+  return [NSDate dateWithTimeIntervalSince1970:t];
+}
+- (NSString *)makeETag:(BOOL)_forceWeak {
+  return [NSString stringWithCString:ap_make_etag(AP_HANDLE, _forceWeak)];
+}
+- (void)setETag {
+  ap_set_etag(AP_HANDLE);
+}
+- (void)setLastModified {
+  ap_set_last_modified(AP_HANDLE);
+}
+- (int)meetsConditions {
+  return ap_meets_conditions(AP_HANDLE);
+}
+
+/* sending content */
+
+- (long)sendFile:(FILE *)_file {
+  return ap_send_fd(_file, AP_HANDLE);
+}
+- (long)sendFile:(FILE *)_file length:(long)_len {
+  return ap_send_fd_length(_file, AP_HANDLE, _len);
+}
+- (unsigned int)sendMMap:(void *)_mm
+  offset:(unsigned int)_off length:(unsigned int)_len
+{
+  return ap_send_mmap(_mm, AP_HANDLE, _off, _len);
+}
+
+- (int)rputc:(int)_c {
+  return ap_rputc(_c, AP_HANDLE);
+}
+- (int)rputs:(const char *)_cstr {
+  return ap_rputs(_cstr, AP_HANDLE);
+}
+- (int)rwrite:(const void *)_buf length:(unsigned int)_len {
+  return ap_rwrite(_buf, _len, AP_HANDLE);
+}
+- (int)rflush {
+  return ap_rflush(AP_HANDLE);
+}
+
+- (int)rwriteData:(NSData *)_data {
+  return ap_rwrite([_data bytes], [_data length], AP_HANDLE);
+}
+
+/* Reading a block of data from the client connection (e.g., POST arg) */
+
+- (int)setupClientBlock:(int)_readPolicy {
+  return ap_setup_client_block(AP_HANDLE, _readPolicy);
+}
+- (int)shouldClientBlock {
+  return ap_should_client_block(AP_HANDLE);
+}
+- (long)getClientBlock:(char *)_buffer length:(int)_bufsiz {
+  return ap_get_client_block(AP_HANDLE, _buffer, _bufsiz);
+}
+- (int)discardRequestBody {
+  return ap_discard_request_body(AP_HANDLE);
+}
+
+/* Sending a byterange */
+
+- (int)setByteRange {
+  return ap_set_byterange(AP_HANDLE);
+}
+// ap_each_byterange(request_rec *r, long *offset, long *length);
+
+/* basic authentication */
+
+- (void)noteAuthFailure {
+  ap_note_auth_failure(AP_HANDLE);
+}
+- (void)noteBasicAuthFailure {
+  ap_note_basic_auth_failure(AP_HANDLE);
+}
+- (int)getBasicAuthPassword:(const char **)_pwd {
+  return ap_get_basic_auth_pw(AP_HANDLE, _pwd);
+}
+
+#undef AP_HANDLE
+
+- (NSString *)description {
+  NSMutableString *ms;
+  id tmp;
+  
+  ms = [NSMutableString stringWithCapacity:128];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  [ms appendFormat:@" 0x%08X", self->handle];
+  
+  if ([self isHeadRequest]) [ms appendString:@" head"];
+  
+  tmp = [self method];
+  if ([tmp length] > 0) [ms appendFormat:@" %@", tmp];
+  tmp = [self uri];
+  if ([tmp length] > 0) [ms appendFormat:@" uri='%@'", tmp];
+
+  if ([self isChunkedReceiving]) [ms appendString:@" in-chunked"];
+  if ([self isChunkedSending])   [ms appendString:@" out-chunked"];
+  
+  if ([self numberOfReadBytes] > 0)
+    [ms appendFormat:@" bytesRead=%i", [self numberOfReadBytes]];
+  if ([self numberOfRemainingBytes] > 0)
+    [ms appendFormat:@" remainingBytes=%i", [self numberOfRemainingBytes]];
+  if ([self bytesSent] > 0)
+    [ms appendFormat:@" bytesSent=%i", [self bytesSent]];
+
+  if ((tmp = [self connection]))
+    [ms appendFormat:@" con=%@", tmp];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+@end /* ApacheRequest */
diff --git a/Recycler/mod_objc/ApacheResourcePool.h b/Recycler/mod_objc/ApacheResourcePool.h
new file mode 100644 (file)
index 0000000..b1593b0
--- /dev/null
@@ -0,0 +1,134 @@
+// $Id: ApacheResourcePool.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheResourcePool_H__
+#define __ApacheResourcePool_H__
+
+#include "ApacheObject.h"
+#include <stdio.h>
+
+/*
+  Note: Apache resource pools are some kind of mixture between an
+  FoundationNSAutoreleasePool and a Foundation NSZone. You should mix
+  up Apache resource pools and autorelease pools !
+
+  Objective-C support: ApacheResourcePool can register release
+  callbacks for Foundation objects.
+  Eg:
+    ApacheResourcePool *p;
+    id s = [[NSString alloc] initWithCString:"blah"];
+    [p releaseObject:s];
+  
+  This will release the string (but not necessarily -dealloc !!!) if the
+  resource pool is freed by Apache.
+
+  Most commonly used Apache resource pools (info take from API notes):
+    
+    permanent-pool:
+      - the "root" pool
+    
+    pconf
+      - subpool of permanent-pool
+      - created at the beginning of the config cycle
+      - exists until the server is restarted or terminated
+      - passed to all config routines via [cmd pool] or inPool:pool
+      - passed to the module init function
+    
+    ptemp
+      - subpool of permanent-pool
+      - created at the beginning of the config cycle
+      - exists until the end of the config parsing
+      - passed to config routines via [cmd temporaryPool]
+    
+    pchild
+      - subpool of permanent-pool
+      - created when a child is forked
+      - exists until child exits
+      - passedto -initializeChildProcessWithServer:inPool: and
+        -exitChildProcessWithServer:inPool:
+    
+    ptrans
+      - subpool of permanent-pool
+      - created by child before going into the accept loop
+      - passed in with [connection pool]
+    
+    r->pool
+      - for the main request a subpool of ptrans
+        for sub requests a subpool of the parent request pool
+      - exist until the end of the processing of the request
+      - note: the request itself is allocated from this pool !!
+*/
+
+@interface ApacheResourcePool : ApacheObject
+{
+}
+
+- (id)makeSubPool;
+
+/* Clearing out EVERYTHING in an pool... destroys any sub-pools */
+- (void)clearPool;
+
+- (BOOL)isAncestorOf:(ApacheResourcePool *)_pool;
+
+/* stats */
+
+- (unsigned int)bytesInPool;
++ (unsigned int)bytesInFreeBlocks;
+
+/* memory blocks */
+
+- (void *)malloc:(unsigned)size;
+- (void *)mallocAtomic:(unsigned)size;
+- (void *)calloc:(unsigned)numElems byteSize:(unsigned)byteSize;
+- (void *)callocAtomic:(unsigned)numElems byteSize:(unsigned)byteSize;
+
+- (void *)realloc:(void*)pointer size:(unsigned)size;
+- (void)freePointer:(void *)pointer;
+
+/* string allocations */
+
+- (unsigned char *)strdup:(const unsigned char *)_cstr;
+- (unsigned char *)strdup:(const unsigned char *)_cstr length:(unsigned)_l;
+- (unsigned char *)strcat:(const unsigned char *)_cstr;
+- (unsigned char *)pvsprintf:(const unsigned char *)_fmt arguments:(va_list)va;
+
+/* file allocations */
+
+- (FILE *)openFile:(NSString *)_name mode:(NSString *)_mode;
+- (FILE *)openFD:(int)_fd mode:(NSString *)_mode;
+- (int)popenf:(NSString *)_name flag:(int)_flg mode:(int)_mode;
+
+- (void)closeFile:(FILE *)_file;
+- (void)pclosef:(int)_fd;
+#ifdef WIN32
+- (void)closeHandle:(HANDLE)_h;
+#endif
+
+- (void)noteCleanUpsForFile:(FILE *)_file;
+- (void)noteCleanUpsForFD:(int)_fd;
+#ifdef WIN32
+- (void)noteCleanUpsForHandle:(HANDLE)_h;
+#endif
+- (void)killCleanUpsForFD:(int)_fd;
+
+/* process management */
+
+/*
+  Preparing for exec() --- close files, etc., but *don't* flush I/O
+  buffers, *don't* wait for subprocesses, and *don't* free any memory.
+*/
++ (void)cleanUpForExec;
+
+/* Objective-C objects */
+
+- (void)releaseObject:(id)_object;
+- (void)unreleaseObject:(id)_object;
+
+@end
+
+@interface NSObject(PoolRelease)
+
+- (void)cleanupForApacheExec; /* called before exec() */
+
+@end
+
+#endif /* __ApacheResourcePool_H__ */
diff --git a/Recycler/mod_objc/ApacheResourcePool.m b/Recycler/mod_objc/ApacheResourcePool.m
new file mode 100644 (file)
index 0000000..39657b6
--- /dev/null
@@ -0,0 +1,179 @@
+// $Id: ApacheResourcePool.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheResourcePool.h"
+#include "httpd.h"
+#include "ap_alloc.h"
+#include <Foundation/Foundation.h>
+
+@implementation ApacheResourcePool
+
+- (void)destroyHandle {
+  if (self->handle) {
+    ap_destroy_pool(self->handle);
+    self->handle = NULL;
+  }
+}
+- (id)makeSubPool {
+  ap_pool *p;
+
+  if (self->handle == NULL)
+    return nil;
+  
+  if ((p = ap_make_sub_pool(self->handle)) == NULL)
+    return nil;
+  
+  return [[[ApacheResourcePool alloc]
+                               initWithHandle:p freeWhenDone:YES]
+                               autorelease];
+}
+- (void)clearPool {
+  if (self->handle) ap_clear_pool(self->handle);
+}
+
+- (BOOL)isAncestorOf:(ApacheResourcePool *)_pool {
+#ifdef POOL_DEBUG
+  if (_pool      == NULL) return NO;
+  if (self->handle == NULL) return NO;
+
+  return ap_pool_is_ancestor(self->handle, _pool) ? YES : NO;
+#else
+  return NO;
+#endif
+}
+
+/* stats */
+
+- (unsigned int)bytesInPool {
+  if (self->handle == NULL) return 0;
+  return ap_bytes_in_pool(self->handle);
+}
++ (unsigned int)bytesInFreeBlocks {
+  return ap_bytes_in_free_blocks();
+}
+
+/* memory blocks */
+
+- (void *)malloc:(unsigned)size {
+  if (self->handle == NULL) return NULL;
+  return ap_palloc(self->handle, size);
+}
+- (void *)mallocAtomic:(unsigned)size {
+  if (self->handle == NULL) return NULL;
+  return ap_palloc(self->handle, size);
+}
+- (void *)calloc:(unsigned)numElems byteSize:(unsigned)byteSize {
+  if (self->handle == NULL) return NULL;
+  return ap_pcalloc(self->handle, byteSize * numElems);
+}
+- (void *)callocAtomic:(unsigned)numElems byteSize:(unsigned)byteSize {
+  if (self->handle == NULL) return NULL;
+  return ap_pcalloc(self->handle, byteSize * numElems);
+}
+
+- (void *)realloc:(void*)pointer size:(unsigned)size {
+  return NULL;
+}
+- (void)freePointer:(void *)pointer {
+}
+
+/* string allocations */
+
+- (unsigned char *)strdup:(const unsigned char *)_cstr {
+  if (self->handle == NULL) return NULL;
+  return ap_pstrdup(self->handle, _cstr);
+}
+- (unsigned char *)strdup:(const unsigned char *)_cstr length:(unsigned)_l {
+  if (self->handle == NULL) return NULL;
+  return ap_pstrndup(self->handle, _cstr, _l);
+}
+- (unsigned char *)strcat:(const unsigned char *)_cstr {
+  if (self->handle == NULL) return NULL;
+  return ap_pstrcat(self->handle, _cstr, NULL);
+}
+- (unsigned char *)pvsprintf:(const unsigned char *)_fmt arguments:(va_list)va{
+  if (self->handle == NULL) return NULL;
+  return ap_pvsprintf(self->handle, _fmt, va);
+}
+
+/* file allocations */
+
+- (FILE *)openFile:(NSString *)_name mode:(NSString *)_mode {
+  return ap_pfopen(self->handle, [_name cString], [_mode cString]);
+}
+- (FILE *)openFD:(int)_fd mode:(NSString *)_mode {
+  return ap_pfdopen(self->handle, _fd, [_mode cString]);
+}
+- (int)popenf:(NSString *)_name flag:(int)_flg mode:(int)_mode {
+  return ap_popenf(self->handle, [_name cString], _flg, _mode);
+}
+
+- (void)closeFile:(FILE *)_file {
+  ap_pfclose(self->handle, _file);
+}
+- (void)pclosef:(int)_fd {
+  ap_pclosef(self->handle, _fd);
+}
+#ifdef WIN32
+- (void)closeHandle:(HANDLE)_h {
+  ap_pcloseh(self->handle, _h);
+}
+#endif
+
+- (void)noteCleanUpsForFile:(FILE *)_file {
+  ap_note_cleanups_for_file(self->handle, _file);
+}
+- (void)noteCleanUpsForFD:(int)_fd {
+  ap_note_cleanups_for_fd(self->handle, _fd);
+}
+#ifdef WIN32
+- (void)noteCleanUpsForHandle:(HANDLE)_h {
+  ap_note_cleanups_for_h(self->handle, _h);
+}
+#endif
+- (void)killCleanUpsForFD:(int)_fd {
+  ap_kill_cleanups_for_fd(self->handle, _fd);
+}
+
+/* process management */
+
++ (void)cleanUpForExec {
+  ap_cleanup_for_exec();
+}
+
++ (void)blockAlarms {
+  ap_block_alarms();
+}
++ (void)unlockAlarms {
+  ap_unblock_alarms();
+}
+
+/* Objective-C objects */
+
+static void plainReleaseCleanup(void *data) {
+  if (data) [(id)data release];
+}
+static void childReleaseCleanup(void *data) {
+  if (data) {
+    if ([(id)data respondsToSelector:@selector(cleanupForApacheExec)])
+      [(id)data cleanupForApacheExec];
+  }
+}
+
+- (void)releaseObject:(id)_object {
+  if (_object == nil) return;
+
+  ap_block_alarms();
+  ap_register_cleanup(self->handle, _object,
+                      plainReleaseCleanup,
+                      childReleaseCleanup);
+  ap_unblock_alarms();
+}
+- (void)unreleaseObject:(id)_object {
+  if (_object == nil) return;
+  
+  ap_block_alarms();
+  ap_kill_cleanup(self->handle, _object, plainReleaseCleanup);
+  ap_unblock_alarms();
+}
+
+@end /* ApacheResourcePool */
diff --git a/Recycler/mod_objc/ApacheServer.h b/Recycler/mod_objc/ApacheServer.h
new file mode 100644 (file)
index 0000000..1d41070
--- /dev/null
@@ -0,0 +1,57 @@
+// $Id: ApacheServer.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheServer_H__
+#define __ApacheServer_H__
+
+#include <ApacheAPI/ApacheObject.h>
+
+@interface ApacheServer : ApacheObject
+{
+}
+
+/* accessors */
+
+- (ApacheServer *)nextServer;
+
+/* description of where the definition came from */
+
+- (NSString *)definitionName;
+- (unsigned int)definitionLineNumber;
+
+/* locations of server config info */
+
+- (NSString *)srmConfigName;
+- (NSString *)accessConfigName;
+
+- (NSString *)serverAdmin;
+- (NSString *)serverHostName;
+- (unsigned short)port;
+
+/* log files */
+
+- (NSString *)errorFileName;
+- (FILE *)errorLogFile;
+- (int)logLevel;
+
+/* module-specific configuration for server, and defaults... */
+
+- (BOOL)isVirtual;
+
+/* transaction handling */
+
+- (NSTimeInterval)timeout;
+- (NSTimeInterval)keepAliveTimeout;
+- (int)keepAliveMax;
+- (BOOL)keepAlive;
+- (int)sendBufferSize;
+
+- (id)serverUserId;
+- (id)serverGroupId;
+
+- (int)requestLineLimit;
+- (int)requestFieldSizeLimit;
+- (int)requestFieldCountLimit;
+
+@end
+
+#endif /* __ApacheServer_H__ */
diff --git a/Recycler/mod_objc/ApacheServer.m b/Recycler/mod_objc/ApacheServer.m
new file mode 100644 (file)
index 0000000..3317ee7
--- /dev/null
@@ -0,0 +1,151 @@
+// $Id: ApacheServer.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheServer.h"
+#include <httpd.h>
+#import <Foundation/Foundation.h>
+
+static NSString *mkString(const char *str) {
+  static Class NSStringClass = Nil;
+  unsigned len;
+
+  if (str == NULL) return nil;
+  if (NSStringClass == Nil) NSStringClass = [NSString class];
+  if ((len = strlen(str)) == 0) return nil;
+
+  return [[[NSStringClass alloc] initWithCString:str] autorelease];
+}
+
+@implementation ApacheServer
+#define AP_HANDLE ((server_rec *)self->handle)
+
+/* accessors */
+
+- (ApacheServer *)nextServer {
+  return [[[ApacheServer alloc] initWithHandle:AP_HANDLE->next] autorelease];
+}
+
+/* description of where the definition came from */
+
+- (NSString *)definitionName {
+  return mkString(AP_HANDLE->defn_name);
+}
+- (unsigned int)definitionLineNumber {
+  return AP_HANDLE->defn_line_number;
+}
+
+/* Full locations of server config info */
+
+- (NSString *)srmConfigName {
+  return mkString(AP_HANDLE->srm_confname);
+}
+- (NSString *)accessConfigName {
+  return mkString(AP_HANDLE->access_confname);
+}
+
+- (NSString *)serverAdmin {
+  return mkString(AP_HANDLE->server_admin);
+}
+- (NSString *)serverHostName {
+  return mkString(AP_HANDLE->server_hostname);
+}
+- (unsigned short)port {
+  return AP_HANDLE->port;
+}
+
+/* log files */
+
+- (NSString *)errorFileName {
+  return mkString(AP_HANDLE->error_fname);
+}
+- (FILE *)errorLogFile {
+  return AP_HANDLE->error_log;
+}
+- (int)logLevel {
+  return AP_HANDLE->loglevel;
+}
+
+/* module-specific configuration for server, and defaults... */
+
+- (BOOL)isVirtual {
+  return AP_HANDLE->is_virtual ? YES : NO;
+}
+
+/* transaction handling */
+
+- (NSTimeInterval)timeout {
+  return AP_HANDLE->timeout;
+}
+- (NSTimeInterval)keepAliveTimeout {
+  return AP_HANDLE->keep_alive_timeout;
+}
+- (int)keepAliveMax {
+  return AP_HANDLE->keep_alive_max;
+}
+- (BOOL)keepAlive {
+  return AP_HANDLE->keep_alive ? YES : NO;
+}
+- (int)sendBufferSize {
+  return AP_HANDLE->send_buffer_size;
+}
+
+- (NSString *)serverPath {
+  return [NSString stringWithCString:AP_HANDLE->path
+                   length:AP_HANDLE->pathlen];
+}
+
+#warning names, wild_names
+
+- (id)serverUserId {
+  return [NSNumber numberWithInt:AP_HANDLE->server_uid];
+}
+- (id)serverGroupId {
+  return [NSNumber numberWithInt:AP_HANDLE->server_gid];
+}
+
+- (int)requestLineLimit {
+  return AP_HANDLE->limit_req_line;
+}
+- (int)requestFieldSizeLimit {
+  return AP_HANDLE->limit_req_fieldsize;
+}
+- (int)requestFieldCountLimit {
+  return AP_HANDLE->limit_req_fields;
+}
+
+/* description */
+
+- (NSString *)description {
+  NSMutableString *ms;
+  id tmp;
+
+  ms = [NSMutableString stringWithCapacity:128];
+  [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])];
+  [ms appendFormat:@" 0x%08X", self->handle];
+  
+  if ([self isVirtual])
+    [ms appendString:@" virtual"];
+  
+  [ms appendFormat:@" uid=%@ gid=%@",
+        [self serverUserId], [self serverGroupId]];
+  
+  if ([(tmp = [self definitionName]) length] > 0)
+    [ms appendFormat:@" def=%@:%i", tmp, [self definitionLineNumber]];
+
+  if ((tmp = [self serverHostName]))
+    [ms appendFormat:@" host=%@:%i", tmp, [self port]];
+
+#if 0
+  if ((tmp = [self serverAdmin]))
+    [ms appendFormat:@" admin=%@", tmp];
+#endif
+  
+  [ms appendFormat:@" loglevel=%i", [self logLevel]];
+  
+  if ((tmp = [self nextServer]))
+    [ms appendFormat:@" next=%@", tmp];
+  
+  [ms appendString:@">"];
+  return ms;
+}
+
+@end /* ApacheServer */
diff --git a/Recycler/mod_objc/ApacheTable.h b/Recycler/mod_objc/ApacheTable.h
new file mode 100644 (file)
index 0000000..6a71d1e
--- /dev/null
@@ -0,0 +1,28 @@
+// $Id: ApacheTable.h,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#ifndef __ApacheTable_H__
+#define __ApacheTable_H__
+
+#include "ApacheObject.h"
+
+@interface ApacheTable : ApacheObject
+{
+}
+
+/* query */
+
+- (id)objectForKey:(NSString *)_key;
+
+/* modification */
+
+- (void)setObject:(id)_obj forKey:(NSString *)_key;
+
+- (void)mergeObject:(id)_obj forKey:(NSString *)_key;
+- (void)addObject:(id)_obj forKey:(NSString *)_key;
+
+- (void)removeAllObjects;
+- (void)removeObjectForKey:(NSString *)_key;
+
+@end
+
+#endif /* __ApacheTable_H__ */
diff --git a/Recycler/mod_objc/ApacheTable.m b/Recycler/mod_objc/ApacheTable.m
new file mode 100644 (file)
index 0000000..f0f2a64
--- /dev/null
@@ -0,0 +1,50 @@
+// $Id: ApacheTable.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "ApacheTable.h"
+#import <Foundation/NSString.h>
+#include <NGExtensions/NGExtensions.h>
+#include "httpd.h"
+#include "ap_alloc.h"
+
+@implementation ApacheTable
+#define AP_HANDLE ((table *)self->handle)
+
+/* query */
+
+- (id)objectForKey:(NSString *)_key {
+  return [NSString stringWithCString:ap_table_get(AP_HANDLE, [_key cString])];
+}
+
+/* modification */
+
+- (void)setObject:(id)_obj forKey:(NSString *)_key {
+  const char *v;
+  
+  if ((v = [[_obj stringValue] cString]))
+    ap_table_set(AP_HANDLE, [_key cString], v);
+  else
+    ap_table_unset(AP_HANDLE, [_key cString]);
+}
+
+- (void)mergeObject:(id)_obj forKey:(NSString *)_key {
+  const char *v;
+  
+  if ((v = [[_obj stringValue] cString]))
+    ap_table_merge(AP_HANDLE, [_key cString], v);
+}
+- (void)addObject:(id)_obj forKey:(NSString *)_key {
+  const char *v;
+  
+  if ((v = [[_obj stringValue] cString]))
+    ap_table_add(AP_HANDLE, [_key cString], v);
+}
+
+- (void)removeAllObjects {
+  ap_clear_table(AP_HANDLE);
+}
+- (void)removeObjectForKey:(NSString *)_key {
+  ap_table_unset(AP_HANDLE, [_key cString]);
+}
+
+#undef AP_HANDLE
+@end /* ApacheTable */
diff --git a/Recycler/mod_objc/GNUmakefile b/Recycler/mod_objc/GNUmakefile
new file mode 100644 (file)
index 0000000..1373254
--- /dev/null
@@ -0,0 +1,50 @@
+# $Id: GNUmakefile,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+include $(GNUSTEP_MAKEFILES)/common.make
+
+LIBRARY_NAME = libApacheAPI libApHelper
+BUNDLE_NAME  = ApTest
+MODULE_NAME  = gsbundle
+
+libApacheAPI_OBJC_FILES = \
+       ApacheCmdParms.m                \
+       ApacheConnection.m              \
+       ApacheObject.m                  \
+       ApacheRequest.m                 \
+       ApacheResourcePool.m            \
+       ApacheServer.m                  \
+       ApacheTable.m                   \
+       ApacheModule.m                  \
+       ApModuleBaseClass.m             \
+       ApModuleBaseClass+Callbacks.m   \
+       ApModuleBaseClass+Handler.m     \
+       ApModuleBaseClass+Cmds.m        \
+
+libApHelper_OBJC_FILES = \
+       GSBundleModule.m        \
+
+gsbundle_OBJC_FILES = \
+       mod_gsbundle.m          \
+
+ApTest_PRINCIPAL_CLASS = ApTest
+ApTest_OBJC_FILES = \
+       ApTest.m                        \
+       ApTest_module_structure.m       \
+
+libApHelper_LIBRARIES_DEPEND_UPON += \
+       -lApacheAPI     \
+       -lFoundation    \
+       -lobjc          \
+       -lpthread
+
+ADDITIONAL_LIB_DIRS  += -L./$(GNUSTEP_OBJ_DIR)
+ApTest_BUNDLE_LIBS   += -lApacheAPI
+
+gsbundle_TOOL_LIBS   += -lpthread -ldl
+
+include $(GNUSTEP_MAKEFILES)/library.make
+include $(GNUSTEP_MAKEFILES)/apache.make
+include $(GNUSTEP_MAKEFILES)/bundle.make
+
+before-ApTest-all:: 
+       genApacheModule.sh ApTest ApTest_module_structure.m
diff --git a/Recycler/mod_objc/GSBundleModule.m b/Recycler/mod_objc/GSBundleModule.m
new file mode 100644 (file)
index 0000000..bf803d5
--- /dev/null
@@ -0,0 +1,407 @@
+// $Id: GSBundleModule.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "httpd.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "ap_config.h"
+
+#include "ApacheCmdParms.h"
+#include "ApacheServer.h"
+#include "ApacheModule.h"
+#include "ApacheResourcePool.h"
+#import <Foundation/Foundation.h>
+
+/*
+  Note:
+  
+  an Apache module gets *unloaded* during the config process !!!
+
+  This is why we have this helper shared object which is not unloaded :-)
+*/
+
+@interface NSObject(ModuleClass)
++ (void)setBundleHandler:(id)_handler;
+- (module *)apacheModule;
+@end
+
+static void _ensureObjCEnvironment(void) {
+#if LIB_FOUNDATION_LIBRARY
+  extern char **environ; /* man 5 environ */
+  static char *argv[2] = { "apache", NULL };
+  [NSProcessInfo initializeWithArguments:argv
+                 count:1
+                 environment:environ];
+#endif
+}
+
+@interface ApBundleInfo : NSObject
+{
+@public
+  ApacheResourcePool *configPool;
+  NSString     *bundlePath;
+  NSString     *bundleName;
+  NSBundle     *bundle;
+  module       *apacheModule;
+  ApacheModule *bundleHandler;
+  BOOL         moduleAdded;
+  BOOL         bundleLoaded;
+}
+
++ (NSString *)makeBundlePathAbsolute:(NSString *)_relpath;
++ (ApBundleInfo *)bundleInfoForPath:(NSString *)_relpath;
+
+/* accessors */
+
+- (NSBundle *)bundle;
+- (NSString *)bundleModuleClassName;
+- (Class)bundleModuleClass;
+
+- (BOOL)isBundleLoaded;
+- (BOOL)isApacheModuleInitialized;
+
+/* operations */
+
+- (NSString *)setUpWithArgs:(NSString *)_args
+  inPool:(ApacheResourcePool *)_pool;
+- (void)tearDown;
+
+- (void)configureForServer:(ApacheServer *)_server;
+
+@end
+
+@implementation ApBundleInfo
+
++ (ApBundleInfo *)bundleInfoForPath:(NSString *)_relpath {
+  static NSMutableDictionary *pathToInfo = nil;
+  NSString     *p;
+  ApBundleInfo *bi;
+  
+  p = [self makeBundlePathAbsolute:_relpath];
+  if ([p length] == 0) return nil;
+  
+  if (pathToInfo == nil)
+    pathToInfo = [[NSMutableDictionary alloc] initWithCapacity:16];
+
+  if ((bi = [pathToInfo objectForKey:p]))
+    return bi;
+  
+  if ((bi = [[self alloc] initWithPath:p])) {
+    [pathToInfo setObject:bi forKey:p];
+    RELEASE(bi);
+  }
+  return bi;
+}
++ (NSString *)makeBundlePathAbsolute:(NSString *)_relpath {
+  NSString *s;
+  
+  if ([_relpath length] == 0) return nil;
+  
+  s = [[[NSProcessInfo processInfo]
+                       environment]
+                       objectForKey:@"GNUSTEP_SYSTEM_ROOT"];
+  s = [s stringByAppendingPathComponent:@"Library/Bundles"];
+  s = [s stringByAppendingPathComponent:_relpath];
+  
+  return s;
+}
+
+- (id)initWithPath:(NSString *)_path {
+  if ([_path length] == 0) {
+    RELEASE(self);
+    return nil;
+  }
+  if (![_path isAbsolutePath]) {
+    NSLog(@"bundle path '%@' is not absolute ...", _path);
+    RELEASE(self);
+    return nil;
+  }
+  
+  self->bundlePath = [_path copy];
+  self->bundleName =
+    [[[_path lastPathComponent] stringByDeletingPathExtension] copy];
+  self->bundle     = [[NSBundle bundleWithPath:self->bundlePath] retain];
+  
+  if (self->bundle == nil) {
+    NSLog(@"missing bundle at path %@", self->bundlePath);
+    RELEASE(self);
+    return nil;
+  }
+  
+  return self;
+}
+
+- (void)dealloc {
+  NSAutoreleasePool *pool;
+
+  pool = [[NSAutoreleasePool alloc] init];
+  RELEASE(self->configPool);
+  RELEASE(self->bundleHandler);
+  RELEASE(self->bundlePath);
+  RELEASE(self->bundleName);
+  RELEASE(self->bundle);
+  RELEASE(pool);
+  [super dealloc];
+}
+
+/* accessors */
+
+- (BOOL)isBundleLoaded {
+  if (self->bundle == nil) return NO;
+  return self->bundleLoaded;
+}
+- (BOOL)isApacheModuleInitialized {
+  if (self->apacheModule == NULL) return NO;
+  return self->moduleAdded;
+}
+
+- (NSBundle *)bundle {
+  return self->bundle;
+}
+
+- (NSString *)bundleModuleClassName {
+  return [self->bundleName stringByAppendingString:@"Mod_Module_Class"];
+}
+- (Class)bundleModuleClass {
+  /* the class which manages the module structure (helper class) */
+  return NSClassFromString([self bundleModuleClassName]);
+}
+
+- (Class)bundleHandlerClass {
+  /* the class which represents the apache module itself */
+  Class c;
+  
+  if ((c = [self->bundle principalClass]) == Nil)
+    return nil;
+  if (![c isKindOfClass:[ApacheModule class]])
+    return nil;
+  
+  return c;
+}
+
+/* operations */
+
+- (NSString *)setUpWithArgs:(NSString *)_args
+  inPool:(ApacheResourcePool *)_pool
+{
+  NSAutoreleasePool *pool;
+  Class modClass;
+  
+  /* check pre-conditions */
+
+  if (self->bundle == nil) {
+    return [NSString stringWithFormat:@"%s: missing bundle info",
+                       __PRETTY_FUNCTION__];
+  }
+  if (self->configPool)
+    return @"config pool is already setup";
+  if (self->bundleHandler)
+    return @"bundle handler is already set up !!!";
+  
+  pool = [[NSAutoreleasePool alloc] init];
+
+#if 0
+  printf("\nSETUP 0x%08X (loaded=%s) ...\n", (unsigned int)self,
+         self->bundleLoaded ? "yes" : "no");
+  fflush(stdout);
+#endif
+  
+  /* Step 0: setup resource pool wrapper */
+  
+  self->configPool = RETAIN(_pool);
+  
+  /* Step 1: Load bundle if not done already ... */
+  
+  if (!self->bundleLoaded) {
+    if (![self->bundle load]) {
+      return
+        [NSString stringWithFormat:@"couldn't load bundle %@", self->bundle];
+    }
+    self->bundleLoaded = YES;
+  }
+  
+  if ((modClass = [self bundleModuleClass]) == Nil) {
+    RELEASE(pool);
+    return [NSString stringWithFormat:
+                       @"did not find bundle module class (name=%@) ...",
+                       [self bundleModuleClassName]];
+  }
+  
+  /* Step 2: Initialize bundle handler object ... */
+  
+  self->bundleHandler = [[[self bundleHandlerClass] alloc] init];
+  if (self->bundleHandler == nil) {
+    RELEASE(pool);
+    return [NSString stringWithFormat:
+                       @"couldn't initialize bundle handler of class '%@'",
+                       [self bundleHandlerClass]];
+  }
+  
+  /* Step 3: Remember bundle handler in module-handler class ... */
+  
+  [modClass setBundleHandler:self->bundleHandler];
+  
+  /* Step 4: add Apache C module structure */
+  
+  if ((self->apacheModule = [modClass apacheModule]) == NULL) {
+    RELEASE(pool);
+    return @"did not find apache module structure of bundle";
+  }
+  if (self->apacheModule->magic != MODULE_MAGIC_COOKIE) {
+    RELEASE(pool);
+    return [NSString stringWithFormat:
+                       @"API module structure of bundle is broken !"];
+  }
+  
+  /* Step 5: register module with apache ... */
+  
+  ap_add_loaded_module(self->apacheModule);
+  self->moduleAdded = YES;
+  
+  /* release pool & done */
+  
+  RELEASE(pool);
+  
+  return nil;
+}
+
+- (void)tearDown {
+  NSAutoreleasePool *pool;
+
+  pool = [[NSAutoreleasePool alloc] init];
+
+#if 0
+  printf("TEARDOWN 0x%08X ...\n", (unsigned int)self);
+  fflush(stdout);
+#endif
+
+  /* Reverse Step 5: unregister module with apache */
+  
+  if ((self->apacheModule != NULL) && self->moduleAdded)
+    ap_remove_loaded_module(self->apacheModule);
+  
+  self->moduleAdded = NO;
+  
+  /* Reverse Step 4: reset apache module structure */
+  self->apacheModule = NULL;
+  
+  /* Reverse Step 3: reset bundle handler in module-handler class ... */
+  [[self bundleModuleClass] setBundleHandler:nil];
+  
+  /* Reverse Step 2: release bundle handler object ... */
+  RELEASE(self->bundleHandler);
+  self->bundleHandler = nil;
+  
+  /* DO NOT reverse Step 1 ... */
+
+  /* Reverse Step 0: release config pool proxy */
+  RELEASE(self->configPool); self->configPool = nil;
+  
+  RELEASE(pool);
+}
+
+- (void)configureForServer:(ApacheServer *)_server {
+  if (self->apacheModule == NULL) {
+    NSLog(@"missing bundle module ...");
+    return;
+  }
+  if (self->configPool == NULL) {
+    NSLog(@"missing config pool ...");
+    return;
+  }
+
+#if DEBUG && 0
+  printf("CONFIGURE 0x%08X ...\n", (unsigned int)self);
+  fflush(stdout);
+#endif
+  
+  ap_single_module_configure([self->configPool handle],
+                             [_server handle],
+                             self->apacheModule);
+}
+
+@end /* ApBundleInfo */
+
+static void unloadModule(void *data) {
+  ApBundleInfo *binfo;
+
+  if ((binfo = (void *)data)) {
+    [binfo tearDown];
+  }
+}
+
+static int callCount = 0;
+
+/* Called when the LoadBundle config directive is found */
+const char *GSBundleModuleLoadBundleCommand
+(module *module, cmd_parms *cmd, char *bundlePath)
+{
+  const char         *result = NULL;
+  ApacheCmdParms     *paras;
+  NSAutoreleasePool  *opool;
+  NSString     *bp, *args;
+  ApBundleInfo *bi;
+  id tmp;
+  
+  _ensureObjCEnvironment();
+  callCount++;
+  
+#if HEAVY_GSBUNDLE_DEBUG
+  printf("%s: #%i module=0x%08X pid=%i "
+         "(cmd=0x%08X,bp=0x%08X) ...\n",
+         __PRETTY_FUNCTION__, callCount, (unsigned int)module, getpid(),
+         (unsigned int)cmd, (unsigned int)bundlePath);
+  fflush(stdout); fflush(stderr);
+#endif
+  
+  opool = [[NSAutoreleasePool alloc] init];
+  paras = [[ApacheCmdParms alloc] initWithHandle:cmd];
+  
+  /* separate bundle path from bundle args */
+  
+  tmp = [NSString stringWithCString:bundlePath];
+#if HEAVY_GSBUNDLE_DEBUG
+  printf("%s: %s\n", __PRETTY_FUNCTION__, [[s description] cString]);
+  printf("  paras: %s\n",  [[paras description] cString]);
+  printf("  server: %s\n", [[[paras server] description] cString]);
+  fflush(stdout); fflush(stderr);
+#endif
+  
+  /* separate bundle path and load arguments ... */
+  {
+    unsigned idx;
+    
+    if ((idx = [tmp indexOfString:@" "]) == NSNotFound) {
+      bp   = tmp;
+      args = nil;
+    }
+    else {
+      bp   = [tmp substringToIndex:idx];
+      args = [tmp substringFromIndex:(idx + 1)];
+    }
+  }
+  
+  /* makeup absolute bundle path */
+
+  if ((bi = [ApBundleInfo bundleInfoForPath:bp]) == nil) {
+    result = ap_pstrcat(cmd->pool, "bundle at '", [bp cString], "' could "
+                        "not find info !");
+    goto done;
+  }
+
+  if ((tmp = [bi setUpWithArgs:args inPool:[paras pool]])) {
+    result = ap_pstrdup(cmd->pool, [tmp cString]);
+    goto done;
+  }
+
+  /* register cleanup */
+  ap_register_cleanup(cmd->pool, bi, 
+                      (void (*)(void*))unloadModule, ap_null_cleanup);
+  
+  /* run module configuration */
+  [bi configureForServer:[paras server]];
+  
+ done:
+  RELEASE(paras);
+  RELEASE(opool);
+  return result;
+}
diff --git a/Recycler/mod_objc/README b/Recycler/mod_objc/README
new file mode 100644 (file)
index 0000000..21bd560
--- /dev/null
@@ -0,0 +1,7 @@
+# $Id: README,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+TODO
+- resolve mem-leaks created by handler and command tables
+
+Last change: 20011126?
+
diff --git a/Recycler/mod_objc/genApacheModule.sh b/Recycler/mod_objc/genApacheModule.sh
new file mode 100755 (executable)
index 0000000..e338b49
--- /dev/null
@@ -0,0 +1,146 @@
+#!/bin/sh
+
+MODULENAME=$1
+MFILE=$2
+MODULECLASS="${MODULENAME}Mod_Module_Class"
+
+#
+# This tool is used to generate Apache module stub structures and classes.
+#
+# An Objective-C class is used to "emulate" a module object.
+#
+
+echo "creating structure for Apache module ${MODULENAME} in file ${MFILE} ..."
+
+cat >$MFILE <<EOF
+/*
+  DO NOT EDIT, automagically generated !!
+  
+    Apache module: ${MODULENAME}
+    Module file:   ${MFILE}
+    Module class:  ${MODULECLASS}
+    Date:          `date`
+    Generated By:  ${USER}
+    Generator:     $0
+*/
+
+#include "ApModuleBaseClass.h"
+#include <httpd.h>
+#include "http_config.h"
+#import <Foundation/NSBundle.h>
+#import <Foundation/NSString.h>
+#include "ApacheModule.h"
+
+static module ${MODULENAME}_module_template;
+module MODULE_VAR_EXPORT ${MODULENAME}_module;
+
+@interface ${MODULECLASS} : ApModuleBaseClass
+@end
+
+@implementation ${MODULECLASS}
+
+static ApacheModule *bundleHandler = nil;
+
++ (void)setBundleHandler:(ApacheModule *)_handler {
+  if (_handler == bundleHandler)
+    return;
+  
+  if ((bundleHandler != nil) && (_handler != nil)) {
+    printf("WARNING(%s): handler of bundle %s already set !\n",
+           __PRETTY_FUNCTION__,
+           [[[NSBundle bundleForClass:self] description] cString]);
+  }
+  
+  ASSIGN(bundleHandler, _handler);
+}
++ (ApacheModule *)bundleHandler {
+  return bundleHandler;
+}
+
++ (void *)apacheTemplateModule {
+  return &(${MODULENAME}_module_template);
+}
++ (void *)apacheModuleStructure {
+  return &${MODULENAME}_module;
+}
+
+static int _handleRequest(request_rec *_request) {
+  return [${MODULECLASS} _handleRequest:_request];
+}
++ (void *)handleRequestStubFunction {
+  return &_handleRequest;
+}
+
+@end /* ${MODULECLASS} */
+
+static void _moduleInit(server_rec *s, pool *p) {
+  [${MODULECLASS} _moduleInit:s pool:p];
+}
+
+static void *_perDirConfCreate(pool *p, char *dirspec) {
+  return [${MODULECLASS} _perDirConfCreate:dirspec pool:p];
+}
+static void *_perDirConfMerge(pool *p, void *baseConf, void *newConf) {
+  return [${MODULECLASS} _perDirConfMerge:baseConf with:newConf pool:p];
+}
+
+static void *_perServerConfCreate(pool *p, server_rec *s) {
+  return [${MODULECLASS} _perServerConfCreate:s pool:p];
+}
+static void *_perServerConfMerge(pool *p, void *baseConf, void *newConf) {
+  return [${MODULECLASS} _perServerConfMerge:baseConf with:newConf pool:p];
+}
+
+static int _translateHandler(request_rec *_request) {
+  return [${MODULECLASS} _translateHandler:_request];
+}
+static int _apCheckUserId(request_rec *_request) {
+  return [${MODULECLASS} _apCheckUserId:_request];
+}
+static int _authChecker(request_rec *_request) {
+  return [${MODULECLASS} _authChecker:_request];
+}
+static int _accessChecker(request_rec *_request) {
+  return [${MODULECLASS} _accessChecker:_request];
+}
+static int _typeChecker(request_rec *_request) {
+  return [${MODULECLASS} _typeChecker:_request];
+}
+static int _fixerUpper(request_rec *_request) {
+  return [${MODULECLASS} _fixerUpper:_request];
+}
+static int _logger(request_rec *_request) {
+  return [${MODULECLASS} _logger:_request];
+}
+static int _headerParser(request_rec *_request) {
+  return [${MODULECLASS} _headerParser:_request];
+}
+
+static void _childInit(server_rec *_server, pool *_pool) {
+  [${MODULECLASS} _childInit:_server pool:_pool];
+}
+static void _childExit(server_rec *_server, pool *_pool) {
+  [${MODULECLASS} _childExit:_server pool:_pool];
+}
+
+static int _postReadRequest(request_rec *_request) {
+  return [${MODULECLASS} _postReadRequest:_request];
+}
+
+static module ${MODULENAME}_module_template = {
+    STANDARD_MODULE_STUFF,
+    _moduleInit, _perDirConfCreate, _perDirConfMerge,
+    _perServerConfCreate, _perServerConfMerge,
+    NULL,  /* table of config file commands       */
+    NULL,  /* [#8] MIME-typed-dispatched handlers */
+    _translateHandler, _apCheckUserId, _authChecker, _accessChecker,
+    _typeChecker, _fixerUpper, _logger, _headerParser,
+    _childInit, _childExit, _postReadRequest
+};
+
+module MODULE_VAR_EXPORT ${MODULENAME}_module = {
+    STANDARD_MODULE_STUFF,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+    NULL, NULL, NULL, NULL, NULL, NULL, NULL
+};
+EOF
diff --git a/Recycler/mod_objc/mod_gsbundle.m b/Recycler/mod_objc/mod_gsbundle.m
new file mode 100644 (file)
index 0000000..cafda6a
--- /dev/null
@@ -0,0 +1,91 @@
+// $Id: mod_gsbundle.m,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+#include "httpd.h"
+#include "http_config.h"
+#include <dlfcn.h>
+
+/*
+  Note:
+
+  an Apache bundle gets *unloaded* during the config process !!!
+*/
+
+module MODULE_VAR_EXPORT gsbundle_module;
+
+static void *helperLib = NULL;
+
+static const char *(*GSBundleModuleLoadBundleCommand)
+(module *module, cmd_parms *cmd, char *bundlePath) = NULL;
+
+/* Called when the LoadBundle config directive is found */
+static const char *loadBundle
+(cmd_parms *cmd, void *dummy, char *bundlePath)
+{
+  if (helperLib == NULL) {
+    const char *path;
+    const char *dirpath;
+    
+    dirpath = ap_pstrcat(cmd->pool,
+                         getenv("GNUSTEP_SYSTEM_ROOT"), "/Libraries/",
+                         getenv("GNUSTEP_HOST_CPU"),    "/",
+                         getenv("GNUSTEP_HOST_OS"),     "/",
+                         getenv("LIBRARY_COMBO"),       "/",
+                         NULL);
+    path = ap_pstrcat(cmd->pool, dirpath, "libApHelper_d.so", NULL);
+    
+    helperLib = dlopen(path, RTLD_NOW | RTLD_GLOBAL);
+    if (helperLib == NULL) {
+      return ap_pstrcat(cmd->pool,
+                        "couldn't load ObjC bundle helper lib:\n  '",
+                        path,
+                        "' ..." , NULL);
+    }
+    
+    GSBundleModuleLoadBundleCommand =
+      dlsym(helperLib, "GSBundleModuleLoadBundleCommand");
+  }
+  
+  if (GSBundleModuleLoadBundleCommand == NULL){
+    return ap_pstrcat(cmd->pool,
+                      "couldn't find load bundle command in helper lib ...",
+                      NULL);
+  }
+  
+  return GSBundleModuleLoadBundleCommand(&gsbundle_module, cmd, bundlePath);
+}
+
+/* Config file commands we recognize */
+static const command_rec gsbundle_cmds[] =
+{
+  {
+    "LoadBundle",
+    loadBundle,
+    "my userinfo",
+    RSRC_CONF,
+    RAW_ARGS,
+    "takes bundle-path as arg"
+  },
+  {NULL}
+};
+
+module MODULE_VAR_EXPORT gsbundle_module = {
+    STANDARD_MODULE_STUFF,
+    NULL,                  /* module initializer                  */
+    NULL,                  /* create per-dir    config structures */
+    NULL,                  /* merge  per-dir    config structures */
+    NULL,                  /* create per-server config structures */
+    NULL,                  /* merge  per-server config structures */
+    gsbundle_cmds,         /* table of config file commands       */
+    NULL,                  /* [#8] MIME-typed-dispatched handlers */
+    NULL,                  /* [#1] URI to filename translation    */
+    NULL,                  /* [#4] validate user id from request  */
+    NULL,                  /* [#5] check if the user is ok _here_ */
+    NULL,                  /* [#3] check access by host address   */
+    NULL,                  /* [#6] determine MIME type            */
+    NULL,                  /* [#7] pre-run fixups                 */
+    NULL,                  /* [#9] log a transaction              */
+    NULL,                  /* [#2] header parser                  */
+    NULL,                  /* child_init                          */
+    NULL,                  /* child_exit                          */
+    NULL                   /* [#0] post read-request              */
+};
diff --git a/Recycler/mod_objc/test.conf b/Recycler/mod_objc/test.conf
new file mode 100644 (file)
index 0000000..58b513f
--- /dev/null
@@ -0,0 +1,121 @@
+# $Id: test.conf,v 1.1 2004/06/08 11:15:59 helge Exp $
+
+# globals
+ServerType           standalone
+ServerRoot           "/HOME/helge/mdev/SkyrixRoot"
+PidFile              /HOME/helge/mdev/SkyrixRoot/logs/httpd.pid
+ScoreBoardFile       /HOME/helge/mdev/SkyrixRoot/logs/httpd.scoreboard
+DocumentRoot         "/HOME/helge/mdev/SkyrixRoot/Library/WebServer/Documents"
+ErrorLog             /HOME/helge/mdev/SkyrixRoot/logs/error_log
+AccessFileName       .htaccess
+Timeout              300
+KeepAlive            On
+MaxKeepAliveRequests 100
+KeepAliveTimeout     15
+MinSpareServers      1
+MaxSpareServers      1
+StartServers         1
+MaxClients           150
+MaxRequestsPerChild  0
+ExtendedStatus       On
+Port                 8090
+User                 helge
+Group                dev
+ServerAdmin          helge.hess@skyrix.com
+HostnameLookups      Off
+ServerSignature      On
+
+#LoadModule dav_module Libraries/ix86/linux-gnu/apache/libdav.so
+#AddModule  mod_dav.c
+
+LoadModule gnustep_conf_module \
+        Libraries/ix86/linux-gnu/apache/mod_gnustep_conf.so
+
+# GNUstep Config
+
+#GNUstepRootPath /HOME/helge/mdev/SkyrixRoot
+
+# load bundle loader ...
+
+LoadModule gsbundle_module \
+        Libraries/ix86/linux-gnu/apache/mod_gsbundle.so
+AddModule  mod_gsbundle.m
+
+# load a bundle ...
+
+LoadBundle   ApTest.bundle  
+#a=10 b=20  
+
+<Directory />
+    Options       FollowSymLinks
+    AllowOverride None
+    MyDirAlias diraliasaa documents
+    MyDirAlias diralias2aa documents2
+    PrintDirConfig 1
+</Directory>
+
+MyServerAlias server alias
+
+<Directory "/HOME/helge/mdev/SkyrixRoot/Library/WebServer/Documents">
+    Options Indexes FollowSymLinks MultiViews
+    AllowOverride None
+    Order allow,deny
+    Allow from all
+    #SetHandler ap-test
+    MyDirAlias diralias documents
+    MyDirAlias diralias2 documents2
+    PrintDirConfig 1
+</Directory>
+
+<IfModule mod_dir.c>
+    DirectoryIndex index.xhtml index.html
+</IfModule>
+
+<Files ~ "^\.ht">
+    Order allow,deny
+    Deny from all
+</Files>
+
+UseCanonicalName On
+
+<IfModule mod_mime.c>
+    TypesConfig /HOME/helge/mdev/SkyrixRoot/Library/WebServer/mime.types
+</IfModule>
+
+DefaultType text/plain
+
+# LogLevel: Control the number of messages logged to the error_log.
+# Possible values include: debug, info, notice, warn, error, crit,
+# alert, emerg.
+#
+LogLevel warn
+
+LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
+LogFormat "%h %l %u %t \"%r\" %>s %b" common
+LogFormat "%{Referer}i -> %U" referer
+LogFormat "%{User-agent}i" agent
+
+CustomLog /HOME/helge/mdev/SkyrixRoot/logs/access_log common
+
+# Alias fakename realname
+<IfModule mod_alias.c>
+</IfModule>
+
+<IfModule mod_mime.c>
+    AddEncoding x-compress Z
+    AddEncoding x-gzip gz tgz
+    AddLanguage en .en
+    AddLanguage fr .fr
+    AddLanguage de .de
+    AddCharset UCS-2        .ucs2
+    AddCharset UCS-4        .ucs4
+    AddCharset UTF-8        .utf8
+</IfModule>
+
+<IfModule mod_setenvif.c>
+    BrowserMatch "Mozilla/2" nokeepalive
+    BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0
+    BrowserMatch "RealPlayer 4\.0" force-response-1.0
+    BrowserMatch "Java/1\.0" force-response-1.0
+    BrowserMatch "JDK/1\.0" force-response-1.0
+</IfModule>