upstream 0.7.33
[nginx.git] / nginx / src / http / ngx_http_core_module.c
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     u_char    *name;
14     uint32_t   method;
15 } ngx_http_method_name_t;
16
17
18 #define NGX_HTTP_REQUEST_BODY_FILE_OFF    0
19 #define NGX_HTTP_REQUEST_BODY_FILE_ON     1
20 #define NGX_HTTP_REQUEST_BODY_FILE_CLEAN  2
21
22
23 static ngx_int_t ngx_http_core_find_location(ngx_http_request_t *r);
24 static ngx_int_t ngx_http_core_find_static_location(ngx_http_request_t *r,
25     ngx_http_location_tree_node_t *node);
26
27 static ngx_int_t ngx_http_core_preconfiguration(ngx_conf_t *cf);
28 static void *ngx_http_core_create_main_conf(ngx_conf_t *cf);
29 static char *ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf);
30 static void *ngx_http_core_create_srv_conf(ngx_conf_t *cf);
31 static char *ngx_http_core_merge_srv_conf(ngx_conf_t *cf,
32     void *parent, void *child);
33 static void *ngx_http_core_create_loc_conf(ngx_conf_t *cf);
34 static char *ngx_http_core_merge_loc_conf(ngx_conf_t *cf,
35     void *parent, void *child);
36
37 static char *ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd,
38     void *dummy);
39 static char *ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd,
40     void *dummy);
41 static ngx_int_t ngx_http_core_regex_location(ngx_conf_t *cf,
42     ngx_http_core_loc_conf_t *clcf, ngx_str_t *regex, ngx_uint_t caseless);
43
44 static char *ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd,
45     void *conf);
46 static char *ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy,
47     void *conf);
48
49 static char *ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
50     void *conf);
51 static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
52     void *conf);
53 static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
54 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
55     void *conf);
56 static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
57     void *conf);
58 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
59     void *conf);
60 static char *ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd,
61     void *conf);
62 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
63     void *conf);
64 static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
65     void *conf);
66 static char *ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
67     void *conf);
68 static char *ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd,
69     void *conf);
70 static char *ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd,
71     void *conf);
72 #if (NGX_HTTP_GZIP)
73 static char *ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd,
74     void *conf);
75 #endif
76
77 static char *ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data);
78 static char *ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data);
79
80 static ngx_conf_post_t  ngx_http_core_lowat_post =
81     { ngx_http_core_lowat_check };
82
83 static ngx_conf_post_handler_pt  ngx_http_core_pool_size_p =
84     ngx_http_core_pool_size;
85
86 static ngx_conf_deprecated_t  ngx_conf_deprecated_optimize_server_names = {
87     ngx_conf_deprecated, "optimize_server_names", "server_name_in_redirect"
88 };
89
90 static ngx_conf_deprecated_t  ngx_conf_deprecated_open_file_cache_retest = {
91     ngx_conf_deprecated, "open_file_cache_retest", "open_file_cache_valid"
92 };
93
94 static ngx_conf_deprecated_t  ngx_conf_deprecated_satisfy_any = {
95     ngx_conf_deprecated, "satisfy_any", "satisfy"
96 };
97
98
99 static ngx_conf_enum_t  ngx_http_core_request_body_in_file[] = {
100     { ngx_string("off"), NGX_HTTP_REQUEST_BODY_FILE_OFF },
101     { ngx_string("on"), NGX_HTTP_REQUEST_BODY_FILE_ON },
102     { ngx_string("clean"), NGX_HTTP_REQUEST_BODY_FILE_CLEAN },
103     { ngx_null_string, 0 }
104 };
105
106
107 static ngx_conf_enum_t  ngx_http_core_satisfy[] = {
108     { ngx_string("all"), NGX_HTTP_SATISFY_ALL },
109     { ngx_string("any"), NGX_HTTP_SATISFY_ANY },
110     { ngx_null_string, 0 }
111 };
112
113
114 static ngx_conf_enum_t  ngx_http_core_if_modified_since[] = {
115     { ngx_string("exact"), 0 },
116     { ngx_string("before"), 1 },
117     { ngx_null_string, 0 }
118 };
119
120
121 #if (NGX_HTTP_GZIP)
122
123 static ngx_conf_enum_t  ngx_http_gzip_http_version[] = {
124     { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
125     { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
126     { ngx_null_string, 0 }
127 };
128
129
130 static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
131     { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
132     { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
133     { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
134     { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
135     { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
136     { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
137     { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
138     { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
139     { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
140     { ngx_null_string, 0 }
141 };
142
143
144 static ngx_str_t  ngx_http_gzip_no_cache = ngx_string("no-cache");
145 static ngx_str_t  ngx_http_gzip_no_store = ngx_string("no-store");
146 static ngx_str_t  ngx_http_gzip_private = ngx_string("private");
147
148 #endif
149
150
151 static ngx_command_t  ngx_http_core_commands[] = {
152
153     { ngx_string("variables_hash_max_size"),
154       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
155       ngx_conf_set_num_slot,
156       NGX_HTTP_MAIN_CONF_OFFSET,
157       offsetof(ngx_http_core_main_conf_t, variables_hash_max_size),
158       NULL },
159
160     { ngx_string("variables_hash_bucket_size"),
161       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
162       ngx_conf_set_num_slot,
163       NGX_HTTP_MAIN_CONF_OFFSET,
164       offsetof(ngx_http_core_main_conf_t, variables_hash_bucket_size),
165       NULL },
166
167     { ngx_string("server_names_hash_max_size"),
168       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
169       ngx_conf_set_num_slot,
170       NGX_HTTP_MAIN_CONF_OFFSET,
171       offsetof(ngx_http_core_main_conf_t, server_names_hash_max_size),
172       NULL },
173
174     { ngx_string("server_names_hash_bucket_size"),
175       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
176       ngx_conf_set_num_slot,
177       NGX_HTTP_MAIN_CONF_OFFSET,
178       offsetof(ngx_http_core_main_conf_t, server_names_hash_bucket_size),
179       NULL },
180
181     { ngx_string("server"),
182       NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_MULTI|NGX_CONF_NOARGS,
183       ngx_http_core_server,
184       0,
185       0,
186       NULL },
187
188     { ngx_string("connection_pool_size"),
189       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
190       ngx_conf_set_size_slot,
191       NGX_HTTP_SRV_CONF_OFFSET,
192       offsetof(ngx_http_core_srv_conf_t, connection_pool_size),
193       &ngx_http_core_pool_size_p },
194
195     { ngx_string("request_pool_size"),
196       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
197       ngx_conf_set_size_slot,
198       NGX_HTTP_SRV_CONF_OFFSET,
199       offsetof(ngx_http_core_srv_conf_t, request_pool_size),
200       &ngx_http_core_pool_size_p },
201
202     { ngx_string("client_header_timeout"),
203       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
204       ngx_conf_set_msec_slot,
205       NGX_HTTP_SRV_CONF_OFFSET,
206       offsetof(ngx_http_core_srv_conf_t, client_header_timeout),
207       NULL },
208
209     { ngx_string("client_header_buffer_size"),
210       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1,
211       ngx_conf_set_size_slot,
212       NGX_HTTP_SRV_CONF_OFFSET,
213       offsetof(ngx_http_core_srv_conf_t, client_header_buffer_size),
214       NULL },
215
216     { ngx_string("large_client_header_buffers"),
217       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE2,
218       ngx_conf_set_bufs_slot,
219       NGX_HTTP_SRV_CONF_OFFSET,
220       offsetof(ngx_http_core_srv_conf_t, large_client_header_buffers),
221       NULL },
222
223     { ngx_string("optimize_server_names"),
224       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
225       ngx_conf_set_flag_slot,
226       NGX_HTTP_LOC_CONF_OFFSET,
227       offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
228       &ngx_conf_deprecated_optimize_server_names },
229
230     { ngx_string("ignore_invalid_headers"),
231       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
232       ngx_conf_set_flag_slot,
233       NGX_HTTP_SRV_CONF_OFFSET,
234       offsetof(ngx_http_core_srv_conf_t, ignore_invalid_headers),
235       NULL },
236
237     { ngx_string("merge_slashes"),
238       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
239       ngx_conf_set_flag_slot,
240       NGX_HTTP_SRV_CONF_OFFSET,
241       offsetof(ngx_http_core_srv_conf_t, merge_slashes),
242       NULL },
243
244     { ngx_string("underscores_in_headers"),
245       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
246       ngx_conf_set_flag_slot,
247       NGX_HTTP_SRV_CONF_OFFSET,
248       offsetof(ngx_http_core_srv_conf_t, underscores_in_headers),
249       NULL },
250
251     { ngx_string("location"),
252       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
253       ngx_http_core_location,
254       NGX_HTTP_SRV_CONF_OFFSET,
255       0,
256       NULL },
257
258     { ngx_string("listen"),
259       NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
260       ngx_http_core_listen,
261       NGX_HTTP_SRV_CONF_OFFSET,
262       0,
263       NULL },
264
265     { ngx_string("server_name"),
266       NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
267       ngx_http_core_server_name,
268       NGX_HTTP_SRV_CONF_OFFSET,
269       0,
270       NULL },
271
272     { ngx_string("types_hash_max_size"),
273       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
274       ngx_conf_set_num_slot,
275       NGX_HTTP_LOC_CONF_OFFSET,
276       offsetof(ngx_http_core_loc_conf_t, types_hash_max_size),
277       NULL },
278
279     { ngx_string("types_hash_bucket_size"),
280       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
281       ngx_conf_set_num_slot,
282       NGX_HTTP_LOC_CONF_OFFSET,
283       offsetof(ngx_http_core_loc_conf_t, types_hash_bucket_size),
284       NULL },
285
286     { ngx_string("types"),
287       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF
288                                           |NGX_CONF_BLOCK|NGX_CONF_NOARGS,
289       ngx_http_core_types,
290       NGX_HTTP_LOC_CONF_OFFSET,
291       0,
292       NULL },
293
294     { ngx_string("default_type"),
295       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
296       ngx_conf_set_str_slot,
297       NGX_HTTP_LOC_CONF_OFFSET,
298       offsetof(ngx_http_core_loc_conf_t, default_type),
299       NULL },
300
301     { ngx_string("root"),
302       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
303                         |NGX_CONF_TAKE1,
304       ngx_http_core_root,
305       NGX_HTTP_LOC_CONF_OFFSET,
306       0,
307       NULL },
308
309     { ngx_string("alias"),
310       NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
311       ngx_http_core_root,
312       NGX_HTTP_LOC_CONF_OFFSET,
313       0,
314       NULL },
315
316     { ngx_string("limit_except"),
317       NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
318       ngx_http_core_limit_except,
319       NGX_HTTP_LOC_CONF_OFFSET,
320       0,
321       NULL },
322
323     { ngx_string("client_max_body_size"),
324       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
325       ngx_conf_set_off_slot,
326       NGX_HTTP_LOC_CONF_OFFSET,
327       offsetof(ngx_http_core_loc_conf_t, client_max_body_size),
328       NULL },
329
330     { ngx_string("client_body_buffer_size"),
331       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
332       ngx_conf_set_size_slot,
333       NGX_HTTP_LOC_CONF_OFFSET,
334       offsetof(ngx_http_core_loc_conf_t, client_body_buffer_size),
335       NULL },
336
337     { ngx_string("client_body_timeout"),
338       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
339       ngx_conf_set_msec_slot,
340       NGX_HTTP_LOC_CONF_OFFSET,
341       offsetof(ngx_http_core_loc_conf_t, client_body_timeout),
342       NULL },
343
344     { ngx_string("client_body_temp_path"),
345       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
346       ngx_conf_set_path_slot,
347       NGX_HTTP_LOC_CONF_OFFSET,
348       offsetof(ngx_http_core_loc_conf_t, client_body_temp_path),
349       (void *) ngx_garbage_collector_temp_handler },
350
351     { ngx_string("client_body_in_file_only"),
352       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
353       ngx_conf_set_enum_slot,
354       NGX_HTTP_LOC_CONF_OFFSET,
355       offsetof(ngx_http_core_loc_conf_t, client_body_in_file_only),
356       &ngx_http_core_request_body_in_file },
357
358     { ngx_string("sendfile"),
359       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
360                         |NGX_CONF_TAKE1,
361       ngx_conf_set_flag_slot,
362       NGX_HTTP_LOC_CONF_OFFSET,
363       offsetof(ngx_http_core_loc_conf_t, sendfile),
364       NULL },
365
366     { ngx_string("sendfile_max_chunk"),
367       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
368       ngx_conf_set_size_slot,
369       NGX_HTTP_LOC_CONF_OFFSET,
370       offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk),
371       NULL },
372
373     { ngx_string("directio"),
374       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
375       ngx_http_core_directio,
376       NGX_HTTP_LOC_CONF_OFFSET,
377       0,
378       NULL },
379
380     { ngx_string("tcp_nopush"),
381       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
382       ngx_conf_set_flag_slot,
383       NGX_HTTP_LOC_CONF_OFFSET,
384       offsetof(ngx_http_core_loc_conf_t, tcp_nopush),
385       NULL },
386
387     { ngx_string("tcp_nodelay"),
388       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
389       ngx_conf_set_flag_slot,
390       NGX_HTTP_LOC_CONF_OFFSET,
391       offsetof(ngx_http_core_loc_conf_t, tcp_nodelay),
392       NULL },
393
394     { ngx_string("send_timeout"),
395       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
396       ngx_conf_set_msec_slot,
397       NGX_HTTP_LOC_CONF_OFFSET,
398       offsetof(ngx_http_core_loc_conf_t, send_timeout),
399       NULL },
400
401     { ngx_string("send_lowat"),
402       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
403       ngx_conf_set_size_slot,
404       NGX_HTTP_LOC_CONF_OFFSET,
405       offsetof(ngx_http_core_loc_conf_t, send_lowat),
406       &ngx_http_core_lowat_post },
407
408     { ngx_string("postpone_output"),
409       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
410       ngx_conf_set_size_slot,
411       NGX_HTTP_LOC_CONF_OFFSET,
412       offsetof(ngx_http_core_loc_conf_t, postpone_output),
413       NULL },
414
415     { ngx_string("limit_rate"),
416       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
417                         |NGX_CONF_TAKE1,
418       ngx_conf_set_size_slot,
419       NGX_HTTP_LOC_CONF_OFFSET,
420       offsetof(ngx_http_core_loc_conf_t, limit_rate),
421       NULL },
422
423     { ngx_string("keepalive_timeout"),
424       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
425       ngx_http_core_keepalive,
426       NGX_HTTP_LOC_CONF_OFFSET,
427       0,
428       NULL },
429
430     { ngx_string("satisfy"),
431       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
432       ngx_conf_set_enum_slot,
433       NGX_HTTP_LOC_CONF_OFFSET,
434       offsetof(ngx_http_core_loc_conf_t, satisfy),
435       &ngx_http_core_satisfy },
436
437     { ngx_string("satisfy_any"),
438       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
439       ngx_conf_set_flag_slot,
440       NGX_HTTP_LOC_CONF_OFFSET,
441       offsetof(ngx_http_core_loc_conf_t, satisfy),
442       &ngx_conf_deprecated_satisfy_any },
443
444     { ngx_string("internal"),
445       NGX_HTTP_LOC_CONF|NGX_CONF_NOARGS,
446       ngx_http_core_internal,
447       NGX_HTTP_LOC_CONF_OFFSET,
448       0,
449       NULL },
450
451     { ngx_string("lingering_time"),
452       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
453       ngx_conf_set_msec_slot,
454       NGX_HTTP_LOC_CONF_OFFSET,
455       offsetof(ngx_http_core_loc_conf_t, lingering_time),
456       NULL },
457
458     { ngx_string("lingering_timeout"),
459       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
460       ngx_conf_set_msec_slot,
461       NGX_HTTP_LOC_CONF_OFFSET,
462       offsetof(ngx_http_core_loc_conf_t, lingering_timeout),
463       NULL },
464
465     { ngx_string("reset_timedout_connection"),
466       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
467       ngx_conf_set_flag_slot,
468       NGX_HTTP_LOC_CONF_OFFSET,
469       offsetof(ngx_http_core_loc_conf_t, reset_timedout_connection),
470       NULL },
471
472     { ngx_string("server_name_in_redirect"),
473       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
474       ngx_conf_set_flag_slot,
475       NGX_HTTP_LOC_CONF_OFFSET,
476       offsetof(ngx_http_core_loc_conf_t, server_name_in_redirect),
477       NULL },
478
479     { ngx_string("port_in_redirect"),
480       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
481       ngx_conf_set_flag_slot,
482       NGX_HTTP_LOC_CONF_OFFSET,
483       offsetof(ngx_http_core_loc_conf_t, port_in_redirect),
484       NULL },
485
486     { ngx_string("msie_padding"),
487       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
488       ngx_conf_set_flag_slot,
489       NGX_HTTP_LOC_CONF_OFFSET,
490       offsetof(ngx_http_core_loc_conf_t, msie_padding),
491       NULL },
492
493     { ngx_string("msie_refresh"),
494       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
495       ngx_conf_set_flag_slot,
496       NGX_HTTP_LOC_CONF_OFFSET,
497       offsetof(ngx_http_core_loc_conf_t, msie_refresh),
498       NULL },
499
500     { ngx_string("log_not_found"),
501       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
502       ngx_conf_set_flag_slot,
503       NGX_HTTP_LOC_CONF_OFFSET,
504       offsetof(ngx_http_core_loc_conf_t, log_not_found),
505       NULL },
506
507     { ngx_string("log_subrequest"),
508       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
509       ngx_conf_set_flag_slot,
510       NGX_HTTP_LOC_CONF_OFFSET,
511       offsetof(ngx_http_core_loc_conf_t, log_subrequest),
512       NULL },
513
514     { ngx_string("recursive_error_pages"),
515       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
516       ngx_conf_set_flag_slot,
517       NGX_HTTP_LOC_CONF_OFFSET,
518       offsetof(ngx_http_core_loc_conf_t, recursive_error_pages),
519       NULL },
520
521     { ngx_string("server_tokens"),
522       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
523       ngx_conf_set_flag_slot,
524       NGX_HTTP_LOC_CONF_OFFSET,
525       offsetof(ngx_http_core_loc_conf_t, server_tokens),
526       NULL },
527
528     { ngx_string("if_modified_since"),
529       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
530       ngx_conf_set_enum_slot,
531       NGX_HTTP_LOC_CONF_OFFSET,
532       offsetof(ngx_http_core_loc_conf_t, if_modified_since),
533       &ngx_http_core_if_modified_since },
534
535     { ngx_string("error_page"),
536       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
537                         |NGX_CONF_2MORE,
538       ngx_http_core_error_page,
539       NGX_HTTP_LOC_CONF_OFFSET,
540       0,
541       NULL },
542
543     { ngx_string("try_files"),
544       NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
545       ngx_http_core_try_files,
546       NGX_HTTP_LOC_CONF_OFFSET,
547       0,
548       NULL },
549
550     { ngx_string("post_action"),
551       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
552                         |NGX_CONF_TAKE1,
553       ngx_conf_set_str_slot,
554       NGX_HTTP_LOC_CONF_OFFSET,
555       offsetof(ngx_http_core_loc_conf_t, post_action),
556       NULL },
557
558     { ngx_string("error_log"),
559       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
560       ngx_http_core_error_log,
561       NGX_HTTP_LOC_CONF_OFFSET,
562       0,
563       NULL },
564
565     { ngx_string("open_file_cache"),
566       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
567       ngx_http_core_open_file_cache,
568       NGX_HTTP_LOC_CONF_OFFSET,
569       offsetof(ngx_http_core_loc_conf_t, open_file_cache),
570       NULL },
571
572     { ngx_string("open_file_cache_valid"),
573       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
574       ngx_conf_set_sec_slot,
575       NGX_HTTP_LOC_CONF_OFFSET,
576       offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid),
577       NULL },
578
579     { ngx_string("open_file_cache_retest"),
580       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
581       ngx_conf_set_sec_slot,
582       NGX_HTTP_LOC_CONF_OFFSET,
583       offsetof(ngx_http_core_loc_conf_t, open_file_cache_valid),
584       &ngx_conf_deprecated_open_file_cache_retest },
585
586     { ngx_string("open_file_cache_min_uses"),
587       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
588       ngx_conf_set_num_slot,
589       NGX_HTTP_LOC_CONF_OFFSET,
590       offsetof(ngx_http_core_loc_conf_t, open_file_cache_min_uses),
591       NULL },
592
593     { ngx_string("open_file_cache_errors"),
594       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
595       ngx_conf_set_flag_slot,
596       NGX_HTTP_LOC_CONF_OFFSET,
597       offsetof(ngx_http_core_loc_conf_t, open_file_cache_errors),
598       NULL },
599
600     { ngx_string("open_file_cache_events"),
601       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
602       ngx_conf_set_flag_slot,
603       NGX_HTTP_LOC_CONF_OFFSET,
604       offsetof(ngx_http_core_loc_conf_t, open_file_cache_events),
605       NULL },
606
607     { ngx_string("resolver"),
608       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
609       ngx_http_core_resolver,
610       NGX_HTTP_LOC_CONF_OFFSET,
611       0,
612       NULL },
613
614     { ngx_string("resolver_timeout"),
615       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
616       ngx_conf_set_msec_slot,
617       NGX_HTTP_LOC_CONF_OFFSET,
618       offsetof(ngx_http_core_loc_conf_t, resolver_timeout),
619       NULL },
620
621 #if (NGX_HTTP_GZIP)
622
623     { ngx_string("gzip_vary"),
624       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
625       ngx_conf_set_flag_slot,
626       NGX_HTTP_LOC_CONF_OFFSET,
627       offsetof(ngx_http_core_loc_conf_t, gzip_vary),
628       NULL },
629
630     { ngx_string("gzip_http_version"),
631       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
632       ngx_conf_set_enum_slot,
633       NGX_HTTP_LOC_CONF_OFFSET,
634       offsetof(ngx_http_core_loc_conf_t, gzip_http_version),
635       &ngx_http_gzip_http_version },
636
637     { ngx_string("gzip_proxied"),
638       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
639       ngx_conf_set_bitmask_slot,
640       NGX_HTTP_LOC_CONF_OFFSET,
641       offsetof(ngx_http_core_loc_conf_t, gzip_proxied),
642       &ngx_http_gzip_proxied_mask },
643
644     { ngx_string("gzip_disable"),
645       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
646       ngx_http_gzip_disable,
647       NGX_HTTP_LOC_CONF_OFFSET,
648       0,
649       NULL },
650
651 #endif
652
653       ngx_null_command
654 };
655
656
657 static ngx_http_module_t  ngx_http_core_module_ctx = {
658     ngx_http_core_preconfiguration,        /* preconfiguration */
659     NULL,                                  /* postconfiguration */
660
661     ngx_http_core_create_main_conf,        /* create main configuration */
662     ngx_http_core_init_main_conf,          /* init main configuration */
663
664     ngx_http_core_create_srv_conf,         /* create server configuration */
665     ngx_http_core_merge_srv_conf,          /* merge server configuration */
666
667     ngx_http_core_create_loc_conf,         /* create location configuration */
668     ngx_http_core_merge_loc_conf           /* merge location configuration */
669 };
670
671
672 ngx_module_t  ngx_http_core_module = {
673     NGX_MODULE_V1,
674     &ngx_http_core_module_ctx,             /* module context */
675     ngx_http_core_commands,                /* module directives */
676     NGX_HTTP_MODULE,                       /* module type */
677     NULL,                                  /* init master */
678     NULL,                                  /* init module */
679     NULL,                                  /* init process */
680     NULL,                                  /* init thread */
681     NULL,                                  /* exit thread */
682     NULL,                                  /* exit process */
683     NULL,                                  /* exit master */
684     NGX_MODULE_V1_PADDING
685 };
686
687
688 static ngx_str_t  ngx_http_core_get_method = { 3, (u_char *) "GET " };
689
690
691 void
692 ngx_http_handler(ngx_http_request_t *r)
693 {
694     ngx_http_core_main_conf_t  *cmcf;
695
696     r->connection->log->action = NULL;
697
698     r->connection->unexpected_eof = 0;
699
700     if (!r->internal) {
701         switch (r->headers_in.connection_type) {
702         case 0:
703             if (r->http_version > NGX_HTTP_VERSION_10) {
704                 r->keepalive = 1;
705             } else {
706                 r->keepalive = 0;
707             }
708             break;
709
710         case NGX_HTTP_CONNECTION_CLOSE:
711             r->keepalive = 0;
712             break;
713
714         case NGX_HTTP_CONNECTION_KEEP_ALIVE:
715             r->keepalive = 1;
716             break;
717         }
718
719         if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
720
721             /*
722              * MSIE may wait for some time if an response for
723              * a POST request was sent over a keepalive connection
724              */
725
726             r->keepalive = 0;
727         }
728
729         if (r->headers_in.content_length_n > 0) {
730             r->lingering_close = 1;
731
732         } else {
733             r->lingering_close = 0;
734         }
735
736         r->phase_handler = 0;
737
738     } else {
739         cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
740         r->phase_handler = cmcf->phase_engine.server_rewrite_index;
741     }
742
743     if (r->unparsed_uri.len) {
744         r->valid_unparsed_uri = 1;
745     }
746
747     r->valid_location = 1;
748     r->gzip = 0;
749
750     r->write_event_handler = ngx_http_core_run_phases;
751     ngx_http_core_run_phases(r);
752 }
753
754
755 void
756 ngx_http_core_run_phases(ngx_http_request_t *r)
757 {
758     ngx_int_t                   rc;
759     ngx_http_phase_handler_t   *ph;
760     ngx_http_core_main_conf_t  *cmcf;
761
762     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
763
764     ph = cmcf->phase_engine.handlers;
765
766     while (ph[r->phase_handler].checker) {
767
768         rc = ph[r->phase_handler].checker(r, &ph[r->phase_handler]);
769
770         if (rc == NGX_OK) {
771             return;
772         }
773     }
774 }
775
776
777 ngx_int_t
778 ngx_http_core_generic_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
779 {
780     ngx_int_t  rc;
781
782     /*
783      * generic phase checker,
784      * used by the post read, server rewrite, rewrite, and pre-access phases
785      */
786
787     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
788                    "generic phase: %ui", r->phase_handler);
789
790     rc = ph->handler(r);
791
792     if (rc == NGX_OK) {
793         r->phase_handler = ph->next;
794         return NGX_AGAIN;
795     }
796
797     if (rc == NGX_DECLINED) {
798         r->phase_handler++;
799         return NGX_AGAIN;
800     }
801
802     if (rc == NGX_AGAIN || rc == NGX_DONE) {
803         return NGX_OK;
804     }
805
806     /* rc == NGX_ERROR || rc == NGX_HTTP_...  */
807
808     ngx_http_finalize_request(r, rc);
809
810     return NGX_OK;
811 }
812
813
814 ngx_int_t
815 ngx_http_core_find_config_phase(ngx_http_request_t *r,
816     ngx_http_phase_handler_t *ph)
817 {
818     u_char                    *p;
819     size_t                     len;
820     ngx_int_t                  rc;
821     ngx_http_core_loc_conf_t  *clcf;
822
823     r->content_handler = NULL;
824     r->uri_changed = 0;
825
826     rc = ngx_http_core_find_location(r);
827
828     if (rc == NGX_ERROR) {
829         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
830         return NGX_OK;
831     }
832
833     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
834
835     if (!r->internal && clcf->internal) {
836         ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
837         return NGX_OK;
838     }
839
840     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
841                    "using configuration \"%s%V\"",
842                    (clcf->noname ? "*" : (clcf->exact_match ? "=" : "")),
843                    &clcf->name);
844
845     ngx_http_update_location_config(r);
846
847     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
848                    "http cl:%O max:%O",
849                    r->headers_in.content_length_n, clcf->client_max_body_size);
850
851     if (r->headers_in.content_length_n != -1
852         && !r->discard_body
853         && clcf->client_max_body_size
854         && clcf->client_max_body_size < r->headers_in.content_length_n)
855     {
856         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
857                       "client intended to send too large body: %O bytes",
858                       r->headers_in.content_length_n);
859
860         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
861         return NGX_OK;
862     }
863
864     if (rc == NGX_DONE) {
865         r->headers_out.location = ngx_list_push(&r->headers_out.headers);
866         if (r->headers_out.location == NULL) {
867             ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
868             return NGX_OK;
869         }
870
871         /*
872          * we do not need to set the r->headers_out.location->hash and
873          * r->headers_out.location->key fields
874          */
875
876         if (r->args.len == 0) {
877             r->headers_out.location->value = clcf->name;
878
879         } else {
880             len = clcf->name.len + 1 + r->args.len;
881             p = ngx_pnalloc(r->pool, len);
882
883             if (p == NULL) {
884                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
885                 return NGX_OK;
886             }
887
888             r->headers_out.location->value.len = len;
889             r->headers_out.location->value.data = p;
890
891             p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
892             *p++ = '?';
893             ngx_memcpy(p, r->args.data, r->args.len);
894         }
895
896         ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
897         return NGX_OK;
898     }
899
900     r->phase_handler++;
901     return NGX_AGAIN;
902 }
903
904
905 ngx_int_t
906 ngx_http_core_post_rewrite_phase(ngx_http_request_t *r,
907     ngx_http_phase_handler_t *ph)
908 {
909     ngx_http_core_srv_conf_t  *cscf;
910
911     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
912                    "post rewrite phase: %ui", r->phase_handler);
913
914     if (!r->uri_changed) {
915         r->phase_handler++;
916         return NGX_AGAIN;
917     }
918
919     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
920                    "uri changes: %d", r->uri_changes);
921
922     /*
923      * gcc before 3.3 compiles the broken code for
924      *     if (r->uri_changes-- == 0)
925      * if the r->uri_changes is defined as
926      *     unsigned  uri_changes:4
927      */
928
929     r->uri_changes--;
930
931     if (r->uri_changes == 0) {
932         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
933                       "rewrite or internal redirection cycle "
934                       "while processing \"%V\"", &r->uri);
935
936         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
937         return NGX_OK;
938     }
939
940     r->phase_handler = ph->next;
941
942     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
943     r->loc_conf = cscf->ctx->loc_conf;
944
945     return NGX_AGAIN;
946 }
947
948
949 ngx_int_t
950 ngx_http_core_access_phase(ngx_http_request_t *r, ngx_http_phase_handler_t *ph)
951 {
952     ngx_int_t                  rc;
953     ngx_http_core_loc_conf_t  *clcf;
954
955     if (r != r->main) {
956         r->phase_handler = ph->next;
957         return NGX_AGAIN;
958     }
959
960     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
961                    "access phase: %ui", r->phase_handler);
962
963     rc = ph->handler(r);
964
965     if (rc == NGX_DECLINED) {
966         r->phase_handler++;
967         return NGX_AGAIN;
968     }
969
970     if (rc == NGX_AGAIN || rc == NGX_DONE) {
971         return NGX_OK;
972     }
973
974     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
975
976     if (clcf->satisfy == NGX_HTTP_SATISFY_ALL) {
977
978         if (rc == NGX_OK) {
979             r->phase_handler++;
980             return NGX_AGAIN;
981         }
982
983     } else {
984         if (rc == NGX_OK) {
985             r->access_code = 0;
986
987             if (r->headers_out.www_authenticate) {
988                 r->headers_out.www_authenticate->hash = 0;
989             }
990
991             r->phase_handler = ph->next;
992             return NGX_AGAIN;
993         }
994
995         if (rc == NGX_HTTP_FORBIDDEN || rc == NGX_HTTP_UNAUTHORIZED) {
996             r->access_code = rc;
997
998             r->phase_handler++;
999             return NGX_AGAIN;
1000         }
1001     }
1002
1003     /* rc == NGX_ERROR || rc == NGX_HTTP_...  */
1004
1005     ngx_http_finalize_request(r, rc);
1006     return NGX_OK;
1007 }
1008
1009
1010 ngx_int_t
1011 ngx_http_core_post_access_phase(ngx_http_request_t *r,
1012     ngx_http_phase_handler_t *ph)
1013 {
1014     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1015                    "post access phase: %ui", r->phase_handler);
1016
1017     if (r->access_code) {
1018
1019         if (r->access_code == NGX_HTTP_FORBIDDEN) {
1020             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1021                           "access forbidden by rule");
1022         }
1023
1024         ngx_http_finalize_request(r, r->access_code);
1025         return NGX_OK;
1026     }
1027
1028     r->phase_handler++;
1029     return NGX_AGAIN;
1030 }
1031
1032
1033 ngx_int_t
1034 ngx_http_core_try_files_phase(ngx_http_request_t *r,
1035     ngx_http_phase_handler_t *ph)
1036 {
1037     size_t                        len, root, alias, reserve, allocated;
1038     u_char                       *p, *name;
1039     ngx_str_t                     path;
1040     ngx_uint_t                    test_dir;
1041     ngx_http_try_file_t          *tf;
1042     ngx_open_file_info_t          of;
1043     ngx_http_script_code_pt       code;
1044     ngx_http_script_engine_t      e;
1045     ngx_http_core_loc_conf_t     *clcf;
1046     ngx_http_script_len_code_pt   lcode;
1047
1048     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1049                    "try files phase: %ui", r->phase_handler);
1050
1051     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1052
1053     if (clcf->try_files == NULL) {
1054         r->phase_handler++;
1055         return NGX_AGAIN;
1056     }
1057
1058     allocated = 0;
1059     root = 0;
1060     name = NULL;
1061     /* suppress MSVC warning */
1062     path.data = NULL;
1063
1064     tf = clcf->try_files;
1065
1066     alias = clcf->alias ? clcf->name.len : 0;
1067
1068     for ( ;; ) {
1069
1070         if (tf->lengths) {
1071             ngx_memzero(&e, sizeof(ngx_http_script_engine_t));
1072
1073             e.ip = tf->lengths->elts;
1074             e.request = r;
1075
1076             /* 1 is for terminating '\0' as in static names */
1077             len = 1;
1078
1079             while (*(uintptr_t *) e.ip) {
1080                 lcode = *(ngx_http_script_len_code_pt *) e.ip;
1081                 len += lcode(&e);
1082             }
1083
1084         } else {
1085             len = tf->name.len;
1086         }
1087
1088         reserve = len - r->uri.len;
1089
1090         /* 16 bytes are preallocation */
1091         reserve = reserve < 16 ? 16 : reserve + 16;
1092
1093         reserve += alias;
1094
1095         if (reserve > allocated) {
1096
1097             /* we just need to allocate path and to copy a root */
1098
1099             if (ngx_http_map_uri_to_path(r, &path, &root, reserve) == NULL) {
1100                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1101                 return NGX_OK;
1102             }
1103
1104             name = path.data + root;
1105             allocated = path.len - root - (r->uri.len - alias);
1106          }
1107
1108         if (tf->values == NULL) {
1109
1110             /* tf->name.len includes the terminating '\0' */
1111
1112             ngx_memcpy(name, tf->name.data, tf->name.len);
1113
1114             path.len = (name + tf->name.len - 1) - path.data;
1115
1116         } else {
1117             e.ip = tf->values->elts;
1118             e.pos = name;
1119             e.flushed = 1;
1120
1121             while (*(uintptr_t *) e.ip) {
1122                 code = *(ngx_http_script_code_pt *) e.ip;
1123                 code((ngx_http_script_engine_t *) &e);
1124             }
1125
1126             path.len = e.pos - path.data;
1127
1128             *e.pos++ = '\0';
1129
1130             if (alias && ngx_strncmp(name, clcf->name.data, alias) == 0) {
1131                 ngx_memcpy(name, name + alias, len - alias);
1132                 path.len -= alias;
1133             }
1134         }
1135
1136         test_dir = tf->test_dir;
1137
1138         tf++;
1139
1140         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1141                        "try to use file: \"%s\"", name);
1142
1143         if (tf->lengths == NULL && tf->name.len == 0) {
1144
1145             path.len -= root;
1146             path.data += root;
1147
1148             if (path.data[0] == '@') {
1149                 (void) ngx_http_named_location(r, &path);
1150
1151             } else {
1152                 (void) ngx_http_internal_redirect(r, &path, NULL);
1153             }
1154
1155             return NGX_OK;
1156         }
1157
1158         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1159
1160         of.directio = clcf->directio;
1161         of.valid = clcf->open_file_cache_valid;
1162         of.min_uses = clcf->open_file_cache_min_uses;
1163         of.errors = clcf->open_file_cache_errors;
1164         of.events = clcf->open_file_cache_events;
1165
1166         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1167             != NGX_OK)
1168         {
1169             if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
1170                 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1171                               ngx_open_file_n " \"%s\" failed", path.data);
1172             }
1173
1174             continue;
1175         }
1176
1177         if (of.is_dir && !test_dir) {
1178             continue;
1179         }
1180
1181         path.len -= root;
1182         path.data += root;
1183
1184         if (!alias) {
1185             r->uri = path;
1186
1187         } else {
1188             r->uri.len = alias + path.len;
1189             r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1190             if (r->uri.data == NULL) {
1191                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1192                 return NGX_OK;
1193             }
1194
1195             p = ngx_copy(r->uri.data, clcf->name.data, alias);
1196             ngx_memcpy(p, name, path.len);
1197         }
1198
1199         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1200                        "try file uri: \"%V\"", &r->uri);
1201
1202         r->phase_handler++;
1203         return NGX_AGAIN;
1204     }
1205
1206     /* not reached */
1207 }
1208
1209
1210 ngx_int_t
1211 ngx_http_core_content_phase(ngx_http_request_t *r,
1212     ngx_http_phase_handler_t *ph)
1213 {
1214     size_t     root;
1215     ngx_int_t  rc;
1216     ngx_str_t  path;
1217
1218     if (r->content_handler) {
1219         r->write_event_handler = ngx_http_request_empty_handler;
1220         ngx_http_finalize_request(r, r->content_handler(r));
1221         return NGX_OK;
1222     }
1223
1224     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1225                    "content phase: %ui", r->phase_handler);
1226
1227     rc = ph->handler(r);
1228
1229     if (rc == NGX_DONE) {
1230         return NGX_OK;
1231     }
1232
1233     if (rc != NGX_DECLINED) {
1234         ngx_http_finalize_request(r, rc);
1235         return NGX_OK;
1236     }
1237
1238     /* rc == NGX_DECLINED */
1239
1240     ph++;
1241
1242     if (ph->checker) {
1243         r->phase_handler++;
1244         return NGX_AGAIN;
1245     }
1246
1247     /* no content handler was found */
1248
1249     if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
1250
1251         if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
1252             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1253                           "directory index of \"%s\" is forbidden", path.data);
1254         }
1255
1256         ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
1257         return NGX_OK;
1258     }
1259
1260     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
1261
1262     ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1263     return NGX_OK;
1264 }
1265
1266
1267 void
1268 ngx_http_update_location_config(ngx_http_request_t *r)
1269 {
1270     ngx_http_core_loc_conf_t  *clcf;
1271
1272     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1273
1274     if (r->method & clcf->limit_except) {
1275         r->loc_conf = clcf->limit_except_loc_conf;
1276         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1277     }
1278
1279     if (r == r->main) {
1280         r->connection->log->file = clcf->err_log->file;
1281
1282         if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1283             r->connection->log->log_level = clcf->err_log->log_level;
1284         }
1285     }
1286
1287     if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
1288         r->connection->sendfile = 1;
1289
1290     } else {
1291         r->connection->sendfile = 0;
1292     }
1293
1294     if (clcf->client_body_in_file_only) {
1295         r->request_body_in_file_only = 1;
1296         r->request_body_in_persistent_file = 1;
1297         r->request_body_in_clean_file =
1298             clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
1299         r->request_body_file_log_level = NGX_LOG_NOTICE;
1300
1301     } else {
1302         r->request_body_file_log_level = NGX_LOG_WARN;
1303     }
1304
1305     if (r->keepalive && clcf->keepalive_timeout == 0) {
1306         r->keepalive = 0;
1307     }
1308
1309     if (!clcf->tcp_nopush) {
1310         /* disable TCP_NOPUSH/TCP_CORK use */
1311         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
1312     }
1313
1314     if (r->limit_rate == 0) {
1315         r->limit_rate = clcf->limit_rate;
1316     }
1317
1318     if (clcf->handler) {
1319         r->content_handler = clcf->handler;
1320     }
1321 }
1322
1323
1324 /*
1325  * NGX_OK       - exact or regex match
1326  * NGX_DONE     - auto redirect
1327  * NGX_AGAIN    - inclusive match
1328  * NGX_ERROR    - regex error
1329  * NGX_DECLINED - no match
1330  */
1331
1332 static ngx_int_t
1333 ngx_http_core_find_location(ngx_http_request_t *r)
1334 {
1335     ngx_int_t                  rc;
1336     ngx_http_core_loc_conf_t  *pclcf;
1337 #if (NGX_PCRE)
1338     ngx_int_t                  n;
1339     ngx_uint_t                 noregex;
1340     ngx_http_core_loc_conf_t  *clcf, **clcfp;
1341
1342     noregex = 0;
1343 #endif
1344
1345     pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1346
1347     rc = ngx_http_core_find_static_location(r, pclcf->static_locations);
1348
1349     if (rc == NGX_AGAIN) {
1350
1351 #if (NGX_PCRE)
1352         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1353
1354         noregex = clcf->noregex;
1355 #endif
1356
1357         /* look up nested locations */
1358
1359         rc = ngx_http_core_find_location(r);
1360     }
1361
1362     if (rc == NGX_OK || rc == NGX_DONE) {
1363         return rc;
1364     }
1365
1366     /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */
1367
1368 #if (NGX_PCRE)
1369
1370     if (noregex == 0 && pclcf->regex_locations) {
1371
1372         for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
1373
1374             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1375                            "test location: ~ \"%V\"", &(*clcfp)->name);
1376
1377             n = ngx_regex_exec((*clcfp)->regex, &r->uri, NULL, 0);
1378
1379             if (n == NGX_REGEX_NO_MATCHED) {
1380                 continue;
1381             }
1382
1383             if (n < 0) {
1384                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1385                               ngx_regex_exec_n
1386                               " failed: %d on \"%V\" using \"%V\"",
1387                               n, &r->uri, &(*clcfp)->name);
1388                 return NGX_ERROR;
1389             }
1390
1391             /* match */
1392
1393             r->loc_conf = (*clcfp)->loc_conf;
1394
1395             /* look up nested locations */
1396
1397             rc = ngx_http_core_find_location(r);
1398
1399             return (rc == NGX_ERROR) ? rc : NGX_OK;
1400         }
1401     }
1402 #endif
1403
1404     return rc;
1405 }
1406
1407
1408 /*
1409  * NGX_OK       - exact match
1410  * NGX_DONE     - auto redirect
1411  * NGX_AGAIN    - inclusive match
1412  * NGX_DECLINED - no match
1413  */
1414
1415 static ngx_int_t
1416 ngx_http_core_find_static_location(ngx_http_request_t *r,
1417     ngx_http_location_tree_node_t *node)
1418 {
1419     u_char     *uri;
1420     size_t      len, n;
1421     ngx_int_t   rc, rv;
1422
1423     len = r->uri.len;
1424     uri = r->uri.data;
1425
1426     rv = NGX_DECLINED;
1427
1428     for ( ;; ) {
1429
1430         if (node == NULL) {
1431             return rv;
1432         }
1433
1434         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1435                        "test location: \"%*s\"", node->len, node->name);
1436
1437         n = (len <= (size_t) node->len) ? len : node->len;
1438
1439         rc = ngx_filename_cmp(uri, node->name, n);
1440
1441         if (rc != 0) {
1442             node = (rc < 0) ? node->left : node->right;
1443
1444             continue;
1445         }
1446
1447         if (len > (size_t) node->len) {
1448
1449             if (node->inclusive) {
1450
1451                 r->loc_conf = node->inclusive->loc_conf;
1452                 rv = NGX_AGAIN;
1453
1454                 node = node->tree;
1455                 uri += n;
1456                 len -= n;
1457
1458                 continue;
1459             }
1460
1461             /* exact only */
1462
1463             node = node->right;
1464
1465             continue;
1466         }
1467
1468         if (len == (size_t) node->len) {
1469
1470             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1471                                           node->inclusive->loc_conf;
1472             return NGX_OK;
1473         }
1474
1475         /* len < node->len */
1476
1477         if (len + 1 == (size_t) node->len && node->auto_redirect) {
1478
1479             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1480                                           node->inclusive->loc_conf;
1481             rv = NGX_DONE;
1482         }
1483
1484         node = node->left;
1485     }
1486 }
1487
1488
1489 void *
1490 ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
1491 {
1492     u_char       c, *p;
1493     ngx_uint_t   i, hash;
1494
1495     if (r->headers_out.content_type.len == 0) {
1496         return NULL;
1497     }
1498
1499     if (r->headers_out.content_type_lowcase == NULL) {
1500
1501         p = ngx_pnalloc(r->pool, r->headers_out.content_type_len);
1502
1503         if (p == NULL) {
1504             return NULL;
1505         }
1506
1507         r->headers_out.content_type_lowcase = p;
1508
1509         hash = 0;
1510
1511         for (i = 0; i < r->headers_out.content_type_len; i++) {
1512             c = ngx_tolower(r->headers_out.content_type.data[i]);
1513             hash = ngx_hash(hash, c);
1514             *p++ = c;
1515         }
1516
1517         r->headers_out.content_type_hash = hash;
1518     }
1519
1520     return ngx_hash_find(types_hash,
1521                          r->headers_out.content_type_hash,
1522                          r->headers_out.content_type_lowcase,
1523                          r->headers_out.content_type_len);
1524 }
1525
1526
1527 ngx_int_t
1528 ngx_http_set_content_type(ngx_http_request_t *r)
1529 {
1530     u_char                     c, *exten;
1531     ngx_str_t                 *type;
1532     ngx_uint_t                 i, hash;
1533     ngx_http_core_loc_conf_t  *clcf;
1534
1535     if (r->headers_out.content_type.len) {
1536         return NGX_OK;
1537     }
1538
1539     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1540
1541     if (r->exten.len) {
1542
1543         hash = 0;
1544
1545         for (i = 0; i < r->exten.len; i++) {
1546             c = r->exten.data[i];
1547
1548             if (c >= 'A' && c <= 'Z') {
1549
1550                 exten = ngx_pnalloc(r->pool, r->exten.len);
1551                 if (exten == NULL) {
1552                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
1553                 }
1554
1555                 hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);
1556
1557                 r->exten.data = exten;
1558
1559                 break;
1560             }
1561
1562             hash = ngx_hash(hash, c);
1563         }
1564
1565         type = ngx_hash_find(&clcf->types_hash, hash,
1566                              r->exten.data, r->exten.len);
1567
1568         if (type) {
1569             r->headers_out.content_type_len = type->len;
1570             r->headers_out.content_type = *type;
1571
1572             return NGX_OK;
1573         }
1574     }
1575
1576     r->headers_out.content_type_len = clcf->default_type.len;
1577     r->headers_out.content_type = clcf->default_type;
1578
1579     return NGX_OK;
1580 }
1581
1582
1583 ngx_int_t
1584 ngx_http_set_exten(ngx_http_request_t *r)
1585 {
1586     ngx_int_t  i;
1587
1588     r->exten.len = 0;
1589     r->exten.data = NULL;
1590
1591     for (i = r->uri.len - 1; i > 1; i--) {
1592         if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
1593
1594             r->exten.len = r->uri.len - i - 1;
1595             r->exten.data = &r->uri.data[i + 1];
1596
1597             break;
1598
1599         } else if (r->uri.data[i] == '/') {
1600             break;
1601         }
1602     }
1603
1604     return NGX_OK;
1605 }
1606
1607
1608 ngx_int_t
1609 ngx_http_send_header(ngx_http_request_t *r)
1610 {
1611     if (r->err_status) {
1612         r->headers_out.status = r->err_status;
1613         r->headers_out.status_line.len = 0;
1614     }
1615
1616     return ngx_http_top_header_filter(r);
1617 }
1618
1619
1620 ngx_int_t
1621 ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
1622 {
1623     ngx_int_t  rc;
1624
1625     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1626                    "http output filter \"%V?%V\"", &r->uri, &r->args);
1627
1628     rc = ngx_http_top_body_filter(r, in);
1629
1630     if (rc == NGX_ERROR) {
1631         /* NGX_ERROR may be returned by any filter */
1632         r->connection->error = 1;
1633     }
1634
1635     return rc;
1636 }
1637
1638
1639 u_char *
1640 ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
1641     size_t *root_length, size_t reserved)
1642 {
1643     u_char                    *last;
1644     size_t                     alias;
1645     ngx_http_core_loc_conf_t  *clcf;
1646
1647     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1648
1649     alias = clcf->alias ? clcf->name.len : 0;
1650
1651     if (alias && !r->valid_location) {
1652         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1653                       "\"alias\" could not be used in location \"%V\" "
1654                       "where URI was rewritten", &clcf->name);
1655         return NULL;
1656     }
1657
1658     reserved += r->uri.len - alias + 1;
1659
1660     if (clcf->root_lengths == NULL) {
1661
1662         *root_length = clcf->root.len;
1663
1664         path->len = clcf->root.len + reserved;
1665
1666         path->data = ngx_pnalloc(r->pool, path->len);
1667         if (path->data == NULL) {
1668             return NULL;
1669         }
1670
1671         last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
1672
1673     } else {
1674         if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
1675                                 clcf->root_values->elts)
1676             == NULL)
1677         {
1678             return NULL;
1679         }
1680
1681         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0)== NGX_ERROR)
1682         {
1683             return NULL;
1684         }
1685
1686         *root_length = path->len - reserved;
1687         last = path->data + *root_length;
1688     }
1689
1690     last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
1691
1692     return last;
1693 }
1694
1695
1696 ngx_int_t
1697 ngx_http_auth_basic_user(ngx_http_request_t *r)
1698 {
1699     ngx_str_t   auth, encoded;
1700     ngx_uint_t  len;
1701
1702     if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
1703         return NGX_DECLINED;
1704     }
1705
1706     if (r->headers_in.authorization == NULL) {
1707         r->headers_in.user.data = (u_char *) "";
1708         return NGX_DECLINED;
1709     }
1710
1711     encoded = r->headers_in.authorization->value;
1712
1713     if (encoded.len < sizeof("Basic ") - 1
1714         || ngx_strncasecmp(encoded.data, (u_char *) "Basic ",
1715                            sizeof("Basic ") - 1)
1716            != 0)
1717     {
1718         r->headers_in.user.data = (u_char *) "";
1719         return NGX_DECLINED;
1720     }
1721
1722     encoded.len -= sizeof("Basic ") - 1;
1723     encoded.data += sizeof("Basic ") - 1;
1724
1725     while (encoded.len && encoded.data[0] == ' ') {
1726         encoded.len--;
1727         encoded.data++;
1728     }
1729
1730     if (encoded.len == 0) {
1731         r->headers_in.user.data = (u_char *) "";
1732         return NGX_DECLINED;
1733     }
1734
1735     auth.len = ngx_base64_decoded_length(encoded.len);
1736     auth.data = ngx_pnalloc(r->pool, auth.len + 1);
1737     if (auth.data == NULL) {
1738         return NGX_ERROR;
1739     }
1740
1741     if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
1742         r->headers_in.user.data = (u_char *) "";
1743         return NGX_DECLINED;
1744     }
1745
1746     auth.data[auth.len] = '\0';
1747
1748     for (len = 0; len < auth.len; len++) {
1749         if (auth.data[len] == ':') {
1750             break;
1751         }
1752     }
1753
1754     if (len == 0 || len == auth.len) {
1755         r->headers_in.user.data = (u_char *) "";
1756         return NGX_DECLINED;
1757     }
1758
1759     r->headers_in.user.len = len;
1760     r->headers_in.user.data = auth.data;
1761     r->headers_in.passwd.len = auth.len - len - 1;
1762     r->headers_in.passwd.data = &auth.data[len + 1];
1763
1764     return NGX_OK;
1765 }
1766
1767
1768 ngx_int_t
1769 ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
1770 {
1771     socklen_t            len;
1772     ngx_connection_t    *c;
1773     struct sockaddr_in   sin;
1774
1775     /* AF_INET only */
1776
1777     c = r->connection;
1778
1779     if (r->in_addr == 0) {
1780         len = sizeof(struct sockaddr_in);
1781         if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
1782             ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1783             return NGX_ERROR;
1784         }
1785
1786         r->in_addr = sin.sin_addr.s_addr;
1787
1788     } else {
1789         sin.sin_family = c->sockaddr->sa_family;
1790         sin.sin_addr.s_addr = r->in_addr;
1791     }
1792
1793     if (s == NULL) {
1794         return NGX_OK;
1795     }
1796
1797     s->len = ngx_sock_ntop((struct sockaddr *) &sin, s->data,
1798                            NGX_INET_ADDRSTRLEN);
1799
1800     return NGX_OK;
1801 }
1802
1803
1804 #if (NGX_HTTP_GZIP)
1805
1806 ngx_int_t
1807 ngx_http_gzip_ok(ngx_http_request_t *r)
1808 {
1809     time_t                     date, expires;
1810     ngx_uint_t                 p;
1811     ngx_array_t               *cc;
1812     ngx_table_elt_t           *e, *d;
1813     ngx_http_core_loc_conf_t  *clcf;
1814
1815     if (r->gzip == 1) {
1816         return NGX_OK;
1817     }
1818
1819     if (r->gzip == 2) {
1820         return NGX_DECLINED;
1821     }
1822
1823     r->gzip = 2;
1824
1825     if (r != r->main
1826         || r->headers_in.accept_encoding == NULL
1827         || ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
1828                            "gzip", 4 - 1)
1829            == NULL
1830
1831         /*
1832          * if the URL (without the "http://" prefix) is longer than 253 bytes,
1833          * then MSIE 4.x can not handle the compressed stream - it waits
1834          * too long, hangs up or crashes
1835          */
1836
1837         || (r->headers_in.msie4 && r->unparsed_uri.len > 200))
1838     {
1839         return NGX_DECLINED;
1840     }
1841
1842     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1843
1844     if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
1845         return NGX_DECLINED;
1846     }
1847
1848     if (r->http_version < clcf->gzip_http_version) {
1849         return NGX_DECLINED;
1850     }
1851
1852     if (r->headers_in.via == NULL) {
1853         goto ok;
1854     }
1855
1856     p = clcf->gzip_proxied;
1857
1858     if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
1859         return NGX_DECLINED;
1860     }
1861
1862     if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
1863         goto ok;
1864     }
1865
1866     if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
1867         goto ok;
1868     }
1869
1870     e = r->headers_out.expires;
1871
1872     if (e) {
1873
1874         if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
1875             return NGX_DECLINED;
1876         }
1877
1878         expires = ngx_http_parse_time(e->value.data, e->value.len);
1879         if (expires == NGX_ERROR) {
1880             return NGX_DECLINED;
1881         }
1882
1883         d = r->headers_out.date;
1884
1885         if (d) {
1886             date = ngx_http_parse_time(d->value.data, d->value.len);
1887             if (date == NGX_ERROR) {
1888                 return NGX_DECLINED;
1889             }
1890
1891         } else {
1892             date = ngx_time();
1893         }
1894
1895         if (expires < date) {
1896             goto ok;
1897         }
1898
1899         return NGX_DECLINED;
1900     }
1901
1902     cc = &r->headers_out.cache_control;
1903
1904     if (cc->elts) {
1905
1906         if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
1907             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
1908                                                  NULL)
1909                >= 0)
1910         {
1911             goto ok;
1912         }
1913
1914         if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
1915             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
1916                                                  NULL)
1917                >= 0)
1918         {
1919             goto ok;
1920         }
1921
1922         if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
1923             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
1924                                                  NULL)
1925                >= 0)
1926         {
1927             goto ok;
1928         }
1929
1930         return NGX_DECLINED;
1931     }
1932
1933     if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
1934         return NGX_DECLINED;
1935     }
1936
1937     if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
1938         return NGX_DECLINED;
1939     }
1940
1941 ok:
1942
1943 #if (NGX_PCRE)
1944
1945     if (clcf->gzip_disable && r->headers_in.user_agent) {
1946
1947         if (ngx_regex_exec_array(clcf->gzip_disable,
1948                                  &r->headers_in.user_agent->value,
1949                                  r->connection->log)
1950             != NGX_DECLINED)
1951         {
1952             return NGX_DECLINED;
1953         }
1954     }
1955
1956 #endif
1957
1958     r->gzip = 1;
1959
1960     return NGX_OK;
1961 }
1962
1963 #endif
1964
1965
1966 ngx_int_t
1967 ngx_http_subrequest(ngx_http_request_t *r,
1968     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
1969     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
1970 {
1971     ngx_connection_t              *c;
1972     ngx_http_request_t            *sr;
1973     ngx_http_core_srv_conf_t      *cscf;
1974     ngx_http_postponed_request_t  *pr, *p;
1975
1976     r->main->subrequests--;
1977
1978     if (r->main->subrequests == 0) {
1979         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1980                       "subrequests cycle while processing \"%V\"", uri);
1981         r->main->subrequests = 1;
1982         return NGX_ERROR;
1983     }
1984
1985     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
1986     if (sr == NULL) {
1987         return NGX_ERROR;
1988     }
1989
1990     sr->signature = NGX_HTTP_MODULE;
1991
1992     c = r->connection;
1993     sr->connection = c;
1994
1995     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
1996     if (sr->ctx == NULL) {
1997         return NGX_ERROR;
1998     }
1999
2000     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
2001                       sizeof(ngx_table_elt_t))
2002         == NGX_ERROR)
2003     {
2004         return NGX_ERROR;
2005     }
2006
2007     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2008     sr->main_conf = cscf->ctx->main_conf;
2009     sr->srv_conf = cscf->ctx->srv_conf;
2010     sr->loc_conf = cscf->ctx->loc_conf;
2011
2012     sr->pool = r->pool;
2013
2014     sr->headers_in = r->headers_in;
2015
2016     ngx_http_clear_content_length(sr);
2017     ngx_http_clear_accept_ranges(sr);
2018     ngx_http_clear_last_modified(sr);
2019
2020     sr->request_body = r->request_body;
2021
2022     sr->method = NGX_HTTP_GET;
2023     sr->http_version = r->http_version;
2024
2025     sr->request_line = r->request_line;
2026     sr->uri = *uri;
2027
2028     if (args) {
2029         sr->args = *args;
2030     }
2031
2032     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2033                    "http subrequest \"%V?%V\"", uri, &sr->args);
2034
2035     sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
2036     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
2037     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
2038
2039     sr->unparsed_uri = r->unparsed_uri;
2040     sr->method_name = ngx_http_core_get_method;
2041     sr->http_protocol = r->http_protocol;
2042
2043     if (ngx_http_set_exten(sr) != NGX_OK) {
2044         return NGX_ERROR;
2045     }
2046
2047     sr->main = r->main;
2048     sr->parent = r;
2049     sr->post_subrequest = ps;
2050     sr->read_event_handler = ngx_http_request_empty_handler;
2051     sr->write_event_handler = ngx_http_handler;
2052
2053     if (c->data == r && r->postponed == NULL) {
2054         c->data = sr;
2055     }
2056
2057     sr->in_addr = r->in_addr;
2058     sr->port = r->port;
2059     sr->port_text = r->port_text;
2060
2061     sr->variables = r->variables;
2062
2063     sr->log_handler = r->log_handler;
2064
2065     pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
2066     if (pr == NULL) {
2067         return NGX_ERROR;
2068     }
2069
2070     pr->request = sr;
2071     pr->out = NULL;
2072     pr->next = NULL;
2073
2074     if (r->postponed) {
2075         for (p = r->postponed; p->next; p = p->next) { /* void */ }
2076         p->next = pr;
2077
2078     } else {
2079         r->postponed = pr;
2080     }
2081
2082     sr->internal = 1;
2083
2084     sr->discard_body = r->discard_body;
2085     sr->expect_tested = 1;
2086     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
2087
2088     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
2089
2090     r->main->subrequests++;
2091
2092     *psr = sr;
2093
2094     return ngx_http_post_request(sr);
2095 }
2096
2097
2098 ngx_int_t
2099 ngx_http_internal_redirect(ngx_http_request_t *r,
2100     ngx_str_t *uri, ngx_str_t *args)
2101 {
2102     ngx_http_core_srv_conf_t  *cscf;
2103
2104     r->uri_changes--;
2105
2106     if (r->uri_changes == 0) {
2107         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2108                       "rewrite or internal redirection cycle "
2109                       "while internal redirect to \"%V\"", uri);
2110
2111         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2112         return NGX_DONE;
2113     }
2114
2115     r->uri = *uri;
2116
2117     if (args) {
2118         r->args = *args;
2119
2120     } else {
2121         r->args.len = 0;
2122         r->args.data = NULL;
2123     }
2124
2125     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2126                    "internal redirect: \"%V?%V\"", uri, &r->args);
2127
2128     if (ngx_http_set_exten(r) != NGX_OK) {
2129         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2130         return NGX_DONE;
2131     }
2132
2133     /* clear the modules contexts */
2134     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2135
2136     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2137     r->loc_conf = cscf->ctx->loc_conf;
2138
2139     ngx_http_update_location_config(r);
2140
2141     r->internal = 1;
2142
2143     ngx_http_handler(r);
2144
2145     return NGX_DONE;
2146 }
2147
2148
2149 ngx_int_t
2150 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
2151 {
2152     ngx_http_core_srv_conf_t    *cscf;
2153     ngx_http_core_loc_conf_t   **clcfp;
2154     ngx_http_core_main_conf_t   *cmcf;
2155
2156     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2157
2158     if (cscf->named_locations) {
2159
2160         for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
2161
2162             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2163                            "test location: \"%V\"", &(*clcfp)->name);
2164
2165             if (name->len != (*clcfp)->name.len
2166                 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
2167             {
2168                 continue;
2169             }
2170
2171             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2172                            "using location: %V \"%V?%V\"",
2173                            name, &r->uri, &r->args);
2174
2175             r->internal = 1;
2176             r->content_handler = NULL;
2177             r->loc_conf = (*clcfp)->loc_conf;
2178
2179             ngx_http_update_location_config(r);
2180
2181             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2182
2183             r->phase_handler = cmcf->phase_engine.location_rewrite_index;
2184
2185             ngx_http_core_run_phases(r);
2186
2187             return NGX_DONE;
2188         }
2189     }
2190
2191     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2192                   "could not find named location \"%V\"", name);
2193
2194     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2195
2196     return NGX_DONE;
2197 }
2198
2199
2200 ngx_http_cleanup_t *
2201 ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
2202 {
2203     ngx_http_cleanup_t  *cln;
2204
2205     r = r->main;
2206
2207     cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
2208     if (cln == NULL) {
2209         return NULL;
2210     }
2211
2212     if (size) {
2213         cln->data = ngx_palloc(r->pool, size);
2214         if (cln->data == NULL) {
2215             return NULL;
2216         }
2217
2218     } else {
2219         cln->data = NULL;
2220     }
2221
2222     cln->handler = NULL;
2223     cln->next = r->cleanup;
2224
2225     r->cleanup = cln;
2226
2227     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2228                    "http cleanup add: %p", cln);
2229
2230     return cln;
2231 }
2232
2233
2234 static char *
2235 ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2236 {
2237     char                        *rv;
2238     void                        *mconf;
2239     ngx_uint_t                   i;
2240     ngx_conf_t                   pcf;
2241     ngx_http_module_t           *module;
2242     ngx_http_conf_ctx_t         *ctx, *http_ctx;
2243     ngx_http_core_srv_conf_t    *cscf, **cscfp;
2244     ngx_http_core_main_conf_t   *cmcf;
2245
2246     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2247     if (ctx == NULL) {
2248         return NGX_CONF_ERROR;
2249     }
2250
2251     http_ctx = cf->ctx;
2252     ctx->main_conf = http_ctx->main_conf;
2253
2254     /* the server{}'s srv_conf */
2255
2256     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2257     if (ctx->srv_conf == NULL) {
2258         return NGX_CONF_ERROR;
2259     }
2260
2261     /* the server{}'s loc_conf */
2262
2263     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2264     if (ctx->loc_conf == NULL) {
2265         return NGX_CONF_ERROR;
2266     }
2267
2268     for (i = 0; ngx_modules[i]; i++) {
2269         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2270             continue;
2271         }
2272
2273         module = ngx_modules[i]->ctx;
2274
2275         if (module->create_srv_conf) {
2276             mconf = module->create_srv_conf(cf);
2277             if (mconf == NULL) {
2278                 return NGX_CONF_ERROR;
2279             }
2280
2281             ctx->srv_conf[ngx_modules[i]->ctx_index] = mconf;
2282         }
2283
2284         if (module->create_loc_conf) {
2285             mconf = module->create_loc_conf(cf);
2286             if (mconf == NULL) {
2287                 return NGX_CONF_ERROR;
2288             }
2289
2290             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
2291         }
2292     }
2293
2294
2295     /* the server configuration context */
2296
2297     cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
2298     cscf->ctx = ctx;
2299
2300
2301     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
2302
2303     cscfp = ngx_array_push(&cmcf->servers);
2304     if (cscfp == NULL) {
2305         return NGX_CONF_ERROR;
2306     }
2307
2308     *cscfp = cscf;
2309
2310
2311     /* parse inside server{} */
2312
2313     pcf = *cf;
2314     cf->ctx = ctx;
2315     cf->cmd_type = NGX_HTTP_SRV_CONF;
2316
2317     rv = ngx_conf_parse(cf, NULL);
2318
2319     *cf = pcf;
2320
2321     return rv;
2322 }
2323
2324
2325 static char *
2326 ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2327 {
2328     char                      *rv;
2329     u_char                    *mod;
2330     size_t                     len;
2331     ngx_str_t                 *value, *name;
2332     ngx_uint_t                 i;
2333     ngx_conf_t                 save;
2334     ngx_http_module_t         *module;
2335     ngx_http_conf_ctx_t       *ctx, *pctx;
2336     ngx_http_core_loc_conf_t  *clcf, *pclcf;
2337
2338     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2339     if (ctx == NULL) {
2340         return NGX_CONF_ERROR;
2341     }
2342
2343     pctx = cf->ctx;
2344     ctx->main_conf = pctx->main_conf;
2345     ctx->srv_conf = pctx->srv_conf;
2346
2347     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2348     if (ctx->loc_conf == NULL) {
2349         return NGX_CONF_ERROR;
2350     }
2351
2352     for (i = 0; ngx_modules[i]; i++) {
2353         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2354             continue;
2355         }
2356
2357         module = ngx_modules[i]->ctx;
2358
2359         if (module->create_loc_conf) {
2360             ctx->loc_conf[ngx_modules[i]->ctx_index] =
2361                                                    module->create_loc_conf(cf);
2362             if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) {
2363                  return NGX_CONF_ERROR;
2364             }
2365         }
2366     }
2367
2368     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
2369     clcf->loc_conf = ctx->loc_conf;
2370
2371     value = cf->args->elts;
2372
2373     if (cf->args->nelts == 3) {
2374
2375         len = value[1].len;
2376         mod = value[1].data;
2377         name = &value[2];
2378
2379         if (len == 1 && mod[0] == '=') {
2380
2381             clcf->name = *name;
2382             clcf->exact_match = 1;
2383
2384         } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
2385
2386             clcf->name = *name;
2387             clcf->noregex = 1;
2388
2389         } else if (len == 1 && mod[0] == '~') {
2390
2391             if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2392                 return NGX_CONF_ERROR;
2393             }
2394
2395         } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
2396
2397             if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2398                 return NGX_CONF_ERROR;
2399             }
2400
2401         } else {
2402             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2403                                "invalid location modifier \"%V\"", &value[1]);
2404             return NGX_CONF_ERROR;
2405         }
2406
2407     } else {
2408
2409         name = &value[1];
2410
2411         if (name->data[0] == '=') {
2412
2413             clcf->name.len = name->len - 1;
2414             clcf->name.data = name->data + 1;
2415             clcf->exact_match = 1;
2416
2417         } else if (name->data[0] == '^' && name->data[1] == '~') {
2418
2419             clcf->name.len = name->len - 2;
2420             clcf->name.data = name->data + 2;
2421             clcf->noregex = 1;
2422
2423         } else if (name->data[0] == '~') {
2424
2425             name->len--;
2426             name->data++;
2427
2428             if (name->data[0] == '*') {
2429
2430                 name->len--;
2431                 name->data++;
2432
2433                 if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2434                     return NGX_CONF_ERROR;
2435                 }
2436
2437             } else {
2438                 if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2439                     return NGX_CONF_ERROR;
2440                 }
2441             }
2442
2443         } else {
2444
2445             clcf->name = *name;
2446
2447             if (name->data[0] == '@') {
2448                 clcf->named = 1;
2449             }
2450         }
2451     }
2452
2453     pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
2454
2455     if (pclcf->name.len) {
2456
2457         /* nested location */
2458
2459 #if 0
2460         clcf->prev_location = pclcf;
2461 #endif
2462
2463         if (pclcf->exact_match) {
2464             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2465                                "location \"%V\" could not be inside "
2466                                "the exact location \"%V\"",
2467                                &clcf->name, &pclcf->name);
2468             return NGX_CONF_ERROR;
2469         }
2470
2471         if (pclcf->named) {
2472             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2473                                "location \"%V\" could not be inside "
2474                                "the named location \"%V\"",
2475                                &clcf->name, &pclcf->name);
2476             return NGX_CONF_ERROR;
2477         }
2478
2479         if (clcf->named) {
2480             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2481                                "named location \"%V\" must be "
2482                                "on server level only",
2483                                &clcf->name);
2484             return NGX_CONF_ERROR;
2485         }
2486
2487         len = pclcf->name.len;
2488
2489 #if (NGX_PCRE)
2490         if (clcf->regex == NULL
2491             && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2492 #else
2493         if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2494 #endif
2495         {
2496             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2497                                "location \"%V\" is outside location \"%V\"",
2498                                &clcf->name, &pclcf->name);
2499             return NGX_CONF_ERROR;
2500         }
2501     }
2502
2503     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
2504         return NGX_CONF_ERROR;
2505     }
2506
2507     save = *cf;
2508     cf->ctx = ctx;
2509     cf->cmd_type = NGX_HTTP_LOC_CONF;
2510
2511     rv = ngx_conf_parse(cf, NULL);
2512
2513     *cf = save;
2514
2515     return rv;
2516 }
2517
2518
2519 static ngx_int_t
2520 ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
2521     ngx_str_t *regex, ngx_uint_t caseless)
2522 {
2523 #if (NGX_PCRE)
2524     ngx_str_t  err;
2525     u_char     errstr[NGX_MAX_CONF_ERRSTR];
2526
2527     err.len = NGX_MAX_CONF_ERRSTR;
2528     err.data = errstr;
2529
2530     clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
2531                                     cf->pool, &err);
2532
2533     if (clcf->regex == NULL) {
2534         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
2535         return NGX_ERROR;
2536     }
2537
2538     clcf->name = *regex;
2539
2540     return NGX_OK;
2541
2542 #else
2543
2544     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2545                        "the using of the regex \"%V\" requires PCRE library",
2546                        regex);
2547     return NGX_ERROR;
2548
2549 #endif
2550 }
2551
2552
2553 static char *
2554 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2555 {
2556     ngx_http_core_loc_conf_t *lcf = conf;
2557
2558     char        *rv;
2559     ngx_conf_t   save;
2560
2561     if (lcf->types == NULL) {
2562         lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
2563         if (lcf->types == NULL) {
2564             return NGX_CONF_ERROR;
2565         }
2566     }
2567
2568     save = *cf;
2569     cf->handler = ngx_http_core_type;
2570     cf->handler_conf = conf;
2571
2572     rv = ngx_conf_parse(cf, NULL);
2573
2574     *cf = save;
2575
2576     return rv;
2577 }
2578
2579
2580 static char *
2581 ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
2582 {
2583     ngx_http_core_loc_conf_t *lcf = conf;
2584
2585     ngx_str_t       *value, *content_type, *old, file;
2586     ngx_uint_t       i, n, hash;
2587     ngx_hash_key_t  *type;
2588
2589     value = cf->args->elts;
2590
2591     if (ngx_strcmp(value[0].data, "include") == 0) {
2592         file = value[1];
2593
2594         if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){
2595             return NGX_CONF_ERROR;
2596         }
2597
2598         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
2599
2600         return ngx_conf_parse(cf, &file);
2601     }
2602
2603     content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
2604     if (content_type == NULL) {
2605         return NGX_CONF_ERROR;
2606     }
2607
2608     *content_type = value[0];
2609
2610     for (i = 1; i < cf->args->nelts; i++) {
2611
2612         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
2613
2614         type = lcf->types->elts;
2615         for (n = 0; n < lcf->types->nelts; n++) {
2616             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
2617                 old = type[n].value;
2618                 type[n].value = content_type;
2619
2620                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2621                                    "duplicate extention \"%V\", "
2622                                    "content type: \"%V\", "
2623                                    "old content type: \"%V\"",
2624                                    &value[i], content_type, old);
2625                 continue;
2626             }
2627         }
2628
2629
2630         type = ngx_array_push(lcf->types);
2631         if (type == NULL) {
2632             return NGX_CONF_ERROR;
2633         }
2634
2635         type->key = value[i];
2636         type->key_hash = hash;
2637         type->value = content_type;
2638     }
2639
2640     return NGX_CONF_OK;
2641 }
2642
2643
2644 static ngx_int_t
2645 ngx_http_core_preconfiguration(ngx_conf_t *cf)
2646 {
2647     return ngx_http_variables_add_core_vars(cf);
2648 }
2649
2650
2651 static void *
2652 ngx_http_core_create_main_conf(ngx_conf_t *cf)
2653 {
2654     ngx_http_core_main_conf_t  *cmcf;
2655
2656     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
2657     if (cmcf == NULL) {
2658         return NGX_CONF_ERROR;
2659     }
2660
2661     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
2662                        sizeof(ngx_http_core_srv_conf_t *))
2663         != NGX_OK)
2664     {
2665         return NGX_CONF_ERROR;
2666     }
2667
2668     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
2669     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
2670
2671     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
2672     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
2673
2674     return cmcf;
2675 }
2676
2677
2678 static char *
2679 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
2680 {
2681     ngx_http_core_main_conf_t *cmcf = conf;
2682
2683     if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
2684         cmcf->server_names_hash_max_size = 512;
2685     }
2686
2687     if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2688         cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
2689     }
2690
2691     cmcf->server_names_hash_bucket_size =
2692             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
2693
2694
2695     if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
2696         cmcf->variables_hash_max_size = 512;
2697     }
2698
2699     if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2700         cmcf->variables_hash_bucket_size = 64;
2701     }
2702
2703     cmcf->variables_hash_bucket_size =
2704                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
2705
2706     return NGX_CONF_OK;
2707 }
2708
2709
2710 static void *
2711 ngx_http_core_create_srv_conf(ngx_conf_t *cf)
2712 {
2713     ngx_http_core_srv_conf_t  *cscf;
2714
2715     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
2716     if (cscf == NULL) {
2717         return NGX_CONF_ERROR;
2718     }
2719
2720     /*
2721      * set by ngx_pcalloc():
2722      *
2723      *     conf->client_large_buffers.num = 0;
2724      */
2725
2726     if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t))
2727         == NGX_ERROR)
2728     {
2729         return NGX_CONF_ERROR;
2730     }
2731
2732     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
2733                        sizeof(ngx_http_server_name_t))
2734         == NGX_ERROR)
2735     {
2736         return NGX_CONF_ERROR;
2737     }
2738
2739     cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
2740     cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
2741     cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
2742     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
2743     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
2744     cscf->merge_slashes = NGX_CONF_UNSET;
2745     cscf->underscores_in_headers = NGX_CONF_UNSET;
2746
2747     return cscf;
2748 }
2749
2750
2751 static char *
2752 ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
2753 {
2754     ngx_http_core_srv_conf_t *prev = parent;
2755     ngx_http_core_srv_conf_t *conf = child;
2756
2757     ngx_http_listen_t       *ls;
2758     ngx_http_server_name_t  *sn;
2759
2760     /* TODO: it does not merge, it inits only */
2761
2762     if (conf->listen.nelts == 0) {
2763         ls = ngx_array_push(&conf->listen);
2764         if (ls == NULL) {
2765             return NGX_CONF_ERROR;
2766         }
2767
2768         ngx_memzero(ls, sizeof(ngx_http_listen_t));
2769
2770         ls->addr = INADDR_ANY;
2771 #if (NGX_WIN32)
2772         ls->port = 80;
2773 #else
2774         /* STUB: getuid() should be cached */
2775         ls->port = (getuid() == 0) ? 80 : 8000;
2776 #endif
2777         ls->family = AF_INET;
2778
2779         ls->conf.backlog = NGX_LISTEN_BACKLOG;
2780         ls->conf.rcvbuf = -1;
2781         ls->conf.sndbuf = -1;
2782     }
2783
2784     if (conf->server_name.data == NULL) {
2785         conf->server_name = cf->cycle->hostname;
2786
2787         sn = ngx_array_push(&conf->server_names);
2788         if (sn == NULL) {
2789             return NGX_CONF_ERROR;
2790         }
2791
2792 #if (NGX_PCRE)
2793         sn->regex = NULL;
2794 #endif
2795         sn->core_srv_conf = conf;
2796         sn->name.len = conf->server_name.len;
2797         sn->name.data = conf->server_name.data;
2798     }
2799
2800     ngx_conf_merge_size_value(conf->connection_pool_size,
2801                               prev->connection_pool_size, 256);
2802     ngx_conf_merge_size_value(conf->request_pool_size,
2803                               prev->request_pool_size, 4096);
2804     ngx_conf_merge_msec_value(conf->client_header_timeout,
2805                               prev->client_header_timeout, 60000);
2806     ngx_conf_merge_size_value(conf->client_header_buffer_size,
2807                               prev->client_header_buffer_size, 1024);
2808     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
2809                               prev->large_client_header_buffers,
2810                               4, ngx_pagesize);
2811
2812     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
2813         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2814                            "the \"large_client_header_buffers\" size must be "
2815                            "equal to or bigger than \"connection_pool_size\"");
2816         return NGX_CONF_ERROR;
2817     }
2818
2819     ngx_conf_merge_value(conf->ignore_invalid_headers,
2820                               prev->ignore_invalid_headers, 1);
2821
2822     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
2823
2824     ngx_conf_merge_value(conf->underscores_in_headers,
2825                               prev->underscores_in_headers, 0);
2826
2827     return NGX_CONF_OK;
2828 }
2829
2830
2831 static void *
2832 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
2833 {
2834     ngx_http_core_loc_conf_t  *lcf;
2835
2836     lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
2837     if (lcf == NULL) {
2838         return NGX_CONF_ERROR;
2839     }
2840
2841     /*
2842      * set by ngx_pcalloc():
2843      *
2844      *     lcf->root = { 0, NULL };
2845      *     lcf->limit_except = 0;
2846      *     lcf->post_action = { 0, NULL };
2847      *     lcf->types = NULL;
2848      *     lcf->default_type = { 0, NULL };
2849      *     lcf->err_log = NULL;
2850      *     lcf->error_pages = NULL;
2851      *     lcf->try_files = NULL;
2852      *     lcf->client_body_path = NULL;
2853      *     lcf->regex = NULL;
2854      *     lcf->exact_match = 0;
2855      *     lcf->auto_redirect = 0;
2856      *     lcf->alias = 0;
2857      *     lcf->gzip_proxied = 0;
2858      */
2859
2860     lcf->client_max_body_size = NGX_CONF_UNSET;
2861     lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
2862     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
2863     lcf->satisfy = NGX_CONF_UNSET_UINT;
2864     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
2865     lcf->internal = NGX_CONF_UNSET;
2866     lcf->client_body_in_file_only = NGX_CONF_UNSET;
2867     lcf->sendfile = NGX_CONF_UNSET;
2868     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
2869     lcf->directio = NGX_CONF_UNSET;
2870     lcf->tcp_nopush = NGX_CONF_UNSET;
2871     lcf->tcp_nodelay = NGX_CONF_UNSET;
2872     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
2873     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
2874     lcf->postpone_output = NGX_CONF_UNSET_SIZE;
2875     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
2876     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
2877     lcf->keepalive_header = NGX_CONF_UNSET;
2878     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
2879     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
2880     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
2881     lcf->reset_timedout_connection = NGX_CONF_UNSET;
2882     lcf->server_name_in_redirect = NGX_CONF_UNSET;
2883     lcf->port_in_redirect = NGX_CONF_UNSET;
2884     lcf->msie_padding = NGX_CONF_UNSET;
2885     lcf->msie_refresh = NGX_CONF_UNSET;
2886     lcf->log_not_found = NGX_CONF_UNSET;
2887     lcf->log_subrequest = NGX_CONF_UNSET;
2888     lcf->recursive_error_pages = NGX_CONF_UNSET;
2889     lcf->server_tokens = NGX_CONF_UNSET;
2890     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
2891     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
2892
2893     lcf->open_file_cache = NGX_CONF_UNSET_PTR;
2894     lcf->open_file_cache_valid = NGX_CONF_UNSET;
2895     lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
2896     lcf->open_file_cache_errors = NGX_CONF_UNSET;
2897     lcf->open_file_cache_events = NGX_CONF_UNSET;
2898
2899 #if (NGX_HTTP_GZIP)
2900     lcf->gzip_vary = NGX_CONF_UNSET;
2901     lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
2902 #if (NGX_PCRE)
2903     lcf->gzip_disable = NGX_CONF_UNSET_PTR;
2904     lcf->gzip_disable_msie6 = 3;
2905 #endif
2906 #endif
2907
2908     return lcf;
2909 }
2910
2911
2912 static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
2913 static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
2914 static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
2915
2916 static ngx_hash_key_t  ngx_http_core_default_types[] = {
2917     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
2918     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
2919     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
2920     { ngx_null_string, 0, NULL }
2921 };
2922
2923
2924 static char *
2925 ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2926 {
2927     ngx_http_core_loc_conf_t *prev = parent;
2928     ngx_http_core_loc_conf_t *conf = child;
2929
2930     ngx_uint_t        i;
2931     ngx_hash_key_t   *type;
2932     ngx_hash_init_t   types_hash;
2933
2934     if (conf->root.data == NULL) {
2935
2936         conf->alias = prev->alias;
2937         conf->root = prev->root;
2938         conf->root_lengths = prev->root_lengths;
2939         conf->root_values = prev->root_values;
2940
2941         if (prev->root.data == NULL) {
2942             conf->root.len = sizeof("html") - 1;
2943             conf->root.data = (u_char *) "html";
2944
2945             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) {
2946                 return NGX_CONF_ERROR;
2947             }
2948         }
2949     }
2950
2951     if (conf->post_action.data == NULL) {
2952         conf->post_action = prev->post_action;
2953     }
2954
2955     ngx_conf_merge_uint_value(conf->types_hash_max_size,
2956                               prev->types_hash_max_size, 1024);
2957
2958     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
2959                               prev->types_hash_bucket_size,
2960                               ngx_cacheline_size);
2961
2962     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
2963                                              ngx_cacheline_size);
2964
2965     /*
2966      * the special handling the "types" directive in the "http" section
2967      * to inherit the http's conf->types_hash to all servers
2968      */
2969
2970     if (prev->types && prev->types_hash.buckets == NULL) {
2971
2972         types_hash.hash = &prev->types_hash;
2973         types_hash.key = ngx_hash_key_lc;
2974         types_hash.max_size = conf->types_hash_max_size;
2975         types_hash.bucket_size = conf->types_hash_bucket_size;
2976         types_hash.name = "types_hash";
2977         types_hash.pool = cf->pool;
2978         types_hash.temp_pool = NULL;
2979
2980         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
2981             != NGX_OK)
2982         {
2983             return NGX_CONF_ERROR;
2984         }
2985     }
2986
2987     if (conf->types == NULL) {
2988         conf->types = prev->types;
2989         conf->types_hash = prev->types_hash;
2990     }
2991
2992     if (conf->types == NULL) {
2993         conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
2994         if (conf->types == NULL) {
2995             return NGX_CONF_ERROR;
2996         }
2997
2998         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
2999             type = ngx_array_push(conf->types);
3000             if (type == NULL) {
3001                 return NGX_CONF_ERROR;
3002             }
3003
3004             type->key = ngx_http_core_default_types[i].key;
3005             type->key_hash =
3006                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3007                                        ngx_http_core_default_types[i].key.len);
3008             type->value = ngx_http_core_default_types[i].value;
3009         }
3010     }
3011
3012     if (conf->types_hash.buckets == NULL) {
3013
3014         types_hash.hash = &conf->types_hash;
3015         types_hash.key = ngx_hash_key_lc;
3016         types_hash.max_size = conf->types_hash_max_size;
3017         types_hash.bucket_size = conf->types_hash_bucket_size;
3018         types_hash.name = "mime_types_hash";
3019         types_hash.pool = cf->pool;
3020         types_hash.temp_pool = NULL;
3021
3022         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3023             != NGX_OK)
3024         {
3025             return NGX_CONF_ERROR;
3026         }
3027     }
3028
3029     if (conf->err_log == NULL) {
3030         if (prev->err_log) {
3031             conf->err_log = prev->err_log;
3032         } else {
3033             conf->err_log = cf->cycle->new_log;
3034         }
3035     }
3036
3037     if (conf->error_pages == NULL && prev->error_pages) {
3038         conf->error_pages = prev->error_pages;
3039     }
3040
3041     ngx_conf_merge_str_value(conf->default_type,
3042                               prev->default_type, "text/plain");
3043
3044     ngx_conf_merge_off_value(conf->client_max_body_size,
3045                               prev->client_max_body_size, 1 * 1024 * 1024);
3046     ngx_conf_merge_size_value(conf->client_body_buffer_size,
3047                               prev->client_body_buffer_size,
3048                               (size_t) 2 * ngx_pagesize);
3049     ngx_conf_merge_msec_value(conf->client_body_timeout,
3050                               prev->client_body_timeout, 60000);
3051
3052     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3053                               NGX_HTTP_SATISFY_ALL);
3054     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3055                               0);
3056     ngx_conf_merge_value(conf->internal, prev->internal, 0);
3057     ngx_conf_merge_value(conf->client_body_in_file_only,
3058                               prev->client_body_in_file_only, 0);
3059     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3060     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3061                               prev->sendfile_max_chunk, 0);
3062     ngx_conf_merge_off_value(conf->directio, prev->directio,
3063                               NGX_MAX_OFF_T_VALUE);
3064     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3065     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3066
3067     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3068     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3069     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3070                               1460);
3071     ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3072     ngx_conf_merge_msec_value(conf->keepalive_timeout,
3073                               prev->keepalive_timeout, 75000);
3074     ngx_conf_merge_sec_value(conf->keepalive_header,
3075                               prev->keepalive_header, 0);
3076     ngx_conf_merge_msec_value(conf->lingering_time,
3077                               prev->lingering_time, 30000);
3078     ngx_conf_merge_msec_value(conf->lingering_timeout,
3079                               prev->lingering_timeout, 5000);
3080     ngx_conf_merge_msec_value(conf->resolver_timeout,
3081                               prev->resolver_timeout, 30000);
3082
3083     if (conf->resolver == NULL) {
3084
3085         if (prev->resolver == NULL) {
3086
3087             /*
3088              * create dummy resolver in http {} context
3089              * to inherit it in all servers
3090              */
3091
3092             prev->resolver = ngx_resolver_create(cf, NULL);
3093             if (prev->resolver == NULL) {
3094                 return NGX_CONF_ERROR;
3095             }
3096         }
3097
3098         conf->resolver = prev->resolver;
3099     }
3100
3101     ngx_conf_merge_path_value(conf->client_body_temp_path,
3102                               prev->client_body_temp_path,
3103                               NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
3104                               ngx_garbage_collector_temp_handler, cf);
3105
3106     ngx_conf_merge_value(conf->reset_timedout_connection,
3107                               prev->reset_timedout_connection, 0);
3108     ngx_conf_merge_value(conf->server_name_in_redirect,
3109                               prev->server_name_in_redirect, 1);
3110     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3111     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3112     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3113     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3114     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3115     ngx_conf_merge_value(conf->recursive_error_pages,
3116                               prev->recursive_error_pages, 0);
3117     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
3118
3119     ngx_conf_merge_ptr_value(conf->open_file_cache,
3120                               prev->open_file_cache, NULL);
3121
3122     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3123                               prev->open_file_cache_valid, 60);
3124
3125     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3126                               prev->open_file_cache_min_uses, 1);
3127
3128     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3129                               prev->open_file_cache_errors, 0);
3130
3131     ngx_conf_merge_sec_value(conf->open_file_cache_events,
3132                               prev->open_file_cache_events, 0);
3133 #if (NGX_HTTP_GZIP)
3134
3135     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3136     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3137                               NGX_HTTP_VERSION_11);
3138     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3139                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3140
3141 #if (NGX_PCRE)
3142     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3143 #endif
3144
3145     if (conf->gzip_disable_msie6 == 3) {
3146         conf->gzip_disable_msie6 =
3147             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3148     }
3149
3150 #endif
3151
3152     return NGX_CONF_OK;
3153 }
3154
3155
3156 /* AF_INET only */
3157
3158 static char *
3159 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3160 {
3161     ngx_http_core_srv_conf_t *scf = conf;
3162
3163     ngx_str_t          *value, size;
3164     ngx_url_t           u;
3165     ngx_uint_t          n;
3166     ngx_http_listen_t  *ls;
3167
3168     /*
3169      * TODO: check duplicate 'listen' directives,
3170      *       add resolved name to server names ???
3171      */
3172
3173     value = cf->args->elts;
3174
3175     ngx_memzero(&u, sizeof(ngx_url_t));
3176
3177     u.url = value[1];
3178     u.listen = 1;
3179     u.default_port = 80;
3180
3181     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3182         if (u.err) {
3183             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3184                                "%s in \"%V\" of the \"listen\" directive",
3185                                u.err, &u.url);
3186         }
3187
3188         return NGX_CONF_ERROR;
3189     }
3190
3191     ls = ngx_array_push(&scf->listen);
3192     if (ls == NULL) {
3193         return NGX_CONF_ERROR;
3194     }
3195
3196     ngx_memzero(ls, sizeof(ngx_http_listen_t));
3197
3198     ls->family = u.family;
3199     ls->addr = u.addr.in_addr;
3200     ls->port = u.port;
3201     ls->file_name = cf->conf_file->file.name.data;
3202     ls->line = cf->conf_file->line;
3203     ls->conf.backlog = NGX_LISTEN_BACKLOG;
3204     ls->conf.rcvbuf = -1;
3205     ls->conf.sndbuf = -1;
3206
3207     n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, NGX_INET_ADDRSTRLEN);
3208     ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port);
3209
3210     if (cf->args->nelts == 2) {
3211         return NGX_CONF_OK;
3212     }
3213
3214     if (ngx_strcmp(value[2].data, "default") == 0) {
3215         ls->conf.default_server = 1;
3216         n = 3;
3217
3218     } else {
3219         n = 2;
3220     }
3221
3222     for ( /* void */ ; n < cf->args->nelts; n++) {
3223
3224         if (ls->conf.default_server == 0) {
3225             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3226                                "\"%V\" parameter can be specified for "
3227                                "the default \"listen\" directive only",
3228                                &value[n]);
3229             return NGX_CONF_ERROR;
3230         }
3231
3232         if (ngx_strcmp(value[n].data, "bind") == 0) {
3233             ls->conf.bind = 1;
3234             continue;
3235         }
3236
3237         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
3238             ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
3239             ls->conf.bind = 1;
3240
3241             if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
3242                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3243                                    "invalid backlog \"%V\"", &value[n]);
3244                 return NGX_CONF_ERROR;
3245             }
3246
3247             continue;
3248         }
3249
3250         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
3251             size.len = value[n].len - 7;
3252             size.data = value[n].data + 7;
3253
3254             ls->conf.rcvbuf = ngx_parse_size(&size);
3255             ls->conf.bind = 1;
3256
3257             if (ls->conf.rcvbuf == NGX_ERROR) {
3258                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3259                                    "invalid rcvbuf \"%V\"", &value[n]);
3260                 return NGX_CONF_ERROR;
3261             }
3262
3263             continue;
3264         }
3265
3266         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
3267             size.len = value[n].len - 7;
3268             size.data = value[n].data + 7;
3269
3270             ls->conf.sndbuf = ngx_parse_size(&size);
3271             ls->conf.bind = 1;
3272
3273             if (ls->conf.sndbuf == NGX_ERROR) {
3274                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3275                                    "invalid sndbuf \"%V\"", &value[n]);
3276                 return NGX_CONF_ERROR;
3277             }
3278
3279             continue;
3280         }
3281
3282         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
3283 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
3284             ls->conf.accept_filter = (char *) &value[n].data[14];
3285             ls->conf.bind = 1;
3286 #else
3287             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3288                                "accept filters \"%V\" are not supported "
3289                                "on this platform, ignored",
3290                                &value[n]);
3291 #endif
3292             continue;
3293         }
3294
3295         if (ngx_strcmp(value[n].data, "deferred") == 0) {
3296 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
3297             ls->conf.deferred_accept = 1;
3298             ls->conf.bind = 1;
3299 #else
3300             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3301                                "the deferred accept is not supported "
3302                                "on this platform, ignored");
3303 #endif
3304             continue;
3305         }
3306
3307         if (ngx_strcmp(value[n].data, "ssl") == 0) {
3308 #if (NGX_HTTP_SSL)
3309             ls->conf.ssl = 1;
3310             continue;
3311 #else
3312             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3313                                "the \"ssl\" parameter requires "
3314                                "ngx_http_ssl_module");
3315             return NGX_CONF_ERROR;
3316 #endif
3317         }
3318
3319         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3320                            "the invalid \"%V\" parameter", &value[n]);
3321         return NGX_CONF_ERROR;
3322     }
3323
3324     return NGX_CONF_OK;
3325 }
3326
3327
3328 static char *
3329 ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3330 {
3331     ngx_http_core_srv_conf_t *cscf = conf;
3332
3333     u_char                   ch;
3334     ngx_str_t               *value, name;
3335     ngx_uint_t               i;
3336     ngx_http_server_name_t  *sn;
3337
3338     value = cf->args->elts;
3339
3340     ch = value[1].data[0];
3341
3342     if (cscf->server_name.data == NULL) {
3343         if (value[1].len) {
3344             name = value[1];
3345
3346             if (ch == '.') {
3347                 name.len--;
3348                 name.data++;
3349             }
3350
3351             cscf->server_name.len = name.len;
3352             cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
3353             if (cscf->server_name.data == NULL) {
3354                 return NGX_CONF_ERROR;
3355             }
3356
3357         } else {
3358             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3359                                "the first server name must not be empty");
3360             return NGX_CONF_ERROR;
3361         }
3362     }
3363
3364     for (i = 1; i < cf->args->nelts; i++) {
3365
3366         ch = value[i].data[0];
3367
3368         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
3369             || (ch == '.' && value[i].len < 2))
3370         {
3371             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3372                                "server name \"%V\" is invalid", &value[i]);
3373             return NGX_CONF_ERROR;
3374         }
3375
3376         if (ngx_strchr(value[i].data, '/')) {
3377             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3378                                "server name \"%V\" has strange symbols",
3379                                &value[i]);
3380         }
3381
3382         if (value[i].len == 1 && ch == '*') {
3383             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3384                                "\"server_name *\" is unsupported, use "
3385                                "\"server_name_in_redirect off\" instead");
3386             return NGX_CONF_ERROR;
3387         }
3388
3389         sn = ngx_array_push(&cscf->server_names);
3390         if (sn == NULL) {
3391             return NGX_CONF_ERROR;
3392         }
3393
3394 #if (NGX_PCRE)
3395         sn->regex = NULL;
3396 #endif
3397         sn->core_srv_conf = cscf;
3398         sn->name = value[i];
3399
3400         if (value[i].data[0] != '~') {
3401             continue;
3402         }
3403
3404 #if (NGX_PCRE)
3405         {
3406         ngx_str_t  err;
3407         u_char     errstr[NGX_MAX_CONF_ERRSTR];
3408
3409         err.len = NGX_MAX_CONF_ERRSTR;
3410         err.data = errstr;
3411
3412         value[i].len--;
3413         value[i].data++;
3414
3415         sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
3416
3417         if (sn->regex == NULL) {
3418             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
3419             return NGX_CONF_ERROR;
3420         }
3421
3422         sn->name = value[i];
3423         }
3424 #else
3425         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3426                            "the using of the regex \"%V\" "
3427                            "requires PCRE library", &value[i]);
3428
3429         return NGX_CONF_ERROR;
3430 #endif
3431     }
3432
3433     return NGX_CONF_OK;
3434 }
3435
3436
3437 static char *
3438 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3439 {
3440     ngx_http_core_loc_conf_t *lcf = conf;
3441
3442     ngx_str_t                  *value;
3443     ngx_uint_t                  alias, n;
3444     ngx_http_script_compile_t   sc;
3445
3446     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
3447
3448     if (lcf->root.data) {
3449
3450         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
3451
3452         if ((ngx_uint_t) lcf->alias == alias) {
3453             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3454                                "\"%V\" directive is duplicate",
3455                                &cmd->name);
3456         } else {
3457             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3458                                "\"%V\" directive is duplicate, "
3459                                "\"%s\" directive is specified before",
3460                                &cmd->name, lcf->alias ? "alias" : "root");
3461         }
3462
3463         return NGX_CONF_ERROR;
3464     }
3465
3466     if (lcf->named && alias) {
3467         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3468                            "the \"alias\" directive may not be used "
3469                            "inside named location");
3470
3471         return NGX_CONF_ERROR;
3472     }
3473
3474 #if (NGX_PCRE)
3475
3476     if (lcf->regex && alias) {
3477         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3478                            "the \"alias\" directive may not be used "
3479                            "inside location given by regular expression");
3480
3481         return NGX_CONF_ERROR;
3482     }
3483
3484 #endif
3485
3486     value = cf->args->elts;
3487
3488     if (ngx_strstr(value[1].data, "$document_root")
3489         || ngx_strstr(value[1].data, "${document_root}"))
3490     {
3491         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3492                            "the $document_root variable may not be used "
3493                            "in the \"%V\" directive",
3494                            &cmd->name);
3495
3496         return NGX_CONF_ERROR;
3497     }
3498
3499     if (ngx_strstr(value[1].data, "$realpath_root")
3500         || ngx_strstr(value[1].data, "${realpath_root}"))
3501     {
3502         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3503                            "the $realpath_root variable may not be used "
3504                            "in the \"%V\" directive",
3505                            &cmd->name);
3506
3507         return NGX_CONF_ERROR;
3508     }
3509
3510     lcf->alias = alias;
3511     lcf->root = value[1];
3512
3513     if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
3514         lcf->root.len--;
3515     }
3516
3517     if (lcf->root.data[0] != '$') {
3518         if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) {
3519             return NGX_CONF_ERROR;
3520         }
3521     }
3522
3523     n = ngx_http_script_variables_count(&lcf->root);
3524
3525     if (n == 0) {
3526         return NGX_CONF_OK;
3527     }
3528
3529     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3530
3531     sc.cf = cf;
3532     sc.source = &lcf->root;
3533     sc.lengths = &lcf->root_lengths;
3534     sc.values = &lcf->root_values;
3535     sc.variables = n;
3536     sc.complete_lengths = 1;
3537     sc.complete_values = 1;
3538
3539     if (ngx_http_script_compile(&sc) != NGX_OK) {
3540         return NGX_CONF_ERROR;
3541     }
3542
3543     return NGX_CONF_OK;
3544 }
3545
3546
3547 static ngx_http_method_name_t  ngx_methods_names[] = {
3548    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
3549    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
3550    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
3551    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
3552    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
3553    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
3554    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
3555    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
3556    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
3557    { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
3558    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
3559    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
3560    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
3561    { NULL, 0 }
3562 };
3563
3564
3565 static char *
3566 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3567 {
3568     ngx_http_core_loc_conf_t *pclcf = conf;
3569
3570     char                      *rv;
3571     void                      *mconf;
3572     ngx_str_t                 *value;
3573     ngx_uint_t                 i;
3574     ngx_conf_t                 save;
3575     ngx_http_module_t         *module;
3576     ngx_http_conf_ctx_t       *ctx, *pctx;
3577     ngx_http_method_name_t    *name;
3578     ngx_http_core_loc_conf_t  *clcf;
3579
3580     if (pclcf->limit_except) {
3581         return "duplicate";
3582     }
3583
3584     pclcf->limit_except = 0xffffffff;
3585
3586     value = cf->args->elts;
3587
3588     for (i = 1; i < cf->args->nelts; i++) {
3589         for (name = ngx_methods_names; name->name; name++) {
3590
3591             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
3592                 pclcf->limit_except &= name->method;
3593                 goto next;
3594             }
3595         }
3596
3597         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3598                            "invalid method \"%V\"", &value[i]);
3599         return NGX_CONF_ERROR;
3600
3601     next:
3602         continue;
3603     }
3604
3605     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
3606         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
3607     }
3608
3609     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3610     if (ctx == NULL) {
3611         return NGX_CONF_ERROR;
3612     }
3613
3614     pctx = cf->ctx;
3615     ctx->main_conf = pctx->main_conf;
3616     ctx->srv_conf = pctx->srv_conf;
3617
3618     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
3619     if (ctx->loc_conf == NULL) {
3620         return NGX_CONF_ERROR;
3621     }
3622
3623     for (i = 0; ngx_modules[i]; i++) {
3624         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
3625             continue;
3626         }
3627
3628         module = ngx_modules[i]->ctx;
3629
3630         if (module->create_loc_conf) {
3631
3632             mconf = module->create_loc_conf(cf);
3633             if (mconf == NULL) {
3634                  return NGX_CONF_ERROR;
3635             }
3636
3637             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
3638         }
3639     }
3640
3641
3642     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
3643     pclcf->limit_except_loc_conf = ctx->loc_conf;
3644     clcf->loc_conf = ctx->loc_conf;
3645     clcf->name = pclcf->name;
3646     clcf->noname = 1;
3647
3648     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
3649         return NGX_CONF_ERROR;
3650     }
3651
3652     save = *cf;
3653     cf->ctx = ctx;
3654     cf->cmd_type = NGX_HTTP_LMT_CONF;
3655
3656     rv = ngx_conf_parse(cf, NULL);
3657
3658     *cf = save;
3659
3660     return rv;
3661 }
3662
3663
3664 static char *
3665 ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3666 {
3667     ngx_http_core_loc_conf_t *clcf = conf;
3668
3669     ngx_str_t  *value;
3670
3671     if (clcf->directio != NGX_CONF_UNSET) {
3672         return "is duplicate";
3673     }
3674
3675     value = cf->args->elts;
3676
3677     if (ngx_strcmp(value[1].data, "off") == 0) {
3678         clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
3679         return NGX_CONF_OK;
3680     }
3681
3682     clcf->directio = ngx_parse_offset(&value[1]);
3683     if (clcf->directio == (off_t) NGX_ERROR) {
3684         return "invalid value";
3685     }
3686
3687     return NGX_CONF_OK;
3688 }
3689
3690
3691 static char *
3692 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3693 {
3694     ngx_http_core_loc_conf_t *lcf = conf;
3695
3696     u_char                     *args;
3697     ngx_int_t                   overwrite;
3698     ngx_str_t                  *value, uri;
3699     ngx_uint_t                  i, n, nvar;
3700     ngx_array_t                *uri_lengths, *uri_values;
3701     ngx_http_err_page_t        *err;
3702     ngx_http_script_compile_t   sc;
3703
3704     if (lcf->error_pages == NULL) {
3705         lcf->error_pages = ngx_array_create(cf->pool, 4,
3706                                             sizeof(ngx_http_err_page_t));
3707         if (lcf->error_pages == NULL) {
3708             return NGX_CONF_ERROR;
3709         }
3710     }
3711
3712     value = cf->args->elts;
3713
3714     i = cf->args->nelts - 2;
3715
3716     if (value[i].data[0] == '=') {
3717         if (i == 1) {
3718             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3719                                "invalid value \"%V\"", &value[i]);
3720             return NGX_CONF_ERROR;
3721         }
3722
3723         if (value[i].len > 1) {
3724             overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
3725
3726             if (overwrite == NGX_ERROR) {
3727                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3728                                    "invalid value \"%V\"", &value[i]);
3729                 return NGX_CONF_ERROR;
3730             }
3731
3732         } else {
3733             overwrite = 0;
3734         }
3735
3736         n = 2;
3737
3738     } else {
3739         overwrite = -1;
3740         n = 1;
3741     }
3742
3743     uri = value[cf->args->nelts - 1];
3744     uri_lengths = NULL;
3745     uri_values = NULL;
3746
3747     nvar = ngx_http_script_variables_count(&uri);
3748
3749     if (nvar) {
3750         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3751
3752         sc.cf = cf;
3753         sc.source = &uri;
3754         sc.lengths = &uri_lengths;
3755         sc.values = &uri_values;
3756         sc.variables = nvar;
3757         sc.complete_lengths = 1;
3758         sc.complete_values = 1;
3759
3760         if (ngx_http_script_compile(&sc) != NGX_OK) {
3761             return NGX_CONF_ERROR;
3762         }
3763     }
3764
3765     args = (u_char *) ngx_strchr(uri.data, '?');
3766
3767     for (i = 1; i < cf->args->nelts - n; i++) {
3768         err = ngx_array_push(lcf->error_pages);
3769         if (err == NULL) {
3770             return NGX_CONF_ERROR;
3771         }
3772
3773         err->status = ngx_atoi(value[i].data, value[i].len);
3774
3775         if (err->status == NGX_ERROR || err->status == 499) {
3776             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3777                                "invalid value \"%V\"", &value[i]);
3778             return NGX_CONF_ERROR;
3779         }
3780
3781         if (err->status < 400 || err->status > 599) {
3782             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3783                                "value \"%V\" must be between 400 and 599",
3784                                &value[i]);
3785             return NGX_CONF_ERROR;
3786         }
3787
3788         if (overwrite >= 0) {
3789             err->overwrite = overwrite;
3790
3791         } else {
3792             switch (err->status) {
3793                 case NGX_HTTP_TO_HTTPS:
3794                 case NGX_HTTPS_CERT_ERROR:
3795                 case NGX_HTTPS_NO_CERT:
3796                     err->overwrite = NGX_HTTP_BAD_REQUEST;
3797                     break;
3798
3799                 default:
3800                     err->overwrite = err->status;
3801                     break;
3802             }
3803         }
3804
3805         if (args) {
3806             err->uri.len = args - uri.data;
3807             err->uri.data = uri.data;
3808             args++;
3809             err->args.len = (uri.data + uri.len) - args;
3810             err->args.data = args;
3811
3812         } else {
3813             err->uri = uri;
3814             err->args.len = 0;
3815             err->args.data = NULL;
3816         }
3817
3818         err->uri_lengths = uri_lengths;
3819         err->uri_values = uri_values;
3820     }
3821
3822     return NGX_CONF_OK;
3823 }
3824
3825
3826 static char *
3827 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3828 {
3829     ngx_http_core_loc_conf_t *clcf = conf;
3830
3831     ngx_str_t                  *value;
3832     ngx_uint_t                  i, n;
3833     ngx_http_try_file_t        *tf;
3834     ngx_http_script_compile_t   sc;
3835     ngx_http_core_main_conf_t  *cmcf;
3836
3837     if (clcf->try_files) {
3838         return "is duplicate";
3839     }
3840
3841     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
3842
3843     cmcf->try_files = 1;
3844
3845     tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
3846     if (tf == NULL) {
3847         return NGX_CONF_ERROR;
3848     }
3849
3850     clcf->try_files = tf;
3851
3852     value = cf->args->elts;
3853
3854     for (i = 0; i < cf->args->nelts - 1; i++) {
3855
3856         tf[i].name = value[i + 1];
3857
3858         if (tf[i].name.data[tf[i].name.len - 1] == '/') {
3859             tf[i].test_dir = 1;
3860             tf[i].name.len--;
3861         }
3862
3863         n = ngx_http_script_variables_count(&tf[i].name);
3864
3865         if (n) {
3866             ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3867
3868             sc.cf = cf;
3869             sc.source = &tf[i].name;
3870             sc.lengths = &tf[i].lengths;
3871             sc.values = &tf[i].values;
3872             sc.variables = n;
3873             sc.complete_lengths = 1;
3874             sc.complete_values = 1;
3875
3876             if (ngx_http_script_compile(&sc) != NGX_OK) {
3877                 return NGX_CONF_ERROR;
3878             }
3879
3880         } else {
3881             /* add trailing '\0' to length */
3882             tf[i].name.len++;
3883         }
3884     }
3885
3886     return NGX_CONF_OK;
3887 }
3888
3889
3890 static char *
3891 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3892 {
3893     ngx_http_core_loc_conf_t *lcf = conf;
3894
3895     time_t       inactive;
3896     ngx_str_t   *value, s;
3897     ngx_int_t    max;
3898     ngx_uint_t   i;
3899
3900     if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) {
3901         return "is duplicate";
3902     }
3903
3904     value = cf->args->elts;
3905
3906     max = 0;
3907     inactive = 60;
3908
3909     for (i = 1; i < cf->args->nelts; i++) {
3910
3911         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
3912
3913             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
3914             if (max == NGX_ERROR) {
3915                 goto failed;
3916             }
3917
3918             continue;
3919         }
3920
3921         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
3922
3923             s.len = value[i].len - 9;
3924             s.data = value[i].data + 9;
3925
3926             inactive = ngx_parse_time(&s, 1);
3927             if (inactive < 0) {
3928                 goto failed;
3929             }
3930
3931             continue;
3932         }
3933
3934         if (ngx_strcmp(value[i].data, "off") == 0) {
3935
3936             lcf->open_file_cache = NULL;
3937
3938             continue;
3939         }
3940
3941     failed:
3942
3943         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3944                            "invalid \"open_file_cache\" parameter \"%V\"",
3945                            &value[i]);
3946         return NGX_CONF_ERROR;
3947     }
3948
3949     if (lcf->open_file_cache == NULL) {
3950         return NGX_CONF_OK;
3951     }
3952
3953     if (max == 0) {
3954         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3955                            "\"open_file_cache\" must have \"max\" parameter");
3956         return NGX_CONF_ERROR;
3957     }
3958
3959     lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
3960     if (lcf->open_file_cache) {
3961         return NGX_CONF_OK;
3962     }
3963
3964     return NGX_CONF_ERROR;
3965 }
3966
3967
3968 static char *
3969 ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3970 {
3971     ngx_http_core_loc_conf_t *lcf = conf;
3972
3973     lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
3974     if (lcf->err_log == NULL) {
3975         return NGX_CONF_ERROR;
3976     }
3977
3978     return ngx_set_error_log_levels(cf, lcf->err_log);
3979 }
3980
3981
3982 static char *
3983 ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3984 {
3985     ngx_http_core_loc_conf_t *lcf = conf;
3986
3987     ngx_str_t  *value;
3988
3989     if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
3990         return "is duplicate";
3991     }
3992
3993     value = cf->args->elts;
3994
3995     lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
3996
3997     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
3998         return "invalid value";
3999     }
4000
4001     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
4002         return "value must be less than 597 hours";
4003     }
4004
4005     if (cf->args->nelts == 2) {
4006         return NGX_CONF_OK;
4007     }
4008
4009     lcf->keepalive_header = ngx_parse_time(&value[2], 1);
4010
4011     if (lcf->keepalive_header == NGX_ERROR) {
4012         return "invalid value";
4013     }
4014
4015     if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
4016         return "value must be less than 68 years";
4017     }
4018
4019     return NGX_CONF_OK;
4020 }
4021
4022
4023 static char *
4024 ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4025 {
4026     ngx_http_core_loc_conf_t *lcf = conf;
4027
4028     if (lcf->internal != NGX_CONF_UNSET) {
4029         return "is duplicate";
4030     }
4031
4032     lcf->internal = 1;
4033
4034     return NGX_CONF_OK;
4035 }
4036
4037
4038 static char *
4039 ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4040 {
4041     ngx_http_core_loc_conf_t  *clcf = conf;
4042
4043     ngx_url_t   u;
4044     ngx_str_t  *value;
4045
4046     if (clcf->resolver) {
4047         return "is duplicate";
4048     }
4049
4050     value = cf->args->elts;
4051
4052     ngx_memzero(&u, sizeof(ngx_url_t));
4053
4054     u.host = value[1];
4055     u.port = 53;
4056
4057     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
4058         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
4059         return NGX_CONF_ERROR;
4060     }
4061
4062     clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
4063     if (clcf->resolver == NULL) {
4064         return NGX_OK;
4065     }
4066
4067     return NGX_CONF_OK;
4068 }
4069
4070
4071 #if (NGX_HTTP_GZIP)
4072
4073 static char *
4074 ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4075 {
4076     ngx_http_core_loc_conf_t  *clcf = conf;
4077
4078 #if (NGX_PCRE)
4079
4080     ngx_str_t         err, *value;
4081     ngx_uint_t        i;
4082     ngx_regex_elt_t  *re;
4083     u_char            errstr[NGX_MAX_CONF_ERRSTR];
4084
4085     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
4086         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
4087                                               sizeof(ngx_regex_elt_t));
4088         if (clcf->gzip_disable == NULL) {
4089             return NGX_CONF_ERROR;
4090         }
4091     }
4092
4093     value = cf->args->elts;
4094
4095     err.len = NGX_MAX_CONF_ERRSTR;
4096     err.data = errstr;
4097
4098     for (i = 1; i < cf->args->nelts; i++) {
4099
4100         if (ngx_strcmp(value[1].data, "msie6") == 0) {
4101             clcf->gzip_disable_msie6 = 1;
4102             continue;
4103         }
4104
4105         re = ngx_array_push(clcf->gzip_disable);
4106         if (re == NULL) {
4107             return NGX_CONF_ERROR;
4108         }
4109
4110         re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
4111                                       &err);
4112
4113         if (re->regex == NULL) {
4114             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
4115             return NGX_CONF_ERROR;
4116         }
4117
4118         re->name = value[i].data;
4119     }
4120
4121     return NGX_CONF_OK;
4122
4123 #else
4124     ngx_str_t  *value;
4125
4126     value = cf->args->elts;
4127
4128     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) {
4129         clcf->gzip_disable_msie6 = 1;
4130         return NGX_CONF_OK;
4131     }
4132
4133     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4134                        "without PCRE library \"gzip_disable\" supports "
4135                        "builtin \"msie6\" mask only");
4136
4137     return NGX_CONF_ERROR;
4138 #endif
4139 }
4140
4141 #endif
4142
4143
4144 static char *
4145 ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
4146 {
4147 #if (NGX_FREEBSD)
4148     ssize_t *np = data;
4149
4150     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
4151         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4152                            "\"send_lowat\" must be less than %d "
4153                            "(sysctl net.inet.tcp.sendspace)",
4154                            ngx_freebsd_net_inet_tcp_sendspace);
4155
4156         return NGX_CONF_ERROR;
4157     }
4158
4159 #elif !(NGX_HAVE_SO_SNDLOWAT)
4160     ssize_t *np = data;
4161
4162     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4163                        "\"send_lowat\" is not supported, ignored");
4164
4165     *np = 0;
4166
4167 #endif
4168
4169     return NGX_CONF_OK;
4170 }
4171
4172
4173 static char *
4174 ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
4175 {
4176     size_t *sp = data;
4177
4178     if (*sp < NGX_MIN_POOL_SIZE) {
4179         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4180                            "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
4181
4182         return NGX_CONF_ERROR;
4183     }
4184
4185     return NGX_CONF_OK;
4186 }