Wed, 02 Jan 2013 16:03:50 +0100
added access log
--- a/Makefile Tue Jan 01 19:22:56 2013 +0100 +++ b/Makefile Wed Jan 02 16:03:50 2013 +0100 @@ -39,6 +39,10 @@ rm -f -R build rm -f -R work -install: +cleanbuild: + @echo "clean build" + rm -f -R build + +install: all cd make; $(MAKE) -f install.mk install
--- a/make/install.mk Tue Jan 01 19:22:56 2013 +0100 +++ b/make/install.mk Wed Jan 02 16:03:50 2013 +0100 @@ -53,7 +53,7 @@ sed s:%%WS_INSTALL_DIR%%:$(INSTALL_DIR):g ../templates/bin/startserv.template > $(INSTALL_DIR)/bin/startserv chmod +x $(INSTALL_DIR)/bin/startserv sed s:%%WS_INSTALL_DIR%%:$(INSTALL_DIR):g ../templates/bin/stopserv.template > $(INSTALL_DIR)/bin/stopserv - chmod -x $(INSTALL_DIR)/bin/stopserv + chmod +x $(INSTALL_DIR)/bin/stopserv sed s:%%WS_INSTALL_DIR%%:$(INSTALL_DIR):g ../templates/bin/reconfig.template > $(INSTALL_DIR)/bin/reconfig chmod -x $(INSTALL_DIR)/bin/reconfig @echo "copy docs"
--- a/src/Makefile Tue Jan 01 19:22:56 2013 +0100 +++ b/src/Makefile Wed Jan 02 16:03:50 2013 +0100 @@ -30,4 +30,3 @@ all: cd server; $(MAKE) all -
--- a/src/server/Makefile Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/Makefile Wed Jan 02 16:03:50 2013 +0100 @@ -1,7 +1,7 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. # -# Copyright 2011 Olaf Wintermann. All rights reserved. +# Copyright 2013 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:
--- a/src/server/daemon/config.c Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/config.c Wed Jan 02 16:03:50 2013 +0100 @@ -180,6 +180,12 @@ return NULL; } + list = ucx_map_sstr_get(serverconf->objects, sstrn("AccessLog", 9)); + UCX_FOREACH(UcxList*, list, elm) { + ServerConfigObject *scfgobj = elm->data; + cfg_handle_accesslog(serverconfig, scfgobj); + } + list = ucx_map_sstr_get(serverconf->objects, sstrn("AuthDB", 6)); UCX_FOREACH(UcxList*, list, elm) { ServerConfigObject *scfgobj = elm->data; @@ -376,6 +382,25 @@ return ret; } +int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj) { + // TODO: use a name to identify the log file + + sstr_t file = cfg_directivelist_get_str(obj->directives, sstr("File")); + if(file.ptr == NULL) { + return 0; + } + sstr_t format; + format.ptr = NULL; + + AccessLog *log = get_access_log(file, format); + if(log) { + // access logs are only stored in the server config to free them + cfg->logfiles = ucx_list_append(cfg->logfiles, log); + } + + return 0; +} + int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj) { sstr_t name = cfg_directivelist_get_str(obj->directives, sstr("Name")); sstr_t type = cfg_directivelist_get_str(obj->directives, sstr("Type")); @@ -493,6 +518,10 @@ } vs->objectfile = sstrdup(file); // TODO: pool vs->objects = (HTTPObjectConfig*)f->data; // TODO: ref + + // set the access log for the virtual server + // TODO: don't use always the default + vs->log = get_default_access_log(); ucx_map_sstr_put(cfg->host_vs, vs->host, vs);
--- a/src/server/daemon/config.h Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/config.h Wed Jan 02 16:03:50 2013 +0100 @@ -86,6 +86,8 @@ int cfg_handle_eventhandler(ServerConfiguration *cfg, ServerConfigObject *obj); +int cfg_handle_accesslog(ServerConfiguration *cfg, ServerConfigObject *obj); + int cfg_handle_authdb(ServerConfiguration *cfg, ServerConfigObject *obj); int cfg_handle_listener(ServerConfiguration *cfg, ServerConfigObject *obj);
--- a/src/server/daemon/httprequest.c Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/httprequest.c Wed Jan 02 16:03:50 2013 +0100 @@ -110,6 +110,12 @@ /* Pass request line as "clf-request" */ /* TODO: with or without \r\n ? */ + // hack to remove \r\n + sstr_t clfreq = request->request_line; + while(clfreq.ptr[clfreq.length - 1] < 33) { + clfreq.length--; + } + request->request_line = clfreq; pblock_kvinsert( pb_key_clf_request, request->request_line.ptr, @@ -348,6 +354,10 @@ } case NSAPIAddLog: { //printf(">>> AddLog\n"); + r = nsapi_addlog(sn, rq); + if(r != REQ_PROCESSING && r != REQ_ABORTED) { + break; + } rq->phase++; nsapi_context_next_stage(&rq->context); } @@ -669,6 +679,43 @@ return ret; } +int nsapi_addlog(NSAPISession *sn, NSAPIRequest *rq) { + //printf("nsapi_addlog\n"); + httpd_objset *objset = rq->rq.os; + + if(NCX_OI(rq) == -1) { + NCX_OI(rq) = objset->pos - 1; + } + + int ret = rq->context.last_req_code; + for(int i=NCX_OI(rq);i>=0;i--) { + httpd_object *obj = objset->obj[i]; + dtable *dt = object_get_dtable(obj, NSAPIAddLog); + + // execute directives + for(int j=NCX_DI(rq);j<dt->ndir;j++) { + if(ret == REQ_NOACTION) { + directive *d = dt->dirs[j]; + ret = nsapi_exec(d, sn, rq); + } + + if(ret != REQ_NOACTION) { + if(ret == REQ_PROCESSING) { + /* save nsapi context */ + rq->context.objset_index = i; + + /* add +1 to start next round with next function */ + rq->context.dtable_index = j + 1; + } + + return ret; + } + } + } + + return REQ_PROCEED; +} + struct _tpd_data { NSAPISession *sn; NSAPIRequest *rq;
--- a/src/server/daemon/httprequest.h Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/httprequest.h Wed Jan 02 16:03:50 2013 +0100 @@ -91,6 +91,7 @@ int nsapi_pathcheck(NSAPISession *sn, NSAPIRequest *rq); int nsapi_objecttype(NSAPISession *sn, NSAPIRequest *rq); int nsapi_service(NSAPISession *sn, NSAPIRequest *rq); +int nsapi_addlog(NSAPISession *sn, NSAPIRequest *rq); int nsapi_exec(directive *d, NSAPISession *sn, NSAPIRequest *rq);
--- a/src/server/daemon/log.c Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/log.c Wed Jan 02 16:03:50 2013 +0100 @@ -40,16 +40,24 @@ #include "log.h" #include "../util/strbuf.h" #include "../util/io.h" - -int is_initialized = 0; +#include "../ucx/map.h" -int log_file_fd; -int log_level = 0; +static int is_initialized = 0; + +static int log_file_fd; +static int log_level = 0; /* * if the log file is uninitialized, output is written to the ui_buffer */ -sbuf_t *ui_buffer = NULL; +static sbuf_t *ui_buffer = NULL; + +/* + * access logfile map + */ +static UcxMap *access_log_files; // map of AccessLog* +static AccessLog *default_access_log; + char *log_date_month[] = { "Jan", @@ -215,3 +223,57 @@ return 0; } + + +/* + * access log + * This source file only manages access log files. IO is performed directly + * by AddLog safs. + */ +AccessLog* get_access_log(sstr_t file, sstr_t format) { + if(!access_log_files) { + access_log_files = ucx_map_new(4); + } + + if(file.ptr == NULL || file.length == 0) { + return NULL; + } + + AccessLog *log = ucx_map_sstr_get(access_log_files, file); + if(log != NULL) { + // TODO: ref + return log; + } + + // the log file is not opened + // check first if we can open it + sstr_t path = sstrdup(file); + FILE *out = fopen(path.ptr, "a"); + if(out == NULL) { + free(path.ptr); + return NULL; + } + + // create access log object + log = calloc(1, sizeof(AccessLog)); + log->file = path; + if(format.ptr != NULL) { + log->format = sstrdup(format); + } + log->log = out; + // TODO: log->ref = 1; + + // add access log to the map + ucx_map_sstr_put(access_log_files, file, log); + + if(!default_access_log) { + default_access_log = log; + } + + return log; +} + +AccessLog* get_default_access_log() { + // TODO: ref + return default_access_log; +}
--- a/src/server/daemon/log.h Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/log.h Wed Jan 02 16:03:50 2013 +0100 @@ -32,6 +32,8 @@ #include "../public/nsapi.h" #include "../ucx/string.h" +#include <inttypes.h> + #ifdef __cplusplus extern "C" { #endif @@ -46,7 +48,15 @@ int log_stdout; int log_stderr; } LogConfig; - + +typedef struct { + sstr_t file; + sstr_t format; // unused + FILE *log; + uint32_t ref; +} AccessLog; + +// server logging int init_log_file(LogConfig *cfg); void log_uninitialized_writeln(char *str, size_t len); @@ -57,6 +67,11 @@ int log_ereport(int degree, const char *format, ...); +// access logging +AccessLog* get_access_log(sstr_t file, sstr_t format); +AccessLog* get_default_access_log(); + +// TODO: ref/unref #ifdef __cplusplus }
--- a/src/server/daemon/protocol.c Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/protocol.c Wed Jan 02 16:03:50 2013 +0100 @@ -248,7 +248,7 @@ for(int i=0;i<h->hsize;i++) { p = h->ht[i]; - while(p != NULL) { + while(p != NULL) { /* from http.cpp */ const pb_key *key = PARAM_KEY(p->param); if (key == pb_key_status || key == pb_key_server || key == pb_key_date) { @@ -262,6 +262,7 @@ char *value = p->param->value; /* make first char of name uppercase */ + // TODO: don't modify the headers if(name[0] > 90) { name[0] -= 32; } @@ -288,7 +289,7 @@ flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags ^ O_NONBLOCK); - /* iovec output buffer */ + /* output buffer */ sbuf_t *out = sbuf_new(512); /* add the http status line to the output buffer */
--- a/src/server/daemon/vserver.c Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/vserver.c Wed Jan 02 16:03:50 2013 +0100 @@ -32,6 +32,7 @@ VirtualServer *vs = malloc(sizeof(VirtualServer)); vs->objects = NULL; vs->document_root = sstr("docs"); + vs->log = NULL; vs->ref = 1; return vs; } @@ -43,6 +44,7 @@ newvs->host = sstrdup_pool(pool, vs->host); newvs->name = sstrdup_pool(pool, vs->name); newvs->objectfile = sstrdup_pool(pool, vs->objectfile); + newvs->log = vs->log; // TODO: ref newvs->objects = vs->objects;
--- a/src/server/daemon/vserver.h Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/vserver.h Wed Jan 02 16:03:50 2013 +0100 @@ -34,6 +34,8 @@ #include "../ucx/string.h" +#include "log.h" + #ifdef __cplusplus extern "C" { #endif @@ -48,6 +50,8 @@ sstr_t document_root; + AccessLog *log; + uint32_t ref; // reference counter };
--- a/src/server/daemon/ws-fn.c Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/daemon/ws-fn.c Wed Jan 02 16:03:50 2013 +0100 @@ -35,6 +35,7 @@ #include "../safs/service.h" #include "../safs/init.h" #include "../safs/common.h" +#include "../safs/addlog.h" #include "../webdav/webdav.h" #include "../admin/adminui.h" @@ -55,5 +56,6 @@ { "auth-db", auth_db, NULL, 0 }, { "require-auth", require_auth, NULL, 0}, { "print-message", print_message, NULL, 0}, + { "common-log", common_log, NULL, 0}, {NULL, NULL, NULL, 0} };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/safs/addlog.c Wed Jan 02 16:03:50 2013 +0100 @@ -0,0 +1,88 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 "addlog.h" + +#include "../daemon/request.h" +#include "../daemon/vserver.h" +#include "../daemon/log.h" + +int common_log(pblock *pb, Session *sn, Request *rq) { + NSAPIRequest *request = (NSAPIRequest*)rq; + VirtualServer *vs = request->vs; + AccessLog *log = vs->log; + + if(log == NULL) { + return REQ_NOACTION; + } + + char *ip = pblock_findval("ip", sn->client); + char *user = pblock_findval("auth-user", rq->vars); + time_t t = time(NULL); + char *time = ctime(&t); + char *req = pblock_findval("clf-request", rq->reqpb); + + // hack to get the content length + // http_start_response should not modify the header names + char *len = pblock_findval("Content-length", rq->srvhdrs); + + if(!ip) { + ip = "-"; + } + if(!user) { + user = "-"; + } + if(!len) { + len = "0"; + } + + // remove trailing line feed + sstr_t tmstr = sstr(time); + if(tmstr.ptr[tmstr.length-1] == '\n') { + tmstr.length--; + } + tmstr = sstrdup_pool(sn->pool, tmstr); + + fprintf( + log->log, + "%s - %s [%s] \"%s\" %d %s\n", + ip, + user, + tmstr.ptr, + req, + rq->status_num, + len); + fflush(log->log); + + + return REQ_PROCEED; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/server/safs/addlog.h Wed Jan 02 16:03:50 2013 +0100 @@ -0,0 +1,46 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2013 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 ADDLOG_H +#define ADDLOG_H + +#include "../public/nsapi.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int common_log(pblock *pb, Session *sn, Request *rq); + + +#ifdef __cplusplus +} +#endif + +#endif /* ADDLOG_H */ +
--- a/src/server/safs/objs.mk Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/safs/objs.mk Wed Jan 02 16:03:50 2013 +0100 @@ -37,6 +37,7 @@ SAFOBJ += auth.o SAFOBJ += pathcheck.o SAFOBJ += common.o +SAFOBJ += addlog.o SAFOBJS = $(SAFOBJ:%=$(SAFS_OBJPRE)%) SAFSOURCE = $(SAFOBJ:%.o=safs/%.c)
--- a/src/server/webdav/objs.mk Tue Jan 01 19:22:56 2013 +0100 +++ b/src/server/webdav/objs.mk Wed Jan 02 16:03:50 2013 +0100 @@ -26,7 +26,7 @@ # POSSIBILITY OF SUCH DAMAGE. # -DAV_SRC_DIR = server/safs/ +DAV_SRC_DIR = server/webdav/ DAV_OBJPRE = $(OBJ_DIR)$(DAV_SRC_DIR)
--- a/templates/config/obj.conf Tue Jan 01 19:22:56 2013 +0100 +++ b/templates/config/obj.conf Wed Jan 02 16:03:50 2013 +0100 @@ -10,6 +10,7 @@ Service fn="send-options" method="OPTIONS" Service fn="common-index" type="internal/directory" Service fn="send-file" +AddLog fn="common-log" </Object> <Object name="hello">
--- a/templates/config/server.template Tue Jan 01 19:22:56 2013 +0100 +++ b/templates/config/server.template Wed Jan 02 16:03:50 2013 +0100 @@ -13,6 +13,10 @@ Level INFO </LogFile> +<AccessLog> + File logs/access +</AccessLog> + <EventHandler> Name default Threads 1 @@ -25,11 +29,6 @@ MaxThreads 32 </Threadpool> -<AuthDB> - Name keyfile - Type keyfile -</AuthDB> - <Listener> Name http-listener-1 Port 9090