Ticket #911: lighttpd-1.4.18-redirect-rewrite-urlencoding.patch

File lighttpd-1.4.18-redirect-rewrite-urlencoding.patch, 5.1 kB (added by spillgroup, 9 months ago)
  • src/mod_redirect.c

    Patch for: http://trac.lighttpd.net/trac/ticket/911
    
    Allows $n and %n references to be actively urlencoded by using the # character.
    
    Example:
    
    $HTTP["referer"] =~ "(.+)" {
      url.redirect = (
        "(.*)" => "http://www.mydomain.com/myscript.php?&ref=%#1"
      )
    }
    
    So $n and %n are original values, while $#n and %#n are urlencoded values.
    This affects both mod_redirect and mod_rewrite.
    
    
    diff -Nur ../lighttpd-1.4.18/src/mod_redirect.c ./src/mod_redirect.c
    old new  
    1313#include "config.h" 
    1414#endif 
    1515 
     16/* Helper function */ 
     17int config_append_cond_match_buffer_encoded(connection *con, data_config *dc, buffer *buf, int n) 
     18{ 
     19        cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; 
     20        if (n > cache->patterncount) { 
     21                return 0; 
     22        } 
     23 
     24        n <<= 1; /* n *= 2 */ 
     25        buffer_append_string_encoded(buf, 
     26                        cache->comp_value->ptr + cache->matches[n], 
     27                        cache->matches[n + 1] - cache->matches[n], 
     28                        ENCODING_REL_URI_PART); 
     29        return 1; 
     30} 
     31 
    1632typedef struct { 
    1733        pcre_keyvalue_buffer *redirect; 
    1834        data_config *context; /* to which apply me */ 
     
    216232                        start = 0; end = pattern_len; 
    217233                        for (k = 0; k < pattern_len; k++) { 
    218234                                if ((pattern[k] == '$' || pattern[k] == '%') && 
    219                                     isdigit((unsigned char)pattern[k + 1])) { 
     235                                    (isdigit((unsigned char)pattern[k + 1]) ||  
     236                                    (pattern[k + 1] == '#' && pattern_len > k+2 && isdigit((unsigned char)pattern[k + 2])))) { 
     237                                     
    220238                                        /* got one */ 
    221  
    222                                         size_t num = pattern[k + 1] - '0'; 
     239                                        size_t num = 0; 
     240                                        if(pattern[k + 1] == '#') { 
     241                                                num = pattern[k + 2] - '0'; 
     242                                        } else { 
     243                                                num = pattern[k + 1] - '0'; 
     244                                        } 
    223245 
    224246                                        end = k; 
    225247 
     
    228250                                        if (pattern[k] == '$') { 
    229251                                                /* n is always > 0 */ 
    230252                                                if (num < (size_t)n) { 
    231                                                         buffer_append_string(p->location, list[num]); 
     253                                                        if(pattern[k + 1] == '#') { 
     254                                                                buffer_append_string_encoded(p->location, list[num], strlen(list[num]), ENCODING_REL_URI_PART); 
     255                                                        } else { 
     256                                                                buffer_append_string(p->location, list[num]); // HERE 
     257                                                        } 
    232258                                                } 
    233259                                        } else if (p->conf.context == NULL) { 
    234260                                                /* we have no context, we are global */ 
     
    236262                                                                "used a rewrite containing a %[0-9]+ in the global scope, ignored:", 
    237263                                                                kv->value); 
    238264                                        } else { 
    239                                                 config_append_cond_match_buffer(con, p->conf.context, p->location, num); 
     265                                                if(pattern[k + 1] == '#') { 
     266                                                        config_append_cond_match_buffer_encoded(con, p->conf.context, p->location, num); 
     267                                                } else { 
     268                                                        config_append_cond_match_buffer(con, p->conf.context, p->location, num); 
     269                                                } 
    240270                                        } 
    241271 
    242                                         k++; 
     272                                        if(pattern[k + 1] == '#') { 
     273                                                k += 2; 
     274                                        } else { 
     275                                                k++; 
     276                                        } 
     277                                         
    243278                                        start = k + 1; 
    244279                                } 
    245280                        } 
  • src/mod_rewrite.c

    diff -Nur ../lighttpd-1.4.18/src/mod_rewrite.c ./src/mod_rewrite.c
    old new  
    1212#include "config.h" 
    1313#endif 
    1414 
     15/* Helper function */ 
     16int config_append_cond_match_buffer_encoded(connection *con, data_config *dc, buffer *buf, int n) 
     17{ 
     18        cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; 
     19        if (n > cache->patterncount) { 
     20                return 0; 
     21        } 
     22 
     23        n <<= 1; /* n *= 2 */ 
     24        buffer_append_string_encoded(buf, 
     25                        cache->comp_value->ptr + cache->matches[n], 
     26                        cache->matches[n + 1] - cache->matches[n], 
     27                        ENCODING_REL_URI_PART); 
     28        return 1; 
     29} 
     30 
    1531typedef struct { 
    1632#ifdef HAVE_PCRE_H 
    1733        pcre *key; 
     
    386402                        start = 0; end = pattern_len; 
    387403                        for (k = 0; k < pattern_len; k++) { 
    388404                                if ((pattern[k] == '$' || pattern[k] == '%') && 
    389                                     isdigit((unsigned char)pattern[k + 1])) { 
     405                                    (isdigit((unsigned char)pattern[k + 1]) ||  
     406                                    (pattern[k + 1] == '#' && pattern_len > k+2 && isdigit((unsigned char)pattern[k + 2])))) { 
    390407                                        /* got one */ 
    391408 
    392                                         size_t num = pattern[k + 1] - '0'; 
     409                                        size_t num = 0; 
     410                                        if(pattern[k + 1] == '#') { 
     411                                                num = pattern[k + 2] - '0'; 
     412                                        } else { 
     413                                                num = pattern[k + 1] - '0'; 
     414                                        } 
    393415 
    394416                                        end = k; 
    395417 
     
    398420                                        if (pattern[k] == '$') { 
    399421                                                /* n is always > 0 */ 
    400422                                                if (num < (size_t)n) { 
    401                                                         buffer_append_string(con->request.uri, list[num]); 
     423                                                        if(pattern[k + 1] == '#') { 
     424                                                                buffer_append_string_encoded(con->request.uri, list[num], strlen(list[num]), ENCODING_REL_URI_PART); 
     425                                                        } else { 
     426                                                                buffer_append_string(con->request.uri, list[num]); 
     427                                                        } 
    402428                                                } 
    403429                                        } else if (p->conf.context == NULL) { 
    404430                                                /* we have no context, we are global */ 
     
    407433                                                                rule->value); 
    408434 
    409435                                        } else { 
    410                                                 config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num); 
     436                                                if(pattern[k + 1] == '#') { 
     437                                                        config_append_cond_match_buffer_encoded(con, p->conf.context, con->request.uri, num); 
     438                                                } else { 
     439                                                        config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num); 
     440                                                } 
    411441                                        } 
    412442 
    413                                         k++; 
     443                                        if(pattern[k + 1] == '#') { 
     444                                                k += 2; 
     445                                        } else { 
     446                                                k++; 
     447                                        } 
     448                                         
    414449                                        start = k + 1; 
    415450                                } 
    416451                        }