Changes with Apache 1.3.20
+ *) Added NOESCAPE (NS) flag to RewriteRule and enabled use of
+ '\' to allow escaping of special characters. Previously
+ there was no way to embed either '$' or '%' in the output
+ of a RewriteRule; now 'foo\$1' will result in a literal
+ 'foo$1' appearing in the result rather than 'foo\<value of $1>'.
+ Note that [NS] disables *all* normal URI escaping, so incautious
+ use can give unexpected results. [Ken Coar]
+
*) Add support for Win32 apxs. Note that cygwin builders must use a
cygwin perl to avoid the MSWin32 handling. [William Rowe]
for Win32 systems, see http://www.cygwin.com)
[Stipe Tolj <tolj@wapme-systems.de>]
- *) Changes to 'ab'; fixed int overrun's, added statistics, output in
- csv/gnuplot format, rudimentary ssl support and various other tweaks
+ *) Changes to 'ab': fixed int overruns, added statistics, output in
+ csv/gnuplot format, rudimentary SSL support and various other tweaks
to make results more true to what is measured. The upshot of this it
turns out that 'ab' has often underreported the true performance of
apache. Often by a order of magnitude :-) See talk/paper of Sander
cfg->forced_responsecode = status;
}
}
+ else if ( strcasecmp(key, "noescape") == 0
+ || strcasecmp(key, "NE") == 0 ) {
+ cfg->flags |= RULEFLAG_NOESCAPE;
+ }
else if ( strcasecmp(key, "last") == 0
|| strcasecmp(key, "L") == 0 ) {
cfg->flags |= RULEFLAG_LASTRULE;
const char *ccp;
struct stat finfo;
unsigned int port;
+ int rulestatus;
int n;
int l;
/*
* now apply the rules ...
*/
- if (apply_rewrite_list(r, conf->rewriterules, NULL)) {
+ rulestatus = apply_rewrite_list(r, conf->rewriterules, NULL);
+ if (rulestatus) {
if (strlen(r->filename) > 6 &&
strncmp(r->filename, "proxy:", 6) == 0) {
for ( ; *cp != '/' && *cp != '\0'; cp++)
;
if (*cp != '\0') {
- rewritelog(r, 1, "escaping %s for redirect", r->filename);
- cp2 = ap_escape_uri(r->pool, cp);
+ if (rulestatus != ACTION_NOESCAPE) {
+ rewritelog(r, 1, "escaping %s for redirect", r->filename);
+ cp2 = ap_escape_uri(r->pool, cp);
+ }
+ else {
+ cp2 = ap_pstrdup(r->pool, cp);
+ }
*cp = '\0';
r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL);
}
/* append the QUERY_STRING part */
if (r->args != NULL) {
+ char *args;
+ if (rulestatus == ACTION_NOESCAPE) {
+ args = r->args;
+ }
+ else {
+ args = ap_escape_uri(r->pool, r->args);
+ }
r->filename = ap_pstrcat(r->pool, r->filename, "?",
- ap_escape_uri(r->pool, r->args), NULL);
+ args, NULL);
}
/* determine HTTP redirect response code */
const char *ccp;
char *prefix;
int l;
+ int rulestatus;
int n;
char *ofilename;
/*
* now apply the rules ...
*/
- if (apply_rewrite_list(r, dconf->rewriterules, dconf->directory)) {
+ rulestatus = apply_rewrite_list(r, dconf->rewriterules, dconf->directory);
+ if (rulestatus) {
if (strlen(r->filename) > 6 &&
strncmp(r->filename, "proxy:", 6) == 0) {
for ( ; *cp != '/' && *cp != '\0'; cp++)
;
if (*cp != '\0') {
- rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
- dconf->directory, r->filename);
- cp2 = ap_escape_uri(r->pool, cp);
+ if (rulestatus != ACTION_NOESCAPE) {
+ rewritelog(r, 1, "[per-dir %s] escaping %s for redirect",
+ dconf->directory, r->filename);
+ cp2 = ap_escape_uri(r->pool, cp);
+ }
+ else {
+ cp2 = ap_pstrdup(r->pool, cp);
+ }
*cp = '\0';
r->filename = ap_pstrcat(r->pool, r->filename, cp2, NULL);
}
/* append the QUERY_STRING part */
if (r->args != NULL) {
+ char *args;
+ if (rulestatus == ACTION_NOESCAPE) {
+ args = r->args;
+ }
+ else {
+ args = ap_escape_uri(r->pool, r->args);
+ }
r->filename = ap_pstrcat(r->pool, r->filename, "?",
- ap_escape_uri(r->pool, r->args), NULL);
+ args, NULL);
}
/* determine HTTP redirect response code */
* Indicate a change if this was not a match-only rule.
*/
if (rc != 2) {
- changed = 1;
+ changed = ((p->flags & RULEFLAG_NOESCAPE)
+ ? ACTION_NOESCAPE : ACTION_NORMAL);
}
/*
"to next API URI-to-filename handler", r->filename);
r->filename = ap_pstrcat(r->pool, "passthrough:",
r->filename, NULL);
- changed = 1;
+ changed = ACTION_NORMAL;
break;
}
rewritelog(r, 2, "forcing '%s' to be forbidden", r->filename);
r->filename = ap_pstrcat(r->pool, "forbidden:",
r->filename, NULL);
- changed = 1;
+ changed = ACTION_NORMAL;
break;
}
if (p->flags & RULEFLAG_GONE) {
rewritelog(r, 2, "forcing '%s' to be gone", r->filename);
r->filename = ap_pstrcat(r->pool, "gone:", r->filename, NULL);
- changed = 1;
+ changed = ACTION_NORMAL;
break;
}
space = nbuf - 1; /* room for '\0' */
for (;;) {
- span = strcspn(inp, "$%");
+ span = strcspn(inp, "\\$%");
if (span > space) {
span = space;
}
if (space == 0 || *inp == '\0') {
break;
}
- /* now we have a '$' or a '%' */
- if (inp[1] == '{') {
+ /* now we have a '\', '$', or '%' */
+ if (inp[0] == '\\') {
+ if (inp[1] != '\0') {
+ inp++;
+ goto skip;
+ }
+ }
+ else if (inp[1] == '{') {
char *endp;
endp = find_closing_bracket(inp+2, '{', '}');
if (endp == NULL) {
char xkey[MAX_STRING_LEN];
char xdflt[MAX_STRING_LEN];
key = find_char_in_brackets(inp+2, ':', '{', '}');
- if (key == NULL)
+ if (key == NULL) {
goto skip;
+ }
map = ap_pstrndup(r->pool, inp+2, key-inp-2);
dflt = find_char_in_brackets(key+1, '|', '{', '}');
if (dflt == NULL) {
key = ap_pstrndup(r->pool, key+1, endp-key-1);
dflt = "";
- } else {
+ }
+ else {
key = ap_pstrndup(r->pool, key+1, dflt-key-1);
dflt = ap_pstrndup(r->pool, dflt+1, endp-dflt-1);
}