]> granicus.if.org Git - apache/commitdiff
new configuration option for mod_rewrite to set cookies.
authorIan Holsman <ianh@apache.org>
Sat, 22 Jun 2002 03:36:57 +0000 (03:36 +0000)
committerIan Holsman <ianh@apache.org>
Sat, 22 Jun 2002 03:36:57 +0000 (03:36 +0000)
configuration is like the following

RewriteRule (.*) - [CO=<cookiename>:$1:<domain>:<expiry in minutes>]

Submitted by: Brian Degenhardt <bmd@mp3.com>
Reviewed by: Ian Holsman

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95840 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_rewrite.html.en
docs/manual/mod/mod_rewrite.xml
modules/mappers/mod_rewrite.c
modules/mappers/mod_rewrite.h

diff --git a/CHANGES b/CHANGES
index 38622a076d3a48b5efda13a9e69f8c7f321ac482..6c75a5079b718581f895ff92eaab0ffde15cbbd2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
 
 Changes with Apache 2.0.40
 
+  *) mod_rewrite can now set cookies  (RewriteRule (.*) - [CO=name:$1:.domain])
+     [Brian Degenhardt <bmd@mp3.com>, Ian Holsman]
+
   *) Fix perchild to work with apachectl by adding -k support to perchild.
      PR 10074  [Jeff Trawick]
 
index 85bffaf1bf2b165c5e2a7c84d1fa8c94383be046..299baee02d3878f59e37f5c82ff1eb3f5ccb976c 100644 (file)
@@ -1467,6 +1467,15 @@ There is a special feature:
         it in a following RewriteCond pattern via
         <code>%{ENV:VAR}</code>. Use this to strip but remember
         information from URLs.</li>
+
+        <li>
+        '<strong><code>cookie|CO=</code></strong><em>NAME</em>:<em>VAL</em>:<em>domain</em>[:<em>lifetime</em>]'
+        (set <strong>co</strong>cookie)<br>
+        This sets a cookie on the client's browser.  The cookie's name
+        is specified by <em>NAME</em> and the value is
+        <em>VAL</em>. The <em>domain</em> field is the domain of the
+        cookie, such as '.apache.org' and the optional <em>lifetime</em>
+        is the lifetime of the cookie in minutes.</li>
       </ul>
 
 <blockquote><table><tr><td bgcolor="#e0e5f5"><p align="center"><strong>Note</strong></p> Never forget that <em>Pattern</em> is
index 3e74dadd1a698979f37a64ce04749bf55585bfb6..7548d450fda50d2c3cbfff51823309925cf09082 100644 (file)
@@ -1605,6 +1605,16 @@ There is a special feature:
         it in a following RewriteCond pattern via
         <code>%{ENV:VAR}</code>. Use this to strip but remember
         information from URLs.</li>
+
+        <li>
+        '<strong><code>cookie|CO=</code></strong><em>NAME</em>:<em>VAL</em>:<em>domain</em>[:<em>lifetime</em>]'
+        (set <strong>co</strong>cookie)<br>
+        This sets a cookie on the client's browser.  The cookie's name
+        is specified by <em>NAME</em> and the value is
+        <em>VAL</em>. The <em>domain</em> field is the domain of the
+        cookie, such as '.apache.org' and the optional <em>lifetime</em>
+        is the lifetime of the cookie in minutes.</li>
       </ul>
 
 <note><title>Note</title> Never forget that <em>Pattern</em> is
index cac38419d11b77c46355a2e3dee1a25e9180a527..9aaddae54df5355c345a5a9ee52feb663f4a50c0 100644 (file)
@@ -707,6 +707,7 @@ static const char *cmd_rewriterule(cmd_parms *cmd, void *in_dconf,
     newrule->forced_responsecode = HTTP_MOVED_TEMPORARILY;
     newrule->flags  = RULEFLAG_NONE;
     newrule->env[0] = NULL;
+    newrule->cookie[0] = NULL;
     newrule->skip   = 0;
     if (a3 != NULL) {
         if ((err = cmd_rewriterule_parseflagfield(cmd->pool, newrule,
@@ -875,6 +876,17 @@ static const char *cmd_rewriterule_setflag(apr_pool_t *p, rewriterule_entry *cfg
             return "RewriteRule: too many environment flags 'E'";
         }
     }
+    else  if ( strcasecmp(key, "cookie") == 0 || strcasecmp(key, "CO") == 0) {
+        for (i = 0; (cfg->cookie[i] != NULL) && (i < MAX_COOKIE_FLAGS); i++)
+            ;
+        if (i < MAX_COOKIE_FLAGS) {
+            cfg->cookie[i] = apr_pstrdup(p, val);
+            cfg->cookie[i+1] = NULL;
+        }
+        else {
+            return "RewriteRule: too many cookie flags 'CO'";
+        }
+    }
     else if (   strcasecmp(key, "nosubreq") == 0
              || strcasecmp(key, "NS") == 0      ) {
         cfg->flags |= RULEFLAG_IGNOREONSUBREQ;
@@ -1960,11 +1972,13 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
     /*
      *  If this is a pure matching rule (`RewriteRule <pat> -')
      *  we stop processing and return immediately. The only thing
-     *  we have not to forget are the environment variables
-     *  (`RewriteRule <pat> - [E=...]')
+     *  we have not to forget are the environment variables and
+     *  cookies:
+     *  (`RewriteRule <pat> - [E=...,CO=...]')
      */
     if (strcmp(output, "-") == 0) {
         do_expand_env(r, p->env, briRR, briRC);
+        do_expand_cookie(r, p->cookie, briRR, briRC);
         if (p->forced_mimetype != NULL) {
             if (perdir == NULL) {
                 /* In the per-server context we can force the MIME-type
@@ -2013,6 +2027,12 @@ static int apply_rewrite_rule(request_rec *r, rewriterule_entry *p,
      */
     do_expand_env(r, p->env, briRR, briRC);
 
+    /*
+     *  Also set cookies for any cookie strings
+     *  (`RewriteRule .. .. [CO=<string>]').
+     */
+    do_expand_cookie(r, p->cookie, briRR, briRC);
+
     /*
      *  Now replace API's knowledge of the current URI:
      *  Replace r->filename with the new URI string and split out
@@ -2460,6 +2480,18 @@ static void do_expand_env(request_rec *r, char *env[],
     }
 }
 
+static void do_expand_cookie( request_rec *r, char *cookie[],
+                              backrefinfo *briRR, backrefinfo *briRC)
+{
+    int i;
+    char buf[MAX_STRING_LEN];
+
+    for (i = 0; cookie[i] != NULL; i++) {
+        do_expand(r, cookie[i], buf, sizeof(buf), briRR, briRC);
+        add_cookie(r, buf);
+    }
+}
+
 
 /*
 **
@@ -4097,6 +4129,50 @@ static void add_env_variable(request_rec *r, char *s)
     }
 }
 
+static void add_cookie(request_rec *r, char *s)
+{
+    char *var;
+    char *val;
+    char *domain;
+    char *expires;
+
+    char *tok_cntx;
+    char *cookie;
+
+    if (s) {
+        var = apr_strtok(s, ":", &tok_cntx);
+        val = apr_strtok(NULL, ":", &tok_cntx);
+        domain = apr_strtok(NULL, ":", &tok_cntx);
+        /** the line below won't hit the token ever **/
+        expires = apr_strtok(NULL, ":", &tok_cntx); 
+
+        if (var && val && domain) {
+            /* FIX: use cached time similar to how logging does it */
+            cookie = apr_pstrcat( r->pool, 
+                                  var,
+                                  "=",
+                                  val,
+                                  "; path=/; domain=",
+                                  domain,
+                                  (expires)? "; expires=" : NULL,
+                                  (expires)? ap_ht_time(r->pool, 
+                                                        r->request_time + 
+                                                        (60 * atol(expires)),
+                                                         "%a, %d-%b-%Y %T GMT", 1)
+                                           : NULL, 
+                                  NULL);
+
+            
+            /* 
+             * XXX: should we add it to err_headers_out as well ?
+             * if we do we need to be careful that only ONE gets sent out
+             */
+            apr_table_add(r->headers_out, "Set-Cookie", cookie);
+            rewritelog(r, 5, "setting cookie '%s' to '%s'", var, val);
+        }
+    }
+}
+
 
 /*
 **
index 7d7661dea9d84e83b645ecc6a448a8b44a9af121..6e9a848e77f1f477bf634d7fe984c15a343ad037 100644 (file)
 #endif
 
 #define MAX_ENV_FLAGS 15
+#define MAX_COOKIE_FLAGS 15
+/*** max cookie size in rfc 2109 ***/
+#define MAX_COOKIE_LEN 4096
 
 #define MAX_NMATCH    10
 
+
+
 /*
 **
 **  our private data structures we handle with
@@ -272,6 +277,7 @@ typedef struct {
     char    *forced_mimetype;      /* forced MIME type of substitution */
     int      forced_responsecode;  /* forced HTTP redirect response status */
     char    *env[MAX_ENV_FLAGS+1]; /* added environment variables */
+    char    *cookie[MAX_COOKIE_FLAGS+1]; /* added cookies */
     int      skip;                 /* number of next rules to skip */
 } rewriterule_entry;
 
@@ -414,6 +420,8 @@ static void do_expand(request_rec *r, char *input, char *buffer, int nbuf,
                      backrefinfo *briRR, backrefinfo *briRC);
 static void do_expand_env(request_rec *r, char *env[],
                          backrefinfo *briRR, backrefinfo *briRC);
+static void do_expand_cookie(request_rec *r, char *cookie[],
+                         backrefinfo *briRR, backrefinfo *briRC);
 
     /* URI transformation function */
 static void  splitout_queryargs(request_rec *r, int qsappend);
@@ -481,6 +489,7 @@ static char  *subst_prefix_path(request_rec *r, char *input, char *match,
 static int    parseargline(char *str, char **a1, char **a2, char **a3);
 static int    prefix_stat(const char *path, apr_finfo_t *sb);
 static void   add_env_variable(request_rec *r, char *s);
+static void   add_cookie(request_rec *r, char *s);
 static int    subreq_ok(request_rec *r);
 
     /* Lexicographic Comparison */