Mercurial > hg > nginx
comparison src/http/modules/ngx_http_referer_module.c @ 1388:92bc89c5ff0f
regex in valid_referers
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sun, 12 Aug 2007 20:06:43 +0000 |
parents | 8ef04207c84f |
children | 4c43e25d11ea |
comparison
equal
deleted
inserted
replaced
1387:cb8b30ef3e7e | 1388:92bc89c5ff0f |
---|---|
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 | 11 |
12 #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) | 12 #define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) |
13 | 13 |
14 #if (NGX_PCRE) | |
15 | |
16 typedef struct { | |
17 ngx_regex_t *regex; | |
18 ngx_str_t name; | |
19 } ngx_http_referer_regex_t; | |
20 | |
21 #else | |
22 | |
23 #define ngx_regex_t void | |
24 | |
25 #endif | |
26 | |
27 | |
14 typedef struct { | 28 typedef struct { |
15 ngx_hash_combined_t hash; | 29 ngx_hash_combined_t hash; |
30 | |
31 #if (NGX_PCRE) | |
32 ngx_array_t *regex; | |
33 #endif | |
16 | 34 |
17 ngx_flag_t no_referer; | 35 ngx_flag_t no_referer; |
18 ngx_flag_t blocked_referer; | 36 ngx_flag_t blocked_referer; |
19 | 37 |
20 ngx_hash_keys_arrays_t *keys; | 38 ngx_hash_keys_arrays_t *keys; |
26 void *child); | 44 void *child); |
27 static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, | 45 static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, |
28 void *conf); | 46 void *conf); |
29 static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, | 47 static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, |
30 ngx_str_t *value, ngx_str_t *uri); | 48 ngx_str_t *value, ngx_str_t *uri); |
49 static char *ngx_http_add_regex_referer(ngx_conf_t *cf, | |
50 ngx_http_referer_conf_t *rlcf, ngx_str_t *name, ngx_regex_t *regex); | |
31 static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, | 51 static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, |
32 const void *two); | 52 const void *two); |
33 | 53 |
34 | 54 |
35 static ngx_command_t ngx_http_referer_commands[] = { | 55 static ngx_command_t ngx_http_referer_commands[] = { |
78 | 98 |
79 static ngx_int_t | 99 static ngx_int_t |
80 ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | 100 ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, |
81 uintptr_t data) | 101 uintptr_t data) |
82 { | 102 { |
83 u_char *p, *ref, *last; | 103 u_char *p, *ref, *last; |
84 size_t len; | 104 size_t len; |
85 ngx_str_t *uri; | 105 ngx_str_t *uri; |
86 ngx_uint_t i, key; | 106 ngx_uint_t i, key; |
87 ngx_http_referer_conf_t *rlcf; | 107 ngx_http_referer_conf_t *rlcf; |
88 u_char buf[256]; | 108 u_char buf[256]; |
109 #if (NGX_PCRE) | |
110 ngx_int_t n; | |
111 ngx_str_t referer; | |
112 ngx_http_referer_regex_t *regex; | |
113 #endif | |
89 | 114 |
90 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); | 115 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); |
91 | 116 |
92 if (rlcf->hash.hash.buckets == NULL | 117 if (rlcf->hash.hash.buckets == NULL |
93 && rlcf->hash.wc_head == NULL | 118 && rlcf->hash.wc_head == NULL |
94 && rlcf->hash.wc_tail == NULL) | 119 && rlcf->hash.wc_tail == NULL |
120 #if (NGX_PCRE) | |
121 && rlcf->regex == NULL | |
122 #endif | |
123 ) | |
95 { | 124 { |
96 goto valid; | 125 goto valid; |
97 } | 126 } |
98 | 127 |
99 if (r->headers_in.referer == NULL) { | 128 if (r->headers_in.referer == NULL) { |
133 if (i == 256) { | 162 if (i == 256) { |
134 goto invalid; | 163 goto invalid; |
135 } | 164 } |
136 } | 165 } |
137 | 166 |
138 len = p - ref; | 167 uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref); |
139 | |
140 uri = ngx_hash_find_combined(&rlcf->hash, key, buf, len); | |
141 | 168 |
142 if (uri) { | 169 if (uri) { |
143 goto uri; | 170 goto uri; |
144 } | 171 } |
172 | |
173 #if (NGX_PCRE) | |
174 | |
175 if (rlcf->regex) { | |
176 | |
177 referer.len = len - 7; | |
178 referer.data = ref; | |
179 | |
180 regex = rlcf->regex->elts; | |
181 | |
182 for (i = 0; i < rlcf->regex->nelts; i++) { | |
183 n = ngx_regex_exec(regex[i].regex, &referer, NULL, 0); | |
184 | |
185 if (n == NGX_REGEX_NO_MATCHED) { | |
186 continue; | |
187 } | |
188 | |
189 if (n < 0) { | |
190 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
191 ngx_regex_exec_n | |
192 " failed: %d on \"%V\" using \"%V\"", | |
193 n, &referer, ®ex[i].name); | |
194 return NGX_ERROR; | |
195 } | |
196 | |
197 /* match */ | |
198 | |
199 goto valid; | |
200 } | |
201 } | |
202 | |
203 #endif | |
145 | 204 |
146 invalid: | 205 invalid: |
147 | 206 |
148 *v = ngx_http_variable_true_value; | 207 *v = ngx_http_variable_true_value; |
149 | 208 |
355 | 414 |
356 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); | 415 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); |
357 | 416 |
358 sn = cscf->server_names.elts; | 417 sn = cscf->server_names.elts; |
359 for (n = 0; n < cscf->server_names.nelts; n++) { | 418 for (n = 0; n < cscf->server_names.nelts; n++) { |
419 | |
420 #if (NGX_PCRE) | |
421 if (sn[n].regex) { | |
422 | |
423 if (ngx_http_add_regex_referer(cf, rlcf, &sn[n].name, | |
424 sn[n].regex) | |
425 != NGX_OK) | |
426 { | |
427 return NGX_CONF_ERROR; | |
428 } | |
429 | |
430 continue; | |
431 } | |
432 #endif | |
433 | |
360 if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) | 434 if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) |
361 != NGX_OK) | 435 != NGX_OK) |
362 { | 436 { |
363 return NGX_CONF_ERROR; | 437 return NGX_CONF_ERROR; |
364 } | 438 } |
365 } | 439 } |
366 | 440 |
367 continue; | 441 continue; |
368 } | 442 } |
369 | 443 |
444 if (value[i].data[0] == '~') { | |
445 if (ngx_http_add_regex_referer(cf, rlcf, &value[i], NULL) != NGX_OK) | |
446 { | |
447 return NGX_CONF_ERROR; | |
448 } | |
449 | |
450 continue; | |
451 } | |
452 | |
370 p = (u_char *) ngx_strchr(value[i].data, '/'); | 453 p = (u_char *) ngx_strchr(value[i].data, '/'); |
371 | 454 |
372 if (p) { | 455 if (p) { |
373 uri.len = (value[i].data + value[i].len) - p; | 456 uri.len = (value[i].data + value[i].len) - p; |
374 uri.data = p; | 457 uri.data = p; |
421 | 504 |
422 return NGX_CONF_ERROR; | 505 return NGX_CONF_ERROR; |
423 } | 506 } |
424 | 507 |
425 | 508 |
509 static char * | |
510 ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf, | |
511 ngx_str_t *name, ngx_regex_t *regex) | |
512 { | |
513 #if (NGX_PCRE) | |
514 ngx_str_t err; | |
515 ngx_http_referer_regex_t *rr; | |
516 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
517 | |
518 if (rlcf->regex == NULL) { | |
519 rlcf->regex = ngx_array_create(cf->pool, 2, | |
520 sizeof(ngx_http_referer_regex_t)); | |
521 if (rlcf->regex == NULL) { | |
522 return NGX_CONF_ERROR; | |
523 } | |
524 } | |
525 | |
526 rr = ngx_array_push(rlcf->regex); | |
527 if (rr == NULL) { | |
528 return NGX_CONF_ERROR; | |
529 } | |
530 | |
531 if (regex) { | |
532 rr->regex = regex; | |
533 rr->name = *name; | |
534 | |
535 return NGX_CONF_OK; | |
536 } | |
537 | |
538 err.len = NGX_MAX_CONF_ERRSTR; | |
539 err.data = errstr; | |
540 | |
541 name->len--; | |
542 name->data++; | |
543 | |
544 rr->regex = ngx_regex_compile(name, NGX_REGEX_CASELESS, cf->pool, &err); | |
545 | |
546 if (rr->regex == NULL) { | |
547 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | |
548 return NGX_CONF_ERROR; | |
549 } | |
550 | |
551 rr->name = *name; | |
552 | |
553 return NGX_CONF_OK; | |
554 | |
555 #else | |
556 | |
557 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
558 "the using of the regex \"%V\" requires PCRE library", | |
559 name); | |
560 | |
561 return NGX_CONF_ERROR; | |
562 | |
563 #endif | |
564 } | |
565 | |
566 | |
426 static int ngx_libc_cdecl | 567 static int ngx_libc_cdecl |
427 ngx_http_cmp_referer_wildcards(const void *one, const void *two) | 568 ngx_http_cmp_referer_wildcards(const void *one, const void *two) |
428 { | 569 { |
429 ngx_hash_key_t *first, *second; | 570 ngx_hash_key_t *first, *second; |
430 | 571 |