On 09/08/2007 02:46 PM, wrote: > Author: niq > Date: Sat Sep 8 05:46:10 2007 > New Revision: 573831 > > URL: http://svn.apache.org/viewvc?rev=573831&view=rev > Log: > Add option to escape backreferences in RewriteRule. > PR 34602 and PR 39746 > Patch by Guenther Gsenger > > Modified: > httpd/httpd/trunk/CHANGES > httpd/httpd/trunk/docs/manual/mod/mod_rewrite.xml > httpd/httpd/trunk/modules/mappers/mod_rewrite.c >
> > Modified: httpd/httpd/trunk/docs/manual/mod/mod_rewrite.xml > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/docs/manual/mod/mod_rewrite.xml?rev=573831&r1=573830&r2=573831&view=diff > ============================================================================== > --- httpd/httpd/trunk/docs/manual/mod/mod_rewrite.xml (original) > +++ httpd/httpd/trunk/docs/manual/mod/mod_rewrite.xml Sat Sep 8 05:46:10 2007 > @@ -1243,6 +1243,21 @@ > brackets, of any of the following flags: </p> > > <dl> > + <dt>'<code>B</code>' (escape backreferences)</dt> > + <dd><p>Apache has to unescape URLs before mapping them, > + so backreferences will be unescaped at the time they are applied. > + Using the B flag, non-alphanumeric characters in backreferences > + will be escaped. For example, consider the rule:</p> > + <pre><code> RewriteRule RewriteRule ^(.*)$ index.php?show=$1 > </code></pre> > + <p>This will map <code>/C++</code> to > <code>index.php?show=C++</code>. > + But it will also map <code>/C%2b%2b</code> to > + <code>index.php?show=C++</code>, because the <code>%2b</code> > + has been unescaped. With the B flag, it will instead map to > + <code>index.php?show=>/C%2b%2b</code>.</p> > + <p>This escaping is particularly necessary in a proxy situation, > + when the backend may break if presented with an unescaped URL.</p> > + </dd> > + I am a little bit unsure if this can have security implications in some cases. > > > Modified: httpd/httpd/trunk/modules/mappers/mod_rewrite.c > URL: > http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/mappers/mod_rewrite.c?rev=573831&r1=573830&r2=573831&view=diff > ============================================================================== > --- httpd/httpd/trunk/modules/mappers/mod_rewrite.c (original) > +++ httpd/httpd/trunk/modules/mappers/mod_rewrite.c Sat Sep 8 05:46:10 2007 > @@ -635,6 +637,46 @@ > return 0; > } > > +static const char c2x_table[] = "0123456789abcdef"; > + > +static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix, > + unsigned char *where) > +{ > +#if APR_CHARSET_EBCDIC > + what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what); > +#endif /*APR_CHARSET_EBCDIC*/ > + *where++ = prefix; > + *where++ = c2x_table[what >> 4]; > + *where++ = c2x_table[what & 0xf]; > + return where; > +} > + > +/* > + * Escapes a uri in a similar way as php's urlencode does. > + * Based on ap_os_escape_path in server/util.c > + */ > +static char *escape_uri(apr_pool_t *p, const char *path) { > + char *copy = apr_palloc(p, 3 * strlen(path) + 3); > + const unsigned char *s = (const unsigned char *)path; > + unsigned char *d = (unsigned char *)copy; > + unsigned c; > + > + while ((c = *s)) { > + if (apr_isalnum(c) || c == '_') { > + *d++ = c; > + } > + else if (c == ' ') { > + *d++ = '+'; > + } > + else { > + d = c2x(c, '%', d); > + } > + ++s; > + } > + *d = '\0'; > + return copy; > +} > + Does it make sense to duplicate code? Shouldn't this be placed in util.c? > /* > * escape absolute uri, which may or may not be path oriented. > * So let's handle them differently. > @@ -2322,9 +2364,23 @@ > if (bri->source && n < AP_MAX_REG_MATCH > && bri->regmatch[n].rm_eo > bri->regmatch[n].rm_so) { > span = bri->regmatch[n].rm_eo - bri->regmatch[n].rm_so; > - > - current->len = span; > - current->string = bri->source + bri->regmatch[n].rm_so; > + if (entry && (entry->flags & RULEFLAG_ESCAPEBACKREF)) { > + /* escape the backreference */ > + char *tmp2, *tmp; > + tmp = apr_palloc(pool, span + 1); > + strncpy(tmp, bri->source + bri->regmatch[n].rm_so, span); How about using apr_pstrndup instead? > + tmp[span] = '\0'; > + tmp2 = escape_uri(pool, tmp); > + rewritelog((ctx->r, 5, ctx->perdir, "escaping > backreference '%s' to '%s'", > + tmp, tmp2)); > + > + current->len = span = strlen(tmp2); > + current->string = tmp2; > + } else { > + current->len = span; > + current->string = bri->source + bri->regmatch[n].rm_so; > + } > + > outlen += span; > } > Regards Rüdiger
