added source

Tue, 06 Sep 2011 22:27:32 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 06 Sep 2011 22:27:32 +0200
changeset 1
3c066d52342d
parent 0
4c89c7683fb6
child 2
cee3e65e789c

added source

src/Makefile file | annotate | diff | comparison | revisions
src/server/LinkedList.hh file | annotate | diff | comparison | revisions
src/server/Makefile file | annotate | diff | comparison | revisions
src/server/conf.c file | annotate | diff | comparison | revisions
src/server/conf.h file | annotate | diff | comparison | revisions
src/server/ereport.h file | annotate | diff | comparison | revisions
src/server/func.c file | annotate | diff | comparison | revisions
src/server/func.h file | annotate | diff | comparison | revisions
src/server/httplistener.c file | annotate | diff | comparison | revisions
src/server/httplistener.h file | annotate | diff | comparison | revisions
src/server/httpparser.c file | annotate | diff | comparison | revisions
src/server/httpparser.h file | annotate | diff | comparison | revisions
src/server/httprequest.c file | annotate | diff | comparison | revisions
src/server/httprequest.h file | annotate | diff | comparison | revisions
src/server/io.c file | annotate | diff | comparison | revisions
src/server/io.h file | annotate | diff | comparison | revisions
src/server/list.c file | annotate | diff | comparison | revisions
src/server/list.h file | annotate | diff | comparison | revisions
src/server/main.c file | annotate | diff | comparison | revisions
src/server/map.c file | annotate | diff | comparison | revisions
src/server/map.h file | annotate | diff | comparison | revisions
src/server/netsite.h file | annotate | diff | comparison | revisions
src/server/nsapi.h file | annotate | diff | comparison | revisions
src/server/objs.mk file | annotate | diff | comparison | revisions
src/server/pblock.cpp file | annotate | diff | comparison | revisions
src/server/pblock.h file | annotate | diff | comparison | revisions
src/server/plist.c file | annotate | diff | comparison | revisions
src/server/plist.h file | annotate | diff | comparison | revisions
src/server/plist_pvt.h file | annotate | diff | comparison | revisions
src/server/plistdef.h file | annotate | diff | comparison | revisions
src/server/pool.c file | annotate | diff | comparison | revisions
src/server/pool.h file | annotate | diff | comparison | revisions
src/server/pool_pvt.h file | annotate | diff | comparison | revisions
src/server/request.c file | annotate | diff | comparison | revisions
src/server/request.h file | annotate | diff | comparison | revisions
src/server/session.c file | annotate | diff | comparison | revisions
src/server/session.h file | annotate | diff | comparison | revisions
src/server/sessionhandler.c file | annotate | diff | comparison | revisions
src/server/sessionhandler.h file | annotate | diff | comparison | revisions
src/server/sstring.c file | annotate | diff | comparison | revisions
src/server/sstring.h file | annotate | diff | comparison | revisions
src/server/system.c file | annotate | diff | comparison | revisions
src/server/systems.h file | annotate | diff | comparison | revisions
src/server/systhr.c file | annotate | diff | comparison | revisions
src/server/systhr.h file | annotate | diff | comparison | revisions
src/server/thrpool.c file | annotate | diff | comparison | revisions
src/server/thrpool.h file | annotate | diff | comparison | revisions
src/server/uri.cpp file | annotate | diff | comparison | revisions
src/server/util.c file | annotate | diff | comparison | revisions
src/server/util.h file | annotate | diff | comparison | revisions
src/server/webserver.c file | annotate | diff | comparison | revisions
src/server/webserver.h file | annotate | diff | comparison | revisions
src/server/ws-fn.c file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Makefile	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,33 @@
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 2011 Olaf Wintermann. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#   1. Redistributions of source code must retain the above copyright
+#      notice, this list of conditions and the following disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above copyright
+#      notice, this list of conditions and the following disclaimer in the
+#      documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BUILD_ROOT = ../
+
+all:
+	cd server; $(MAKE) all
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/LinkedList.hh	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,272 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _LINKED_LIST_H_
+#define _LINKED_LIST_H_
+
+/*
+ *   Provided a template implementation of a simple linked list. 
+ * It is a reference based container (stores the pointers to the
+ * objects contained) It doesn't check for duplicates etc and find
+ * (delete) will find(delete) the first occurence of an element.
+ *
+ * Iterator class can be used for traversal using the "++" operator.
+ */
+template <class C> class CList; // forward declaration
+template <class C> class CListIterator; // forward declaration
+template <class C> class CListConstIterator; // forward declaration
+
+template <class C> class CListElmt {
+  friend class CList<C>;
+  friend class CListIterator<C>;
+  friend class CListConstIterator<C>;
+  private:
+    CListElmt(C* refP, int id) : _refP(refP), _nextP(0), _prevP(0), _id(id)
+        {
+                // Nothing really has to be done here
+        };
+
+
+  private:
+    int       _id;    
+    C         *_refP;
+#if defined(AIX)
+    CListElmt<C> *_nextP;
+    CListElmt<C> *_prevP;
+#else
+    CListElmt *_nextP;
+    CListElmt *_prevP;
+#endif
+};
+
+//
+// NOTE : If you need the find functionality, make sure that 
+//  class C has "==" defined.
+//
+template <class C> class CList {
+  friend class CListIterator<C>;
+  friend class CListConstIterator<C>;
+  private:
+    CListElmt<C>* _headP;
+    CListElmt<C>* _tailP;
+    CListElmt<C>* Lookup(C * memberP)
+        {
+                CListElmt<C> *curEltP = _headP;
+                
+                while (curEltP)
+                {
+                        if (curEltP->_refP == memberP) 
+                                break;
+                        curEltP = curEltP->_nextP;
+                };
+                return(curEltP);
+        };
+    
+    int _nextId;
+    int _numElts;
+    int autoDestroy;
+    C* Remove(CListElmt<C> *elmtP)
+        {
+                C  *recP = NULL;
+                if (elmtP)
+                {
+                        if (elmtP->_nextP)
+                                elmtP->_nextP->_prevP = elmtP->_prevP;
+                        if (elmtP->_prevP)
+                                elmtP->_prevP->_nextP = elmtP->_nextP;
+                        if (elmtP == _tailP)
+                                _tailP = elmtP->_prevP;
+                        if (elmtP == _headP)
+                                _headP = _headP->_nextP;
+                        recP = elmtP->_refP;
+                        _numElts--;
+                        delete elmtP;
+                };
+                if ( (1==autoDestroy) && recP)
+                        delete recP;
+                
+                return(recP);
+        };
+    
+
+  public:
+    CList() :  _headP(0), _tailP(0), _nextId(0), _numElts(0), autoDestroy(0)
+        {
+                // Nothing really has to be done here
+        };
+        
+    void setAutoDestroy(int setting)
+        {
+                autoDestroy = setting;
+        };
+
+    virtual ~CList()
+        {
+                while (_headP)
+                        Remove(_headP);
+        };
+
+    int NextId()
+        {
+                return _nextId;
+        };
+
+    int Append(C* refP)
+        {
+                CListElmt<C> *newElmtP = new CListElmt<C>(refP, _nextId++);
+                newElmtP->_prevP = _tailP;
+                if (_tailP)
+                        _tailP->_nextP = newElmtP;
+                if (_headP == 0)
+                        _headP = newElmtP;
+                _tailP = newElmtP;
+                _numElts++;
+                return(newElmtP->_id);
+        };
+
+    int Member(C* memberP)
+        {
+                return(Lookup(memberP) != 0);
+        };
+    
+    int Delete(C* memberP)
+        {
+                CListElmt<C> *listElmtP = Lookup(memberP);
+                if (listElmtP)
+                {
+                        (void) Remove(listElmtP);
+                        return(1);
+                }
+                return(0);
+        };
+    
+    int NumEntries() const { return _numElts; }
+    C* Find(C* memberP) // Lookup based on == operator for class C
+        {
+                CListElmt<C> *curEltP = _headP;
+        
+                while (curEltP)
+                {
+                        if (curEltP->_refP == memberP) 
+                                break;
+                        curEltP = curEltP->_nextP;
+                };
+                return(curEltP ? curEltP->_refP : 0);
+        };
+    
+    C* First() { return(_headP ? _headP->_refP : 0); }
+    C* Last() { return(_tailP ? _tailP->_refP : 0); }
+};
+
+template <class C> class CListIterator {
+  private:
+    CList<C>* _listP;
+    int _curId;
+  public:
+    CListIterator(CList<C>* linkedListP) : _listP(linkedListP), _curId(-1)
+        {
+                // Nothing more to be done
+        };
+    
+    virtual ~CListIterator()
+        {
+                _listP = NULL;
+        };
+    
+    C* operator++() // Define ++ operator to move forward along the list.
+        {
+                C *valueP = NULL;
+                CListElmt<C> *curEltP = _listP->_headP;
+
+                while (curEltP)
+                {
+                        if (curEltP->_id > _curId)
+                        {
+                                _curId = curEltP->_id;
+                                return(curEltP->_refP);
+                        }
+                        curEltP = curEltP->_nextP;
+                }
+                _curId = -1;
+                return(NULL);
+        };
+    
+    void operator()() // Overload the function operator to reset the iterator
+        {
+                _curId = -1;
+        };
+    
+};
+
+template <class C> class CListConstIterator {
+  private:
+    const CList<C>* _listP;
+    int _curId;
+  public:
+    CListConstIterator(const CList<C>* linkedListP)
+        : _listP(linkedListP), _curId(-1)
+        {
+                // Nothing more to be done
+        };
+    
+    virtual ~CListConstIterator()
+        {
+                _listP = NULL;
+        };
+    
+    const C* operator++() // Define ++ operator to move forward along the list.
+        {
+                const C *valueP = NULL;
+                const CListElmt<C> *curEltP = _listP->_headP;
+
+                while (curEltP)
+                {
+                        if (curEltP->_id > _curId)
+                        {
+                                _curId = curEltP->_id;
+                                return(curEltP->_refP);
+                        }
+                        curEltP = curEltP->_nextP;
+                }
+                _curId = -1;
+                return(NULL);
+        };
+    
+    void operator()() // Overload the function operator to reset the iterator
+        {
+                _curId = -1;
+        };
+    
+};
+
+#endif // _LINKED_LIST_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/Makefile	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,53 @@
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 2011 Olaf Wintermann. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#   1. Redistributions of source code must retain the above copyright
+#      notice, this list of conditions and the following disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above copyright
+#      notice, this list of conditions and the following disclaimer in the
+#      documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+BUILD_ROOT = ../../
+OBJ_DIR = $(BUILD_ROOT)build/
+
+CFLAGS  = -I/usr/include/mps
+LDFLAGS = -L/usr/lib/mps -lplds4 -lplc4 -lnspr4 -lpthread -ldl -lposix4  -lsocket -lnsl -lgen -lm -R/usr/lib/mps
+
+MAIN_TARGET = $(BUILD_ROOT)work/bin/webservd
+
+include objs.mk
+
+all: preparation $(MAIN_TARGET)
+
+preparation:
+	mkdir -p $(OBJPRE)
+	mkdir -p $(BUILD_ROOT)work/bin
+
+$(MAIN_TARGET): $(MAINOBJS)
+	CC -o $(MAIN_TARGET) $(LDFLAGS) $(MAINOBJS)
+
+$(OBJPRE)%.o: %.c
+	cc -o $@ -c $(CFLAGS) $<
+
+$(OBJPRE)%.o: %.cpp
+	CC -o $@ -c $(CFLAGS) $<
+	
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/conf.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,50 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "nsapi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "httplistener.h"
+#include "conf.h"
+
+void load_init_conf(char *file) {
+    printf("load_init_conf\n");
+}
+
+void load_server_conf(char *file) {
+    printf("load_server_conf\n");
+    
+    ListenerConfig *conf = malloc(sizeof(ListenerConfig));
+    conf->port = 8080;
+    conf->nacceptors = 1;
+    conf->name = "default";
+
+    http_listener_new(conf);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/conf.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CONF_H
+#define	CONF_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+void load_init_conf(char *file);
+
+void load_server_conf(char *file);
+
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* CONF_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ereport.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,125 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_EREPORT_H
+#define BASE_EREPORT_H
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * ereport.h: Records transactions, reports errors to administrators, etc.
+ * 
+ * Rob McCool
+ */
+
+#ifndef BASE_SESSION_H
+#include "session.h"
+#endif /* !BASE_SESSION_H */
+
+/* Pseudo-filename to enable logging to syslog */
+#define EREPORT_SYSLOG "SYSLOG"
+
+/* NSAPI degrees used by Java but not exposed in nsapi.h */
+#define LOG_FINER  7
+#define LOG_FINEST 8
+
+/* --- Begin function prototypes --- */
+
+#ifdef INTNSAPI
+
+NSPR_BEGIN_EXTERN_C
+
+/*
+ * INTereport logs an error of the given degree and formats the arguments with 
+ * the printf() style fmt. Returns whether the log was successful. Records 
+ * the current date.
+ */
+
+NSAPI_PUBLIC int INTereport(int degree, const char *fmt, ...);
+NSAPI_PUBLIC int INTereport_v(int degree, const char *fmt, va_list args);
+
+/*
+ * INTereport_init initializes the error logging subsystem and opens the static
+ * file descriptors. It returns NULL upon success and an error string upon
+ * error. If a userpw is given, the logs will be chowned to that user.
+ */
+
+NSAPI_PUBLIC
+char *INTereport_init(const char *err_fn, const char *email, struct passwd *pwuser, const char *version, int restarted);
+
+NSAPI_PUBLIC void INTereport_terminate(void);
+
+/* For restarts */
+NSAPI_PUBLIC SYS_FILE INTereport_getfd(void);
+
+NSPR_END_EXTERN_C
+
+#ifdef __cplusplus
+class EreportableException;
+NSAPI_PUBLIC int INTereport_exception(const EreportableException& e);
+#endif
+
+/* --- End function prototypes --- */
+
+#define ereport INTereport
+#define ereport_v INTereport_v
+#define ereport_init INTereport_init
+#define ereport_terminate INTereport_terminate
+#define ereport_getfd INTereport_getfd
+#define ereport_exception INTereport_exception
+
+typedef int (EreportFunc)(const VirtualServer* vs, int degree, const char *formatted, int formattedlen, const char *raw, int rawlen, void *data);
+
+void ereport_set_servername(const char* name);
+void ereport_set_logvsid(PRBool b);
+void ereport_set_logall(PRBool b);
+void ereport_set_alwaysreopen(PRBool b);
+void ereport_set_timefmt(const char* timeFmt);
+void ereport_set_degree(int degree);
+int ereport_level2degree(const char *level, int defdegree);
+PRBool ereport_can_log(int degree);
+int ereport_request(Request* rq, int degree, const char *fmt, ...);
+char *ereport_abs_filename(const char *filename);
+void ereport_rotate(const char* ext);
+void ereport_set_rotate_callback(void (*fn)(const char* filenameNew, const char* filenameOld));
+void ereport_reopen(void);
+void ereport_outofmemory(void);
+void ereport_disaster(int degree, const char *fmt, ...);
+NSAPI_PUBLIC int ereport_register_cb(EreportFunc* ereport_func, void* data);
+NSAPI_PUBLIC int ereport_register_thread_cb(EreportFunc* ereport_func, void* data);
+
+#endif /* INTNSAPI */
+
+#endif /* !BASE_EREPORT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/func.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,55 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdlib.h>
+
+#include "nsapi.h"
+#include "map.h"
+#include "func.h"
+
+hashmap_t *function_map;
+
+void func_init() {
+    function_map = hashmap_new(128);
+}
+
+void add_function(struct FuncStruct *func) {
+    struct FuncStruct *f = malloc(sizeof(FuncStruct));
+    *f = *func;
+    hashmap_put(function_map, sstr((char*)f->name), func);
+}
+
+void add_functions(struct FuncStruct *funcs) {
+    int i = 0;
+    while(funcs[i].func != NULL) {  
+        add_function(&funcs[i]);
+        i++;
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/func.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,50 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef FUNC_H
+#define	FUNC_H
+
+#include "nsapi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+void func_init();
+
+void add_function(struct FuncStruct *func);
+
+void add_functions(struct FuncStruct *funcs);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* FUNC_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/httplistener.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,178 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "nsapi.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "map.h"
+#include "httplistener.h"
+
+#include "session.h"
+
+hashmap_t *listener_map = NULL;
+
+
+int start_all_listener() {
+    HttpListener *listener = get_http_listener("default");
+    http_listener_start(listener); 
+
+    return 0;
+}
+
+HttpListener* get_http_listener(char *name) {
+    return hashmap_get(listener_map, sstr(name));
+}
+
+
+HttpListener* http_listener_new(ListenerConfig *conf) {
+    HttpListener *listener = malloc(sizeof(HttpListener));
+    listener->session_handler = create_basic_session_handler();
+    listener->nacceptors = conf->nacceptors;
+
+    struct sockaddr_in servaddr;   /* server address */
+
+    /* init address structure */
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+    servaddr.sin_port = htons(conf->port);
+
+    /* create socket */
+    if((listener->server_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
+        perror("Error: http_listener_new: socket");
+        return NULL;
+    }
+
+    int o = 1;
+    setsockopt(
+            listener->server_socket,
+            SOL_SOCKET, SO_REUSEADDR,
+            &o,
+            sizeof(int));
+
+    /* bind server socket to address */
+    if(bind(listener->server_socket, (struct sockaddr*)&servaddr, sizeof(servaddr))){
+        perror("Error: http_listener_new: bind");
+        return NULL;
+    }
+
+    /* create acceptors */
+    listener->acceptors = calloc(listener->nacceptors, sizeof(void*));
+    for (int i=0;i<listener->nacceptors;i++) {
+        listener->acceptors[i] = acceptor_new(listener);
+    }
+
+    if(listener_map == NULL) {
+        listener_map = hashmap_new(8);
+    }
+    hashmap_put(listener_map, sstr(conf->name), listener);
+    return listener;
+}
+
+int http_listener_start(HttpListener *listener) {
+    printf("INFO: start listener\n");
+
+    if (listen(listener->server_socket, 16) == -1) {
+        perror("Error: http_listener_start: listen");
+        return -1;
+    }
+
+    /* start acceptor threads */
+    for (int i=0;i<listener->nacceptors;i++) {
+        acceptor_start(listener->acceptors[i]);
+    }
+}
+
+
+
+Acceptor* acceptor_new(HttpListener *listener) {
+    Acceptor *acceptor = malloc(sizeof(Acceptor));
+    acceptor->listener = listener;
+    return acceptor;
+}
+
+void acceptor_start(Acceptor *a) {
+    if(pthread_create(
+            &a->tid,
+            NULL,
+            (void*(*)(void*))acceptor_thread,
+            a) != 0)
+    {
+        perror("Error: acceptor_start: pthread_create");
+    }
+}
+
+void* acceptor_thread(Acceptor *acceptor) {
+    HttpListener *listener = acceptor->listener;
+
+    for (;;) {
+        /* accept connections */
+        struct sockaddr_in ca;
+        int length = sizeof(ca);
+        int clientfd;
+
+        /* accept a connection */
+        clientfd = accept(
+                listener->server_socket,
+                (struct sockaddr*)&ca,
+                &length);
+        if (clientfd == -1) {
+            perror("Error: acceptor_thread: accept");
+            continue;
+        }
+
+        /* create Connection object */
+        Connection *conn = malloc(sizeof(Connection));
+        conn->address = ca;
+        conn->fd = clientfd;
+
+        /* enqueue the connection */
+        listener->session_handler->enqueue_connection(
+                listener->session_handler,
+                conn);
+
+        /* ready for new connection */
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/httplistener.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,82 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTTPLISTENER_H
+#define	HTTPLISTENER_H
+
+#include "sessionhandler.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _http_listener    HttpListener;
+typedef struct _acceptor         Acceptor;
+typedef struct _listener_config  ListenerConfig;
+
+struct _listener_config {
+    char           *name;
+    char           *address;
+    int            port;
+    int            nacceptors;
+};
+
+struct _acceptor {
+    pthread_t      tid;
+    HttpListener   *listener;
+};
+
+struct _http_listener {
+    int              server_socket;
+    Acceptor         **acceptors;
+    int              nacceptors;
+    SessionHandler   *session_handler;
+};
+
+int start_all_listener();
+HttpListener* get_http_listener(char *name);
+
+
+HttpListener* http_listener_new(ListenerConfig *conf);
+
+int http_listener_start(HttpListener *listener);
+
+
+Acceptor* acceptor_new(HttpListener *listener);
+
+void acceptor_start(Acceptor *a);
+
+void* acceptor_thread(Acceptor *a);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* HTTPLISTENER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/httpparser.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,196 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "httpparser.h"
+#include "nsapi.h"
+//include "request.h"
+
+
+HttpParser* http_parser_new(HTTPRequest *request) {
+    HttpParser *parser = malloc(sizeof(HttpParser));
+    parser->request = request;
+    
+    parser->state = 0;
+    parser->start_line.ptr = (char*)request->netbuf->inbuf;
+    parser->start_line.length = 0;
+
+    return parser;
+}
+
+void http_parser_free(HttpParser *parser) {
+    free(parser);
+}
+
+int http_parser_process(HttpParser *parser) {
+    switch(parser->state) {
+        case 0: {
+            int r = get_start_line(parser);
+            switch(r) {
+                case 0: break;
+                default: return r;
+            }
+            parse_request_line(parser);
+            parser->state++;
+        }
+        case 1: {
+            return http_parser_parse_header(parser);
+        }
+        case 2: {
+            return 0;
+        }
+    }
+}
+
+int get_start_line(HttpParser *parser) {
+    netbuf *buf = parser->request->netbuf;
+    while(buf->pos < buf->cursize) {
+        unsigned char c = buf->inbuf[buf->pos];
+        if(c == '\n') {
+            if(buf->pos <= 1) {
+                // insufficient chars for request, return error
+                return 2;
+            }
+            if(buf->inbuf[buf->pos - 1] == '\r') {
+                parser->start_line.length = buf->pos;
+            } else {
+                parser->start_line.length = buf->pos + 1;
+            }
+            parser->start_line.ptr = (char*)buf->inbuf;
+            buf->pos++;
+            return 0;
+        }
+        buf->pos++;
+    }
+    return 1;
+}
+
+int http_parser_parse_header(HttpParser *parser) {
+    netbuf *buf = parser->request->netbuf;
+
+    parser->offset = buf->pos; // line offset
+    parser->name.ptr = NULL;
+    parser->value.ptr = NULL;
+    while(1) {
+        if(buf->pos >= buf->cursize) {
+            return 1;
+        }
+        char c = (char)buf->inbuf[buf->pos++];
+
+        if(c > 32) {
+            parser->wl = 0;
+            if(c == ':' && parser->value.ptr == NULL) {
+                parser->name.ptr = (char*)buf->inbuf + parser->offset;
+                buf->inbuf[buf->pos-1] = 0;
+            } else if(parser->name.ptr != NULL && parser->value.ptr == NULL) {
+                parser->value.ptr = (char*)buf->inbuf + buf->pos - 1;
+            }
+        } else if(c == '\n') {
+            if(parser->wl) {
+                // line contains only white space -> end of request
+                parser->state++;
+                return 0;
+            } else {
+                parser->offset = buf->pos;
+                if(parser->value.ptr != NULL) {
+                    buf->inbuf[buf->pos-1] = 0;
+                    // add header
+                    header_add(
+                            parser->request->headers,
+                            parser->name.ptr,
+                            parser->value.ptr);
+                } else {
+                    // error: no value
+                    return 2;
+                }
+                parser->name.ptr = NULL;
+                parser->value.ptr = NULL;
+                parser->wl = 1;
+            }
+        }
+    }
+}
+
+int parse_request_line(HttpParser *parser) {
+    sstr_t line = parser->start_line;
+    parser->request->request_line = line;
+    
+    /*
+     * parse method, url and http version
+     */
+    
+    int i = 0;
+    int ns = 0;
+
+    parser->request->method.ptr = line.ptr;
+    for(;i<line.length;i++) {
+        if(!ns && line.ptr[i] == ' ') {
+            ns = 1;
+            //line.ptr[i] = 0; // TODO: remove
+            parser->request->method.length = i;
+        } else if(ns) {
+            if(line.ptr[i] != ' ') {
+                break;
+            }
+        }
+    }
+
+    parser->request->uri.ptr = line.ptr + i;
+    ns = 0;
+    int s = i;
+    for(;i<line.length;i++) {
+        if(!ns && line.ptr[i] < 33) {
+            ns = 1;
+            //line.ptr[i] = 0; // TODO: remove
+            parser->request->uri.length = i - s;
+        } else if(ns) {
+            if(line.ptr[i] > 32) {
+                break;
+            }
+        }
+    }
+
+    parser->request->httpv.ptr = line.ptr + i;
+    ns = 0;
+    s = i;
+    for(;i<line.length;i++) {
+        if(!ns && line.ptr[i] < 33) {
+            ns = 1;
+            //line.ptr[i] = 0; // TODO: remove
+            parser->request->httpv.length = i - s;
+        } else if(ns) {
+            if(line.ptr[i] > 32) {
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/httpparser.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,90 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTTPPARSER_H
+#define	HTTPPARSER_H
+
+
+#include "sstring.h"
+#include "httprequest.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+/*
+ * http parser states
+ *
+ * 0: start line
+ * 1: header
+ * 2: finish
+ */
+
+typedef struct _http_parser {
+    HTTPRequest *request;
+
+    int state;
+    sstr_t start_line;
+
+    /* local parser varaibles */
+    int wl;       /* only white space */
+    int tk;       /* token: 0: header name 1: header value */
+    int offset;   /* offset of parsed string */
+    int strend;   /* end position */
+    sstr_t name;
+    sstr_t value;
+
+} HttpParser;
+
+HttpParser* http_parser_new(HTTPRequest *request);
+void http_parser_free(HttpParser *parser);
+
+/*
+ * process http parsing
+ *
+ * return
+ * 0: finish
+ * 1: need more data
+ * 2: error
+ */
+int http_parser_process(HttpParser *parser);
+
+int get_start_line(HttpParser *parser);
+int http_parser_parse_header(HttpParser *parser);
+
+int parse_request_line(HttpParser *parser);
+
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+
+#endif	/* HTTPPARSER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/httprequest.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,154 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nsapi.h"
+#include "pool.h"
+#include "pblock.h"
+#include "io.h"
+#include "util.h"
+#include "httprequest.h"
+
+HTTPRequest *http_request_new() {
+    HTTPRequest *req = malloc(sizeof(HTTPRequest));
+    req->connection = NULL;
+    req->uri.ptr = NULL;
+
+    HeaderArray *hd = malloc(sizeof(HeaderArray));
+    hd->next = NULL;
+    hd->len = 0;
+    hd->headers = calloc(16, sizeof(Header));
+    hd->alloc = 16;
+
+    req->headers = hd;
+
+    return req;
+}
+
+int handle_request(HTTPRequest *request) {
+    // handle nsapi request
+
+    // create pool
+    request->pool = pool_create();
+
+    // create nsapi data structures
+    NSAPISession *sn = malloc(sizeof(NSAPISession));
+    NSAPIRequest *rq = malloc(sizeof(NSAPIRequest));
+    request->rq = rq;
+
+    // fill session structure
+    sn->sn.pool = pool_create();
+    sn->sn.csd = stream_new_from_fd(request->connection->fd);
+    sn->sn.client = NULL;
+    sn->sn.next = NULL;
+    sn->sn.fill = 1;
+    sn->sn.subject = NULL;
+
+    // init NSAPI request structure
+    if(request_initialize(request->pool, request, rq) != 0) {
+        return 1;
+    }
+
+    /* Pass request line as "clf-request" */
+    pblock_kvinsert(
+            pb_key_clf_request,
+            request->request_line.ptr,
+            request->request_line.length,
+            rq->rq.reqpb);
+
+    /* Pass method as "method" in reqpb, and also as method_num */
+    pblock_kvinsert(
+            pb_key_method,
+            request->method.ptr,
+            request->method.length,
+            rq->rq.reqpb);
+    // TODO: method num
+    //rqRq.rq.method_num = rqHdr->GetMethodNumber();
+    //PR_ASSERT(rqRq.rq.method_num != -1 || iStatus);
+    
+    /* Pass protocol as "protocol" in reqpb, and also in protv_num */
+    pblock_kvinsert(
+            pb_key_protocol,
+            request->httpv.ptr,
+            request->httpv.length,
+            rq->rq.reqpb);
+    // TODO: protocol num
+
+    /* Pass any query as "query" in reqpb */
+    // TODO: query
+
+    /* Get abs_path part of request URI, and canonicalize the path */
+    sstr_t absPath = request->uri;
+    // TODO: get abs_path
+    absPath.ptr = util_canonicalize_uri(
+            request->pool,
+            absPath.ptr,
+            absPath.length,
+            (int*)&absPath.length);
+
+    /* Decode the abs_path */
+    // TODO: decode abs_path
+
+    /* Pass the abs_path as "uri" in reqpb */
+    // TODO: pass abs_path to reqpb
+    // TODO: replace this code
+    pblock_kvinsert(
+            pb_key_uri,
+            absPath.ptr,
+            absPath.length,
+            rq->rq.reqpb);
+
+    // pass http header to the NSAPI request structure
+
+
+    // Send the request to the NSAPI system
+
+    return 0;
+}
+
+
+
+void header_add(HeaderArray *hd, char *name, char *value) {
+    while(hd->len >= hd->alloc) {
+        if(hd->next == NULL) {
+            HeaderArray *block = malloc(sizeof(HeaderArray));
+            block->next = NULL;
+            block->len = 0;
+            block->headers = calloc(16, sizeof(Header));
+            block->alloc = 16;
+            hd->next = block;
+        }
+        hd = hd->next;
+    }
+    hd->headers[hd->len].name = name;
+    hd->headers[hd->len].value = value;
+    hd->len++;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/httprequest.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,93 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef HTTPREQUEST_H
+#define	HTTPREQUEST_H
+
+#include "sstring.h"
+#include "sessionhandler.h"
+#include "nsapi.h"
+#include "pool.h"
+#include "session.h"
+#include "sstring.h"
+#include "request.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _http_request   HTTPRequest;
+typedef struct _header         Header;
+typedef struct _header_array   HeaderArray;
+
+struct _http_request {
+    Connection     *connection;
+    sstr_t         request_line;
+    sstr_t         method;
+    sstr_t         uri;
+    sstr_t         httpv;
+    HeaderArray    *headers;
+    netbuf         *netbuf;
+    NSAPISession   *sn;
+    NSAPIRequest   *rq;
+    pool_handle_t  *pool;
+};
+
+struct _header {
+    char *name;
+    char *value;
+};
+
+struct _header_array {
+    HeaderArray *next;
+    Header      *headers;
+    int         len;
+    int         alloc;
+};
+
+HTTPRequest *http_request_new();
+
+int handle_request(HTTPRequest *request);
+
+
+
+void header_add(HeaderArray *hd, char *name, char *value);
+
+
+/* request.h functions */
+int request_initialize(
+        pool_handle_t *pool,
+        HTTPRequest *hrq,
+        NSAPIRequest *nrq);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* HTTPREQUEST_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/io.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,53 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "io.h"
+
+IOStream native_io_funcs = {
+    system_write,
+    system_read
+};
+
+
+IOStream* stream_new_from_fd(int fd) {
+    SystemIOStream *st = malloc(sizeof(SystemIOStream));
+    st->st = native_io_funcs;
+    st->fd = fd;
+    return (IOStream*)st;
+}
+
+ssize_t system_write(IOStream *st, void *buf, size_t nbytes) {
+    return write(((SystemIOStream*)st)->fd, buf, nbytes);
+}
+
+ssize_t system_read(IOStream *st, void *buf, size_t nbytes) {
+    return read(((SystemIOStream*)st)->fd, buf, nbytes);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/io.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,63 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef IOSTREAM_H
+#define	IOSTREAM_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct io_stream IOStream;
+
+typedef ssize_t(*io_write_f)(IOStream *, void *, size_t);
+typedef ssize_t(*io_read_f)(IOStream *, void *, size_t);
+
+struct io_stream {
+    io_write_f write;
+    io_read_f  read;
+};
+
+typedef struct SystemIOStream {
+    IOStream st;
+    int      fd;
+} SystemIOStream;
+
+
+IOStream* stream_new_from_fd(int fd);
+
+
+ssize_t system_write(IOStream *st, void *buf, size_t nbytes);
+ssize_t system_read(IOStream *st, void *buf, size_t nbytes);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* IOSTREAM_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/list.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,175 @@
+/* 
+ * File:   list.c
+ * Author: olaf
+ *
+ * Created on 18. Dezember 2010, 11:23
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "list.h"
+
+/* add functions */
+sdlist_t* sdlist_add(sdlist_t *list, void *data) {
+    sdlist_t *elm = malloc(sizeof(sdlist_t));
+    elm->data = data;
+    elm->next = NULL;
+
+    return sdlist_addl(list, elm);
+}
+
+sdlist_t* sdlist_addl(sdlist_t *list, sdlist_t *l) {
+    if (list != NULL) {
+        sdlist_t *end = sdlist_getlast(list);
+        end->next = l;
+        return list;
+    } else {
+        return l;
+    }
+}
+
+
+
+/* remove functions */
+sdlist_t* sdlist_remove(sdlist_t *list, void *data) {
+    sdlist_t *s = list;
+
+    sdlist_t *prev = NULL;
+    while (list != NULL) {
+        if (list->data == data) {
+            sdlist_t *nl =  sdlist_remove_elm(s, prev, list);
+            free(list);
+            return nl;
+        }
+
+        prev = list;
+        list = list->next;
+    }
+
+    return s;
+}
+
+sdlist_t* sdlist_removei(sdlist_t *list, int index) {
+    sdlist_t *s = list;
+
+    sdlist_t *prev = NULL;
+    int i = 0;
+    while (list != NULL) {
+        if (i == index) {
+            sdlist_t *nl =  sdlist_remove_elm(s, prev, list);
+            free(list);
+            return nl;
+        }
+
+        prev = list;
+        list = list->next;
+        i++;
+    }
+
+    return s;
+}
+
+sdlist_t* sdlist_removel(sdlist_t *list, sdlist_t *l) {
+    sdlist_t *s = list;
+
+    sdlist_t *prev = NULL;
+    while (list != NULL) {
+        if (list == l) {
+            return sdlist_remove_elm(s, prev, list);
+        }
+
+        prev = list;
+        list = list->next;
+    }
+
+    return s;
+}
+
+
+sdlist_t *sdlist_remove_elm(sdlist_t *list, sdlist_t *prev, sdlist_t *elm) {
+    if (elm == NULL) {
+        return list;
+    }
+
+    if (prev == NULL) {
+        return elm->next;
+    }
+
+    prev->next = elm->next;
+
+    return list;
+}
+
+
+
+/* insert functions */
+void sdlist_insert(sdlist_t *elm, void *data) {
+    sdlist_t *newelm = malloc(sizeof(sdlist_t));
+    newelm->data = data;
+    sdlist_insertl(elm, newelm);
+}
+
+void sdlist_insertl(sdlist_t *elm, sdlist_t *l) {
+    if (elm == NULL || l == NULL) {
+        return;
+    }
+    
+    l->next = elm->next;
+    elm->next = l;
+}
+
+
+/* get functions */
+sdlist_t* sdlist_get(sdlist_t *list, void *data) {
+    while (list != NULL) {
+        if (list->data == data) {
+            return list;
+        }
+        list = list->next;
+    }
+    return NULL;
+}
+
+sdlist_t* sdlist_geti(sdlist_t *list, int index) {
+    for (int i=0;i<index;i++) {
+        if (list == NULL) {
+            return NULL;
+        }
+        list = list->next;
+    }
+    return list;
+}
+
+sdlist_t* sdlist_getlast(sdlist_t *list) {
+    while(list->next != NULL) {
+        list = list->next;
+    }
+    return list;
+}
+
+
+
+/* miscellaneous functions */
+size_t sdlist_length(sdlist_t *list) {
+    int i = 0;
+    while(list->next != NULL) {
+        list = list->next;
+        i++;
+    }
+    return i;
+}
+
+void sdlist_free(sdlist_t *elm) {
+    free(elm);
+}
+
+void sdlist_foreach(sdlist_t *list, sdlist_iterator_func f, void *data) {
+    while(list != NULL) {
+        int r = f(list, data);
+        if (r) {
+            return;
+        }
+        list = list->next;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/list.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,106 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef LIST_H
+#define	LIST_H
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _util_slist sdlist_t;
+
+struct _util_slist {
+    void *data;
+    sdlist_t *next;
+};
+
+typedef int (*sdlist_iterator_func)(sdlist_t*, void*);
+
+
+/* single linked list */
+
+/*
+ * sdlist_add/sdllist_addl
+ *
+ * append to the end of the list one element
+ */
+sdlist_t* sdlist_add(sdlist_t *list, void *data);
+sdlist_t* sdlist_addl(sdlist_t *list, sdlist_t *l);
+    
+/*
+ * sdlist_remove/sdlist_removei
+ *
+ * remove one element from the list and free the sdlist_t object
+ * returns the first element of the new list
+ */
+sdlist_t* sdlist_remove(sdlist_t *list, void *data);
+sdlist_t* sdlist_removei(sdlist_t *list, int index);
+
+/*
+ * sdlist_removel
+ *
+ * remove element l from the list
+ * returns the first element of the new list
+ */
+sdlist_t* sdlist_removel(sdlist_t *list, sdlist_t *l);
+
+/*
+ * removes one element from the list
+ *
+ * list:   list
+ * prev:   previous to elm
+ * elm:    element which should be removed
+ *
+ * returns the first element of the new list
+ */
+sdlist_t *sdlist_remove_elm(sdlist_t *list, sdlist_t *prev, sdlist_t *elm);
+    
+
+/*
+ * sdlist_insert
+ *
+ * insert one element after the element elm
+ */
+void sdlist_insert(sdlist_t *elm, void *data);
+void sdlist_insertl(sdlist_t *elm, sdlist_t *l);
+
+sdlist_t* sdlist_get(sdlist_t *list, void *data);
+sdlist_t* sdlist_geti(sdlist_t *list, int index);
+sdlist_t* sdlist_getlast(sdlist_t *list);
+
+size_t sdlist_length(sdlist_t *list);
+void sdlist_free(sdlist_t *elm);
+void sdlist_foreach(sdlist_t *list, sdlist_iterator_func f, void *data);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* LIST_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/main.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,67 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "pool.h"
+#include "nsapi.h"
+#include "plist.h"
+
+#include "webserver.h"
+
+#include "httprequest.h"
+
+void test() {
+    exit(0);
+}
+
+int main(int argc, char **argv) {
+    //test();
+
+    pool_init(NULL, NULL, NULL);
+
+    int status;
+    status = webserver_init();
+    if(status != 0) {
+        fprintf(stderr, "Cannot initialize server!\n");
+        return EXIT_FAILURE;
+    }
+
+    status = webserver_run();
+    if(status != 0) {
+        fprintf(stderr, "Cannot run server!\n");
+        return EXIT_FAILURE;
+    }
+
+    getchar();
+
+    return EXIT_SUCCESS;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/map.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,134 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "map.h"
+
+hashmap_t* hashmap_new(size_t size) {
+    hashmap_t *map = malloc(sizeof(hashmap_t));
+    map->map = calloc(size, sizeof(sdlist_t));
+    map->len = size;
+
+    return map;
+}
+
+void hashmap_free(hashmap_t *map) {
+    for(int i=0;i<map->len;i++) {
+        sdlist_t *list = map->map[0];
+        while(list != NULL) {
+            hashmap_elm_t *elm = (hashmap_elm_t*)list->data;
+            free(elm->key.ptr);
+            sdlist_t *l = list;
+            list = list->next;
+            free(elm);
+            free(l);
+        }
+    }
+    free(map->map);
+    free(map);
+}
+
+
+void hashmap_put(hashmap_t *map, sstr_t key, void *value) {
+    int hash = hashmap_hash(key.ptr, key.length);
+
+    sdlist_t *list = map->map[hash%map->len];
+
+    sstr_t k = sstrdub(key);
+
+    hashmap_elm_t *elm = malloc(sizeof(hashmap_elm_t));
+    elm->data = value;
+    elm->hash = hash;
+    elm->key = k;
+
+    map->map[hash%map->len] = sdlist_add(list, elm);
+}
+
+void* hashmap_get(hashmap_t *map, sstr_t key) {
+    int hash = hashmap_hash(key.ptr, key.length);
+    sdlist_t *list = map->map[hash%map->len];
+    void *value = NULL;
+
+    while (list != NULL) {
+        hashmap_elm_t *elm = list->data;
+        if (elm->hash == hash &&
+                strncmp(key.ptr, elm->key.ptr, key.length) == 0) {
+            value = elm->data;
+            break;
+        }
+        list = list->next;
+    }
+
+    return value;
+}
+
+
+
+
+/* hash function */
+int hashmap_hash(char *data, size_t len) {
+    /* murmur hash 2 */
+
+    int m = 0x5bd1e995;
+    int r = 24;
+
+    int h = 25 ^ len;
+
+    int i = 0;
+    while (len >= 4) {
+        int k = data[i + 0] & 0xFF;
+        k |= (data[i + 1] & 0xFF) << 8;
+        k |= (data[i + 2] & 0xFF) << 16;
+        k |= (data[i + 3] & 0xFF) << 24;
+
+        k *= m;
+        k ^= k >> r;
+        k *= m;
+
+        h *= m;
+        h ^= k;
+
+        i += 4;
+        len -= 4;
+    }
+
+    switch (len) {
+        case 3: h ^= (data[i + 2] & 0xFF) << 16;
+        case 2: h ^= (data[i + 1] & 0xFF) << 8;
+        case 1: h ^= (data[i + 0] & 0xFF); h *= m;
+    }
+
+    h ^= h >> 13;
+    h *= m;
+    h ^= h >> 15;
+
+    return h;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/map.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,64 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MAP_H
+#define	MAP_H
+
+#include "list.h"
+#include "sstring.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _hashmap_elm {
+    int hash;
+    sstr_t key;
+
+    void *data;
+} hashmap_elm_t;
+
+typedef struct _util_hashmap {
+    sdlist_t **map;
+    size_t len;
+} hashmap_t;
+
+hashmap_t* hashmap_new(size_t size);
+void hashmap_free(hashmap_t *map);
+
+void hashmap_put(hashmap_t *map, sstr_t key, void *value);
+void* hashmap_get(hashmap_t *map, sstr_t key);
+
+int hashmap_hash(char *data, size_t len);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* MAP_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/netsite.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,173 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef NETSITE_H
+#define NETSITE_H
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * Standard defs for NetSite servers.
+ */
+
+#include <mps/nspr.h>
+
+#ifndef BASE_SYSTEMS_H
+#include "systems.h"
+#endif /* !BASE_SYSTEMS_H */
+
+
+
+#define MAGNUS_VERSION_STRING INTsystem_version()
+#define MAGNUS_VERSION PRODUCT_VERSION_ID
+
+/* Include the public nsapi.h definitions */
+#ifndef PUBLIC_NETSITE_H
+#include "nsapi.h"
+#endif /* PUBLIC_NETSITE_H */
+
+NSPR_BEGIN_EXTERN_C
+
+/*
+ * Only the mainline needs to set the malloc key.
+ */
+
+NSAPI_PUBLIC void InitThreadMallocKey(void);
+
+NSAPI_PUBLIC void system_set_temp_dir(const char *dir);
+
+NSAPI_PUBLIC const char *system_get_temp_dir(void);
+
+/* This probably belongs somewhere else, perhaps with a different name */
+NSAPI_PUBLIC char *INTdns_guess_domain(char * hname);
+
+/* --- Begin public functions --- */
+
+#ifdef INTNSAPI
+
+NSAPI_PUBLIC char *INTsystem_version(void);
+
+/*
+   Depending on the system, memory allocated via these macros may come from 
+   an arena. If these functions are called from within an Init function, they 
+   will be allocated from permanent storage. Otherwise, they will be freed 
+   when the current request is finished.
+ */
+
+#define MALLOC(size) INTsystem_malloc(size)
+NSAPI_PUBLIC void *INTsystem_malloc(int size);
+
+#define CALLOC(size) INTsystem_calloc(size)
+NSAPI_PUBLIC void *INTsystem_calloc(int size);
+
+#define REALLOC(ptr, size) INTsystem_realloc(ptr, size)
+NSAPI_PUBLIC void *INTsystem_realloc(void *ptr, int size);
+
+#define FREE(ptr) INTsystem_free(ptr)
+NSAPI_PUBLIC void INTsystem_free(void *ptr);
+
+#define STRDUP(ptr) INTsystem_strdup(ptr)
+NSAPI_PUBLIC char *INTsystem_strdup(const char *ptr);
+
+/*
+   These macros always provide permanent storage, for use in global variables
+   and such. They are checked at runtime to prevent them from returning NULL.
+ */
+
+#define PERM_MALLOC(size) INTsystem_malloc_perm(size)
+NSAPI_PUBLIC void *INTsystem_malloc_perm(int size);
+
+#define PERM_CALLOC(size) INTsystem_calloc_perm(size)
+NSAPI_PUBLIC void *INTsystem_calloc_perm(int size);
+
+#define PERM_REALLOC(ptr, size) INTsystem_realloc_perm(ptr, size)
+NSAPI_PUBLIC void *INTsystem_realloc_perm(void *ptr, int size);
+
+#define PERM_FREE(ptr) INTsystem_free_perm(ptr)
+NSAPI_PUBLIC void INTsystem_free_perm(void *ptr);
+
+#define PERM_STRDUP(ptr) INTsystem_strdup_perm(ptr)
+NSAPI_PUBLIC char *INTsystem_strdup_perm(const char *ptr);
+
+/* Thread-Private data key index for accessing the thread-private memory pool.
+ * Each thread creates its own pool for allocating data.  The MALLOC/FREE/etc
+ * macros have been defined to check the thread private data area with the
+ * thread_malloc_key index to find the address for the pool currently in use.
+ *
+ * If a thread wants to use a different pool, it must change the thread-local-
+ * storage[thread_malloc_key].
+ */
+
+NSAPI_PUBLIC int INTgetThreadMallocKey(void);
+
+NSAPI_PUBLIC pool_handle_t *INTsystem_pool(void);
+
+/* Not sure where to put this. */
+NSAPI_PUBLIC void INTmagnus_atrestart(void (*fn)(void *), void *data);
+
+NSAPI_PUBLIC void INTsystem_setnewhandler(void);
+
+#endif /* INTNSAPI */
+
+/* --- End public functions --- */
+
+NSPR_END_EXTERN_C
+
+#ifdef INTNSAPI
+
+#define dns_guess_domain INTdns_guess_domain
+//define system_version INTsystem_version
+#define system_malloc INTsystem_malloc
+#define system_calloc INTsystem_calloc
+#define system_realloc INTsystem_realloc
+#define system_free INTsystem_free
+#define system_strdup INTsystem_strdup
+#define system_malloc_perm INTsystem_malloc_perm
+#define system_calloc_perm INTsystem_calloc_perm
+#define system_realloc_perm INTsystem_realloc_perm
+#define system_free_perm INTsystem_free_perm
+#define system_strdup_perm INTsystem_strdup_perm
+#define getThreadMallocKey INTgetThreadMallocKey
+#define system_pool INTsystem_pool
+#define magnus_atrestart INTmagnus_atrestart
+#define system_setnewhandler INTsystem_setnewhandler
+
+#endif /* INTNSAPI */
+
+#ifndef HTTPS_ADMSERV 
+#define HTTPS_ADMSERV "https-admserv"
+#endif
+
+#endif /* NETSITE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/nsapi.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,1656 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PUBLIC_NSAPI_H
+#define PUBLIC_NSAPI_H
+
+/*
+ * File:        nsapi.h
+ *
+ * Description:
+ *
+ *      This file defines an interface for extending the server with
+ *      in-process plug-ins.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* NSAPI version defined by this header file */
+#define NSAPI_VERSION 303
+
+/* Define USE_NSAPI_VERSION to use a specific NSAPI version at compile time */
+#ifdef USE_NSAPI_VERSION
+#if USE_NSAPI_VERSION < 300 || USE_NSAPI_VERSION > NSAPI_VERSION
+#error This header file does not support the requested NSAPI version
+#else
+#undef NSAPI_VERSION
+#define NSAPI_VERSION USE_NSAPI_VERSION
+#endif
+#endif
+
+/* --- Begin native platform configuration definitions --- */
+
+#if !defined(XP_WIN32) && !defined(XP_UNIX)
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
+#define XP_WIN32
+#else
+#define XP_UNIX
+#endif
+#endif
+
+#ifdef XP_UNIX
+#define NSAPI_PUBLIC
+#define ZERO(ptr, len) memset(ptr, 0, len)
+#ifdef AIX
+#define TCPLEN_T size_t
+#endif
+#ifdef HPUX
+#define TCPLEN_T int
+#endif
+#ifndef TCPLEN_T
+#define TCPLEN_T socklen_t
+#endif
+#endif /* XP_UNIX */
+
+#ifdef XP_WIN32
+#define NSAPI_PUBLIC __declspec(dllexport)
+struct iovec {
+    char *iov_base;
+    unsigned iov_len;
+};
+#ifndef S_ISDIR
+#define S_ISDIR(mode) ((mode & S_IFMT) == S_IFDIR)
+#endif
+#ifndef S_ISREG
+#define S_ISREG(mode) ((mode & S_IFMT) == S_IFREG)
+#endif
+#ifndef S_ISLNK
+#define S_ISLNK(x) (0)
+#endif
+#define caddr_t PCHAR
+#define NEED_STRCASECMP
+#define NEED_STRNCASECMP
+#define ZERO(ptr, len) ZeroMemory(ptr, len)
+#define TCPLEN_T int
+#endif /* XP_WIN32 */
+
+/* --- End native platform configuration definitions --- */
+
+/* --- Begin miscellaneous definitions --- */
+
+/* Used in some places as a length limit on error messages */
+#define MAGNUS_ERROR_LEN 1024
+
+/* Carriage return and line feed */
+#define CR 13
+#define LF 10
+#ifdef XP_WIN32
+#define ENDLINE "\r\n"
+#else
+#define ENDLINE "\n"
+#endif
+
+/* mime.types file identification line */
+#define NCC_MT_MAGIC "#--Netscape Communications Corporation MIME Information"
+#define NCC_MT_MAGIC_LEN 55
+
+/* The character which separates extensions with cinfo_find */
+#define CINFO_SEPARATOR '.'
+
+/* The maximum length of a line in a mime.types file */
+#define CINFO_MAX_LEN 1024
+
+/* The maximum length of an error message */
+#define MAX_ERROR_LEN 4096
+
+/*
+ * A warning is a minor mishap, such as a 404 being issued.
+ */
+#define LOG_WARN 0
+
+/* 
+ * A misconfig is when there is a syntax error or permission violation in
+ * a config file.
+ */
+#define LOG_MISCONFIG 1
+
+/* 
+ * Security warnings are issued when authentication fails, or a host is
+ * given a 403 return code.
+ */
+#define LOG_SECURITY 2
+
+/*
+ * A failure is when a request could not be fulfilled due to an internal
+ * problem, such as a CGI script exiting prematurely, or a filesystem 
+ * permissions problem.
+ */
+#define LOG_FAILURE 3
+
+/*
+ * A catastrophe is a fatal server error such as running out of
+ * memory or processes, or a system call failing, or even a server crash. 
+ * The server child cannot recover from a catastrophe.
+ */
+#define LOG_CATASTROPHE 4
+
+/*
+ * Informational message, of no concern.
+ */
+#define LOG_INFORM 5
+
+/*
+ * Internal diagnostic message.
+ */
+#define LOG_VERBOSE 6
+
+/*
+ * The time format to use in the error log
+ */
+#define ERR_TIMEFMT "[%d/%b/%Y:%H:%M:%S]"
+
+
+/* The fd you will get if you are reporting errors to SYSLOG */
+#define ERRORS_TO_SYSLOG NULL
+
+/* Return codes from file I/O routines */
+#define IO_OKAY 1
+#define IO_ERROR -1
+#define IO_EOF 0
+#define NETBUF_EOF      -1
+#define NETBUF_ERROR    -2
+#define NETBUF_FULL     -3
+
+/* The disk page size on this machine. */
+#define FILE_BUFFERSIZE 4096
+
+#ifdef XP_UNIX
+
+#define FILE_PATHSEP '/'
+#define FILE_PARENT "../"
+
+#elif defined(XP_WIN32)
+
+#define FILE_PATHSEP '/'
+#define FILE_PARENT "..\\"
+
+#endif /* XP_WIN32 */
+
+#define NET_INFINITE_TIMEOUT 0
+#define NET_ZERO_TIMEOUT -1
+
+#ifdef USE_REGEX
+/* WILDPAT uses regular expressions */
+#define WILDPAT_VALID(exp)              regexp_valid(exp)
+#define WILDPAT_MATCH(str, exp)         regexp_match(str, exp)
+#define WILDPAT_CMP(str, exp)           regexp_cmp(str, exp)
+#define WILDPAT_CASECMP(str, exp)       regexp_casecmp(str, exp)
+#define WILDPAT_USES_REGEXP              1
+#else
+/* WILDPAT uses shell expressions */
+#define WILDPAT_VALID(exp)              shexp_valid(exp)
+#define WILDPAT_MATCH(str, exp)         shexp_match(str, exp)
+#define WILDPAT_CMP(str, exp)           shexp_cmp(str, exp)
+#define WILDPAT_CASECMP(str, exp)       shexp_casecmp(str, exp)
+#define WILDPAT_USES_SHEXP              1
+#endif
+
+/* Define return codes from WILDPAT_VALID */
+#define NON_WILDPAT     -1              /* exp is ordinary string */
+#define INVALID_WILDPAT -2              /* exp is an invalid pattern */
+#define VALID_WILDPAT   1               /* exp is a valid pattern */
+
+/* Define return codes from regexp_valid and shexp_valid */
+#define NON_SXP         NON_WILDPAT     /* exp is an ordinary string */
+#define INVALID_SXP     INVALID_WILDPAT /* exp is an invalid shell exp */
+#define VALID_SXP       VALID_WILDPAT   /* exp is a valid shell exp */
+
+#define NON_REGEXP      NON_SXP
+#define INVALID_REGEXP  INVALID_SXP
+#define VALID_REGEXP    VALID_SXP
+
+#define SYSTHREAD_DEFAULT_PRIORITY 16
+
+/* The longest line in the configuration file */
+#define CONF_MAXLEN 16384
+
+#define HTTP_DATE_LEN 30
+#define HTTP_DATE_FMT "%a, %d %b %Y %T GMT"
+
+/* HTTP status codes */
+#define PROTOCOL_CONTINUE 100
+#define PROTOCOL_SWITCHING 101
+#define PROTOCOL_OK 200
+#define PROTOCOL_CREATED 201
+#define PROTOCOL_ACCEPTED 202
+#define PROTOCOL_NONAUTHORITATIVE 203
+#define PROTOCOL_NO_RESPONSE 204
+#define PROTOCOL_NO_CONTENT 204
+#define PROTOCOL_RESET_CONTENT 205
+#define PROTOCOL_PARTIAL_CONTENT 206
+#define PROTOCOL_MULTI_STATUS 207
+#define PROTOCOL_MULTIPLE_CHOICES 300
+#define PROTOCOL_MOVED_PERMANENTLY 301
+#define PROTOCOL_REDIRECT 302
+#define PROTOCOL_SEE_OTHER 303
+#define PROTOCOL_NOT_MODIFIED 304
+#define PROTOCOL_USE_PROXY 305
+#define PROTOCOL_TEMPORARY_REDIRECT 307
+#define PROTOCOL_BAD_REQUEST 400
+#define PROTOCOL_UNAUTHORIZED 401
+#define PROTOCOL_PAYMENT_REQUIRED 402
+#define PROTOCOL_FORBIDDEN 403
+#define PROTOCOL_NOT_FOUND 404
+#define PROTOCOL_METHOD_NOT_ALLOWED 405
+#define PROTOCOL_NOT_ACCEPTABLE 406
+#define PROTOCOL_PROXY_UNAUTHORIZED 407
+#define PROTOCOL_REQUEST_TIMEOUT 408
+#define PROTOCOL_CONFLICT 409
+#define PROTOCOL_GONE 410
+#define PROTOCOL_LENGTH_REQUIRED 411
+#define PROTOCOL_PRECONDITION_FAIL 412
+#define PROTOCOL_ENTITY_TOO_LARGE 413
+#define PROTOCOL_URI_TOO_LARGE 414
+#define PROTOCOL_UNSUPPORTED_MEDIA_TYPE 415
+#define PROTOCOL_REQUESTED_RANGE_NOT_SATISFIABLE 416
+#define PROTOCOL_EXPECTATION_FAILED 417
+#define PROTOCOL_LOCKED 423
+#define PROTOCOL_FAILED_DEPENDENCY 424
+#define PROTOCOL_SERVER_ERROR 500
+#define PROTOCOL_NOT_IMPLEMENTED 501
+#define PROTOCOL_BAD_GATEWAY 502
+#define PROTOCOL_SERVICE_UNAVAILABLE 503
+#define PROTOCOL_GATEWAY_TIMEOUT 504
+#define PROTOCOL_VERSION_NOT_SUPPORTED 505
+#define PROTOCOL_INSUFFICIENT_STORAGE 507
+
+#define PROTOCOL_VERSION_HTTP09 9
+#define PROTOCOL_VERSION_HTTP10 100
+#define PROTOCOL_VERSION_HTTP11 101
+#define CURRENT_PROTOCOL_VERSION PROTOCOL_VERSION_HTTP11
+
+/* Definitions for HTTP over SSL */
+#define HTTPS_PORT 443
+#define HTTPS_URL "https"
+
+/* Definitions for HTTP over TCP */
+#define HTTP_PORT 80
+#define HTTP_URL "http"
+
+
+#define REQ_MAX_LINE 4096
+    
+/*
+ * The REQ_ return codes. These codes are used to determine what the server
+ * should do after a particular module completes its task.
+ *
+ * Func type functions return these as do many internal functions.
+ */
+
+/* The function performed its task, proceed with the request */
+#define REQ_PROCEED 0
+/* The entire request should be aborted: An error occurred */
+#define REQ_ABORTED -1
+/* The function performed no task, but proceed anyway */
+#define REQ_NOACTION -2
+/* Tear down the session and exit */
+#define REQ_EXIT -3
+/* Restart the entire request-response process */
+#define REQ_RESTART -4
+/* Too busy to execute this now */
+#define REQ_TOOBUSY -5
+
+/* --- End miscellaneous definitions --- */
+
+/* --- Begin native platform includes --- */
+
+#ifdef XP_UNIX
+#include <unistd.h>
+#include <sys/file.h>
+#ifndef HPUX
+#include <sys/select.h>
+#endif
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <pwd.h>
+#include <netinet/in.h>
+#endif /* XP_UNIX */
+
+#ifdef XP_WIN32
+#include <wtypes.h>
+#include <winbase.h>
+#include <direct.h>
+#include <winsock.h>
+#endif /* XP_WIN32 */
+
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+
+/* --- End native platform includes --- */
+
+/* --- Begin type definitions --- */
+
+/* NOTE: both SYS_FILE and SYS_NETFD are actually NSPR PRFileDesc * and can */
+/*       be used with NSPR API calls (after casting them to PRFileDesc *) */
+
+#ifndef SYS_FILE_T
+typedef void *SYS_FILE;
+#define SYS_FILE_T void *
+#endif /* !SYS_FILE_T */
+
+#define SYS_ERROR_FD ((SYS_FILE)-1)
+
+#ifndef SYS_NETFD_T
+typedef void *SYS_NETFD;
+#define SYS_NETFD_T void *
+#endif /* !SYS_NETFD_T */
+
+/* Error value for a SYS_NETFD */
+#ifndef SYS_NET_ERRORFD
+#define SYS_NET_ERRORFD ((SYS_NETFD)-1)
+#endif /* !SYS_NET_ERRORFD */
+
+/*
+ * These structures were originally defined in nsapi.h, but those definitions
+ * were removed in iPlanet Web Server 4.0.  The contents of these structures
+ * are now private to the server implementation and must not be accessed
+ * directly.  Instead, use the objset_*, object_*, directive_table_*, and
+ * directive_* accessor functions.
+ */
+typedef struct directive directive;
+typedef struct dtable dtable;
+typedef struct httpd_object httpd_object;
+typedef struct httpd_objset httpd_objset;
+
+/*
+ * Type:        filebuffer, filebuf_t
+ *
+ * Description:
+ *
+ *      This structure is used to represent a buffered file.  On some
+ *      systems the file may be memory-mapped.  A filebuffer is created
+ *      by filebuf_open(), and destroyed by filebuf_close().
+ *
+ * Notes:
+ *
+ *      Direct access to the members of this structure, not using
+ *      macros defined here, is discouraged.
+ *
+ *      The filebuf alias that used to be defined for this type was
+ *      found to conflict with a C++ class of the same name, so it
+ *      has been renamed to filebuf_t.
+ */
+typedef struct filebuffer filebuffer;
+
+/* Version of filebuffer when memory-mapped files are supported */
+struct filebuffer {
+    SYS_FILE fd;
+#ifdef XP_WIN32
+    HANDLE fdmap;
+#endif
+    caddr_t fp;
+    int len;
+
+    unsigned char *inbuf;
+    int cursize;
+
+    int pos;
+    const char *errmsg;
+};
+
+/* Return next character or IO_EOF */
+#define filebuf_getc(b) ((b)->pos == (b)->len ? IO_EOF : (int)((b)->fp)[(b)->pos++])
+
+#define filebuf_iseof(b) ((b)->pos == (b)->len)
+
+/* C++ streamio defines a filebuf class. */
+typedef filebuffer filebuf_t;
+
+#ifdef XP_WIN32
+/* Use a filebuffer to read data from a pipe */
+#define pipebuf_getc(b) \
+ ((b)->pos != (b)->cursize ? (int)((b)->inbuf[(b)->pos++]) : pipebuf_next(b,1))
+#endif /* XP_WIN32 */
+
+/*
+ * Type:        netbuf
+ *
+ * Description:
+ *
+ *      This structure is used to represent a buffered network socket.
+ *      It is created by netbuf_open(), and destroyed by netbuf_close().
+ *
+ * Notes:
+ *
+ *      Direct access to the members of this structure, not using
+ *      macros defined here, is discouraged.
+ *
+ *      The inbuf field used to be (unsigned char *), but is now
+ *      simply (char *).  The value returned by the netbuf_getc()
+ *      macro is (int).
+ */
+typedef struct netbuf netbuf;
+struct netbuf {
+    SYS_NETFD sd;
+
+    int pos, cursize, maxsize, rdtimeout;
+#ifdef XP_WIN32
+    CHAR address[64];
+#endif /* XP_WIN32 */
+    unsigned char *inbuf;
+    char *errmsg;
+#ifndef XP_WIN32
+    char address[64];
+#endif /* !XP_WIN32 */
+};
+
+/*
+ * netbuf_getc gets a character from the given network buffer and returns 
+ * it (as an integer).
+ * 
+ * It will return (int) IO_ERROR for an error and (int) IO_EOF for
+ * an error condition or EOF respectively.
+ */
+#define netbuf_getc(b) \
+ ((b)->pos != (b)->cursize ? (int)((b)->inbuf[(b)->pos++]) : netbuf_next(b,1))
+
+/*
+ * buffer_error returns the last error that occurred with buffer.  Don't use
+ * this unless you know an error occurred.  Independent of network/file type.
+ */
+#define buffer_error(b) ((b)->errmsg)
+
+/*
+ * Type:        sendfiledata
+ *
+ * Description:
+ *
+ *      This structure is used to pass arguments to the net_sendfile()
+ *      function.  offset and len may be set to 0 to transmit a file in its
+ *      entirety.
+ */
+typedef struct sendfiledata sendfiledata;
+struct sendfiledata {
+    SYS_FILE fd;         /* file to send */
+    size_t offset;       /* offset in file to start sending from */
+    size_t len;          /* number of bytes to send from file */
+    const void *header;  /* data to send before file */
+    int hlen;            /* number of bytes to send before file */
+    const void *trailer; /* data to send after file */
+    int tlen;            /* number of bytes to send after file */
+};
+
+/*
+ * Type:        NSAPIIOVec
+ *
+ * Description:
+ *
+ *      This structure is used to pass arguments to the net_writev()
+ *      and FilterWritevFunc() functions.  
+ */
+#ifdef _LP64
+typedef struct NSAPIIOVec NSAPIIOVec;
+struct NSAPIIOVec {
+    char *iov_base;
+    int iov_len;
+};
+#else
+typedef struct iovec NSAPIIOVec;
+#endif /* _LP64 */
+
+
+/*
+ * Type:        cinfo
+ *
+ * Description:
+ *
+ *      This is a structure that captures the information in the name/value
+ *      pairs on one line of a mime.types file.  A cinfo structure is
+ *      stored in the memory-resident database, indexed by each of the
+ *      file extensions specified in the "exts" name/value pair.  It
+ *      defines various attributes of resources with names containing
+ *      the specified file extensions.
+ *
+ * Notes:
+ *
+ *      Pointers to cinfo structures returned by this API may or may not
+ *      need to freed by the caller.  See the individual function
+ *      descriptions.
+ *
+ *      The strings referenced by the fields of cinfo structures returned
+ *      by this API should be considered read-only, and do not need to be
+ *      freed by the caller, even when the cinfo structure does.
+ */
+typedef struct cinfo cinfo;
+struct cinfo {
+    char *type;
+    char *encoding;
+    char *language;
+};
+
+
+typedef void* CONDVAR;
+typedef void *COUNTING_SEMAPHORE;
+typedef void* CRITICAL;
+
+#ifdef XP_UNIX
+typedef DIR* SYS_DIR;
+typedef struct dirent SYS_DIRENT;
+#endif /* XP_UNIX */
+
+#ifdef XP_WIN32
+
+typedef struct dirent_s dirent_s;
+struct dirent_s {
+    char *d_name;
+};
+
+typedef struct dir_s dir_s;
+struct dir_s {
+    HANDLE dp;
+    WIN32_FIND_DATA fdata;
+    dirent_s de;
+};
+
+typedef dir_s* SYS_DIR;
+typedef dirent_s SYS_DIRENT;
+
+#endif /* XP_WIN32 */
+
+typedef struct pb_param pb_param;
+struct pb_param {
+    char *name,*value;
+};
+
+typedef struct pb_entry pb_entry;
+struct pb_entry {
+    pb_param *param;
+    struct pb_entry *next;
+};
+
+typedef struct pblock pblock;
+struct pblock {
+    int hsize;
+    struct pb_entry **ht;
+};
+
+#ifndef POOL_HANDLE_T
+#define POOL_HANDLE_T
+typedef void *pool_handle_t;
+#endif
+
+#ifndef SEMAPHORE_T
+typedef void *SEMAPHORE;
+#define SEMAPHORE_T void *
+#endif /* !SEMAPHORE_T */
+
+#define SESSION_HASHSIZE 5
+
+typedef struct PListStruct_s PListStruct_s;
+typedef struct ACLListHandle ACLListHandle;
+
+#ifndef PR_AF_INET
+typedef union PRNetAddr PRNetAddr;
+#endif
+
+typedef struct Session Session;
+typedef struct Request Request;
+struct Session {
+    pblock *client;     /* client-specific information */
+
+    SYS_NETFD csd;      /* client file descriptor */
+    netbuf *inbuf;      /* input buffer */
+    int csd_open;
+
+    struct in_addr iaddr;
+
+    pool_handle_t *pool;
+
+    void *clauth;       /* v2 ACL client authentication information */
+    struct Session *next;
+    int fill;
+    struct sockaddr_in local_addr;      /* local addr for this session */
+
+    PListStruct_s *subject;
+    int ssl;            /* 0 = SSL OFF, 1 = SSL ON */
+    int clientauth;     /* 0 = client auth OFF, 1 = client auth ON */
+
+    PRNetAddr *pr_client_addr;
+    PRNetAddr *pr_local_addr;
+};
+
+/*
+ * FuncPtr is a pointer to an NSAPI SAF function
+ */
+
+#ifdef XP_UNIX
+typedef int Func(pblock *, Session *, Request *);
+#else /* XP_WIN32 */
+typedef int _cdecl Func(pblock *, Session *, Request *);
+#endif /* XP_WIN32 */
+
+typedef Func *FuncPtr;
+
+/*
+ * FuncStruct is a structure used in the static declaration of the 
+ * functions.  This static declaration is parsed into a hash table at 
+ * startup.
+ */
+
+typedef struct FuncStruct FuncStruct;
+
+struct FuncStruct {
+    const char * name;
+    FuncPtr func;
+    struct FuncStruct *next;
+    unsigned flags;
+    unsigned poolID;
+    unsigned pool_resolved;
+};
+
+/*
+ * VSInitFunc, VSDestroyFunc, VSDirectiveInitFunc and VSDirectiveDestroyFunc
+ */
+typedef struct VirtualServer VirtualServer;
+typedef int VSInitFunc(VirtualServer *incoming, const VirtualServer *current);
+typedef void VSDestroyFunc(VirtualServer *outgoing);
+typedef VSInitFunc *VSInitFuncPtr;
+typedef VSDestroyFunc *VSDestroyFuncPtr;
+typedef int VSDirectiveInitFunc(const directive *dir, VirtualServer *incoming, const VirtualServer *current);
+typedef void VSDirectiveDestroyFunc(const directive *dir, VirtualServer *outgoing);
+typedef VSDirectiveInitFunc *VSDirectiveInitFuncPtr;
+typedef VSDirectiveDestroyFunc *VSDirectiveDestroyFuncPtr;
+
+/*
+ * Filter is an opaque filter identifier
+ */
+typedef struct Filter Filter;
+
+/*
+ * FilterContext stores context associated with a particular filter layer
+ */
+
+typedef struct FilterContext FilterContext;
+
+struct FilterContext {
+    pool_handle_t *pool; /* pool context was allocated from */
+    Session *sn;         /* session being processed */
+    Request *rq;         /* request being processed */
+    void *data;          /* filter-defined private data */
+};
+
+/*
+ * FilterLayer represents one layer of a filter stack
+ */
+
+typedef struct FilterLayer FilterLayer;
+
+struct FilterLayer {
+    Filter *filter;         /* the filter at this layer in the filter stack */
+    FilterContext *context; /* context for the filter */
+    SYS_NETFD lower;        /* access to the next filter layer in the stack */
+};
+
+/*
+ * Function prototypes for filter methods
+ */
+typedef int (FilterInsertFunc)(FilterLayer *layer, pblock *pb);
+typedef void (FilterRemoveFunc)(FilterLayer *layer);
+typedef int (FilterFlushFunc)(FilterLayer *layer);
+typedef int (FilterReadFunc)(FilterLayer *layer, void *buf, int amount, int timeout);
+typedef int (FilterWriteFunc)(FilterLayer *layer, const void *buf, int amount);
+typedef int (FilterWritevFunc)(FilterLayer *layer, const NSAPIIOVec *iov, int iov_size);
+typedef int (FilterSendfileFunc)(FilterLayer *layer, sendfiledata *sfd);
+
+/*
+ * FilterMethods is passed to filter_create() to declare the filter methods for
+ * a new filter.  Each instance of the FilterMethods structure should be
+ * initialized using the FILTER_METHODS_INITIALIZER macro.
+ */
+
+typedef struct FilterMethods FilterMethods;
+
+struct FilterMethods {
+    size_t size;
+#if NSAPI_VERSION >= 302
+    FilterInsertFunc *insert;
+    FilterRemoveFunc *remove;
+    FilterFlushFunc *flush;
+    FilterReadFunc *read;
+    FilterWriteFunc *write;
+    FilterWritevFunc *writev;
+    FilterSendfileFunc *sendfile;
+#else
+    void *reserved1;
+    void *reserved2;
+    void *reserved3;
+    void *reserved4;
+    void *reserved5;
+    void *reserved6;
+    void *reserved7;
+#endif /* NSAPI_VERSION >= 302 */
+};
+
+#define FILTER_METHODS_INITIALIZER \
+{                                  \
+    sizeof(FilterMethods),         \
+    NULL, /* insert */             \
+    NULL, /* remove */             \
+    NULL, /* flush */              \
+    NULL, /* read */               \
+    NULL, /* write */              \
+    NULL, /* writev */             \
+    NULL  /* sendfile */           \
+}
+
+/*
+ * Filter order definitions for filter_create()
+ */
+#define FILTER_CONTENT_GENERATION       0xf0000
+#define FILTER_CONTENT_TRANSLATION_HIGH 0xa0000
+#define FILTER_CONTENT_TRANSLATION      0x90000
+#define FILTER_CONTENT_TRANSLATION_LOW  0x80000
+#define FILTER_CONTENT_CODING           0x50000
+#define FILTER_TRANSFER_CODING          0x40000
+#define FILTER_MESSAGE_CODING           0x30000
+#define FILTER_TRANSPORT_CODING         0x20000
+#define FILTER_NETWORK                  0x10000
+
+typedef struct shmem_s shmem_s;
+struct shmem_s {
+    void *data;   /* the data */
+#ifdef XP_WIN32
+    HANDLE fdmap;
+#endif /* XP_WIN32 */
+    int size;     /* the maximum length of the data */
+
+    char *name;   /* internal use: filename to unlink if exposed */
+    SYS_FILE fd;  /* internal use: file descriptor for region */
+};
+
+/* Define a handle for a thread */
+typedef void* SYS_THREAD;
+
+/* Define an error value for the thread handle */
+#define SYS_THREAD_ERROR NULL
+
+
+typedef struct conf_global_vars_s conf_global_vars_s;
+struct conf_global_vars_s {
+
+    /* What port we listen to */
+    int Vport;                                  /* OBSOLETE */
+#define server_portnum conf_getglobals()->Vport
+
+    /* What address to bind to */
+    char *Vaddr;                                /* OBSOLETE */
+
+    /* User to run as */
+    struct passwd *Vuserpw;
+
+    /* Directory to chroot to */
+    char *Vchr;
+
+    /* Where to log our pid to */
+    char *Vpidfn;
+
+#define pool_max conf_getglobals()->Vpool_max
+    int Vpool_max;
+#define pool_min conf_getglobals()->Vpool_min
+    int Vpool_min;                              /* OBSOLETE */
+#define pool_life conf_getglobals()->Vpool_life
+    int Vpool_life;                             /* OBSOLETE */
+
+    /* For multiprocess UNIX servers, the maximum threads per process */
+#define pool_maxthreads conf_getglobals()->Vpool_maxthreads
+    int Vpool_maxthreads;
+
+#define pool_minthreads conf_getglobals()->Vpool_minthreads
+    int Vpool_minthreads;                       /* OBSOLETE */
+
+    char *Vsecure_keyfn;                        /* OBSOLETE */
+    char *Vsecure_certfn;                       /* OBSOLETE */
+
+#define security_active conf_getglobals()->Vsecurity_active
+    int Vsecurity_active;
+    int Vssl3_active;                           /* OBSOLETE */
+    int Vssl2_active;                           /* OBSOLETE */
+    int Vsecure_auth;                           /* OBSOLETE */
+    int Vsecurity_session_timeout;
+    long Vssl3_session_timeout;
+
+    /* The server's hostname as should be reported in self-ref URLs */
+#define server_hostname conf_getglobals()->Vserver_hostname
+    char *Vserver_hostname;
+
+    /* The main object from which all are derived */
+#define root_object conf_getglobals()->Vroot_object
+    char *Vroot_object;
+
+    /* The object set the administrator has asked us to load */
+#define std_os conf_getglobals()->Vstd_os
+    httpd_objset *Vstd_os;
+
+    /* The root of ACL data structures */
+    void *Vacl_root;
+
+    /* The main error log, where all errors are logged */
+    char *Vmaster_error_log;
+
+    /* The server root directory (contains instance subdirectories) */
+#define server_root conf_getglobals()->Vserver_root
+    char *Vserver_root;
+
+    /* This server's id */
+#define server_id conf_getglobals()->Vserver_id
+    char *Vserver_id;
+
+    /* Admin server users file */
+    char *Vadmin_users;
+
+    /* The installation directory (contains bin and lib subdirectories) */
+    char *Vnetsite_root;
+
+    /* Digest authentication stale nonce timeout value */
+    int digest_stale_timeout;
+
+    int single_accept;          /* OBSOLETE */
+    int num_keep_alives;        /* OBSOLETE */
+    int log_verbose;            /* OBSOLETE */
+    int mmap_flags;             /* OBSOLETE */
+    int mmap_prots;             /* OBSOLETE */
+    int unused1;
+    int unused2;
+
+    /* Begin Enterprise 3.0 fields */
+    int accept_language;        /* turn accept-language on/off */
+
+    char *mtahost;
+    char *nntphost;             /* OBSOLETE */
+
+    /* The root of ACL data structures */
+    void *Vacl_root_30;
+
+    char *agentFilePath;        /* OBSOLETE */
+
+    int Allowed;                /* OBSOLETE */
+
+    pblock *genericGlobals;     /* OBSOLETE */
+
+    char *agentsACLFile;        /* OBSOLETE */
+
+    int wait_for_cgi;           /* OBSOLETE */
+    int cgiwatch_timeout;       /* OBSOLETE */
+    int started_by_watchdog;
+    int restarted_by_watchdog;
+    int old_accel_cache_enabled; /* OBSOLETE */
+    int Vssl_cache_entries;
+    int blocking_listen_socket; /* OBSOLETE */
+    pblock **initfns;
+    char *vs_config_file;       /* OBSOLETE */
+};
+
+/* Type used for Request rq_attr bit flags */
+#ifdef AIX
+#define RQATTR unsigned
+#else
+#define RQATTR unsigned long
+#endif
+
+struct Request {
+    /* Server working variables */
+    pblock *vars;
+
+    /* The method, URI, and protocol revision of this request */
+    pblock *reqpb;
+    /* Protocol specific headers */
+    int loadhdrs;
+    pblock *headers;
+
+    /* Server's response headers */
+    int senthdrs;
+    pblock *srvhdrs;
+
+    /* The object set constructed to fulfill this request */
+    httpd_objset *os;
+    /* Array of objects that were created from .nsconfig files */
+    httpd_objset *tmpos;
+
+    /* The stat last returned by request_stat_path */
+    char *statpath;
+    char *staterr;
+    struct stat *finfo;
+
+    /* access control state */
+    int aclstate;               /* ACL decision state */
+    int acldirno;               /* deciding ACL directive number */
+    char *aclname;              /* name of deciding ACL */
+    pblock *aclpb;              /* OBSOLETE */
+    /* 3.0 ACL list pointer */
+    ACLListHandle *acllist;
+
+    int request_is_cacheable;   /* */
+    int directive_is_cacheable; /* set by SAFs with no external side effects that make decisions based solely on URI and path */
+
+    char *cached_headers;       /* OBSOLETE */
+    int cached_headers_len;     /* OBSOLETE */
+    char *unused;
+
+    /* HTTP/1.1 features */
+#define REQ_TIME(x)             (x)->req_start
+    time_t req_start;           /* time request arrived - used for selecting weak or strong cache validation */
+    short protv_num;            /* protocol version number */
+    short method_num;           /* method number */
+    struct rq_attr {
+        RQATTR abs_uri:1;               /* set if absolute URI was used */
+        RQATTR chunked:1;               /* chunked transfer-coding */
+        RQATTR keep_alive:1;            /* connection keep-alive */
+        RQATTR pipelined:1;             /* request packet is pipelined */
+        RQATTR internal_req:1;          /* this was an internal request */
+        RQATTR perm_req:1;              /* don't FREE() this request */
+        RQATTR header_file_present:1;   /* OBSOLETE */
+        RQATTR footer_file_present:1;   /* OBSOLETE */
+        RQATTR jvm_attached:1;          /* OBSOLETE */
+        RQATTR req_restarted:1;         /* request was restarted */
+        RQATTR jvm_request_locked:1;    /* used for first-request serialization on some platforms */
+        RQATTR default_type_set:1;      /* set if default types were set using set-default-type objecttype function */
+        RQATTR is_web_app:1;            /* OBSOLETE */
+        RQATTR ssl_unclean_shutdown:1;  /* set if browser requires unclean SSL shutdown */
+        RQATTR vary_accept_language:1;  /* set if request was restarted based on an accept-language header */
+        RQATTR reserved:17;             /* if you add a flag, make sure to subtract from this */
+    } rq_attr;
+    char *hostname;             /* hostname used to access server (always non-NULL) */
+    int allowed;                /* OBSOLETE */
+    int byterange;              /* OBSOLETE */
+    short status_num;           /* HTTP status code */
+
+    int staterrno;              /* used for rqstat */
+    Request *orig_rq;           /* original Request - used for internal redirects */
+};
+
+/* Request attribute macros */
+#define ABS_URI(x)                      (x)->rq_attr.abs_uri
+#define CHUNKED(x)                      (x)->rq_attr.chunked
+#define KEEP_ALIVE(x)                   (x)->rq_attr.keep_alive 
+#define PIPELINED(x)                    (x)->rq_attr.pipelined 
+#define INTERNAL_REQUEST(x)             (x)->rq_attr.internal_req 
+#define RESTARTED_REQUEST(x)            (x)->rq_attr.req_restarted
+#define PERM_REQUEST(x)                 (x)->rq_attr.perm_req
+#define JVM_REQUEST_LOCKED(x)           (x)->rq_attr.jvm_request_locked
+#define SSL_UNCLEAN_SHUTDOWN(x)         (x)->rq_attr.ssl_unclean_shutdown
+#define VARY_ACCEPT_LANGUAGE(x)         (x)->rq_attr.vary_accept_language
+
+/* Define methods for HTTP/1.1 */
+#define METHOD_HEAD     0
+#define METHOD_GET      1
+#define METHOD_PUT      2
+#define METHOD_POST     3
+#define METHOD_DELETE   4
+#define METHOD_TRACE    5
+#define METHOD_OPTIONS  6
+/* The following methods are Netscape method extensions */
+#define METHOD_MOVE     7
+#define METHOD_INDEX    8
+#define METHOD_MKDIR    9
+#define METHOD_RMDIR    10
+#define METHOD_COPY     11
+#define METHOD_MAX      12      /* Number of methods available on this server */
+
+#define ISMGET(r)       ((r)->method_num == METHOD_GET)
+#define ISMHEAD(r)      ((r)->method_num == METHOD_HEAD)
+#define ISMPUT(r)       ((r)->method_num == METHOD_PUT)
+#define ISMPOST(r)      ((r)->method_num == METHOD_POST)
+#define ISMDELETE(r)    ((r)->method_num == METHOD_DELETE)
+#define ISMMOVE(r)      ((r)->method_num == METHOD_MOVE)
+#define ISMINDEX(r)     ((r)->method_num == METHOD_INDEX)
+#define ISMMKDIR(r)     ((r)->method_num == METHOD_MKDIR)
+#define ISMRMDIR(r)     ((r)->method_num == METHOD_RMDIR)
+#define ISMCOPY(r)      ((r)->method_num == METHOD_COPY)
+#define ISMTRACE(r)     ((r)->method_num == METHOD_TRACE)
+#define ISMOPTIONS(r)   ((r)->method_num == METHOD_OPTIONS)
+
+
+/* --- End type definitions --- */
+
+/* --- Begin dispatch vector table definition --- */
+
+typedef struct nsapi_dispatch_s nsapi_dispatch_t;
+struct nsapi_dispatch_s {
+    char *(*f_system_version)();
+    void *(*f_system_malloc)(int size);
+    void *(*f_system_calloc)(int size);
+    void *(*f_system_realloc)(void *ptr, int size);
+    void (*f_system_free)(void *ptr);
+    char *(*f_system_strdup)(const char *ptr);
+    void *(*f_system_malloc_perm)(int size);
+    void *(*f_system_calloc_perm)(int size);
+    void *(*f_system_realloc_perm)(void *ptr, int size);
+    void (*f_system_free_perm)(void *ptr);
+    char *(*f_system_strdup_perm)(const char *ptr);
+    int (*f_getThreadMallocKey)(void);
+    void (*f_magnus_atrestart)(void (*fn)(void *), void *data);
+    filebuf_t *(*f_filebuf_open)(SYS_FILE fd, int sz);
+    netbuf *(*f_netbuf_open)(SYS_NETFD sd, int sz);
+    filebuf_t *(*f_filebuf_create)(SYS_FILE fd, caddr_t mmap_ptr,
+                                   int mmap_len, int bufsz);
+    void (*f_filebuf_close_buffer)(filebuf_t *buf, int clean_mmap);
+    filebuf_t *(*f_filebuf_open_nostat)(SYS_FILE fd, int sz,
+                                        struct stat *finfo);
+#ifdef XP_WIN32
+    filebuf_t *(*f_pipebuf_open)(SYS_FILE fd, int sz, struct stat *finfo);
+#else
+    void *(*f_pipebuf_open)(void);
+#endif /* XP_WIN32 */
+    int (*f_filebuf_next)(void);
+    int (*f_netbuf_next)(netbuf *buf, int advance);
+#ifdef XP_WIN32 
+    int (*f_pipebuf_next)(filebuf_t *buf, int advance);
+#else
+    int (*f_pipebuf_next)(void);
+#endif /* XP_WIN32 */
+    void (*f_filebuf_close)(filebuf_t *buf);
+    void (*f_netbuf_close)(netbuf *buf);
+#ifdef XP_WIN32
+    void        (*f_pipebuf_close)(filebuf_t *buf);
+#else
+    void (*f_pipebuf_close)(void);
+#endif /* XP_WIN32 */
+    int (*f_filebuf_grab)(filebuf_t *buf, int sz);
+    int (*f_netbuf_grab)(netbuf *buf, int sz);
+#ifdef XP_WIN32
+    int (*f_pipebuf_grab)(filebuf_t *buf, int sz);
+#else
+    int (*f_pipebuf_grab)(void);
+#endif /* XP_WIN32 */
+    int (*f_netbuf_buf2sd)(netbuf *buf, SYS_NETFD sd, int len);
+    int (*f_filebuf_buf2sd)(filebuf_t *buf, SYS_NETFD sd);
+#ifdef XP_WIN32
+    int (*f_pipebuf_buf2sd)(filebuf_t *buf, SYS_NETFD sd, int len);
+    int (*f_pipebuf_netbuf2sd)(netbuf *buf, SYS_FILE sd, int len);
+    int (*f_pipebuf_netbuf2pipe)(netbuf *buf, SYS_NETFD sd, int len);
+#else
+    int (*f_pipebuf_buf2sd)(void);
+    int (*f_pipebuf_netbuf2sd)(void);
+    int (*f_pipebuf_netbuf2pipe)(void);
+#endif /* XP_WIN32 */
+    void (*f_cinfo_init)(void);
+    void (*f_cinfo_terminate)(void);
+    char *(*f_cinfo_merge)(char *fn);
+    cinfo *(*f_cinfo_find)(char *uri);
+    cinfo *(*f_cinfo_lookup)(char *type);
+    void (*f_cinfo_dump_database)(FILE *dump);
+    CRITICAL (*f_crit_init)(void);
+    void (*f_crit_enter)(CRITICAL id);
+    void (*f_crit_exit)(CRITICAL id);
+    void (*f_crit_terminate)(CRITICAL id);
+    CONDVAR (*f_condvar_init)(CRITICAL id);
+    void (*f_condvar_wait)(CONDVAR cv);
+    void (*f_condvar_notify)(CONDVAR cv);
+    void (*f_condvar_notifyAll)(CONDVAR cv);
+    void (*f_condvar_terminate)(CONDVAR cv);
+    COUNTING_SEMAPHORE (*f_cs_init)(int initial_count);
+    void (*f_cs_terminate)(COUNTING_SEMAPHORE csp);
+    int (*f_cs_wait)(COUNTING_SEMAPHORE csp);
+    int (*f_cs_trywait)(COUNTING_SEMAPHORE csp);
+    int (*f_cs_release)(COUNTING_SEMAPHORE csp);
+    void (*f_daemon_atrestart)(void (*fn)(void *), void *data);
+    /* Obsolete: servssl_init() */
+    void (*f_servssl_init)(void);
+    int (*f_ereport)(int degree, const char *fmt, ...);
+    int (*f_ereport_v)(int degree, const char *fmt, va_list args);
+    char *(*f_ereport_init)(const char *err_fn, const char *email,
+                            struct passwd *pwuser, const char *version,
+                            int restart);
+    void (*f_ereport_terminate)(void);
+    SYS_FILE (*f_ereport_getfd)(void);
+    SYS_FILE (*f_system_fopenRO)(const char *path);
+    SYS_FILE (*f_system_fopenWA)(const char *path);
+    SYS_FILE (*f_system_fopenRW)(const char *path);
+    SYS_FILE (*f_system_fopenWT)(const char *path);
+    int (*f_system_fread)(SYS_FILE fd, void *buf, int sz);
+    int (*f_system_fwrite)(SYS_FILE fd, const void *buf,int sz);
+    int (*f_system_fwrite_atomic)(SYS_FILE fd, const void *buf, int sz);
+    int (*f_system_lseek)(SYS_FILE fd, int off, int wh);
+    int (*f_system_fclose)(SYS_FILE fd);
+    int (*f_system_stat)(const char *name, struct stat *finfo);
+    int (*f_system_rename)(const char *oldpath, const char *newpath);
+    int (*f_system_unlink)(const char *path);
+    int (*f_system_tlock)(SYS_FILE fd);
+    int (*f_system_flock)(SYS_FILE fd);
+    int (*f_system_ulock)(SYS_FILE fd);
+#ifdef XP_WIN32
+    SYS_DIR (*f_dir_open)(const char *path);
+    SYS_DIRENT *(*f_dir_read)(SYS_DIR ds);
+    void (*f_dir_close)(SYS_DIR ds);
+#else
+    void *(*f_dir_open)(void);
+    void *(*f_dir_read)(void);
+    void (*f_dir_close)(void);
+#endif /* XP_WIN32 */
+    int (*f_dir_create_all)(char *dir);
+#ifdef XP_WIN32
+    void *(*f_system_winsockerr)(void);
+    void *(*f_system_winerr)(void);
+    int (*f_system_pread)(SYS_FILE fd, void *buf, int sz);
+    int (*f_system_pwrite)(SYS_FILE fd, const void *buf, int sz);
+    void (*f_file_unix2local)(const char *path, char *p2);
+#else
+    void *(*f_system_winsockerr)(void);
+    void *(*f_system_winerr)(void);
+    int (*f_system_pread)(void);
+    int (*f_system_pwrite)(void);
+    void (*f_file_unix2local)(void);
+#endif /* XP_WIN32 */
+    int (*f_system_nocoredumps)(void);
+    int (*f_file_setinherit)(SYS_FILE fd, int value);
+    int (*f_file_notfound)(void);
+    char *(*f_system_errmsg)(void);
+    int (*f_system_errmsg_fn)(char **buff, size_t maxlen);
+    SYS_NETFD (*f_net_socket)(int domain, int type, int protocol);
+    int (*f_net_listen)(SYS_NETFD s, int backlog);
+    SYS_NETFD (*f_net_create_listener)(const char *ipaddr, int port);
+    int (*f_net_connect)(SYS_NETFD s, const void *sockaddr, int namelen);
+    int (*f_net_getpeername)(SYS_NETFD s, struct sockaddr *name, int *namelen);
+    int (*f_net_close)(SYS_NETFD s);
+    int (*f_net_bind)(SYS_NETFD s, const struct sockaddr *name, int namelen);
+    SYS_NETFD (*f_net_accept)(SYS_NETFD s, struct sockaddr *addr, int *addrlen);
+    int (*f_net_read)(SYS_NETFD sd, void *buf, int sz, int timeout);
+    int (*f_net_write)(SYS_NETFD sd, const void *buf, int sz);
+    int (*f_net_writev)(SYS_NETFD sd, const NSAPIIOVec *iov, int iovlen);
+    int (*f_net_isalive)(SYS_NETFD sd);
+    char *(*f_net_ip2host)(const char *ip, int verify);
+    int (*f_net_getsockopt)(SYS_NETFD s, int level, int optname,
+                            void *optval, int *optlen);
+    int (*f_net_setsockopt)(SYS_NETFD s, int level, int optname,
+                            const void *optval, int optlen);
+    int (*f_net_select)(int nfds, fd_set *r, fd_set *w, fd_set *e, 
+                        struct timeval *timeout);
+    int (*f_net_ioctl)(SYS_NETFD s, int tag, void *result);
+    pb_param *(*f_param_create)(const char *name, const char *value);
+    int (*f_param_free)(pb_param *pp);
+    pblock *(*f_pblock_create)(int n);
+    void (*f_pblock_free)(pblock *pb);
+    char *(*f_pblock_findval)(const char *name, const pblock *pb);
+    pb_param *(*f_pblock_nvinsert)(const char *name, const char *value, pblock *pb);
+    pb_param *(*f_pblock_nninsert)(const char *name, int value, pblock *pb);
+    void (*f_pblock_pinsert)(pb_param *pp, pblock *pb);
+    int (*f_pblock_str2pblock)(const char *str, pblock *pb);
+    char *(*f_pblock_pblock2str)(const pblock *pb, char *str);
+    int (*f_pblock_copy)(const pblock *src, pblock *dst);
+    pblock *(*f_pblock_dup)(const pblock *src);
+    char **(*f_pblock_pb2env)(const pblock *pb, char **env);
+    pb_param *(*f_pblock_fr)(const char *name, pblock *pb, int remove);
+    char * (*f_pblock_replace)(const char *name,char * new_value,pblock *pb);
+    pool_handle_t *(*f_pool_create)(void);
+    void (*f_pool_destroy)(pool_handle_t *pool_handle);
+    int (*f_pool_enabled)(void);
+    void *(*f_pool_malloc)(pool_handle_t *pool_handle, size_t size );
+    void (*f_pool_free)(pool_handle_t *pool_handle, void *ptr );
+    void *(*f_pool_calloc)(pool_handle_t *pool_handle, size_t nelem, size_t elsize);
+    void *(*f_pool_realloc)(pool_handle_t *pool_handle, void *ptr, size_t size );
+    char *(*f_pool_strdup)(pool_handle_t *pool_handle, const char *orig_str );
+    int (*f_regexp_valid)(const char *exp);
+    int (*f_regexp_match)(const char *str, const char *exp);
+    int (*f_regexp_cmp)(const char *str, const char *exp);
+    int (*f_regexp_casecmp)(const char *str, const char *exp);
+    SEMAPHORE (*f_sem_init)(char *name, int number);
+    void (*f_sem_terminate)(SEMAPHORE id);
+    int (*f_sem_grab)(SEMAPHORE id);
+    int (*f_sem_tgrab)(SEMAPHORE id);
+    int (*f_sem_release)(SEMAPHORE id);
+    Session *(*f_session_alloc)(SYS_NETFD csd, struct sockaddr_in *sac); /* internal */
+    Session *(*f_session_fill)(Session *sn); /* internal */
+    Session *(*f_session_create)(SYS_NETFD csd, struct sockaddr_in *sac);
+    void (*f_session_free)(Session *sn);
+    char *(*f_session_dns_lookup)(Session *sn, int verify);
+    int (*f_shexp_valid)(const char *exp);
+    int (*f_shexp_match)(const char *str, const char *exp);
+    int (*f_shexp_cmp)(const char *str, const char *exp);
+    int (*f_shexp_casecmp)(const char *str, const char *exp);
+    shmem_s *(*f_shmem_alloc)(char *name, int size, int expose);
+    void (*f_shmem_free)(shmem_s *region);
+    SYS_THREAD (*f_systhread_start)(int prio, int stksz, void (*fn)(void *), void *arg);
+    SYS_THREAD (*f_systhread_current)(void);
+    void (*f_systhread_yield)(void);
+    SYS_THREAD (*f_systhread_attach)(void);
+    void (*f_systhread_detach)(SYS_THREAD thr);
+    void (*f_systhread_terminate)(SYS_THREAD thr);
+    void (*f_systhread_sleep)(int milliseconds);
+    void (*f_systhread_init)(char *name);
+    void (*f_systhread_timerset)(int usec);
+    int (*f_systhread_newkey)(void);
+    void *(*f_systhread_getdata)(int key);
+    void (*f_systhread_setdata)(int key, void *data);
+    void (*f_systhread_set_default_stacksize)(unsigned long size);
+    int (*f_util_getline)(filebuffer *buf, int lineno, int maxlen, char *l);
+    char **(*f_util_env_create)(char **env, int n, int *pos);
+    char *(*f_util_env_str)(const char *name, const char *value);
+    void (*f_util_env_replace)(char **env, const char *name, const char *value);
+    void (*f_util_env_free)(char **env);
+    char **(*f_util_env_copy)(char **src, char **dst);
+    char *(*f_util_env_find)(char **env, const char *name);
+    char *(*f_util_hostname)(void);
+    int (*f_util_chdir2path)(char *path);
+    int (*f_util_is_mozilla)(char *ua, char *major, char *minor);
+    int (*f_util_is_url)(const char *url);
+    int (*f_util_later_than)(const struct tm *lms, const char *ims);
+    int (*f_util_time_equal)(const struct tm *lms, const char *ims);
+    int (*f_util_str_time_equal)(const char *t1, const char *t2);
+    int (*f_util_uri_is_evil)(const char *t);
+    void (*f_util_uri_parse)(char *uri);
+    void (*f_util_uri_unescape)(char *s);
+    char *(*f_util_uri_escape)(char *d, const char *s);
+    char *(*f_util_url_escape)(char *d, const char *s);
+    char *(*f_util_sh_escape)(char *s);
+    int (*f_util_mime_separator)(char *sep);
+    int (*f_util_itoa)(int i, char *a);
+    int (*f_util_vsprintf)(char *s, register const char *fmt, va_list args);
+    int (*f_util_sprintf)(char *s, const char *fmt, ...);
+    int (*f_util_vsnprintf)(char *s, int n, register const char *fmt, 
+                            va_list args);
+    int (*f_util_snprintf)(char *s, int n, const char *fmt, ...);
+    int (*f_util_strftime)(char *s, const char *format, const struct tm *t);
+    char *(*f_util_strtok)(char *s1, const char *s2, char **lasts);
+    struct tm *(*f_util_localtime)(const time_t *clock, struct tm *res);
+    char *(*f_util_ctime)(const time_t *clock, char *buf, int buflen);
+    char *(*f_util_strerror)(int errnum, char *msg, int buflen);
+    struct tm *(*f_util_gmtime)(const time_t *clock, struct tm *res);
+    char *(*f_util_asctime)(const struct tm *tm,char *buf, int buflen);
+#ifdef NEED_STRCASECMP
+    int (*f_util_strcasecmp)(const char *one, const char *two);
+#else
+    int (*f_util_strcasecmp)(void);
+#endif /* NEED_STRCASECMP */
+#ifdef NEED_STRNCASECMP
+    int (*f_util_strncasecmp)(const char *one, const char *two, int n);
+#else
+    int (*f_util_strncasecmp)(void);
+#endif /* NEED_STRNCASECMP */
+#ifdef XP_UNIX
+    int (*f_util_can_exec)(struct stat *finfo, uid_t uid, gid_t gid);
+    struct passwd *(*f_util_getpwnam)(const char *name, struct passwd
+                                      *result, char *buffer,  int buflen);
+    pid_t (*f_util_waitpid)(pid_t pid, int *statptr, int options);
+#else
+    int (*f_util_can_exec)(void);
+    void *(*f_util_getpwnam)(void);
+    int (*f_util_waitpid)(void);
+#endif /* XP_UNIX */
+#ifdef XP_WIN32
+    VOID (*f_util_delete_directory)(char *FileName, BOOL delete_directory);
+#else
+    void (*f_util_delete_directory)(void);
+#endif /* XP_WIN32 */
+    void *(*f_conf_init)(void);
+    void *(*f_conf_run_init_functions)(void);
+    void (*f_conf_terminate)(void);
+    conf_global_vars_s *(*f_conf_getglobals)(void);
+    void (*f_func_init)(struct FuncStruct *func_standard);
+    FuncPtr (*f_func_find)(char *name);
+    int (*f_func_exec)(pblock *pb, Session *sn, Request *rq);
+    struct FuncStruct *(*f_func_insert)(char *name, FuncPtr fn);
+    int (*f_object_execute)(directive *inst, Session *sn, Request *rq);
+    void *(*f_http_find_request)(void);
+    int (*f_http_parse_request)(char *t, Request *rq, Session *sn);
+    int (*f_http_scan_headers)(void);
+    int (*f_http_start_response)(Session *sn, Request *rq);
+    char **(*f_http_hdrs2env)(pblock *pb);
+    void (*f_http_status)(Session *sn, Request *rq, int n, const char *r);
+    int (*f_http_set_finfo)(Session *sn, Request *rq, struct stat *finfo);
+    char *(*f_http_dump822)(pblock *pb, char *t, int *pos, int tsz);
+    void (*f_http_finish_request)(Session *sn, Request *rq);
+    void (*f_http_handle_session)(void);
+    char *(*f_http_uri2url)(const char *prefix, const char *suffix);
+    char *(*f_http_uri2url_dynamic)(const char *prefix, const char *suffix,
+                                    Session *sn, Request *rq);
+    void (*f_http_set_keepalive_timeout)(int secs);
+    int (*f_log_error_v)(int degree, const char *func, Session *sn,
+                         Request *rq, const char *fmt, va_list args);
+    int (*f_log_error)(int degree, const char *func, Session *sn, Request *rq,
+                       const char *fmt, ...);
+    int (*f_log_ereport_v)(int degree, const char *fmt, va_list args);
+    int (*f_log_ereport)(int degree, const char *fmt, ...);
+    httpd_object *(*f_object_create)(int nd, pblock *name);
+    void (*f_object_free)(httpd_object *obj);
+    void (*f_object_add_directive)(int dc, pblock *p, pblock *c,
+                                   httpd_object *obj);
+    httpd_objset *(*f_objset_scan_buffer)(filebuffer *buf, char *errstr,
+                                          httpd_objset *os);
+    httpd_objset *(*f_objset_create)(void);
+    void (*f_objset_free)(httpd_objset *os);
+    void (*f_objset_free_setonly)(httpd_objset *os);
+    httpd_object *(*f_objset_new_object)(pblock *name, httpd_objset *os);
+    void (*f_objset_add_object)(httpd_object *obj, httpd_objset *os);
+    void (*f_objset_add_init)(pblock *initfn, httpd_objset *os);
+    httpd_object *(*f_objset_findbyname)(const char *name, httpd_objset *ign,
+                                         httpd_objset *os);
+    httpd_object *(*f_objset_findbyppath)(char *ppath, httpd_objset *ign,
+                                          httpd_objset *os);
+    Request *(*f_request_create)(void);
+    void (*f_request_free)(Request *req);
+    Request *(*f_request_restart_internal)(const char *uri, Request *rq);
+    int (*f_request_header)(char *name, char **value, Session *sn,
+                            Request *rq);
+    struct stat *(*f_request_stat_path)(const char *path, Request *rq);
+    const char *(*f_conf_getServerString)(void);
+    FuncPtr (*f_func_replace)(char *funcname, FuncPtr fn);
+    int (*f_net_socketpair)(SYS_NETFD *pair);
+#ifdef XP_UNIX
+    SYS_NETFD (*f_net_dup2)(SYS_NETFD prfd, int osfd);
+    int (*f_net_is_STDOUT)(SYS_NETFD prfd);
+    int (*f_net_is_STDIN)(SYS_NETFD prfd);
+#else
+    void *(*f_net_dup2)(void);
+    int (*f_net_is_STDOUT)(void);
+    int (*f_net_is_STDIN)(void);
+#endif /* XP_UNIX */
+    int (*f_func_set_native_thread_flag)(char *name, int flags);
+#ifdef NET_SSL
+    void *(*f_random_create)(void);
+    void (*f_random_update)(void *rctx, unsigned char *inbuf, int length);
+    void (*f_random_generate)(void *rctx, unsigned char *outbuf, int length);
+    void (*f_random_destroy)(void *rctx);
+    void *(*f_md5hash_create)(void);
+    void *(*f_md5hash_copy)(void *hctx);
+    void (*f_md5hash_begin)(void *hctx);
+    void (*f_md5hash_update)(void *hctx, unsigned char *inbuf, int length);
+    void (*f_md5hash_end)(void *hctx, unsigned char *outbuf);
+    void (*f_md5hash_destroy)(void *hctx);
+    void (*f_md5hash_data)(unsigned char *outbuf, unsigned char *src, int length);
+#else
+    void *(*f_random_create)(void);
+    void (*f_random_update)(void);
+    void (*f_random_generate)(void);
+    void (*f_random_destroy)(void);
+    void *(*f_md5hash_create)(void);
+    void *(*f_md5hash_copy)(void);
+    void (*f_md5hash_begin)(void);
+    void (*f_md5hash_update)(void);
+    void (*f_md5hash_end)(void);
+    void (*f_md5hash_destroy)(void);
+    void (*f_md5hash_data)(void);
+#endif
+    int (*f_ACL_SetupEval)(struct ACLListHandle *acllist, Session *sn, Request *rq, char **rights, char **map_generic, const char *user);
+    int (*f_netbuf_getbytes)(netbuf *buf, char *buffer, int size);
+    char *(*f_servact_translate_uri)(char *uri, Session *sn);
+#ifdef NET_SSL
+    int (*f_rsa_set_priv_fn)(void *);
+#else
+    int (*f_rsa_set_priv_fn)(void);
+#endif
+#ifdef XP_UNIX
+    int (*f_net_native_handle)(SYS_NETFD s);
+#else
+    HANDLE (*f_net_native_handle)(SYS_NETFD s);
+#endif /* XP_UNIX */
+    int (*f_internal_request)(Request *rq);
+    char *(*f_util_cookie_find)(char *cookie, const char *name);
+    char *(*f_util_cookie_next)(char *cookie, char **name, char **value);
+    char *(*f_util_cookie_next_av_pair)(char *cookie, char **name, char **value);
+    int (*f_objset_get_number_objects)(const httpd_objset *objset);
+    const httpd_object *(*f_objset_get_object)(const httpd_objset *objset, int pos);
+    const pblock * const *(*f_objset_get_initfns)(const httpd_objset *objset);
+    const pblock *(*f_object_get_name)(const httpd_object *object);
+    int (*f_object_get_num_directives)(const httpd_object *object);
+    const dtable *(*f_object_get_directive_table)(const httpd_object *object, int n);
+    int (*f_directive_table_get_num_directives)(const dtable *dt);
+    const directive *(*f_directive_table_get_directive)(const dtable *dt, int pos);
+    const pblock *(*f_directive_get_pblock)(const directive *);
+    const FuncStruct *(*f_directive_get_funcstruct)(const directive *);
+    const pblock *(*f_directive_get_client_pblock)(const directive *);
+#if NSAPI_VERSION >= 301
+    int (*f_vs_register_cb)(VSInitFunc *vs_init_func, VSDestroyFunc *vs_destroy_func);
+    const char* (*f_vs_get_id)(const VirtualServer *vs);
+    const char* (*f_vs_lookup_config_var)(const VirtualServer *vs, const char *name);
+    int (*f_vs_alloc_slot)(void);
+    void* (*f_vs_set_data)(const VirtualServer *vs, int *slot, void *data);
+    void* (*f_vs_get_data)(const VirtualServer *vs, int slot);
+    const VirtualServer* (*f_request_get_vs)(Request *rq);
+    httpd_objset* (*f_vs_get_httpd_objset)(VirtualServer *vs);
+    httpd_object* (*f_vs_get_default_httpd_object)(VirtualServer *vs);
+    char* (*f_vs_get_doc_root)(const VirtualServer *vs);
+    char* (*f_vs_translate_uri)(const VirtualServer *vs, const char *uri);
+    char* (*f_vs_get_mime_type)(const VirtualServer *vs, const char *uri);
+    int (*f_vs_is_default_vs)(const VirtualServer *vs);
+    void *(*f_vs_get_acllist)(const VirtualServer *vs);
+    void (*f_vs_set_acllist)(VirtualServer *vs, void *acllist);
+    int (*f_file_is_path_abs)(const char *path);
+    char* (*f_file_canonicalize_path)(const char* path);
+    int (*f_file_are_files_distinct)(SYS_FILE fd1, SYS_FILE fd2);
+    int (*f_vs_directive_register_cb)(FuncPtr func, VSDirectiveInitFunc *vs_init_func, VSDirectiveDestroyFunc *vs_destroy_func);
+    char* (*f_vs_substitute_vars)(const VirtualServer *vs, const char *string);
+    const char *(*f_conf_getfilename)(void);
+    const char *(*f_conf_getstring)(const char *name, const char *def);
+    int (*f_conf_getboolean)(const char *name, int def);
+    int (*f_conf_getinteger)(const char *name, int def);
+    int (*f_conf_getboundedinteger)(const char *name, int min, int max, int def);
+    void (*f_prepare_nsapi_thread)(Request *rq, Session *sn);
+#endif /* NSAPI_VERSION >= 301 */
+};
+
+#if NSAPI_VERSION >= 302
+typedef struct nsapi302_dispatch_s nsapi302_dispatch_t;
+struct nsapi302_dispatch_s {
+    int (*f_net_flush)(SYS_NETFD sd);
+    int (*f_net_sendfile)(SYS_NETFD sd, sendfiledata *sfd);
+    const Filter *(*f_filter_create)(const char *name, int order, const FilterMethods *methods);
+    const char *(*f_filter_name)(const Filter *filter);
+    const Filter *(*f_filter_find)(const char *name);
+    FilterLayer *(*f_filter_layer)(SYS_NETFD sd, const Filter *filter);
+    int (*f_filter_insert)(SYS_NETFD sd, pblock *pb, Session *sn, Request *rq, void *data, const Filter *filter);
+    int (*f_filter_remove)(SYS_NETFD sd, const Filter *filter);
+    SYS_NETFD (*f_filter_create_stack)(Session *sn);
+};
+#endif /* NSAPI_VERSION >= 302 */
+
+#if NSAPI_VERSION >= 303
+typedef struct nsapi303_dispatch_s nsapi303_dispatch_t;
+struct hostent;
+struct nsapi303_dispatch_s {
+    int (*f_dns_set_hostent)(struct hostent *he, Session *sn, Request *rq);
+};
+#endif /* NSAPI_VERSION >= 303 */
+
+/* --- End dispatch vector table definition --- */
+
+/* --- Begin API macro definitions --- */
+
+#ifndef INTNSAPI
+
+#if NSAPI_VERSION >= 301
+
+/*
+ * In Sun ONE Web Server 6.1 and higher, http_parse_request("", NULL, NULL)
+ * returns the NSAPI version.  In previous releases, it returns -1.
+ */
+#define __NSAPI_RUNTIME_VERSION \
+        ((*__nsapi30_table->f_http_parse_request)("", NULL, NULL))
+
+/*
+ * NSAPI_RUNTIME_VERSION returns the NSAPI version the server implements.  The
+ * returned NSAPI version number is reliable only in iPlanet Web Server 6.0,
+ * Netscape Enterprise Server 6.0, and Sun ONE Web Server 6.0 and higher.
+ */
+#define NSAPI_RUNTIME_VERSION \
+        (__NSAPI_RUNTIME_VERSION > 0 ? __NSAPI_RUNTIME_VERSION : 301)
+
+#endif /* NSAPI_VERSION >= 301 */
+
+#define system_version (*__nsapi30_table->f_system_version)
+
+/*
+ * Depending on the system, memory allocated via these macros may come from 
+ * an arena.  If these functions are called from within an Init function, they
+ * will be allocated from permanent storage.  Otherwise, they will be freed 
+ * when the current request is finished.
+ */
+
+
+
+#endif /* !INTNSAPI */
+
+#ifdef XP_UNIX
+#define dir_open opendir
+#define dir_read readdir
+#define dir_close closedir
+#define dir_create(path) mkdir(path, 0755)
+#define dir_remove rmdir
+#define system_chdir chdir
+#define file_unix2local(path,p2) strcpy(p2,path)
+#endif /* XP_UNIX */
+
+#ifdef XP_WIN32
+#define dir_create _mkdir
+#define dir_remove _rmdir
+#define system_chdir SetCurrentDirectory
+#endif /* XP_WIN32 */
+
+/*
+ * Thread-safe variants of localtime and gmtime
+ */
+#define system_localtime(curtime, ret) util_localtime(curtime, ret)
+#define system_gmtime(curtime, ret) util_gmtime(curtime, ret)
+
+/* 
+ * pblock_find finds the entry with the given name in pblock pb.
+ *
+ * If it is successful, it returns the param block.  If not, it returns NULL.
+ */
+#define pblock_find(name, pb) (pblock_fr(name,pb,0))
+
+/*
+ * pblock_remove behaves exactly like pblock_find, but removes the given
+ * entry from pb.
+ */
+#define pblock_remove(name, pb) (pblock_fr(name,pb,1))
+
+/*
+ * session_dns returns the DNS hostname of the client of this session,
+ * and inserts it into the client pblock.  Returns NULL if unavailable.
+ */
+#define session_dns(sn) session_dns_lookup(sn, 0)
+
+/*
+ * session_maxdns looks up a hostname from an IP address, and then verifies 
+ * that the host is really who they claim to be. 
+ */
+#define session_maxdns(sn) session_dns_lookup(sn, 1)
+
+#define protocol_start_response http_start_response
+#define protocol_status http_status
+#define protocol_set_finfo http_set_finfo
+#define protocol_finish_request http_finish_request
+#define protocol_uri2url http_uri2url
+#define protocol_uri2url_dynamic http_uri2url_dynamic
+
+#define request_translate_uri servact_translate_uri
+
+/* --- OBSOLETE ----------------------------------------------------------
+ * The following macros/functions are obsolete and are only maintained for
+ * compatibility.  Do not use them.
+ * -----------------------------------------------------------------------
+ */
+
+#define SYS_STDERR STDERR_FILENO
+
+#ifdef XP_WIN32
+
+typedef HANDLE pid_t;
+
+#define ERROR_PIPE \
+        (ERROR_BROKEN_PIPE | ERROR_BAD_PIPE | \
+         ERROR_PIPE_BUSY | ERROR_PIPE_LISTENING | ERROR_PIPE_NOT_CONNECTED)
+#define CONVERT_TO_PRINTABLE_FORMAT(Filename)   \
+{                                               \
+        register char *s;                       \
+        if (Filename)                           \
+        for (s = Filename; *s; s++)             \
+                if ( *s == '\\')                \
+                        *s = '/';               \
+}
+#define CONVERT_TO_NATIVE_FS(Filename)          \
+{                                               \
+        register char *s;                       \
+        if (Filename)                           \
+                for (s = Filename; *s; s++)     \
+                        if ( *s == '/')         \
+                                *s = '\\';      \
+}                                                                        
+
+#ifdef INTNSAPI
+NSAPI_PUBLIC extern nsapi_dispatch_t *__nsapi30_table;
+#if NSAPI_VERSION >= 302
+NSAPI_PUBLIC extern nsapi302_dispatch_t *__nsapi302_table;
+#endif /* NSAPI_VERSION >= 302 */
+#if NSAPI_VERSION >= 303
+NSAPI_PUBLIC extern nsapi303_dispatch_t *__nsapi303_table;
+#endif /* NSAPI_VERSION >= 303 */
+#else
+__declspec(dllimport) nsapi_dispatch_t *__nsapi30_table;
+#if NSAPI_VERSION >= 302
+__declspec(dllimport) nsapi302_dispatch_t *__nsapi302_table;
+#endif /* NSAPI_VERSION >= 302 */
+#if NSAPI_VERSION >= 303
+__declspec(dllimport) nsapi303_dispatch_t *__nsapi303_table;
+#endif /* NSAPI_VERSION >= 303 */
+#endif /* INTNSAPI */
+
+#else /* !XP_WIN32 */
+
+NSAPI_PUBLIC extern nsapi_dispatch_t *__nsapi30_table;
+#if NSAPI_VERSION >= 302
+NSAPI_PUBLIC extern nsapi302_dispatch_t *__nsapi302_table;
+#endif /* NSAPI_VERSION >= 302 */
+#if NSAPI_VERSION >= 303
+NSAPI_PUBLIC extern nsapi303_dispatch_t *__nsapi303_table;
+#endif /* NSAPI_VERSION >= 303 */
+
+#endif /* XP_WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !PUBLIC_NSAPI_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/objs.mk	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,59 @@
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 2011 Olaf Wintermann. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+#   1. Redistributions of source code must retain the above copyright notice,
+#      this list of conditions and the following disclaimer.
+#
+#   2. Redistributions in binary form must reproduce the above copyright
+#      notice, this list of conditions and the following disclaimer in the
+#      documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+SRC_DIR = server/
+
+OBJPRE = $(OBJ_DIR)$(SRC_DIR)
+
+MOBJ = main.o
+MOBJ += webserver.o
+MOBJ += util.o
+MOBJ += uri.o
+MOBJ += systhr.o
+MOBJ += system.o
+MOBJ += pool.o
+MOBJ += plist.o
+MOBJ += pblock.o
+MOBJ += sstring.o
+MOBJ += list.o
+MOBJ += map.o
+MOBJ += func.o
+MOBJ += ws-fn.o
+MOBJ += conf.o
+MOBJ += httplistener.o
+MOBJ += session.o
+MOBJ += request.o
+MOBJ += io.o
+MOBJ += thrpool.o
+MOBJ += sessionhandler.o
+MOBJ += httpparser.o
+MOBJ += httprequest.o
+
+
+MAINOBJS = $(MOBJ:%=$(OBJPRE)%)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/pblock.cpp	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,1193 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * pblock.c: Handles Parameter Blocks
+ * 
+ * See pblock.h for public documentation.
+ * 
+ * Rob McCool
+ * 
+ * This code uses property lists to implement pblocks.
+ */
+
+
+#include <limits.h>
+#include "pblock.h"
+#include "plist_pvt.h"
+#include "plist.h"
+#include "LinkedList.hh"
+#include "util.h"   /* util_itoa */
+#include "pool.h"
+#include "systhr.h"
+
+#define MALLOC_POOL_HANDLE (thread_malloc_key != -1 ? (pool_handle_t *)systhread_getdata(thread_malloc_key) : getThreadMallocPool())
+
+static int thread_malloc_key = -1;
+static int _pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase);
+
+static pool_handle_t *getThreadMallocPool()
+{
+    pool_handle_t *thread_malloc_pool = 0;
+
+    thread_malloc_key = getThreadMallocKey();
+    if (thread_malloc_key != -1) {
+        thread_malloc_pool = (pool_handle_t *)systhread_getdata(thread_malloc_key);
+    }
+
+    return thread_malloc_pool;
+}
+
+/* ------------------------------- HashList ------------------------------- */
+
+template <class Name, class Value>
+class HashList {
+public:
+    HashList(int mask)
+    : _mask(mask),
+      _list(new CList<Value>[mask + 1])
+    { }
+
+    void Insert(Name name, Value *value)
+    {
+        _list[name & _mask].Append(value);
+    }
+
+    const CList<Value>& Find(Name name)
+    {
+        return _list[name & _mask];
+    }
+
+private:
+    CList<Value> *_list;
+    unsigned int _mask;
+};
+
+/* ---------------------- pb_key static initializers ---------------------- */
+
+/*
+ * pb_key
+ *
+ * Contains a precomputed hash value for a specific pblock variable name.
+ */
+typedef struct pb_key pb_key;
+struct pb_key {
+    const char *name;
+    int namelen; 
+    unsigned int hashval;
+    int sizendx;
+    int hashndx;
+};
+
+static HashList<unsigned int, pb_key> _hashKeys(0x7f);
+CList<pb_key> _listKeys;
+
+static const pb_key *const _create_key(const char *name, int sizendx = 0)
+{
+    /* Create a the new pb_key */
+    pb_key *key = (pb_key*)malloc(sizeof(pb_key));
+    key->name = STRDUP(name);
+    key->namelen = strlen(name);
+    key->hashval = PListHash(name);
+    key->sizendx = sizendx;
+    key->hashndx = key->hashval % PLSIZENDX(sizendx);
+
+    /* Group pb_keys by hashval for later retrieval */
+    _hashKeys.Insert(key->hashval, key);
+
+    /* Keep a list of all the registered keys */
+    _listKeys.Append(key);
+
+    return key;
+}
+
+const pb_key *const pb_key_accept = _create_key("accept");
+const pb_key *const pb_key_accept_charset = _create_key("accept-charset");
+const pb_key *const pb_key_accept_encoding = _create_key("accept-encoding");
+const pb_key *const pb_key_accept_language = _create_key("accept-language");
+const pb_key *const pb_key_accept_ranges = _create_key("accept-ranges");
+const pb_key *const pb_key_actual_route = _create_key("actual-route");
+const pb_key *const pb_key_age = _create_key("age");
+const pb_key *const pb_key_always_allow_chunked = _create_key("always-allow-chunked");
+const pb_key *const pb_key_always_use_keep_alive = _create_key("always-use-keep-alive");
+const pb_key *const pb_key_auth_cert = _create_key("auth-cert");
+const pb_key *const pb_key_auth_expiring = _create_key("auth-expiring");
+const pb_key *const pb_key_auth_group = _create_key("auth-group");
+const pb_key *const pb_key_auth_type = _create_key("auth-type");
+const pb_key *const pb_key_auth_user = _create_key("auth-user");
+const pb_key *const pb_key_authorization = _create_key("authorization");
+const pb_key *const pb_key_browser = _create_key("browser");
+const pb_key *const pb_key_c2p_cl = _create_key("c2p-cl");
+const pb_key *const pb_key_c2p_hl = _create_key("c2p-hl");
+const pb_key *const pb_key_cache_info = _create_key("cache-info");
+const pb_key *const pb_key_charset = _create_key("charset");
+const pb_key *const pb_key_check_http_server = _create_key("check-http-server");
+const pb_key *const pb_key_ChunkedRequestBufferSize = _create_key("ChunkedRequestBufferSize");
+const pb_key *const pb_key_ChunkedRequestTimeout = _create_key("ChunkedRequestTimeout");
+const pb_key *const pb_key_cipher = _create_key("cipher");
+const pb_key *const pb_key_clf_request = _create_key("clf-request");
+const pb_key *const pb_key_cli_status = _create_key("cli-status");
+const pb_key *const pb_key_client_cert_nickname = _create_key("client-cert-nickname");
+const pb_key *const pb_key_client_ip = _create_key("client-ip");
+const pb_key *const pb_key_close = _create_key("close");
+const pb_key *const pb_key_connect_timeout = _create_key("connect-timeout");
+const pb_key *const pb_key_connection = _create_key("connection");
+const pb_key *const pb_key_cont = _create_key("cont");
+const pb_key *const pb_key_content_encoding = _create_key("content-encoding");
+const pb_key *const pb_key_content_language = _create_key("content-language");
+const pb_key *const pb_key_content_length = _create_key("content-length");
+const pb_key *const pb_key_content_location = _create_key("content-location");
+const pb_key *const pb_key_content_md5 = _create_key("content-md5");
+const pb_key *const pb_key_content_range = _create_key("content-range");
+const pb_key *const pb_key_content_type = _create_key("content-type");
+const pb_key *const pb_key_cookie = _create_key("cookie");
+const pb_key *const pb_key_date = _create_key("date");
+const pb_key *const pb_key_DATE_GMT = _create_key("DATE_GMT");
+const pb_key *const pb_key_DATE_LOCAL = _create_key("DATE_LOCAL");
+const pb_key *const pb_key_dir = _create_key("dir");
+const pb_key *const pb_key_Directive = _create_key("Directive");
+const pb_key *const pb_key_dns = _create_key("dns");
+const pb_key *const pb_key_DOCUMENT_NAME = _create_key("DOCUMENT_NAME");
+const pb_key *const pb_key_DOCUMENT_URI = _create_key("DOCUMENT_URI");
+const pb_key *const pb_key_domain = _create_key("domain");
+const pb_key *const pb_key_enc = _create_key("enc");
+const pb_key *const pb_key_engine = _create_key("engine");
+const pb_key *const pb_key_error_action = _create_key("error-action");
+const pb_key *const pb_key_error_desc = _create_key("error-desc");
+const pb_key *const pb_key_error_fn = _create_key("error-fn");
+const pb_key *const pb_key_escape = _create_key("escape");
+const pb_key *const pb_key_escaped = _create_key("escaped");
+const pb_key *const pb_key_etag = _create_key("etag");
+const pb_key *const pb_key_expect = _create_key("expect");
+const pb_key *const pb_key_expires = _create_key("expires");
+const pb_key *const pb_key_expr = _create_key("expr");
+const pb_key *const pb_key_filter = _create_key("filter");
+const pb_key *const pb_key_find_pathinfo_forward = _create_key("find-pathinfo-forward");
+const pb_key *const pb_key_flushTimer = _create_key("flushTimer");
+const pb_key *const pb_key_fn = _create_key("fn");
+const pb_key *const pb_key_from = _create_key("from");
+const pb_key *const pb_key_full_headers = _create_key("full-headers");
+const pb_key *const pb_key_hdr = _create_key("hdr");
+const pb_key *const pb_key_host = _create_key("host");
+const pb_key *const pb_key_hostname = _create_key("hostname");
+const pb_key *const pb_key_if_match = _create_key("if-match");
+const pb_key *const pb_key_if_modified_since = _create_key("if-modified-since");
+const pb_key *const pb_key_if_none_match = _create_key("if-none-match");
+const pb_key *const pb_key_if_range = _create_key("if-range");
+const pb_key *const pb_key_if_unmodified_since = _create_key("if-unmodified-since");
+const pb_key *const pb_key_ip = _create_key("ip");
+const pb_key *const pb_key_iponly = _create_key("iponly");
+const pb_key *const pb_key_issuer_dn = _create_key("issuer_dn");
+const pb_key *const pb_key_jroute = _create_key("jroute");
+const pb_key *const pb_key_keep_alive = _create_key("keep-alive");
+const pb_key *const pb_key_keep_alive_timeout = _create_key("keep-alive-timeout");
+const pb_key *const pb_key_keysize = _create_key("keysize");
+const pb_key *const pb_key_lang = _create_key("lang");
+const pb_key *const pb_key_LAST_MODIFIED = _create_key("LAST_MODIFIED");
+const pb_key *const pb_key_last_modified = _create_key("last-modified");
+const pb_key *const pb_key_level = _create_key("level");
+const pb_key *const pb_key_location = _create_key("location");
+const pb_key *const pb_key_lock_owner = _create_key("lock-owner");
+const pb_key *const pb_key_magnus_charset = _create_key("magnus-charset");
+const pb_key *const pb_key_magnus_internal = _create_key("magnus-internal");
+const pb_key *const pb_key_magnus_internal_dav_src = _create_key("magnus-internal/dav-src");
+const pb_key *const pb_key_magnus_internal_default_acls_only = _create_key("magnus-internal/default-acls-only");
+const pb_key *const pb_key_magnus_internal_error_j2ee = _create_key("magnus-internal/error-j2ee");
+const pb_key *const pb_key_magnus_internal_j2ee_nsapi = _create_key("magnus-internal/j2ee-nsapi");
+const pb_key *const pb_key_magnus_internal_preserve_srvhdrs = _create_key("magnus-internal/preserve-srvhdrs-after-req-restart");
+const pb_key *const pb_key_magnus_internal_set_request_status = _create_key("magnus-internal/set-request-status");
+const pb_key *const pb_key_magnus_internal_set_response_status = _create_key("magnus-internal/set-response-status");
+const pb_key *const pb_key_magnus_internal_webapp_errordesc = _create_key("magnus-internal/webapp-errordesc");
+const pb_key *const pb_key_matched_browser = _create_key("matched-browser");
+const pb_key *const pb_key_max_age = _create_key("max-age");
+const pb_key *const pb_key_max_forwards = _create_key("max-forwards");
+const pb_key *const pb_key_message = _create_key("message");
+const pb_key *const pb_key_method = _create_key("method");
+const pb_key *const pb_key_name = _create_key("name");
+const pb_key *const pb_key_nocache = _create_key("nocache");
+const pb_key *const pb_key_nostat = _create_key("nostat");
+const pb_key *const pb_key_ntrans_base = _create_key("ntrans-base");
+const pb_key *const pb_key_offline_origin_addr = _create_key("offline-origin-addr");
+const pb_key *const pb_key_offline_proxy_addr = _create_key("offline-proxy-addr");
+const pb_key *const pb_key_origin_addr = _create_key("origin-addr");
+const pb_key *const pb_key_p2c_cl = _create_key("p2c-cl");
+const pb_key *const pb_key_p2c_hl = _create_key("p2c-hl");
+const pb_key *const pb_key_p2r_cl = _create_key("p2r-cl");
+const pb_key *const pb_key_p2r_hl = _create_key("p2r-hl");
+const pb_key *const pb_key_parse_timeout = _create_key("parse-timeout");
+const pb_key *const pb_key_password = _create_key("password");
+const pb_key *const pb_key_path = _create_key("path");
+const pb_key *const pb_key_PATH_INFO = _create_key("PATH_INFO");
+const pb_key *const pb_key_path_info = _create_key("path-info");
+const pb_key *const pb_key_pblock = _create_key("pblock");
+const pb_key *const pb_key_poll_interval = _create_key("poll-interval");
+const pb_key *const pb_key_port = _create_key("port");
+const pb_key *const pb_key_ppath = _create_key("ppath");
+const pb_key *const pb_key_pragma = _create_key("pragma");
+const pb_key *const pb_key_process_request_body = _create_key("process-request-body");
+const pb_key *const pb_key_process_response_body = _create_key("process-response-body");
+const pb_key *const pb_key_protocol = _create_key("protocol");
+const pb_key *const pb_key_proxy_addr = _create_key("proxy-addr");
+const pb_key *const pb_key_proxy_agent = _create_key("proxy-agent");
+const pb_key *const pb_key_proxy_auth_cert = _create_key("proxy-auth-cert");
+const pb_key *const pb_key_proxy_authorization = _create_key("proxy-authorization");
+const pb_key *const pb_key_proxy_cipher = _create_key("proxy-cipher");
+const pb_key *const pb_key_proxy_issuer_dn = _create_key("proxy-issuer-dn");
+const pb_key *const pb_key_proxy_jroute = _create_key("proxy-jroute");
+const pb_key *const pb_key_proxy_keysize = _create_key("proxy-keysize");
+const pb_key *const pb_key_proxy_ping = _create_key("proxy-ping");
+const pb_key *const pb_key_proxy_request = _create_key("proxy-request");
+const pb_key *const pb_key_proxy_secret_keysize = _create_key("proxy-secret-keysize");
+const pb_key *const pb_key_proxy_ssl_id = _create_key("proxy-ssl-id");
+const pb_key *const pb_key_proxy_user_dn = _create_key("proxy-user-dn");
+const pb_key *const pb_key_query = _create_key("query");
+const pb_key *const pb_key_QUERY_STRING = _create_key("QUERY_STRING");
+const pb_key *const pb_key_QUERY_STRING_UNESCAPED = _create_key("QUERY_STRING_UNESCAPED");
+const pb_key *const pb_key_r2p_cl = _create_key("r2p-cl");
+const pb_key *const pb_key_r2p_hl = _create_key("r2p-hl");
+const pb_key *const pb_key_range = _create_key("range");
+const pb_key *const pb_key_referer = _create_key("referer");
+const pb_key *const pb_key_reformat_request_headers = _create_key("reformat-request-headers");
+const pb_key *const pb_key_remote_status = _create_key("remote-status");
+const pb_key *const pb_key_request_jroute = _create_key("request-jroute");
+const pb_key *const pb_key_required_rights = _create_key("required-rights");
+const pb_key *const pb_key_retries = _create_key("retries");
+const pb_key *const pb_key_rewrite_content_location = _create_key("rewrite-content-location");
+const pb_key *const pb_key_rewrite_host = _create_key("rewrite-host");
+const pb_key *const pb_key_rewrite_location = _create_key("rewrite-location");
+const pb_key *const pb_key_rewrite_set_cookie = _create_key("rewrite-set-cookie");
+const pb_key *const pb_key_root = _create_key("root");
+const pb_key *const pb_key_route = _create_key("route");
+const pb_key *const pb_key_route_cookie = _create_key("route-cookie");
+const pb_key *const pb_key_route_hdr = _create_key("route-hdr");
+const pb_key *const pb_key_route_offline = _create_key("route-offline");
+const pb_key *const pb_key_script_name = _create_key("script-name");
+const pb_key *const pb_key_secret_keysize = _create_key("secret-keysize");
+const pb_key *const pb_key_secure = _create_key("secure");
+const pb_key *const pb_key_server = _create_key("server");
+const pb_key *const pb_key_set_cookie = _create_key("set-cookie");
+const pb_key *const pb_key_socks_addr = _create_key("socks_addr");
+const pb_key *const pb_key_ssl_id = _create_key("ssl-id");
+const pb_key *const pb_key_ssl_unclean_shutdown = _create_key("ssl-unclean-shutdown");
+const pb_key *const pb_key_status = _create_key("status");
+const pb_key *const pb_key_sticky_cookie = _create_key("sticky-cookie");
+const pb_key *const pb_key_sticky_param = _create_key("sticky-param");
+const pb_key *const pb_key_suppress_request_headers = _create_key("suppress-request-headers");
+const pb_key *const pb_key_svr_status = _create_key("svr-status");
+const pb_key *const pb_key_timeout = _create_key("timeout");
+const pb_key *const pb_key_to = _create_key("to");
+const pb_key *const pb_key_transfer_encoding = _create_key("transfer-encoding");
+const pb_key *const pb_key_transmit_timeout = _create_key("transmit-timeout");
+const pb_key *const pb_key_tunnel_non_http_response = _create_key("tunnel-non-http-response");
+const pb_key *const pb_key_type = _create_key("type");
+const pb_key *const pb_key_upstream_jroute = _create_key("upstream-jroute");
+const pb_key *const pb_key_uri = _create_key("uri");
+const pb_key *const pb_key_url = _create_key("url");
+const pb_key *const pb_key_url_prefix = _create_key("url-prefix");
+const pb_key *const pb_key_UseOutputStreamSize = _create_key("UseOutputStreamSize");
+const pb_key *const pb_key_user = _create_key("user");
+const pb_key *const pb_key_user_agent = _create_key("user-agent");
+const pb_key *const pb_key_user_dn = _create_key("user_dn");
+const pb_key *const pb_key_validate_server_cert = _create_key("validate-server-cert");
+const pb_key *const pb_key_value = _create_key("value");
+const pb_key *const pb_key_vary = _create_key("vary");
+const pb_key *const pb_key_via = _create_key("via");
+const pb_key *const pb_key_warning = _create_key("warning");
+
+
+/* ------------------------------ _find_key ------------------------------- */
+
+static inline const pb_key *_find_key(const char *name, unsigned int hashval)
+{
+    /* Check to see if name corresponds to a pb_key */
+    CListConstIterator<pb_key> iter(&_hashKeys.Find(hashval));
+    const pb_key *key;
+    while (key = ++iter) {
+        if (key->hashval == hashval && !strcmp(key->name, name))
+            return key;
+    }
+    return NULL;
+}
+
+
+/* --------------------------- _get_hash_index ---------------------------- */
+
+static inline int _get_hash_index(const PListStruct_t *pl, const pb_key *key)
+{
+    /* Get the hash index from the key.  Requires a symbol table. */
+    int i;
+    if (key->sizendx == pl->pl_symtab->pt_sizendx)
+        i = key->hashndx;
+    else
+        i = key->hashval % PLSIZENDX(pl->pl_symtab->pt_sizendx);
+    return i;
+}
+
+
+/* ---------------------------- _param_create ----------------------------- */
+
+static inline pb_param *_param_create(pool_handle_t *pool_handle, const char *name, int namelen, const char *value, int valuelen)
+{
+    PLValueStruct_t *ret;
+
+    ret = (PLValueStruct_t *)pool_malloc(pool_handle, sizeof(PLValueStruct_t));
+
+    ret->pv_pbentry.param = &ret->pv_pbparam;
+    ret->pv_pbentry.next = 0;
+    ret->pv_next = 0;
+    ret->pv_type = 0;
+    ret->pv_mempool = pool_handle;
+
+    if (name || namelen) {
+        ret->pv_name = (char*)pool_malloc(pool_handle, namelen + 1);
+        if (name) {
+            memcpy(ret->pv_name, name, namelen);
+            ret->pv_name[namelen] = '\0';
+        } else {
+            ret->pv_name[0] = '\0';
+        }
+    } else {
+        ret->pv_name = 0;
+    }
+
+    if (value || valuelen) {
+        ret->pv_value = (char*)pool_malloc(pool_handle, valuelen + 1);
+        if (value) {
+            memcpy(ret->pv_value, value, valuelen);
+            ret->pv_value[valuelen] = '\0';
+        } else {
+            ret->pv_value[0] = '\0';
+        }
+    } else {
+        ret->pv_value = 0;
+    }
+
+    return &ret->pv_pbparam;
+}
+
+
+/* ----------------------- pblock_key_param_create  ----------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb, const pb_key *key, const char *value, int valuelen)
+{
+    /*
+     * Allocate a PLValueStruct_t from the property list's memory pool.
+     */
+    PListStruct_t *pl = PBTOPL(pb);
+    return _param_create(pl->pl_mempool, key->name, key->namelen, value, valuelen);
+}
+
+
+/* ------------------------- pblock_param_create -------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb, const char *name, const char *value)
+{
+    /*
+     * Allocate a PLValueStruct_t from the property list's memory pool.
+     */
+    PListStruct_t *pl = PBTOPL(pb);
+    return _param_create(pl->pl_mempool, name, name ? strlen(name) : 0, value, value ? strlen(value) : 0);
+}
+
+
+/* ----------------------------- param_create ----------------------------- */
+
+NSAPI_PUBLIC pb_param *param_create(const char *name, const char *value)
+{
+    /*
+     * Allocate a PLValueStruct_t containing the pb_param that will
+     * be returned.  Normally PLValueStruct_ts are allocated from the
+     * memory pool associated with a property list, but we don't have
+     * that here, so we just use the thread's pool and indicate we were
+     * allocated from a specific pool.
+     */
+    return _param_create(system_pool(), name, name ? strlen(name) : 0, value, value ? strlen(value) : 0);
+}
+
+
+/* ------------------------------ param_free ------------------------------ */
+
+NSAPI_PUBLIC int param_free(pb_param *pp)
+{
+    if (pp) {
+        PLValueStruct_t *pv = PATOPV(pp);
+
+        /* Don't bother if the pblock was allocated from a pool */
+        if (!pv->pv_mempool) {
+            pool_free(pv->pv_mempool, pv->pv_name);
+            pool_free(pv->pv_mempool, pv->pv_value);
+            pool_free(pv->pv_mempool, pv);
+        }
+
+        return 1;
+    }
+
+    return 0;
+}
+
+
+/* -------------------------- pblock_create_pool -------------------------- */
+
+NSAPI_PUBLIC pblock *pblock_create_pool(pool_handle_t *pool_handle, int n)
+{
+    /* Create a property list with n property indices */
+    PListStruct_t *plist = (PListStruct_t *)PListCreate(pool_handle, n, 0, 0);
+    if (!plist)
+        return NULL;
+
+    plist->pl_resvpi = 0;
+
+    return &plist->pl_pb;
+}
+
+
+/* ----------------------------- pblock_pool ------------------------------ */
+
+NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+    return pl->pl_mempool;
+}
+
+
+/* ---------------------------- pblock_create ----------------------------- */
+
+NSAPI_PUBLIC pblock *pblock_create(int n)
+{
+    return pblock_create_pool(MALLOC_POOL_HANDLE, n);
+}
+
+
+/* ----------------------------- pblock_free ------------------------------ */
+
+NSAPI_PUBLIC void pblock_free(pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int i;
+
+    if (!pb) {
+        return;
+    }
+
+    /* If the pools are enabled, this routine has no effect anyway, so 
+     * just return. 
+     */
+    if (pl->pl_mempool || pool_enabled()) {
+        return;
+    }
+
+    /* Free the property name symbol table if any */
+    if (pl->pl_symtab) {
+        pool_free(pl->pl_mempool, (void *)(pl->pl_symtab));
+    }
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Loop over the initialized property indices */
+    for (i = 0; i < pl->pl_initpi; ++i) {
+
+        /* Got a property here? */
+        pv = ppval[i];
+        if (pv) {
+
+            param_free(&pv->pv_pbparam);
+        }
+    }
+
+    /* Free the array of pointers to property values */
+    pool_free(pl->pl_mempool, (void *)ppval);
+
+    /* Free the property list head */
+    pool_free(pl->pl_mempool, (void *)pl);
+}
+
+
+/* ------------------------------ pblock_key ------------------------------ */
+
+NSAPI_PUBLIC const pb_key *pblock_key(const char *name)
+{
+    if (!name)
+        return NULL;
+
+    return _find_key(name, PListHash(name));
+}
+
+
+/* --------------------------- pblock_kpinsert ---------------------------- */
+
+NSAPI_PUBLIC void pblock_kpinsert(const pb_key *key, pb_param *pp, pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+    PLValueStruct_t *pv = PATOPV(pp);
+
+    PR_ASSERT(pv->pv_mempool == pl->pl_mempool);
+
+    /* Check to see if the name corresponds to a pb_key */
+    unsigned int hashval;
+    if (!key) {
+        hashval = PListHash(pv->pv_name);
+        key = _find_key(pv->pv_name, hashval);
+    }
+
+    /* Find property index */
+    int pindex = PListGetFreeIndex(pl);
+    if (pindex < 1) {
+        /* Error - invalid property index */
+        return;
+    }
+
+    /* Allocate/grow the symbol table as needed */
+    PLSymbolTable_t *pt = PListSymbolTable(pl);
+    if (!pt) {
+        return;
+    }
+
+    /* Add PLValueStruct_t to the property list */
+    PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
+    pv->pv_pbkey = key;
+    pv->pv_pi = pindex;
+    ppval[pv->pv_pi - 1] = pv;
+
+    /* Add name to symbol table */
+    int i = key ? _get_hash_index(pl, key) : (hashval % PLSIZENDX(pt->pt_sizendx));
+    pv->pv_next = pt->pt_hash[i];
+    pt->pt_hash[i] = pv;
+    pt->pt_nsyms++;
+
+    PR_ASSERT(param_key(pp) == key);
+}
+
+
+/* ---------------------------- pblock_pinsert ---------------------------- */
+
+NSAPI_PUBLIC void pblock_pinsert(pb_param *pp, pblock *pb)
+{
+    pblock_kpinsert(NULL, pp, pb);
+}
+
+
+/* --------------------------- pblock_nvinsert ---------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_nvinsert(const char *name, const char *value, pblock *pb)
+{
+    pb_param *pp = pblock_param_create(pb, name, value);
+    if (pp)
+        pblock_kpinsert(NULL, pp, pb);
+    return pp;
+}
+
+
+/* --------------------------- pblock_kvinsert ---------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_kvinsert(const pb_key *key, const char *value, int valuelen, pblock *pb)
+{
+    pb_param *pp = pblock_key_param_create(pb, key, value, valuelen);
+    if (pp)
+        pblock_kpinsert(key, pp, pb);
+    return pp;
+}
+
+
+/* --------------------------- pblock_nninsert ---------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_nninsert(const char *name, int value, pblock *pb)
+{
+    char num[UTIL_ITOA_SIZE];
+
+    util_itoa(value, num);
+    return pblock_nvinsert(name, num, pb);
+}
+
+
+/* --------------------------- pblock_kninsert ---------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_kninsert(const pb_key *key, int value, pblock *pb)
+{
+    pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_ITOA_SIZE);
+    if (pp) {
+        util_itoa(value, pp->value);
+        pblock_kpinsert(key, pp, pb);
+    }
+    return pp;
+}
+
+
+/* --------------------------- pblock_kllinsert --------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, PRInt64 value, pblock *pb)
+{
+    pb_param *pp = pblock_key_param_create(pb, key, NULL, UTIL_I64TOA_SIZE);
+    if (pp) {
+        util_i64toa(value, pp->value);
+        pblock_kpinsert(key, pp, pb);
+    }
+    return pp;
+}
+
+
+/* ---------------------------- pblock_findkey ---------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_findkey(const pb_key *key, const pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+
+    /* Lookup key by examining symbol table */
+    if (pl->pl_symtab) {
+        int i = _get_hash_index(pl, key);
+        PLValueStruct_t *pv;
+
+        /* Search hash collision list for matching name */
+        for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
+            if (pv->pv_pbkey == key)
+                return &pv->pv_pbparam;
+        }
+    }
+
+    return NULL;
+}
+
+
+/* -------------------------- pblock_findkeyval --------------------------- */
+
+NSAPI_PUBLIC char *pblock_findkeyval(const pb_key *key, const pblock *pb)
+{
+    pb_param *pp = pblock_findkey(key, pb);
+    return pp ? pp->value : NULL;
+}
+
+
+/* ---------------------------- pblock_findval ---------------------------- */
+
+NSAPI_PUBLIC char *pblock_findval(const char *name, const pblock *pb)
+{
+    void *pvalue = 0;
+
+    (void)PListFindValue((PList_t)(PBTOPL(pb)), name, &pvalue, 0);
+
+    return (char *)pvalue;
+}
+
+
+/* ------------------------------ pblock_fr ------------------------------ */
+
+NSAPI_PUBLIC pb_param *pblock_fr(const char *name, pblock *pb, int remove)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+    PLValueStruct_t **ppval;
+    PLValueStruct_t **pvp;
+    PLValueStruct_t *pv = NULL;
+    int pindex;
+    int i;
+
+    if (pl->pl_symtab) {
+
+        /* Compute hash index of specified property name */
+        i = PListHashName(pl->pl_symtab, name);
+
+        /* Search hash collision list for matching name */
+        for (pvp = &pl->pl_symtab->pt_hash[i];
+             (pv = *pvp); pvp = &(*pvp)->pv_next) {
+
+            if (!strcmp(name, pv->pv_name)) {
+
+                if (remove) {
+                    /* Remove PLValueStruct_t from symbol table */
+                    *pvp = pv->pv_next;
+                    pl->pl_symtab->pt_nsyms--;
+
+                    /* Remove it from pl_ppval too */
+                    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+                    pindex = pv->pv_pi;
+                    ppval[pindex - 1] = 0;
+                }
+                break;
+            }
+        }
+    }
+
+    return (pv) ? &pv->pv_pbparam : NULL;
+}
+
+
+/* --------------------------- pblock_removekey --------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_removekey(const pb_key *key, pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+    PLValueStruct_t **ppval;
+    PLValueStruct_t **pvp;
+    PLValueStruct_t *pv = NULL;
+    int pindex;
+    int i;
+
+    if (pl->pl_symtab) {
+        /* Lookup hash index for specified property key */
+        i = _get_hash_index(pl, key);
+
+        /* Search hash collision list for matching key */
+        for (pvp = &pl->pl_symtab->pt_hash[i]; (pv = *pvp); pvp = &pv->pv_next) {
+            /* If this value has the requested key... */
+            if (pv->pv_pbkey == key) {
+                /* Remove PLValueStruct_t from symbol table */
+                *pvp = pv->pv_next;
+                pl->pl_symtab->pt_nsyms--;
+
+                /* Remove it from pl_ppval too */
+                ppval = (PLValueStruct_t **)(pl->pl_ppval);
+                pindex = pv->pv_pi;
+                ppval[pindex - 1] = 0;
+
+                break;
+            }
+        }
+    }
+
+    return (pv) ? &pv->pv_pbparam : NULL;
+}
+
+
+/* -------------------------- pblock_removeone --------------------------- */
+
+NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+
+    if (pl && pl->pl_symtab) {
+        /* Search hash buckets */
+        for (int i = 0; i < PLSIZENDX(pl->pl_symtab->pt_sizendx); i++) {
+            /* Search hash collision list */
+            PLValueStruct_t *pv = pl->pl_symtab->pt_hash[i];
+            if (pv) {
+                /* Remove PLValueStruct_t from symbol table */
+                pl->pl_symtab->pt_hash[i] = pv->pv_next;
+                pl->pl_symtab->pt_nsyms--;
+
+                /* Remove it from pl_ppval too */
+                PLValueStruct_t **ppval = (PLValueStruct_t**)pl->pl_ppval;
+                ppval[pv->pv_pi - 1] = 0;
+
+                return &pv->pv_pbparam;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+
+/* -------------------------- pblock_str2pblock --------------------------- */
+
+
+int _verify_pbstr(const char *str)
+{
+    const char *cp;
+    const char *scp;
+    int np;
+    int state;
+    int quote;
+
+    for(cp = str, np = 0, state = 0; *cp; ) {
+        switch (state) {
+        case 0:                 /* skipping leading spaces */
+
+            while (*cp && isspace(*cp)) ++cp;
+            if (*cp == '=') {
+                return -1;
+            }
+            if (*cp) state = 1;
+            break;
+
+        case 1:                 /* scanning parameter name */
+
+            scp = cp;
+            while (*cp && (*cp != '=') && !isspace(*cp)) ++cp;
+            if (*cp == '=') ++cp;
+            else cp = scp;
+            state = 2;
+            break;
+
+        case 2:                 /* scanning parameter value */
+            quote = 0;
+            if (*cp == '\"') {
+                quote = 1;
+                ++cp;
+            }
+            for (;;) {
+                if (*cp == '\\') {
+                    ++cp;
+                    if (*cp == 0) {
+                        return -1;
+                    }
+                }
+                else if (*cp == '\"') {
+                    if (!quote) {
+                        return -1;
+                    }
+                    ++np;
+                    ++cp;
+                    quote = 0;
+                    state = 0;
+                    break;
+                }
+                else if (!quote && (!*cp || isspace(*cp))) {
+                    ++np;
+                    if (*cp) ++cp;
+                    state = 0;
+                    break;
+                }
+                else if (*cp == 0) {
+                    return -1;
+                }
+                ++cp;
+            }
+            if (quote) {
+                return -1;
+            }
+            break;
+        }
+    }
+
+    return (state == 0) ? np : -1;
+}
+
+NSAPI_PUBLIC int
+INTpblock_str2pblock_lowercasename(const char *str, pblock *pb)
+{
+    return _pblock_str2pblock(str, pb, PR_TRUE);
+}
+
+NSAPI_PUBLIC int pblock_str2pblock(const char *str, pblock *pb)
+{
+    return _pblock_str2pblock(str, pb, PR_FALSE);
+}
+
+int
+_pblock_str2pblock(const char* str, pblock* pb, PRBool lowerCase)
+{
+    char *cpy;
+    char *cp;
+    char *dp;
+    char *pname;
+    char *pvalue;
+    int np;
+    int quote;
+    int state;
+    char numbuf[UTIL_ITOA_SIZE];
+
+    if((np = _verify_pbstr(str)) < 1)
+        return -1;
+
+    while (*str && isspace(*str)) ++str;
+
+    cpy = STRDUP(str);
+
+    for (np = 0, cp = cpy, state = 0; *cp; ) {
+        switch (state) {
+
+        case 0:                 /* skipping leading spaces */
+
+            while (*cp && isspace(*cp)) ++cp;
+            if (*cp) state = 1;
+            break;
+
+        case 1:                 /* scanning parameter name */
+
+            pname = cp;
+            while (*cp && (*cp != '=') && !isspace(*cp)) ++cp;
+            if (*cp == '=') {
+                *cp++ = 0;
+            }
+            else {
+                cp = pname;
+                pname = numbuf;
+                util_itoa(np+1, numbuf);
+            }
+            state = 2;
+            break;
+
+        case 2:                 /* scanning parameter value */
+            quote = 0;
+            if (*cp == '\"') {
+                quote = 1;
+                ++cp;
+            }
+            for (pvalue = cp, dp = cp; ; ++cp, ++dp) {
+                if (*cp == '\\') {
+                    ++cp;
+                }
+                else if (*cp == '\"') {
+                    ++np;
+                    ++cp;
+                    *dp = 0;
+                    quote = 0;
+                    state = 0;
+                    break;
+                }
+                else if (!quote && ((*cp == 0) || isspace(*cp))) {
+                    ++np;
+                    if (*cp != 0) {
+                        ++cp;
+                    }
+                    *dp = 0;
+                    state = 0;
+                    break;
+                }
+                if (cp != dp) *dp = *cp;
+            }
+            if (lowerCase == PR_TRUE) {
+                for (char* p = pname; *p; p++) {
+                    *p = tolower(*p);
+                }
+            }
+            pblock_nvinsert(pname, pvalue, pb);
+            break;
+        }
+    }
+
+    FREE(cpy);
+
+    return np;
+}
+
+
+/* -------------------------- pblock_pblock2str --------------------------- */
+
+
+NSAPI_PUBLIC char *pblock_pblock2str(const pblock *pb, char *str)
+{
+    register char *s = str, *t, *u;
+    PListStruct_t *pl = PBTOPL(pb);
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int i;
+    int sl;
+    int xlen;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Loop over the initialized property indices */
+    for (i = 0, xlen = 0; i < pl->pl_initpi; ++i) {
+
+        /* Got a property here? */
+        pv = ppval[i];
+        if (pv && pv->pv_name) {
+
+            int ln = strlen(pv->pv_name);
+            int lv = strlen((char *)(pv->pv_value));
+
+            /* Check for " or \ because we'll have to escape them */
+            for (t = (char *)(pv->pv_value); *t; ++t) {
+                if ((*t == '\"') || (*t == '\\')) ++lv;
+            }
+
+            /* 4: two quotes, =, and a null */
+            xlen += (ln + lv + 4);
+        }
+    }
+
+    /* Allocate string to hold parameter settings, or increase size */
+    if (!s) {
+        s = (char *)MALLOC(xlen);
+        s[0] = '\0';
+        t = &s[0];
+        sl = xlen;
+    }
+    else {
+        sl = strlen(s);
+        t = &s[sl];
+        sl += xlen;
+        s = (char *)REALLOC(s, sl);
+    }
+
+    /* Loop over the initialized property indices */
+    for (i = 0; i < pl->pl_initpi; ++i) {
+
+        /* Got a property here? */
+        pv = ppval[i];
+        if (pv && pv->pv_name) {
+
+            if (t != s) *t++ = ' ';
+
+            for (u = pv->pv_name; *u; ) *t++ = *u++;
+
+            *t++ = '=';
+            *t++ = '\"';
+
+            for (u = (char *)(pv->pv_value); *u; ) {
+                if ((*u == '\\') || (*u == '\"')) *t++ = '\\';
+                *t++ = *u++;
+            }
+
+            *t++ = '\"';
+            *t = '\0';
+        }
+    }
+
+    return s;
+}
+
+
+/* ----------------------------- pblock_copy ------------------------------ */
+
+
+NSAPI_PUBLIC int pblock_copy(const pblock *src, pblock *dst)
+{
+    PListStruct_t *pl = PBTOPL(src);
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int rv = 0;
+    int i;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    for (i = 0; i < pl->pl_initpi; ++i) {
+        pv = ppval[i];
+        if (pv) {
+            if (pv->pv_pbkey) {
+                if (pv->pv_pbkey != pb_key_magnus_internal) {
+                    if (!pblock_kvinsert(pv->pv_pbkey, (char *)(pv->pv_value), strlen(pv->pv_value), dst))
+                        rv = -1;
+                }
+            } else {
+                if (!pblock_nvinsert(pv->pv_name, (char *)(pv->pv_value), dst))
+                    rv = -1;
+            }
+        }
+    }
+
+    return rv;
+}
+
+/* ---------------------------- pblock_dup -------------------------------- */
+
+NSAPI_PUBLIC pblock *pblock_dup(const pblock *src)
+{
+    pblock *dst;
+
+    if (!src)
+        return NULL;
+
+    if ( (dst = pblock_create(src->hsize)) )
+        pblock_copy(src, dst);
+
+    return dst;
+}
+
+
+/* ---------------------------- pblock_pb2env ----------------------------- */
+
+/*
+NSAPI_PUBLIC char **pblock_pb2env(const pblock *pb, char **env)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int i;
+    int nval;
+    int pos;
+
+    /* Find out how many there are. */
+    /*
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    for (i = 0, nval = 0; i < pl->pl_initpi; ++i) {
+        if (ppval[i]) ++nval;
+    }
+
+    env = util_env_create(env, nval, &pos);
+
+    for (i = 0; i < pl->pl_initpi; ++i) {
+        pv = ppval[i];
+        if (pv) {
+            env[pos++] = util_env_str(pv->pv_name, (char *)(pv->pv_value));
+        }
+    }
+    env[pos] = NULL;
+
+    return env;
+}
+*/
+
+/* ---------------------------- pblock_replace ---------------------------- */
+
+NSAPI_PUBLIC char * pblock_replace(const char *name,
+                                   char * new_value, pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+
+    /* Replace an existing value */
+    pb_param *pp = pblock_find(name, pb);
+    if (!pp)
+        return NULL;
+    pool_free(pl->pl_mempool, pp->value);
+    pp->value = new_value;
+
+    return new_value;
+}
+
+
+/* --------------------------- pblock_nvreplace --------------------------- */
+
+NSAPI_PUBLIC void pblock_nvreplace (const char *name, const char *value, pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+
+    /* Replace an existing value or insert a new value */
+    pb_param *pp = pblock_find(name, pb);
+    if (pp) {
+        pool_free(pl->pl_mempool, pp->value);
+        pp->value = pool_strdup(pl->pl_mempool, value);
+    } else {
+        pblock_nvinsert(name, value, pb);
+    }
+}
+
+
+/* --------------------------- pblock_kvreplace --------------------------- */
+
+NSAPI_PUBLIC void pblock_kvreplace(const pb_key *key, const char *value, int valuelen, pblock *pb)
+{
+    PListStruct_t *pl = PBTOPL(pb);
+
+    /* Replace an existing value or insert a new value */
+    pb_param *pp = pblock_findkey(key, pb);
+    if (pp) {
+        pool_free(pl->pl_mempool, pp->value);
+        pp->value = (char*)pool_malloc(pl->pl_mempool, valuelen + 1);
+        memcpy(pp->value, value, valuelen + 1);
+    } else {
+        pblock_kvinsert(key, value, valuelen, pb);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/pblock.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,362 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_PBLOCK_H
+#define BASE_PBLOCK_H
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * pblock.h: Header for Parameter Block handling functions
+ * 
+ *
+ * A parameter block is a set of name=value pairs which are generally used 
+ * as parameters, but can be anything. They are kept in a hash table for 
+ * reasonable speed, but if you are doing any intensive modification or
+ * access of them you should probably make a local copy of each parameter
+ * while working.
+ *
+ * Rob McCool
+ * 
+ */
+
+#ifndef NETSITE_H
+#include "nsapi.h"
+#include "netsite.h"
+#endif /* !NETSITE_H */
+
+#ifdef XP_WIN32
+#ifdef BUILD_DLL
+#define BASE_DLL _declspec(dllexport)
+#else
+#define BASE_DLL _declspec(dllimport)
+#endif
+#else
+#define BASE_DLL
+#endif
+
+#ifdef INTNSAPI
+
+/* --- Begin function prototypes --- */
+
+NSPR_BEGIN_EXTERN_C
+
+NSAPI_PUBLIC pb_param *INTparam_create(const char *name, const char *value);
+
+NSAPI_PUBLIC int INTparam_free(pb_param *pp);
+
+NSAPI_PUBLIC pblock *INTpblock_create(int n);
+
+NSAPI_PUBLIC void INTpblock_free(pblock *pb);
+
+NSAPI_PUBLIC char *INTpblock_findval(const char *name, const pblock *pb);
+
+NSAPI_PUBLIC pb_param *INTpblock_nvinsert(const char *name, const char *value, pblock *pb);
+
+NSAPI_PUBLIC pb_param *INTpblock_nninsert(const char *name, int value, pblock *pb);
+
+NSAPI_PUBLIC void INTpblock_pinsert(pb_param *pp, pblock *pb);
+
+NSAPI_PUBLIC int INTpblock_str2pblock(const char *str, pblock *pb);
+
+NSAPI_PUBLIC char *INTpblock_pblock2str(const pblock *pb, char *str);
+
+NSAPI_PUBLIC int INTpblock_copy(const pblock *src, pblock *dst);
+
+NSAPI_PUBLIC pblock *INTpblock_dup(const pblock *src);
+
+NSAPI_PUBLIC char **INTpblock_pb2env(const pblock *pb, char **env);
+
+NSAPI_PUBLIC void pblock_nvreplace (const char *name, const char *value, pblock *pb);
+
+/* --------------------------- Internal things ---------------------------- */
+
+typedef struct pb_key pb_key;
+
+BASE_DLL extern const pb_key *const pb_key_accept;
+BASE_DLL extern const pb_key *const pb_key_accept_charset;
+BASE_DLL extern const pb_key *const pb_key_accept_encoding;
+BASE_DLL extern const pb_key *const pb_key_accept_language;
+BASE_DLL extern const pb_key *const pb_key_accept_ranges;
+BASE_DLL extern const pb_key *const pb_key_actual_route;
+BASE_DLL extern const pb_key *const pb_key_age;
+BASE_DLL extern const pb_key *const pb_key_always_allow_chunked;
+BASE_DLL extern const pb_key *const pb_key_always_use_keep_alive;
+BASE_DLL extern const pb_key *const pb_key_auth_cert;
+BASE_DLL extern const pb_key *const pb_key_auth_expiring;
+BASE_DLL extern const pb_key *const pb_key_auth_group;
+BASE_DLL extern const pb_key *const pb_key_auth_type;
+BASE_DLL extern const pb_key *const pb_key_auth_user;
+BASE_DLL extern const pb_key *const pb_key_authorization;
+BASE_DLL extern const pb_key *const pb_key_browser;
+BASE_DLL extern const pb_key *const pb_key_c2p_cl;
+BASE_DLL extern const pb_key *const pb_key_c2p_hl;
+BASE_DLL extern const pb_key *const pb_key_cache_info;
+BASE_DLL extern const pb_key *const pb_key_charset;
+BASE_DLL extern const pb_key *const pb_key_check_http_server;
+BASE_DLL extern const pb_key *const pb_key_ChunkedRequestBufferSize;
+BASE_DLL extern const pb_key *const pb_key_ChunkedRequestTimeout;
+BASE_DLL extern const pb_key *const pb_key_cipher;
+BASE_DLL extern const pb_key *const pb_key_clf_request;
+BASE_DLL extern const pb_key *const pb_key_cli_status;
+BASE_DLL extern const pb_key *const pb_key_client_cert_nickname;
+BASE_DLL extern const pb_key *const pb_key_client_ip;
+BASE_DLL extern const pb_key *const pb_key_close;
+BASE_DLL extern const pb_key *const pb_key_connect_timeout;
+BASE_DLL extern const pb_key *const pb_key_connection;
+BASE_DLL extern const pb_key *const pb_key_cont;
+BASE_DLL extern const pb_key *const pb_key_content_encoding;
+BASE_DLL extern const pb_key *const pb_key_content_language;
+BASE_DLL extern const pb_key *const pb_key_content_length;
+BASE_DLL extern const pb_key *const pb_key_content_location;
+BASE_DLL extern const pb_key *const pb_key_content_md5;
+BASE_DLL extern const pb_key *const pb_key_content_range;
+BASE_DLL extern const pb_key *const pb_key_content_type;
+BASE_DLL extern const pb_key *const pb_key_cookie;
+BASE_DLL extern const pb_key *const pb_key_date;
+BASE_DLL extern const pb_key *const pb_key_DATE_GMT;
+BASE_DLL extern const pb_key *const pb_key_DATE_LOCAL;
+BASE_DLL extern const pb_key *const pb_key_dir;
+BASE_DLL extern const pb_key *const pb_key_Directive;
+BASE_DLL extern const pb_key *const pb_key_dns;
+BASE_DLL extern const pb_key *const pb_key_DOCUMENT_NAME;
+BASE_DLL extern const pb_key *const pb_key_DOCUMENT_URI;
+BASE_DLL extern const pb_key *const pb_key_domain;
+BASE_DLL extern const pb_key *const pb_key_enc;
+BASE_DLL extern const pb_key *const pb_key_engine;
+BASE_DLL extern const pb_key *const pb_key_error_action;
+BASE_DLL extern const pb_key *const pb_key_error_desc;
+BASE_DLL extern const pb_key *const pb_key_error_fn;
+BASE_DLL extern const pb_key *const pb_key_escape;
+BASE_DLL extern const pb_key *const pb_key_escaped;
+BASE_DLL extern const pb_key *const pb_key_etag;
+BASE_DLL extern const pb_key *const pb_key_expect;
+BASE_DLL extern const pb_key *const pb_key_expires;
+BASE_DLL extern const pb_key *const pb_key_expr;
+BASE_DLL extern const pb_key *const pb_key_filter;
+BASE_DLL extern const pb_key *const pb_key_find_pathinfo_forward;
+BASE_DLL extern const pb_key *const pb_key_flushTimer;
+BASE_DLL extern const pb_key *const pb_key_fn;
+BASE_DLL extern const pb_key *const pb_key_from;
+BASE_DLL extern const pb_key *const pb_key_full_headers;
+BASE_DLL extern const pb_key *const pb_key_hdr;
+BASE_DLL extern const pb_key *const pb_key_host;
+BASE_DLL extern const pb_key *const pb_key_hostname;
+BASE_DLL extern const pb_key *const pb_key_if_match;
+BASE_DLL extern const pb_key *const pb_key_if_modified_since;
+BASE_DLL extern const pb_key *const pb_key_if_none_match;
+BASE_DLL extern const pb_key *const pb_key_if_range;
+BASE_DLL extern const pb_key *const pb_key_if_unmodified_since;
+BASE_DLL extern const pb_key *const pb_key_ip;
+BASE_DLL extern const pb_key *const pb_key_iponly;
+BASE_DLL extern const pb_key *const pb_key_issuer_dn;
+BASE_DLL extern const pb_key *const pb_key_jroute;
+BASE_DLL extern const pb_key *const pb_key_keep_alive;
+BASE_DLL extern const pb_key *const pb_key_keep_alive_timeout;
+BASE_DLL extern const pb_key *const pb_key_keysize;
+BASE_DLL extern const pb_key *const pb_key_lang;
+BASE_DLL extern const pb_key *const pb_key_LAST_MODIFIED;
+BASE_DLL extern const pb_key *const pb_key_last_modified;
+BASE_DLL extern const pb_key *const pb_key_level;
+BASE_DLL extern const pb_key *const pb_key_location;
+BASE_DLL extern const pb_key *const pb_key_lock_owner;
+BASE_DLL extern const pb_key *const pb_key_magnus_charset;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_dav_src;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_default_acls_only;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_error_j2ee;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_j2ee_nsapi;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_preserve_srvhdrs;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_set_request_status;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_set_response_status;
+BASE_DLL extern const pb_key *const pb_key_magnus_internal_webapp_errordesc;
+BASE_DLL extern const pb_key *const pb_key_matched_browser;
+BASE_DLL extern const pb_key *const pb_key_max_age;
+BASE_DLL extern const pb_key *const pb_key_max_forwards;
+BASE_DLL extern const pb_key *const pb_key_message;
+BASE_DLL extern const pb_key *const pb_key_method;
+BASE_DLL extern const pb_key *const pb_key_name;
+BASE_DLL extern const pb_key *const pb_key_nocache;
+BASE_DLL extern const pb_key *const pb_key_nostat;
+BASE_DLL extern const pb_key *const pb_key_ntrans_base;
+BASE_DLL extern const pb_key *const pb_key_offline_origin_addr;
+BASE_DLL extern const pb_key *const pb_key_offline_proxy_addr;
+BASE_DLL extern const pb_key *const pb_key_origin_addr;
+BASE_DLL extern const pb_key *const pb_key_p2c_cl;
+BASE_DLL extern const pb_key *const pb_key_p2c_hl;
+BASE_DLL extern const pb_key *const pb_key_p2r_cl;
+BASE_DLL extern const pb_key *const pb_key_p2r_hl;
+BASE_DLL extern const pb_key *const pb_key_parse_timeout;
+BASE_DLL extern const pb_key *const pb_key_password;
+BASE_DLL extern const pb_key *const pb_key_path;
+BASE_DLL extern const pb_key *const pb_key_PATH_INFO;
+BASE_DLL extern const pb_key *const pb_key_path_info;
+BASE_DLL extern const pb_key *const pb_key_pblock;
+BASE_DLL extern const pb_key *const pb_key_poll_interval;
+BASE_DLL extern const pb_key *const pb_key_port;
+BASE_DLL extern const pb_key *const pb_key_ppath;
+BASE_DLL extern const pb_key *const pb_key_pragma;
+BASE_DLL extern const pb_key *const pb_key_process_request_body;
+BASE_DLL extern const pb_key *const pb_key_process_response_body;
+BASE_DLL extern const pb_key *const pb_key_protocol;
+BASE_DLL extern const pb_key *const pb_key_proxy_addr;
+BASE_DLL extern const pb_key *const pb_key_proxy_agent;
+BASE_DLL extern const pb_key *const pb_key_proxy_auth_cert;
+BASE_DLL extern const pb_key *const pb_key_proxy_authorization;
+BASE_DLL extern const pb_key *const pb_key_proxy_cipher;
+BASE_DLL extern const pb_key *const pb_key_proxy_issuer_dn;
+BASE_DLL extern const pb_key *const pb_key_proxy_jroute;
+BASE_DLL extern const pb_key *const pb_key_proxy_keysize;
+BASE_DLL extern const pb_key *const pb_key_proxy_ping;
+BASE_DLL extern const pb_key *const pb_key_proxy_request;
+BASE_DLL extern const pb_key *const pb_key_proxy_secret_keysize;
+BASE_DLL extern const pb_key *const pb_key_proxy_ssl_id;
+BASE_DLL extern const pb_key *const pb_key_proxy_user_dn;
+BASE_DLL extern const pb_key *const pb_key_query;
+BASE_DLL extern const pb_key *const pb_key_QUERY_STRING;
+BASE_DLL extern const pb_key *const pb_key_QUERY_STRING_UNESCAPED;
+BASE_DLL extern const pb_key *const pb_key_r2p_cl;
+BASE_DLL extern const pb_key *const pb_key_r2p_hl;
+BASE_DLL extern const pb_key *const pb_key_range;
+BASE_DLL extern const pb_key *const pb_key_referer;
+BASE_DLL extern const pb_key *const pb_key_reformat_request_headers;
+BASE_DLL extern const pb_key *const pb_key_remote_status;
+BASE_DLL extern const pb_key *const pb_key_request_jroute;
+BASE_DLL extern const pb_key *const pb_key_required_rights;
+BASE_DLL extern const pb_key *const pb_key_retries;
+BASE_DLL extern const pb_key *const pb_key_rewrite_content_location;
+BASE_DLL extern const pb_key *const pb_key_rewrite_host;
+BASE_DLL extern const pb_key *const pb_key_rewrite_location;
+BASE_DLL extern const pb_key *const pb_key_rewrite_set_cookie;
+BASE_DLL extern const pb_key *const pb_key_root;
+BASE_DLL extern const pb_key *const pb_key_route;
+BASE_DLL extern const pb_key *const pb_key_route_cookie;
+BASE_DLL extern const pb_key *const pb_key_route_hdr;
+BASE_DLL extern const pb_key *const pb_key_route_offline;
+BASE_DLL extern const pb_key *const pb_key_script_name;
+BASE_DLL extern const pb_key *const pb_key_secret_keysize;
+BASE_DLL extern const pb_key *const pb_key_secure;
+BASE_DLL extern const pb_key *const pb_key_server;
+BASE_DLL extern const pb_key *const pb_key_set_cookie;
+BASE_DLL extern const pb_key *const pb_key_socks_addr;
+BASE_DLL extern const pb_key *const pb_key_ssl_id;
+BASE_DLL extern const pb_key *const pb_key_ssl_unclean_shutdown;
+BASE_DLL extern const pb_key *const pb_key_status;
+BASE_DLL extern const pb_key *const pb_key_sticky_cookie;
+BASE_DLL extern const pb_key *const pb_key_sticky_param;
+BASE_DLL extern const pb_key *const pb_key_suppress_request_headers;
+BASE_DLL extern const pb_key *const pb_key_svr_status;
+BASE_DLL extern const pb_key *const pb_key_timeout;
+BASE_DLL extern const pb_key *const pb_key_to;
+BASE_DLL extern const pb_key *const pb_key_transfer_encoding;
+BASE_DLL extern const pb_key *const pb_key_transmit_timeout;
+BASE_DLL extern const pb_key *const pb_key_tunnel_non_http_response;
+BASE_DLL extern const pb_key *const pb_key_type;
+BASE_DLL extern const pb_key *const pb_key_upstream_jroute;
+BASE_DLL extern const pb_key *const pb_key_uri;
+BASE_DLL extern const pb_key *const pb_key_url;
+BASE_DLL extern const pb_key *const pb_key_url_prefix;
+BASE_DLL extern const pb_key *const pb_key_UseOutputStreamSize;
+BASE_DLL extern const pb_key *const pb_key_user;
+BASE_DLL extern const pb_key *const pb_key_user_agent;
+BASE_DLL extern const pb_key *const pb_key_user_dn;
+BASE_DLL extern const pb_key *const pb_key_validate_server_cert;
+BASE_DLL extern const pb_key *const pb_key_value;
+BASE_DLL extern const pb_key *const pb_key_vary;
+BASE_DLL extern const pb_key *const pb_key_via;
+BASE_DLL extern const pb_key *const pb_key_warning;
+
+NSAPI_PUBLIC pool_handle_t *pblock_pool(pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_param_create(pblock *pb, const char *name, const char *value);
+
+NSAPI_PUBLIC pblock *pblock_create_pool(pool_handle_t *pool_handle, int n);
+
+NSAPI_PUBLIC pb_param *INTpblock_fr(const char *name, pblock *pb, int remove);
+
+NSAPI_PUBLIC char *INTpblock_replace(const char *name,char * new_value,pblock *pb);
+
+NSAPI_PUBLIC int INTpblock_str2pblock_lowercasename(const char *str, pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_removeone(pblock *pb);
+
+NSAPI_PUBLIC const pb_key *pblock_key(const char *name);
+
+NSAPI_PUBLIC pb_param *pblock_key_param_create(pblock *pb, const pb_key *key, const char *value, int valuelen);
+
+NSAPI_PUBLIC char *pblock_findkeyval(const pb_key *key, const pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_findkey(const pb_key *key, const pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_removekey(const pb_key *key, pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_kvinsert(const pb_key *key, const char *value, int valuelen, pblock *pb);
+
+NSAPI_PUBLIC void pblock_kpinsert(const pb_key *key, pb_param *pp, pblock *pb);
+
+NSAPI_PUBLIC void pblock_kvreplace(const pb_key *key, const char *value, int valuelen, pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_kninsert(const pb_key *key, int value, pblock *pb);
+
+NSAPI_PUBLIC pb_param *pblock_kllinsert(const pb_key *key, PRInt64 value, pblock *pb);
+
+#ifdef __cplusplus
+inline const pb_key *param_key(pb_param *pp)
+{
+    return *(const pb_key **)(pp + 1); /* XXX see plist_pvt.h */
+}
+#endif
+
+NSPR_END_EXTERN_C
+
+#define param_create INTparam_create
+#define param_free INTparam_free
+#define pblock_create INTpblock_create
+#define pblock_free INTpblock_free
+#define pblock_findval INTpblock_findval
+#define pblock_nvinsert INTpblock_nvinsert
+#define pblock_nninsert INTpblock_nninsert
+#define pblock_pinsert INTpblock_pinsert
+#define pblock_str2pblock INTpblock_str2pblock
+#define pblock_pblock2str INTpblock_pblock2str
+#define pblock_copy INTpblock_copy
+#define pblock_dup INTpblock_dup
+#define pblock_pb2env INTpblock_pb2env
+#define pblock_fr INTpblock_fr
+#define pblock_replace INTpblock_replace
+
+#endif /* INTNSAPI */
+
+#endif /* !BASE_PBLOCK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/plist.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,1273 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * MODULE:      plist.c
+ *
+ * DESCRIPTION:
+ *
+ *      This module implements property lists.  A property list is an
+ *      ordered array of property values.  Each property value has an
+ *      handle for some data item, and may have a reference to
+ *      another property list which describes the type of the data
+ *      item.  Each property value has a property index which specifies
+ *      its position in the property list.  A property value may also
+ *      have a name.  Since the data item associated with a property
+ *      value may reference another property list, it is possible to
+ *      construct arbitrary linked structures of property lists.
+ *
+ * IMPLEMENTATION NOTES:
+ */
+
+#include "netsite.h"
+#include "plist.h"
+#include "plist_pvt.h"
+
+int plistHashSizes[] = PLSTSIZES;
+
+/*
+ * FUNCTION:    PListAssignValue
+ *
+ * DESCRIPTION:
+ *
+ *      This function sets the value and/or type of a defined property
+ *      in given property list.  If the property type is specified as
+ *      NULL, it is unchanged.  However, the property value is always
+ *      set to the specified value.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pname                   - the property name
+ *      pvalue                  - the new property value
+ *      ptype                   - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ *      If successful, the property index of the referenced property is
+ *      returned as the function value.  Errors are indicated by a
+ *      negative return code as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListAssignValue(PList_t plist, const char *pname,
+                 const void *pvalue, PList_t ptype)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t *pv;
+    int pindex;
+    int i;
+
+    if (!plist) return ERRPLUNDEF;
+
+    /* Got a symbol table for this property list? */
+    if (pl->pl_symtab) {
+
+        /* Yes, compute hash of specified name */
+        i = PListHashName(pl->pl_symtab, pname);
+
+        /* Search hash collision list for matching name */
+        for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
+
+            if (!strcmp(pname, pv->pv_name)) {
+
+                /* Name match, get property index */
+                pindex = pv->pv_pi;
+
+                /* Set the new value */
+                pv->pv_value = (char *)pvalue;
+
+                /* Set type if type is given */
+                if (ptype) pv->pv_type = (PListStruct_t *)ptype;
+
+                /* Return the property index */
+                return pindex;
+            }
+        }
+    }
+
+    /* Error - specified property name is undefined */
+    return ERRPLUNDEF;
+}
+
+/*
+ * FUNCTION:    PListCreate
+ *
+ * DESCRIPTION:
+ *
+ *      This function creates a new property list and returns a handle for
+ *      it.  It allows the caller to reserve a specified number of
+ *      property indices at the beginning of the list, and also to limit
+ *      the total number of property values that may be added to the list.
+ *
+ * ARGUMENTS:
+ *
+ *      mempool                 - handle for a memory pool to be associated
+ *                                with the new property list
+ *      resvprop                - number of reserved property indices
+ *      maxprop                 - maximum number of properties in list
+ *                                (zero or negative imposes no limit)
+ *      flags                   - unused, reserved, must be zero
+ *
+ * RETURNS:
+ *
+ *      If successful, the function return value is a handle for the new
+ *      property list.  Otherwise NULL is returned.
+ */
+
+NSAPI_PUBLIC PList_t
+PListCreate(pool_handle_t *mempool, int resvprop, int maxprop, int flags)
+{
+    PListStruct_t *plist;       /* pointer to property list structure */
+    int i;
+
+    plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
+    if (plist) {
+
+        /* Negative maxprop is the same as zero, i.e. no limit */
+        if (maxprop < 0) maxprop = 0;
+
+        /* If resvprop and maxprop are both specified, limit resvprop */
+        if (resvprop > 0) {
+            if (maxprop && (resvprop > maxprop)) resvprop = maxprop;
+        }
+        else resvprop = 0;
+
+        /* Initialize property list structure */
+        plist->pl_mempool = mempool;
+        plist->pl_symtab = NULL;
+        plist->pl_maxprop = maxprop;
+        plist->pl_resvpi = resvprop;
+        plist->pl_initpi = resvprop;
+        plist->pl_lastpi = resvprop;
+
+        /* Set initialize size for array of property value pointers */
+        plist->pl_cursize = (resvprop) ? resvprop : PLIST_DEFSIZE;
+
+        /* Allocate the initial array of property value pointers */
+        plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
+                                   	           (plist->pl_cursize *
+                                                    sizeof(PLValueStruct_t *)));
+        if (!plist->pl_ppval) {
+
+            /* Failed - insufficient memory */
+            pool_free(mempool, (void *)plist);
+            plist = NULL;
+        }
+        else {
+            /* NULL out pointers in the reserved index range, if any */
+            for (i = 0; i < plist->pl_lastpi; ++i) {
+                plist->pl_ppval[i] = 0;
+            }
+        }
+    }
+
+    return (PList_t)plist;
+}
+
+/*
+ * FUNCTION:    PListDefProp
+ *
+ * DESCRIPTION:
+ *
+ *      This function creates a new property in a specified property list.
+ *      The 'pindex' argument may be used to request a particular property
+ *      index for the new property.  If 'pindex' is greater than zero,
+ *      the specified value is used as the new property's index, provided
+ *      there is no property at that index already.  If 'pindex' is zero,
+ *      then the next available property index is assigned to the new
+ *      property.  A name may optionally be specified for the new property.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - new property index (or zero)
+ *      pname                   - new property name (or NULL)
+ *
+ * RETURNS:
+ *
+ *      If successful, the index of the new property is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListDefProp(PList_t plist, int pindex, const char *pname, const int flags)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t *pv;
+
+    if (!plist) return ERRPLUNDEF;
+
+    /* Is pindex specified? */
+    if (pindex > 0) {
+
+        /* Yes, is it in the reserved range? */
+        if (flags != PLFLG_IGN_RES && pindex > pl->pl_resvpi) {
+            /* No, error */
+            return ERRPLINVPI;
+        }
+
+        PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
+        if (ppval[pindex - 1]) {
+            /* Error - property already exists at specified index */
+            return ERRPLEXIST;
+        }
+    }
+    else {
+
+        /* Look for a free property index */
+        pindex = PListGetFreeIndex(pl);
+        if (pindex < 1) {
+            /* Error - no free property index */
+            return pindex;
+        }
+    }
+
+    /* We have a property index.  Create a new property value */
+    pv = (PLValueStruct_t *)pool_calloc(pl->pl_mempool,
+                                        1, sizeof(PLValueStruct_t));
+    if (!pv) {
+
+        /* Error - insufficient memory */
+        return ERRPLNOMEM;
+    }
+
+    PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
+    pv->pv_pbentry.param = &pv->pv_pbparam;
+    pv->pv_pi = pindex;
+    pv->pv_mempool = pl->pl_mempool;
+    ppval[pindex - 1] = pv;
+
+    /* Name the property if the name was specified */
+    if (pname) {
+
+        /* XXX Maybe should delete property if naming fails */
+        return PListNameProp(plist, pindex, pname);
+    }
+
+    /* Return the property index of the new property */
+    return pindex;
+}
+
+/*
+ * FUNCTION:    PListDeleteProp
+ *
+ * DESCRIPTION:
+ *
+ *      This function deletes a property from a specified property list.
+ *      The property can be specified by its property index, using a
+ *      pindex value greater than zero, or by its name, by specifying
+ *      pindex as zero and pname as the property name.  This does not
+ *      have any effect on the data referenced by the property value,
+ *      if any, nor does it have any effect on the property list that
+ *      describes the property value's type, if any.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - the property index, or zero
+ *      pname                   - the property name, or NULL
+ */
+
+NSAPI_PUBLIC const void *
+PListDeleteProp(PList_t plist, int pindex, const char *pname_in)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t **pvp;
+    PLValueStruct_t *pv = NULL;
+    int i;
+    const void *pvalue = NULL;
+    char *pname = (char *)pname_in;
+
+    if (!plist) return NULL;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Check for valid property index */
+    if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+        /* Get the pointer to the property structure */
+        pv = ppval[pindex - 1];
+	pname = 0;
+	if (pv) {
+	    pname = pv->pv_name;
+	}
+    }
+
+    if (pname && pl->pl_symtab) {
+
+        /* Compute hash of specified property name */
+        i = PListHashName(pl->pl_symtab, pname);
+
+        /* Search hash collision list for matching name */
+        for (pvp = &pl->pl_symtab->pt_hash[i]; *pvp; pvp = &(*pvp)->pv_next) {
+
+            pv = *pvp;
+            if (!strcmp(pname, pv->pv_name)) {
+
+                /* Found it.  Get its index and remove it. */
+                pindex = pv->pv_pi;
+                *pvp = pv->pv_next;
+                pl->pl_symtab->pt_nsyms--;
+                break;
+            }
+            pv = NULL;
+        }
+    }
+
+    /* Found the indicated property by index or name? */
+    if (pv) {
+
+        /* Yes, remove it from the property list */
+        ppval[pindex - 1] = NULL;
+
+        /* Free the property name, if any */
+        if (pv->pv_name) {
+            pool_free(pv->pv_mempool, (void *)(pv->pv_name));
+        }
+        pvalue = pv->pv_value;
+
+        /* Free the property */
+        pool_free(pv->pv_mempool, (void *)pv);
+    }
+    return(pvalue);
+}
+
+/*
+ * FUNCTION:    PListFindValue
+ *
+ * DESCRIPTION:
+ *
+ *      This function retrieves the value and type of a property with a
+ *      specified property name.  If the pvalue argument is non-NULL,
+ *      it specifies a location in which to return the property value.
+ *      Similarly, if ptype is non-NULL, it specifies where the property
+ *      list describing the property type is to be returned.  If a
+ *      property has no value, the value returned for pvalue is NULL.
+ *      If a property has no type, the value returned for ptype is NULL.
+ *      A property can have a value, a type, both, or neither.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pname                   - pointer to property name string
+ *      pvalue                  - property value return pointer
+ *      ptype                   - property type return pointer
+ *
+ * RETURNS:
+ *
+ *      If successful, the index of the referenced property is returned
+ *      as the function value.  Errors are indicated by a negative
+ *      return code as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListFindValue(PList_t plist, const char *pname, void **pvalue, PList_t *ptype)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t *pv;
+    int pindex;
+    int i;
+
+    if (!plist) return ERRPLUNDEF;
+
+    /* Got a symbol table for this property list? */
+    if (pl->pl_symtab) {
+
+        /* Yes, compute hash of specified name */
+        i = PListHashName(pl->pl_symtab, pname);
+
+        /* Search hash collision list for matching name */
+        for (pv = pl->pl_symtab->pt_hash[i]; pv; pv = pv->pv_next) {
+
+            if (!strcmp(pname, pv->pv_name)) {
+
+                /* Name match, get property index */
+                pindex = pv->pv_pi;
+
+                /* Return the value if requested */
+                if (pvalue) *pvalue = (void *)(pv->pv_value);
+
+                /* Return the type if requested */
+                if (ptype) *ptype = (PList_t)(pv->pv_type);
+
+                /* Return the property index */
+                return pindex;
+            }
+        }
+    }
+
+    /* Error - specified property name is undefined */
+    return ERRPLUNDEF;
+}
+
+/*
+ * FUNCTION:    PListInitProp
+ *
+ * DESCRIPTION:
+ *
+ *      This function combines the functions of PListDefProp() and
+ *      PListSetValue(), defining a new property and assigning it an
+ *      initial value and optionally a type and/or a name.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - a reserved property index, or zero
+ *      pname                   - the new property name, or NULL
+ *      pvalue                  - the new property value
+ *      ptype                   - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ *      If successful, the property index (pindex) is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListInitProp(PList_t plist, int pindex, const char *pname,
+              const void *pvalue, PList_t ptype)
+{
+    int rv;
+
+    if (!plist) return ERRPLUNDEF;
+
+    /* Create the property */
+    rv = PListDefProp(plist, pindex, pname, PLFLG_USE_RES);
+    if (rv > 0) {
+
+        /* If that worked, set the value and type */
+        rv = PListSetValue(plist, rv, pvalue, ptype);
+    }
+
+    return rv;
+}
+
+/*
+ * FUNCTION:    PListNew
+ *
+ * DESCRIPTION:
+ *
+ *      This function creates a new property list, using the specified
+ *      memory pool for allocating the internal data structures used to
+ *      represent it.  If the mempool argument is NULL, the default
+ *      memory pool is used.
+ *
+ * ARGUMENTS:
+ *
+ *      mempool                 - handle for a memory pool to be associated
+ *                                with the new property list
+ *
+ * RETURNS:
+ *
+ *      If successful, the function return value is a handle for the new
+ *      property list.  Otherwise NULL is returned.
+ */
+
+NSAPI_PUBLIC PList_t
+PListNew(pool_handle_t *mempool)
+{
+    /* Just call PListCreate with default parameters */
+    return PListCreate(mempool, 0, 0, 0);
+}
+
+/*
+ * FUNCTION:    PListDestroy
+ *
+ * DESCRIPTION:
+ *
+ *      This function destroys a specified property list.  This means
+ *      that any dynamic memory which was allocated as a result of calls
+ *      to the property list API is freed to the memory pool from which
+ *      it was allocated.  Property value data is not freed, nor are
+ *      any property lists associated with property types.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ */
+
+void
+PListDestroy(PList_t plist)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int i;
+
+    if (!plist) return;
+
+    /* Free the property name symbol table if any */
+    if (pl->pl_symtab) {
+        pool_free(pl->pl_mempool, (void *)(pl->pl_symtab));
+    }
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Loop over the initialized property indices */
+    for (i = 0; i < pl->pl_initpi; ++i) {
+
+        /* Got a property here? */
+        pv = ppval[i];
+        if (pv) {
+
+            /* Free the property name string if any */
+            if (pv->pv_name) {
+                pool_free(pv->pv_mempool, (void *)(pv->pv_name));
+            }
+
+            /* Free the property value structure */
+            pool_free(pv->pv_mempool, (void *)pv);
+        }
+    }
+
+    /* Free the array of pointers to property values */
+    pool_free(pl->pl_mempool, (void *)ppval);
+
+    /* Free the property list head */
+    pool_free(pl->pl_mempool, (void *)pl);
+}
+
+/*
+ * FUNCTION:    PListGetValue
+ *
+ * DESCRIPTION:
+ *
+ *      This function retrieves the value and type of the property with
+ *      the property index given by pindex in the specified property
+ *      list.  The pindex argument must specify the index of a defined
+ *      property.  If the pvalue argument is non-NULL, it specifies a
+ *      location in which to return the property value.  Similarly, if
+ *      ptype is non-NULL, it specifies where the property list
+ *      describing the property type is to be returned.  If a property
+ *      has no value, the value returned for pvalue is NULL.  If a
+ *      property has no type, the value returned for ptype is NULL. A
+ *      property can have a value, a type, both, or neither.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - the property index
+ *      pvalue                  - property value return pointer
+ *      ptype                   - property type return pointer
+ *
+ * RETURNS:
+ *
+ *      If successful, the property index (pindex) is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListGetValue(PList_t plist, int pindex, void **pvalue, PList_t *ptype)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+
+    if (!plist) return ERRPLUNDEF;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Check for valid property index */
+    if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+        /* Does the property exist? */
+        pv = ppval[pindex - 1];
+        if (pv) {
+
+            /* Yes, return the value if requested */
+            if (pvalue) *pvalue = (void *)(pv->pv_value);
+
+            /* Return the type if requested */
+            if (ptype) *ptype = (PList_t)(pv->pv_type);
+
+            /* Successful return */
+            return pindex;
+        }
+    }
+
+    /* Error - invalid property index or non-existent property */
+    return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION:    PListHash
+ *
+ * DESCRIPTION:
+ *
+ *      This function hashes a given string.
+ *
+ * ARGUMENTS:
+ *
+ *      string                  - pointer to the string to hash
+ *
+ * RETURNS:
+ *
+ *      The hash value is returned as the function value.
+ */
+
+unsigned int
+PListHash(const char *string)
+{
+    unsigned int hashval = 0;           /* hash value */
+
+    while (*string) {
+        hashval = (hashval<<5) ^ (*string++ & 0x7f);
+    }
+
+    return hashval;
+}
+
+/*
+ * FUNCTION:    PListHashName
+ *
+ * DESCRIPTION:
+ *
+ *      This function hashes a given property name for a specified
+ *      symbol table.  It produces a value that can be used as an
+ *      index in the pt_hash array associated with the symbol table.
+ *
+ * ARGUMENTS:
+ *
+ *      symtab                  - pointer to the symbol table
+ *      pname                   - pointer to the property name string
+ *
+ * RETURNS:
+ *
+ *      The hash index is returned as the function value.
+ */
+
+int
+PListHashName(PLSymbolTable_t *symtab, const char *pname)
+{
+    return PListHash(pname) % PLSIZENDX(symtab->pt_sizendx);
+}
+
+/*
+ * FUNCTION:    PListNameProp
+ *
+ * DESCRIPTION:
+ *
+ *      This function assigns a name to a defined property with the
+ *      property index, pindex.  If the property has an existing name,
+ *      it will be replaced with the name specified by pname.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - the property index
+ *      pname                   - the new property name
+ *
+ * RETURNS:
+ *
+ *      If successful, the property index (pindex) is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListNameProp(PList_t plist, int pindex, const char *pname)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t *pv;
+    PLSymbolTable_t *pt;
+    int i;
+
+    if (!plist) return ERRPLUNDEF;
+
+    pt = pl->pl_symtab;
+
+    /* Check for valid property index */
+    if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+        /* Does the property exist? */
+        pv = ((PLValueStruct_t **)(pl->pl_ppval))[pindex - 1];
+        if (pv) {
+
+            /* If it has a name already, unname it */
+            if (pv->pv_name) {
+                PLValueStruct_t **pvp;
+
+                /* Get hash bucket index */
+                i = PListHashName(pt, pv->pv_name);
+
+                /* Seach hash collision list for this property */
+                for (pvp = &pt->pt_hash[i];
+                     *pvp; pvp = &(*pvp)->pv_next) {
+
+                    if (*pvp == pv) {
+
+                        /* Remove it from the list */
+                        *pvp = pv->pv_next;
+                        pt->pt_nsyms--;
+                        break;
+                    }
+                }
+
+                /* Free the current name string */
+                pool_free(pv->pv_mempool, (void *)(pv->pv_name));
+            }
+
+            /* Got a new name? */
+            if (pname) {
+
+                /* Allocate/grow the symbol table as needed */
+                pt = PListSymbolTable(pl);
+                if (!pt) {
+                    return ERRPLNOMEM;
+                }
+
+                /* Duplicate the name string */
+                pv->pv_name = pool_strdup(pv->pv_mempool, (char *)pname);
+
+                /* Add name to symbol table */
+                i = PListHashName(pt, pname);
+                pv->pv_next = pt->pt_hash[i];
+                pt->pt_hash[i] = pv;
+                pt->pt_nsyms++;
+            }
+
+            /* Successful return */
+            return pindex;
+        }
+    }
+
+    /* Error - invalid property index or non-existent property */
+    return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION:    PListSetType
+ *
+ * DESCRIPTION:
+ *
+ *      This function sets the property type of the defined property
+ *      with the property index, pindex.  The property list describing
+ *      the property type is specified by ptype.  If ptype is NULL,
+ *      the property type will be set to be undefined (NULL).
+ *
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - the property index
+ *      ptype                   - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ *      If successful, the property index (pindex) is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListSetType(PList_t plist, int pindex, PList_t ptype)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+
+    if (!plist) return ERRPLUNDEF;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Check for valid property index */
+    if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+        /* Does the property exist? */
+        pv = ppval[pindex - 1];
+        if (pv) {
+
+            /* Yes, set the new type */
+            pv->pv_type = ptype;
+
+            /* Successful return */
+            return pindex;
+        }
+    }
+
+    /* Error - invalid property index or non-existent property */
+    return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION:    PListSetValue
+ *
+ * DESCRIPTION:
+ *
+ *      This function sets the value and optionally the type of a
+ *      defined property in a given property list.  The pindex argument
+ *      specifies the property index, which must be greater than zero.
+ *      The ptype argument specifies a property list that describes the
+ *      property type.  If ptype is NULL, the property type, if any, is
+ *      unchanged by this function.  However, the property value is
+ *      always set to the value given by pvalue.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      pindex                  - the property index
+ *      pvalue                  - the new property value
+ *      ptype                   - the new property type, or NULL
+ *
+ * RETURNS:
+ *
+ *      If successful, the property index (pindex) is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+NSAPI_PUBLIC int
+PListSetValue(PList_t plist, int pindex, const void *pvalue, PList_t ptype)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+
+    if (!plist) return ERRPLUNDEF;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Check for valid property index */
+    if ((pindex > 0) && (pindex <= pl->pl_initpi)) {
+
+        /* Does the property exist? */
+        pv = ppval[pindex - 1];
+        if (pv) {
+
+            /* Yes, set the new value */
+            pv->pv_value = (char *)pvalue;
+
+            /* Set type if type is given */
+            if (ptype) pv->pv_type = (PListStruct_t *)ptype;
+
+            /* Successful return */
+            return pindex;
+        }
+    }
+
+    /* Error - invalid property index or non-existent property */
+    return ERRPLINVPI;
+}
+
+/*
+ * FUNCTION:    PListEnumerate
+ *
+ * DESCRIPTION:
+ *
+ *      This function walks through a specified property list
+ *	calling a user supplied function with the property
+ *	name and value as parameters.  
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      user_func               - handle for the user function 
+ */
+
+NSAPI_PUBLIC void
+PListEnumerate(PList_t plist, PListFunc_t *user_func, void *user_data)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int i;
+
+    if (!plist) return;
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Loop over the initialized property indices */
+    for (i = 0; i < pl->pl_initpi; ++i) {
+
+        /* Got a property here? */
+        pv = ppval[i];
+        if (pv) {
+            (*user_func)(pv->pv_name, pv->pv_value, user_data);
+        }
+
+    }
+
+}
+
+/*
+ * FUNCTION:    PListCreateDuplicate
+ *
+ * DESCRIPTION:
+ *
+ *      This function creates a new property list and returns a handle for
+ *      it.  The source plist provides the new plists parameters.
+ *
+ * ARGUMENTS:
+ *
+ *	src_plist		- source plist to duplicate
+ *      mempool                 - handle for a memory pool to be associated
+ *                                with the new property list, only
+ *				  used if flags is set to PLFLG_NEW_MPOOL
+ *      flags                   - if PLFLG_NEW_MPOOL uses new_mempool
+ *				  parameter
+ *
+ * RETURNS:
+ *
+ *      If successful, the function return value is a handle for the new
+ *      property list.  Otherwise NULL is returned.
+ */
+
+static PList_t
+PListCreateDuplicate(PList_t src_plist, pool_handle_t *new_mempool, int flags)
+{
+    PListStruct_t *plist;       /* pointer to property list structure */
+    int i;
+    pool_handle_t *mempool;
+
+    mempool = (flags == PLFLG_NEW_MPOOL) ? new_mempool : src_plist->pl_mempool;
+
+    plist = (PListStruct_t *)pool_malloc(mempool, sizeof(PListStruct_t));
+    if (plist) {
+
+        /* Initialize property list structure */
+        plist->pl_mempool = mempool;
+        plist->pl_symtab = NULL;
+        plist->pl_maxprop = src_plist->pl_maxprop;
+        plist->pl_resvpi = src_plist->pl_resvpi;
+        plist->pl_initpi = src_plist->pl_initpi;
+        plist->pl_lastpi = src_plist->pl_lastpi;
+
+        /* Set initialize size for array of property value pointers */
+        plist->pl_cursize = src_plist->pl_cursize; 
+
+        /* Allocate the initial array of property value pointers */
+        plist->pl_ppval = (pb_entry **)pool_malloc(mempool,
+                                                   (plist->pl_cursize *
+                                                    sizeof(PLValueStruct_t *)));
+        if (!plist->pl_ppval) {
+
+            /* Failed - insufficient memory */
+            pool_free(mempool, (void *)plist);
+            plist = NULL;
+        }
+        else {
+            /* NULL out pointers in the reserved index range, if any */
+            for (i = 0; i < plist->pl_lastpi; ++i) {
+                plist->pl_ppval[i] = 0;
+            }
+        }
+    }
+
+    return (PList_t)plist;
+}
+
+
+/*
+ * FUNCTION:    PListDuplicate
+ *
+ * DESCRIPTION:
+ *
+ *      This function duplicates a specified PList_t.  
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *      mempool                 - handle for a memory pool to be associated
+ *                                with the new property list
+ *      resvprop                - number of reserved property indices
+ *      maxprop                 - maximum number of properties in list
+ *                                (zero or negative imposes no limit)
+ *      flags                   - unused, reserved, must be zero
+ *
+ * RETURNS:
+ *
+ *      If successful, the function return value is a handle for the new
+ *      property list.  Otherwise NULL is returned.
+ */
+
+NSAPI_PUBLIC PList_t
+PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags)
+{
+    PListStruct_t *pl = (PListStruct_t *)plist;
+    PLValueStruct_t **ppval;
+    PLValueStruct_t *pv;
+    int i;
+    int rv = 0;
+    PList_t new_plist;
+
+    if (!plist) return NULL;
+
+    new_plist = PListCreateDuplicate(plist, new_mempool, flags);
+    if (new_plist == NULL) {
+        return(NULL);
+    }
+
+    ppval = (PLValueStruct_t **)(pl->pl_ppval);
+
+    /* Loop over the initialized property indices */
+    for (i = 0; i < pl->pl_initpi; ++i) {
+
+        /* Got a property here? */
+        pv = ppval[i];
+        if (pv) {
+            /* Create the property */
+            rv = PListDefProp(new_plist, i + 1, pv->pv_name, PLFLG_IGN_RES);
+            if (rv > 0) {
+        
+                /* If that worked, set the value and type */
+                rv = PListSetValue(new_plist, rv, pv->pv_value, pv->pv_type);
+            }
+        
+            if ( rv <= 0 ) {
+                PListDestroy(new_plist);
+                return(NULL);
+            }
+        }
+
+    }
+
+    return(new_plist);
+}
+
+/*
+ * FUNCTION:    PListGetPool
+ *
+ * DESCRIPTION:
+ *
+ *      This function returns the memory pool the PList is allocated from.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *
+ * RETURNS:
+ *
+ *      The memory pool address, which can be NULL.
+ */
+
+NSAPI_PUBLIC pool_handle_t *
+PListGetPool(PList_t plist)
+{
+    if (!plist) return NULL;
+
+    return(plist->pl_mempool);
+}
+
+/*
+ * FUNCTION:    PListGetFreeIndex
+ *
+ * DESCRIPTION:
+ *
+ *      This function returns an available property index.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *
+ * RETURNS:
+ *
+ *      If successful, an available property index is returned as the
+ *      function value.  Errors are indicated by a negative return code
+ *      as defined in plist.h.
+ */
+
+int
+PListGetFreeIndex(PListStruct_t *pl)
+{
+    PLValueStruct_t **ppval = (PLValueStruct_t **)(pl->pl_ppval);
+    int wrapped;
+    int i;
+
+    /*
+     * Look for a free property index, starting at pl_lastpi + 1.
+     * (Note that i is the property index - 1)
+     */
+    for (wrapped = 0, i = pl->pl_lastpi; ;) {
+
+        /* Are we in an initialized part of the array? */
+        if (i < pl->pl_initpi) {
+
+            /* Yes, use this index if it's free */
+            if (ppval[i] == 0) break;
+
+            /* Otherwise step to the next one */
+            ++i;
+        }
+        else {
+
+            /* Have we reached the end yet? */
+            if (i < pl->pl_cursize) {
+
+                /*
+                 * We are above the highest initialized index, but
+                 * still within the allocated size.  An index in
+                 * this range can be used with no further checks.
+                 */
+                ppval[i] = 0;
+            }
+            else {
+
+                /*
+                 * It's looking like time to grow the array, but
+                 * first go back and look for an unused, unreserved
+                 * index that might have been freed.
+                 */
+                if (!wrapped) {
+
+                    i = pl->pl_resvpi;
+                    wrapped = 1;
+                    continue;
+                }
+
+                /*
+                 * Grow the array unless there is a specified maximum
+                 * size and we've reached it.
+                 */
+                i = pl->pl_cursize;
+                if (pl->pl_maxprop && (i > pl->pl_maxprop)) {
+
+                    /* Error - property list is full */
+                    return ERRPLFULL;
+                }
+
+                /* Increase planned size of list */
+                int cursize = i + PLIST_DEFGROW;
+
+                /* Reallocate the array of property value pointers */
+                ppval = (PLValueStruct_t **)pool_realloc(pl->pl_mempool,
+                                   (void *)ppval,
+                                   (cursize * sizeof(PLValueStruct_t *)));
+                if (!ppval) {
+
+                    /* Error - insufficient memory */
+                    return ERRPLNOMEM;
+                }
+
+                /* Initialize the first new entry and select it */
+                ppval[i] = NULL;
+                pl->pl_ppval = (pb_entry **)ppval;
+                pl->pl_cursize = cursize;
+            }
+
+            /* Update the highest initialized index value */
+            pl->pl_initpi = i + 1;
+            break;
+        }
+    }
+
+    /* Set the starting point for the next allocation */
+    pl->pl_lastpi = i + 1;
+
+    return i + 1;
+}
+
+/*
+ * FUNCTION:    PListSymbolTable
+ *
+ * DESCRIPTION:
+ *
+ *      This function allocates or grows a property list's symbol table as
+ *      needed.
+ *
+ * ARGUMENTS:
+ *
+ *      plist                   - handle for the property list
+ *
+ * RETURNS:
+ *
+ *      If successful, a pointer to the symbol table is returned as the
+ *      function value.  Errors are indicated by a NULL return code.
+ */
+
+PLSymbolTable_t *
+PListSymbolTable(PListStruct_t *pl)
+{
+    PLSymbolTable_t *pt;
+    int i;
+
+    pt = pl->pl_symtab;
+
+    /* Is there a hash table? */
+    if (!pl->pl_symtab) {
+
+        /* No, create one */
+        pt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1, PLHASHSIZE(0));
+
+        pl->pl_symtab = pt;
+    }
+    else {
+
+        /* Is it time to grow the hash table? */
+        i = PLSIZENDX(pt->pt_sizendx);
+        if ((pt->pt_sizendx < PLMAXSIZENDX) && pt->pt_nsyms >= (i + i)) {
+
+            PLSymbolTable_t *npt;
+
+            /* Yes, allocate the new table */
+            npt = (PLSymbolTable_t *)pool_calloc(pl->pl_mempool, 1,
+                                                 PLHASHSIZE(pt->pt_sizendx+1));
+            if (npt) {
+                npt->pt_sizendx = pt->pt_sizendx + 1;
+                npt->pt_nsyms = pt->pt_nsyms;
+
+                /* Rehash all the names into the new table, preserving order */
+                for (i = 0; i < PLSIZENDX(pt->pt_sizendx); ++i) {
+                    /* While there are names at this hash index... */
+                    while (pt->pt_hash[i]) {
+                        PLValueStruct_t **pvp;
+                        int j;
+
+                        /* Find the last name at this hash index */
+                        for (pvp = &pt->pt_hash[i]; (*pvp)->pv_next; pvp = &(*pvp)->pv_next);
+                        
+                        /* Move the name to the new table */
+                        j = PListHashName(npt, (*pvp)->pv_name);
+                        (*pvp)->pv_next = npt->pt_hash[j];
+                        npt->pt_hash[j] = (*pvp);
+
+                        /* Remove the name from the old table */
+                        *pvp = NULL;
+                    }
+                }
+
+                pl->pl_symtab = npt;
+
+                /* Free the old symbol table */
+                pool_free(pl->pl_mempool, (void *)pt);
+                pt = npt;
+            }
+        }
+    }
+
+    return pl->pl_symtab;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/plist.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,94 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PLIST_H
+#define _PLIST_H
+
+#ifndef NOINTNSACL
+#define INTNSACL
+#endif /* !NOINTNSACL */
+
+/*
+ * TYPE:        PList_t
+ *
+ * DESCRIPTION:
+ *
+ *      This type defines a handle for a property list.
+ */
+
+#include "pool.h"
+#include "mps/nspr.h"
+#include "nsapi.h"
+#include "plist_pvt.h"
+
+#ifndef PUBLIC_NSACL_PLISTDEF_H
+#include "plistdef.h"
+#endif /* !PUBLIC_NSACL_PLISTDEF_H */
+
+#ifdef INTNSACL
+
+/* Functions in plist.c */
+NSPR_BEGIN_EXTERN_C
+
+NSAPI_PUBLIC extern int PListAssignValue(PList_t plist, const char *pname,
+                            const void *pvalue, PList_t ptype);
+NSAPI_PUBLIC extern PList_t PListCreate(pool_handle_t *mempool,
+                           int resvprop, int maxprop, int flags);
+NSAPI_PUBLIC extern int PListDefProp(PList_t plist, int pindex, 
+                        const char *pname, const int flags);
+NSAPI_PUBLIC extern const void * PListDeleteProp(PList_t plist, int pindex, const char *pname);
+NSAPI_PUBLIC extern int PListFindValue(PList_t plist,
+                          const char *pname, void **pvalue, PList_t *type);
+NSAPI_PUBLIC extern int PListInitProp(PList_t plist, int pindex, const char *pname,
+                         const void *pvalue, PList_t ptype);
+NSAPI_PUBLIC extern PList_t PListNew(pool_handle_t *mempool);
+NSAPI_PUBLIC extern void PListDestroy(PList_t plist);
+NSAPI_PUBLIC extern int PListGetValue(PList_t plist,
+                         int pindex, void **pvalue, PList_t *type);
+NSAPI_PUBLIC extern int PListNameProp(PList_t plist, int pindex, const char *pname);
+NSAPI_PUBLIC extern int PListSetType(PList_t plist, int pindex, PList_t type);
+NSAPI_PUBLIC extern int PListSetValue(PList_t plist,
+                         int pindex, const void *pvalue, PList_t type);
+NSAPI_PUBLIC extern void PListEnumerate(PList_t plist, PListFunc_t *user_func, 
+                           void *user_data);
+NSAPI_PUBLIC extern PList_t
+PListDuplicate(PList_t plist, pool_handle_t *new_mempool, int flags);
+NSAPI_PUBLIC extern pool_handle_t *PListGetPool(PList_t plist);
+NSAPI_PUBLIC extern int PListDefKey(PList_t plist, pb_key *key, const char *pname, const int flags);
+NSAPI_PUBLIC extern int PListInitKey(PList_t plist, pb_key *key, const void *pvalue, PList_t ptype);
+
+NSPR_END_EXTERN_C
+
+#endif /* INTNSACL */
+
+#endif /* _PLIST_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/plist_pvt.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,162 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _PLIST_PVT_H
+#define _PLIST_PVT_H
+
+/*
+ * FILE:        plist_pvt.h
+ *
+ * DESCRIPTION:
+ *
+ *      This file contains private definitions for the property list
+ *      utility implementation.
+ */
+
+#include "nsapi.h"
+#include "pool.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declarations */
+typedef struct PLValueStruct_s PLValueStruct_t;
+typedef struct PLSymbol_s PLSymbol_t;
+typedef struct PLSymbolTable_s PLSymbolTable_t;
+typedef struct PListStruct_s PListStruct_t;
+
+/*
+ * TYPE:        PLValueStruct_t
+ *
+ * DESCRIPTION:
+ *
+ *      This type represents a property value. It is dynamically
+ *      allocated when a new property is added to a property list.
+ *      It contains a reference to a property list that contains
+ *      information about the property value, and a reference to
+ *      the property value data.
+ */
+
+#ifndef PBLOCK_H
+#include "pblock.h"
+#endif /* PBLOCK_H */
+
+struct PLValueStruct_s {
+    pb_entry pv_pbentry;	/* used for pblock compatibility */
+    pb_param pv_pbparam;	/* property name and value pointers */
+    const pb_key *pv_pbkey;     /* property pb_key pointer (optional) */
+    PLValueStruct_t *pv_next;   /* property name hash collision link */
+    PListStruct_t *pv_type;     /* property value type reference */
+    int pv_pi;                  /* property index */
+    pool_handle_t *pv_mempool;  /* pool we were allocated from */
+};
+
+#define pv_name pv_pbparam.name
+#define pv_value pv_pbparam.value
+
+/* Offset to pv_pbparam in PLValueStruct_t */
+#define PVPBOFFSET ((char *)&((PLValueStruct_t *)0)->pv_pbparam)
+
+/* Convert pb_param pointer to PLValueStruct_t pointer */
+#define PATOPV(p) ((PLValueStruct_t *)((char *)(p) - PVPBOFFSET))
+
+/*
+ * TYPE:        PLSymbolTable_t
+ *
+ * DESCRIPTION:
+ *
+ *      This type represents a symbol table that maps property names
+ *      to properties.  It is dynamically allocated the first time a
+ *      property is named.
+ */
+
+#define PLSTSIZES       {7, 19, 31, 67, 123, 257, 513}
+#define PLMAXSIZENDX    (sizeof(plistHashSizes)/sizeof(plistHashSizes[0]) - 1)
+
+struct PLSymbolTable_s {
+    int pt_sizendx;             /* pt_hash size, as an index in PLSTSIZES */
+    int pt_nsyms;               /* number of symbols in table */
+    PLValueStruct_t *pt_hash[1];/* variable-length array */
+};
+
+/*
+ * TYPE:        PListStruct_t
+ *
+ * DESCRIPTION:
+ *
+ *      This type represents the top-level of a property list structure.
+ *      It is dynamically allocated when a property list is created, and
+ *      freed when the property list is destroyed.  It references a
+ *      dynamically allocated array of pointers to property value
+ *      structures (PLValueStruct_t).
+ */
+
+#define PLIST_DEFSIZE   8       /* default initial entries in pl_ppval */
+#define PLIST_DEFGROW   16      /* default incremental entries for pl_ppval */
+
+struct PListStruct_s {
+    pblock pl_pb;		/* pblock subset of property list head */
+    PLSymbolTable_t *pl_symtab; /* property name to index symbol table */
+    pool_handle_t *pl_mempool;  /* associated memory pool handle */
+    int pl_maxprop;             /* maximum number of properties */
+    int pl_resvpi;              /* number of reserved property indices */
+    int pl_lastpi;              /* last allocated property index */
+    int pl_cursize;             /* current size of pl_ppval in entries */
+};
+
+#define pl_initpi pl_pb.hsize    /* number of pl_ppval entries initialized */
+#define pl_ppval pl_pb.ht	/* pointer to array of value pointers */
+
+/* Convert pblock pointer to PListStruct_t pointer */
+#define PBTOPL(p) ((PListStruct_t *)(p))
+
+#define PLSIZENDX(i) (plistHashSizes[i])
+#define PLHASHSIZE(i) (sizeof(PLSymbolTable_t) + \
+                       (PLSIZENDX(i) - 1)*sizeof(PLValueStruct_t *))
+
+extern int plistHashSizes[7];
+
+unsigned int PListHash(const char *string);
+
+int PListHashName(PLSymbolTable_t *symtab, const char *pname);
+
+int PListGetFreeIndex(PListStruct_t *pl);
+
+PLSymbolTable_t *PListSymbolTable(PListStruct_t *pl);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* _PLIST_PVT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/plistdef.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,77 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PUBLIC_NSACL_PLISTDEF_H
+#define PUBLIC_NSACL_PLISTDEF_H
+
+/*
+ * File:        plistdef.h
+ *
+ * Description:
+ *
+ *      This file defines the interface to property lists.  Property
+ *      lists are a generalization of parameter blocks (pblocks).
+ */
+
+#ifndef PUBLIC_NSAPI_H
+#include "nsapi.h"
+#endif /* !PUBLIC_NSAPI_H */
+
+typedef struct PListStruct_s *PList_t;
+
+/* Define error codes returned from property list routines */
+
+#define ERRPLINVPI      -1      /* invalid property index */
+#define ERRPLEXIST      -2      /* property already exists */
+#define ERRPLFULL       -3      /* property list is full */
+#define ERRPLNOMEM      -4      /* insufficient dynamic memory */
+#define ERRPLUNDEF      -5      /* undefined property name */
+
+#define PLFLG_OLD_MPOOL	0	/* use the plist memory pool */
+#define PLFLG_NEW_MPOOL	1	/* use the input memory pool */
+#define PLFLG_IGN_RES	2	/* ignore the reserved properties */
+#define PLFLG_USE_RES	3	/* use the reserved properties */
+
+#ifdef __cplusplus
+typedef void (PListFunc_t)(char*, const void*, void*);
+#else
+typedef void (PListFunc_t)();
+#endif
+
+#ifndef INTNSACL
+
+
+
+#endif /* !INTNSACL */
+
+#endif /* !PUBLIC_NSACL_PLISTDEF_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/pool.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,699 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Generic pool handling routines.
+ *
+ * These routines reduce contention on the heap and guard against
+ * memory leaks.
+ *
+ * Thread warning:
+ *     This implementation is thread safe.  However, simultaneous 
+ *     mallocs/frees to the same "pool" are not safe.  Do not share
+ *     pools across multiple threads without providing your own
+ *     synchronization.
+ *
+ * Mike Belshe
+ * 11-20-95
+ *
+ */
+
+//include "netsite.h"
+//include "systems.h"
+#include "systhr.h"
+#include "pool_pvt.h"
+#include "ereport.h"
+//include "base/session.h"
+//include "frame/req.h"
+//include "frame/http.h"
+#include "util.h"
+//include "base/crit.h"
+
+//include "base/dbtbase.h"
+
+
+
+#include <stdlib.h>
+#include <string.h>
+//define PERM_MALLOC   malloc
+//define PERM_FREE     free
+//define PERM_REALLOC  realloc
+//define PERM_CALLOC   calloc
+//define PERM_STRDUP   strdup
+
+/* Pool configuration parameters */
+static pool_config_t pool_config = POOL_CONFIG_INIT;
+
+/* Pool global statistics */
+static pool_global_stats_t pool_global_stats;
+
+static int 
+pool_internal_init()
+{
+    if (pool_global_stats.lock == NULL) {
+        pool_global_stats.lock = PR_NewLock();
+    }
+
+    if (pool_config.block_size == 0) {
+        //ereport(LOG_INFORM, XP_GetAdminStr(DBT_poolInitInternalAllocatorDisabled_));
+    }
+
+    return 0;
+}
+
+NSAPI_PUBLIC int
+pool_init(pblock *pb, Session *sn, Request *rq)
+{
+    //char *str_block_size = pblock_findval("block-size", pb);
+    //char *str_pool_disable = pblock_findval("disable", pb);
+    char *str_block_size = "16384";
+    char *str_pool_disable = "false";
+    int n;
+
+    //printf("standard block size: %d\n", pool_config.block_size);
+
+    if (str_block_size != NULL) {
+        n = atoi(str_block_size);
+        if (n > 0)
+            pool_config.block_size = n;
+    }
+
+    if (str_pool_disable && util_getboolean(str_pool_disable, PR_TRUE)) {
+        /* We'll call PERM_MALLOC() on each pool_malloc() call */
+        pool_config.block_size = 0;
+        pool_config.retain_size = 0;
+        pool_config.retain_num = 0;
+    }
+
+    pool_internal_init();
+
+    return REQ_PROCEED;
+}
+
+static block_t *
+_create_block(pool_t *pool, int size)
+{
+    block_t *newblock;
+    char *newdata;
+    block_t **blk_ptr;
+    long blen;
+
+    /* Does the pool have any retained blocks on its free list? */
+    for (blk_ptr = &pool->free_blocks;
+         (newblock = *blk_ptr) != NULL; blk_ptr = &newblock->next) {
+
+        /* Yes, is this block large enough? */
+        blen = newblock->end - newblock->data;
+        if (blen >= size) {
+
+            /* Yes, take it off the free list */
+            *blk_ptr = newblock->next;
+            pool->free_size -= blen;
+            --pool->free_num;
+
+            /* Give the block to the caller */
+            newblock->start = newblock->data;
+            goto done;
+        }
+    }
+
+    newblock = (block_t *)PERM_MALLOC(sizeof(block_t));
+    newdata = (char *)PERM_MALLOC(size);
+    if (newblock == NULL || (newdata == NULL && size != 0)) {
+        //ereport(LOG_CATASTROPHE,
+        //        XP_GetAdminStr(DBT_poolCreateBlockOutOfMemory_));
+        PERM_FREE(newblock);
+        PERM_FREE(newdata);
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+        return NULL;
+    }
+    newblock->data = newdata;
+    newblock->start = newblock->data;
+    newblock->end   = newblock->data + size;
+    newblock->next  = NULL;
+    blen = size;
+
+#ifdef POOL_GLOBAL_STATISTICS
+    PR_AtomicIncrement((PRInt32 *)&pool_global_stats.blkAlloc);
+#endif /* POOL_GLOBAL_STATISTICS */
+
+  done:
+
+#ifdef PER_POOL_STATISTICS
+    ++pool->stats.blkAlloc;
+#endif /* PER_POOL_STATISTICS */
+
+    return newblock;
+}
+
+static void 
+_free_block(block_t *block)
+{
+    long blen = block->end - block->data;
+
+#ifdef POOL_ZERO_DEBUG
+    memset(block->data, POOL_ZERO_DEBUG, blen);
+#endif /* POOL_ZERO_DEBUG */
+
+    PERM_FREE(block->data);
+
+#ifdef POOL_ZERO_DEBUG
+    memset(block, POOL_ZERO_DEBUG, sizeof(block));
+#endif /* POOL_ZERO_DEBUG */
+
+    PERM_FREE(block);
+
+#ifdef POOL_GLOBAL_STATISTICS
+    PR_AtomicIncrement((PRInt32 *)&pool_global_stats.blkFree);
+#endif /* POOL_GLOBAL_STATISTICS */
+}
+
+/* ptr_in_pool()
+ * Checks to see if the given pointer is in the given pool.
+ * If true, returns a ptr to the block_t containing the ptr;
+ * otherwise returns NULL
+ */
+block_t * 
+_ptr_in_pool(pool_t *pool, const void *ptr)
+{
+    block_t *block_ptr = NULL;
+
+    /* try to find a block which contains this ptr */
+
+    if (POOL_PTR_IN_BLOCK(pool->curr_block, ptr)) {
+        block_ptr = pool->curr_block;
+    }
+    else {
+        for (block_ptr = pool->used_blocks; block_ptr; block_ptr = block_ptr->next) {
+            if (POOL_PTR_IN_BLOCK(block_ptr, ptr))
+                break;
+        }
+    }
+    return block_ptr;
+}
+
+
+NSAPI_PUBLIC pool_handle_t *
+pool_create()
+{
+    pool_t *newpool;
+
+    newpool = (pool_t *)PERM_MALLOC(sizeof(pool_t));
+
+    if (newpool) {
+        /* Have to initialize now, as pools get created sometimes
+         * before pool_init can be called...
+         */
+        if (pool_global_stats.lock == NULL) {
+            pool_internal_init();
+        }
+
+        newpool->used_blocks = NULL;
+        newpool->free_blocks = NULL;
+        newpool->free_size = 0;
+        newpool->free_num = 0;
+        newpool->size = 0;
+        newpool->next = NULL;
+
+#ifdef PER_POOL_STATISTICS
+        /* Initial per pool statistics */
+        memset((void *)(&newpool->stats), 0, sizeof(newpool->stats));
+        newpool->stats.thread = PR_GetCurrentThread();
+        newpool->stats.created = PR_Now();
+#endif /* PER_POOL_STATISTICS */
+
+        /* No need to lock, since pool has not been exposed yet */
+        newpool->curr_block =_create_block(newpool, pool_config.block_size);
+        if (newpool->curr_block == NULL) {
+            //ereport(LOG_CATASTROPHE, XP_GetAdminStr(DBT_poolCreateOutOfMemory_));
+            pool_destroy((pool_handle_t *)newpool);
+            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+            return NULL;
+        }
+
+        /* Add to known pools list */
+        PR_Lock(pool_global_stats.lock);
+        newpool->next = pool_global_stats.poolList;
+        pool_global_stats.poolList = newpool;
+        ++pool_global_stats.createCnt;
+#ifdef PER_POOL_STATISTICS
+        newpool->stats.poolId = pool_global_stats.createCnt;
+#endif /* PER_POOL_STATISTICS */
+        PR_Unlock(pool_global_stats.lock);
+
+    }
+    else {
+        //ereport(LOG_CATASTROPHE, XP_GetAdminStr(DBT_poolCreateOutOfMemory_1));
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+
+    return (pool_handle_t *)newpool;
+}
+
+/*
+ * pool_mark - get mark for subsequent recycle
+ *
+ * This function returns a value that can be used to free all pool
+ * memory which is subsequently allocated, without freeing memory
+ * that has already been allocated when pool_mark() is called.
+ * The pool_recycle() function is used to free the memory allocated
+ * since pool_mark() was called.
+ *
+ * This function may be called several times before pool_recycle()
+ * is called, but some care must be taken not to pass an invalid
+ * mark value to pool_recycle(), which would cause all pool memory
+ * to be freed.  A mark value becomes invalid when pool_recycle is
+ * called with a previously returned mark value.
+ */
+NSAPI_PUBLIC void *
+pool_mark(pool_handle_t *pool_handle)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+
+    PR_ASSERT(pool != NULL);
+
+    if (pool == NULL)
+        return NULL;
+
+#ifdef PER_POOL_STATISTICS
+    pool->stats.thread = PR_GetCurrentThread();
+#endif /* PER_POOL_STATISTICS */
+
+    /* Never return end as it points outside the block */
+    if (pool->curr_block->start == pool->curr_block->end)
+        return pool->curr_block;
+
+    return (void *)(pool->curr_block->start);
+}
+
+/*
+ * pool_recycle - recycle memory in a pool
+ *
+ * This function returns all the allocated memory for a pool back to
+ * a free list associated with the pool. It is like pool_destroy() in
+ * the sense that all data structures previously allocated from the
+ * pool are freed, but it keeps the memory associated with the pool,
+ * and doesn't actually destroy the pool.
+ *
+ * The "mark" argument can be a value previously returned by
+ * pool_mark(), in which case the pool is returned to the state it
+ * was in when pool_mark() was called, or it can be NULL, in which
+ * case the pool is completely recycled.
+ */
+NSAPI_PUBLIC void
+pool_recycle(pool_handle_t *pool_handle, void *mark)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+    block_t *tmp_blk;
+    unsigned long blen;
+
+    PR_ASSERT(pool != NULL);
+
+    if (pool == NULL)
+        return;
+
+    /* Fix up curr_block.  There should always be a curr_block. */
+    tmp_blk = pool->curr_block;
+    PR_ASSERT(tmp_blk != NULL);
+
+    /* Start with curr_block, then scan blocks on used_blocks list */
+    for (;;) {
+
+        /* Check if the mark is at the end of this block */
+        if (tmp_blk == mark) {
+            pool->curr_block = tmp_blk;
+            break;
+        }
+
+        /* Look for a block containing the mark */
+        if (POOL_PTR_IN_BLOCK(tmp_blk, mark)) {
+
+            /* Reset block start pointer to marked spot */
+            if (tmp_blk == pool->curr_block) {
+                blen = tmp_blk->start - (char *)mark;
+            } else {
+                blen = tmp_blk->end - (char *)mark;
+            }
+            pool->size -= blen;
+            PR_ASSERT(pool->size >= 0);
+            tmp_blk->start = (char *)mark;
+            pool->curr_block = tmp_blk;
+            break;
+        }
+
+        /* Reset block start pointer to base of block */
+        if (tmp_blk == pool->curr_block) {
+            /* Count just the allocated length in the current block */
+            blen = tmp_blk->start - tmp_blk->data;
+        }
+        else {
+            /* Count the entire size of a used_block */
+            blen = tmp_blk->end - tmp_blk->data;
+        }
+        tmp_blk->start = tmp_blk->data;
+        pool->size -= blen;
+        PR_ASSERT(pool->size >= 0);
+
+        /*
+         * If there are no more used blocks after this one, then set
+         * this block up as the current block and return.
+         */
+        if (pool->used_blocks == NULL) {
+            PR_ASSERT(mark == NULL);
+            pool->curr_block = tmp_blk;
+            break;
+        }
+
+        /* Otherwise free this block one way or another */
+
+        /* Add block length to total retained length and check limit */
+        if ((pool->free_size + blen) <= pool_config.retain_size &&
+            pool->free_num < pool_config.retain_num) {
+
+            /* Retain block on pool free list */
+            /*
+             * XXX hep - could sort blocks on free list in order
+             * ascending size to get "best fit" allocation in
+             * _create_block(), but the default block size is large
+             * enough that fit should rarely be an issue.
+             */
+            tmp_blk->next = pool->free_blocks;
+            pool->free_blocks = tmp_blk;
+            pool->free_size += blen;
+            ++pool->free_num;
+        }
+        else {
+            /* Limit exceeded - free block */
+            _free_block(tmp_blk);
+        }
+
+#ifdef PER_POOL_STATISTICS
+        ++pool->stats.blkFree;
+#endif /* PER_POOL_STATISTICS */
+
+        /* Remove next block from used blocks list */
+        tmp_blk = pool->used_blocks;
+        pool->used_blocks = tmp_blk->next;
+    }
+}
+
+NSAPI_PUBLIC void
+pool_destroy(pool_handle_t *pool_handle)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+    block_t *tmp_blk;
+
+    PR_ASSERT(pool != NULL);
+
+    if (pool == NULL)
+        return;
+
+    if (pool->curr_block)
+        _free_block(pool->curr_block);
+
+    while(pool->used_blocks) {
+        tmp_blk = pool->used_blocks;
+        pool->used_blocks = tmp_blk->next;
+        _free_block(tmp_blk);
+    }
+
+    while(pool->free_blocks) {
+        tmp_blk = pool->free_blocks;
+        pool->free_blocks = tmp_blk->next;
+        _free_block(tmp_blk);
+    }
+
+    {
+        pool_t **ppool;
+
+        /* Remove from the known pools list */
+        PR_Lock(pool_global_stats.lock);
+        for (ppool = &pool_global_stats.poolList;
+             *ppool; ppool = &(*ppool)->next) {
+            if (*ppool == pool) {
+                ++pool_global_stats.destroyCnt;
+                *ppool = pool->next;
+                break;
+            }
+        }
+        PR_Unlock(pool_global_stats.lock);
+    }
+
+#ifdef POOL_ZERO_DEBUG
+    memset(pool, POOL_ZERO_DEBUG, sizeof(pool));
+#endif /* POOL_ZERO_DEBUG */
+
+    PERM_FREE(pool);
+
+    return;
+}
+
+
+NSAPI_PUBLIC void *
+pool_malloc(pool_handle_t *pool_handle, size_t size)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+    block_t *curr_block;
+    long reqsize, blocksize;
+    char *ptr;
+
+    if (pool == NULL)
+        return PERM_MALLOC(size);
+
+    reqsize = ALIGN(size);
+    if (reqsize == 0) {
+        /* Assign a unique address to each 0-byte allocation */
+        reqsize = WORD_SIZE;
+    }
+
+    curr_block = pool->curr_block;
+    ptr = curr_block->start;
+    curr_block->start += reqsize;
+
+    /* does this fit into the last allocated block? */
+    if (curr_block->start > curr_block->end) {
+
+        /* Did not fit; time to allocate a new block */
+
+        curr_block->start -= reqsize;  /* keep structs in tact */
+
+        /* Count unallocated bytes in current block in pool size */
+        pool->size += curr_block->end - curr_block->start;
+        PR_ASSERT(pool->size >= 0);
+#ifdef PER_POOL_STATISTICS
+        if (pool->size > pool->stats.maxAlloc) {
+            pool->stats.maxAlloc = pool->size;
+        }
+#endif /* PER_POOL_STATISTICS */
+
+        /* Move current block to used block list */
+        curr_block->next = pool->used_blocks;
+        pool->used_blocks = curr_block;
+
+        /* Allocate a chunk of memory which is at least block_size bytes */
+        blocksize = reqsize;
+        if (blocksize < pool_config.block_size)
+            blocksize = pool_config.block_size;
+
+        curr_block = _create_block(pool, blocksize);
+        pool->curr_block = curr_block;
+
+        if (curr_block == NULL) {
+            //ereport(LOG_CATASTROPHE,
+            //        XP_GetAdminStr(DBT_poolMallocOutOfMemory_));
+            PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+            return NULL;
+        }
+
+        ptr = curr_block->start;
+        curr_block->start += reqsize;
+    }
+
+    pool->size += reqsize;
+    PR_ASSERT(pool->size >= 0);
+
+#ifdef PER_POOL_STATISTICS
+    if (pool->size > pool->stats.maxAlloc) {
+        pool->stats.maxAlloc = pool->size;
+    }
+    ++pool->stats.allocCnt;
+    pool->stats.thread = PR_GetCurrentThread();
+#endif /* PER_POOL_STATISTICS */
+
+    return ptr;
+}
+
+NSAPI_PUBLIC void
+pool_free(pool_handle_t *pool_handle, void *ptr)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+
+    if (ptr == NULL)
+        return;
+
+    if (pool == NULL) {
+        PERM_FREE(ptr);
+        return;
+    }
+
+    PR_ASSERT(_ptr_in_pool(pool, ptr));
+
+#ifdef PER_POOL_STATISTICS
+
+    ++pool->stats.freeCnt;
+    pool->stats.thread = PR_GetCurrentThread();
+
+#endif /* PER_POOL_STATISTICS */
+
+    return;
+}
+
+NSAPI_PUBLIC void *
+pool_calloc(pool_handle_t *pool_handle, size_t nelem, size_t elsize)
+{
+    void *ptr;
+
+    if (pool_handle == NULL)
+        return calloc(1, elsize * nelem);
+
+    ptr = pool_malloc(pool_handle, elsize * nelem);
+    if (ptr)
+        memset(ptr, 0, elsize * nelem);
+    return ptr;
+}
+
+NSAPI_PUBLIC void *
+pool_realloc(pool_handle_t *pool_handle, void *ptr, size_t size)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+    void *newptr;
+    block_t *block_ptr;
+    size_t oldsize;
+
+    if (pool == NULL)
+        return PERM_REALLOC(ptr, size);
+
+    if ( (newptr = pool_malloc(pool_handle, size)) == NULL) 
+        return NULL;
+
+    /* With our structure we don't know exactly where the end
+     * of the original block is.  But we do know an upper bound
+     * which is a valid ptr.  Search the outstanding blocks
+     * for the block which contains this ptr, and copy...
+     */
+
+    if ( !(block_ptr = _ptr_in_pool(pool, ptr)) ) {
+        /* User is trying to realloc nonmalloc'd space! */
+        return newptr;
+    }
+
+    oldsize = block_ptr->end - (char *)ptr ;
+    if (oldsize > size)
+        oldsize = size;
+    memmove((char *)newptr, (char *)ptr, oldsize);
+
+    return newptr;
+}
+
+NSAPI_PUBLIC char *
+pool_strdup(pool_handle_t *pool_handle, const char *orig_str)
+{
+    char *new_str;
+    int len = strlen(orig_str);
+
+    if (pool_handle == NULL)
+        return PERM_STRDUP(orig_str);
+
+    new_str = (char *)pool_malloc(pool_handle, len+1);
+
+    if (new_str) 
+        memcpy(new_str, orig_str, len+1);
+
+    return new_str;
+}
+
+NSAPI_PUBLIC long
+pool_space(pool_handle_t *pool_handle)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+
+    return pool->size;
+}
+
+NSAPI_PUBLIC int pool_enabled()
+{
+    if (getThreadMallocKey() == -1)
+        return 0;
+
+    if (!systhread_getdata(getThreadMallocKey()))
+        return 0;
+
+    return 1;
+}
+
+#ifdef DEBUG
+NSAPI_PUBLIC void INTpool_assert(pool_handle_t *pool_handle, const void *ptr)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+
+    if (pool == NULL)
+        return;
+
+    PR_ASSERT(_ptr_in_pool(pool, ptr));
+}
+#endif
+
+NSAPI_PUBLIC pool_config_t *pool_getConfig(void)
+{
+    return &pool_config;
+}
+
+#ifdef POOL_GLOBAL_STATISTICS
+NSAPI_PUBLIC pool_global_stats_t *pool_getGlobalStats(void)
+{
+    return &pool_global_stats;
+}
+#endif /* POOL_GLOBAL_STATISTICS */
+
+#ifdef PER_POOL_STATISTICS
+NSAPI_PUBLIC pool_stats_t *pool_getPoolStats(pool_handle_t *pool_handle)
+{
+    pool_t *pool = (pool_t *)pool_handle;
+
+    if (pool == NULL)
+        return NULL;
+
+    return &pool->stats;
+}
+#endif /* PER_POOL_STATISTICS */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/pool.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,139 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_POOL_H
+#define BASE_POOL_H
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * pool.h
+ *
+ * Module for handling memory allocations.
+ *
+ * Notes:
+ * This module is used instead of the NSPR prarena module because the prarenas
+ * did not fit as cleanly into the existing server.
+ *
+ * Mike Belshe
+ * 10-02-95
+ *
+ */
+
+#ifndef NETSITE_H
+//include "netsite.h"
+#include "nsapi.h"
+#include "nspr.h"
+#endif /* !NETSITE_H */
+
+#ifndef BASE_PBLOCK_H
+//include "pblock.h"
+#endif /* !BASE_PBLOCK_H */
+
+#ifndef BASE_SESSION_H
+//#include "session.h"
+#endif /* !BASE_SESSION_H */
+
+#ifndef FRAME_REQ_H
+//include "frame/req.h"
+#endif /* !FRAME_REQ_H */
+
+/* --- Begin function prototypes --- */
+
+#ifdef INTNSAPI
+
+NSPR_BEGIN_EXTERN_C
+
+NSAPI_PUBLIC int INTpool_init(pblock *pb, Session *sn, Request *rq);
+
+#ifdef DEBUG_CACHES
+NSAPI_PUBLIC int INTpool_service_debug(pblock *pb, Session *sn, Request *rq);
+#endif
+
+NSAPI_PUBLIC pool_handle_t *INTpool_create(void);
+
+NSAPI_PUBLIC void *INTpool_mark(pool_handle_t *pool_handle);
+
+NSAPI_PUBLIC void INTpool_recycle(pool_handle_t *pool_handle, void *mark);
+
+NSAPI_PUBLIC void INTpool_destroy(pool_handle_t *pool_handle);
+
+NSAPI_PUBLIC int INTpool_enabled(void);
+
+NSAPI_PUBLIC void *INTpool_malloc(pool_handle_t *pool_handle, size_t size );
+
+NSAPI_PUBLIC void INTpool_free(pool_handle_t *pool_handle, void *ptr );
+
+NSAPI_PUBLIC 
+void *INTpool_calloc(pool_handle_t *pool_handle, size_t nelem, size_t elsize);
+
+NSAPI_PUBLIC 
+void *INTpool_realloc(pool_handle_t *pool_handle, void *ptr, size_t size );
+
+NSAPI_PUBLIC
+char *INTpool_strdup(pool_handle_t *pool_handle, const char *orig_str );
+
+#ifdef DEBUG
+NSAPI_PUBLIC void INTpool_assert(pool_handle_t *pool_handle, const void *ptr);
+#endif
+
+NSPR_END_EXTERN_C
+
+#define pool_init INTpool_init
+
+#ifdef DEBUG_CACHES
+#define pool_service_debug INTpool_service_debug
+#endif /* DEBUG_CACHES */
+
+#ifdef DEBUG
+#define POOL_ASSERT(pool, ptr) INTpool_assert(pool, ptr);
+#else
+#define POOL_ASSERT(pool, ptr)
+#endif
+
+#define pool_create INTpool_create
+#define pool_mark INTpool_mark
+#define pool_recycle INTpool_recycle
+#define pool_destroy INTpool_destroy
+#define pool_enabled INTpool_enabled
+#define pool_malloc INTpool_malloc
+#define pool_free INTpool_free
+#define pool_calloc INTpool_calloc
+#define pool_realloc INTpool_realloc
+#define pool_strdup INTpool_strdup
+
+#endif /* INTNSAPI */
+
+#endif /* !BASE_POOL_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/pool_pvt.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,183 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_POOL_PVT_H
+#define BASE_POOL_PVT_H
+
+#ifndef BASE_POOL_H
+#include "pool.h"
+#endif /* BASE_POOL_H */
+
+/*
+ * pool_pvt.h - private definitions for memory pools
+ */
+
+/* Definitions */
+
+/*
+ * Define PER_POOL_STATISTICS to get detailed statistics for each
+ * pool.
+ */
+#ifdef DEBUG
+#define PER_POOL_STATISTICS
+#endif
+
+/* Define POOL_GLOBAL_STATISTICS to get global pool statistics */
+#define POOL_GLOBAL_STATISTICS
+
+/*
+ * When POOL_ZERO_DEBUG is defined, overwrite the contents of freed
+ * pool data structures and memory with the POOL_ZERO_DEBUG byte value.
+ */
+#ifdef DEBUG
+#define POOL_ZERO_DEBUG 0xa
+#endif
+
+/*
+ * DEFAULT_BLOCK_SIZE specifies the minimum granularity, in bytes, used
+ * in allocating memory from the heap for use with a pool.  A request
+ * for more than DEFAULT_BLOCK_SIZE bytes from a pool will cause a block
+ * of that size to be allocated from the heap.
+ */
+#define DEFAULT_BLOCK_SIZE      (32 * 1024)
+
+/*
+ * The pool_recycle() mechanism keeps a list of free blocks associated
+ * with each pool, in order to avoid global locking when doing the
+ * pool_recycle() operation, or when subsequently allocating memory
+ * from the pool.  DEFAULT_RETENTION_SIZE and DEFAULT_RETENTION_NUM
+ * specify the maximum number of bytes and blocks, respectively, that
+ * will be kept on a per-pool free list.
+ */
+#define DEFAULT_RETENTION_SIZE  (DEFAULT_BLOCK_SIZE * 2)
+#define DEFAULT_RETENTION_NUM   2
+
+/* WORD_SIZE 8 sets us up for 8 byte alignment. */
+#define WORD_SIZE       8   
+#undef  ALIGN
+#define ALIGN(x)        ( (x + WORD_SIZE-1) & (~(WORD_SIZE-1)) )
+
+/* Types */
+
+/*
+ * pool_stats_t
+ * This structure contains per pool statistics.
+ */
+#ifdef PER_POOL_STATISTICS
+typedef struct pool_stats_t pool_stats_t;
+struct pool_stats_t {
+    PRUint32  poolId;      /* pool id */
+    PRUint32  maxAlloc;    /* maximum bytes ever used from pool */
+    PRUint32  allocCnt;    /* count of memory allocations from pool */
+    PRUint32  freeCnt;     /* count of pool memory free operations */
+    PRUint32  blkAlloc;    /* count of block allocations */
+    PRUint32  blkFree;     /* count of blocks freed (on pool_recycle) */
+    PRThread *thread;      /* last thread to use pool */
+    PRTime    created;     /* time of pool creation */
+};
+#endif /* PER_POOL_STATISTICS */
+
+typedef struct pool_config_t pool_config_t;
+struct pool_config_t {
+    PRUint32 block_size;   /* size of blocks to allocate */
+    PRUint32 retain_size;  /* maximum bytes kept on per-pool free list */
+    PRUint32 retain_num;   /* maximum blocks kept on per-pool free list */
+};
+
+#define POOL_CONFIG_INIT { \
+                           DEFAULT_BLOCK_SIZE,     /* block_size */ \
+                           DEFAULT_RETENTION_SIZE, /* retain_size */ \
+                           DEFAULT_RETENTION_NUM,  /* retain_num */ \
+                         }
+
+/*
+ * block_t
+ * When the user allocates space, a DEFAULT_BLOCK_SIZE (or larger) block
+ * is created in the pool.  This block is used until all the space is
+ * eaten within it.  When all the space is gone, a new block is created.
+ */
+typedef struct block_t block_t;
+struct block_t {
+    char    *data;              /* the real alloc'd space */
+    char    *start;             /* first free byte in block */
+    char    *end;               /* ptr to end of block */
+    block_t *next;              /* ptr to next block */
+};
+
+#define POOL_PTR_IN_BLOCK(blk, ptr) \
+    (((char *)(ptr) < (blk)->end) && ((char *)(ptr) >= (blk)->data))
+
+/*
+ * pool_t
+ * A pool is a collection of blocks.  The blocks consist of multiple 
+ * allocations of memory, but a single allocation cannot be freed by
+ * itself.  Once the memory is allocated it is allocated until the
+ * entire pool is freed.
+ */
+typedef struct pool_t pool_t;
+struct pool_t {
+    block_t  *curr_block;       /* current block being used */
+    block_t  *used_blocks;      /* blocks that are all used up */
+    block_t  *free_blocks;      /* blocks that are free */
+    PRUint32  free_size;        /* number of bytes in free_blocks */
+    PRUint32  free_num;         /* number of blocks in free_blocks */
+    size_t    size;             /* size of memory in pool */
+    pool_t   *next;             /* known_pools list */
+#ifdef PER_POOL_STATISTICS
+    pool_stats_t stats;         /* statistics for this pool */
+#endif /* PER_POOL_STATISTICS */
+};
+
+typedef struct pool_global_stats_t pool_global_stats_t;
+struct pool_global_stats_t {
+    PRLock   *lock;        /* lock for access to poolList */
+    pool_t   *poolList;    /* list of known pools */
+    PRUint32  createCnt;   /* count of pools created */
+    PRUint32  destroyCnt;  /* count of pools destroyed */
+#ifdef POOL_GLOBAL_STATISTICS
+    PRUint32  blkAlloc;    /* count of block allocations from heap */
+    PRUint32  blkFree;     /* count of blocks freed to heap */
+#endif /* POOL_GLOBAL_STATISTICS */
+};
+
+/* Private functions for inspecting pool configuration/statistics */
+
+NSAPI_PUBLIC pool_config_t *pool_getConfig(void);
+
+NSAPI_PUBLIC pool_global_stats_t *pool_getGlobalStats(void);
+
+#ifdef PER_POOL_STATISTICS
+NSAPI_PUBLIC pool_stats_t *pool_getPoolStats(pool_handle_t *pool_handle);
+#endif
+
+#endif /* BASE_POOL_PVT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/request.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,91 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "request.h"
+
+#include "pblock.h"
+#include "httprequest.h"
+
+
+/* Code from req.cpp */
+
+/* -------------------------- request_initialize -------------------------- */
+
+int request_initialize(
+        pool_handle_t *pool,
+        HTTPRequest *hrq,
+        NSAPIRequest *nrq)
+{
+    Request *rq = &nrq->rq;
+
+    rq->vars = pblock_create_pool(pool, REQ_HASHSIZE);
+    if (!rq->vars)
+        return 1;
+    rq->reqpb = pblock_create_pool(pool, REQ_HASHSIZE);
+    if (!rq->reqpb)
+        return 1;
+    rq->loadhdrs = 0;
+    rq->headers = pblock_create_pool(pool, REQ_HASHSIZE);
+    if (!rq->headers)
+        return 1;
+    rq->senthdrs = 0;
+    rq->srvhdrs = pblock_create_pool(pool, REQ_HASHSIZE);
+    if (!rq->srvhdrs)
+        return 1;
+
+    rq->os = NULL;
+    rq->tmpos = NULL;
+    rq->statpath = NULL;
+    rq->staterr = NULL;
+    rq->finfo = NULL;
+    rq->aclstate = 0;
+    rq->acldirno = 0;
+    rq->aclname = NULL;
+    rq->aclpb = NULL;
+    rq->acllist = NULL;
+    rq->request_is_cacheable = 0;
+    rq->directive_is_cacheable = 0;
+    rq->cached_headers = NULL;
+    rq->cached_headers_len = 0;
+    rq->unused = NULL;
+    //rq->req_start = ft_time(); // TODO: ft_time
+    rq->protv_num = 0;
+    rq->method_num = -1;
+    //PR_ASSERT(sizeof(rq->rq_attr) == sizeof(RQATTR)); // TODO: assert
+    *(RQATTR *) &rq->rq_attr = 0;
+    //rq->hostname = pool_strdup(pool, hostname); // TODO: hostname
+    rq->allowed = 0;
+    rq->byterange = 0;
+    rq->status_num = 0;
+    rq->staterrno = 0;
+    rq->orig_rq = rq;
+
+    // TODO: nrq
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/request.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,53 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef REQUEST_H
+#define	REQUEST_H
+
+#include "nsapi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct NSAPIRequest NSAPIRequest;
+
+
+struct NSAPIRequest {
+    Request rq;
+};
+
+#define REQ_HASHSIZE 10
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* REQUEST_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/session.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,33 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "nsapi.h"
+
+#include "session.h"
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/session.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,51 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SESSION_H
+#define	SESSION_H
+
+#include "nsapi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct NSAPISession NSAPISession;
+
+struct NSAPISession {
+    Session sn; /* public session structure */
+    int sys_fd; /* system file descriptor */
+};
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* SESSION_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/sessionhandler.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,103 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nsapi.h"
+
+#include "sessionhandler.h"
+#include "httprequest.h"
+#include "httpparser.h"
+
+SessionHandler* create_basic_session_handler() {
+    BasicSessionHandler *handler = malloc(sizeof(BasicSessionHandler));
+    handler->threadpool = threadpool_new(8);
+    handler->sh.enqueue_connection = basic_enq_conn;
+
+
+    return (SessionHandler*)handler;
+}
+
+void basic_enq_conn(SessionHandler *handler, Connection *conn) {
+    BasicSessionHandler *sh = (BasicSessionHandler*)handler;
+    conn->session_handler = handler;
+    threadpool_run(sh->threadpool, basic_run_session, conn);
+}
+
+void* basic_run_session(void *data) {
+    Connection *conn = (Connection*)data;
+
+    HTTPRequest *request = http_request_new();
+    request->connection = conn;
+
+    // read request
+    netbuf *buf = malloc(sizeof(netbuf));
+    buf->rdtimeout = 120;
+    buf->pos = 0;
+    buf->cursize = 0;
+    buf->maxsize = 2048;
+    buf->sd = &conn->fd;
+    buf->inbuf = malloc(2048);
+    buf->errmsg = NULL;
+
+    request->netbuf = buf;
+
+    HttpParser *parser = http_parser_new(request);
+    int state;
+    int r;
+    r = read(conn->fd, buf->inbuf + buf->pos, buf->maxsize - buf->pos);
+    if(r == -1) {
+         // TODO: error handling
+        fprintf(stderr, "%s\n", "Error: Cannot read from socket");
+        return NULL;
+    }
+    buf->cursize += r;
+    while((state = http_parser_process(parser)) != 0) {
+        if(state == 2) {
+            // TODO: error handling
+            fprintf(stderr, "%s\n", "Error: Cannot parse http request");
+            return NULL;
+        }
+        r = read(conn->fd, buf->inbuf + buf->pos, buf->maxsize - buf->pos);
+        if(r == -1) {
+            // TODO: error handling
+            fprintf(stderr, "%s\n", "Error: Cannot read from socket");
+            return NULL;
+        }
+        buf->cursize += r;
+    }
+
+    // process request
+    r = handle_request(request);
+
+
+    return NULL;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/sessionhandler.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,79 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SESSIONHANDLER_H
+#define	SESSIONHANDLER_H
+
+#include "thrpool.h"
+#include "nsapi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _session_handler   SessionHandler;
+typedef struct _connection        Connection;
+
+struct _connection {
+    int fd;
+    struct sockaddr_in address;
+    SessionHandler *session_handler;
+};
+
+typedef void(*enqueue_connection_f)(SessionHandler*, Connection*);
+struct _session_handler {
+    enqueue_connection_f enqueue_connection;
+};
+
+/*
+ * BasicSessionHandler
+ *
+ * The BasicSessionHandler enqueues the connections to a threadpool. IO and
+ * request processing is handled by one thread.
+ */
+typedef struct _basic_session_handler {
+    SessionHandler sh;
+    threadpool_t   *threadpool;
+    
+} BasicSessionHandler;
+
+
+SessionHandler* create_basic_session_handler();
+
+void basic_enq_conn(SessionHandler *handler, Connection *conn);
+
+void* basic_run_session(void *data);
+
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* SESSIONHANDLER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/sstring.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,120 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "sstring.h"
+
+sstr_t sstr (char *s) {
+    sstr_t string;
+    string.ptr = s;
+    string.length = strlen(s);
+    return string;
+}
+
+sstr_t sstrn (char *s, size_t n) {
+    sstr_t string;
+    string.ptr = s;
+    string.length = n;
+    return string;
+}
+
+size_t sstrnlen (size_t n, sstr_t s, ...) {
+    va_list ap;
+    size_t size = s.length;
+    va_start(ap, s);
+
+    for (int i=0;i<n-1;i++) {
+        sstr_t str = va_arg(ap, sstr_t);
+        size += str.length;
+    }
+
+    return size;
+}
+
+sstr_t sstrcat (sstr_t s, ...) {
+    va_list ap;
+    va_start(ap, s);
+    s.ptr[0] = 0;
+
+    sstr_t str = va_arg (ap, sstr_t);
+    while (str.ptr != NULL) {
+        s.ptr = strncat (s.ptr, str.ptr, s.length);
+        str = va_arg (ap, sstr_t);
+    }
+    
+    return s;
+}
+
+sstr_t sstrncat (size_t n, sstr_t s, sstr_t c1, ...) {
+    va_list ap;
+    va_start(ap, c1);
+    s.ptr[0] = 0;
+
+    s.ptr = strncat (s.ptr, c1.ptr, s.length);
+    for (int i=0;i<n-1;i++) {
+        sstr_t str = va_arg (ap, sstr_t);
+        s.ptr = strncat (s.ptr, str.ptr, s.length);
+    }
+
+    return s;
+}
+
+sstr_t sstrsubs (sstr_t s, size_t start) {
+    return sstrsubsl (s, start, s.length-start);
+}
+
+sstr_t sstrsubsl (sstr_t s, size_t start, size_t length) {
+    sstr_t new_sstr;
+    if (start < 0 || start >= s.length || length < 0) {
+        return s;
+    }
+    if (length > s.length-start) {
+        length = s.length-start;
+    }
+    new_sstr.ptr = &s.ptr[start];
+    new_sstr.length = length;
+    return new_sstr;
+}
+
+int sstrcmp(sstr_t s1, sstr_t s2) {
+    return strncmp(s1.ptr, s2.ptr, s1.length>s2.length ? s2.length: s1.length);
+}
+
+sstr_t sstrdub(sstr_t s) {
+    sstr_t newstring;
+    newstring.ptr = malloc(s.length + 1);
+    newstring.length = s.length;
+    newstring.ptr[newstring.length] = 0;
+
+    memcpy(newstring.ptr, s.ptr, s.length);
+
+    return newstring;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/sstring.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,100 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _SSTRING_H
+#define	_SSTRING_H
+
+#define S(s) { s, sizeof(s)-1 }
+#define ST(s) sstrn(s, sizeof(s)-1)
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct sstring {
+    char   *ptr;
+    size_t length;
+} sstr_t;
+
+/*
+ * creates a new sstr_t from a null terminated string
+ *
+ * s  null terminated string
+ */
+sstr_t sstr (char *s);
+
+/*
+ * creates a new sstr_t from a string and length
+ *
+ * s  string
+ * n  length of string
+ */
+sstr_t sstrn (char *s, size_t n);
+
+
+/*
+ * gets the length of n sstr_t strings
+ *
+ * n    number of strings
+ * s    string
+ * ...  strings
+ */
+size_t sstrnlen (size_t n, sstr_t s, ...);
+
+
+/*
+ * concatenates n strings
+ *
+ * n    number of strings
+ * s    new string with enough memory allocated
+ * ...  strings
+ */
+sstr_t sstrncat (size_t n, sstr_t s, sstr_t c1, ...);
+
+
+/*
+ * 
+ */
+sstr_t sstrsubs (sstr_t s, size_t start);
+
+/*
+ * 
+ */
+sstr_t sstrsubsl (sstr_t s, size_t start, size_t end);
+
+
+int sstrcmp(sstr_t s1, sstr_t s2);
+
+sstr_t sstrdub(sstr_t s);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _SSTRING_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/system.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,387 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * system.c: A grab bag of system-level abstractions
+ * 
+ * Many authors
+ */
+
+#if (defined(__GNUC__) && (__GNUC__ > 2))
+#include <new>
+using namespace std;
+#else
+//include <new.h>
+#endif
+#include "netsite.h"
+#include "ereport.h"
+
+#ifdef XP_WIN32
+#include <windows.h>
+#include <process.h>
+#endif
+
+static int thread_malloc_key = -1;
+
+static char* temp_dir = NULL;
+
+#ifdef XP_WIN32
+_PNH original_newhandler = 0;
+#else
+typedef void (newhandler)(void);
+static newhandler *original_newhandler = 0;
+#endif
+
+#include "pool.h"
+#include "systhr.h"
+
+#define MALLOC_KEY \
+    ((pool_handle_t *)(thread_malloc_key != -1 ? systhread_getdata(thread_malloc_key) : NULL))
+
+
+#ifdef MCC_DEBUG
+#define DEBUG_MALLOC
+#endif
+
+#ifdef DEBUG_MALLOC
+
+/* The debug malloc routines provide several functions:
+ *
+ *  - detect allocated memory overflow/underflow
+ *  - detect multiple frees
+ *  - intentionally clobbers malloc'd buffers
+ *  - intentionally clobbers freed buffers
+ */
+#define DEBUG_MAGIC 0x12345678
+#define DEBUG_MARGIN 32
+#define DEBUG_MARGIN_CHAR '*'
+#define DEBUG_MALLOC_CHAR '.'
+#define DEBUG_FREE_CHAR   'X'
+#endif /* DEBUG_MALLOC */
+
+NSAPI_PUBLIC char *system_version()
+{
+    //return PRODUCT_ID"/"PRODUCT_VERSION_ID;
+    return "Solaris 11 Express";
+}
+
+NSAPI_PUBLIC pool_handle_t *system_pool(void)
+{
+    return MALLOC_KEY;
+}
+
+NSAPI_PUBLIC void *system_malloc(int size)
+{
+    void *ret;
+    ret = pool_malloc(MALLOC_KEY, size);
+    if (!ret) {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+    return ret;
+}
+
+
+NSAPI_PUBLIC void *system_calloc(int size)
+{
+    void *ret;
+    ret = pool_malloc(MALLOC_KEY, size);
+    if(ret) {
+        ZERO(ret, size);
+    } else {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+    return ret;
+}
+
+
+NSAPI_PUBLIC void *system_realloc(void *ptr, int size)
+{
+    void *ret;
+    ret = pool_realloc(MALLOC_KEY, ptr, size);
+    if (!ret) {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+    return ret;
+}
+
+
+NSAPI_PUBLIC void system_free(void *ptr)
+{
+    pool_free(MALLOC_KEY, ptr);
+}
+
+NSAPI_PUBLIC char *system_strdup(const char *ptr)
+{
+    //NS_ASSERT(ptr);
+    char *ret;
+    ret = pool_strdup(MALLOC_KEY, ptr);
+    if (!ret) {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+    return ret;
+}
+
+
+NSAPI_PUBLIC void *system_malloc_perm(int size)
+{
+    void *ret;
+#ifndef DEBUG_MALLOC
+    ret = malloc(size);
+#else
+    char *ptr = (char *)malloc(size + 2*DEBUG_MARGIN+2*sizeof(int));
+    char *real_ptr;
+    int *magic;
+    int *length;
+  
+    magic = (int *)ptr;
+    *magic = DEBUG_MAGIC;
+    ptr += sizeof(int);
+    length = (int *)ptr;
+    *length = size;
+    ptr += sizeof(int);
+    memset(ptr, DEBUG_MARGIN_CHAR, DEBUG_MARGIN);
+    ptr += DEBUG_MARGIN;
+    memset(ptr, DEBUG_MALLOC_CHAR, size);
+    real_ptr = ptr;
+    ptr += size;
+    memset(ptr, DEBUG_MARGIN_CHAR, DEBUG_MARGIN);
+
+    ret = real_ptr;
+#endif
+    if (!ret) {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+    return ret;
+}
+
+NSAPI_PUBLIC void *system_calloc_perm(int size)
+{
+    void *ret = system_malloc_perm(size);
+    if(ret)
+        ZERO(ret, size);
+    return ret;
+}
+
+NSAPI_PUBLIC void *system_realloc_perm(void *ptr, int size)
+{
+    void *ret;
+
+#ifndef DEBUG_MALLOC
+    ret = realloc(ptr, size);
+#else
+    int *magic, *length;
+    char *baseptr;
+    char *cptr;
+
+    /* realloc semantics allow realloc(NULL, size) */
+    if (ptr == NULL)
+        return system_malloc_perm(size);
+
+    cptr = (char *)ptr - DEBUG_MARGIN - 2 * sizeof(int);
+    magic = (int *)cptr;
+    if (*magic == DEBUG_MAGIC) {
+        cptr += sizeof(int);
+        length = (int *)cptr;
+        if (*length < size) {
+            char *newptr = (char *)system_malloc_perm(size);
+            memcpy(newptr, ptr, *length);
+            system_free_perm(ptr);
+
+            ret = newptr;
+        }else {
+            ret = ptr;
+        }
+    } else {
+        ereport(LOG_WARN, XP_GetAdminString(DBT_systemReallocSmallerSize));
+        ret = realloc(ptr, size);
+    }
+#endif
+
+    if (!ret) {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+
+    return ret;
+}
+
+NSAPI_PUBLIC void system_free_perm(void *ptr)
+{
+#ifdef DEBUG_MALLOC
+    int *length, *magic;
+    char *baseptr, *cptr;
+    int index;
+
+    NS_ASSERT(ptr);
+
+    cptr = baseptr = ((char *)ptr) - DEBUG_MARGIN - 2*sizeof(int);
+
+    magic = (int *)cptr;
+    if (*magic == DEBUG_MAGIC) {
+        cptr += sizeof(int);
+
+        length = (int *)cptr;
+
+        cptr += sizeof(int); 
+        for (index=0; index<DEBUG_MARGIN; index++)
+            if (cptr[index] != DEBUG_MARGIN_CHAR) {
+                ereport(LOG_CATASTROPHE, XP_GetAdminString(DBT_systemRFreeCorruptMemoryPre));
+                break;
+            }
+
+        cptr += DEBUG_MARGIN + *length;
+        for (index=0; index<DEBUG_MARGIN; index++)
+            if (cptr[index] != DEBUG_MARGIN_CHAR) {
+                ereport(LOG_CATASTROPHE, XP_GetAdminString(DBT_systemRFreeCorruptMemoryPost));
+                break;
+            }
+
+        memset(baseptr, DEBUG_FREE_CHAR, *length + 2*DEBUG_MARGIN+sizeof(int));
+    } else {
+        ereport(LOG_CATASTROPHE, XP_GetAdminString(DBT_systemRFreeUnallocatedMem));
+    }
+    free(baseptr);
+#else
+    free(ptr);
+#endif
+}
+
+NSAPI_PUBLIC char *system_strdup_perm(const char *ptr)
+{
+    char *ret;
+
+#ifndef DEBUG_MALLOC
+    //NS_ASSERT(ptr);
+    ret = strdup(ptr);
+#else
+    int len = strlen(ptr);
+    char *nptr = (char *)system_malloc_perm(len+1);
+    memcpy(nptr, ptr, len);
+    nptr[len] = '\0';
+    ret = nptr;
+#endif
+
+    if (!ret) {
+        //ereport_outofmemory();
+        PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
+    }
+
+    return ret;
+}
+
+NSAPI_PUBLIC void system_set_temp_dir(const char *dir)
+{
+    // Leak any previously-allocated dir in case someone still has a reference
+    temp_dir = STRDUP(dir);
+}
+
+NSAPI_PUBLIC const char *system_get_temp_dir(void)
+{
+    char* dir = temp_dir;
+
+    if (!dir) {
+#ifdef XP_WIN32
+        dir = getenv("TEMP");
+        if (!dir) dir = getenv("TMP");
+        if (!dir) dir = "C:\\TEMP";
+#else
+        dir = "/tmp";
+#endif
+    }
+
+    return dir;
+}
+
+NSAPI_PUBLIC int 
+getThreadMallocKey(void)
+{
+    return thread_malloc_key;
+}
+
+NSAPI_PUBLIC void
+InitThreadMallocKey(void)
+{
+    PR_NewThreadPrivateIndex((unsigned int *)&thread_malloc_key, NULL);
+    PR_ASSERT(thread_malloc_key);
+}
+
+#ifdef XP_WIN32
+static int _cdecl system_newhandler(unsigned int size)
+{
+    //ereport_outofmemory();
+
+    if (original_newhandler) {
+        // Let original handler deal with things
+        return (*original_newhandler)(size);
+    }
+
+    // Tell new not to retry the allocation
+    return 0;
+}
+#else
+static void system_newhandler()
+{
+    // We want to preserve the original new semantics, but we don't know what
+    // those semantics are.  Some platforms throw xalloc while others throw
+    // bad_alloc.
+
+    //ereport_outofmemory();
+
+    if (original_newhandler) {
+        // Let original handler deal with things
+        (*original_newhandler)();
+    } else {
+        // No original handler to call; try to remove all handlers
+        static PRBool flagRemovedHandler = PR_FALSE;
+        if (flagRemovedHandler) {
+            abort();
+        }
+        //set_new_handler(0); // TODO: set_new_handler
+        flagRemovedHandler = PR_TRUE;
+    }
+}
+#endif
+
+NSAPI_PUBLIC void system_setnewhandler(void)
+{
+#ifdef XP_WIN32
+    original_newhandler = _set_new_handler(system_newhandler);
+#else
+    //original_newhandler = set_new_handler(system_newhandler); // TODO: ...
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/systems.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,541 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_SYSTEMS_H
+#define BASE_SYSTEMS_H
+
+#include <nspr.h>
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * systems.h: Lists of defines for systems
+ * 
+ * This sets what general flavor the system is (UNIX, etc.), 
+ * and defines what extra functions your particular system needs.
+ */
+
+
+/* --- Begin common definitions for all supported platforms --- */
+
+#define DAEMON_ANY
+#define DAEMON_STATS
+
+/* --- End common definitions for all supported platforms --- */
+
+/* --- Begin platform-specific definitions --- */
+
+#if defined(AIX)
+
+#define HAS_IPV6
+#define AUTH_DBM
+#define BSD_RLIMIT
+#undef BSD_SIGNALS
+//define DAEMON_NEEDS_SEMAPHORE
+//define DAEMON_UNIX_MOBRULE
+//define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW|RTLD_GLOBAL
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATFS
+#define HAVE_ATEXIT
+#define HAVE_STRERROR_R
+#define HAVE_STRTOK_R
+#define HAVE_TIME_R 2 /* arg count */
+#define HAVE_STRFTIME /* no cftime */
+#define JAVA_STATIC_LINK
+#undef NEED_CRYPT_H
+#define NEED_STRINGS_H /* for strcasecmp */
+#define NET_SOCKETS
+#define SA_HANDLER_T(x) (void (*)(int))x
+#ifdef NS_OLDES3X
+#define SA_NOCLDWAIT 0 /* AIX don't got this */
+#endif
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+#ifdef HW_THREADS
+#define THREAD_ANY
+#endif
+#elif defined(BSDI)
+
+#define AUTH_DBM
+#define BSD_MAIL
+#define BSD_RLIMIT
+#define BSD_SIGNALS
+#define BSD_TIME
+#define DAEMON_UNIX_MOBRULE
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS (MAP_FILE | MAP_SHARED)
+#define HAS_STATFS
+#define HAVE_ATEXIT
+#undef NEED_CRYPT_PROTO
+#define NET_SOCKETS
+#define NO_DOMAINNAME
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+#define JAVA_STATIC_LINK
+
+#elif defined(HPUX)
+
+#define HAVE_TIME_R 2 /* arg count */
+#define AUTH_DBM
+#undef BSD_RLIMIT
+#undef BSD_SIGNALS
+#ifdef MCC_PROXY
+#define DAEMON_NEEDS_SEMAPHORE
+#else
+#define DAEMON_NEEDS_SEMAPHORE
+#endif
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_HPSHL
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_PRIVATE
+#define HAS_STATFS
+#define HAVE_ATEXIT
+#define HAVE_STRFTIME
+#define JAVA_STATIC_LINK
+#undef NEED_CRYPT_H
+#define NET_SOCKETS
+#define SA_HANDLER_T(x) (void (*)(int))x
+#define SEM_FLOCK
+/* warning: mmap doesn't work under 9.04 */
+#define SHMEM_MMAP_FLAGS MAP_FILE | MAP_VARIABLE | MAP_SHARED
+
+#elif defined (IRIX)
+
+#define AUTH_DBM
+#define BSD_RLIMIT
+#undef BSD_SIGNALS
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define HAVE_STRTOK_R
+#define HAVE_TIME_R 2 /* arg count */
+#define JAVA_STATIC_LINK
+#define NEED_CRYPT_H
+#define NET_SOCKETS
+#define SA_HANDLER_T(x) (void (*)(int))x
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+#define THROW_HACK throw()
+
+#elif defined(Linux)
+
+#define HAS_IPV6
+#define AUTH_DBM
+#define BSD_RLIMIT
+#undef BSD_SIGNALS
+#define DAEMON_NEEDS_SEMAPHORE
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define HAVE_STRTOK_R
+#define HAVE_TIME_R 2 /* arg count */
+#define NEED_CRYPT_H
+#undef NEED_FILIO
+#define NEED_GHN_PROTO
+#define NET_SOCKETS
+#define SA_HANDLER_T(x) (void (*)(int))x
+#undef NEED_GHN_PROTO 
+
+#elif defined(NCR)
+
+#define AUTH_DBM
+#undef BSD_RLIMIT
+/* #define DAEMON_NEEDS_SEMAPHORE */
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define HAVE_STRTOK_R
+#define JAVA_STATIC_LINK
+#define NEED_CRYPT_H
+#define NEED_FILIO
+#define NEED_GHN_PROTO
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#elif defined(NEC)
+
+#define DNS_CACHE
+#define AUTH_DBM
+#undef BSD_RLIMIT
+#define DAEMON_NEEDS_SEMAPHORE
+#define DAEMON_UNIX_MOBRULE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DLL_CAPABLE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define HAVE_STRTOK_R
+#define HAVE_TIME_R 2 /* arg count */
+#define JAVA_STATIC_LINK
+#define NEED_CRYPT_H
+#define NEED_FILIO
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#elif defined(OSF1)
+
+#define HAS_IPV6
+#define AUTH_DBM
+#define BSD_RLIMIT
+#undef BSD_SIGNALS
+#define BSD_TIME
+#define DAEMON_UNIX_MOBRULE
+#define DAEMON_NEEDS_SEMAPHORE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAVE_ATEXIT
+#define HAVE_STRFTIME /* no cftime */
+#define HAVE_TIME_R 2 /* ctime_r arg count */
+#define NET_SOCKETS
+#define SA_HANDLER_T(x) (void (*)(int))x
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#elif defined(SCO)
+
+#define AUTH_DBM
+#undef BSD_RLIMIT
+#undef BSD_SIGNALS
+#define DAEMON_NEEDS_SEMAPHORE
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#undef NEED_CRYPT_H
+#undef NEED_FILIO
+#undef NEED_GHN_PROTO
+#undef NEED_SETEID_PROTO /* setegid, seteuid */
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+#define SA_HANDLER_T(x) (void (*)(int))x
+
+
+#elif defined(SNI)
+
+#define AUTH_DBM
+#undef BSD_RLIMIT
+#define DAEMON_NEEDS_SEMAPHORE
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define JAVA_STATIC_LINK
+#define NEED_CRYPT_H
+#define NEED_FILIO
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+#define USE_PIPE
+
+#elif defined(SOLARIS)
+
+#if defined(ENABLE_IPV6)
+#define HAS_IPV6
+#endif
+#define AUTH_DBM
+#define BSD_RLIMIT
+#undef BSD_SIGNALS
+#define DAEMON_NEEDS_SEMAPHORE
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW|RTLD_FIRST
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define HAVE_STRTOK_R
+#define HAVE_TIME_R 3 /* arg count */
+#define NEED_CRYPT_H
+#define NEED_FILIO
+#define NEED_GHN_PROTO
+#define NET_SOCKETS
+#if OSVERSION > 504 
+#define SA_HANDLER_T(x) x 
+#endif
+#if OSVERSION >= 506 
+#undef NEED_GHN_PROTO 
+#endif
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#elif defined (SONY)
+
+#define AUTH_DBM
+#undef BSD_RLIMIT
+#define DAEMON_NEEDS_SEMAPHORE
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAVE_ATEXIT
+#define NEED_CRYPT_H
+#define NEED_FILIO
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#elif defined(SUNOS4)
+
+#define AUTH_DBM
+#define BSD_MAIL
+#define BSD_RLIMIT
+#define BSD_SIGNALS
+#define BSD_TIME
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS 1
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATFS
+#undef HAVE_ATEXIT
+#undef NEED_CRYPT_H
+#define NEED_CRYPT_PROTO
+#define NEED_FILIO
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#elif defined(UNIXWARE)
+
+#define AUTH_DBM
+#undef BSD_RLIMIT
+#define DAEMON_UNIX_MOBRULE
+#define DLL_CAPABLE
+#define DLL_DLOPEN
+#define DLL_DLOPEN_FLAGS RTLD_NOW
+#define DNS_CACHE
+#define FILE_INHERIT_FCNTL
+#define FILE_MMAP_FLAGS MAP_SHARED
+#define HAS_STATVFS
+#define HAVE_ATEXIT
+#define NEED_CRYPT_H
+#define NEED_FILIO
+#define NEED_GHN_PROTO
+#define NEED_SETEID_PROTO /* setegid, seteuid */
+#define NET_SOCKETS
+#define SEM_FLOCK
+#define SHMEM_MMAP_FLAGS MAP_SHARED
+
+#ifndef boolean
+#define boolean boolean
+#endif
+
+#elif defined (XP_WIN32)      /* Windows NT */
+
+#include <wtypes.h>
+#include <winbase.h>
+
+#define AUTH_DBM
+#define DAEMON_WIN32
+#define DLL_CAPABLE
+#define DLL_WIN32
+#define DNS_CACHE
+#define LOG_BUFFERING
+#define HAVE_STRFTIME /* no cftime */
+#define NEED_CRYPT_PROTO
+#define NEEDS_WRITEV
+#define NET_SOCKETS
+#define NO_DOMAINNAME
+#ifdef BUILD_DLL
+#if defined (NSAPI_PUBLIC)
+#undef  NSAPI_PUBLIC
+#endif
+#define NSAPI_PUBLIC __declspec(dllexport)
+#else
+#if defined (NSAPI_PUBLIC)
+#undef  NSAPI_PUBLIC
+#endif
+#define NSAPI_PUBLIC
+#endif /* BUILD_DLL */
+#define SEM_WIN32
+#define THREAD_ANY
+#define THREAD_NSPR_KERNEL
+#define USE_NSPR
+#define USE_STRFTIME /* no cftime */
+#define FILE_DEV_NULL "\\\\.\NUL"
+
+#endif	/* Windows NT */
+
+/* --- Begin defaults for values not defined above --- */
+
+#ifndef DAEMON_LISTEN_SIZE
+#define DAEMON_LISTEN_SIZE 128
+#endif /* !DAEMON_LISTEN_SIZE */
+
+#ifndef NSAPI_PUBLIC
+#define NSAPI_PUBLIC
+#endif
+
+#ifndef SA_HANDLER_T
+#define SA_HANDLER_T(x) (void (*)())x 
+#endif
+
+#ifndef THROW_HACK
+#define THROW_HACK /* as nothing */
+#endif
+
+#ifndef FILE_DEV_NULL
+#define FILE_DEV_NULL "/dev/null"
+#endif
+
+/* --- End defaults for values not defined above --- */
+
+/* --- Begin the great debate --- */
+
+/* NS_MAIL builds sec-key.c which calls systhread_init, which requires */
+/* that USE_NSPR is defined when systhr.c is compiled.  --lachman */
+/* MCC_PROXY does the same thing now --nbreslow -- LIKE HELL --ari */
+#if (defined(MCC_HTTPD) || defined(MCC_ADMSERV) || defined(MCC_PROXY) || defined(NS_MAIL)) && defined(XP_UNIX)
+#define USE_NSPR
+/* XXXrobm This is UNIX-only for the moment */
+#define LOG_BUFFERING
+#ifdef SW_THREADS
+#define THREAD_NSPR_USER
+#else
+#define THREAD_NSPR_KERNEL
+#endif
+#define THREAD_ANY
+#endif
+
+/* --- End the great debate --- */
+
+#ifndef APSTUDIO_READONLY_SYMBOLS
+
+#ifndef NSPR_PRIO_H
+//include "prio.h"
+#define NSPR_PRIO_H
+#endif /* !NSPR_PRIO_H */
+
+/*
+ * These types have to be defined early, because they are defined
+ * as (void *) in the public API.
+ */
+
+#ifndef SYS_FILE_T
+typedef PRFileDesc *SYS_FILE;
+#define SYS_FILE_T PRFileDesc *
+#endif /* !SYS_FILE_T */
+
+#ifndef SYS_NETFD_T
+typedef PRFileDesc *SYS_NETFD;
+#define SYS_NETFD_T PRFileDesc *
+#endif /* !SYS_NETFD_T */
+
+#ifdef SEM_WIN32
+
+typedef HANDLE SEMAPHORE;
+#define SEMAPHORE_T HANDLE
+#define SEM_ERROR NULL
+/* That oughta hold them (I hope) */
+#define SEM_MAXVALUE 32767
+
+#elif defined(SEM_FLOCK)
+
+//define SEMAPHORE_T int
+//typedef int SEMAPHORE;
+//define SEM_ERROR -1
+
+#elif defined(SEM_POSIX)
+
+#define SEM_ERROR ((void *)(-1))
+typedef	void* SEMAPHORE_T;
+
+#else /* ! SEM_WIN32 */
+
+typedef int SEMAPHORE;
+#define SEMAPHORE_T int
+#define SEM_ERROR -1
+
+#endif /* SEM_WIN32 */
+
+#endif /* !APSTUDIO_READONLY_SYMBOLS */
+
+#ifndef XP_CPLUSPLUS
+#ifdef __cplusplus
+#define XP_CPLUSPLUS
+#endif /* __cplusplus */
+#endif /* !XP_CPLUSPLUS */
+
+#endif /* BASE_SYSTEMS_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/systhr.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,182 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * systhr.c: Abstracted threading mechanisms
+ * 
+ * Rob McCool
+ */
+
+
+#include "systhr.h"
+#include "ereport.h"
+
+#include "prinit.h"
+#include "prthread.h"
+#include "private/pprthred.h"
+
+#include "systems.h"
+
+#ifdef XP_UNIX
+#include <poll.h>
+#endif
+
+#ifdef THREAD_WIN32
+#include <process.h>
+
+typedef struct {
+    HANDLE hand;
+    DWORD id;
+} sys_thread_s;
+
+#endif
+
+#define DEFAULT_STACKSIZE (64*1024)
+
+static unsigned long _systhr_stacksize = DEFAULT_STACKSIZE;
+
+NSAPI_PUBLIC 
+void systhread_set_default_stacksize(unsigned long size)
+{
+	_systhr_stacksize = size;
+}
+
+NSAPI_PUBLIC 
+SYS_THREAD systhread_start(int prio, int stksz, thrstartfunc fn, void *arg)
+{
+    PRThread *ret = PR_CreateThread(PR_USER_THREAD, (void (*)(void *))fn,
+				    (void *)arg, (PRThreadPriority)prio, 
+				    PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD,
+                                    stksz ? stksz : _systhr_stacksize);
+    return (void *) ret;
+}
+
+
+NSAPI_PUBLIC SYS_THREAD systhread_current(void)
+{
+    return PR_GetCurrentThread();
+}
+
+NSAPI_PUBLIC void systhread_yield(void)
+{
+    PR_Sleep(PR_INTERVAL_NO_WAIT);
+}
+
+
+NSAPI_PUBLIC void systhread_timerset(int usec)
+{
+   /* This is an interesting problem.  If you ever do turn on interrupts
+    * on the server, you're in for lots of fun with NSPR Threads
+   PR_StartEvents(usec); */
+}
+
+
+NSAPI_PUBLIC 
+SYS_THREAD systhread_attach(void)
+{
+    PRThread *ret;
+    ret = PR_AttachThread(PR_USER_THREAD, PR_PRIORITY_NORMAL, NULL);
+
+    return (void *) ret;
+}
+
+NSAPI_PUBLIC
+void systhread_detach(SYS_THREAD thr)
+{
+    /* XXXMB - this is not correct! */
+    PR_DetachThread();
+}
+
+NSAPI_PUBLIC void systhread_terminate(SYS_THREAD thr)
+{
+    PR_Interrupt((PRThread *)thr);
+}
+
+NSAPI_PUBLIC void systhread_sleep(int milliseconds)
+{
+#ifdef XP_WIN32
+    PR_Sleep(PR_MillisecondsToInterval(milliseconds));
+#else
+    /* poll() is more efficient than PR_Sleep() */
+    if (milliseconds > 0)
+        poll(NULL, NULL, milliseconds);
+#endif
+}
+
+NSAPI_PUBLIC void systhread_init(char *name)
+{
+    if (!PR_Initialized()) {
+        PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 256);
+    }
+    // XXX: ruslan - this bug can potentially exist on all plafroms due to
+    //	possible priority inversion on NSPR spin locks. This code will
+    //	need to be remove as we get new NSPR drop
+    // <WORKAROUND>
+    /* VB: This is to fix bug# 364813 coupled with NSPR not wanting to patch
+           their problems. The fix is to prevent NSPR itself from
+           using atomic stacks.
+    */
+    // ruslan: this problem exists on DEC also. We will roll it back when
+    //	we have the right fix from NSPR group. It has smth. to do with
+    //	atomic operations on DEC, it's an assembly code which is different
+    //	for every platform. NSPR_FD_CACHE_SIZE_HIGH env var will cause the
+    //	same effect as this fix. Debug version of NSPR always works as it doesn't
+    //  have FD stack.
+
+    int maxPRFdCache = 8192;
+    PR_SetFDCacheSize(0, maxPRFdCache);
+    // </WORKAROUND>
+}
+
+
+NSAPI_PUBLIC int systhread_newkey()
+{
+    uintn newkey;
+
+    PR_NewThreadPrivateIndex(&newkey, NULL);
+    return (newkey);
+}
+
+NSAPI_PUBLIC void *systhread_getdata(int key)
+{
+    return PR_GetThreadPrivate(key);
+}
+
+NSAPI_PUBLIC void systhread_setdata(int key, void *data)
+{
+    PR_SetThreadPrivate(key, data);
+}
+
+NSAPI_PUBLIC void systhread_dummy(void)
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/systhr.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,114 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_SYSTHR_H
+#define BASE_SYSTHR_H
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * systhr.h: Abstracted threading mechanisms
+ * 
+ * Rob McCool
+ */
+
+#ifndef NETSITE_H
+#include "netsite.h"
+#include "nsapi.h"
+#include "nspr.h"
+#endif /* !NETSITE_H */
+
+#define THREAD_ANY
+#ifdef THREAD_ANY
+
+/* --- Begin function prototypes --- */
+
+#define INTNSAPI
+#ifdef INTNSAPI
+
+NSPR_BEGIN_EXTERN_C
+
+typedef void (*thrstartfunc)(void *);
+NSAPI_PUBLIC
+SYS_THREAD INTsysthread_start(int prio, int stksz, thrstartfunc fn, void *arg);
+
+NSAPI_PUBLIC SYS_THREAD INTsysthread_current(void);
+
+NSAPI_PUBLIC void INTsysthread_yield(void);
+
+NSAPI_PUBLIC SYS_THREAD INTsysthread_attach(void);
+
+NSAPI_PUBLIC void INTsysthread_detach(SYS_THREAD thr);
+
+NSAPI_PUBLIC void INTsysthread_terminate(SYS_THREAD thr);
+
+NSAPI_PUBLIC void INTsysthread_sleep(int milliseconds);
+
+NSAPI_PUBLIC void INTsysthread_init(char *name);
+
+NSAPI_PUBLIC void INTsysthread_timerset(int usec);
+
+NSAPI_PUBLIC int INTsysthread_newkey(void);
+
+NSAPI_PUBLIC void *INTsysthread_getdata(int key);
+
+NSAPI_PUBLIC void INTsysthread_setdata(int key, void *data);
+
+NSAPI_PUBLIC 
+void INTsysthread_set_default_stacksize(unsigned long size);
+
+NSPR_END_EXTERN_C
+
+/* --- End function prototypes --- */
+
+#define systhread_start INTsysthread_start
+#define systhread_current INTsysthread_current
+#define systhread_yield INTsysthread_yield
+#define systhread_attach INTsysthread_attach
+#define systhread_detach INTsysthread_detach
+#define systhread_terminate INTsysthread_terminate
+#define systhread_sleep INTsysthread_sleep
+#define systhread_init INTsysthread_init
+#define systhread_timerset INTsysthread_timerset
+#define systhread_newkey INTsysthread_newkey
+#define systhread_getdata INTsysthread_getdata
+#define systhread_setdata INTsysthread_setdata
+#define systhread_set_default_stacksize INTsysthread_set_default_stacksize
+
+#endif /* INTNSAPI */
+
+#endif /* THREAD_ANY */
+
+#endif /* !BASE_SYSTHR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/thrpool.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,122 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "thrpool.h"
+
+
+
+threadpool_t* threadpool_new(int n) {
+    threadpool_t *pool = malloc(sizeof(threadpool_t));
+    pool->queue = NULL;
+    pool->queue_len = 0;
+
+    pthread_mutex_init(&pool->queue_lock, NULL);
+    pthread_mutex_init(&pool->avlbl_lock, NULL);
+    pthread_cond_init(&pool->available, NULL);
+
+    /* create pool threads */
+    for(int i=0;i<n;i++) {
+        pthread_t t;
+        if (pthread_create(&t, NULL, threadpool_func, pool) != 0) {
+            perror("Error: threadpool_new: pthread_create");
+            return NULL;
+        }
+    }
+
+    return pool;
+}
+
+void* threadpool_func(void *data) {
+    threadpool_t *pool = (threadpool_t*)data;
+
+    for(;;) {
+        threadpool_job *job = threadpool_get_job(pool);
+        if(job == NULL) {
+            break;
+        }
+
+        job->callback(job->data);
+
+        free(job);
+    }
+    return NULL;
+}
+
+threadpool_job* threadpool_get_job(threadpool_t *pool) {
+    pthread_mutex_lock(&pool->queue_lock);
+
+    threadpool_job *job = NULL;
+    while(job == NULL) {
+        if(pool->queue_len == 0) {
+            pthread_cond_wait(&pool->available, &pool->queue_lock);
+            continue;
+        } else {
+            pool_queue_t *q = pool->queue;
+            job = q->job;
+            pool->queue = q->next;
+            pool->queue_len--;
+            free(q);
+        }
+    }
+
+    pthread_mutex_unlock(&pool->queue_lock);
+
+    return job;
+}
+
+void threadpool_run(threadpool_t *pool, job_callback_f func, void *data) {
+    threadpool_job *job = malloc(sizeof(threadpool_job));
+    job->callback = func;
+    job->data = data;
+
+    pool_queue_t *q = malloc(sizeof(pool_queue_t));
+    q->job = job;
+    q->next = NULL;
+
+    pthread_mutex_lock(&pool->queue_lock);
+    if(pool->queue == NULL) {
+        pool->queue = q;
+    } else {
+        pool_queue_t *last_elem = pool->queue;
+        while(last_elem->next != NULL) {
+            last_elem = last_elem->next;
+        }
+        last_elem->next = q;
+    }
+    pool->queue_len++;
+
+    if(pool->queue_len == 1) {
+        pthread_cond_signal(&pool->available);
+    }
+
+    pthread_mutex_unlock(&pool->queue_lock);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/thrpool.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,71 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef THREADPOOL_H
+#define	THREADPOOL_H
+
+#include <pthread.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _pool_queue pool_queue_t;
+typedef struct _thread_pool {
+    pthread_mutex_t queue_lock;
+    pthread_mutex_t avlbl_lock;
+    pthread_cond_t  available;
+    int             queue_len;
+    pool_queue_t    *queue;
+} threadpool_t;
+
+typedef void*(*job_callback_f)(void *data);
+typedef struct _threadpool_job {
+    job_callback_f  callback;
+    void            *data;
+} threadpool_job;
+
+struct _pool_queue {
+    threadpool_job   *job;
+    pool_queue_t     *next;
+};
+
+
+threadpool_t* threadpool_new(int n);
+
+void* threadpool_func(void *data);
+
+threadpool_job* threadpool_get_job(threadpool_t *pool);
+
+void threadpool_run(threadpool_t *pool, job_callback_f func, void *data);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* THREADPOOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/uri.cpp	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,561 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef XP_WIN32
+#define _MBCS
+#include <windows.h>
+#include <mbctype.h>
+#endif
+
+#include "util.h"
+#include "pool.h"
+//include "frame/conf_api.h"
+//include "support/stringvalue.h"
+
+#ifdef XP_WIN32
+static PRBool _getfullpathname = -1;
+#endif /* XP_WIN32 */
+
+/* --------------------------- util_uri_is_evil --------------------------- */
+
+static inline int allow_dbcs_uri()
+{
+    /*
+    static int flagDbcsUri = -1;
+    if (flagDbcsUri == -1) {
+        flagDbcsUri = StringValue::getBoolean(conf_findGlobal("DbcsUri"));
+    }
+    return flagDbcsUri;
+    */
+    return PR_FALSE;
+}
+
+#ifdef XP_WIN32
+void set_fullpathname(PRBool b)
+{
+    _getfullpathname = b;
+}
+#endif  /*XP_WIN32*/
+
+NSAPI_PUBLIC int util_uri_is_evil_internal(const char *t, int allow_tilde, int allow_dot_dir)
+{
+#ifdef XP_WIN32
+    int flagDbcsUri = allow_dbcs_uri();
+#endif // XP_WIN32
+    PRBool flagEmptySegment = PR_FALSE;
+    register int x;
+
+    for (x = 0; t[x]; ++x) {
+        if (t[x] == '/') {
+            if (flagEmptySegment)
+                return 1; // "/;a/b"
+#ifdef XP_WIN32
+            if (t[x+1] == '/' && x != 0)
+#else
+            if (t[x+1] == '/')
+#endif
+                return 1;
+            if (t[x+1] == ';')
+                flagEmptySegment = PR_TRUE; // "/;a/b" is evil, "/a/;b" is not
+            if (t[x+1] == '.') {
+                /* "." at end of line is always prohibited */
+                if (t[x+2] == '\0')
+                    return 1;
+
+                /* "." as a path segment is prohibited conditionally */
+                if (!allow_dot_dir && (t[x+2] == '/' || t[x+2] == ';'))
+                    return 1;
+
+                /* ".." as a path segment is always prohibited */
+                if (t[x+2] == '.' && (t[x+3] == '/' || t[x+3] == ';' || t[x+3] == '\0'))
+                    return 1;
+            }
+        }
+#ifdef XP_WIN32
+        // Don't allow '~' in the filename.  On some filesystems a long name
+        // (e.g. longfilename.htm) can be accessed using '~' bypassing any ACL
+        // checks (e.g. longfi~1.htm).
+        if (!allow_tilde && (t[x] == '~')) {
+            return 1;
+        }
+
+        // Do not allow ':' apart from drive letter. Windows filestream
+        // will treat filename::$DATA as a plain file & display content.
+        // So block it to prevent source viewing vulnerability.
+        if ((t[x] == ':') && x > 1) {
+            return 1;
+        }
+
+        // On NT, the directory "abc...." is the same as "abc"
+        // The only cheap way to catch this globally is to disallow
+        // names with the trailing "."s.  Hopefully this is not over
+        // restrictive.
+        // Also trailing spaces in names can wreak havoc on ACL checks
+        // and name resolution.  Therefore, ban them on the end of a
+        // name.
+        if (((t[x] == '.') || (t[x] == ' ')) &&
+            ((t[x+1] == ';') || (t[x+1] == '/') || (t[x+1] == '\0')))
+        {
+            return 1;
+        }
+
+        // Skip past the second byte of two byte DBCS characters.  Bug 353999
+        if (flagDbcsUri && t[x+1] && IsDBCSLeadByte(t[x])) x++;
+#endif // XP_WIN32
+    }
+    return 0;
+}
+
+NSAPI_PUBLIC int util_uri_is_evil(const char *t)
+{
+    return util_uri_is_evil_internal(t, 0, 0);
+}
+
+
+/* -------------------- util_uri_unescape_and_normalize -------------------- */
+
+#ifdef XP_WIN32
+/* The server calls this function to unescape the URI and also normalize
+ * the uri.  Normalizing the uri converts all "\" characters in the URI
+ * and pathinfo portion to "/".  Does not touch "\" in query strings.
+ */
+NSAPI_PUBLIC
+int util_uri_unescape_and_normalize(pool_handle_t *pool, char *s, char *unnormalized)
+{
+    if(!(util_uri_unescape_strict(s)))
+        return 0;
+
+    if (unnormalized) strcpy(unnormalized, s);
+
+    if (_getfullpathname == -1)
+        _getfullpathname = (_getmbcp() != 0);
+
+    /* Get canonical filename Bugid: 4672869 */
+    if(_getfullpathname && strcmp(s, "*") && (*s == '/' ) ) {
+        char *pzAbsPath = NULL;
+        int pathlen = 0;
+        int len = 0;
+        int ret = 0;
+        if(!(pzAbsPath = util_canonicalize_uri(pool, s, strlen(s), NULL))) {
+            //Error canonicalizing; possibly pointing out of docroot
+            return 0;
+        }
+        char *pzPath = (char *)MALLOC(MAX_PATH + 1); /* reserved byte for trailing slash */
+        char *pzFilename = NULL;
+
+        /* If required length of the buffer(pzPath) is more than the allocated one i.e. MAX_PATH(neglecting the reserved byte for trailing slash), return BAD REQUEST. This will happen if length of uri is more than the specified uri length(257) for MBCS windows */
+        if(!(ret = GetFullPathName(pzAbsPath, MAX_PATH, pzPath, &pzFilename)) || ( ret > MAX_PATH)){
+            FREE(pzAbsPath);
+            FREE(pzPath);
+            return 0;
+        }
+        len = strlen(pzAbsPath);
+        pathlen = strlen( pzPath );
+
+        /*  GetFullPathName behaves differently in case of WINNT and WIN2K */
+        /* o/p string doesn't contain the trailing slash in case of WINNT */
+        /* if i/p is /foo/, we get o/p as c:\foo instead of c:\foo\ */
+        /* Checking if i/p has trailing slash and o/p doesn't have, then */
+        /* adding slash */
+        if ( pzAbsPath[len-1] == '/' && pzPath[pathlen-1] != '\\')
+            strcat( pzPath, "\\");
+        FREE(pzAbsPath);
+        pzFilename = strchr(pzPath, '\\');
+        if(!pzFilename) {
+            FREE(pzPath);
+            return 0;
+        }
+        strcpy(s, pzFilename);
+        FREE(pzPath);
+    }
+
+    util_uri_normalize_slashes(s);
+
+    return 1;
+}
+#endif /* XP_WIN32 */
+
+
+/* ---------------------- util_uri_normalize_slashes ---------------------- */
+
+void util_uri_normalize_slashes(char *s)
+{
+#ifdef XP_WIN32
+    int flagDbcsUri = allow_dbcs_uri();
+
+    while (*s) {
+        if (*s == '\\') {
+            // Normalize '\\' to '/'
+            *s = '/';
+        } else if (flagDbcsUri && s[1] && IsDBCSLeadByte(s[0])) {
+            // Skip past two byte DBCS characters.  Bug 353999
+            s++;
+        }
+        s++;
+    }
+#endif
+}
+
+
+/* --------------------------- util_uri_escape ---------------------------- */
+/*
+NSAPI_PUBLIC char *util_uri_escape(char *od, const char *s)
+{
+    int flagDbcsUri = allow_dbcs_uri();
+    char *d;
+
+    if (!od)
+        od = (char *) MALLOC((strlen(s)*3) + 1);
+    d = od;
+
+    while (*s) {
+        if (strchr("% ?#:+&*\"'<>\r\n", *s)) {
+            util_sprintf(d, "%%%02x", (unsigned char)*s);
+            ++s; d += 3;
+        }
+#ifdef XP_WIN32
+        else if (flagDbcsUri && s[1] && IsDBCSLeadByte(s[0]))
+#else
+        // Treat any character with the high bit set as a DBCS lead byte
+        else if (flagDbcsUri && s[1] && (s[0] & 0x80))
+#endif
+	{
+            // Escape the second byte of DBCS characters.  The first byte will
+            // have been escaped already.  IE translates all unescaped '\\'s
+            // into '/'.
+            // Bug 353999
+            util_sprintf(d, "%%%02x%%%02x", (unsigned char)s[0], (unsigned char)s[1]);
+            s += 2; d += 6;
+        }
+        else if (0x80 & *s) {
+            util_sprintf(d, "%%%02x", (unsigned char)*s);
+            ++s; d += 3;
+        } else {
+            *d++ = *s++;
+        }
+    }
+    *d = '\0';
+    return od;
+}
+*/
+
+
+/* --------------------------- util_url_escape ---------------------------- */
+/*
+NSAPI_PUBLIC char *util_url_escape(char *od, const char *s)
+{
+    int flagDbcsUri = allow_dbcs_uri();
+    char *d;
+
+    if (!od)
+        od = (char *) MALLOC((strlen(s)*3) + 1);
+    d = od;
+
+    while (*s) {
+        if (strchr("% +*\"'<>\r\n", *s)) {
+            util_sprintf(d, "%%%02x", (unsigned char)*s);
+            ++s; d += 3;
+        }
+#ifdef XP_WIN32
+        else if (flagDbcsUri && s[1] && IsDBCSLeadByte(s[0]))
+#else
+        // Treat any character with the high bit set as a DBCS lead byte
+        else if (flagDbcsUri && s[1] && (s[0] & 0x80))
+#endif
+	{
+            // Escape the second byte of DBCS characters.  The first byte will
+            // have been escaped already.  IE translates all unescaped '\\'s
+            // into '/'.
+            // Bug 353999
+            util_sprintf(d, "%%%02x%%%02x", (unsigned char)s[0], (unsigned char)s[1]);
+            s += 2; d += 6;
+        }
+        else if (0x80 & *s) {
+            util_sprintf(d, "%%%02x", (unsigned char)*s);
+            ++s; d += 3;
+        } else {
+            *d++ = *s++;
+        }
+    }
+    *d = '\0';
+    return od;
+}
+*/
+
+/* ------------------------- util_uri_strip_params ------------------------- */
+
+NSAPI_PUBLIC char* util_uri_strip_params(char *uri)
+{
+    // As per RFC2396, URI path segments can contain parameters beginning with
+    // ';'.  These parameters must be removed from the ppath.  Bug 418271
+    char* out;
+    if (out = strchr(uri, ';')) {
+        char* in = out;
+        while (*in) {
+            if (*in == ';') {
+                // Skip past parameter
+                do in++; while (*in && *in != '/');
+            } else {
+                // Copy non-parameter path data
+                *out++ = *in++;
+            }
+        }
+        *out = 0;
+    }
+    return uri;
+}
+
+
+/* ------------------------ util_canonicalize_uri ------------------------- */
+
+/*
+ * rewrite rules:
+ *   //                       ->  '/'
+ *   /./                      ->  '/'
+ *   /.\0                     ->  '/'
+ *   /foo/../                 ->  '/'
+ *   /foo/..\0                ->  '/'
+ *
+ * Allocate a new string, as otherwise replacing in-line would impact the
+ * RequestURI, i.e. original URI in the request.
+ * Some guidelines in: http://www.ietf.org/rfc/rfc2396.txt
+ *      Uniform Resource Identifiers (URI): Generic Syntax
+ */
+NSAPI_PUBLIC char* util_canonicalize_uri(pool_handle_t *pool, const char *uri, int len, int *pcanonlen)
+{
+    PRBool success = PR_TRUE;
+    const char *in_ptr = uri;
+    int in = 0;
+    int in_len = len;
+
+    PR_ASSERT(uri != NULL);
+
+    char* canonPath = (char *)pool_malloc(pool, in_len+1);
+    char* out_ptr = canonPath;
+
+    if (!canonPath) {
+        success = PR_FALSE;
+        goto done;
+    }
+
+
+    /* in goes from 0 .. sURIPath.len-1; out_ptr points to
+     * space where next char from input would be copied to
+     */
+    while (in < in_len) {
+
+        /* If the character isn't '/' then copy it out and move on*/
+        if (in_ptr[0] != '/') {
+            *out_ptr++ = *in_ptr++;
+            in++;
+            continue;
+        }
+
+        /* found '/' and reached end of sURIPath, done */
+        if (in+1 >= in_len) {
+            *out_ptr++ = *in_ptr++;
+            in++;
+            break;
+        }
+
+        /* we have '/' and there are more chars in the string */
+        switch(in_ptr[1]) {
+        case '/':
+            /*  '//' => '/'  */
+            in_ptr++;
+            in++;
+            break;
+
+        case '.':
+            /* we have "/." so far */
+            if (in+2 >= in_len) {
+                /*  the string ends after this; basically ignore '.'
+                 *  make sure the ending / is transferred to output.
+                 */
+                *out_ptr++ = *in_ptr++;
+                goto done;
+            }
+
+            /* more chars after "/."; see if it is a '/' */
+            if (in_ptr[2] == '/') {
+                /* in deed, compact "/./" => "/"; */
+                in_ptr += 2;
+                in += 2;
+                break;
+            }
+
+            if (in_ptr[2] != '.') {
+                /* "/.x" where x is not '.'; copy as is */
+                *out_ptr++ = *in_ptr++;
+                in++;
+                break;
+            }
+
+            /* we have "/.." so far. see if we have either string
+             * ending after this or '/' following.
+             */
+            if (in+3 < in_len && in_ptr[3] != '/' && in_ptr[3] != ';') {
+                /* we have "/..x" here; so copy as is */
+                *out_ptr++ = *in_ptr++;
+                in++;
+            }
+            else {
+                /* we have "foo/../" or "foo/.." at the end; */
+                if (out_ptr == canonPath) {
+                    /* oops, we found "/../" pointing out of docroot */
+                    success = PR_FALSE;
+                    goto done;
+                }
+
+                /* remove the previous segment in the output */
+                for (out_ptr--;
+                     out_ptr != canonPath && out_ptr[0] != '/';
+                     out_ptr--); /* Empty Loop */
+
+                /* point to '/' if the last segment ended with .. then
+                 * leave the '/' before the previous segment.
+                 */
+                if(in+3 == in_len)
+                    out_ptr++;
+
+                /* skip the input as well */
+                in_ptr += 3;
+                in += 3;
+            }
+            break;
+
+        default:
+            /* If we already have '/' at out_ptr we donot need to copy */
+            if (out_ptr == canonPath || *(out_ptr-1) != '/')
+                *out_ptr++ = *in_ptr;
+            in_ptr++; in++;
+            break;
+        }
+    }
+
+done:
+    int canonLen = 0;
+
+    if (success) {
+        /* the path looks fine; return the canonicalized form */
+        canonLen = out_ptr - canonPath;
+        canonPath[canonLen] = '\0';
+    } else {
+        /* error canonicalizing */
+        pool_free(pool, canonPath);
+        canonPath = NULL;
+    }
+
+    if (pcanonlen)
+        *pcanonlen = canonLen;
+
+    return canonPath;
+}
+
+
+/* ---------------------- util_canonicalize_redirect ---------------------- */
+
+NSAPI_PUBLIC char* util_canonicalize_redirect(pool_handle_t *pool, const char *baseUri, const char *newUri)
+{
+    PR_ASSERT(baseUri != NULL);
+
+    if (*newUri == '/')
+        return util_canonicalize_uri(pool, newUri, strlen(newUri), NULL);
+
+    int bLen = strlen(baseUri);
+    if (bLen > 0 && baseUri[bLen - 1] != '/') {
+        while (bLen > 0 && baseUri[bLen - 1] != '/')
+            bLen--;
+    }
+
+    int pLen = strlen(newUri) + bLen + 1; // 1 for slash
+    char *pUri = (char *)pool_malloc(pool, pLen + 1);
+    if (!pUri)
+        return PR_FALSE;
+
+    memcpy(pUri, baseUri, bLen);
+    pUri[bLen] = '/';
+    strcpy(pUri + bLen + 1, newUri);
+
+    char *rval = util_canonicalize_uri(pool, pUri, pLen, NULL);
+    pool_free(pool, pUri);
+
+    return rval;
+}
+
+
+/* ------------------------ util_host_port_suffix ------------------------- */
+
+NSAPI_PUBLIC char *util_host_port_suffix(char *h)
+{
+    return (char *)util_host_port_suffix((const char *)h);
+}
+
+const char *util_host_port_suffix(const char *h)
+{
+    /* Return a pointer to the colon preceding the port number in a hostname.
+     *
+     * util_host_port_suffix("foo.com:80") = ":80"
+     * util_host_port_suffix("foo.com") = NULL
+     * util_host_port_suffix("[::]:80") = ":80"
+     * util_host_port_suffix("[::]") = NULL
+     */
+
+    if (h == NULL)
+        return h;
+
+    for (;;) {
+        /* Find end of host, beginning of ":port", or an IPv6 address */
+        for (;;) {
+            register char c = *h;
+
+            if (c == '\0')
+                return NULL; /* end of host, no port found */
+
+            if (c == '/')
+                return NULL; /* end of host, no port found */
+
+            if (c == ':')
+                return h; /* found port */
+
+            if (c == '[')
+                break; /* skip IPv6 address */
+
+            h++;
+        }
+
+        /* Skip IPv6 address */
+        while (*h != '\0' && *h != ']')
+            h++;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/util.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,133 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * util.c: A hodge podge of utility functions and standard functions which 
+ *         are unavailable on certain systems
+ * 
+ * Rob McCool
+ */
+
+#ifdef XP_UNIX
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include "prthread.h"
+#endif /* XP_UNIX */
+
+
+#include "nspr.h"
+#include "nsapi.h"
+
+#include "util.h"
+
+/*
+NSAPI_PUBLIC int util_getboolean(const char *v, int def) {
+    if(v[0] == 'T' || v[0] == 't') {
+        return 1;
+    }
+    if(v[0] == 'F' || v[0] == 'f') {
+        return 0;
+    }
+    return def;
+}
+*/
+
+NSAPI_PUBLIC int INTutil_getboolean(const char *v, int def) {
+    if(v[0] == 'T' || v[0] == 't') {
+        return 1;
+    }
+    if(v[0] == 'F' || v[0] == 'f') {
+        return 0;
+    }
+    return def;
+}
+
+
+/* ------------------------------ util_itoa ------------------------------- */
+/*
+NSAPI_PUBLIC int util_itoa(int i, char *a)
+{
+    int len = util_i64toa(i, a);
+
+    PR_ASSERT(len < UTIL_ITOA_SIZE);
+
+    return len;
+}
+*/
+NSAPI_PUBLIC int INTutil_itoa(int i, char *a) {
+    return INTutil_i64toa(i, a);
+}
+
+
+/* ----------------------------- util_i64toa ------------------------------ */
+
+/*
+ * Assumption: Reversing the digits will be faster in the general case
+ * than doing a log10 or some nasty trick to find the # of digits.
+ */
+
+NSAPI_PUBLIC int INTutil_i64toa(PRInt64 i, char *a)
+{
+    register int x, y, p;
+    register char c;
+    int negative;
+
+    negative = 0;
+    if(i < 0) {
+        *a++ = '-';
+        negative = 1;
+        i = -i;
+    }
+    p = 0;
+    while(i > 9) {
+        a[p++] = (i%10) + '0';
+        i /= 10;
+    }
+    a[p++] = i + '0';
+
+    if(p > 1) {
+        for(x = 0, y = p - 1; x < y; ++x, --y) {
+            c = a[x];
+            a[x] = a[y];
+            a[y] = c;
+        }
+    }
+    a[p] = '\0';
+
+    //PR_ASSERT(p + negative < UTIL_I64TOA_SIZE);
+
+    return p + negative;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/util.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,356 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ *
+ * THE BSD LICENSE
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer. 
+ * Redistributions in binary form must reproduce the above copyright notice, 
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution. 
+ *
+ * Neither the name of the  nor the names of its contributors may be
+ * used to endorse or promote products derived from this software without 
+ * specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef BASE_UTIL_H
+#define BASE_UTIL_H
+
+#include "netsite.h"
+
+#ifndef NOINTNSAPI
+#define INTNSAPI
+#endif /* !NOINTNSAPI */
+
+/*
+ * util.h: A hodge podge of utility functions and standard functions which 
+ *         are unavailable on certain systems
+ * 
+ * Rob McCool
+ */
+
+/* Needed for various reentrant functions */
+#define DEF_CTIMEBUF 26
+#define DEF_ERRBUF 256
+#define DEF_PWBUF 1024
+
+#ifndef BASE_BUFFER_H
+//include "buffer.h"    /* filebuf for getline */
+#endif /* !BASE_BUFFER_H */
+
+/*
+ * UTIL_ITOA_SIZE is the minimum size for buffers passed to util_itoa().
+ */
+#define UTIL_ITOA_SIZE 12
+
+/*
+ * UTIL_I64TOA_SIZE is the minimum size for buffers passed to util_i64toa().
+ */
+#define UTIL_I64TOA_SIZE 21
+
+/* --- Begin common function prototypes --- */
+
+#ifdef INTNSAPI
+
+NSPR_BEGIN_EXTERN_C
+
+NSAPI_PUBLIC
+int INTutil_init_PRNetAddr(PRNetAddr * naddr, char * ipstr, int iplen, int type);
+
+NSAPI_PUBLIC
+int INTutil_getline(filebuffer *buf, int lineno, int maxlen, char *l);
+
+NSAPI_PUBLIC char **INTutil_env_create(char **env, int n, int *pos);
+
+NSAPI_PUBLIC char *INTutil_env_str(const char *name, const char *value);
+
+NSAPI_PUBLIC void INTutil_env_replace(char **env, const char *name, const char *value);
+
+NSAPI_PUBLIC void INTutil_env_free(char **env);
+
+NSAPI_PUBLIC char **INTutil_env_copy(char **src, char **dst);
+
+NSAPI_PUBLIC char *INTutil_env_find(char **env, const char *name);
+
+NSAPI_PUBLIC char **util_argv_parse(const char *cmdline);
+
+NSAPI_PUBLIC char *INTutil_hostname(void);
+
+NSAPI_PUBLIC int INTutil_chdir2path(char *path);
+
+NSAPI_PUBLIC int INTutil_chdir(const char *path);
+
+NSAPI_PUBLIC char *INTutil_getcwd(void);
+
+NSAPI_PUBLIC int INTutil_is_mozilla(char *ua, char *major, char *minor);
+
+NSAPI_PUBLIC int INTutil_is_url(const char *url);
+
+NSAPI_PUBLIC int INTutil_mstr2num(const char *s);
+
+NSAPI_PUBLIC int INTutil_later_than(const struct tm *lms, const char *ims);
+
+NSAPI_PUBLIC int INTutil_time_equal(const struct tm *lms, const char *ims);
+
+NSAPI_PUBLIC int INTutil_str_time_equal(const char *t1, const char *t2);
+
+NSAPI_PUBLIC int INTutil_uri_is_evil(const char *t);
+
+NSAPI_PUBLIC int INTutil_uri_is_evil_internal(const char *t, int, int);
+
+NSAPI_PUBLIC void INTutil_uri_parse(char *uri);
+
+#ifdef XP_WIN32
+NSAPI_PUBLIC int INTutil_uri_unescape_and_normalize(pool_handle_t *pool, char *s, char *unnormalized);
+#endif /* XP_WIN32 */
+
+NSAPI_PUBLIC void INTutil_uri_normalize_slashes(char *s);
+
+NSAPI_PUBLIC void INTutil_uri_unescape		(char *s);
+
+NSAPI_PUBLIC int INTutil_uri_unescape_strict		(char *s);
+
+NSAPI_PUBLIC int  INTutil_uri_unescape_plus (const char *src, char *trg, int len);
+
+NSAPI_PUBLIC char *INTutil_uri_escape(char *d, const char *s);
+
+NSAPI_PUBLIC char *INTutil_uri_strip_params(char *uri);
+
+NSAPI_PUBLIC char* util_canonicalize_uri(pool_handle_t *pool, const char *uri, int len, int *pcanonlen);
+
+NSAPI_PUBLIC char* util_canonicalize_redirect(pool_handle_t *pool, const char *baseUri, const char *newUri);
+
+NSAPI_PUBLIC char *INTutil_url_escape(char *d, const char *s);
+
+NSAPI_PUBLIC char *INTutil_sh_escape(char *s);
+
+NSAPI_PUBLIC int INTutil_mime_separator(char *sep);
+
+NSAPI_PUBLIC int INTutil_itoa(int i, char *a);
+
+NSAPI_PUBLIC int INTutil_i64toa(PRInt64 i, char *a);
+
+
+NSAPI_PUBLIC
+int INTutil_vsprintf(char *s, register const char *fmt, va_list args);
+
+NSAPI_PUBLIC int INTutil_sprintf(char *s, const char *fmt, ...);
+
+NSAPI_PUBLIC int INTutil_vsnprintf(char *s, int n, register const char *fmt, 
+                                  va_list args);
+
+NSAPI_PUBLIC int INTutil_snprintf(char *s, int n, const char *fmt, ...);
+
+NSAPI_PUBLIC int util_strlftime(char *dst, size_t dstsize, const char *format, const struct tm *t);
+
+NSAPI_PUBLIC int INTutil_strftime(char *s, const char *format, const struct tm *t);
+
+NSAPI_PUBLIC char *INTutil_strtok(char *s1, const char *s2, char **lasts);
+
+NSAPI_PUBLIC struct tm *INTutil_localtime(const time_t *clock, struct tm *res);
+
+NSAPI_PUBLIC char *INTutil_ctime(const time_t *clock, char *buf, int buflen);
+
+NSAPI_PUBLIC char *INTutil_strerror(int errnum, char *msg, int buflen);
+
+NSAPI_PUBLIC struct tm *INTutil_gmtime(const time_t *clock, struct tm *res);
+
+NSAPI_PUBLIC char *INTutil_asctime(const struct tm *tm,char *buf, int buflen);
+
+NSAPI_PUBLIC char *INTutil_cookie_find(char *cookie, const char *name);
+
+NSAPI_PUBLIC char *INTutil_cookie_next(char *cookie, char **name, char **value);
+
+NSAPI_PUBLIC char *INTutil_cookie_next_av_pair(char *cookie, char **name, char **value);
+
+NSAPI_PUBLIC void INTutil_random(void *buf, size_t sz);
+
+NSAPI_PUBLIC PRBool INTutil_format_http_version(const char *v, int *protv_num, char *buffer, int size);
+
+NSAPI_PUBLIC int INTutil_getboolean(const char *v, int def);
+NSAPI_PUBLIC PRIntervalTime INTutil_getinterval(const char *v, PRIntervalTime def);
+
+#ifdef NEED_STRCASECMP
+NSAPI_PUBLIC int INTutil_strcasecmp(const char *one, const char *two);
+#endif /* NEED_STRCASECMP */
+
+#ifdef NEED_STRNCASECMP
+NSAPI_PUBLIC int INTutil_strncasecmp(const char *one, const char *two, int n);
+#endif /* NEED_STRNCASECMP */
+
+NSAPI_PUBLIC char *INTutil_strcasestr(char *str, const char *substr);
+
+NSAPI_PUBLIC size_t util_strlcpy(char *dst, const char *src, size_t dstsize);
+
+NSAPI_PUBLIC size_t util_strlcat(char *dst, const char *src, size_t dstsize);
+
+NSAPI_PUBLIC char *INTutil_uuencode(const char *src, int len);
+
+NSAPI_PUBLIC char *INTutil_uudecode(const char *src);
+
+NSAPI_PUBLIC char *util_strlower(char *s);
+
+NSAPI_PUBLIC char *util_decrement_string(char *s);
+
+NSAPI_PUBLIC PRInt64 util_atoi64(const char *a);
+
+NSAPI_PUBLIC char *util_html_escape(const char *s);
+
+NSAPI_PUBLIC int util_qtoi(const char *q, const char **p);
+
+/* --- End common function prototypes --- */
+
+/* --- Begin Unix-only function prototypes --- */
+
+#ifdef XP_UNIX
+
+NSAPI_PUBLIC int INTutil_can_exec(struct stat *finfo, uid_t uid, gid_t gid);
+
+NSAPI_PUBLIC
+struct passwd *INTutil_getpwnam(const char *name, struct passwd *result,
+                               char *buffer,  int buflen);
+
+NSAPI_PUBLIC
+struct passwd *INTutil_getpwuid(uid_t uid, struct passwd *result,
+                                char *buffer, int buflen);
+
+NSAPI_PUBLIC pid_t INTutil_waitpid(pid_t pid, int *statptr, int options);
+
+#endif /* XP_UNIX */
+
+/* --- End Unix-only function prototypes --- */
+
+/* --- Begin Windows-only function prototypes --- */
+
+#ifdef XP_WIN32
+
+NSAPI_PUBLIC
+VOID INTutil_delete_directory(char *FileName, BOOL delete_directory);
+
+#endif /* XP_WIN32 */
+
+/* --- End Windows-only function prototypes --- */
+
+NSPR_END_EXTERN_C
+
+#ifdef __cplusplus
+
+NSAPI_PUBLIC char *util_host_port_suffix(char *h);
+
+NSAPI_PUBLIC const char *util_host_port_suffix(const char *h);
+
+#endif
+
+#define util_init_PRNetAddr INTutil_init_PRNetAddr
+#define util_getline INTutil_getline
+#define util_env_create INTutil_env_create
+#define util_env_str INTutil_env_str
+#define util_env_replace INTutil_env_replace
+#define util_env_free INTutil_env_free
+#define util_env_copy INTutil_env_copy
+#define util_env_find INTutil_env_find
+#define util_hostname INTutil_hostname
+#define util_chdir2path INTutil_chdir2path
+#define util_chdir INTutil_chdir
+#define util_getcwd INTutil_getcwd
+#define util_is_mozilla INTutil_is_mozilla
+#define util_is_url INTutil_is_url
+#define util_mstr2num INTutil_mstr2num
+#define util_later_than INTutil_later_than
+#define util_time_equal INTutil_time_equal
+#define util_str_time_equal INTutil_str_time_equal
+#define util_uri_is_evil INTutil_uri_is_evil
+#define util_uri_is_evil_internal INTutil_uri_is_evil_internal
+#define util_uri_parse INTutil_uri_parse
+#ifdef XP_WIN32
+#define util_uri_unescape_and_normalize INTutil_uri_unescape_and_normalize
+#endif /* XP_WIN32 */
+#define util_uri_normalize_slashes INTutil_uri_normalize_slashes
+#define util_uri_unescape	   INTutil_uri_unescape
+#define util_uri_unescape_strict	   INTutil_uri_unescape_strict
+#define util_uri_unescape_plus INTutil_uri_unescape_plus
+
+#define util_uri_escape INTutil_uri_escape
+#define util_uri_strip_params INTutil_uri_strip_params
+#define util_url_escape INTutil_url_escape
+#define util_sh_escape INTutil_sh_escape
+#define util_mime_separator INTutil_mime_separator
+#define util_itoa INTutil_itoa
+#define util_i64toa INTutil_i64toa
+#define util_vsprintf INTutil_vsprintf
+#define util_sprintf INTutil_sprintf
+#define util_vsnprintf INTutil_vsnprintf
+#define util_snprintf INTutil_snprintf
+#define util_strftime INTutil_strftime
+#define util_strcasecmp INTutil_strcasecmp
+#define util_strncasecmp INTutil_strncasecmp
+#define util_strcasestr INTutil_strcasestr
+#define util_strtok INTutil_strtok
+#define util_localtime INTutil_localtime
+#define util_ctime INTutil_ctime
+#define util_strerror INTutil_strerror
+#define util_gmtime INTutil_gmtime
+#define util_asctime INTutil_asctime
+#define util_uuencode INTutil_uuencode
+#define util_uudecode INTutil_uudecode
+
+#ifdef XP_UNIX
+#define util_can_exec INTutil_can_exec
+#define util_getpwnam INTutil_getpwnam
+#define util_getpwuid INTutil_getpwuid
+#define util_waitpid INTutil_waitpid
+#endif /* XP_UNIX */
+
+#ifdef XP_WIN32
+#define util_delete_directory INTutil_delete_directory
+#endif /* XP_WIN32 */
+
+#ifdef NEED_STRCASECMP
+#define util_strcasecmp INTutil_strcasecmp
+#define strcasecmp INTutil_strcasecmp
+#endif /* NEED_STRCASECMP */
+
+#ifdef NEED_STRINGS_H /* usually for strcasecmp */
+#include <strings.h>
+#endif
+
+#ifdef NEED_STRNCASECMP
+#define util_strncasecmp INTutil_strncasecmp
+#define strncasecmp INTutil_strncasecmp
+#endif /* NEED_STRNCASECMP */
+
+#define util_cookie_find INTutil_cookie_find
+#define util_cookie_next INTutil_cookie_next
+#define util_cookie_next_av_pair INTutil_cookie_next_av_pair
+
+#define util_random INTutil_random
+#define util_format_http_version INTutil_format_http_version
+#define util_getboolean INTutil_getboolean
+#define util_getinterval INTutil_getinterval
+
+#ifdef XP_WIN32
+void set_fullpathname(PRBool b);
+#endif /* XP_WIN32 */
+#endif /* INTNSAPI */
+
+#endif /* !BASE_UTIL_H */
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/webserver.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,76 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "nsapi.h"
+#include "systhr.h"
+
+#include "func.h"
+#include "conf.h"
+#include "httplistener.h"
+#include "webserver.h"
+
+
+extern struct FuncStruct webserver_funcs[];
+
+
+int webserver_init() {
+    // init NSPR
+    systhread_init("webserver");
+
+    // init NSAPI functions
+    func_init();
+    add_functions(webserver_funcs);
+
+    // load init.conf
+    load_init_conf(NULL);
+
+    // load server.conf
+    load_server_conf(NULL);
+
+    // load obj.conf
+
+    // init NSAPI functions
+
+    
+
+    return 0;
+}
+
+int webserver_run() {
+    printf("webserver_run\n");
+
+    // start all http listener
+    if(start_all_listener() != 0) {
+        fprintf(stderr, "Error: Cannot start http listener\n");
+    }
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/webserver.h	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,48 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WEBSERVER_H
+#define	WEBSERVER_H
+
+#include "nsapi.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+int webserver_init();
+int webserver_run();
+
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* WEBSERVER_H */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/ws-fn.c	Tue Sep 06 22:27:32 2011 +0200
@@ -0,0 +1,33 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2011 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "nsapi.h"
+
+struct FuncStruct webserver_funcs[] = {
+    {NULL, NULL, NULL, 0}
+};

mercurial