added mime type configuration file

Sun, 30 Dec 2012 15:49:44 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 30 Dec 2012 15:49:44 +0100
changeset 39
de4bc3cd2d36
parent 38
d07810b02147
child 40
56cda23f48d4

added mime type configuration file

Makefile file | annotate | diff | comparison | revisions
src/server/config/conf.c file | annotate | diff | comparison | revisions
src/server/config/mimeconf.c file | annotate | diff | comparison | revisions
src/server/config/mimeconf.h file | annotate | diff | comparison | revisions
src/server/config/objs.mk file | annotate | diff | comparison | revisions
src/server/daemon/config.c file | annotate | diff | comparison | revisions
src/server/daemon/config.h file | annotate | diff | comparison | revisions
src/server/daemon/configmanager.c file | annotate | diff | comparison | revisions
src/server/daemon/webserver.c file | annotate | diff | comparison | revisions
src/server/safs/objecttype.c file | annotate | diff | comparison | revisions
templates/conf/init.conf file | annotate | diff | comparison | revisions
templates/conf/mime.types file | annotate | diff | comparison | revisions
templates/conf/obj.conf file | annotate | diff | comparison | revisions
templates/conf/server.conf file | annotate | diff | comparison | revisions
templates/config/init.conf file | annotate | diff | comparison | revisions
templates/config/mime.types file | annotate | diff | comparison | revisions
templates/config/obj.conf file | annotate | diff | comparison | revisions
templates/config/server.conf file | annotate | diff | comparison | revisions
--- a/Makefile	Sat Dec 29 18:08:23 2012 +0100
+++ b/Makefile	Sun Dec 30 15:49:44 2012 +0100
@@ -41,14 +41,15 @@
 	@echo "install Webserver to $(WS_INSTALL_DIR)"
 	mkdir -p $(WS_INSTALL_DIR)bin
 	mkdir -p $(WS_INSTALL_DIR)lib
-	mkdir -p $(WS_INSTALL_DIR)conf
+	mkdir -p $(WS_INSTALL_DIR)config
 	mkdir -p $(WS_INSTALL_DIR)docs
 	mkdir -p $(WS_INSTALL_DIR)logs
 	mkdir -p $(WS_INSTALL_DIR)include
 	@echo "copy config"
-	cp templates/conf/init.conf $(WS_INSTALL_DIR)conf/init.conf
-	cp templates/conf/obj.conf $(WS_INSTALL_DIR)conf/obj.conf
-	cp templates/conf/server.conf $(WS_INSTALL_DIR)conf/server.conf
+	cp templates/config/init.conf $(WS_INSTALL_DIR)config/init.conf
+	cp templates/config/obj.conf $(WS_INSTALL_DIR)config/obj.conf
+	cp templates/config/server.conf $(WS_INSTALL_DIR)config/server.conf
+	cp templates/config/mime.types $(WS_INSTALL_DIR)config/mime.types
 	@echo "copy binaries"
 	mv work/bin/webservd work/bin/webservd.bin
 	cp work/bin/webservd.bin $(WS_INSTALL_DIR)bin/webservd
--- a/src/server/config/conf.c	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/config/conf.c	Sun Dec 30 15:49:44 2012 +0100
@@ -229,8 +229,15 @@
             break; // end of value
         }
     }
-    value->length = i - name->length - 2;
-    i++;
+    
+    if(quote) {
+        // if the value is quoted, i points to the last quote char
+        value->length = i - name->length - 2; // subtract the quotes
+        i++; // set i behind the last quote
+    } else {
+        // i points to a white space char, which must be subtraced
+        value->length = i - name->length - 1;
+    }
 
     if(value->length <= 0) {
         value->length = 0;
@@ -333,7 +340,6 @@
         if(pname.length <= 0) {
             break;
         }
-        
 
         // create param object
         ConfigParam *param = OBJ_NEW(mp, ConfigParam);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/config/mimeconf.c	Sun Dec 30 15:49:44 2012 +0100
@@ -0,0 +1,97 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2012 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 "mimeconf.h"
+
+MimeConfig *load_mime_config(char *file) {
+    FILE *in = fopen(file, "r");
+    if(in == NULL) {
+        return NULL;
+    }
+    
+    MimeConfig *conf = malloc(sizeof(MimeConfig));
+    conf->parser.parse = mimeconf_parse;
+    conf->file = file;
+    conf->directives = NULL;
+    conf->ntypes = 0;
+
+    int r = cfg_parse_basic_file((ConfigParser*)conf, in);
+    if(r != 0) {
+        // TODO: free
+        return NULL;
+    }
+
+    return conf;
+}
+
+void free_mime_config(MimeConfig *conf) {
+    if(conf->directives != NULL) {
+        ucx_list_free(conf->directives);
+    }
+    if(conf->parser.lines != NULL) {
+        ucx_dlist_free(conf->parser.lines);
+    }
+    ucx_mempool_free(conf->parser.mp);
+    free(conf);
+}
+
+int mimeconf_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line) {
+    MimeConfig *conf = p;
+    UcxMempool *mp = conf->parser.mp;
+    
+    // parse mime directive
+    MimeDirective *dir = ucx_mempool_calloc(mp, 1, sizeof(MimeDirective));
+    
+    UcxList *params = cfg_param_list(line, mp);
+    UCX_FOREACH(UcxList*, params, pl) {
+        ConfigParam *param = pl->data;
+        
+        if(!sstrcmp(param->name, sstr("type"))) {
+            dir->type = param->value;
+        } else if(!sstrcmp(param->name, sstr("exts"))) {
+            // comma-separated file extensions
+            
+            size_t nx = 0;
+            sstr_t *exts = sstrsplit(param->value, sstrn(",", 1), &nx);
+            for(int i=0;i<nx;i++) {
+                dir->exts = ucx_list_append(dir->exts, exts[i].ptr);
+            }
+            
+            free(exts);
+        }
+    }
+    
+    conf->directives = ucx_list_append(conf->directives, dir);
+    conf->ntypes++;
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/config/mimeconf.h	Sun Dec 30 15:49:44 2012 +0100
@@ -0,0 +1,61 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2012 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 MIMECONF_H
+#define	MIMECONF_H
+
+#include "conf.h"
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef struct _mime_conf {
+    ConfigParser parser;
+    char         *file;
+    UcxList      *directives; // MimeDirective list
+    int          ntypes;
+} MimeConfig;
+
+typedef struct _mime_dir {
+    sstr_t  type;
+    UcxList *exts; // char*
+} MimeDirective;
+
+MimeConfig *load_mime_config(char *file);
+
+void free_mime_config(MimeConfig *conf);
+
+int mimeconf_parse(void *p, ConfigLine *begin, ConfigLine *end, sstr_t line);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* MIMECONF_H */
+
--- a/src/server/config/objs.mk	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/config/objs.mk	Sun Dec 30 15:49:44 2012 +0100
@@ -34,6 +34,7 @@
 CONFOBJ += conf.o
 CONFOBJ += initconf.o
 CONFOBJ += serverconf.o
+CONFOBJ += mimeconf.o
 
 CONFOBJS = $(CONFOBJ:%=$(CONF_OBJPRE)%)
 CONFSOURCE = $(CONFOBJ:%.o=config/%.c)
--- a/src/server/daemon/config.c	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/daemon/config.c	Sun Dec 30 15:49:44 2012 +0100
@@ -246,7 +246,30 @@
     cfg->tmp = sstrdup(cfg_directivelist_get_str(
             obj->directives,
             sstr("Temp")));
-
+    
+    // mime file
+    sstr_t mf = cfg_directivelist_get_str(obj->directives, sstr("MimeFile"));
+    
+    sstr_t base = sstr("config/");
+    sstr_t file;
+    file.length = base.length + mf.length + 1;
+    file.ptr = alloca(file.length);
+    file.ptr[file.length] = 0;
+    file = sstrncat(2, file, base, mf);
+    
+    ConfigFile *f = cfgmgr_get_file(file);
+    if(f == NULL) {
+        f = malloc(sizeof(ConfigFile));
+        f->file = sstrdup(file);
+        f->reload = mime_conf_reload;
+        
+        // load the file content
+        f->reload(f, cfg);
+        cfgmgr_attach_file(f);
+    }
+    
+    cfg->mimetypes = f->data; // TODO: ref
+    
     return 0;
 }
 
@@ -453,7 +476,7 @@
     sstr_t objfile = cfg_directivelist_get_str(
             obj->directives,
             sstr("ObjectFile"));
-    sstr_t base = sstr("conf/");
+    sstr_t base = sstr("config/");
     sstr_t file;
     file.length = base.length + objfile.length + 1;
     file.ptr = alloca(file.length);
@@ -572,3 +595,23 @@
 
     return conf;
 }
+
+int mime_conf_reload(ConfigFile *file, ServerConfiguration *cfg) {
+    MimeConfig *mimecfg = load_mime_config(file->file.ptr);
+    
+    UcxMap *mimemap = ucx_map_new((mimecfg->ntypes * 3) / 2);
+    
+    // add ext type pairs
+    UCX_FOREACH(UcxList*, mimecfg->directives, md) {
+        MimeDirective *d = md->data;
+        // add the type for each extension to the map
+        UCX_FOREACH(UcxList*, d->exts, xl) {
+            sstr_t ext = sstr(xl->data);
+            sstr_t value = sstrdup(d->type);
+            ucx_map_sstr_put(mimemap, ext, value.ptr);
+        }
+    }
+    
+    file->data = mimemap;
+    return 0;
+}
--- a/src/server/daemon/config.h	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/daemon/config.h	Sun Dec 30 15:49:44 2012 +0100
@@ -36,6 +36,7 @@
 #include "../config/objconf.h"
 #include "../config/initconf.h"
 #include "../config/serverconf.h"
+#include "../config/mimeconf.h"
 
 #include "../ucx/list.h"
 #include "../ucx/dlist.h"
@@ -54,6 +55,7 @@
     UcxList         *listeners; // list of all listeners
     UcxList         *logfiles;
     UcxMap          *authdbs;
+    UcxMap          *mimetypes;
     sstr_t          tmp;
     sstr_t          user;
     uint32_t        ref;        // reference counter
@@ -98,6 +100,8 @@
 
 HTTPObjectConfig* load_obj_conf(char *file);
 
+int mime_conf_reload(ConfigFile *file, ServerConfiguration *cfg);
+
 
 
 #ifdef	__cplusplus
--- a/src/server/daemon/configmanager.c	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/daemon/configmanager.c	Sun Dec 30 15:49:44 2012 +0100
@@ -118,8 +118,8 @@
     }
 
     struct stat s;
-    if(stat("conf/server.conf", &s) != 0) {
-        perror("stat(\"conf/server.conf\")");
+    if(stat("config/server.conf", &s) != 0) {
+        perror("stat(\"config/server.conf\")");
         return -1;
     }
 
@@ -128,7 +128,7 @@
         printf("cfgmgr load server.conf\n");
         config = load_server_conf(
             current_config,
-            "conf/server.conf");
+            "config/server.conf");
 
         if(config == NULL) {
             fprintf(stderr, "Cannot load server.conf\n");
@@ -144,7 +144,7 @@
         /*
         config = load_server_conf(
             current_config,
-            "conf/server.conf");
+            "config/server.conf");
         */
         config = malloc(sizeof(ServerConfiguration));
         config->ref = 1;
@@ -152,7 +152,7 @@
         config->user = sstrdup_pool(config->pool, current_config->user);
         config->tmp = sstrdup_pool(config->pool, current_config->tmp);
         
-        // copy configuration       
+        // copy configuration
         config->host_vs = ucx_map_clone(
                 current_config->host_vs,
                 copy_vs,
@@ -163,7 +163,9 @@
                 (copy_func)copy_listener,
                 config);
         
-
+        // TODO: we need to get the mime map from the configfile data
+        config->mimetypes = current_config->mimetypes;
+        
         if(config == NULL) {
             fprintf(stderr, "Cannot load server.conf\n");
             return -1;
--- a/src/server/daemon/webserver.c	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/daemon/webserver.c	Sun Dec 30 15:49:44 2012 +0100
@@ -55,7 +55,7 @@
     add_functions(webserver_funcs);
     
     // load init.conf
-    load_init_conf("conf/init.conf");
+    load_init_conf("config/init.conf");
 
     // load server.conf
     init_configuration_manager();
--- a/src/server/safs/objecttype.c	Sat Dec 29 18:08:23 2012 +0100
+++ b/src/server/safs/objecttype.c	Sun Dec 30 15:49:44 2012 +0100
@@ -30,6 +30,9 @@
 #include "../util/pblock.h"
 
 #include "../ucx/string.h"
+#include "../ucx/map.h"
+#include "../daemon/config.h"
+#include "../daemon/session.h"
 
 int object_type_by_extension(pblock *pb, Session *sn, Request *rq) {
     sstr_t ppath = sstr(pblock_findkeyval(pb_key_ppath, rq->vars));
@@ -55,18 +58,16 @@
             return REQ_NOACTION;
         }
 
-        /* TODO: we need a map for extensions/types */
-        if(!sstrcmp(ext, sstrn("txt", 3))) {
-            ct = sstr("text/plain");
-        } else if(!sstrcmp(ext, sstrn("htm", 3))) {
-            ct = sstr("text/html");
-        } else if(!sstrcmp(ext, sstrn("html", 4))) {
-            ct = sstr("text/html");
-        } else if(!sstrcmp(ext, sstrn("xml", 3))) {
-            ct = sstr("text/xml");
-        } else {
+        /* get the mime type for the ext from the server configuration */
+        ServerConfiguration *config = session_get_config(sn);
+        char *type = ucx_map_sstr_get(config->mimetypes, ext);
+        
+        if(!type) {
             return REQ_NOACTION;
         }
+        
+        ct.ptr = type;
+        ct.length = strlen(type);
     }
 
     pblock_kvinsert(pb_key_content_type, ct.ptr, ct.length, rq->srvhdrs);
--- a/templates/conf/init.conf	Sat Dec 29 18:08:23 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-#
-# init.conf
-#
-
-Init fn="init-test"
-
--- a/templates/conf/mime.types	Sat Dec 29 18:08:23 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-type=image/png                                   exts=png
-type=image/x-icon                                exts=ico
-type=image/gif                                   exts=gif
-type=image/jpeg                                  exts=jpeg,jpg,jpe,jfif,pjpeg,pjp
-type=image/tiff                                  exts=tiff,tif
-type=image/bmp                                   exts=bmp
-type=application/pdf                             exts=pdf
-type=application/postscript                      exts=ai,eps,ps
-type=application/x-sh                            exts=sh
-type=text/css                                    exts=css
-type=text/html                                   exts=htm,html
-type=text/plain                                  exts=txt
-type=text/xml                                    exts=xml
-type=application/x-javascript                    exts=js
-type=application/x-javascript;charset=UTF-8      exts=jsu
-type=application/x-tex                           exts=tex
--- a/templates/conf/obj.conf	Sat Dec 29 18:08:23 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#
-# obj.conf
-#
-# NSAPI configuration
-#
-
-<Object name="default">
-NameTrans fn="assign-name" from="/hello" name="hello"
-ObjectType fn="type-by-extension"
-Service fn="send-options" method="OPTIONS"
-Service fn="common-index" type="internal/directory"
-Service fn="send-file"
-</Object>
-
-<Object name="hello">
-Service fn="service-hello"
-</Object>
-
--- a/templates/conf/server.conf	Sat Dec 29 18:08:23 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#
-# server.conf
-#
-
-<Runtime>
-	Temp        /tmp/webserver-rw6pgl8b/
-	User        webservd
-</Runtime>
-
-<LogFile>
-	File        logs/errors
-	Level       INFO
-</LogFile>
-
-<EventHandler>
-    Name        default
-    Threads     1
-    Default     true
-</EventHandler>
-
-<Threadpool>
-    Name        default
-    MinThreads  4
-    MaxThreads  32
-</Threadpool>
-
-<AuthDB>
-    Name        keyfile
-    Type        keyfile
-</AuthDB>
-
-<Listener>
-    Name        http-listener-1
-    Port        9090
-    DefaultVS   x4
-</Listener>
-
-<Listener>
-    Name        http-listener-2
-    Port        9091
-    DefaultVS   x4
-</Listener>
-
-<VirtualServer>
-	Name        x4
-	Host        x4
-    Listener    http-listener-1
-    Listener    http-listener-2
-    ObjectFile  obj.conf
-    ACLFile     acl.conf
-    DAVFile     dav.conf
-    DocRoot     docs/ 
-</VirtualServer>
-
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/config/init.conf	Sun Dec 30 15:49:44 2012 +0100
@@ -0,0 +1,6 @@
+#
+# init.conf
+#
+
+Init fn="init-test"
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/config/mime.types	Sun Dec 30 15:49:44 2012 +0100
@@ -0,0 +1,16 @@
+type=image/png                                   exts=png
+type=image/x-icon                                exts=ico
+type=image/gif                                   exts=gif
+type=image/jpeg                                  exts=jpeg,jpg,jpe,jfif,pjpeg,pjp
+type=image/tiff                                  exts=tiff,tif
+type=image/bmp                                   exts=bmp
+type=application/pdf                             exts=pdf
+type=application/postscript                      exts=ai,eps,ps
+type=application/x-sh                            exts=sh
+type=text/css                                    exts=css
+type=text/html                                   exts=htm,html
+type=text/plain                                  exts=txt
+type=text/xml                                    exts=xml
+type=application/x-javascript                    exts=js
+type=application/x-javascript;charset=UTF-8      exts=jsu
+type=application/x-tex                           exts=tex
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/config/obj.conf	Sun Dec 30 15:49:44 2012 +0100
@@ -0,0 +1,18 @@
+#
+# obj.conf
+#
+# NSAPI configuration
+#
+
+<Object name="default">
+NameTrans fn="assign-name" from="/hello" name="hello"
+ObjectType fn="type-by-extension"
+Service fn="send-options" method="OPTIONS"
+Service fn="common-index" type="internal/directory"
+Service fn="send-file"
+</Object>
+
+<Object name="hello">
+Service fn="service-hello"
+</Object>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/templates/config/server.conf	Sun Dec 30 15:49:44 2012 +0100
@@ -0,0 +1,56 @@
+#
+# server.conf
+#
+
+<Runtime>
+	Temp        /tmp/webserver-rw6pgl8b/
+	User        webservd
+	MimeFile    mime.types
+</Runtime>
+
+<LogFile>
+	File        logs/errors
+	Level       INFO
+</LogFile>
+
+<EventHandler>
+    Name        default
+    Threads     1
+    Default     true
+</EventHandler>
+
+<Threadpool>
+    Name        default
+    MinThreads  4
+    MaxThreads  32
+</Threadpool>
+
+<AuthDB>
+    Name        keyfile
+    Type        keyfile
+</AuthDB>
+
+<Listener>
+    Name        http-listener-1
+    Port        9090
+    DefaultVS   x4
+</Listener>
+
+<Listener>
+    Name        http-listener-2
+    Port        9091
+    DefaultVS   x4
+</Listener>
+
+<VirtualServer>
+	Name        x4
+	Host        x4
+    Listener    http-listener-1
+    Listener    http-listener-2
+    ObjectFile  obj.conf
+    ACLFile     acl.conf
+    DAVFile     dav.conf
+    DocRoot     docs/ 
+</VirtualServer>
+
+

mercurial