@@ -380,6 +380,7 @@ static apr_global_mutex_t *rewrite_log_lock = NULL;
380380/* Optional functions imported from mod_ssl when loaded: */
381381static APR_OPTIONAL_FN_TYPE (ssl_var_lookup ) * rewrite_ssl_lookup = NULL ;
382382static APR_OPTIONAL_FN_TYPE (ssl_is_https ) * rewrite_is_https = NULL ;
383+ static char * escape_uri (apr_pool_t * p , const char * path );
383384
384385/*
385386 * +-------------------------------------------------------+
@@ -628,6 +629,46 @@ static unsigned is_absolute_uri(char *uri)
628629 return 0 ;
629630}
630631
632+ static const char c2x_table [] = "0123456789abcdef" ;
633+
634+ static APR_INLINE unsigned char * c2x (unsigned what , unsigned char prefix ,
635+ unsigned char * where )
636+ {
637+ #if APR_CHARSET_EBCDIC
638+ what = apr_xlate_conv_byte (ap_hdrs_to_ascii , (unsigned char )what );
639+ #endif /*APR_CHARSET_EBCDIC*/
640+ * where ++ = prefix ;
641+ * where ++ = c2x_table [what >> 4 ];
642+ * where ++ = c2x_table [what & 0xf ];
643+ return where ;
644+ }
645+
646+ /*
647+ * Escapes a uri in a similar way as php's urlencode does.
648+ * Based on ap_os_escape_path in server/util.c
649+ */
650+ static char * escape_uri (apr_pool_t * p , const char * path ) {
651+ char * copy = apr_palloc (p , 3 * strlen (path ) + 3 );
652+ const unsigned char * s = (const unsigned char * )path ;
653+ unsigned char * d = (unsigned char * )copy ;
654+ unsigned c ;
655+
656+ while ((c = * s )) {
657+ if (apr_isalnum (c ) || c == '_' ) {
658+ * d ++ = c ;
659+ }
660+ else if (c == ' ' ) {
661+ * d ++ = '+' ;
662+ }
663+ else {
664+ d = c2x (c , '%' , d );
665+ }
666+ ++ s ;
667+ }
668+ * d = '\0' ;
669+ return copy ;
670+ }
671+
631672/*
632673 * escape absolute uri, which may or may not be path oriented.
633674 * So let's handle them differently.
@@ -2240,15 +2281,16 @@ static char *do_expand(char *input, rewrite_ctx *ctx, rewriterule_entry *entry)
22402281 if (entry && (entry -> flags & RULEFLAG_ESCAPEBACKREF )) {
22412282 /* escape the backreference */
22422283 char * tmp2 , * tmp ;
2243- tmp = apr_pstrndup (pool , bri -> source + bri -> regmatch [n ].rm_so , span );
2244- tmp2 = ap_escape_path_segment (pool , tmp );
2284+ tmp = apr_palloc (pool , span + 1 );
2285+ strncpy (tmp , bri -> source + bri -> regmatch [n ].rm_so , span );
2286+ tmp [span ] = '\0' ;
2287+ tmp2 = escape_uri (pool , tmp );
22452288 rewritelog ((ctx -> r , 5 , ctx -> perdir , "escaping backreference '%s' to '%s'" ,
22462289 tmp , tmp2 ));
22472290
22482291 current -> len = span = strlen (tmp2 );
22492292 current -> string = tmp2 ;
2250- }
2251- else {
2293+ } else {
22522294 current -> len = span ;
22532295 current -> string = bri -> source + bri -> regmatch [n ].rm_so ;
22542296 }
0 commit comments