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}
   };