Feature #443 » ticket-443.patch
tests/mod-redirect.t (working copy) | ||
---|---|---|
use strict;
|
||
use IO::Socket;
|
||
use Test::More tests => 6;
|
||
use Test::More tests => 8;
|
||
use LightyTest;
|
||
my $tf = LightyTest->new();
|
||
... | ... | |
Host: vvv.example.org
|
||
EOF
|
||
);
|
||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/' } ];
|
||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/$' } ];
|
||
ok($tf->handle_http($t) == 0, 'external redirect');
|
||
$t->{REQUEST} = ( <<EOF
|
||
GET /redirect/vvv/ HTTP/1.0
|
||
Host: vvv.example.org
|
||
EOF
|
||
);
|
||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/$vvv%2f' } ];
|
||
ok($tf->handle_http($t) == 0, 'external redirect with urlencoded');
|
||
$t->{REQUEST} = ( <<EOF
|
||
GET /redirect/ HTTP/1.0
|
||
Host: zzz.example.org
|
||
Referer: zzz
|
||
EOF
|
||
);
|
||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/zzz' } ];
|
||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/%zzz' } ];
|
||
ok($tf->handle_http($t) == 0, 'external redirect with cond regsub');
|
||
$t->{REQUEST} = ( <<EOF
|
||
GET /redirect/ HTTP/1.0
|
||
Host: zzz.example.org
|
||
Referer: zzz/
|
||
EOF
|
||
);
|
||
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 301, 'Location' => 'http://localhost:'.$tf->{PORT}.'/%zzz%2f' } ];
|
||
ok($tf->handle_http($t) == 0, 'external redirect with cond regsub and urlencoded');
|
||
$t->{REQUEST} = ( <<EOF
|
||
GET /redirect/ HTTP/1.0
|
||
Host: remoteip.example.org
|
||
EOF
|
||
);
|
tests/lighttpd.conf (working copy) | ||
---|---|---|
}
|
||
$HTTP["host"] =~ "(vvv).example.org" {
|
||
url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
|
||
url.redirect = ( "^/redirect/(.*)?$" => "http://localhost:2048/$$$!1" )
|
||
}
|
||
$HTTP["host"] =~ "(zzz).example.org" {
|
||
url.redirect = ( "^/redirect/$" => "http://localhost:2048/%1" )
|
||
$HTTP["host"] =~ "zzz.example.org" {
|
||
url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
|
||
$HTTP["referer"] =~ "(.+)" {
|
||
url.redirect = ( "^/redirect/$" => "http://localhost:2048/%%%!1" )
|
||
}
|
||
}
|
||
$HTTP["host"] =~ "(remoteip)\.example\.org" {
|
src/buffer.c (working copy) | ||
---|---|---|
map = encoded_chars_hex;
|
||
break;
|
||
case ENCODING_UNSET:
|
||
break;
|
||
return buffer_append_string_len(b, s, s_len);
|
||
}
|
||
assert(map != NULL);
|
src/plugin.h (working copy) | ||
---|---|---|
int config_setup_connection(server *srv, connection *con);
|
||
int config_patch_connection(server *srv, connection *con, comp_key_t comp);
|
||
int config_check_cond(server *srv, connection *con, data_config *dc);
|
||
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
|
||
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n, buffer_encoding_t encoding);
|
||
int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
|
||
#endif
|
src/keyvalue.h (working copy) | ||
---|---|---|
char *value;
|
||
} s_keyvalue;
|
||
typedef enum {
|
||
PCRE_PIECE_STRING,
|
||
PCRE_PIECE_SUB_KEY,
|
||
PCRE_PIECE_SUB_KEY_ENCODE,
|
||
PCRE_PIECE_SUB_COND,
|
||
PCRE_PIECE_SUB_COND_ENCODE
|
||
} pcre_piece_type_t;
|
||
typedef struct {
|
||
pcre_piece_type_t type;
|
||
union {
|
||
buffer *buf;
|
||
size_t num;
|
||
} u;
|
||
} pcre_piece_t;
|
||
typedef struct {
|
||
#ifdef HAVE_PCRE_H
|
||
pcre *key;
|
||
pcre_extra *key_extra;
|
||
#endif
|
||
buffer *value;
|
||
pcre_piece_t *pieces;
|
||
size_t pieces_count;
|
||
} pcre_keyvalue;
|
||
typedef enum { HTTP_AUTH_BASIC, HTTP_AUTH_DIGEST } httpauth_type;
|
src/keyvalue.c (working copy) | ||
---|---|---|
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <stdio.h>
|
||
#include <ctype.h>
|
||
#include "server.h"
|
||
#include "keyvalue.h"
|
||
#include "buffer.h"
|
||
static keyvalue http_versions[] = {
|
||
{ HTTP_VERSION_1_1, "HTTP/1.1" },
|
||
... | ... | |
return kvb;
|
||
}
|
||
static size_t pcre_keyvalue_parse_value(pcre_piece_t *result, buffer *value)
|
||
{
|
||
size_t start;
|
||
size_t i;
|
||
size_t count = 0;
|
||
size_t pattern_len = value->used - 1;
|
||
const char *pattern = value->ptr;
|
||
int lastisstring = 0;
|
||
#define ADD_PIECE_SUB(_type, _num) \
|
||
if (result) { \
|
||
result[count].type = _type; \
|
||
result[count].u.num = _num; \
|
||
} \
|
||
count ++; \
|
||
lastisstring = 0;
|
||
#define ADD_PIECE_STRING(end) \
|
||
if ((end) != start) { \
|
||
if (lastisstring) { \
|
||
if (result) { \
|
||
buffer_append_string_len(result[count - 1].u.buf, pattern + start, (end) - start); \
|
||
} \
|
||
} \
|
||
else { \
|
||
if (result) { \
|
||
result[count].type = PCRE_PIECE_STRING; \
|
||
result[count].u.buf = buffer_init(); \
|
||
buffer_append_string_len(result[count].u.buf, pattern + start, (end) - start); \
|
||
} \
|
||
count ++; \
|
||
} \
|
||
lastisstring = 1; \
|
||
}
|
||
start = 0;
|
||
for (i = 0; i < pattern_len; i++) {
|
||
if (pattern[i] == '$' || pattern[i] == '%') {
|
||
if (isdigit((unsigned char)pattern[i + 1])) {
|
||
size_t num = pattern[i + 1] - '0';
|
||
ADD_PIECE_STRING(i);
|
||
if (pattern[i] == '$') {
|
||
ADD_PIECE_SUB(PCRE_PIECE_SUB_KEY, num);
|
||
} else {
|
||
ADD_PIECE_SUB(PCRE_PIECE_SUB_COND, num);
|
||
}
|
||
i++;
|
||
start = i + 1;
|
||
} else if (pattern[i + 1] == '!' && isdigit((unsigned char)pattern[i + 2])) {
|
||
size_t num = pattern[i + 2] - '0';
|
||
ADD_PIECE_STRING(i);
|
||
if (pattern[i] == '$') {
|
||
ADD_PIECE_SUB(PCRE_PIECE_SUB_KEY_ENCODE, num);
|
||
} else {
|
||
ADD_PIECE_SUB(PCRE_PIECE_SUB_COND_ENCODE, num);
|
||
}
|
||
i += 2;
|
||
start = i + 1;
|
||
} else if (pattern[i + 1] == pattern[i]) {
|
||
ADD_PIECE_STRING(i);
|
||
start = i;
|
||
/* add the % or $ */
|
||
ADD_PIECE_STRING(i + 1);
|
||
i ++;
|
||
start = i + 1;
|
||
}
|
||
}
|
||
}
|
||
ADD_PIECE_STRING(pattern_len);
|
||
#undef ADD_PIECE_STRING
|
||
return count;
|
||
}
|
||
int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, const char *value) {
|
||
#ifdef HAVE_PCRE_H
|
||
size_t i;
|
||
... | ... | |
}
|
||
kv->value = buffer_init_string(value);
|
||
kv->pieces_count = pcre_keyvalue_parse_value(NULL, kv->value);
|
||
kv->pieces = calloc(kv->pieces_count, sizeof(*kv->pieces));
|
||
pcre_keyvalue_parse_value(kv->pieces, kv->value);
|
||
#if 0
|
||
fprintf(stderr, "pattern %s is parsed into:\n", kv->value->ptr);
|
||
for (i = 0; i < kv->pieces_count; i ++) {
|
||
if (kv->pieces[i].type == PCRE_PIECE_STRING) {
|
||
fprintf(stderr, "#%d PCRE_PIECE_STRING: %s\n", i, kv->pieces[i].u.buf->ptr);
|
||
} else {
|
||
const char *type;
|
||
switch (kv->pieces[i].type) {
|
||
case PCRE_PIECE_STRING: type = "PCRE_PIECE_STRING" ; break;
|
||
case PCRE_PIECE_SUB_KEY: type = "PCRE_PIECE_SUB_KEY" ; break;
|
||
case PCRE_PIECE_SUB_KEY_ENCODE: type = "PCRE_PIECE_SUB_KEY_ENCODE" ; break;
|
||
case PCRE_PIECE_SUB_COND: type = "PCRE_PIECE_SUB_COND" ; break;
|
||
case PCRE_PIECE_SUB_COND_ENCODE: type = "PCRE_PIECE_SUB_COND_ENCODE"; break;
|
||
default: SEGFAULT();
|
||
}
|
||
fprintf(stderr, "#%d %s: %d\n", i, type, kv->pieces[i].u.num);
|
||
}
|
||
}
|
||
#endif
|
||
kvb->used++;
|
||
src/configfile-glue.c (working copy) | ||
---|---|---|
#include <string.h>
|
||
#include <ctype.h>
|
||
#include "base.h"
|
||
#include "buffer.h"
|
||
... | ... | |
return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
|
||
}
|
||
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n)
|
||
int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *result, int n, buffer_encoding_t encoding)
|
||
{
|
||
cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
|
||
if (n > cache->patterncount) {
|
||
... | ... | |
}
|
||
n <<= 1; /* n *= 2 */
|
||
buffer_append_string_len(buf,
|
||
buffer_append_string_encoded(result,
|
||
cache->comp_value->ptr + cache->matches[n],
|
||
cache->matches[n + 1] - cache->matches[n]);
|
||
cache->matches[n + 1] - cache->matches[n],
|
||
encoding);
|
||
return 1;
|
||
}
|
||
... | ... | |
#ifdef HAVE_PCRE_H
|
||
pcre *match;
|
||
pcre_extra *extra;
|
||
const char *pattern;
|
||
size_t pattern_len;
|
||
int n;
|
||
int n, num;
|
||
size_t i;
|
||
pcre_keyvalue *kv;
|
||
# define N 10
|
||
... | ... | |
match = kv->key;
|
||
extra = kv->key_extra;
|
||
pattern = kv->value->ptr;
|
||
pattern_len = kv->value->used - 1;
|
||
if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
|
||
if (n != PCRE_ERROR_NOMATCH) {
|
||
return n;
|
||
}
|
||
} else {
|
||
const char **list;
|
||
size_t start, end;
|
||
pcre_piece_t *pieces = kv->pieces;
|
||
size_t pieces_count = kv->pieces_count;
|
||
size_t k;
|
||
/* it matched */
|
||
pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
|
||
/* search for $[0-9] */
|
||
buffer_reset(result);
|
||
start = 0; end = pattern_len;
|
||
for (k = 0; k < pattern_len; k++) {
|
||
if ((pattern[k] == '$' || pattern[k] == '%') &&
|
||
isdigit((unsigned char)pattern[k + 1])) {
|
||
/* got one */
|
||
for (k = 0; k < pieces_count; k ++) {
|
||
if (pieces[k].type == PCRE_PIECE_STRING) {
|
||
buffer_append_string_buffer(result, pieces[k].u.buf);
|
||
}
|
||
else {
|
||
num = pieces[k].u.num;
|
||
switch (pieces[k].type) {
|
||
case PCRE_PIECE_SUB_KEY:
|
||
if (num <= n) {
|
||
num <<= 1; /* num *= 2 */
|
||
buffer_append_string_len(result, match_buf->ptr + ovec[num], ovec[num + 1] - ovec[num]);
|
||
}
|
||
break;
|
||
size_t num = pattern[k + 1] - '0';
|
||
case PCRE_PIECE_SUB_KEY_ENCODE:
|
||
if (num <= n) {
|
||
num <<= 1; /* num *= 2 */
|
||
buffer_append_string_encoded(result, match_buf->ptr + ovec[num], ovec[num + 1] - ovec[num], ENCODING_REL_URI_PART);
|
||
}
|
||
break;
|
||
end = k;
|
||
case PCRE_PIECE_SUB_COND:
|
||
config_append_cond_match_buffer(con, context, result, num, ENCODING_UNSET);
|
||
break;
|
||
buffer_append_string_len(result, pattern + start, end - start);
|
||
if (pattern[k] == '$') {
|
||
/* n is always > 0 */
|
||
if (num < (size_t)n) {
|
||
buffer_append_string(result, list[num]);
|
||
}
|
||
} else {
|
||
config_append_cond_match_buffer(con, context, result, num);
|
||
case PCRE_PIECE_SUB_COND_ENCODE:
|
||
config_append_cond_match_buffer(con, context, result, num, ENCODING_REL_URI_PART);
|
||
break;
|
||
case PCRE_PIECE_STRING:
|
||
SEGFAULT();
|
||
}
|
||
k++;
|
||
start = k + 1;
|
||
}
|
||
}
|
||
buffer_append_string_len(result, pattern + start, pattern_len - start);
|
||
pcre_free(list);
|
||
return i;
|
||
}
|
||
}
|
- « Previous
- 1
- 2
- Next »