Mercurial > hg > nginx
annotate src/http/modules/ngx_http_rewrite_module.c @ 517:dadfa78d2270 release-0.1.33
nginx-0.1.33-RELEASE import
*) Bugfix: nginx could not be built with the --without-pcre parameter;
the bug had appeared in 0.1.29.
*) Bugfix: 3, 4, 7, and 8 the "proxy_set_header" directives in one
level cause the bus fault on start up.
*) Bugfix: the HTTP protocol was specified in the HTTPS redirects.
*) Bugfix: if the "rewrite" directive used the captures inside the "if"
directive, then the 500 error code was returned.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 23 May 2005 12:07:45 +0000 |
parents | 417a087c9c4d |
children | 12234c998d83 |
rev | line source |
---|---|
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
1 |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
2 /* |
444
42d11f017717
nginx-0.1.0-2004-09-29-20:00:49 import; remove years from copyright
Igor Sysoev <igor@sysoev.ru>
parents:
441
diff
changeset
|
3 * Copyright (C) Igor Sysoev |
441
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
4 */ |
da8c5707af39
nginx-0.1.0-2004-09-28-12:34:51 import; set copyright and remove unused files
Igor Sysoev <igor@sysoev.ru>
parents:
437
diff
changeset
|
5 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
6 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 #include <ngx_config.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_core.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_http.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
11 |
485 | 12 typedef struct { |
509 | 13 ngx_str_t name; |
14 ngx_uint_t wildcard; | |
485 | 15 } ngx_http_rewrite_referer_t; |
16 | |
17 | |
18 typedef struct { | |
509 | 19 ngx_array_t *codes; /* uintptr_t */ |
20 ngx_array_t *referers; /* ngx_http_rewrite_referer_t */ | |
485 | 21 |
515 | 22 ngx_uint_t captures; |
509 | 23 ngx_uint_t stack_size; |
485 | 24 |
509 | 25 ngx_flag_t log; |
485 | 26 |
509 | 27 ngx_flag_t no_referer; |
28 ngx_flag_t blocked_referer; | |
485 | 29 } ngx_http_rewrite_loc_conf_t; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
30 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
31 |
485 | 32 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); |
33 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, | |
487 | 34 void *parent, void *child); |
509 | 35 static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle); |
485 | 36 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
37 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, | |
487 | 38 void *conf); |
485 | 39 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, |
487 | 40 void *conf); |
501 | 41 static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, |
42 ngx_http_rewrite_loc_conf_t *lcf); | |
43 static char *ngx_http_rewrite_variable(ngx_conf_t *cf, | |
44 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
487 | 45 static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf, |
46 ngx_command_t *cmd, void *conf); | |
509 | 47 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, |
501 | 48 void *conf); |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
49 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
50 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
51 static ngx_command_t ngx_http_rewrite_commands[] = { |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
52 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
53 { ngx_string("rewrite"), |
485 | 54 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
55 |NGX_CONF_TAKE23, | |
56 ngx_http_rewrite, | |
57 NGX_HTTP_LOC_CONF_OFFSET, | |
58 0, | |
59 NULL }, | |
60 | |
61 { ngx_string("return"), | |
62 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
63 |NGX_CONF_TAKE1, | |
64 ngx_http_rewrite_return, | |
65 NGX_HTTP_LOC_CONF_OFFSET, | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
66 0, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
67 NULL }, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
68 |
485 | 69 { ngx_string("if"), |
70 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE, | |
71 ngx_http_rewrite_if, | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
72 NGX_HTTP_LOC_CONF_OFFSET, |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
73 0, |
485 | 74 NULL }, |
75 | |
76 { ngx_string("valid_referers"), | |
77 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, | |
78 ngx_http_rewrite_valid_referers, | |
79 NGX_HTTP_LOC_CONF_OFFSET, | |
80 0, | |
81 NULL }, | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
82 |
501 | 83 { ngx_string("set"), |
84 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
85 |NGX_CONF_TAKE2, | |
86 ngx_http_rewrite_set, | |
87 NGX_HTTP_LOC_CONF_OFFSET, | |
88 0, | |
89 NULL }, | |
90 | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
91 { ngx_string("rewrite_log"), |
485 | 92 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
93 |NGX_CONF_TAKE1, | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
94 ngx_conf_set_flag_slot, |
485 | 95 NGX_HTTP_LOC_CONF_OFFSET, |
96 offsetof(ngx_http_rewrite_loc_conf_t, log), | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
97 NULL }, |
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
98 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
99 ngx_null_command |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
100 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
101 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
102 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
103 ngx_http_module_t ngx_http_rewrite_module_ctx = { |
509 | 104 NULL, /* preconfiguration */ |
105 NULL, /* postconfiguration */ | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
106 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
107 NULL, /* create main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
108 NULL, /* init main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
109 |
485 | 110 NULL, /* create server configuration */ |
111 NULL, /* merge server configuration */ | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
112 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
113 ngx_http_rewrite_create_loc_conf, /* create location configration */ |
485 | 114 ngx_http_rewrite_merge_loc_conf /* merge location configration */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
115 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
116 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
117 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
118 ngx_module_t ngx_http_rewrite_module = { |
509 | 119 NGX_MODULE_V1, |
485 | 120 &ngx_http_rewrite_module_ctx, /* module context */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
121 ngx_http_rewrite_commands, /* module directives */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
122 NGX_HTTP_MODULE, /* module type */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
123 ngx_http_rewrite_init, /* init module */ |
485 | 124 NULL /* init process */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
125 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
126 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
127 |
501 | 128 static ngx_http_variable_value_t ngx_http_rewrite_null_value = |
509 | 129 { 0, ngx_string("") }; |
501 | 130 |
485 | 131 |
487 | 132 static ngx_int_t |
133 ngx_http_rewrite_handler(ngx_http_request_t *r) | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
134 { |
509 | 135 ngx_http_script_code_pt code; |
136 ngx_http_script_engine_t *e; | |
485 | 137 ngx_http_rewrite_loc_conf_t *cf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
138 |
485 | 139 cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
140 |
485 | 141 if (cf->codes == NULL) { |
142 return NGX_DECLINED; | |
143 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
144 |
509 | 145 e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); |
501 | 146 if (e == NULL) { |
485 | 147 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
148 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
149 |
509 | 150 e->sp = ngx_pcalloc(r->pool, |
151 cf->stack_size * sizeof(ngx_http_variable_value_t)); | |
485 | 152 if (e->sp == NULL) { |
153 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
154 } | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
155 |
515 | 156 if (cf->captures) { |
157 e->captures = ngx_palloc(r->pool, cf->captures * sizeof(int)); | |
485 | 158 if (e->captures == NULL) { |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
159 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
160 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
161 |
485 | 162 } else { |
163 e->captures = NULL; | |
164 } | |
165 | |
166 e->ip = cf->codes->elts; | |
509 | 167 e->request = r; |
485 | 168 e->quote = 1; |
509 | 169 e->log = cf->log; |
485 | 170 e->status = NGX_DECLINED; |
171 | |
172 while (*(uintptr_t *) e->ip) { | |
509 | 173 code = *(ngx_http_script_code_pt *) e->ip; |
485 | 174 code(e); |
175 } | |
176 | |
177 return e->status; | |
178 } | |
179 | |
180 | |
487 | 181 static void |
509 | 182 ngx_http_rewrite_invalid_referer_code(ngx_http_script_engine_t *e) |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
183 { |
485 | 184 u_char *ref; |
185 size_t len; | |
186 ngx_uint_t i, n; | |
187 ngx_http_request_t *r; | |
188 ngx_http_rewrite_referer_t *refs; | |
189 ngx_http_rewrite_loc_conf_t *cf; | |
190 | |
191 r = e->request; | |
192 | |
193 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
194 "http rewrite invalid referer"); | |
195 | |
196 cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | |
197 | |
198 e->ip += sizeof(uintptr_t); | |
199 | |
200 if (cf->referers == NULL) { | |
501 | 201 e->sp->value = 0; |
202 e->sp->text.len = 0; | |
203 e->sp->text.data = (u_char *) ""; | |
204 e->sp++; | |
205 | |
485 | 206 return; |
207 } | |
208 | |
209 if (r->headers_in.referer == NULL) { | |
210 if (cf->no_referer) { | |
501 | 211 e->sp->value = 0; |
212 e->sp->text.len = 0; | |
213 e->sp->text.data = (u_char *) ""; | |
214 e->sp++; | |
215 | |
485 | 216 return; |
505 | 217 |
485 | 218 } else { |
501 | 219 e->sp->value = 1; |
220 e->sp->text.len = 1; | |
221 e->sp->text.data = (u_char *) "1"; | |
222 e->sp++; | |
223 | |
485 | 224 return; |
225 } | |
226 } | |
227 | |
228 len = r->headers_in.referer->value.len; | |
229 ref = r->headers_in.referer->value.data; | |
230 | |
231 if (len < sizeof("http://i.ru") - 1 | |
232 || (ngx_strncasecmp(ref, "http://", 7) != 0)) | |
233 { | |
505 | 234 if (cf->blocked_referer) { |
235 e->sp->value = 0; | |
236 e->sp->text.len = 0; | |
237 e->sp->text.data = (u_char *) "0"; | |
238 e->sp++; | |
239 | |
240 return; | |
501 | 241 |
505 | 242 } else { |
243 e->sp->value = 1; | |
244 e->sp->text.len = 1; | |
245 e->sp->text.data = (u_char *) "1"; | |
246 e->sp++; | |
247 | |
248 return; | |
249 } | |
485 | 250 } |
251 | |
252 len -= 7; | |
253 ref += 7; | |
254 | |
255 refs = cf->referers->elts; | |
256 for (i = 0; i < cf->referers->nelts; i++ ){ | |
257 | |
258 if (refs[i].name.len > len) { | |
259 continue; | |
260 } | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
261 |
485 | 262 if (refs[i].wildcard) { |
263 for (n = 0; n < len; n++) { | |
264 if (ref[n] == '/' || ref[n] == ':') { | |
265 break; | |
266 } | |
267 | |
268 if (ref[n] != '.') { | |
269 continue; | |
270 } | |
271 | |
272 if (ngx_strncmp(&ref[n], refs[i].name.data, | |
273 refs[i].name.len) == 0) | |
274 { | |
501 | 275 e->sp->value = 0; |
276 e->sp->text.len = 0; | |
277 e->sp->text.data = (u_char *) ""; | |
278 e->sp++; | |
279 | |
485 | 280 return; |
281 } | |
282 } | |
283 | |
284 } else { | |
285 if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0) | |
286 { | |
501 | 287 e->sp->value = 0; |
288 e->sp->text.len = 0; | |
289 e->sp->text.data = (u_char *) ""; | |
290 e->sp++; | |
291 | |
485 | 292 return; |
293 } | |
294 } | |
295 } | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
296 |
501 | 297 e->sp->value = 1; |
298 e->sp->text.len = 1; | |
299 e->sp->text.data = (u_char *) "1"; | |
300 e->sp++; | |
485 | 301 } |
302 | |
303 | |
501 | 304 static ngx_http_variable_value_t * |
305 ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data) | |
306 { | |
307 ngx_http_variable_t *var; | |
308 ngx_http_core_main_conf_t *cmcf; | |
309 | |
310 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
311 | |
312 var = cmcf->variables.elts; | |
313 | |
314 /* | |
315 * the ngx_http_rewrite_module sets variables directly in r->variables, | |
316 * and they should be handle by ngx_http_get_indexed_variable(), | |
317 * so the handler is called only if the variable is not initialized | |
318 */ | |
319 | |
320 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
321 "using uninitialized \"%V\" variable", &var[data].name); | |
322 | |
323 return &ngx_http_rewrite_null_value; | |
324 } | |
325 | |
326 | |
487 | 327 static void * |
328 ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf) | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
329 { |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
330 ngx_http_rewrite_loc_conf_t *conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
331 |
501 | 332 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); |
333 if (conf == NULL) { | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
334 return NGX_CONF_ERROR; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
335 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
336 |
485 | 337 conf->stack_size = NGX_CONF_UNSET_UINT; |
338 conf->log = NGX_CONF_UNSET; | |
339 conf->no_referer = NGX_CONF_UNSET; | |
505 | 340 conf->blocked_referer = NGX_CONF_UNSET; |
485 | 341 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
342 return conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
343 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
344 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
345 |
487 | 346 static char * |
347 ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
348 { |
485 | 349 ngx_http_rewrite_loc_conf_t *prev = parent; |
350 ngx_http_rewrite_loc_conf_t *conf = child; | |
351 | |
509 | 352 uintptr_t *code; |
485 | 353 |
354 ngx_conf_merge_value(conf->log, prev->log, 0); | |
355 ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10); | |
356 | |
357 if (conf->referers == NULL) { | |
358 conf->referers = prev->referers; | |
359 ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0); | |
505 | 360 ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0); |
485 | 361 } |
362 | |
499 | 363 if (conf->no_referer == NGX_CONF_UNSET) { |
364 conf->no_referer = 0; | |
365 } | |
366 | |
505 | 367 if (conf->blocked_referer == NGX_CONF_UNSET) { |
368 conf->blocked_referer = 0; | |
369 } | |
370 | |
485 | 371 if (conf->codes == NULL) { |
372 return NGX_CONF_OK; | |
373 } | |
374 | |
375 if (conf->codes == prev->codes) { | |
376 return NGX_CONF_OK; | |
377 } | |
378 | |
501 | 379 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); |
380 if (code == NULL) { | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
381 return NGX_CONF_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
382 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
383 |
485 | 384 *code = (uintptr_t) NULL; |
385 | |
386 return NGX_CONF_OK; | |
387 } | |
388 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
389 |
509 | 390 static ngx_int_t |
391 ngx_http_rewrite_init(ngx_cycle_t *cycle) | |
392 { | |
393 ngx_http_handler_pt *h; | |
394 ngx_http_core_main_conf_t *cmcf; | |
395 | |
396 cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module); | |
397 | |
398 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); | |
399 if (h == NULL) { | |
400 return NGX_ERROR; | |
401 } | |
402 | |
403 *h = ngx_http_rewrite_handler; | |
404 | |
405 return NGX_OK; | |
406 } | |
407 | |
408 | |
487 | 409 static char * |
410 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 411 { |
412 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
413 | |
509 | 414 ngx_str_t *value, err; |
415 ngx_int_t n; | |
416 ngx_uint_t last; | |
417 ngx_http_script_code_pt *code; | |
418 ngx_http_script_compile_t sc; | |
419 ngx_http_script_regex_code_t *regex; | |
420 ngx_http_script_regex_end_code_t *regex_end; | |
421 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
485 | 422 |
509 | 423 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
424 sizeof(ngx_http_script_regex_code_t)); | |
485 | 425 if (regex == NULL) { |
426 return NGX_CONF_ERROR; | |
427 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
428 |
509 | 429 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
430 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
431 value = cf->args->elts; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
432 |
485 | 433 err.len = NGX_MAX_CONF_ERRSTR; |
434 err.data = errstr; | |
435 | |
436 /* TODO: NGX_REGEX_CASELESS */ | |
437 | |
438 regex->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err); | |
439 | |
440 if (regex->regex == NULL) { | |
441 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | |
442 return NGX_CONF_ERROR; | |
443 } | |
444 | |
509 | 445 regex->code = ngx_http_script_regex_start_code; |
485 | 446 regex->uri = 1; |
447 regex->name = value[1]; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
448 |
509 | 449 if (value[2].data[value[2].len - 1] == '?') { |
450 | |
451 /* the last "?" drops the original arguments */ | |
452 value[2].len--; | |
453 | |
454 } else { | |
455 regex->add_args = 1; | |
456 } | |
457 | |
485 | 458 last = 0; |
459 | |
460 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) { | |
461 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
462 regex->redirect = 1; | |
463 last = 1; | |
464 } | |
465 | |
466 if (cf->args->nelts == 4) { | |
467 if (ngx_strcmp(value[3].data, "last") == 0) { | |
468 last = 1; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
469 |
487 | 470 } else if (ngx_strcmp(value[3].data, "break") == 0) { |
471 regex->break_cycle = 1; | |
472 last = 1; | |
473 | |
485 | 474 } else if (ngx_strcmp(value[3].data, "redirect") == 0) { |
475 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
476 regex->redirect = 1; | |
477 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
478 |
485 | 479 } else if (ngx_strcmp(value[3].data, "permanent") == 0) { |
480 regex->status = NGX_HTTP_MOVED_PERMANENTLY; | |
481 regex->redirect = 1; | |
482 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
483 |
485 | 484 } else { |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
485 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
461 | 486 "invalid parameter \"%V\"", &value[3]); |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
487 return NGX_CONF_ERROR; |
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
488 } |
485 | 489 } |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
490 |
509 | 491 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
485 | 492 |
509 | 493 sc.cf = cf; |
494 sc.source = &value[2]; | |
495 sc.lengths = ®ex->lengths; | |
496 sc.values = &lcf->codes; | |
497 sc.variables = ngx_http_script_variables_count(&value[2]); | |
498 sc.main = regex; | |
499 sc.complete_lengths = 1; | |
500 sc.compile_args = !regex->redirect; | |
485 | 501 |
509 | 502 if (ngx_http_script_compile(&sc) != NGX_OK) { |
503 return NGX_CONF_ERROR; | |
504 } | |
485 | 505 |
509 | 506 regex = sc.main; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
507 |
509 | 508 regex->ncaptures = sc.ncaptures; |
509 regex->size = sc.size; | |
510 regex->args = sc.args; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
511 |
509 | 512 if (sc.variables == 0) { |
513 regex->lengths = NULL; | |
485 | 514 } |
515 | |
516 n = ngx_regex_capture_count(regex->regex); | |
517 | |
501 | 518 if (n < 0) { |
519 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
520 ngx_regex_capture_count_n " failed for " | |
521 "pattern \"%V\"", &value[1]); | |
522 return NGX_CONF_ERROR; | |
523 } | |
524 | |
525 if (regex->ncaptures > (ngx_uint_t) n) { | |
485 | 526 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
527 "pattern \"%V\" has less captures " | |
528 "than referrenced in substitution \"%V\"", | |
529 &value[1], &value[2]); | |
530 return NGX_CONF_ERROR; | |
531 } | |
532 | |
501 | 533 if (regex->ncaptures < (ngx_uint_t) n) { |
534 regex->ncaptures = (ngx_uint_t) n; | |
485 | 535 } |
481 | 536 |
485 | 537 if (regex->ncaptures) { |
538 regex->ncaptures = (regex->ncaptures + 1) * 3; | |
539 | |
515 | 540 if (lcf->captures < regex->ncaptures) { |
541 lcf->captures = regex->ncaptures; | |
542 } | |
509 | 543 } |
544 | |
545 regex_end = ngx_http_script_add_code(lcf->codes, | |
546 sizeof(ngx_http_script_regex_end_code_t), | |
547 ®ex); | |
485 | 548 if (regex_end == NULL) { |
549 return NGX_CONF_ERROR; | |
550 } | |
551 | |
509 | 552 regex_end->code = ngx_http_script_regex_end_code; |
485 | 553 regex_end->uri = regex->uri; |
554 regex_end->args = regex->args; | |
509 | 555 regex_end->add_args = regex->add_args; |
485 | 556 regex_end->redirect = regex->redirect; |
557 | |
558 if (last) { | |
517 | 559 code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex); |
485 | 560 if (code == NULL) { |
561 return NGX_CONF_ERROR; | |
218
05592fd7a436
nginx-0.0.1-2004-01-05-23:55:48 import
Igor Sysoev <igor@sysoev.ru>
parents:
216
diff
changeset
|
562 } |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
563 |
485 | 564 *code = (uintptr_t) NULL; |
565 } | |
566 | |
567 regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
568 - (u_char *) regex; | |
569 | |
570 return NGX_CONF_OK; | |
571 } | |
572 | |
573 | |
487 | 574 static char * |
575 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 576 { |
577 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
578 |
509 | 579 ngx_str_t *value; |
580 ngx_http_script_return_code_t *ret; | |
485 | 581 |
509 | 582 ret = ngx_http_script_start_code(cf->pool, &lcf->codes, |
583 sizeof(ngx_http_script_return_code_t)); | |
485 | 584 if (ret == NULL) { |
585 return NGX_CONF_ERROR; | |
586 } | |
587 | |
588 value = cf->args->elts; | |
589 | |
509 | 590 ret->code = ngx_http_script_return_code; |
485 | 591 ret->null = (uintptr_t) NULL; |
592 | |
593 ret->status = ngx_atoi(value[1].data, value[1].len); | |
594 | |
595 if (ret->status == (uintptr_t) NGX_ERROR) { | |
596 return NGX_CONF_ERROR; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
597 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
598 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
599 return NGX_CONF_OK; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
600 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
601 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
602 |
487 | 603 static char * |
604 ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
605 { |
485 | 606 ngx_http_rewrite_loc_conf_t *lcf = conf; |
607 | |
608 void *mconf; | |
609 char *rv; | |
610 u_char *elts; | |
611 ngx_uint_t i; | |
612 ngx_conf_t save; | |
613 ngx_http_module_t *module; | |
614 ngx_http_conf_ctx_t *ctx, *pctx; | |
615 ngx_http_core_loc_conf_t *clcf, *pclcf, **clcfp; | |
509 | 616 ngx_http_script_if_code_t *if_code; |
485 | 617 ngx_http_rewrite_loc_conf_t *nlcf; |
618 | |
501 | 619 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
620 if (ctx == NULL) { | |
485 | 621 return NGX_CONF_ERROR; |
622 } | |
623 | |
624 pctx = cf->ctx; | |
625 ctx->main_conf = pctx->main_conf; | |
626 ctx->srv_conf = pctx->srv_conf; | |
627 | |
628 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | |
629 if (ctx->loc_conf == NULL) { | |
630 return NGX_CONF_ERROR; | |
631 } | |
632 | |
633 for (i = 0; ngx_modules[i]; i++) { | |
634 if (ngx_modules[i]->type != NGX_HTTP_MODULE) { | |
635 continue; | |
636 } | |
637 | |
638 module = ngx_modules[i]->ctx; | |
639 | |
640 if (module->create_loc_conf) { | |
641 | |
501 | 642 mconf = module->create_loc_conf(cf); |
643 if (mconf == NULL) { | |
485 | 644 return NGX_CONF_ERROR; |
645 } | |
646 | |
647 ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf; | |
648 } | |
649 } | |
650 | |
651 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; | |
652 | |
653 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
654 clcf->loc_conf = ctx->loc_conf; | |
655 clcf->name = pclcf->name; | |
656 clcf->noname = 1; | |
657 | |
658 if (pclcf->locations.elts == NULL) { | |
659 if (ngx_array_init(&pclcf->locations, cf->pool, 4, sizeof(void *)) | |
660 == NGX_ERROR) | |
661 { | |
662 return NGX_CONF_ERROR; | |
663 } | |
664 } | |
665 | |
501 | 666 clcfp = ngx_array_push(&pclcf->locations); |
667 if (clcfp == NULL) { | |
485 | 668 return NGX_CONF_ERROR; |
669 } | |
670 | |
671 *clcfp = clcf; | |
672 | |
673 | |
501 | 674 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { |
485 | 675 return NGX_CONF_ERROR; |
676 } | |
677 | |
509 | 678 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); |
485 | 679 if (if_code == NULL) { |
680 return NULL; | |
681 } | |
682 | |
509 | 683 if_code->code = ngx_http_script_if_code; |
485 | 684 |
685 elts = lcf->codes->elts; | |
686 | |
687 | |
688 /* the inside directives must compile to the same code array */ | |
689 | |
690 nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index]; | |
691 nlcf->codes = lcf->codes; | |
692 | |
693 | |
694 save = *cf; | |
695 cf->ctx = ctx; | |
696 | |
697 if (pclcf->name.len == 0) { | |
698 if_code->loc_conf = NULL; | |
699 cf->cmd_type = NGX_HTTP_SIF_CONF; | |
700 | |
701 } else { | |
702 if_code->loc_conf = ctx->loc_conf; | |
703 cf->cmd_type = NGX_HTTP_LIF_CONF; | |
704 } | |
705 | |
706 rv = ngx_conf_parse(cf, NULL); | |
707 | |
708 *cf = save; | |
709 | |
710 if (rv != NGX_CONF_OK) { | |
711 return rv; | |
712 } | |
713 | |
714 | |
517 | 715 if (lcf->captures < nlcf->captures) { |
716 lcf->captures = nlcf->captures; | |
717 } | |
718 | |
719 | |
485 | 720 if (elts != lcf->codes->elts) { |
509 | 721 if_code = (ngx_http_script_if_code_t *) |
485 | 722 ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); |
723 } | |
724 | |
725 if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
726 - (u_char *) if_code; | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
727 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
728 return NGX_CONF_OK; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
729 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
730 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
731 |
487 | 732 static char * |
501 | 733 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) |
734 { | |
509 | 735 ngx_str_t *value, err; |
515 | 736 ngx_uint_t cur, last, n; |
509 | 737 ngx_http_script_regex_code_t *regex; |
738 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
501 | 739 |
740 value = cf->args->elts; | |
741 last = cf->args->nelts - 1; | |
742 | |
743 if (value[1].len < 1 || value[1].data[0] != '(') { | |
744 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
745 "invalid condition \"%V\"", &value[1]); | |
746 return NGX_CONF_ERROR; | |
747 } | |
748 | |
749 if (value[1].len == 1) { | |
750 cur = 2; | |
751 | |
752 } else { | |
753 cur = 1; | |
754 value[1].len--; | |
755 value[1].data++; | |
756 } | |
757 | |
758 if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') { | |
759 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
760 "invalid condition \"%V\"", &value[last]); | |
761 return NGX_CONF_ERROR; | |
762 } | |
763 | |
764 if (value[last].len == 1) { | |
765 last--; | |
766 | |
767 } else { | |
768 value[last].len--; | |
769 value[last].data[value[last].len] = '\0'; | |
770 } | |
771 | |
772 if (value[cur].len > 1 && value[cur].data[0] == '$') { | |
773 | |
774 if (cur != last && cur + 2 != last) { | |
775 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
776 "invalid condition \"%V\"", &value[cur]); | |
777 return NGX_CONF_ERROR; | |
778 } | |
779 | |
780 if (ngx_http_rewrite_variable(cf, lcf, &value[cur])!= NGX_CONF_OK) { | |
781 return NGX_CONF_ERROR; | |
782 } | |
783 | |
784 if (cur == last) { | |
785 return NGX_CONF_OK; | |
786 } | |
787 | |
788 cur++; | |
789 | |
790 if ((value[cur].len == 1 && value[cur].data[0] != '~') | |
791 || (value[cur].len == 2 | |
792 && value[cur].data[0] != '~' && value[cur].data[1] != '*')) | |
793 { | |
794 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
795 "unexpected \"%V\" in condition", &value[cur]); | |
796 return NGX_CONF_ERROR; | |
797 } | |
798 | |
509 | 799 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
800 sizeof(ngx_http_script_regex_code_t)); | |
501 | 801 if (regex == NULL) { |
802 return NGX_CONF_ERROR; | |
803 } | |
804 | |
509 | 805 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
806 | |
501 | 807 err.len = NGX_MAX_CONF_ERRSTR; |
808 err.data = errstr; | |
809 | |
810 regex->regex = ngx_regex_compile(&value[last], | |
811 (value[cur].len == 2) ? NGX_REGEX_CASELESS : 0, | |
812 cf->pool, &err); | |
813 | |
814 if (regex->regex == NULL) { | |
815 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); | |
816 return NGX_CONF_ERROR; | |
817 } | |
818 | |
509 | 819 regex->code = ngx_http_script_regex_start_code; |
820 regex->next = sizeof(ngx_http_script_regex_code_t); | |
501 | 821 regex->test = 1; |
822 regex->name = value[last]; | |
823 | |
515 | 824 n = ngx_regex_capture_count(regex->regex); |
825 | |
826 if (n) { | |
827 regex->ncaptures = (n + 1) * 3; | |
828 | |
829 if (lcf->captures < regex->ncaptures) { | |
830 lcf->captures = regex->ncaptures; | |
831 } | |
832 } | |
833 | |
501 | 834 return NGX_CONF_OK; |
835 } | |
836 | |
837 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
838 "invalid condition \"%V\"", &value[cur]); | |
839 | |
840 return NGX_CONF_ERROR; | |
841 } | |
842 | |
843 | |
844 static char * | |
845 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
846 ngx_str_t *value) | |
847 { | |
509 | 848 ngx_int_t index; |
849 ngx_http_script_code_pt *code; | |
850 ngx_http_script_var_code_t *var_code; | |
501 | 851 |
852 value->len--; | |
853 value->data++; | |
854 | |
855 if (value->len == sizeof("invalid_referer") - 1 | |
856 && ngx_strncmp(value->data, "invalid_referer", | |
857 sizeof("invalid_referer") - 1) == 0) | |
858 { | |
509 | 859 code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
860 sizeof(ngx_http_script_code_pt)); | |
501 | 861 if (code == NULL) { |
862 return NGX_CONF_ERROR; | |
863 } | |
864 | |
865 *code = ngx_http_rewrite_invalid_referer_code; | |
866 | |
867 } else { | |
509 | 868 index = ngx_http_get_variable_index(cf, value); |
501 | 869 |
509 | 870 if (index == NGX_ERROR) { |
501 | 871 return NGX_CONF_ERROR; |
872 } | |
873 | |
509 | 874 var_code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
875 sizeof(ngx_http_script_var_code_t)); | |
501 | 876 if (var_code == NULL) { |
877 return NGX_CONF_ERROR; | |
878 } | |
879 | |
509 | 880 var_code->code = ngx_http_script_var_code; |
881 var_code->index = index; | |
501 | 882 } |
883 | |
884 return NGX_CONF_OK; | |
885 } | |
886 | |
887 | |
888 static char * | |
487 | 889 ngx_http_rewrite_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
890 { |
485 | 891 ngx_http_rewrite_loc_conf_t *lcf = conf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
892 |
485 | 893 ngx_uint_t i, server_names; |
894 ngx_str_t *value; | |
895 ngx_http_server_name_t *sn; | |
896 ngx_http_core_srv_conf_t *cscf; | |
897 ngx_http_rewrite_referer_t *ref; | |
898 | |
899 cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
900 |
485 | 901 if (lcf->referers == NULL) { |
902 lcf->referers = ngx_array_create(cf->pool, | |
903 cf->args->nelts + cscf->server_names.nelts, | |
904 sizeof(ngx_http_rewrite_referer_t)); | |
905 if (lcf->referers == NULL) { | |
906 return NGX_CONF_ERROR; | |
907 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
908 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
909 |
485 | 910 value = cf->args->elts; |
911 server_names = 0; | |
912 | |
913 for (i = 1; i < cf->args->nelts; i++) { | |
914 if (value[i].len == 0) { | |
915 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
916 "invalid referer \"%V\"", &value[i]); | |
917 return NGX_CONF_ERROR; | |
918 } | |
919 | |
920 if (ngx_strcmp(value[i].data, "none") == 0) { | |
921 lcf->no_referer = 1; | |
922 continue; | |
923 } | |
924 | |
505 | 925 if (ngx_strcmp(value[i].data, "blocked") == 0) { |
926 lcf->blocked_referer = 1; | |
927 continue; | |
928 } | |
929 | |
485 | 930 if (ngx_strcmp(value[i].data, "server_names") == 0) { |
931 server_names = 1; | |
932 continue; | |
933 } | |
934 | |
501 | 935 ref = ngx_array_push(lcf->referers); |
936 if (ref == NULL) { | |
485 | 937 return NGX_CONF_ERROR; |
938 } | |
939 | |
940 if (value[i].data[0] != '*') { | |
941 ref->name = value[i]; | |
942 ref->wildcard = 0; | |
943 continue; | |
944 } | |
945 | |
946 if (value[i].data[1] != '.') { | |
947 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
948 "invalid wildcard referer \"%V\"", &value[i]); | |
949 return NGX_CONF_ERROR; | |
950 } | |
951 | |
952 ref->name.len = value[i].len - 1; | |
953 ref->name.data = value[i].data + 1; | |
954 ref->wildcard = 1; | |
955 } | |
956 | |
957 if (!server_names) { | |
958 return NGX_CONF_OK; | |
959 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
960 |
485 | 961 sn = cscf->server_names.elts; |
962 for (i = 0; i < cscf->server_names.nelts; i++) { | |
501 | 963 ref = ngx_array_push(lcf->referers); |
964 if (ref == NULL) { | |
485 | 965 return NGX_CONF_ERROR; |
966 } | |
967 | |
968 ref->name.len = sn[i].name.len + 1; | |
501 | 969 ref->name.data = ngx_palloc(cf->pool, ref->name.len); |
970 if (ref->name.data == NULL) { | |
485 | 971 return NGX_CONF_ERROR; |
972 } | |
973 | |
974 ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len); | |
975 ref->name.data[sn[i].name.len] = '/'; | |
976 ref->wildcard = sn[i].wildcard; | |
977 } | |
978 | |
979 return NGX_CONF_OK; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
980 } |
485 | 981 |
982 | |
501 | 983 static char * |
984 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
985 { | |
986 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
987 | |
515 | 988 ngx_int_t n, index; |
989 ngx_str_t *value; | |
990 ngx_http_variable_t *v; | |
991 ngx_http_script_compile_t sc; | |
992 ngx_http_script_var_code_t *var; | |
993 ngx_http_script_value_code_t *val; | |
994 ngx_http_script_complex_value_code_t *complex; | |
501 | 995 |
996 value = cf->args->elts; | |
997 | |
998 if (value[1].data[0] != '$') { | |
999 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
1000 "invalid variable name \"%V\"", &value[1]); | |
1001 return NGX_CONF_ERROR; | |
1002 } | |
1003 | |
1004 value[1].len--; | |
1005 value[1].data++; | |
1006 | |
509 | 1007 v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE); |
501 | 1008 if (v == NULL) { |
1009 return NGX_CONF_ERROR; | |
1010 } | |
1011 | |
509 | 1012 index = ngx_http_get_variable_index(cf, &value[1]); |
1013 if (index == NGX_ERROR) { | |
1014 return NGX_CONF_ERROR; | |
1015 } | |
501 | 1016 |
509 | 1017 v->handler = ngx_http_rewrite_var; |
1018 v->data = index; | |
1019 | |
515 | 1020 n = ngx_http_script_variables_count(&value[2]); |
1021 | |
1022 if (n == 0) { | |
1023 val = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
1024 sizeof(ngx_http_script_value_code_t)); | |
1025 if (val == NULL) { | |
1026 return NGX_CONF_ERROR; | |
1027 } | |
501 | 1028 |
515 | 1029 n = ngx_atoi(value[2].data, value[2].len); |
1030 | |
1031 if (n == NGX_ERROR) { | |
1032 n = 0; | |
1033 } | |
1034 | |
1035 val->code = ngx_http_script_value_code; | |
1036 val->value = (uintptr_t) n; | |
1037 val->text_len = (uintptr_t) value[2].len; | |
1038 val->text_data = (uintptr_t) value[2].data; | |
501 | 1039 |
515 | 1040 } else { |
1041 complex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
1042 sizeof(ngx_http_script_complex_value_code_t)); | |
1043 if (complex == NULL) { | |
1044 return NGX_CONF_ERROR; | |
1045 } | |
1046 | |
1047 complex->code = ngx_http_script_complex_value_code; | |
1048 complex->lengths = NULL; | |
1049 | |
1050 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
501 | 1051 |
515 | 1052 sc.cf = cf; |
1053 sc.source = &value[2]; | |
1054 sc.lengths = &complex->lengths; | |
1055 sc.values = &lcf->codes; | |
1056 sc.variables = n; | |
1057 sc.complete_lengths = 1; | |
1058 | |
1059 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1060 return NGX_CONF_ERROR; | |
1061 } | |
1062 } | |
501 | 1063 |
509 | 1064 var = ngx_http_script_start_code(cf->pool, &lcf->codes, |
1065 sizeof(ngx_http_script_var_code_t)); | |
501 | 1066 if (var == NULL) { |
1067 return NGX_CONF_ERROR; | |
1068 } | |
1069 | |
509 | 1070 var->code = ngx_http_script_set_var_code; |
1071 var->index = (uintptr_t) index; | |
501 | 1072 |
1073 return NGX_CONF_OK; | |
1074 } |