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,
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;
/*
* 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
*/
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
}
}
+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);
+ }
+}
+
/*
**
}
}
+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);
+ }
+ }
+}
+
/*
**
#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
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;
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);
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 */