You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ji...@apache.org on 2002/12/16 14:17:38 UTC
cvs commit: apache-1.3/src/modules/standard mod_usertrack.c
jim 2002/12/16 05:17:38
Modified: src CHANGES
src/modules/standard mod_usertrack.c
Log:
Add in the new CookiePrefix and CookieFormat directives that allow
for the tracking cookie to have an arbitrary string prepended or
to choose a normal or "compact" cookie.
Obtained from: Fast Search & Transfer (contributed)
Submitted by: P�l L�berg <pa...@initio.no>
Reviewed by: Rasmus, Jim
Revision Changes Path
1.1868 +6 -0 apache-1.3/src/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apache-1.3/src/CHANGES,v
retrieving revision 1.1867
retrieving revision 1.1868
diff -u -r1.1867 -r1.1868
--- CHANGES 12 Dec 2002 16:09:49 -0000 1.1867
+++ CHANGES 16 Dec 2002 13:17:36 -0000 1.1868
@@ -1,5 +1,11 @@
Changes with Apache 1.3.28
+ *) Improvements to mod_usertrack that allows for a regular (verbose)
+ as well as "compact" version of the tracking cookie (the new
+ 'CookieFormat' directive), and the ability to prepend a string
+ to the cookie via the 'CookiePrefix' directive.
+ [P�l L�berg <pa...@initio.no>]
+
*) Certain 3rd party modules would bypass the Apache API and not
invoke ap_cleanup_for_exec() before creating sub-processes.
To such a child process, Apache's file descriptors (lock
1.53 +146 -17 apache-1.3/src/modules/standard/mod_usertrack.c
Index: mod_usertrack.c
===================================================================
RCS file: /home/cvs/apache-1.3/src/modules/standard/mod_usertrack.c,v
retrieving revision 1.52
retrieving revision 1.53
diff -u -r1.52 -r1.53
--- mod_usertrack.c 13 Mar 2002 21:05:34 -0000 1.52
+++ mod_usertrack.c 16 Dec 2002 13:17:38 -0000 1.53
@@ -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}
};