Mercurial > hg > nginx-quic
annotate src/http/modules/ngx_http_rewrite_module.c @ 7401:a7ff19afbb14
Negative size buffers detection.
In the past, there were several security issues which resulted in
worker process memory disclosure due to buffers with negative size.
It looks reasonable to check for such buffers in various places,
much like we already check for zero size buffers.
While here, removed "#if 1 / #endif" around zero size buffer checks.
It looks highly unlikely that we'll disable these checks anytime soon.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Mon, 26 Nov 2018 18:29:56 +0300 |
parents | b64adc956643 |
children | db8df9cd84c8 |
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 |
4412 | 4 * Copyright (C) Nginx, Inc. |
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
|
5 */ |
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
|
6 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
7 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
8 #include <ngx_config.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
9 #include <ngx_core.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
10 #include <ngx_http.h> |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
11 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
12 |
485 | 13 typedef struct { |
577 | 14 ngx_array_t *codes; /* uintptr_t */ |
485 | 15 |
577 | 16 ngx_uint_t stack_size; |
485 | 17 |
577 | 18 ngx_flag_t log; |
635 | 19 ngx_flag_t uninitialized_variable_warn; |
485 | 20 } 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
|
21 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
22 |
485 | 23 static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf); |
24 static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, | |
487 | 25 void *parent, void *child); |
681 | 26 static ngx_int_t ngx_http_rewrite_init(ngx_conf_t *cf); |
485 | 27 static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
28 static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, | |
487 | 29 void *conf); |
527 | 30 static char *ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, |
31 void *conf); | |
485 | 32 static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, |
487 | 33 void *conf); |
501 | 34 static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf, |
35 ngx_http_rewrite_loc_conf_t *lcf); | |
36 static char *ngx_http_rewrite_variable(ngx_conf_t *cf, | |
37 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
509 | 38 static char *ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, |
501 | 39 void *conf); |
577 | 40 static char * ngx_http_rewrite_value(ngx_conf_t *cf, |
41 ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value); | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
42 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
43 |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
44 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
|
45 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
46 { ngx_string("rewrite"), |
485 | 47 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |
48 |NGX_CONF_TAKE23, | |
49 ngx_http_rewrite, | |
50 NGX_HTTP_LOC_CONF_OFFSET, | |
51 0, | |
52 NULL }, | |
53 | |
54 { ngx_string("return"), | |
55 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
3633 | 56 |NGX_CONF_TAKE12, |
485 | 57 ngx_http_rewrite_return, |
58 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
|
59 0, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
60 NULL }, |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
61 |
527 | 62 { ngx_string("break"), |
63 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
64 |NGX_CONF_NOARGS, | |
65 ngx_http_rewrite_break, | |
66 NGX_HTTP_LOC_CONF_OFFSET, | |
67 0, | |
68 NULL }, | |
69 | |
485 | 70 { ngx_string("if"), |
71 NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE, | |
72 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
|
73 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
|
74 0, |
485 | 75 NULL }, |
76 | |
501 | 77 { ngx_string("set"), |
78 NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF | |
79 |NGX_CONF_TAKE2, | |
80 ngx_http_rewrite_set, | |
81 NGX_HTTP_LOC_CONF_OFFSET, | |
82 0, | |
83 NULL }, | |
84 | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
85 { ngx_string("rewrite_log"), |
635 | 86 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF |
87 |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, | |
325
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
88 ngx_conf_set_flag_slot, |
485 | 89 NGX_HTTP_LOC_CONF_OFFSET, |
90 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
|
91 NULL }, |
7c3323909107
nginx-0.0.3-2004-04-23-20:50:51 import
Igor Sysoev <igor@sysoev.ru>
parents:
290
diff
changeset
|
92 |
635 | 93 { ngx_string("uninitialized_variable_warn"), |
94 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF | |
95 |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, | |
96 ngx_conf_set_flag_slot, | |
97 NGX_HTTP_LOC_CONF_OFFSET, | |
98 offsetof(ngx_http_rewrite_loc_conf_t, uninitialized_variable_warn), | |
99 NULL }, | |
100 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
101 ngx_null_command |
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 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
104 |
667 | 105 static ngx_http_module_t ngx_http_rewrite_module_ctx = { |
509 | 106 NULL, /* preconfiguration */ |
681 | 107 ngx_http_rewrite_init, /* postconfiguration */ |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
108 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
109 NULL, /* create main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
110 NULL, /* init main configuration */ |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
111 |
485 | 112 NULL, /* create server configuration */ |
113 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
|
114 |
4499
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
115 ngx_http_rewrite_create_loc_conf, /* create location configuration */ |
778ef9c3fd2d
Fixed spelling in single-line comments.
Ruslan Ermilov <ru@nginx.com>
parents:
4412
diff
changeset
|
116 ngx_http_rewrite_merge_loc_conf /* merge location configuration */ |
216
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 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
119 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
120 ngx_module_t ngx_http_rewrite_module = { |
509 | 121 NGX_MODULE_V1, |
577 | 122 &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
|
123 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
|
124 NGX_HTTP_MODULE, /* module type */ |
541 | 125 NULL, /* init master */ |
681 | 126 NULL, /* init module */ |
541 | 127 NULL, /* init process */ |
128 NULL, /* init thread */ | |
129 NULL, /* exit thread */ | |
130 NULL, /* exit process */ | |
131 NULL, /* exit master */ | |
132 NGX_MODULE_V1_PADDING | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
133 }; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
134 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
135 |
487 | 136 static ngx_int_t |
137 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
|
138 { |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
139 ngx_int_t index; |
509 | 140 ngx_http_script_code_pt code; |
141 ngx_http_script_engine_t *e; | |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
142 ngx_http_core_srv_conf_t *cscf; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
143 ngx_http_core_main_conf_t *cmcf; |
635 | 144 ngx_http_rewrite_loc_conf_t *rlcf; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
145 |
4208
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
146 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
147 cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
148 index = cmcf->phase_engine.location_rewrite_index; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
149 |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
150 if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) { |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
151 /* skipping location rewrite phase for server null location */ |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
152 return NGX_DECLINED; |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
153 } |
470462cfa31b
Skipping location rewrite phase for server null location.
Igor Sysoev <igor@sysoev.ru>
parents:
4147
diff
changeset
|
154 |
635 | 155 rlcf = 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
|
156 |
635 | 157 if (rlcf->codes == NULL) { |
485 | 158 return NGX_DECLINED; |
159 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
160 |
509 | 161 e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); |
501 | 162 if (e == NULL) { |
485 | 163 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
164 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
165 |
509 | 166 e->sp = ngx_pcalloc(r->pool, |
635 | 167 rlcf->stack_size * sizeof(ngx_http_variable_value_t)); |
485 | 168 if (e->sp == NULL) { |
169 return NGX_HTTP_INTERNAL_SERVER_ERROR; | |
170 } | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
171 |
635 | 172 e->ip = rlcf->codes->elts; |
509 | 173 e->request = r; |
485 | 174 e->quote = 1; |
635 | 175 e->log = rlcf->log; |
485 | 176 e->status = NGX_DECLINED; |
177 | |
178 while (*(uintptr_t *) e->ip) { | |
509 | 179 code = *(ngx_http_script_code_pt *) e->ip; |
485 | 180 code(e); |
181 } | |
182 | |
7355
b64adc956643
Rewrite: removed r->err_status special handling (ticket #1634).
Maxim Dounin <mdounin@mdounin.ru>
parents:
6899
diff
changeset
|
183 return e->status; |
485 | 184 } |
185 | |
186 | |
573 | 187 static ngx_int_t |
188 ngx_http_rewrite_var(ngx_http_request_t *r, ngx_http_variable_value_t *v, | |
189 uintptr_t data) | |
501 | 190 { |
635 | 191 ngx_http_variable_t *var; |
192 ngx_http_core_main_conf_t *cmcf; | |
193 ngx_http_rewrite_loc_conf_t *rlcf; | |
194 | |
195 rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); | |
196 | |
197 if (rlcf->uninitialized_variable_warn == 0) { | |
198 *v = ngx_http_variable_null_value; | |
199 return NGX_OK; | |
200 } | |
501 | 201 |
202 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); | |
203 | |
204 var = cmcf->variables.elts; | |
205 | |
206 /* | |
207 * the ngx_http_rewrite_module sets variables directly in r->variables, | |
519 | 208 * and they should be handled by ngx_http_get_indexed_variable(), |
501 | 209 * so the handler is called only if the variable is not initialized |
210 */ | |
211 | |
635 | 212 ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, |
501 | 213 "using uninitialized \"%V\" variable", &var[data].name); |
214 | |
577 | 215 *v = ngx_http_variable_null_value; |
573 | 216 |
217 return NGX_OK; | |
501 | 218 } |
219 | |
220 | |
487 | 221 static void * |
222 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
|
223 { |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
224 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
|
225 |
501 | 226 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)); |
227 if (conf == NULL) { | |
2912
c7d57b539248
return NULL instead of NGX_CONF_ERROR on a create conf failure
Igor Sysoev <igor@sysoev.ru>
parents:
2547
diff
changeset
|
228 return NULL; |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
229 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
230 |
485 | 231 conf->stack_size = NGX_CONF_UNSET_UINT; |
232 conf->log = NGX_CONF_UNSET; | |
635 | 233 conf->uninitialized_variable_warn = NGX_CONF_UNSET; |
485 | 234 |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
235 return conf; |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
236 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
237 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
238 |
487 | 239 static char * |
240 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
|
241 { |
485 | 242 ngx_http_rewrite_loc_conf_t *prev = parent; |
243 ngx_http_rewrite_loc_conf_t *conf = child; | |
244 | |
509 | 245 uintptr_t *code; |
485 | 246 |
247 ngx_conf_merge_value(conf->log, prev->log, 0); | |
635 | 248 ngx_conf_merge_value(conf->uninitialized_variable_warn, |
249 prev->uninitialized_variable_warn, 1); | |
663 | 250 ngx_conf_merge_uint_value(conf->stack_size, prev->stack_size, 10); |
485 | 251 |
252 if (conf->codes == NULL) { | |
253 return NGX_CONF_OK; | |
254 } | |
255 | |
256 if (conf->codes == prev->codes) { | |
257 return NGX_CONF_OK; | |
258 } | |
259 | |
501 | 260 code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)); |
261 if (code == NULL) { | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
262 return NGX_CONF_ERROR; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
263 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
264 |
485 | 265 *code = (uintptr_t) NULL; |
266 | |
267 return NGX_CONF_OK; | |
268 } | |
269 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
270 |
509 | 271 static ngx_int_t |
681 | 272 ngx_http_rewrite_init(ngx_conf_t *cf) |
577 | 273 { |
509 | 274 ngx_http_handler_pt *h; |
275 ngx_http_core_main_conf_t *cmcf; | |
276 | |
681 | 277 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); |
509 | 278 |
573 | 279 h = ngx_array_push(&cmcf->phases[NGX_HTTP_SERVER_REWRITE_PHASE].handlers); |
280 if (h == NULL) { | |
281 return NGX_ERROR; | |
282 } | |
283 | |
284 *h = ngx_http_rewrite_handler; | |
285 | |
509 | 286 h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers); |
287 if (h == NULL) { | |
288 return NGX_ERROR; | |
289 } | |
290 | |
291 *h = ngx_http_rewrite_handler; | |
292 | |
293 return NGX_OK; | |
577 | 294 } |
509 | 295 |
296 | |
487 | 297 static char * |
298 ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 299 { |
577 | 300 ngx_http_rewrite_loc_conf_t *lcf = conf; |
301 | |
3325 | 302 ngx_str_t *value; |
509 | 303 ngx_uint_t last; |
3325 | 304 ngx_regex_compile_t rc; |
509 | 305 ngx_http_script_code_pt *code; |
306 ngx_http_script_compile_t sc; | |
307 ngx_http_script_regex_code_t *regex; | |
308 ngx_http_script_regex_end_code_t *regex_end; | |
309 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
485 | 310 |
509 | 311 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, |
312 sizeof(ngx_http_script_regex_code_t)); | |
485 | 313 if (regex == NULL) { |
314 return NGX_CONF_ERROR; | |
315 } | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
316 |
509 | 317 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
318 | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
319 value = cf->args->elts; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
320 |
3325 | 321 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
322 | |
323 rc.pattern = value[1]; | |
324 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
325 rc.err.data = errstr; | |
485 | 326 |
327 /* TODO: NGX_REGEX_CASELESS */ | |
328 | |
3325 | 329 regex->regex = ngx_http_regex_compile(cf, &rc); |
485 | 330 if (regex->regex == NULL) { |
331 return NGX_CONF_ERROR; | |
332 } | |
333 | |
509 | 334 regex->code = ngx_http_script_regex_start_code; |
485 | 335 regex->uri = 1; |
336 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
|
337 |
509 | 338 if (value[2].data[value[2].len - 1] == '?') { |
339 | |
340 /* the last "?" drops the original arguments */ | |
341 value[2].len--; | |
342 | |
343 } else { | |
344 regex->add_args = 1; | |
345 } | |
346 | |
485 | 347 last = 0; |
348 | |
3524
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
349 if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0 |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
350 || ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0 |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
351 || ngx_strncmp(value[2].data, "$scheme", sizeof("$scheme") - 1) == 0) |
ca24774c16e3
autodetect redirect if URI is rewritten to a string starting with $scheme
Igor Sysoev <igor@sysoev.ru>
parents:
3325
diff
changeset
|
352 { |
2054
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
353 regex->status = NGX_HTTP_MOVED_TEMPORARILY; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
354 regex->redirect = 1; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
355 last = 1; |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
356 } |
989176d3ffc5
auto detect https redirect in rewrite
Igor Sysoev <igor@sysoev.ru>
parents:
2027
diff
changeset
|
357 |
485 | 358 if (cf->args->nelts == 4) { |
359 if (ngx_strcmp(value[3].data, "last") == 0) { | |
360 last = 1; | |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
361 |
487 | 362 } else if (ngx_strcmp(value[3].data, "break") == 0) { |
363 regex->break_cycle = 1; | |
364 last = 1; | |
365 | |
485 | 366 } else if (ngx_strcmp(value[3].data, "redirect") == 0) { |
367 regex->status = NGX_HTTP_MOVED_TEMPORARILY; | |
368 regex->redirect = 1; | |
369 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
370 |
485 | 371 } else if (ngx_strcmp(value[3].data, "permanent") == 0) { |
372 regex->status = NGX_HTTP_MOVED_PERMANENTLY; | |
373 regex->redirect = 1; | |
374 last = 1; | |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
375 |
485 | 376 } else { |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
377 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
461 | 378 "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
|
379 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
|
380 } |
485 | 381 } |
326
8733703a37f3
nginx-0.0.3-2004-04-26-00:13:21 import
Igor Sysoev <igor@sysoev.ru>
parents:
325
diff
changeset
|
382 |
509 | 383 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); |
485 | 384 |
509 | 385 sc.cf = cf; |
386 sc.source = &value[2]; | |
387 sc.lengths = ®ex->lengths; | |
388 sc.values = &lcf->codes; | |
389 sc.variables = ngx_http_script_variables_count(&value[2]); | |
390 sc.main = regex; | |
391 sc.complete_lengths = 1; | |
392 sc.compile_args = !regex->redirect; | |
485 | 393 |
509 | 394 if (ngx_http_script_compile(&sc) != NGX_OK) { |
395 return NGX_CONF_ERROR; | |
396 } | |
485 | 397 |
509 | 398 regex = sc.main; |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
399 |
509 | 400 regex->size = sc.size; |
401 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
|
402 |
641 | 403 if (sc.variables == 0 && !sc.dup_capture) { |
509 | 404 regex->lengths = NULL; |
485 | 405 } |
406 | |
509 | 407 regex_end = ngx_http_script_add_code(lcf->codes, |
408 sizeof(ngx_http_script_regex_end_code_t), | |
409 ®ex); | |
485 | 410 if (regex_end == NULL) { |
411 return NGX_CONF_ERROR; | |
412 } | |
413 | |
509 | 414 regex_end->code = ngx_http_script_regex_end_code; |
485 | 415 regex_end->uri = regex->uri; |
416 regex_end->args = regex->args; | |
509 | 417 regex_end->add_args = regex->add_args; |
485 | 418 regex_end->redirect = regex->redirect; |
419 | |
420 if (last) { | |
517 | 421 code = ngx_http_script_add_code(lcf->codes, sizeof(uintptr_t), ®ex); |
485 | 422 if (code == NULL) { |
423 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
|
424 } |
216
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
425 |
3184 | 426 *code = NULL; |
485 | 427 } |
428 | |
429 regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
430 - (u_char *) regex; | |
431 | |
432 return NGX_CONF_OK; | |
433 } | |
434 | |
435 | |
487 | 436 static char * |
437 ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
485 | 438 { |
577 | 439 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
|
440 |
3633 | 441 u_char *p; |
442 ngx_str_t *value, *v; | |
443 ngx_http_script_return_code_t *ret; | |
444 ngx_http_compile_complex_value_t ccv; | |
485 | 445 |
509 | 446 ret = ngx_http_script_start_code(cf->pool, &lcf->codes, |
447 sizeof(ngx_http_script_return_code_t)); | |
485 | 448 if (ret == NULL) { |
449 return NGX_CONF_ERROR; | |
450 } | |
451 | |
452 value = cf->args->elts; | |
453 | |
3633 | 454 ngx_memzero(ret, sizeof(ngx_http_script_return_code_t)); |
455 | |
509 | 456 ret->code = ngx_http_script_return_code; |
485 | 457 |
3633 | 458 p = value[1].data; |
459 | |
460 ret->status = ngx_atoi(p, value[1].len); | |
485 | 461 |
462 if (ret->status == (uintptr_t) NGX_ERROR) { | |
3633 | 463 |
464 if (cf->args->nelts == 2 | |
465 && (ngx_strncmp(p, "http://", sizeof("http://") - 1) == 0 | |
466 || ngx_strncmp(p, "https://", sizeof("https://") - 1) == 0 | |
467 || ngx_strncmp(p, "$scheme", sizeof("$scheme") - 1) == 0)) | |
468 { | |
469 ret->status = NGX_HTTP_MOVED_TEMPORARILY; | |
470 v = &value[1]; | |
471 | |
472 } else { | |
473 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
474 "invalid return code \"%V\"", &value[1]); | |
475 return NGX_CONF_ERROR; | |
476 } | |
477 | |
478 } else { | |
479 | |
4636
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
480 if (ret->status > 999) { |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
481 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
482 "invalid return code \"%V\"", &value[1]); |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
483 return NGX_CONF_ERROR; |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
484 } |
ed957e0daeb4
Capped the status code that may be returned with "return" and "try_files".
Ruslan Ermilov <ru@nginx.com>
parents:
4499
diff
changeset
|
485 |
3633 | 486 if (cf->args->nelts == 2) { |
487 return NGX_CONF_OK; | |
488 } | |
489 | |
490 v = &value[2]; | |
491 } | |
492 | |
493 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
494 | |
495 ccv.cf = cf; | |
496 ccv.value = v; | |
497 ccv.complex_value = &ret->text; | |
498 | |
499 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
485 | 500 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
|
501 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
502 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
503 return NGX_CONF_OK; |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
504 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
505 |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
506 |
487 | 507 static char * |
527 | 508 ngx_http_rewrite_break(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) |
509 { | |
510 ngx_http_rewrite_loc_conf_t *lcf = conf; | |
511 | |
512 ngx_http_script_code_pt *code; | |
513 | |
514 code = ngx_http_script_start_code(cf->pool, &lcf->codes, sizeof(uintptr_t)); | |
515 if (code == NULL) { | |
516 return NGX_CONF_ERROR; | |
517 } | |
518 | |
519 *code = ngx_http_script_break_code; | |
520 | |
521 return NGX_CONF_OK; | |
522 } | |
523 | |
524 | |
525 static char * | |
487 | 526 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
|
527 { |
577 | 528 ngx_http_rewrite_loc_conf_t *lcf = conf; |
485 | 529 |
530 void *mconf; | |
531 char *rv; | |
532 u_char *elts; | |
533 ngx_uint_t i; | |
534 ngx_conf_t save; | |
535 ngx_http_module_t *module; | |
536 ngx_http_conf_ctx_t *ctx, *pctx; | |
2027 | 537 ngx_http_core_loc_conf_t *clcf, *pclcf; |
509 | 538 ngx_http_script_if_code_t *if_code; |
485 | 539 ngx_http_rewrite_loc_conf_t *nlcf; |
540 | |
501 | 541 ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)); |
542 if (ctx == NULL) { | |
485 | 543 return NGX_CONF_ERROR; |
544 } | |
545 | |
546 pctx = cf->ctx; | |
547 ctx->main_conf = pctx->main_conf; | |
577 | 548 ctx->srv_conf = pctx->srv_conf; |
485 | 549 |
550 ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module); | |
551 if (ctx->loc_conf == NULL) { | |
552 return NGX_CONF_ERROR; | |
553 } | |
554 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
555 for (i = 0; cf->cycle->modules[i]; i++) { |
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
556 if (cf->cycle->modules[i]->type != NGX_HTTP_MODULE) { |
485 | 557 continue; |
558 } | |
559 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
560 module = cf->cycle->modules[i]->ctx; |
577 | 561 |
485 | 562 if (module->create_loc_conf) { |
563 | |
501 | 564 mconf = module->create_loc_conf(cf); |
565 if (mconf == NULL) { | |
6474 | 566 return NGX_CONF_ERROR; |
485 | 567 } |
568 | |
6379
cf5e822cf470
Dynamic modules: changed ngx_modules to cycle->modules.
Maxim Dounin <mdounin@mdounin.ru>
parents:
6244
diff
changeset
|
569 ctx->loc_conf[cf->cycle->modules[i]->ctx_index] = mconf; |
485 | 570 } |
571 } | |
572 | |
573 pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index]; | |
574 | |
575 clcf = ctx->loc_conf[ngx_http_core_module.ctx_index]; | |
576 clcf->loc_conf = ctx->loc_conf; | |
577 clcf->name = pclcf->name; | |
578 clcf->noname = 1; | |
579 | |
2027 | 580 if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) { |
485 | 581 return NGX_CONF_ERROR; |
582 } | |
583 | |
501 | 584 if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) { |
485 | 585 return NGX_CONF_ERROR; |
586 } | |
587 | |
509 | 588 if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_script_if_code_t)); |
485 | 589 if (if_code == NULL) { |
3001 | 590 return NGX_CONF_ERROR; |
485 | 591 } |
592 | |
509 | 593 if_code->code = ngx_http_script_if_code; |
485 | 594 |
595 elts = lcf->codes->elts; | |
596 | |
597 | |
631 | 598 /* the inner directives must be compiled to the same code array */ |
485 | 599 |
600 nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index]; | |
601 nlcf->codes = lcf->codes; | |
602 | |
603 | |
604 save = *cf; | |
605 cf->ctx = ctx; | |
606 | |
6244
055d1f63960a
Fixed segfault with incorrect location nesting.
Maxim Dounin <mdounin@mdounin.ru>
parents:
5816
diff
changeset
|
607 if (cf->cmd_type == NGX_HTTP_SRV_CONF) { |
485 | 608 if_code->loc_conf = NULL; |
609 cf->cmd_type = NGX_HTTP_SIF_CONF; | |
610 | |
611 } else { | |
612 if_code->loc_conf = ctx->loc_conf; | |
613 cf->cmd_type = NGX_HTTP_LIF_CONF; | |
614 } | |
615 | |
616 rv = ngx_conf_parse(cf, NULL); | |
617 | |
618 *cf = save; | |
619 | |
620 if (rv != NGX_CONF_OK) { | |
621 return rv; | |
622 } | |
623 | |
624 | |
625 if (elts != lcf->codes->elts) { | |
509 | 626 if_code = (ngx_http_script_if_code_t *) |
485 | 627 ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts)); |
628 } | |
629 | |
630 if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts | |
631 - (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
|
632 |
555 | 633 /* the code array belong to parent block */ |
634 | |
635 nlcf->codes = NULL; | |
636 | |
437
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
637 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
|
638 } |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
639 |
470270fa84d2
nginx-0.0.12-2004-09-23-20:39:34 import
Igor Sysoev <igor@sysoev.ru>
parents:
396
diff
changeset
|
640 |
487 | 641 static char * |
501 | 642 ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf) |
643 { | |
631 | 644 u_char *p; |
645 size_t len; | |
3325 | 646 ngx_str_t *value; |
647 ngx_uint_t cur, last; | |
648 ngx_regex_compile_t rc; | |
577 | 649 ngx_http_script_code_pt *code; |
631 | 650 ngx_http_script_file_code_t *fop; |
509 | 651 ngx_http_script_regex_code_t *regex; |
652 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
501 | 653 |
654 value = cf->args->elts; | |
655 last = cf->args->nelts - 1; | |
656 | |
657 if (value[1].len < 1 || value[1].data[0] != '(') { | |
658 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
659 "invalid condition \"%V\"", &value[1]); | |
660 return NGX_CONF_ERROR; | |
661 } | |
662 | |
663 if (value[1].len == 1) { | |
664 cur = 2; | |
665 | |
666 } else { | |
667 cur = 1; | |
668 value[1].len--; | |
669 value[1].data++; | |
670 } | |
671 | |
672 if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') { | |
673 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
674 "invalid condition \"%V\"", &value[last]); | |
675 return NGX_CONF_ERROR; | |
676 } | |
677 | |
678 if (value[last].len == 1) { | |
679 last--; | |
680 | |
681 } else { | |
682 value[last].len--; | |
683 value[last].data[value[last].len] = '\0'; | |
684 } | |
685 | |
631 | 686 len = value[cur].len; |
687 p = value[cur].data; | |
688 | |
689 if (len > 1 && p[0] == '$') { | |
501 | 690 |
691 if (cur != last && cur + 2 != last) { | |
692 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
631 | 693 "invalid condition \"%V\"", &value[cur]); |
501 | 694 return NGX_CONF_ERROR; |
695 } | |
696 | |
577 | 697 if (ngx_http_rewrite_variable(cf, lcf, &value[cur]) != NGX_CONF_OK) { |
501 | 698 return NGX_CONF_ERROR; |
699 } | |
700 | |
701 if (cur == last) { | |
702 return NGX_CONF_OK; | |
703 } | |
704 | |
705 cur++; | |
706 | |
631 | 707 len = value[cur].len; |
708 p = value[cur].data; | |
709 | |
710 if (len == 1 && p[0] == '=') { | |
577 | 711 |
712 if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) { | |
713 return NGX_CONF_ERROR; | |
714 } | |
715 | |
716 code = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
717 sizeof(uintptr_t)); | |
718 if (code == NULL) { | |
719 return NGX_CONF_ERROR; | |
720 } | |
721 | |
722 *code = ngx_http_script_equal_code; | |
723 | |
724 return NGX_CONF_OK; | |
501 | 725 } |
726 | |
631 | 727 if (len == 2 && p[0] == '!' && p[1] == '=') { |
728 | |
577 | 729 if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) { |
730 return NGX_CONF_ERROR; | |
731 } | |
732 | |
733 code = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
734 sizeof(uintptr_t)); | |
735 if (code == NULL) { | |
736 return NGX_CONF_ERROR; | |
737 } | |
738 | |
739 *code = ngx_http_script_not_equal_code; | |
740 return NGX_CONF_OK; | |
501 | 741 } |
742 | |
631 | 743 if ((len == 1 && p[0] == '~') |
744 || (len == 2 && p[0] == '~' && p[1] == '*') | |
745 || (len == 2 && p[0] == '!' && p[1] == '~') | |
746 || (len == 3 && p[0] == '!' && p[1] == '~' && p[2] == '*')) | |
577 | 747 { |
748 regex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
749 sizeof(ngx_http_script_regex_code_t)); | |
750 if (regex == NULL) { | |
751 return NGX_CONF_ERROR; | |
752 } | |
509 | 753 |
577 | 754 ngx_memzero(regex, sizeof(ngx_http_script_regex_code_t)); |
755 | |
3325 | 756 ngx_memzero(&rc, sizeof(ngx_regex_compile_t)); |
577 | 757 |
3325 | 758 rc.pattern = value[last]; |
759 rc.options = (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0; | |
760 rc.err.len = NGX_MAX_CONF_ERRSTR; | |
761 rc.err.data = errstr; | |
501 | 762 |
3325 | 763 regex->regex = ngx_http_regex_compile(cf, &rc); |
577 | 764 if (regex->regex == NULL) { |
765 return NGX_CONF_ERROR; | |
766 } | |
767 | |
768 regex->code = ngx_http_script_regex_start_code; | |
769 regex->next = sizeof(ngx_http_script_regex_code_t); | |
770 regex->test = 1; | |
631 | 771 if (p[0] == '!') { |
772 regex->negative_test = 1; | |
773 } | |
577 | 774 regex->name = value[last]; |
501 | 775 |
577 | 776 return NGX_CONF_OK; |
501 | 777 } |
778 | |
577 | 779 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
780 "unexpected \"%V\" in condition", &value[cur]); | |
781 return NGX_CONF_ERROR; | |
631 | 782 |
783 } else if ((len == 2 && p[0] == '-') | |
784 || (len == 3 && p[0] == '!' && p[1] == '-')) | |
785 { | |
786 if (cur + 1 != last) { | |
787 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
788 "invalid condition \"%V\"", &value[cur]); | |
789 return NGX_CONF_ERROR; | |
790 } | |
791 | |
792 value[last].data[value[last].len] = '\0'; | |
793 value[last].len++; | |
794 | |
795 if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) { | |
796 return NGX_CONF_ERROR; | |
797 } | |
798 | |
799 fop = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
800 sizeof(ngx_http_script_file_code_t)); | |
801 if (fop == NULL) { | |
802 return NGX_CONF_ERROR; | |
803 } | |
804 | |
805 fop->code = ngx_http_script_file_code; | |
806 | |
807 if (p[1] == 'f') { | |
808 fop->op = ngx_http_script_file_plain; | |
809 return NGX_CONF_OK; | |
810 } | |
811 | |
669 | 812 if (p[1] == 'd') { |
813 fop->op = ngx_http_script_file_dir; | |
814 return NGX_CONF_OK; | |
815 } | |
816 | |
817 if (p[1] == 'e') { | |
818 fop->op = ngx_http_script_file_exists; | |
819 return NGX_CONF_OK; | |
820 } | |
821 | |
822 if (p[1] == 'x') { | |
823 fop->op = ngx_http_script_file_exec; | |
824 return NGX_CONF_OK; | |
825 } | |
826 | |
631 | 827 if (p[0] == '!') { |
828 if (p[2] == 'f') { | |
829 fop->op = ngx_http_script_file_not_plain; | |
830 return NGX_CONF_OK; | |
831 } | |
669 | 832 |
833 if (p[2] == 'd') { | |
834 fop->op = ngx_http_script_file_not_dir; | |
835 return NGX_CONF_OK; | |
836 } | |
837 | |
838 if (p[2] == 'e') { | |
839 fop->op = ngx_http_script_file_not_exists; | |
840 return NGX_CONF_OK; | |
841 } | |
842 | |
843 if (p[2] == 'x') { | |
844 fop->op = ngx_http_script_file_not_exec; | |
845 return NGX_CONF_OK; | |
846 } | |
631 | 847 } |
848 | |
849 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
850 "invalid condition \"%V\"", &value[cur]); | |
851 return NGX_CONF_ERROR; | |
501 | 852 } |
853 | |
854 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
855 "invalid condition \"%V\"", &value[cur]); | |
856 | |
857 return NGX_CONF_ERROR; | |
858 } | |
859 | |
860 | |
861 static char * | |
862 ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
863 ngx_str_t *value) | |
864 { | |
509 | 865 ngx_int_t index; |
866 ngx_http_script_var_code_t *var_code; | |
501 | 867 |
868 value->len--; | |
869 value->data++; | |
870 | |
577 | 871 index = ngx_http_get_variable_index(cf, value); |
501 | 872 |
577 | 873 if (index == NGX_ERROR) { |
874 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
|
875 } |
f1d0e5f09c1e
nginx-0.0.1-2003-12-25-23:26:58 import
Igor Sysoev <igor@sysoev.ru>
parents:
diff
changeset
|
876 |
577 | 877 var_code = ngx_http_script_start_code(cf->pool, &lcf->codes, |
878 sizeof(ngx_http_script_var_code_t)); | |
879 if (var_code == NULL) { | |
880 return NGX_CONF_ERROR; | |
485 | 881 } |
882 | |
577 | 883 var_code->code = ngx_http_script_var_code; |
884 var_code->index = index; | |
485 | 885 |
886 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
|
887 } |
485 | 888 |
889 | |
501 | 890 static char * |
891 ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
892 { | |
577 | 893 ngx_http_rewrite_loc_conf_t *lcf = conf; |
501 | 894 |
637 | 895 ngx_int_t index; |
896 ngx_str_t *value; | |
897 ngx_http_variable_t *v; | |
898 ngx_http_script_var_code_t *vcode; | |
899 ngx_http_script_var_handler_code_t *vhcode; | |
501 | 900 |
901 value = cf->args->elts; | |
902 | |
4972
8b635cf36ccc
Added checks that disallow adding a variable with an empty name.
Ruslan Ermilov <ru@nginx.com>
parents:
4963
diff
changeset
|
903 if (value[1].data[0] != '$') { |
501 | 904 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
905 "invalid variable name \"%V\"", &value[1]); | |
906 return NGX_CONF_ERROR; | |
907 } | |
908 | |
909 value[1].len--; | |
910 value[1].data++; | |
911 | |
6899
d2b2ff157da5
Variables: generic prefix variables.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6474
diff
changeset
|
912 v = ngx_http_add_variable(cf, &value[1], |
d2b2ff157da5
Variables: generic prefix variables.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6474
diff
changeset
|
913 NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_WEAK); |
501 | 914 if (v == NULL) { |
915 return NGX_CONF_ERROR; | |
916 } | |
917 | |
509 | 918 index = ngx_http_get_variable_index(cf, &value[1]); |
919 if (index == NGX_ERROR) { | |
920 return NGX_CONF_ERROR; | |
921 } | |
501 | 922 |
6899
d2b2ff157da5
Variables: generic prefix variables.
Dmitry Volyntsev <xeioex@nginx.com>
parents:
6474
diff
changeset
|
923 if (v->get_handler == NULL) { |
637 | 924 v->get_handler = ngx_http_rewrite_var; |
555 | 925 v->data = index; |
926 } | |
509 | 927 |
577 | 928 if (ngx_http_rewrite_value(cf, lcf, &value[2]) != NGX_CONF_OK) { |
929 return NGX_CONF_ERROR; | |
515 | 930 } |
501 | 931 |
637 | 932 if (v->set_handler) { |
933 vhcode = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
934 sizeof(ngx_http_script_var_handler_code_t)); | |
935 if (vhcode == NULL) { | |
936 return NGX_CONF_ERROR; | |
937 } | |
938 | |
939 vhcode->code = ngx_http_script_var_set_handler_code; | |
940 vhcode->handler = v->set_handler; | |
941 vhcode->data = v->data; | |
942 | |
943 return NGX_CONF_OK; | |
944 } | |
945 | |
946 vcode = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
947 sizeof(ngx_http_script_var_code_t)); | |
948 if (vcode == NULL) { | |
501 | 949 return NGX_CONF_ERROR; |
950 } | |
951 | |
637 | 952 vcode->code = ngx_http_script_set_var_code; |
953 vcode->index = (uintptr_t) index; | |
501 | 954 |
955 return NGX_CONF_OK; | |
956 } | |
577 | 957 |
958 | |
959 static char * | |
960 ngx_http_rewrite_value(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf, | |
961 ngx_str_t *value) | |
962 { | |
963 ngx_int_t n; | |
964 ngx_http_script_compile_t sc; | |
965 ngx_http_script_value_code_t *val; | |
966 ngx_http_script_complex_value_code_t *complex; | |
967 | |
968 n = ngx_http_script_variables_count(value); | |
969 | |
970 if (n == 0) { | |
971 val = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
972 sizeof(ngx_http_script_value_code_t)); | |
973 if (val == NULL) { | |
974 return NGX_CONF_ERROR; | |
975 } | |
976 | |
977 n = ngx_atoi(value->data, value->len); | |
978 | |
979 if (n == NGX_ERROR) { | |
980 n = 0; | |
981 } | |
982 | |
983 val->code = ngx_http_script_value_code; | |
984 val->value = (uintptr_t) n; | |
985 val->text_len = (uintptr_t) value->len; | |
986 val->text_data = (uintptr_t) value->data; | |
987 | |
988 return NGX_CONF_OK; | |
989 } | |
990 | |
991 complex = ngx_http_script_start_code(cf->pool, &lcf->codes, | |
992 sizeof(ngx_http_script_complex_value_code_t)); | |
993 if (complex == NULL) { | |
994 return NGX_CONF_ERROR; | |
995 } | |
996 | |
997 complex->code = ngx_http_script_complex_value_code; | |
998 complex->lengths = NULL; | |
999 | |
1000 ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); | |
1001 | |
1002 sc.cf = cf; | |
1003 sc.source = value; | |
1004 sc.lengths = &complex->lengths; | |
1005 sc.values = &lcf->codes; | |
1006 sc.variables = n; | |
1007 sc.complete_lengths = 1; | |
1008 | |
1009 if (ngx_http_script_compile(&sc) != NGX_OK) { | |
1010 return NGX_CONF_ERROR; | |
1011 } | |
1012 | |
1013 return NGX_CONF_OK; | |
1014 } |