Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2007-11-07 16:46:29 +0300
committerIgor Sysoev <igor@sysoev.ru>2007-11-07 16:46:29 +0300
commitce87ce477e9c349fbff1d30e3a45a8f0cc928ef6 (patch)
tree5e275a216ad3398bd155782f3fa73673cd47d3e4 /src/http
parentc2378f80289ead8157c63ac6216836bab6e4294b (diff)
r1386, r1388, r1389, r1580, r1581 merge:
regex in server_name and valid_referers
Diffstat (limited to 'src/http')
-rw-r--r--src/http/modules/ngx_http_referer_module.c161
-rw-r--r--src/http/ngx_http.c57
-rw-r--r--src/http/ngx_http_core_module.c51
-rw-r--r--src/http/ngx_http_core_module.h16
-rw-r--r--src/http/ngx_http_request.c46
-rw-r--r--src/http/ngx_http_request.h10
6 files changed, 315 insertions, 26 deletions
diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c
index 8559521e2..bf87a1bfc 100644
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -11,9 +11,27 @@
#define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4)
+#if (NGX_PCRE)
+
+typedef struct {
+ ngx_regex_t *regex;
+ ngx_str_t name;
+} ngx_http_referer_regex_t;
+
+#else
+
+#define ngx_regex_t void
+
+#endif
+
+
typedef struct {
ngx_hash_combined_t hash;
+#if (NGX_PCRE)
+ ngx_array_t *regex;
+#endif
+
ngx_flag_t no_referer;
ngx_flag_t blocked_referer;
@@ -28,6 +46,8 @@ static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
ngx_str_t *value, ngx_str_t *uri);
+static char *ngx_http_add_regex_referer(ngx_conf_t *cf,
+ ngx_http_referer_conf_t *rlcf, ngx_str_t *name, ngx_regex_t *regex);
static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one,
const void *two);
@@ -80,18 +100,27 @@ static ngx_int_t
ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
uintptr_t data)
{
- u_char *p, *ref, *last;
- size_t len;
- ngx_str_t *uri;
- ngx_uint_t i, key;
- ngx_http_referer_conf_t *rlcf;
- u_char buf[256];
+ u_char *p, *ref, *last;
+ size_t len;
+ ngx_str_t *uri;
+ ngx_uint_t i, key;
+ ngx_http_referer_conf_t *rlcf;
+ u_char buf[256];
+#if (NGX_PCRE)
+ ngx_int_t n;
+ ngx_str_t referer;
+ ngx_http_referer_regex_t *regex;
+#endif
rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
if (rlcf->hash.hash.buckets == NULL
&& rlcf->hash.wc_head == NULL
- && rlcf->hash.wc_tail == NULL)
+ && rlcf->hash.wc_tail == NULL
+#if (NGX_PCRE)
+ && rlcf->regex == NULL
+#endif
+ )
{
goto valid;
}
@@ -135,14 +164,44 @@ ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
}
}
- len = p - ref;
-
- uri = ngx_hash_find_combined(&rlcf->hash, key, buf, len);
+ uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref);
if (uri) {
goto uri;
}
+#if (NGX_PCRE)
+
+ if (rlcf->regex) {
+
+ referer.len = len - 7;
+ referer.data = ref;
+
+ regex = rlcf->regex->elts;
+
+ for (i = 0; i < rlcf->regex->nelts; i++) {
+ n = ngx_regex_exec(regex[i].regex, &referer, NULL, 0);
+
+ if (n == NGX_REGEX_NO_MATCHED) {
+ continue;
+ }
+
+ if (n < 0) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ ngx_regex_exec_n
+ " failed: %d on \"%V\" using \"%V\"",
+ n, &referer, &regex[i].name);
+ return NGX_ERROR;
+ }
+
+ /* match */
+
+ goto valid;
+ }
+ }
+
+#endif
+
invalid:
*v = ngx_http_variable_true_value;
@@ -357,6 +416,21 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
sn = cscf->server_names.elts;
for (n = 0; n < cscf->server_names.nelts; n++) {
+
+#if (NGX_PCRE)
+ if (sn[n].regex) {
+
+ if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name,
+ sn[n].regex)
+ != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+#endif
+
if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri)
!= NGX_OK)
{
@@ -367,6 +441,15 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
continue;
}
+ if (value[i].data[0] == '~') {
+ if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK)
+ {
+ return NGX_CONF_ERROR;
+ }
+
+ continue;
+ }
+
p = (u_char *) ngx_strchr(value[i].data, '/');
if (p) {
@@ -423,6 +506,64 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
}
+static char *
+ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
+ ngx_str_t *name, ngx_regex_t *regex)
+{
+#if (NGX_PCRE)
+ ngx_str_t err;
+ ngx_http_referer_regex_t *rr;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+
+ if (rlcf->regex == NULL) {
+ rlcf->regex = ngx_array_create(cf->pool, 2,
+ sizeof(ngx_http_referer_regex_t));
+ if (rlcf->regex == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ rr = ngx_array_push(rlcf->regex);
+ if (rr == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ if (regex) {
+ rr->regex = regex;
+ rr->name = *name;
+
+ return NGX_CONF_OK;
+ }
+
+ err.len = NGX_MAX_CONF_ERRSTR;
+ err.data = errstr;
+
+ name->len--;
+ name->data++;
+
+ rr->regex = ngx_regex_compile(name, NGX_REGEX_CASELESS, cf->pool, &err);
+
+ if (rr->regex == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+ return NGX_CONF_ERROR;
+ }
+
+ rr->name = *name;
+
+ return NGX_CONF_OK;
+
+#else
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the using of the regex \"%V\" requires PCRE library",
+ name);
+
+ return NGX_CONF_ERROR;
+
+#endif
+}
+
+
static int ngx_libc_cdecl
ngx_http_cmp_referer_wildcards(const void *one, const void *two)
{
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index 7a2fb85b3..59b43d054 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -98,6 +98,9 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_http_core_loc_conf_t *clcf;
ngx_http_phase_handler_pt checker;
ngx_http_core_main_conf_t *cmcf;
+#if (NGX_PCRE)
+ ngx_uint_t regex;
+#endif
#if (NGX_WIN32)
ngx_iocp_conf_t *iocpcf;
#endif
@@ -655,10 +658,21 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+#if (NGX_PCRE)
+ regex = 0;
+#endif
+
name = in_addr[a].names.elts;
for (s = 0; s < in_addr[a].names.nelts; s++) {
+#if (NGX_PCRE)
+ if (name[s].regex) {
+ regex++;
+ continue;
+ }
+#endif
+
rc = ngx_hash_add_key(&ha, &name[s].name, name[s].core_srv_conf,
NGX_HASH_WILDCARD_KEY);
@@ -740,6 +754,27 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
ngx_destroy_pool(ha.temp_pool);
+
+#if (NGX_PCRE)
+
+ if (regex == 0) {
+ continue;
+ }
+
+ in_addr[a].nregex = regex;
+ in_addr[a].regex = ngx_palloc(cf->pool,
+ regex * sizeof(ngx_http_server_name_t));
+
+ if (in_addr[a].regex == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0, s = 0; s < in_addr[a].names.nelts; s++) {
+ if (name[s].regex) {
+ in_addr[a].regex[i++] = name[s];
+ }
+ }
+#endif
}
in_addr = in_port[p].addrs.elts;
@@ -871,9 +906,13 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
hip->addrs[i].virtual_names = vn;
- vn->hash = in_addr[i].hash;
- vn->wc_head = in_addr[i].wc_head;
- vn->wc_tail = in_addr[i].wc_tail;
+ vn->names.hash = in_addr[i].hash;
+ vn->names.wc_head = in_addr[i].wc_head;
+ vn->names.wc_tail = in_addr[i].wc_tail;
+#if (NGX_PCRE)
+ vn->nregex = in_addr[i].nregex;
+ vn->regex = in_addr[i].regex;
+#endif
}
if (done) {
@@ -932,7 +971,8 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port,
if (in_port->addrs.elts == NULL) {
if (ngx_array_init(&in_port->addrs, cf->temp_pool, 4,
- sizeof(ngx_http_conf_in_addr_t)) != NGX_OK)
+ sizeof(ngx_http_conf_in_addr_t))
+ != NGX_OK)
{
return NGX_ERROR;
}
@@ -949,6 +989,10 @@ ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port,
in_addr->wc_head = NULL;
in_addr->wc_tail = NULL;
in_addr->names.elts = NULL;
+#if (NGX_PCRE)
+ in_addr->nregex = 0;
+ in_addr->regex = NULL;
+#endif
in_addr->core_srv_conf = cscf;
in_addr->default_server = lscf->conf.default_server;
in_addr->bind = lscf->conf.bind;
@@ -981,13 +1025,15 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr,
if (in_addr->names.elts == NULL) {
if (ngx_array_init(&in_addr->names, cf->temp_pool, 4,
- sizeof(ngx_http_server_name_t)) != NGX_OK)
+ sizeof(ngx_http_server_name_t))
+ != NGX_OK)
{
return NGX_ERROR;
}
}
server_names = cscf->server_names.elts;
+
for (i = 0; i < cscf->server_names.nelts; i++) {
for (n = 0; n < server_names[i].name.len; n++) {
@@ -998,7 +1044,6 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_http_conf_in_addr_t *in_addr,
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0,
"name: %V", &server_names[i].name);
-
name = ngx_array_push(&in_addr->names);
if (name == NULL) {
return NGX_ERROR;
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 1ef1a6c16..78ff87de0 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -2272,9 +2272,12 @@ ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
+#if (NGX_PCRE)
+ sn->regex = NULL;
+#endif
+ sn->core_srv_conf = conf;
sn->name.len = conf->server_name.len;
sn->name.data = conf->server_name.data;
- sn->core_srv_conf = conf;
}
ngx_conf_merge_size_value(conf->connection_pool_size,
@@ -2719,6 +2722,10 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ngx_str_t *value, name;
ngx_uint_t i;
ngx_http_server_name_t *sn;
+#if (NGX_PCRE)
+ ngx_str_t err;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+#endif
value = cf->args->elts;
@@ -2732,6 +2739,13 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+ if (value[1].data[0] == '~') {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "first server name \"%V\" "
+ "must not be regular expression", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
name = value[1];
if (ch == '.') {
@@ -2775,9 +2789,42 @@ ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
+#if (NGX_PCRE)
+ sn->regex = NULL;
+#endif
+ sn->core_srv_conf = cscf;
sn->name.len = value[i].len;
sn->name.data = value[i].data;
- sn->core_srv_conf = cscf;
+
+ if (value[i].data[0] != '~') {
+ continue;
+ }
+
+#if (NGX_PCRE)
+ err.len = NGX_MAX_CONF_ERRSTR;
+ err.data = errstr;
+
+ value[i].len--;
+ value[i].data++;
+
+ sn->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
+ &err);
+
+ if (sn->regex == NULL) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+ return NGX_CONF_ERROR;
+ }
+
+ sn->name.len = value[i].len;
+ sn->name.data = value[i].data;
+
+#else
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "the using of the regex \"%V\" "
+ "requires PCRE library", &value[i]);
+
+ return NGX_CONF_ERROR;
+#endif
}
return NGX_CONF_OK;
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 52ac5ddf3..79cd1f653 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -151,8 +151,10 @@ typedef struct {
typedef struct {
in_addr_t addr;
+
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *core_srv_conf;
+
ngx_http_virtual_names_t *virtual_names;
} ngx_http_in_addr_t;
@@ -180,6 +182,11 @@ typedef struct {
ngx_array_t names; /* array of ngx_http_server_name_t */
+#if (NGX_PCRE)
+ ngx_uint_t nregex;
+ ngx_http_server_name_t *regex;
+#endif
+
/* the default server configuration for this address:port */
ngx_http_core_srv_conf_t *core_srv_conf;
@@ -190,10 +197,13 @@ typedef struct {
} ngx_http_conf_in_addr_t;
-typedef struct {
- ngx_str_t name;
+struct ngx_http_server_name_s {
+#if (NGX_PCRE)
+ ngx_regex_t *regex;
+#endif
ngx_http_core_srv_conf_t *core_srv_conf; /* virtual name server conf */
-} ngx_http_server_name_t;
+ ngx_str_t name;
+};
typedef struct {
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index bc7a92fcc..70434dcb3 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1457,18 +1457,56 @@ static void
ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len,
ngx_uint_t hash)
{
- ngx_http_virtual_names_t *vn;
ngx_http_core_loc_conf_t *clcf;
ngx_http_core_srv_conf_t *cscf;
+#if (NGX_PCRE)
+ ngx_int_t n;
+ ngx_uint_t i;
+ ngx_str_t name;
+ ngx_http_server_name_t *sn;
+#endif
- vn = r->virtual_names;
-
- cscf = ngx_hash_find_combined(vn, hash, host, len);
+ cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len);
if (cscf) {
goto found;
}
+#if (NGX_PCRE)
+
+ if (r->virtual_names->nregex) {
+
+ name.len = len;
+ name.data = host;
+
+ sn = r->virtual_names->regex;
+
+ for (i = 0; i < r->virtual_names->nregex; i++) {
+
+ n = ngx_regex_exec(sn[i].regex, &name, NULL, 0);
+
+ if (n == NGX_REGEX_NO_MATCHED) {
+ continue;
+ }
+
+ if (n < 0) {
+ ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+ ngx_regex_exec_n
+ " failed: %d on \"%V\" using \"%V\"",
+ n, &name, &sn[i].name);
+ return;
+ }
+
+ /* match */
+
+ cscf = sn[i].core_srv_conf;
+
+ goto found;
+ }
+ }
+
+#endif
+
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
if (cscf->wildcard) {
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index b440f14fd..0b269a893 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -275,7 +275,15 @@ typedef struct {
} ngx_http_connection_t;
-typedef ngx_hash_combined_t ngx_http_virtual_names_t;
+typedef struct ngx_http_server_name_s ngx_http_server_name_t;
+
+
+typedef struct {
+ ngx_hash_combined_t names;
+
+ ngx_uint_t nregex;
+ ngx_http_server_name_t *regex;
+} ngx_http_virtual_names_t;
typedef void (*ngx_http_cleanup_pt)(void *data);