From owner-new-httpd@hyperreal.com Tue Sep 3 02:05:54 1996 Received: by taz.hyperreal.com (8.7.5/V2.0) id CAA00710; Tue, 3 Sep 1996 02:05:54 -0700 (PDT) Received: from gate.ukweb.com by taz.hyperreal.com (8.7.5/V2.0) with ESMTP id CAA00701; Tue, 3 Sep 1996 02:05:47 -0700 (PDT) Received: from star(really [192.168.2.10]) by gate.ukweb.com via rsmtp with smtp id for ; Tue, 3 Sep 96 10:05:33 +0100 (BST) (/\##/\ Smail3.1.30.13 #30.13 built 31-aug-95) Date: Tue, 3 Sep 1996 10:04:23 +0100 (BST) From: Mark J Cox To: new-httpd@hyperreal.com Subject: Re: mod_log_config enhancements In-Reply-To: Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-new-httpd@apache.org Precedence: bulk Reply-To: new-httpd@hyperreal.com On Mon, 2 Sep 1996, Alexei Kosut wrote: > mod_cookies put its cookie into a note called "cookie". This allows > mod_log_config to log it without having to use a seperate cookie log +1 on Alexei's patch; works here. Here is an additional patch that I'd like comments on; it uses Alexei's patch and removes the logging code completely from mod_cookies.c. Now that the log_config module can create multiple log files the extra overhead of handling log files and pipes internally is redundant. I've created a "CookieLog" directive that works as before, but the documentation can be changed to deprecate it (and suggest logging as part of standard logs). This has to be applied *after* Alexei's patch Mark *** mod_cookies.c.alex Tue Sep 3 09:13:53 1996 --- mod_cookies.c Tue Sep 3 09:58:08 1996 *************** *** 68,82 **** * the browser (via a "Set-Cookie" header) * Future requests from the same browser should keep the same Cookie line. * ! * The cookie and request are logged to a file. Use the directive ! * "CookieLog somefilename" in one of the config files to enable the Cookie ! * module. By matching up all the requests with the same cookie you can ! * work out exactly what path a user took through your site. * * Notes: ! * 1. This code doesn't log the initial transaction (the one that created ! * the cookie to start with). If it did then the cookie log file would ! * be bigger than a normal access log. * 2. This module has been designed to not interfere with other Cookies * your site may be using; just avoid sending out cookies with * the name "Apache=" or things will get confused. --- 68,89 ---- * the browser (via a "Set-Cookie" header) * Future requests from the same browser should keep the same Cookie line. * ! * By matching up all the requests with the same cookie you can ! * work out exactly what path a user took through your site. To log ! * the cookie use the " %{Cookie}n " directive in a custom access log; ! * ! * Example 1 : If you currently use the standard Log file format (CLF) ! * and use the command "TransferLog somefilename", add the line ! * LogFormat "%h %l %u %t \"%r\" %s %b %{Cookie}n" ! * to your config file. ! * ! * Example 2 : If you used to use the old "CookieLog" directive, you ! * can emulate it by adding the following command to your config file ! * CustomLog filename "%{Cookie}n \"%r\" %t" * * Notes: ! * 1. This code now logs the initial transaction (the one that created ! * the cookie to start with). * 2. This module has been designed to not interfere with other Cookies * your site may be using; just avoid sending out cookies with * the name "Apache=" or things will get confused. *************** *** 97,102 **** --- 104,110 ---- * 24.5.96 MJC Improved documentation after receiving comments from users * 4.7.96 MJC Bug, "else" missing since February caused logging twice * 19.7.96 AEK Added CookieExpires and CookieEnable directives + * 03.9.96 MJC Remove logging stuff from here, (use AEK notes addition) */ #include "httpd.h" *************** *** 107,114 **** module cookies_module; typedef struct { - char *fname; - int log_fd; int always; time_t expires; } cookie_log_state; --- 115,120 ---- *************** *** 156,163 **** #endif tms = gmtime(&when); - - /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */ sprintf(new_cookie, "%s%s%d%ld%d; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", --- 162,167 ---- *************** *** 182,213 **** int *disable = (int *)get_module_config(r->per_dir_config, &cookies_module); char *cookie; if (*disable) return DECLINED; if ((cookie = table_get (r->headers_in, "Cookie"))) ! if (strstr(cookie,COOKIE_NAME)) ! return DECLINED; /* Theres already a cookie, no new one */ make_cookie(r); return OK; /* We set our cookie */ } - static int cookie_flags = ( O_WRONLY | O_APPEND | O_CREAT ); - - #ifdef __EMX__ - /* OS/2 lacks support for users and groups */ - static mode_t cookie_mode = ( S_IREAD | S_IWRITE ); - #else - static mode_t cookie_mode = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); - #endif - void *make_cookie_log_state (pool *p, server_rec *s) { cookie_log_state *cls = (cookie_log_state *)palloc (p, sizeof (cookie_log_state)); - cls->fname = ""; - cls->log_fd = -1; cls->expires = 0; return (void *)cls; --- 186,218 ---- int *disable = (int *)get_module_config(r->per_dir_config, &cookies_module); char *cookie; + char *value; if (*disable) return DECLINED; if ((cookie = table_get (r->headers_in, "Cookie"))) ! if ((value=strstr(cookie,COOKIE_NAME))) { ! char *cookiebuf, *cookieend; ! ! value+=strlen(COOKIE_NAME); ! cookiebuf=pstrdup( r->pool, value ); ! cookieend=strchr(cookiebuf,';'); ! if (cookieend) *cookieend='\0'; /* Ignore anything after a ; */ ! ! /* Set the cookie in a note, for logging */ ! table_set(r->notes, "cookie", cookiebuf); ! ! return DECLINED; /* Theres already a cookie, no new one */ ! } make_cookie(r); return OK; /* We set our cookie */ } void *make_cookie_log_state (pool *p, server_rec *s) { cookie_log_state *cls = (cookie_log_state *)palloc (p, sizeof (cookie_log_state)); cls->expires = 0; return (void *)cls; *************** *** 223,236 **** return NULL; } - char *set_cookie_log (cmd_parms *parms, void *dummy, char *arg) - { - cookie_log_state *cls = get_module_config (parms->server->module_config, - &cookies_module); - cls->fname = arg; - return NULL; - } - char *set_cookie_exp (cmd_parms *parms, void *dummy, char *arg) { cookie_log_state *cls = get_module_config (parms->server->module_config, --- 228,233 ---- *************** *** 297,304 **** } command_rec cookie_log_cmds[] = { - { "CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1, - "the filename of the cookie log" }, { "CookieExpires", set_cookie_exp, NULL, RSRC_CONF, TAKE1, "an expiry date code" }, { "CookieEnable", set_cookie_disable, NULL, OR_FILEINFO, FLAG, --- 294,299 ---- *************** *** 306,425 **** { NULL } }; - void cookie_log_child (void *cmd) - { - /* Child process code for 'CookieLog "|..."'; - * may want a common framework for this, since I expect it will - * be common for other foo-loggers to want this sort of thing... - */ - - cleanup_for_exec(); - signal (SIGHUP, SIG_IGN); - execl (SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL); - exit (1); - } - - void open_cookie_log (server_rec *s, pool *p) - { - cookie_log_state *cls = get_module_config (s->module_config, - &cookies_module); - char *fname = server_root_relative (p, cls->fname); - - if (cls->log_fd > 0) return; - - if (*cls->fname == '|') { - FILE *dummy; - - spawn_child(p, cookie_log_child, (void *)(cls->fname+1), - kill_after_timeout, &dummy, NULL); - - if (dummy == NULL) { - fprintf (stderr, "Couldn't fork child for CookieLog process\n"); - exit (1); - } - - cls->log_fd = fileno (dummy); - } - else if(*cls->fname != '\0') { - if((cls->log_fd = popenf(p, fname, cookie_flags, cookie_mode)) < 0) { - fprintf(stderr, "httpd: could not open cookie log file %s.\n", fname); - perror("open"); - exit(1); - } - } - } - - void init_cookie_log (server_rec *s, pool *p) - { - for (; s; s = s->next) open_cookie_log (s, p); - } - - int cookie_log_transaction(request_rec *orig) - { - cookie_log_state *cls = get_module_config (orig->server->module_config, - &cookies_module); - char *str; - long timz; - struct tm *t; - char tstr[MAX_STRING_LEN],sign; - request_rec *r; - char *cookie,*cookiebuf,*cookieend; - char *value; - - for (r = orig; r->next; r = r->next) - continue; - - if (!(cookie = table_get (r->headers_in, "Cookie"))) - return DECLINED; /* Theres no cookie, don't bother logging */ - value=strstr(cookie,COOKIE_NAME); - if (!value) /* Only log cookies we generated! */ - return DECLINED; - value+=strlen(COOKIE_NAME); - cookiebuf=pstrdup( r->pool, value ); - cookieend=strchr(cookiebuf,';'); - if (cookieend) *cookieend='\0'; /* Ignore anything after a ; */ - - /* Set the cookie in a note, in case we log it seperately */ - table_set(r->notes, "cookie", cookiebuf); - - if (*cls->fname == '\0') /* Don't log cookies */ - return DECLINED; - - t = get_gmtoff(&timz); - sign = (timz < 0 ? '-' : '+'); - if(timz < 0) - timz = -timz; - - strftime(tstr,MAX_STRING_LEN,"\" [%d/%b/%Y:%H:%M:%S ",t); - if (r->status != -1) - sprintf(&tstr[strlen(tstr)], "%c%02ld%02ld] %d\n", sign, timz/3600, - timz%3600, r->status); - else - sprintf(&tstr[strlen(tstr)], "%c%02ld%02ld] -\n", sign, timz/3600, - timz%3600); - - str = pstrcat(orig->pool, cookiebuf, " \"", orig->the_request, tstr, NULL); - - write(cls->log_fd, str, strlen(str)); - - return OK; - } - - module cookies_module = { STANDARD_MODULE_STUFF, ! init_cookie_log, /* initializer */ ! make_cookie_dir, /* dir config creater */ ! NULL, /* dir merger --- default is to override */ ! make_cookie_log_state, /* server config */ ! NULL, /* merge server configs */ ! cookie_log_cmds, /* command table */ ! NULL, /* handlers */ ! NULL, /* filename translation */ ! NULL, /* check_user_id */ ! NULL, /* check auth */ ! NULL, /* check access */ ! NULL, /* type_checker */ ! spot_cookie, /* fixups */ ! cookie_log_transaction, /* logger */ }; --- 301,320 ---- { NULL } }; module cookies_module = { STANDARD_MODULE_STUFF, ! NULL, /* initializer */ ! make_cookie_dir, /* dir config creater */ ! NULL, /* dir merger --- default is to override */ ! make_cookie_log_state, /* server config */ ! NULL, /* merge server configs */ ! cookie_log_cmds, /* command table */ ! NULL, /* handlers */ ! NULL, /* filename translation */ ! NULL, /* check_user_id */ ! NULL, /* check auth */ ! NULL, /* check access */ ! NULL, /* type_checker */ ! spot_cookie, /* fixups */ ! NULL, /* logger */ }; *** mod_log_config.c.alex Tue Sep 3 09:13:59 1996 --- mod_log_config.c Tue Sep 3 09:46:38 1996 *************** *** 65,70 **** --- 65,72 ---- * CustomLog fn format * Log to file fn with format given by the format * argument + * CookieLog fn For backwards compatability with old Cookie + * logging module * * There can be any number of TransferLog and CustomLog * commands. Each request will be logged to _ALL_ the *************** *** 651,661 **** --- 653,670 ---- return add_custom_log(cmd, dummy, fn, NULL); } + char *set_cookie_log(cmd_parms *cmd, void *dummy, char *fn) + { + return add_custom_log(cmd, dummy, fn, "%{Cookie}n \"%r\" %t"); + } + command_rec config_log_cmds[] = { { "CustomLog", add_custom_log, NULL, RSRC_CONF, TAKE2, "a file name and a custom log format string" }, { "TransferLog", set_transfer_log, NULL, RSRC_CONF, TAKE1, "the filename of the access log" }, + { "CookieLog", set_cookie_log, NULL, RSRC_CONF, TAKE1, + "the filename of the Cookie log" }, { "LogFormat", log_format, NULL, RSRC_CONF, TAKE1, "a log format string (see docs)" }, { NULL }