Rodent of Unusual Size <Ken.Coar@Golux.Com>
> Apache 1.3 STATUS:
...
> Available Patches:
...
I (hi - you haven't seen me here before) recently submitted a trivial
patch to extend mod_usertrack.c a bit. I would like to see it on the
list of available patches for 1.3, and either accepted or rejected.
The patch provides per-domain cookies (which I use to share user-ids
among the *.troll.no web servers) and configurable cookie names. It
also marginally increases the efficiency of Apache when the server
runs with DNS lookups turned off.
I hope nobody minds my posting the patch again.
--Arnt
--- /tmp/apache_1.3b3/src/modules/standard/mod_usertrack.c Wed Nov 5 12:23:23 1997
+++ mod_usertrack.c Fri Mar 13 18:53:29 1998
@@ -107,6 +107,8 @@
typedef struct {
int always;
time_t expires;
+ const char * name;
+ const char * domain;
} cookie_log_state;
static const char month_names[12][4] = {
@@ -118,11 +120,15 @@
*/
#define MILLENIAL_COOKIES
+/* Default cookie name. The CookieName directive allows overrriding
+ * this. Note that the trailing "=" is now gone.
+ */
+
+#define COOKIE_NAME "Apache"
+
/* Make Cookie: Now we have to generate something that is going to be
* pretty unique. We can base it on the pid, time, hostip */
-#define COOKIE_NAME "Apache="
-
void make_cookie(request_rec *r)
{
cookie_log_state *cls = get_module_config(r->server->module_config,
@@ -138,12 +144,6 @@
char *new_cookie = palloc(r->pool, 1024);
char *cookiebuf = palloc(r->pool, 1024);
char *dot;
- const char *rname = pstrdup(r->pool,
- get_remote_host(r->connection, r->per_dir_config,
- REMOTE_NAME));
-
- if ((dot = strchr(rname, '.')))
- *dot = '\0'; /* First bit of hostname */
#if defined(NO_GETTIMEOFDAY) && !defined(NO_TIMES)
/* We lack gettimeofday(), so we must use time() to obtain the epoch
@@ -152,7 +152,7 @@
mpe_times = times(&mpe_tms);
- ap_snprintf(cookiebuf, 1024, "%s%d%ld%ld", rname, (int) getpid(),
+ ap_snprintf(cookiebuf, 1024, "%d-%ld-%ld", (int) getpid(),
(long) r->request_time, (long) mpe_tms.tms_utime);
#elif defined(WIN32)
/*
@@ -161,13 +161,13 @@
* was started. It should be relatively unique.
*/
- ap_snprintf(cookiebuf, 1024, "%s%d%ld%ld", rname, (int) getpid(),
+ ap_snprintf(cookiebuf, 1024, "%d-%ld-%ld", (int) getpid(),
(long) r->request_time, (long) GetTickCount());
#else
gettimeofday(&tv, &tz);
- ap_snprintf(cookiebuf, 1024, "%s%d%ld%d", rname, (int) getpid(),
+ ap_snprintf(cookiebuf, 1024, "%d-%ld-%d", (int) getpid(),
(long) tv.tv_sec, (int) tv.tv_usec / 1000);
#endif
@@ -191,14 +191,16 @@
/* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */
ap_snprintf(new_cookie, 1024,
- "%s%s; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
- COOKIE_NAME, cookiebuf, days[tms->tm_wday],
- tms->tm_mday, month_names[tms->tm_mon],
- tms->tm_year % 100,
+ "%s=%s; path=/%s; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT",
+ cls->name ? cls->name : COOKIE_NAME, cookiebuf,
+ cls->domain ? cls->domain : "", days[tms->tm_wday],
+ tms->tm_mday, month_names[tms->tm_mon], tms->tm_year % 100,
tms->tm_hour, tms->tm_min, tms->tm_sec);
+ } else {
+ ap_snprintf(new_cookie, 1024, "%s=%s; path=/%s",
+ cls->name ? cls->name : COOKIE_NAME, cookiebuf,
+ cls->domain ? cls->domain : "");
}
- else
- ap_snprintf(new_cookie, 1024, "%s%s; path=/", COOKIE_NAME, cookiebuf);
table_set(r->headers_out, "Set-Cookie", new_cookie);
table_set(r->notes, "cookie", cookiebuf); /* log first time */
@@ -207,19 +209,21 @@
int spot_cookie(request_rec *r)
{
- int *enable = (int *) get_module_config(r->per_dir_config,
- &usertrack_module);
+ int * enable = (int*) get_module_config(r->per_dir_config,
+ &usertrack_module);
+ cookie_log_state *cls = get_module_config(r->server->module_config,
+ &usertrack_module);
char *cookie;
char *value;
- if (!*enable)
+ if (! *enable )
return DECLINED;
if ((cookie = table_get(r->headers_in, "Cookie")))
- if ((value = strstr(cookie, COOKIE_NAME))) {
+ if ((value = strstr(cookie, cls->name ? cls->name : COOKIE_NAME))) {
char *cookiebuf, *cookieend;
- value += strlen(COOKIE_NAME);
+ value += strlen(cls->name ? cls->name : COOKIE_NAME);
cookiebuf = pstrdup(r->pool, value);
cookieend = strchr(cookiebuf, ';');
if (cookieend)
@@ -251,7 +255,7 @@
const char *set_cookie_enable(cmd_parms *cmd, int *c, int arg)
{
- *c = arg;
+ *c = arg; /* referred to as cls->always in other places */
return NULL;
}
@@ -322,9 +326,86 @@
return NULL;
}
+
+/* Add domain cookie support to Apache.
+ *
+ * By settting "CookieDomain=your.domain.int" you can instruct the
+ * browsers to send this cookie to all servers in the "your.domain.int"
+ * domain. Note that Apache prepends the necessary "." itself.
+ *
+ * Added by Arnt Gulbrandsen <agulbra@troll.no>, March 1998. Comments
+ * are welcome: this is my first apache hack and without doubt could
+ * be improved on easily.
+ */
+
+const char *set_cookie_domain(cmd_parms *parms, void *dummy, const char *arg)
+{
+ int l;
+ const char * p;
+ int chars;
+ cookie_log_state *cls = get_module_config(parms->server->module_config,
+ &usertrack_module);
+
+ /* check that arg is a valid-looking domain name */
+
+ p = arg; /* current character */
+ chars = 0; /* characters seen since last dot */
+ while( *p ) {
+ if ( *p == '.' ) {
+ if ( chars == 0 )
+ return "bad domain name; contains consecutive '.' characters";
+ else
+ chars = 0;
+ } else if ( isalnum(*p) || *p == '/' || *p == '-' ) {
+ chars++;
+ } else {
+ return "bad domain name; contains illegal characters";
+ }
+ p++;
+ }
+
+ if ( chars < 2 || chars > 3 ) {
+ return "bad domain name; top-level domain must contain 2-3 characters";
+ }
+
+ /* at this point we know that arg looks kind of reasonable .
+ so we use it. */
+
+ l = strlen( "; domain=." ) + strlen( arg ) + 1;
+ cls->domain = palloc( parms->pool, l );
+ sprintf( (char *)(cls->domain), "; domain=.%s", arg );
+
+ return NULL;
+}
+
+
+const char *set_cookie_name(cmd_parms *parms, void *dummy, const char *arg)
+{
+ const char * p;
+ cookie_log_state *cls = get_module_config(parms->server->module_config,
+ &usertrack_module);
+
+ for( p=arg; *p; p++ )
+ if ( *p <= ' ' || *p >= (char)127 ||
+ *p == '(' || *p == ')' || *p == '<' || *p == '>' ||
+ *p == '@' || *p == ',' || *p == ';' || *p == ':' ||
+ *p == '\\' || *p == '"' || *p == '/' || *p == '[' ||
+ *p == ']' || *p == '?' || *p == '=' || *p == '{' )
+ return "bad cookie name; contains illegal character";
+
+ cls->name = pstrdup( parms->pool, arg );
+
+ return NULL;
+}
+
+
command_rec cookie_log_cmds[] = {
{"CookieExpires", set_cookie_exp, NULL, RSRC_CONF, TAKE1,
"an expiry date code"},
+ {"CookieDomain", set_cookie_domain, NULL, RSRC_CONF, TAKE1,
+ "what domain the cookie applies to"},
+ {"CookieName", set_cookie_name, NULL, RSRC_CONF, TAKE1,
+ "the name of Apache's built-in user-tracking cookie"},
{"CookieTracking", set_cookie_enable, NULL, OR_FILEINFO, FLAG,
"whether or not to enable cookies"},
{NULL}
|