From: Ian Holsman Date: Sat, 22 Jun 2002 03:36:57 +0000 (+0000) Subject: new configuration option for mod_rewrite to set cookies. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f2619b2b92a3b45c0d42edee7285bb284dafc826;p=apache new configuration option for mod_rewrite to set cookies. configuration is like the following RewriteRule (.*) - [CO=:$1::] Submitted by: Brian Degenhardt Reviewed by: Ian Holsman git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95840 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 38622a076d..6c75a5079b 100644 --- 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 , Ian Holsman] + *) Fix perchild to work with apachectl by adding -k support to perchild. PR 10074 [Jeff Trawick] diff --git a/docs/manual/mod/mod_rewrite.html.en b/docs/manual/mod/mod_rewrite.html.en index 85bffaf1bf..299baee02d 100644 --- a/docs/manual/mod/mod_rewrite.html.en +++ b/docs/manual/mod/mod_rewrite.html.en @@ -1467,6 +1467,15 @@ There is a special feature: it in a following RewriteCond pattern via %{ENV:VAR}. Use this to strip but remember information from URLs. + +
  • + 'cookie|CO=NAME:VAL:domain[:lifetime]' + (set cocookie)
    + This sets a cookie on the client's browser. The cookie's name + is specified by NAME and the value is + VAL. The domain field is the domain of the + cookie, such as '.apache.org' and the optional lifetime + is the lifetime of the cookie in minutes.
  • Note

    Never forget that Pattern is diff --git a/docs/manual/mod/mod_rewrite.xml b/docs/manual/mod/mod_rewrite.xml index 3e74dadd1a..7548d450fd 100644 --- a/docs/manual/mod/mod_rewrite.xml +++ b/docs/manual/mod/mod_rewrite.xml @@ -1605,6 +1605,16 @@ There is a special feature: it in a following RewriteCond pattern via %{ENV:VAR}. Use this to strip but remember information from URLs. + +
  • + 'cookie|CO=NAME:VAL:domain[:lifetime]' + (set cocookie)
    + This sets a cookie on the client's browser. The cookie's name + is specified by NAME and the value is + VAL. The domain field is the domain of the + cookie, such as '.apache.org' and the optional lifetime + is the lifetime of the cookie in minutes.
  • + Note Never forget that Pattern is diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c index cac38419d1..9aaddae54d 100644 --- a/modules/mappers/mod_rewrite.c +++ b/modules/mappers/mod_rewrite.c @@ -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 -') * we stop processing and return immediately. The only thing - * we have not to forget are the environment variables - * (`RewriteRule - [E=...]') + * we have not to forget are the environment variables and + * cookies: + * (`RewriteRule - [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=]'). + */ + 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); + } + } +} + /* ** diff --git a/modules/mappers/mod_rewrite.h b/modules/mappers/mod_rewrite.h index 7d7661dea9..6e9a848e77 100644 --- a/modules/mappers/mod_rewrite.h +++ b/modules/mappers/mod_rewrite.h @@ -231,9 +231,14 @@ #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 */