Mercurial > hg > nginx-vendor-0-5
diff src/http/modules/ngx_http_referer_module.c @ 326:f70f2f565fe0 NGINX_0_5_33
nginx 0.5.33
*) Change: now by default the "echo" SSI command uses entity encoding.
*) Feature: the "encoding" parameter in the "echo" SSI command.
*) Change: mail proxy was split on three modules: pop3, imap and smtp.
*) Feature: the --without-mail_pop3_module, --without-mail_imap_module,
and --without-mail_smtp_module configuration parameters.
*) Feature: the "smtp_greeting_delay" and "smtp_client_buffer"
directives of the ngx_mail_smtp_module.
*) Feature: the "server_name" and "valid_referers" directives support
regular expressions.
*) Feature: the "server_name", "map", and "valid_referers" directives
support the "www.example.*" wildcards.
*) Bugfix: sub_filter did not work with empty substitution.
*) Bugfix: in sub_filter parsing.
*) Bugfix: a worker process may got caught in an endless loop, if the
memcached was used.
*) Bugfix: nginx supported low case only "close" and "keep-alive"
values in the "Connection" request header line; bug appeared in
0.5.32.
*) Bugfix: nginx could not start on Solaris if the shared PCRE library
located in non-standard place was used.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Wed, 07 Nov 2007 00:00:00 +0300 |
parents | 95d92ec39071 |
children | 26ff8d6b618d |
line wrap: on
line diff
--- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -11,9 +11,26 @@ #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) +#if (NGX_PCRE) + typedef struct { - ngx_hash_t hash; - ngx_hash_wildcard_t *dns_wildcards; + 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; @@ -29,6 +46,8 @@ static char *ngx_http_valid_referers(ngx 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); @@ -81,16 +100,28 @@ 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.buckets == NULL && rlcf->dns_wildcards == NULL) { + if (rlcf->hash.hash.buckets == NULL + && rlcf->hash.wc_head == NULL + && rlcf->hash.wc_tail == NULL +#if (NGX_PCRE) + && rlcf->regex == NULL +#endif + ) + { goto valid; } @@ -133,21 +164,43 @@ ngx_http_referer_variable(ngx_http_reque } } - len = p - ref; + 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; - if (rlcf->hash.buckets) { - uri = ngx_hash_find(&rlcf->hash, key, buf, len); - if (uri) { - goto uri; + 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, ®ex[i].name); + return NGX_ERROR; + } + + /* match */ + + goto valid; } } - if (rlcf->dns_wildcards) { - uri = ngx_hash_find_wildcard(rlcf->dns_wildcards, buf, len); - if (uri) { - goto uri; - } - } +#endif invalid: @@ -208,7 +261,6 @@ ngx_http_referer_merge_conf(ngx_conf_t * if (conf->keys == NULL) { conf->hash = prev->hash; - conf->dns_wildcards = prev->dns_wildcards; ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); @@ -217,7 +269,9 @@ ngx_http_referer_merge_conf(ngx_conf_t * } if ((conf->no_referer == 1 || conf->blocked_referer == 1) - && conf->keys->keys.nelts == 0 && conf->keys->dns_wildcards.nelts == 0) + && conf->keys->keys.nelts == 0 + && conf->keys->dns_wc_head.nelts == 0 + && conf->keys->dns_wc_tail.nelts == 0) { ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "the \"none\" or \"blocked\" referers are specified " @@ -233,7 +287,7 @@ ngx_http_referer_merge_conf(ngx_conf_t * hash.pool = cf->pool; if (conf->keys->keys.nelts) { - hash.hash = &conf->hash; + hash.hash = &conf->hash.hash; hash.temp_pool = NULL; if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts) @@ -243,24 +297,44 @@ ngx_http_referer_merge_conf(ngx_conf_t * } } - if (conf->keys->dns_wildcards.nelts) { + if (conf->keys->dns_wc_head.nelts) { - ngx_qsort(conf->keys->dns_wildcards.elts, - (size_t) conf->keys->dns_wildcards.nelts, + ngx_qsort(conf->keys->dns_wc_head.elts, + (size_t) conf->keys->dns_wc_head.nelts, sizeof(ngx_hash_key_t), ngx_http_cmp_referer_wildcards); hash.hash = NULL; hash.temp_pool = cf->temp_pool; - if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wildcards.elts, - conf->keys->dns_wildcards.nelts) + if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts, + conf->keys->dns_wc_head.nelts) != NGX_OK) { return NGX_CONF_ERROR; } - conf->dns_wildcards = (ngx_hash_wildcard_t *) hash.hash; + conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash; + } + + if (conf->keys->dns_wc_tail.nelts) { + + ngx_qsort(conf->keys->dns_wc_tail.elts, + (size_t) conf->keys->dns_wc_tail.nelts, + sizeof(ngx_hash_key_t), + ngx_http_cmp_referer_wildcards); + + hash.hash = NULL; + hash.temp_pool = cf->temp_pool; + + if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts, + conf->keys->dns_wc_tail.nelts) + != NGX_OK) + { + return NGX_CONF_ERROR; + } + + conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash; } if (conf->no_referer == NGX_CONF_UNSET) { @@ -342,6 +416,21 @@ ngx_http_valid_referers(ngx_conf_t *cf, 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) { @@ -352,6 +441,15 @@ ngx_http_valid_referers(ngx_conf_t *cf, 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) { @@ -373,23 +471,8 @@ static char * ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri) { - u_char ch; - ngx_int_t rc; - ngx_str_t *u; - ngx_uint_t flags; - - ch = value->data[0]; - - if ((ch == '*' && (value->len < 3 || value->data[1] != '.')) - || (ch == '.' && value->len < 2)) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "invalid DNS wildcard \"%V\"", value); - - return NGX_CONF_ERROR; - } - - flags = (ch == '*' || ch == '.') ? NGX_HASH_WILDCARD_KEY : 0; + ngx_int_t rc; + ngx_str_t *u; if (uri->len == 0) { u = NGX_HTTP_REFERER_NO_URI_PART; @@ -403,12 +486,17 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx *u = *uri; } - rc = ngx_hash_add_key(keys, value, u, flags); + rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY); if (rc == NGX_OK) { return NGX_CONF_OK; } + if (rc == NGX_DECLINED) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid hostname or wildcard \"%V\"", value); + } + if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting parameter \"%V\"", value); @@ -418,6 +506,64 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx } +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) {