Mercurial > hg > nginx-vendor-0-5
comparison src/http/modules/ngx_http_referer_module.c @ 126:df17fbafec8f NGINX_0_3_10
nginx 0.3.10
*) Change: the "valid_referers" directive and the "$invalid_referer"
variable were moved to the new ngx_http_referer_module from the
ngx_http_rewrite_module.
*) Change: the "$apache_bytes_sent" variable name was changed to
"$body_bytes_sent".
*) Feature: the "$sent_http_..." variables.
*) Feature: the "if" directive supports the "=" and "!=" operations.
*) Feature: the "proxy_pass" directive supports the HTTPS protocol.
*) Feature: the "proxy_set_body" directive.
*) Feature: the "post_action" directive.
*) Feature: the ngx_http_empty_gif_module.
*) Feature: the "worker_cpu_affinity" directive for Linux.
*) Bugfix: the "rewrite" directive did not unescape URI part in
redirect, now it is unescaped except the %00-%25 and %7F-%FF
characters.
*) Bugfix: nginx could not be built by the icc 9.0 compiler.
*) Bugfix: if the SSI was enabled for zero size static file, then the
chunked response was encoded incorrectly.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Tue, 15 Nov 2005 00:00:00 +0300 |
parents | |
children | 91372f004adf |
comparison
equal
deleted
inserted
replaced
125:97504de1f89e | 126:df17fbafec8f |
---|---|
1 | |
2 /* | |
3 * Copyright (C) Igor Sysoev | |
4 */ | |
5 | |
6 | |
7 #include <ngx_config.h> | |
8 #include <ngx_core.h> | |
9 #include <ngx_http.h> | |
10 | |
11 | |
12 typedef struct { | |
13 ngx_str_t name; | |
14 ngx_uint_t wildcard; | |
15 } ngx_http_referer_t; | |
16 | |
17 typedef struct { | |
18 ngx_array_t *referers; /* ngx_http_referer_t */ | |
19 | |
20 ngx_flag_t no_referer; | |
21 ngx_flag_t blocked_referer; | |
22 } ngx_http_referer_conf_t; | |
23 | |
24 | |
25 static void * ngx_http_referer_create_conf(ngx_conf_t *cf); | |
26 static char * ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, | |
27 void *child); | |
28 static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, | |
29 void *conf); | |
30 | |
31 | |
32 static ngx_command_t ngx_http_referer_commands[] = { | |
33 | |
34 { ngx_string("valid_referers"), | |
35 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
36 ngx_http_valid_referers, | |
37 NGX_HTTP_LOC_CONF_OFFSET, | |
38 0, | |
39 NULL }, | |
40 | |
41 ngx_null_command | |
42 }; | |
43 | |
44 | |
45 static ngx_http_module_t ngx_http_referer_module_ctx = { | |
46 NULL, /* preconfiguration */ | |
47 NULL, /* postconfiguration */ | |
48 | |
49 NULL, /* create main configuration */ | |
50 NULL, /* init main configuration */ | |
51 | |
52 NULL, /* create server configuration */ | |
53 NULL, /* merge server configuration */ | |
54 | |
55 ngx_http_referer_create_conf, /* create location configuration */ | |
56 ngx_http_referer_merge_conf /* merge location configuration */ | |
57 }; | |
58 | |
59 | |
60 ngx_module_t ngx_http_referer_module = { | |
61 NGX_MODULE_V1, | |
62 &ngx_http_referer_module_ctx, /* module context */ | |
63 ngx_http_referer_commands, /* module directives */ | |
64 NGX_HTTP_MODULE, /* module type */ | |
65 NULL, /* init master */ | |
66 NULL, /* init module */ | |
67 NULL, /* init process */ | |
68 NULL, /* init thread */ | |
69 NULL, /* exit thread */ | |
70 NULL, /* exit process */ | |
71 NULL, /* exit master */ | |
72 NGX_MODULE_V1_PADDING | |
73 }; | |
74 | |
75 | |
76 static ngx_int_t | |
77 ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
78 uintptr_t data) | |
79 { | |
80 u_char *ref; | |
81 size_t len; | |
82 ngx_uint_t i, n; | |
83 ngx_http_referer_t *refs; | |
84 ngx_http_referer_conf_t *cf; | |
85 | |
86 cf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); | |
87 | |
88 if (cf->referers == NULL) { | |
89 *v = ngx_http_variable_null_value; | |
90 return NGX_OK; | |
91 } | |
92 | |
93 if (r->headers_in.referer == NULL) { | |
94 if (cf->no_referer) { | |
95 *v = ngx_http_variable_null_value; | |
96 return NGX_OK; | |
97 | |
98 } else { | |
99 *v = ngx_http_variable_true_value; | |
100 return NGX_OK; | |
101 } | |
102 } | |
103 | |
104 len = r->headers_in.referer->value.len; | |
105 ref = r->headers_in.referer->value.data; | |
106 | |
107 if (len < sizeof("http://i.ru") - 1 | |
108 || (ngx_strncasecmp(ref, "http://", 7) != 0)) | |
109 { | |
110 if (cf->blocked_referer) { | |
111 *v = ngx_http_variable_null_value; | |
112 return NGX_OK; | |
113 | |
114 } else { | |
115 *v = ngx_http_variable_true_value; | |
116 return NGX_OK; | |
117 } | |
118 } | |
119 | |
120 len -= 7; | |
121 ref += 7; | |
122 | |
123 refs = cf->referers->elts; | |
124 for (i = 0; i < cf->referers->nelts; i++ ){ | |
125 | |
126 if (refs[i].name.len > len) { | |
127 continue; | |
128 } | |
129 | |
130 if (refs[i].wildcard) { | |
131 for (n = 0; n < len; n++) { | |
132 if (ref[n] == '/' || ref[n] == ':') { | |
133 break; | |
134 } | |
135 | |
136 if (ref[n] != '.') { | |
137 continue; | |
138 } | |
139 | |
140 if (ngx_strncmp(&ref[n], refs[i].name.data, | |
141 refs[i].name.len) == 0) | |
142 { | |
143 *v = ngx_http_variable_null_value; | |
144 return NGX_OK; | |
145 } | |
146 } | |
147 | |
148 } else { | |
149 if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0) | |
150 { | |
151 *v = ngx_http_variable_null_value; | |
152 return NGX_OK; | |
153 } | |
154 } | |
155 } | |
156 | |
157 *v = ngx_http_variable_true_value; | |
158 | |
159 return NGX_OK; | |
160 } | |
161 | |
162 | |
163 static void * | |
164 ngx_http_referer_create_conf(ngx_conf_t *cf) | |
165 { | |
166 ngx_http_referer_conf_t *conf; | |
167 | |
168 conf = ngx_palloc(cf->pool, sizeof(ngx_http_referer_conf_t)); | |
169 if (conf == NULL) { | |
170 return NGX_CONF_ERROR; | |
171 } | |
172 | |
173 conf->referers = NULL; | |
174 conf->no_referer = NGX_CONF_UNSET; | |
175 conf->blocked_referer = NGX_CONF_UNSET; | |
176 | |
177 return conf; | |
178 } | |
179 | |
180 | |
181 static char * | |
182 ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
183 { | |
184 ngx_http_referer_conf_t *prev = parent; | |
185 ngx_http_referer_conf_t *conf = child; | |
186 | |
187 if (conf->referers == NULL) { | |
188 conf->referers = prev->referers; | |
189 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); | |
190 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); | |
191 } | |
192 | |
193 if (conf->no_referer == NGX_CONF_UNSET) { | |
194 conf->no_referer = 0; | |
195 } | |
196 | |
197 if (conf->blocked_referer == NGX_CONF_UNSET) { | |
198 conf->blocked_referer = 0; | |
199 } | |
200 | |
201 return NGX_CONF_OK; | |
202 } | |
203 | |
204 | |
205 static char * | |
206 ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
207 { | |
208 ngx_http_referer_conf_t *lcf = conf; | |
209 | |
210 ngx_uint_t i, server_names; | |
211 ngx_str_t *value, name; | |
212 ngx_http_referer_t *ref; | |
213 ngx_http_variable_t *var; | |
214 ngx_http_server_name_t *sn; | |
215 ngx_http_core_srv_conf_t *cscf; | |
216 | |
217 name.len = sizeof("invalid_referer") - 1; | |
218 name.data = (u_char *) "invalid_referer"; | |
219 | |
220 var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGABLE); | |
221 if (var == NULL) { | |
222 return NGX_CONF_ERROR; | |
223 } | |
224 | |
225 var->handler = ngx_http_referer_variable; | |
226 | |
227 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); | |
228 | |
229 if (lcf->referers == NULL) { | |
230 lcf->referers = ngx_array_create(cf->pool, | |
231 cf->args->nelts + cscf->server_names.nelts, | |
232 sizeof(ngx_http_referer_t)); | |
233 if (lcf->referers == NULL) { | |
234 return NGX_CONF_ERROR; | |
235 } | |
236 } | |
237 | |
238 value = cf->args->elts; | |
239 server_names = 0; | |
240 | |
241 for (i = 1; i < cf->args->nelts; i++) { | |
242 if (value[i].len == 0) { | |
243 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
244 "invalid referer \"%V\"", &value[i]); | |
245 return NGX_CONF_ERROR; | |
246 } | |
247 | |
248 if (ngx_strcmp(value[i].data, "none") == 0) { | |
249 lcf->no_referer = 1; | |
250 continue; | |
251 } | |
252 | |
253 if (ngx_strcmp(value[i].data, "blocked") == 0) { | |
254 lcf->blocked_referer = 1; | |
255 continue; | |
256 } | |
257 | |
258 if (ngx_strcmp(value[i].data, "server_names") == 0) { | |
259 server_names = 1; | |
260 continue; | |
261 } | |
262 | |
263 ref = ngx_array_push(lcf->referers); | |
264 if (ref == NULL) { | |
265 return NGX_CONF_ERROR; | |
266 } | |
267 | |
268 if (value[i].data[0] != '*') { | |
269 ref->name = value[i]; | |
270 ref->wildcard = 0; | |
271 continue; | |
272 } | |
273 | |
274 | |
275 if (value[i].data[1] != '.') { | |
276 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
277 "invalid wildcard referer \"%V\"", &value[i]); | |
278 return NGX_CONF_ERROR; | |
279 } | |
280 | |
281 ref->name.len = value[i].len - 1; | |
282 ref->name.data = value[i].data + 1; | |
283 ref->wildcard = 1; | |
284 } | |
285 | |
286 if (!server_names) { | |
287 return NGX_CONF_OK; | |
288 } | |
289 | |
290 sn = cscf->server_names.elts; | |
291 for (i = 0; i < cscf->server_names.nelts; i++) { | |
292 ref = ngx_array_push(lcf->referers); | |
293 if (ref == NULL) { | |
294 return NGX_CONF_ERROR; | |
295 } | |
296 | |
297 ref->name.len = sn[i].name.len + 1; | |
298 ref->name.data = ngx_palloc(cf->pool, ref->name.len); | |
299 if (ref->name.data == NULL) { | |
300 return NGX_CONF_ERROR; | |
301 } | |
302 | |
303 ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len); | |
304 ref->name.data[sn[i].name.len] = '/'; | |
305 ref->wildcard = sn[i].wildcard; | |
306 } | |
307 | |
308 return NGX_CONF_OK; | |
309 } |