Return-Path: Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 93095 invoked by uid 500); 6 Dec 2002 18:09:45 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: list-post: Delivered-To: mailing list dev@httpd.apache.org Delivered-To: moderator for dev@httpd.apache.org Received: (qmail 65344 invoked from network); 6 Dec 2002 14:18:31 -0000 X-Authentication-Warning: pi.boston.fast.no: andrei set sender to andrei.zmievski@fastsearch.com using -f Date: Fri, 6 Dec 2002 09:16:55 -0500 From: Andrei Zmievski To: jim@jagunet.com Cc: dev@httpd.apache.org, Rasmus Lerdorf Subject: Re: mod_usertrack patch Message-ID: <20021206091655.A12325@pi.boston.fast.no> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="dDRMvlgZJXvWKvBx" Content-Disposition: inline User-Agent: Mutt/1.2.5.1i X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N --dDRMvlgZJXvWKvBx Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Jim, Resubmitting the patch, as you requested. -- Andrei Zmievski Mail: andrei.zmievski@fastsearch.com Sr. Front End Software Engineer Web: http://www.fast.no/ Fast Search & Transfer Inc Phone: 781-304-2493 93 Worcester Street Fax: 781-304-2410 Wellesley MA 02481-9181, USA Main: 781-304-2400 --dDRMvlgZJXvWKvBx Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mod_usertrack.patch" --- src/modules/standard/mod_usertrack.c.orig Wed Mar 13 16:05:34 2002 +++ src/modules/standard/mod_usertrack.c Tue Jul 9 11:10:27 2002 @@ -114,11 +114,18 @@ CT_COOKIE2 } cookie_type_e; +typedef enum { + CF_NORMAL, + CF_COMPACT +} cookie_format_e; + typedef struct { int enabled; cookie_type_e style; + cookie_format_e format; char *cookie_name; char *cookie_domain; + char *prefix_string; } cookie_dir_rec; /* Define this to allow post-2000 cookies. Cookies use two-digit dates, @@ -126,15 +133,18 @@ */ #define MILLENIAL_COOKIES -/* Make Cookie: Now we have to generate something that is going to be - * pretty unique. We can base it on the pid, time, hostip */ - +/* Default name of the cookie + */ #define COOKIE_NAME "Apache" -static void make_cookie(request_rec *r) + +/* Make normal cookie: Try to make something unique based on + * pid, time, and hostid, plus the user-configurable prefix. + * + * This function will make a "verbose" version of the cookie. + */ +static char * make_normal_id(char * buffer, int bufsize, request_rec *r) { - cookie_log_state *cls = ap_get_module_config(r->server->module_config, - &usertrack_module); #if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES) clock_t mpe_times; struct tms mpe_tms; @@ -146,9 +156,6 @@ struct timezone tz = {0, 0}; #endif /* defined(NETWARE) */ #endif - /* 1024 == hardcoded constant */ - char cookiebuf[1024]; - char *new_cookie; const char *rname = ap_get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME); cookie_dir_rec *dcfg; @@ -162,12 +169,13 @@ mpe_times = times(&mpe_tms); - ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, - (int) getpid(), + ap_snprintf(buffer, bufsize, "%s%s.%d%ld%ld", + dcfg->prefix_string, rname, (int) getpid(), (long) r->request_time, (long) mpe_tms.tms_utime); #elif defined(NETWARE) - ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, - (int) getpid(), (long) r->request_time, (long) clock()); + ap_snprintf(buffer, bufsize, "%s%s.%d%ld%ld", + dcfg->prefix_string, rname, (int) getpid(), + (long) r->request_time, (long) clock()); #elif defined(WIN32) /* * We lack gettimeofday() and we lack times(). So we'll use a combination @@ -175,18 +183,100 @@ * was started. It should be relatively unique. */ - ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%ld", rname, - (int) getpid(), + ap_snprintf(buffer, bufsize, "%s%s.%d%ld%ld", + dcfg->prefix_string, rname, (int) getpid(), (long) r->request_time, (long) GetTickCount()); #else gettimeofday(&tv, &tz); - ap_snprintf(cookiebuf, sizeof(cookiebuf), "%s.%d%ld%d", rname, - (int) getpid(), + ap_snprintf(buffer, bufsize, "%s%s.%d%ld%d", + dcfg->prefix_string, rname, (int) getpid(), (long) tv.tv_sec, (int) tv.tv_usec / 1000); #endif + return buffer; +} + + +/* Make normal cookie: Try to make something unique based on + * pid, time, and hostid, plus the user-configurable prefix. + * + * This function will make a "compact" version of the cookie. + */ +static char * make_compact_id(char * buffer, int bufsize, request_rec *r) +{ +#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES) + clock_t mpe_times; + struct tms mpe_tms; +#elif !defined(WIN32) + struct timeval tv; +#ifdef NETWARE + time_t tz = 0; +#else + struct timezone tz = {0, 0}; +#endif /* defined(NETWARE) */ +#endif + unsigned long ipaddr = ntohl(r->connection->remote_addr.sin_addr.s_addr); + cookie_dir_rec *dcfg; + + dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module); + +#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES) +/* We lack gettimeofday(), so we must use time() to obtain the epoch + seconds, and then times() to obtain CPU clock ticks (milliseconds). + Combine this together to obtain a hopefully unique cookie ID. */ + + mpe_times = times(&mpe_tms); + + ap_snprintf(buffer, bufsize, "%s%lx%x%lx%lx", + dcfg->prefix_string, ipaddr, (int) getpid(), + (long) r->request_time, (long) mpe_tms.tms_utime); +#elif defined(NETWARE) + ap_snprintf(buffer, bufsize, "%s%lx%x%lx%lx", + dcfg->prefix_string, ipaddr, (int) getpid(), + (long) r->request_time, (long) clock()); +#elif defined(WIN32) + /* + * We lack gettimeofday() and we lack times(). So we'll use a combination + * of time() and GetTickCount(), which returns milliseconds since Windows + * was started. It should be relatively unique. + */ + + ap_snprintf(buffer, bufsize, "%s%lx%x%lx%lx", + dcfg->prefix_string, ipaddr, (int) getpid(), + (long) r->request_time, (long) GetTickCount()); + +#else + gettimeofday(&tv, &tz); + + ap_snprintf(buffer, bufsize, "%s%lx%x%lx%x", + dcfg->prefix_string, ipaddr, (int) getpid(), + (long) tv.tv_sec, (int)(tv.tv_usec % 65535)); +#endif + + return buffer; +} + + +static void make_cookie(request_rec *r) +{ + cookie_log_state *cls = ap_get_module_config(r->server->module_config, + &usertrack_module); + + /* 1024 == hardcoded constant */ + char cookiebuf[1024]; + char *new_cookie; + cookie_dir_rec *dcfg; + + dcfg = ap_get_module_config(r->per_dir_config, &usertrack_module); + + if (dcfg->format == CF_COMPACT) { + make_compact_id(cookiebuf, sizeof(cookiebuf), r); + } else { + make_normal_id(cookiebuf, sizeof(cookiebuf), r); + } + if (cls->expires) { struct tm *tms; time_t when; @@ -296,7 +386,9 @@ dcfg = (cookie_dir_rec *) ap_pcalloc(p, sizeof(cookie_dir_rec)); dcfg->cookie_name = COOKIE_NAME; dcfg->cookie_domain = NULL; + dcfg->prefix_string = ""; dcfg->style = CT_UNSET; + dcfg->format = CF_NORMAL; dcfg->enabled = 0; return dcfg; } @@ -440,6 +532,39 @@ return NULL; } +/* + * Make a note of the cookie format we should use. + */ +static const char *set_cookie_format(cmd_parms *cmd, void *mconfig, char *name) +{ + cookie_dir_rec *dcfg; + + dcfg = (cookie_dir_rec *) mconfig; + + if (strcasecmp(name, "Normal") == 0) { + dcfg->format = CF_NORMAL; + } + else if (strcasecmp(name, "Compact") == 0) { + dcfg->format = CF_COMPACT; + } + else { + return ap_psprintf(cmd->pool, "Invalid %s keyword: '%s'", + cmd->cmd->name, name); + } + + return NULL; +} + +static const char *set_cookie_prefix(cmd_parms *cmd, void *mconfig, char *name) +{ + cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig; + + dcfg->prefix_string = ap_pstrdup(cmd->pool, name); + + return NULL; +} + + static const command_rec cookie_log_cmds[] = { {"CookieExpires", set_cookie_exp, NULL, OR_FILEINFO, TAKE1, "an expiry date code"}, @@ -451,6 +576,10 @@ "domain to which this cookie applies"}, {"CookieStyle", set_cookie_style, NULL, OR_FILEINFO, TAKE1, "'Netscape', 'Cookie' (RFC2109), or 'Cookie2' (RFC2965)"}, + {"CookieFormat", set_cookie_format, NULL, OR_FILEINFO, TAKE1, + "'Normal' or 'Compact'"}, + {"CookiePrefix", set_cookie_prefix, NULL, OR_FILEINFO, TAKE1, + "String prepended to cookie"}, {NULL} }; --dDRMvlgZJXvWKvBx--