1*3da8d17dSfengbojiang(姜凤波) 
2*3da8d17dSfengbojiang(姜凤波) /*
3*3da8d17dSfengbojiang(姜凤波)  * Copyright (C) Igor Sysoev
4*3da8d17dSfengbojiang(姜凤波)  * Copyright (C) Nginx, Inc.
5*3da8d17dSfengbojiang(姜凤波)  */
6*3da8d17dSfengbojiang(姜凤波) 
7*3da8d17dSfengbojiang(姜凤波) 
8*3da8d17dSfengbojiang(姜凤波) #include <ngx_config.h>
9*3da8d17dSfengbojiang(姜凤波) #include <ngx_core.h>
10*3da8d17dSfengbojiang(姜凤波) #include <ngx_http.h>
11*3da8d17dSfengbojiang(姜凤波) 
12*3da8d17dSfengbojiang(姜凤波) 
13*3da8d17dSfengbojiang(姜凤波) #define NGX_HTTP_REFERER_NO_URI_PART  ((void *) 4)
14*3da8d17dSfengbojiang(姜凤波) 
15*3da8d17dSfengbojiang(姜凤波) 
16*3da8d17dSfengbojiang(姜凤波) typedef struct {
17*3da8d17dSfengbojiang(姜凤波)     ngx_hash_combined_t      hash;
18*3da8d17dSfengbojiang(姜凤波) 
19*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
20*3da8d17dSfengbojiang(姜凤波)     ngx_array_t             *regex;
21*3da8d17dSfengbojiang(姜凤波)     ngx_array_t             *server_name_regex;
22*3da8d17dSfengbojiang(姜凤波) #endif
23*3da8d17dSfengbojiang(姜凤波) 
24*3da8d17dSfengbojiang(姜凤波)     ngx_flag_t               no_referer;
25*3da8d17dSfengbojiang(姜凤波)     ngx_flag_t               blocked_referer;
26*3da8d17dSfengbojiang(姜凤波)     ngx_flag_t               server_names;
27*3da8d17dSfengbojiang(姜凤波) 
28*3da8d17dSfengbojiang(姜凤波)     ngx_hash_keys_arrays_t  *keys;
29*3da8d17dSfengbojiang(姜凤波) 
30*3da8d17dSfengbojiang(姜凤波)     ngx_uint_t               referer_hash_max_size;
31*3da8d17dSfengbojiang(姜凤波)     ngx_uint_t               referer_hash_bucket_size;
32*3da8d17dSfengbojiang(姜凤波) } ngx_http_referer_conf_t;
33*3da8d17dSfengbojiang(姜凤波) 
34*3da8d17dSfengbojiang(姜凤波) 
35*3da8d17dSfengbojiang(姜凤波) static ngx_int_t ngx_http_referer_add_variables(ngx_conf_t *cf);
36*3da8d17dSfengbojiang(姜凤波) static void * ngx_http_referer_create_conf(ngx_conf_t *cf);
37*3da8d17dSfengbojiang(姜凤波) static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent,
38*3da8d17dSfengbojiang(姜凤波)     void *child);
39*3da8d17dSfengbojiang(姜凤波) static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd,
40*3da8d17dSfengbojiang(姜凤波)     void *conf);
41*3da8d17dSfengbojiang(姜凤波) static ngx_int_t ngx_http_add_referer(ngx_conf_t *cf,
42*3da8d17dSfengbojiang(姜凤波)     ngx_hash_keys_arrays_t *keys, ngx_str_t *value, ngx_str_t *uri);
43*3da8d17dSfengbojiang(姜凤波) static ngx_int_t ngx_http_add_regex_referer(ngx_conf_t *cf,
44*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t *rlcf, ngx_str_t *name);
45*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
46*3da8d17dSfengbojiang(姜凤波) static ngx_int_t ngx_http_add_regex_server_name(ngx_conf_t *cf,
47*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t *rlcf, ngx_http_regex_t *regex);
48*3da8d17dSfengbojiang(姜凤波) #endif
49*3da8d17dSfengbojiang(姜凤波) static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one,
50*3da8d17dSfengbojiang(姜凤波)     const void *two);
51*3da8d17dSfengbojiang(姜凤波) 
52*3da8d17dSfengbojiang(姜凤波) 
53*3da8d17dSfengbojiang(姜凤波) static ngx_command_t  ngx_http_referer_commands[] = {
54*3da8d17dSfengbojiang(姜凤波) 
55*3da8d17dSfengbojiang(姜凤波)     { ngx_string("valid_referers"),
56*3da8d17dSfengbojiang(姜凤波)       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
57*3da8d17dSfengbojiang(姜凤波)       ngx_http_valid_referers,
58*3da8d17dSfengbojiang(姜凤波)       NGX_HTTP_LOC_CONF_OFFSET,
59*3da8d17dSfengbojiang(姜凤波)       0,
60*3da8d17dSfengbojiang(姜凤波)       NULL },
61*3da8d17dSfengbojiang(姜凤波) 
62*3da8d17dSfengbojiang(姜凤波)     { ngx_string("referer_hash_max_size"),
63*3da8d17dSfengbojiang(姜凤波)       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
64*3da8d17dSfengbojiang(姜凤波)       ngx_conf_set_num_slot,
65*3da8d17dSfengbojiang(姜凤波)       NGX_HTTP_LOC_CONF_OFFSET,
66*3da8d17dSfengbojiang(姜凤波)       offsetof(ngx_http_referer_conf_t, referer_hash_max_size),
67*3da8d17dSfengbojiang(姜凤波)       NULL },
68*3da8d17dSfengbojiang(姜凤波) 
69*3da8d17dSfengbojiang(姜凤波)     { ngx_string("referer_hash_bucket_size"),
70*3da8d17dSfengbojiang(姜凤波)       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
71*3da8d17dSfengbojiang(姜凤波)       ngx_conf_set_num_slot,
72*3da8d17dSfengbojiang(姜凤波)       NGX_HTTP_LOC_CONF_OFFSET,
73*3da8d17dSfengbojiang(姜凤波)       offsetof(ngx_http_referer_conf_t, referer_hash_bucket_size),
74*3da8d17dSfengbojiang(姜凤波)       NULL },
75*3da8d17dSfengbojiang(姜凤波) 
76*3da8d17dSfengbojiang(姜凤波)       ngx_null_command
77*3da8d17dSfengbojiang(姜凤波) };
78*3da8d17dSfengbojiang(姜凤波) 
79*3da8d17dSfengbojiang(姜凤波) 
80*3da8d17dSfengbojiang(姜凤波) static ngx_http_module_t  ngx_http_referer_module_ctx = {
81*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_add_variables,        /* preconfiguration */
82*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* postconfiguration */
83*3da8d17dSfengbojiang(姜凤波) 
84*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* create main configuration */
85*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* init main configuration */
86*3da8d17dSfengbojiang(姜凤波) 
87*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* create server configuration */
88*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* merge server configuration */
89*3da8d17dSfengbojiang(姜凤波) 
90*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_create_conf,          /* create location configuration */
91*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_merge_conf            /* merge location configuration */
92*3da8d17dSfengbojiang(姜凤波) };
93*3da8d17dSfengbojiang(姜凤波) 
94*3da8d17dSfengbojiang(姜凤波) 
95*3da8d17dSfengbojiang(姜凤波) ngx_module_t  ngx_http_referer_module = {
96*3da8d17dSfengbojiang(姜凤波)     NGX_MODULE_V1,
97*3da8d17dSfengbojiang(姜凤波)     &ngx_http_referer_module_ctx,          /* module context */
98*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_commands,             /* module directives */
99*3da8d17dSfengbojiang(姜凤波)     NGX_HTTP_MODULE,                       /* module type */
100*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* init master */
101*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* init module */
102*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* init process */
103*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* init thread */
104*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* exit thread */
105*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* exit process */
106*3da8d17dSfengbojiang(姜凤波)     NULL,                                  /* exit master */
107*3da8d17dSfengbojiang(姜凤波)     NGX_MODULE_V1_PADDING
108*3da8d17dSfengbojiang(姜凤波) };
109*3da8d17dSfengbojiang(姜凤波) 
110*3da8d17dSfengbojiang(姜凤波) 
111*3da8d17dSfengbojiang(姜凤波) static ngx_str_t  ngx_http_invalid_referer_name = ngx_string("invalid_referer");
112*3da8d17dSfengbojiang(姜凤波) 
113*3da8d17dSfengbojiang(姜凤波) 
114*3da8d17dSfengbojiang(姜凤波) static ngx_int_t
ngx_http_referer_variable(ngx_http_request_t * r,ngx_http_variable_value_t * v,uintptr_t data)115*3da8d17dSfengbojiang(姜凤波) ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
116*3da8d17dSfengbojiang(姜凤波)     uintptr_t data)
117*3da8d17dSfengbojiang(姜凤波) {
118*3da8d17dSfengbojiang(姜凤波)     u_char                    *p, *ref, *last;
119*3da8d17dSfengbojiang(姜凤波)     size_t                     len;
120*3da8d17dSfengbojiang(姜凤波)     ngx_str_t                 *uri;
121*3da8d17dSfengbojiang(姜凤波)     ngx_uint_t                 i, key;
122*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t   *rlcf;
123*3da8d17dSfengbojiang(姜凤波)     u_char                     buf[256];
124*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
125*3da8d17dSfengbojiang(姜凤波)     ngx_int_t                  rc;
126*3da8d17dSfengbojiang(姜凤波)     ngx_str_t                  referer;
127*3da8d17dSfengbojiang(姜凤波) #endif
128*3da8d17dSfengbojiang(姜凤波) 
129*3da8d17dSfengbojiang(姜凤波)     rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module);
130*3da8d17dSfengbojiang(姜凤波) 
131*3da8d17dSfengbojiang(姜凤波)     if (rlcf->hash.hash.buckets == NULL
132*3da8d17dSfengbojiang(姜凤波)         && rlcf->hash.wc_head == NULL
133*3da8d17dSfengbojiang(姜凤波)         && rlcf->hash.wc_tail == NULL
134*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
135*3da8d17dSfengbojiang(姜凤波)         && rlcf->regex == NULL
136*3da8d17dSfengbojiang(姜凤波)         && rlcf->server_name_regex == NULL
137*3da8d17dSfengbojiang(姜凤波) #endif
138*3da8d17dSfengbojiang(姜凤波)        )
139*3da8d17dSfengbojiang(姜凤波)     {
140*3da8d17dSfengbojiang(姜凤波)         goto valid;
141*3da8d17dSfengbojiang(姜凤波)     }
142*3da8d17dSfengbojiang(姜凤波) 
143*3da8d17dSfengbojiang(姜凤波)     if (r->headers_in.referer == NULL) {
144*3da8d17dSfengbojiang(姜凤波)         if (rlcf->no_referer) {
145*3da8d17dSfengbojiang(姜凤波)             goto valid;
146*3da8d17dSfengbojiang(姜凤波)         }
147*3da8d17dSfengbojiang(姜凤波) 
148*3da8d17dSfengbojiang(姜凤波)         goto invalid;
149*3da8d17dSfengbojiang(姜凤波)     }
150*3da8d17dSfengbojiang(姜凤波) 
151*3da8d17dSfengbojiang(姜凤波)     len = r->headers_in.referer->value.len;
152*3da8d17dSfengbojiang(姜凤波)     ref = r->headers_in.referer->value.data;
153*3da8d17dSfengbojiang(姜凤波) 
154*3da8d17dSfengbojiang(姜凤波)     if (len >= sizeof("http://i.ru") - 1) {
155*3da8d17dSfengbojiang(姜凤波)         last = ref + len;
156*3da8d17dSfengbojiang(姜凤波) 
157*3da8d17dSfengbojiang(姜凤波)         if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) {
158*3da8d17dSfengbojiang(姜凤波)             ref += 7;
159*3da8d17dSfengbojiang(姜凤波)             len -= 7;
160*3da8d17dSfengbojiang(姜凤波)             goto valid_scheme;
161*3da8d17dSfengbojiang(姜凤波) 
162*3da8d17dSfengbojiang(姜凤波)         } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) {
163*3da8d17dSfengbojiang(姜凤波)             ref += 8;
164*3da8d17dSfengbojiang(姜凤波)             len -= 8;
165*3da8d17dSfengbojiang(姜凤波)             goto valid_scheme;
166*3da8d17dSfengbojiang(姜凤波)         }
167*3da8d17dSfengbojiang(姜凤波)     }
168*3da8d17dSfengbojiang(姜凤波) 
169*3da8d17dSfengbojiang(姜凤波)     if (rlcf->blocked_referer) {
170*3da8d17dSfengbojiang(姜凤波)         goto valid;
171*3da8d17dSfengbojiang(姜凤波)     }
172*3da8d17dSfengbojiang(姜凤波) 
173*3da8d17dSfengbojiang(姜凤波)     goto invalid;
174*3da8d17dSfengbojiang(姜凤波) 
175*3da8d17dSfengbojiang(姜凤波) valid_scheme:
176*3da8d17dSfengbojiang(姜凤波) 
177*3da8d17dSfengbojiang(姜凤波)     i = 0;
178*3da8d17dSfengbojiang(姜凤波)     key = 0;
179*3da8d17dSfengbojiang(姜凤波) 
180*3da8d17dSfengbojiang(姜凤波)     for (p = ref; p < last; p++) {
181*3da8d17dSfengbojiang(姜凤波)         if (*p == '/' || *p == ':') {
182*3da8d17dSfengbojiang(姜凤波)             break;
183*3da8d17dSfengbojiang(姜凤波)         }
184*3da8d17dSfengbojiang(姜凤波) 
185*3da8d17dSfengbojiang(姜凤波)         if (i == 256) {
186*3da8d17dSfengbojiang(姜凤波)             goto invalid;
187*3da8d17dSfengbojiang(姜凤波)         }
188*3da8d17dSfengbojiang(姜凤波) 
189*3da8d17dSfengbojiang(姜凤波)         buf[i] = ngx_tolower(*p);
190*3da8d17dSfengbojiang(姜凤波)         key = ngx_hash(key, buf[i++]);
191*3da8d17dSfengbojiang(姜凤波)     }
192*3da8d17dSfengbojiang(姜凤波) 
193*3da8d17dSfengbojiang(姜凤波)     uri = ngx_hash_find_combined(&rlcf->hash, key, buf, p - ref);
194*3da8d17dSfengbojiang(姜凤波) 
195*3da8d17dSfengbojiang(姜凤波)     if (uri) {
196*3da8d17dSfengbojiang(姜凤波)         goto uri;
197*3da8d17dSfengbojiang(姜凤波)     }
198*3da8d17dSfengbojiang(姜凤波) 
199*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
200*3da8d17dSfengbojiang(姜凤波) 
201*3da8d17dSfengbojiang(姜凤波)     if (rlcf->server_name_regex) {
202*3da8d17dSfengbojiang(姜凤波)         referer.len = p - ref;
203*3da8d17dSfengbojiang(姜凤波)         referer.data = buf;
204*3da8d17dSfengbojiang(姜凤波) 
205*3da8d17dSfengbojiang(姜凤波)         rc = ngx_regex_exec_array(rlcf->server_name_regex, &referer,
206*3da8d17dSfengbojiang(姜凤波)                                   r->connection->log);
207*3da8d17dSfengbojiang(姜凤波) 
208*3da8d17dSfengbojiang(姜凤波)         if (rc == NGX_OK) {
209*3da8d17dSfengbojiang(姜凤波)             goto valid;
210*3da8d17dSfengbojiang(姜凤波)         }
211*3da8d17dSfengbojiang(姜凤波) 
212*3da8d17dSfengbojiang(姜凤波)         if (rc == NGX_ERROR) {
213*3da8d17dSfengbojiang(姜凤波)             return rc;
214*3da8d17dSfengbojiang(姜凤波)         }
215*3da8d17dSfengbojiang(姜凤波) 
216*3da8d17dSfengbojiang(姜凤波)         /* NGX_DECLINED */
217*3da8d17dSfengbojiang(姜凤波)     }
218*3da8d17dSfengbojiang(姜凤波) 
219*3da8d17dSfengbojiang(姜凤波)     if (rlcf->regex) {
220*3da8d17dSfengbojiang(姜凤波)         referer.len = len;
221*3da8d17dSfengbojiang(姜凤波)         referer.data = ref;
222*3da8d17dSfengbojiang(姜凤波) 
223*3da8d17dSfengbojiang(姜凤波)         rc = ngx_regex_exec_array(rlcf->regex, &referer, r->connection->log);
224*3da8d17dSfengbojiang(姜凤波) 
225*3da8d17dSfengbojiang(姜凤波)         if (rc == NGX_OK) {
226*3da8d17dSfengbojiang(姜凤波)             goto valid;
227*3da8d17dSfengbojiang(姜凤波)         }
228*3da8d17dSfengbojiang(姜凤波) 
229*3da8d17dSfengbojiang(姜凤波)         if (rc == NGX_ERROR) {
230*3da8d17dSfengbojiang(姜凤波)             return rc;
231*3da8d17dSfengbojiang(姜凤波)         }
232*3da8d17dSfengbojiang(姜凤波) 
233*3da8d17dSfengbojiang(姜凤波)         /* NGX_DECLINED */
234*3da8d17dSfengbojiang(姜凤波)     }
235*3da8d17dSfengbojiang(姜凤波) 
236*3da8d17dSfengbojiang(姜凤波) #endif
237*3da8d17dSfengbojiang(姜凤波) 
238*3da8d17dSfengbojiang(姜凤波) invalid:
239*3da8d17dSfengbojiang(姜凤波) 
240*3da8d17dSfengbojiang(姜凤波)     *v = ngx_http_variable_true_value;
241*3da8d17dSfengbojiang(姜凤波) 
242*3da8d17dSfengbojiang(姜凤波)     return NGX_OK;
243*3da8d17dSfengbojiang(姜凤波) 
244*3da8d17dSfengbojiang(姜凤波) uri:
245*3da8d17dSfengbojiang(姜凤波) 
246*3da8d17dSfengbojiang(姜凤波)     for ( /* void */ ; p < last; p++) {
247*3da8d17dSfengbojiang(姜凤波)         if (*p == '/') {
248*3da8d17dSfengbojiang(姜凤波)             break;
249*3da8d17dSfengbojiang(姜凤波)         }
250*3da8d17dSfengbojiang(姜凤波)     }
251*3da8d17dSfengbojiang(姜凤波) 
252*3da8d17dSfengbojiang(姜凤波)     len = last - p;
253*3da8d17dSfengbojiang(姜凤波) 
254*3da8d17dSfengbojiang(姜凤波)     if (uri == NGX_HTTP_REFERER_NO_URI_PART) {
255*3da8d17dSfengbojiang(姜凤波)         goto valid;
256*3da8d17dSfengbojiang(姜凤波)     }
257*3da8d17dSfengbojiang(姜凤波) 
258*3da8d17dSfengbojiang(姜凤波)     if (len < uri->len || ngx_strncmp(uri->data, p, uri->len) != 0) {
259*3da8d17dSfengbojiang(姜凤波)         goto invalid;
260*3da8d17dSfengbojiang(姜凤波)     }
261*3da8d17dSfengbojiang(姜凤波) 
262*3da8d17dSfengbojiang(姜凤波) valid:
263*3da8d17dSfengbojiang(姜凤波) 
264*3da8d17dSfengbojiang(姜凤波)     *v = ngx_http_variable_null_value;
265*3da8d17dSfengbojiang(姜凤波) 
266*3da8d17dSfengbojiang(姜凤波)     return NGX_OK;
267*3da8d17dSfengbojiang(姜凤波) }
268*3da8d17dSfengbojiang(姜凤波) 
269*3da8d17dSfengbojiang(姜凤波) 
270*3da8d17dSfengbojiang(姜凤波) static ngx_int_t
ngx_http_referer_add_variables(ngx_conf_t * cf)271*3da8d17dSfengbojiang(姜凤波) ngx_http_referer_add_variables(ngx_conf_t *cf)
272*3da8d17dSfengbojiang(姜凤波) {
273*3da8d17dSfengbojiang(姜凤波)     ngx_http_variable_t  *var;
274*3da8d17dSfengbojiang(姜凤波) 
275*3da8d17dSfengbojiang(姜凤波)     var = ngx_http_add_variable(cf, &ngx_http_invalid_referer_name,
276*3da8d17dSfengbojiang(姜凤波)                                 NGX_HTTP_VAR_CHANGEABLE);
277*3da8d17dSfengbojiang(姜凤波)     if (var == NULL) {
278*3da8d17dSfengbojiang(姜凤波)         return NGX_ERROR;
279*3da8d17dSfengbojiang(姜凤波)     }
280*3da8d17dSfengbojiang(姜凤波) 
281*3da8d17dSfengbojiang(姜凤波)     var->get_handler = ngx_http_referer_variable;
282*3da8d17dSfengbojiang(姜凤波) 
283*3da8d17dSfengbojiang(姜凤波)     return NGX_OK;
284*3da8d17dSfengbojiang(姜凤波) }
285*3da8d17dSfengbojiang(姜凤波) 
286*3da8d17dSfengbojiang(姜凤波) 
287*3da8d17dSfengbojiang(姜凤波) static void *
ngx_http_referer_create_conf(ngx_conf_t * cf)288*3da8d17dSfengbojiang(姜凤波) ngx_http_referer_create_conf(ngx_conf_t *cf)
289*3da8d17dSfengbojiang(姜凤波) {
290*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t  *conf;
291*3da8d17dSfengbojiang(姜凤波) 
292*3da8d17dSfengbojiang(姜凤波)     conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_referer_conf_t));
293*3da8d17dSfengbojiang(姜凤波)     if (conf == NULL) {
294*3da8d17dSfengbojiang(姜凤波)         return NULL;
295*3da8d17dSfengbojiang(姜凤波)     }
296*3da8d17dSfengbojiang(姜凤波) 
297*3da8d17dSfengbojiang(姜凤波)     /*
298*3da8d17dSfengbojiang(姜凤波)      * set by ngx_pcalloc():
299*3da8d17dSfengbojiang(姜凤波)      *
300*3da8d17dSfengbojiang(姜凤波)      *     conf->hash = { NULL };
301*3da8d17dSfengbojiang(姜凤波)      *     conf->server_names = 0;
302*3da8d17dSfengbojiang(姜凤波)      *     conf->keys = NULL;
303*3da8d17dSfengbojiang(姜凤波)      */
304*3da8d17dSfengbojiang(姜凤波) 
305*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
306*3da8d17dSfengbojiang(姜凤波)     conf->regex = NGX_CONF_UNSET_PTR;
307*3da8d17dSfengbojiang(姜凤波)     conf->server_name_regex = NGX_CONF_UNSET_PTR;
308*3da8d17dSfengbojiang(姜凤波) #endif
309*3da8d17dSfengbojiang(姜凤波) 
310*3da8d17dSfengbojiang(姜凤波)     conf->no_referer = NGX_CONF_UNSET;
311*3da8d17dSfengbojiang(姜凤波)     conf->blocked_referer = NGX_CONF_UNSET;
312*3da8d17dSfengbojiang(姜凤波)     conf->referer_hash_max_size = NGX_CONF_UNSET_UINT;
313*3da8d17dSfengbojiang(姜凤波)     conf->referer_hash_bucket_size = NGX_CONF_UNSET_UINT;
314*3da8d17dSfengbojiang(姜凤波) 
315*3da8d17dSfengbojiang(姜凤波)     return conf;
316*3da8d17dSfengbojiang(姜凤波) }
317*3da8d17dSfengbojiang(姜凤波) 
318*3da8d17dSfengbojiang(姜凤波) 
319*3da8d17dSfengbojiang(姜凤波) static char *
ngx_http_referer_merge_conf(ngx_conf_t * cf,void * parent,void * child)320*3da8d17dSfengbojiang(姜凤波) ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
321*3da8d17dSfengbojiang(姜凤波) {
322*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t *prev = parent;
323*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t *conf = child;
324*3da8d17dSfengbojiang(姜凤波) 
325*3da8d17dSfengbojiang(姜凤波)     ngx_uint_t                 n;
326*3da8d17dSfengbojiang(姜凤波)     ngx_hash_init_t            hash;
327*3da8d17dSfengbojiang(姜凤波)     ngx_http_server_name_t    *sn;
328*3da8d17dSfengbojiang(姜凤波)     ngx_http_core_srv_conf_t  *cscf;
329*3da8d17dSfengbojiang(姜凤波) 
330*3da8d17dSfengbojiang(姜凤波)     if (conf->keys == NULL) {
331*3da8d17dSfengbojiang(姜凤波)         conf->hash = prev->hash;
332*3da8d17dSfengbojiang(姜凤波) 
333*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
334*3da8d17dSfengbojiang(姜凤波)         ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
335*3da8d17dSfengbojiang(姜凤波)         ngx_conf_merge_ptr_value(conf->server_name_regex,
336*3da8d17dSfengbojiang(姜凤波)                                  prev->server_name_regex, NULL);
337*3da8d17dSfengbojiang(姜凤波) #endif
338*3da8d17dSfengbojiang(姜凤波)         ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
339*3da8d17dSfengbojiang(姜凤波)         ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
340*3da8d17dSfengbojiang(姜凤波)         ngx_conf_merge_uint_value(conf->referer_hash_max_size,
341*3da8d17dSfengbojiang(姜凤波)                                   prev->referer_hash_max_size, 2048);
342*3da8d17dSfengbojiang(姜凤波)         ngx_conf_merge_uint_value(conf->referer_hash_bucket_size,
343*3da8d17dSfengbojiang(姜凤波)                                   prev->referer_hash_bucket_size, 64);
344*3da8d17dSfengbojiang(姜凤波) 
345*3da8d17dSfengbojiang(姜凤波)         return NGX_CONF_OK;
346*3da8d17dSfengbojiang(姜凤波)     }
347*3da8d17dSfengbojiang(姜凤波) 
348*3da8d17dSfengbojiang(姜凤波)     if (conf->server_names == 1) {
349*3da8d17dSfengbojiang(姜凤波)         cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
350*3da8d17dSfengbojiang(姜凤波) 
351*3da8d17dSfengbojiang(姜凤波)         sn = cscf->server_names.elts;
352*3da8d17dSfengbojiang(姜凤波)         for (n = 0; n < cscf->server_names.nelts; n++) {
353*3da8d17dSfengbojiang(姜凤波) 
354*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
355*3da8d17dSfengbojiang(姜凤波)             if (sn[n].regex) {
356*3da8d17dSfengbojiang(姜凤波) 
357*3da8d17dSfengbojiang(姜凤波)                 if (ngx_http_add_regex_server_name(cf, conf, sn[n].regex)
358*3da8d17dSfengbojiang(姜凤波)                     != NGX_OK)
359*3da8d17dSfengbojiang(姜凤波)                 {
360*3da8d17dSfengbojiang(姜凤波)                     return NGX_CONF_ERROR;
361*3da8d17dSfengbojiang(姜凤波)                 }
362*3da8d17dSfengbojiang(姜凤波) 
363*3da8d17dSfengbojiang(姜凤波)                 continue;
364*3da8d17dSfengbojiang(姜凤波)             }
365*3da8d17dSfengbojiang(姜凤波) #endif
366*3da8d17dSfengbojiang(姜凤波) 
367*3da8d17dSfengbojiang(姜凤波)             if (ngx_http_add_referer(cf, conf->keys, &sn[n].name, NULL)
368*3da8d17dSfengbojiang(姜凤波)                 != NGX_OK)
369*3da8d17dSfengbojiang(姜凤波)             {
370*3da8d17dSfengbojiang(姜凤波)                 return NGX_CONF_ERROR;
371*3da8d17dSfengbojiang(姜凤波)             }
372*3da8d17dSfengbojiang(姜凤波)         }
373*3da8d17dSfengbojiang(姜凤波)     }
374*3da8d17dSfengbojiang(姜凤波) 
375*3da8d17dSfengbojiang(姜凤波)     if ((conf->no_referer == 1 || conf->blocked_referer == 1)
376*3da8d17dSfengbojiang(姜凤波)         && conf->keys->keys.nelts == 0
377*3da8d17dSfengbojiang(姜凤波)         && conf->keys->dns_wc_head.nelts == 0
378*3da8d17dSfengbojiang(姜凤波)         && conf->keys->dns_wc_tail.nelts == 0)
379*3da8d17dSfengbojiang(姜凤波)     {
380*3da8d17dSfengbojiang(姜凤波)         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
381*3da8d17dSfengbojiang(姜凤波)                       "the \"none\" or \"blocked\" referers are specified "
382*3da8d17dSfengbojiang(姜凤波)                       "in the \"valid_referers\" directive "
383*3da8d17dSfengbojiang(姜凤波)                       "without any valid referer");
384*3da8d17dSfengbojiang(姜凤波)         return NGX_CONF_ERROR;
385*3da8d17dSfengbojiang(姜凤波)     }
386*3da8d17dSfengbojiang(姜凤波) 
387*3da8d17dSfengbojiang(姜凤波)     ngx_conf_merge_uint_value(conf->referer_hash_max_size,
388*3da8d17dSfengbojiang(姜凤波)                               prev->referer_hash_max_size, 2048);
389*3da8d17dSfengbojiang(姜凤波)     ngx_conf_merge_uint_value(conf->referer_hash_bucket_size,
390*3da8d17dSfengbojiang(姜凤波)                               prev->referer_hash_bucket_size, 64);
391*3da8d17dSfengbojiang(姜凤波)     conf->referer_hash_bucket_size = ngx_align(conf->referer_hash_bucket_size,
392*3da8d17dSfengbojiang(姜凤波)                                                ngx_cacheline_size);
393*3da8d17dSfengbojiang(姜凤波) 
394*3da8d17dSfengbojiang(姜凤波)     hash.key = ngx_hash_key_lc;
395*3da8d17dSfengbojiang(姜凤波)     hash.max_size = conf->referer_hash_max_size;
396*3da8d17dSfengbojiang(姜凤波)     hash.bucket_size = conf->referer_hash_bucket_size;
397*3da8d17dSfengbojiang(姜凤波)     hash.name = "referer_hash";
398*3da8d17dSfengbojiang(姜凤波)     hash.pool = cf->pool;
399*3da8d17dSfengbojiang(姜凤波) 
400*3da8d17dSfengbojiang(姜凤波)     if (conf->keys->keys.nelts) {
401*3da8d17dSfengbojiang(姜凤波)         hash.hash = &conf->hash.hash;
402*3da8d17dSfengbojiang(姜凤波)         hash.temp_pool = NULL;
403*3da8d17dSfengbojiang(姜凤波) 
404*3da8d17dSfengbojiang(姜凤波)         if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
405*3da8d17dSfengbojiang(姜凤波)             != NGX_OK)
406*3da8d17dSfengbojiang(姜凤波)         {
407*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
408*3da8d17dSfengbojiang(姜凤波)         }
409*3da8d17dSfengbojiang(姜凤波)     }
410*3da8d17dSfengbojiang(姜凤波) 
411*3da8d17dSfengbojiang(姜凤波)     if (conf->keys->dns_wc_head.nelts) {
412*3da8d17dSfengbojiang(姜凤波) 
413*3da8d17dSfengbojiang(姜凤波)         ngx_qsort(conf->keys->dns_wc_head.elts,
414*3da8d17dSfengbojiang(姜凤波)                   (size_t) conf->keys->dns_wc_head.nelts,
415*3da8d17dSfengbojiang(姜凤波)                   sizeof(ngx_hash_key_t),
416*3da8d17dSfengbojiang(姜凤波)                   ngx_http_cmp_referer_wildcards);
417*3da8d17dSfengbojiang(姜凤波) 
418*3da8d17dSfengbojiang(姜凤波)         hash.hash = NULL;
419*3da8d17dSfengbojiang(姜凤波)         hash.temp_pool = cf->temp_pool;
420*3da8d17dSfengbojiang(姜凤波) 
421*3da8d17dSfengbojiang(姜凤波)         if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts,
422*3da8d17dSfengbojiang(姜凤波)                                    conf->keys->dns_wc_head.nelts)
423*3da8d17dSfengbojiang(姜凤波)             != NGX_OK)
424*3da8d17dSfengbojiang(姜凤波)         {
425*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
426*3da8d17dSfengbojiang(姜凤波)         }
427*3da8d17dSfengbojiang(姜凤波) 
428*3da8d17dSfengbojiang(姜凤波)         conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
429*3da8d17dSfengbojiang(姜凤波)     }
430*3da8d17dSfengbojiang(姜凤波) 
431*3da8d17dSfengbojiang(姜凤波)     if (conf->keys->dns_wc_tail.nelts) {
432*3da8d17dSfengbojiang(姜凤波) 
433*3da8d17dSfengbojiang(姜凤波)         ngx_qsort(conf->keys->dns_wc_tail.elts,
434*3da8d17dSfengbojiang(姜凤波)                   (size_t) conf->keys->dns_wc_tail.nelts,
435*3da8d17dSfengbojiang(姜凤波)                   sizeof(ngx_hash_key_t),
436*3da8d17dSfengbojiang(姜凤波)                   ngx_http_cmp_referer_wildcards);
437*3da8d17dSfengbojiang(姜凤波) 
438*3da8d17dSfengbojiang(姜凤波)         hash.hash = NULL;
439*3da8d17dSfengbojiang(姜凤波)         hash.temp_pool = cf->temp_pool;
440*3da8d17dSfengbojiang(姜凤波) 
441*3da8d17dSfengbojiang(姜凤波)         if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts,
442*3da8d17dSfengbojiang(姜凤波)                                    conf->keys->dns_wc_tail.nelts)
443*3da8d17dSfengbojiang(姜凤波)             != NGX_OK)
444*3da8d17dSfengbojiang(姜凤波)         {
445*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
446*3da8d17dSfengbojiang(姜凤波)         }
447*3da8d17dSfengbojiang(姜凤波) 
448*3da8d17dSfengbojiang(姜凤波)         conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
449*3da8d17dSfengbojiang(姜凤波)     }
450*3da8d17dSfengbojiang(姜凤波) 
451*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
452*3da8d17dSfengbojiang(姜凤波)     ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
453*3da8d17dSfengbojiang(姜凤波)     ngx_conf_merge_ptr_value(conf->server_name_regex, prev->server_name_regex,
454*3da8d17dSfengbojiang(姜凤波)                              NULL);
455*3da8d17dSfengbojiang(姜凤波) #endif
456*3da8d17dSfengbojiang(姜凤波) 
457*3da8d17dSfengbojiang(姜凤波)     if (conf->no_referer == NGX_CONF_UNSET) {
458*3da8d17dSfengbojiang(姜凤波)         conf->no_referer = 0;
459*3da8d17dSfengbojiang(姜凤波)     }
460*3da8d17dSfengbojiang(姜凤波) 
461*3da8d17dSfengbojiang(姜凤波)     if (conf->blocked_referer == NGX_CONF_UNSET) {
462*3da8d17dSfengbojiang(姜凤波)         conf->blocked_referer = 0;
463*3da8d17dSfengbojiang(姜凤波)     }
464*3da8d17dSfengbojiang(姜凤波) 
465*3da8d17dSfengbojiang(姜凤波)     conf->keys = NULL;
466*3da8d17dSfengbojiang(姜凤波) 
467*3da8d17dSfengbojiang(姜凤波)     return NGX_CONF_OK;
468*3da8d17dSfengbojiang(姜凤波) }
469*3da8d17dSfengbojiang(姜凤波) 
470*3da8d17dSfengbojiang(姜凤波) 
471*3da8d17dSfengbojiang(姜凤波) static char *
ngx_http_valid_referers(ngx_conf_t * cf,ngx_command_t * cmd,void * conf)472*3da8d17dSfengbojiang(姜凤波) ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
473*3da8d17dSfengbojiang(姜凤波) {
474*3da8d17dSfengbojiang(姜凤波)     ngx_http_referer_conf_t  *rlcf = conf;
475*3da8d17dSfengbojiang(姜凤波) 
476*3da8d17dSfengbojiang(姜凤波)     u_char      *p;
477*3da8d17dSfengbojiang(姜凤波)     ngx_str_t   *value, uri;
478*3da8d17dSfengbojiang(姜凤波)     ngx_uint_t   i;
479*3da8d17dSfengbojiang(姜凤波) 
480*3da8d17dSfengbojiang(姜凤波)     if (rlcf->keys == NULL) {
481*3da8d17dSfengbojiang(姜凤波)         rlcf->keys = ngx_pcalloc(cf->temp_pool, sizeof(ngx_hash_keys_arrays_t));
482*3da8d17dSfengbojiang(姜凤波)         if (rlcf->keys == NULL) {
483*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
484*3da8d17dSfengbojiang(姜凤波)         }
485*3da8d17dSfengbojiang(姜凤波) 
486*3da8d17dSfengbojiang(姜凤波)         rlcf->keys->pool = cf->pool;
487*3da8d17dSfengbojiang(姜凤波)         rlcf->keys->temp_pool = cf->pool;
488*3da8d17dSfengbojiang(姜凤波) 
489*3da8d17dSfengbojiang(姜凤波)         if (ngx_hash_keys_array_init(rlcf->keys, NGX_HASH_SMALL) != NGX_OK) {
490*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
491*3da8d17dSfengbojiang(姜凤波)         }
492*3da8d17dSfengbojiang(姜凤波)     }
493*3da8d17dSfengbojiang(姜凤波) 
494*3da8d17dSfengbojiang(姜凤波)     value = cf->args->elts;
495*3da8d17dSfengbojiang(姜凤波) 
496*3da8d17dSfengbojiang(姜凤波)     for (i = 1; i < cf->args->nelts; i++) {
497*3da8d17dSfengbojiang(姜凤波)         if (value[i].len == 0) {
498*3da8d17dSfengbojiang(姜凤波)             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
499*3da8d17dSfengbojiang(姜凤波)                                "invalid referer \"%V\"", &value[i]);
500*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
501*3da8d17dSfengbojiang(姜凤波)         }
502*3da8d17dSfengbojiang(姜凤波) 
503*3da8d17dSfengbojiang(姜凤波)         if (ngx_strcmp(value[i].data, "none") == 0) {
504*3da8d17dSfengbojiang(姜凤波)             rlcf->no_referer = 1;
505*3da8d17dSfengbojiang(姜凤波)             continue;
506*3da8d17dSfengbojiang(姜凤波)         }
507*3da8d17dSfengbojiang(姜凤波) 
508*3da8d17dSfengbojiang(姜凤波)         if (ngx_strcmp(value[i].data, "blocked") == 0) {
509*3da8d17dSfengbojiang(姜凤波)             rlcf->blocked_referer = 1;
510*3da8d17dSfengbojiang(姜凤波)             continue;
511*3da8d17dSfengbojiang(姜凤波)         }
512*3da8d17dSfengbojiang(姜凤波) 
513*3da8d17dSfengbojiang(姜凤波)         if (ngx_strcmp(value[i].data, "server_names") == 0) {
514*3da8d17dSfengbojiang(姜凤波)             rlcf->server_names = 1;
515*3da8d17dSfengbojiang(姜凤波)             continue;
516*3da8d17dSfengbojiang(姜凤波)         }
517*3da8d17dSfengbojiang(姜凤波) 
518*3da8d17dSfengbojiang(姜凤波)         if (value[i].data[0] == '~') {
519*3da8d17dSfengbojiang(姜凤波)             if (ngx_http_add_regex_referer(cf, rlcf, &value[i]) != NGX_OK) {
520*3da8d17dSfengbojiang(姜凤波)                 return NGX_CONF_ERROR;
521*3da8d17dSfengbojiang(姜凤波)             }
522*3da8d17dSfengbojiang(姜凤波) 
523*3da8d17dSfengbojiang(姜凤波)             continue;
524*3da8d17dSfengbojiang(姜凤波)         }
525*3da8d17dSfengbojiang(姜凤波) 
526*3da8d17dSfengbojiang(姜凤波)         ngx_str_null(&uri);
527*3da8d17dSfengbojiang(姜凤波) 
528*3da8d17dSfengbojiang(姜凤波)         p = (u_char *) ngx_strchr(value[i].data, '/');
529*3da8d17dSfengbojiang(姜凤波) 
530*3da8d17dSfengbojiang(姜凤波)         if (p) {
531*3da8d17dSfengbojiang(姜凤波)             uri.len = (value[i].data + value[i].len) - p;
532*3da8d17dSfengbojiang(姜凤波)             uri.data = p;
533*3da8d17dSfengbojiang(姜凤波)             value[i].len = p - value[i].data;
534*3da8d17dSfengbojiang(姜凤波)         }
535*3da8d17dSfengbojiang(姜凤波) 
536*3da8d17dSfengbojiang(姜凤波)         if (ngx_http_add_referer(cf, rlcf->keys, &value[i], &uri) != NGX_OK) {
537*3da8d17dSfengbojiang(姜凤波)             return NGX_CONF_ERROR;
538*3da8d17dSfengbojiang(姜凤波)         }
539*3da8d17dSfengbojiang(姜凤波)     }
540*3da8d17dSfengbojiang(姜凤波) 
541*3da8d17dSfengbojiang(姜凤波)     return NGX_CONF_OK;
542*3da8d17dSfengbojiang(姜凤波) }
543*3da8d17dSfengbojiang(姜凤波) 
544*3da8d17dSfengbojiang(姜凤波) 
545*3da8d17dSfengbojiang(姜凤波) static ngx_int_t
ngx_http_add_referer(ngx_conf_t * cf,ngx_hash_keys_arrays_t * keys,ngx_str_t * value,ngx_str_t * uri)546*3da8d17dSfengbojiang(姜凤波) ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys,
547*3da8d17dSfengbojiang(姜凤波)     ngx_str_t *value, ngx_str_t *uri)
548*3da8d17dSfengbojiang(姜凤波) {
549*3da8d17dSfengbojiang(姜凤波)     ngx_int_t   rc;
550*3da8d17dSfengbojiang(姜凤波)     ngx_str_t  *u;
551*3da8d17dSfengbojiang(姜凤波) 
552*3da8d17dSfengbojiang(姜凤波)     if (uri == NULL || uri->len == 0) {
553*3da8d17dSfengbojiang(姜凤波)         u = NGX_HTTP_REFERER_NO_URI_PART;
554*3da8d17dSfengbojiang(姜凤波) 
555*3da8d17dSfengbojiang(姜凤波)     } else {
556*3da8d17dSfengbojiang(姜凤波)         u = ngx_palloc(cf->pool, sizeof(ngx_str_t));
557*3da8d17dSfengbojiang(姜凤波)         if (u == NULL) {
558*3da8d17dSfengbojiang(姜凤波)             return NGX_ERROR;
559*3da8d17dSfengbojiang(姜凤波)         }
560*3da8d17dSfengbojiang(姜凤波) 
561*3da8d17dSfengbojiang(姜凤波)         *u = *uri;
562*3da8d17dSfengbojiang(姜凤波)     }
563*3da8d17dSfengbojiang(姜凤波) 
564*3da8d17dSfengbojiang(姜凤波)     rc = ngx_hash_add_key(keys, value, u, NGX_HASH_WILDCARD_KEY);
565*3da8d17dSfengbojiang(姜凤波) 
566*3da8d17dSfengbojiang(姜凤波)     if (rc == NGX_OK) {
567*3da8d17dSfengbojiang(姜凤波)         return NGX_OK;
568*3da8d17dSfengbojiang(姜凤波)     }
569*3da8d17dSfengbojiang(姜凤波) 
570*3da8d17dSfengbojiang(姜凤波)     if (rc == NGX_DECLINED) {
571*3da8d17dSfengbojiang(姜凤波)         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
572*3da8d17dSfengbojiang(姜凤波)                            "invalid hostname or wildcard \"%V\"", value);
573*3da8d17dSfengbojiang(姜凤波)     }
574*3da8d17dSfengbojiang(姜凤波) 
575*3da8d17dSfengbojiang(姜凤波)     if (rc == NGX_BUSY) {
576*3da8d17dSfengbojiang(姜凤波)         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
577*3da8d17dSfengbojiang(姜凤波)                            "conflicting parameter \"%V\"", value);
578*3da8d17dSfengbojiang(姜凤波)     }
579*3da8d17dSfengbojiang(姜凤波) 
580*3da8d17dSfengbojiang(姜凤波)     return NGX_ERROR;
581*3da8d17dSfengbojiang(姜凤波) }
582*3da8d17dSfengbojiang(姜凤波) 
583*3da8d17dSfengbojiang(姜凤波) 
584*3da8d17dSfengbojiang(姜凤波) static ngx_int_t
ngx_http_add_regex_referer(ngx_conf_t * cf,ngx_http_referer_conf_t * rlcf,ngx_str_t * name)585*3da8d17dSfengbojiang(姜凤波) ngx_http_add_regex_referer(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
586*3da8d17dSfengbojiang(姜凤波)     ngx_str_t *name)
587*3da8d17dSfengbojiang(姜凤波) {
588*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
589*3da8d17dSfengbojiang(姜凤波)     ngx_regex_elt_t      *re;
590*3da8d17dSfengbojiang(姜凤波)     ngx_regex_compile_t   rc;
591*3da8d17dSfengbojiang(姜凤波)     u_char                errstr[NGX_MAX_CONF_ERRSTR];
592*3da8d17dSfengbojiang(姜凤波) 
593*3da8d17dSfengbojiang(姜凤波)     if (name->len == 1) {
594*3da8d17dSfengbojiang(姜凤波)         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty regex in \"%V\"", name);
595*3da8d17dSfengbojiang(姜凤波)         return NGX_ERROR;
596*3da8d17dSfengbojiang(姜凤波)     }
597*3da8d17dSfengbojiang(姜凤波) 
598*3da8d17dSfengbojiang(姜凤波)     if (rlcf->regex == NGX_CONF_UNSET_PTR) {
599*3da8d17dSfengbojiang(姜凤波)         rlcf->regex = ngx_array_create(cf->pool, 2, sizeof(ngx_regex_elt_t));
600*3da8d17dSfengbojiang(姜凤波)         if (rlcf->regex == NULL) {
601*3da8d17dSfengbojiang(姜凤波)             return NGX_ERROR;
602*3da8d17dSfengbojiang(姜凤波)         }
603*3da8d17dSfengbojiang(姜凤波)     }
604*3da8d17dSfengbojiang(姜凤波) 
605*3da8d17dSfengbojiang(姜凤波)     re = ngx_array_push(rlcf->regex);
606*3da8d17dSfengbojiang(姜凤波)     if (re == NULL) {
607*3da8d17dSfengbojiang(姜凤波)         return NGX_ERROR;
608*3da8d17dSfengbojiang(姜凤波)     }
609*3da8d17dSfengbojiang(姜凤波) 
610*3da8d17dSfengbojiang(姜凤波)     name->len--;
611*3da8d17dSfengbojiang(姜凤波)     name->data++;
612*3da8d17dSfengbojiang(姜凤波) 
613*3da8d17dSfengbojiang(姜凤波)     ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
614*3da8d17dSfengbojiang(姜凤波) 
615*3da8d17dSfengbojiang(姜凤波)     rc.pattern = *name;
616*3da8d17dSfengbojiang(姜凤波)     rc.pool = cf->pool;
617*3da8d17dSfengbojiang(姜凤波)     rc.options = NGX_REGEX_CASELESS;
618*3da8d17dSfengbojiang(姜凤波)     rc.err.len = NGX_MAX_CONF_ERRSTR;
619*3da8d17dSfengbojiang(姜凤波)     rc.err.data = errstr;
620*3da8d17dSfengbojiang(姜凤波) 
621*3da8d17dSfengbojiang(姜凤波)     if (ngx_regex_compile(&rc) != NGX_OK) {
622*3da8d17dSfengbojiang(姜凤波)         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V", &rc.err);
623*3da8d17dSfengbojiang(姜凤波)         return NGX_ERROR;
624*3da8d17dSfengbojiang(姜凤波)     }
625*3da8d17dSfengbojiang(姜凤波) 
626*3da8d17dSfengbojiang(姜凤波)     re->regex = rc.regex;
627*3da8d17dSfengbojiang(姜凤波)     re->name = name->data;
628*3da8d17dSfengbojiang(姜凤波) 
629*3da8d17dSfengbojiang(姜凤波)     return NGX_OK;
630*3da8d17dSfengbojiang(姜凤波) 
631*3da8d17dSfengbojiang(姜凤波) #else
632*3da8d17dSfengbojiang(姜凤波) 
633*3da8d17dSfengbojiang(姜凤波)     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
634*3da8d17dSfengbojiang(姜凤波)                        "the using of the regex \"%V\" requires PCRE library",
635*3da8d17dSfengbojiang(姜凤波)                        name);
636*3da8d17dSfengbojiang(姜凤波) 
637*3da8d17dSfengbojiang(姜凤波)     return NGX_ERROR;
638*3da8d17dSfengbojiang(姜凤波) 
639*3da8d17dSfengbojiang(姜凤波) #endif
640*3da8d17dSfengbojiang(姜凤波) }
641*3da8d17dSfengbojiang(姜凤波) 
642*3da8d17dSfengbojiang(姜凤波) 
643*3da8d17dSfengbojiang(姜凤波) #if (NGX_PCRE)
644*3da8d17dSfengbojiang(姜凤波) 
645*3da8d17dSfengbojiang(姜凤波) static ngx_int_t
ngx_http_add_regex_server_name(ngx_conf_t * cf,ngx_http_referer_conf_t * rlcf,ngx_http_regex_t * regex)646*3da8d17dSfengbojiang(姜凤波) ngx_http_add_regex_server_name(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf,
647*3da8d17dSfengbojiang(姜凤波)     ngx_http_regex_t *regex)
648*3da8d17dSfengbojiang(姜凤波) {
649*3da8d17dSfengbojiang(姜凤波)     ngx_regex_elt_t  *re;
650*3da8d17dSfengbojiang(姜凤波) 
651*3da8d17dSfengbojiang(姜凤波)     if (rlcf->server_name_regex == NGX_CONF_UNSET_PTR) {
652*3da8d17dSfengbojiang(姜凤波)         rlcf->server_name_regex = ngx_array_create(cf->pool, 2,
653*3da8d17dSfengbojiang(姜凤波)                                                    sizeof(ngx_regex_elt_t));
654*3da8d17dSfengbojiang(姜凤波)         if (rlcf->server_name_regex == NULL) {
655*3da8d17dSfengbojiang(姜凤波)             return NGX_ERROR;
656*3da8d17dSfengbojiang(姜凤波)         }
657*3da8d17dSfengbojiang(姜凤波)     }
658*3da8d17dSfengbojiang(姜凤波) 
659*3da8d17dSfengbojiang(姜凤波)     re = ngx_array_push(rlcf->server_name_regex);
660*3da8d17dSfengbojiang(姜凤波)     if (re == NULL) {
661*3da8d17dSfengbojiang(姜凤波)         return NGX_ERROR;
662*3da8d17dSfengbojiang(姜凤波)     }
663*3da8d17dSfengbojiang(姜凤波) 
664*3da8d17dSfengbojiang(姜凤波)     re->regex = regex->regex;
665*3da8d17dSfengbojiang(姜凤波)     re->name = regex->name.data;
666*3da8d17dSfengbojiang(姜凤波) 
667*3da8d17dSfengbojiang(姜凤波)     return NGX_OK;
668*3da8d17dSfengbojiang(姜凤波) }
669*3da8d17dSfengbojiang(姜凤波) 
670*3da8d17dSfengbojiang(姜凤波) #endif
671*3da8d17dSfengbojiang(姜凤波) 
672*3da8d17dSfengbojiang(姜凤波) 
673*3da8d17dSfengbojiang(姜凤波) static int ngx_libc_cdecl
ngx_http_cmp_referer_wildcards(const void * one,const void * two)674*3da8d17dSfengbojiang(姜凤波) ngx_http_cmp_referer_wildcards(const void *one, const void *two)
675*3da8d17dSfengbojiang(姜凤波) {
676*3da8d17dSfengbojiang(姜凤波)     ngx_hash_key_t  *first, *second;
677*3da8d17dSfengbojiang(姜凤波) 
678*3da8d17dSfengbojiang(姜凤波)     first = (ngx_hash_key_t *) one;
679*3da8d17dSfengbojiang(姜凤波)     second = (ngx_hash_key_t *) two;
680*3da8d17dSfengbojiang(姜凤波) 
681*3da8d17dSfengbojiang(姜凤波)     return ngx_dns_strcmp(first->key.data, second->key.data);
682*3da8d17dSfengbojiang(姜凤波) }
683