upstream nginx-0.7.31
[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;
1038     ssize_t                       reserve, allocated;
1039     u_char                       *p, *name;
1040     ngx_str_t                     path;
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     path.len = 0;
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         tf++;
1137
1138         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1139                        "try to use file: \"%s\"", name);
1140
1141         if (tf->lengths == NULL && tf->name.len == 0) {
1142
1143             path.len -= root;
1144             path.data += root;
1145
1146             if (path.data[0] == '@') {
1147                 (void) ngx_http_named_location(r, &path);
1148
1149             } else {
1150                 (void) ngx_http_internal_redirect(r, &path, NULL);
1151             }
1152
1153             return NGX_OK;
1154         }
1155
1156         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
1157
1158         of.directio = clcf->directio;
1159         of.valid = clcf->open_file_cache_valid;
1160         of.min_uses = clcf->open_file_cache_min_uses;
1161         of.errors = clcf->open_file_cache_errors;
1162         of.events = clcf->open_file_cache_events;
1163
1164         if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
1165             != NGX_OK)
1166         {
1167             if (of.err != NGX_ENOENT && of.err != NGX_ENOTDIR) {
1168                 ngx_log_error(NGX_LOG_CRIT, r->connection->log, of.err,
1169                               ngx_open_file_n " \"%s\" failed", path.data);
1170             }
1171
1172             continue;
1173         }
1174
1175         if (!of.is_file) {
1176             continue;
1177         }
1178
1179         path.len -= root;
1180         path.data += root;
1181
1182         if (!alias) {
1183             r->uri = path;
1184
1185         } else {
1186             r->uri.len = alias + path.len;
1187             r->uri.data = ngx_pnalloc(r->pool, r->uri.len);
1188             if (r->uri.data == NULL) {
1189                 ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
1190                 return NGX_OK;
1191             }
1192
1193             p = ngx_copy(r->uri.data, clcf->name.data, alias);
1194             ngx_memcpy(p, name, path.len);
1195         }
1196
1197         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1198                        "try file uri: \"%V\"", &r->uri);
1199
1200         r->phase_handler++;
1201         return NGX_AGAIN;
1202     }
1203
1204     /* not reached */
1205 }
1206
1207
1208 ngx_int_t
1209 ngx_http_core_content_phase(ngx_http_request_t *r,
1210     ngx_http_phase_handler_t *ph)
1211 {
1212     size_t     root;
1213     ngx_int_t  rc;
1214     ngx_str_t  path;
1215
1216     if (r->content_handler) {
1217         r->write_event_handler = ngx_http_request_empty_handler;
1218         ngx_http_finalize_request(r, r->content_handler(r));
1219         return NGX_OK;
1220     }
1221
1222     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1223                    "content phase: %ui", r->phase_handler);
1224
1225     rc = ph->handler(r);
1226
1227     if (rc == NGX_DONE) {
1228         return NGX_OK;
1229     }
1230
1231     if (rc != NGX_DECLINED) {
1232         ngx_http_finalize_request(r, rc);
1233         return NGX_OK;
1234     }
1235
1236     /* rc == NGX_DECLINED */
1237
1238     ph++;
1239
1240     if (ph->checker) {
1241         r->phase_handler++;
1242         return NGX_AGAIN;
1243     }
1244
1245     /* no content handler was found */
1246
1247     if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
1248
1249         if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
1250             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1251                           "directory index of \"%s\" is forbidden", path.data);
1252         }
1253
1254         ngx_http_finalize_request(r, NGX_HTTP_FORBIDDEN);
1255         return NGX_OK;
1256     }
1257
1258     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no handler found");
1259
1260     ngx_http_finalize_request(r, NGX_HTTP_NOT_FOUND);
1261     return NGX_OK;
1262 }
1263
1264
1265 void
1266 ngx_http_update_location_config(ngx_http_request_t *r)
1267 {
1268     ngx_http_core_loc_conf_t  *clcf;
1269
1270     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1271
1272     if (r->method & clcf->limit_except) {
1273         r->loc_conf = clcf->limit_except_loc_conf;
1274         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1275     }
1276
1277     if (r == r->main) {
1278         r->connection->log->file = clcf->err_log->file;
1279
1280         if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
1281             r->connection->log->log_level = clcf->err_log->log_level;
1282         }
1283     }
1284
1285     if ((ngx_io.flags & NGX_IO_SENDFILE) && clcf->sendfile) {
1286         r->connection->sendfile = 1;
1287
1288     } else {
1289         r->connection->sendfile = 0;
1290     }
1291
1292     if (clcf->client_body_in_file_only) {
1293         r->request_body_in_file_only = 1;
1294         r->request_body_in_persistent_file = 1;
1295         r->request_body_in_clean_file =
1296             clcf->client_body_in_file_only == NGX_HTTP_REQUEST_BODY_FILE_CLEAN;
1297         r->request_body_file_log_level = NGX_LOG_NOTICE;
1298
1299     } else {
1300         r->request_body_file_log_level = NGX_LOG_WARN;
1301     }
1302
1303     if (r->keepalive && clcf->keepalive_timeout == 0) {
1304         r->keepalive = 0;
1305     }
1306
1307     if (!clcf->tcp_nopush) {
1308         /* disable TCP_NOPUSH/TCP_CORK use */
1309         r->connection->tcp_nopush = NGX_TCP_NOPUSH_DISABLED;
1310     }
1311
1312     if (r->limit_rate == 0) {
1313         r->limit_rate = clcf->limit_rate;
1314     }
1315
1316     if (clcf->handler) {
1317         r->content_handler = clcf->handler;
1318     }
1319 }
1320
1321
1322 /*
1323  * NGX_OK       - exact or regex match
1324  * NGX_DONE     - auto redirect
1325  * NGX_AGAIN    - inclusive match
1326  * NGX_ERROR    - regex error
1327  * NGX_DECLINED - no match
1328  */
1329
1330 static ngx_int_t
1331 ngx_http_core_find_location(ngx_http_request_t *r)
1332 {
1333     ngx_int_t                  rc;
1334     ngx_http_core_loc_conf_t  *pclcf;
1335 #if (NGX_PCRE)
1336     ngx_int_t                  n;
1337     ngx_uint_t                 noregex;
1338     ngx_http_core_loc_conf_t  *clcf, **clcfp;
1339
1340     noregex = 0;
1341 #endif
1342
1343     pclcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1344
1345     rc = ngx_http_core_find_static_location(r, pclcf->static_locations);
1346
1347     if (rc == NGX_AGAIN) {
1348
1349 #if (NGX_PCRE)
1350         clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1351
1352         noregex = clcf->noregex;
1353 #endif
1354
1355         /* look up nested locations */
1356
1357         rc = ngx_http_core_find_location(r);
1358     }
1359
1360     if (rc == NGX_OK || rc == NGX_DONE) {
1361         return rc;
1362     }
1363
1364     /* rc == NGX_DECLINED or rc == NGX_AGAIN in nested location */
1365
1366 #if (NGX_PCRE)
1367
1368     if (noregex == 0 && pclcf->regex_locations) {
1369
1370         for (clcfp = pclcf->regex_locations; *clcfp; clcfp++) {
1371
1372             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1373                            "test location: ~ \"%V\"", &(*clcfp)->name);
1374
1375             n = ngx_regex_exec((*clcfp)->regex, &r->uri, NULL, 0);
1376
1377             if (n == NGX_REGEX_NO_MATCHED) {
1378                 continue;
1379             }
1380
1381             if (n < 0) {
1382                 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1383                               ngx_regex_exec_n
1384                               " failed: %d on \"%V\" using \"%V\"",
1385                               n, &r->uri, &(*clcfp)->name);
1386                 return NGX_ERROR;
1387             }
1388
1389             /* match */
1390
1391             r->loc_conf = (*clcfp)->loc_conf;
1392
1393             /* look up nested locations */
1394
1395             rc = ngx_http_core_find_location(r);
1396
1397             return (rc == NGX_ERROR) ? rc : NGX_OK;
1398         }
1399     }
1400 #endif
1401
1402     return rc;
1403 }
1404
1405
1406 /*
1407  * NGX_OK       - exact match
1408  * NGX_DONE     - auto redirect
1409  * NGX_AGAIN    - inclusive match
1410  * NGX_DECLINED - no match
1411  */
1412
1413 static ngx_int_t
1414 ngx_http_core_find_static_location(ngx_http_request_t *r,
1415     ngx_http_location_tree_node_t *node)
1416 {
1417     u_char     *uri;
1418     size_t      len, n;
1419     ngx_int_t   rc, rv;
1420
1421     len = r->uri.len;
1422     uri = r->uri.data;
1423
1424     rv = NGX_DECLINED;
1425
1426     for ( ;; ) {
1427
1428         if (node == NULL) {
1429             return rv;
1430         }
1431
1432         ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1433                        "test location: \"%*s\"", node->len, node->name);
1434
1435         n = (len <= (size_t) node->len) ? len : node->len;
1436
1437         rc = ngx_filename_cmp(uri, node->name, n);
1438
1439         if (rc != 0) {
1440             node = (rc < 0) ? node->left : node->right;
1441
1442             continue;
1443         }
1444
1445         if (len > (size_t) node->len) {
1446
1447             if (node->inclusive) {
1448
1449                 r->loc_conf = node->inclusive->loc_conf;
1450                 rv = NGX_AGAIN;
1451
1452                 node = node->tree;
1453                 uri += n;
1454                 len -= n;
1455
1456                 continue;
1457             }
1458
1459             /* exact only */
1460
1461             node = node->right;
1462
1463             continue;
1464         }
1465
1466         if (len == (size_t) node->len) {
1467
1468             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1469                                           node->inclusive->loc_conf;
1470             return NGX_OK;
1471         }
1472
1473         /* len < node->len */
1474
1475         if (len + 1 == (size_t) node->len && node->auto_redirect) {
1476
1477             r->loc_conf = (node->exact) ? node->exact->loc_conf:
1478                                           node->inclusive->loc_conf;
1479             rv = NGX_DONE;
1480         }
1481
1482         node = node->left;
1483     }
1484 }
1485
1486
1487 void *
1488 ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
1489 {
1490     u_char       c, *p;
1491     ngx_uint_t   i, hash;
1492
1493     if (r->headers_out.content_type.len == 0) {
1494         return NULL;
1495     }
1496
1497     if (r->headers_out.content_type_lowcase == NULL) {
1498
1499         p = ngx_pnalloc(r->pool, r->headers_out.content_type_len);
1500
1501         if (p == NULL) {
1502             return NULL;
1503         }
1504
1505         r->headers_out.content_type_lowcase = p;
1506
1507         hash = 0;
1508
1509         for (i = 0; i < r->headers_out.content_type_len; i++) {
1510             c = ngx_tolower(r->headers_out.content_type.data[i]);
1511             hash = ngx_hash(hash, c);
1512             *p++ = c;
1513         }
1514
1515         r->headers_out.content_type_hash = hash;
1516     }
1517
1518     return ngx_hash_find(types_hash,
1519                          r->headers_out.content_type_hash,
1520                          r->headers_out.content_type_lowcase,
1521                          r->headers_out.content_type_len);
1522 }
1523
1524
1525 ngx_int_t
1526 ngx_http_set_content_type(ngx_http_request_t *r)
1527 {
1528     u_char                     c, *exten;
1529     ngx_str_t                 *type;
1530     ngx_uint_t                 i, hash;
1531     ngx_http_core_loc_conf_t  *clcf;
1532
1533     if (r->headers_out.content_type.len) {
1534         return NGX_OK;
1535     }
1536
1537     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1538
1539     if (r->exten.len) {
1540
1541         hash = 0;
1542
1543         for (i = 0; i < r->exten.len; i++) {
1544             c = r->exten.data[i];
1545
1546             if (c >= 'A' && c <= 'Z') {
1547
1548                 exten = ngx_pnalloc(r->pool, r->exten.len);
1549                 if (exten == NULL) {
1550                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
1551                 }
1552
1553                 hash = ngx_hash_strlow(exten, r->exten.data, r->exten.len);
1554
1555                 r->exten.data = exten;
1556
1557                 break;
1558             }
1559
1560             hash = ngx_hash(hash, c);
1561         }
1562
1563         type = ngx_hash_find(&clcf->types_hash, hash,
1564                              r->exten.data, r->exten.len);
1565
1566         if (type) {
1567             r->headers_out.content_type_len = type->len;
1568             r->headers_out.content_type = *type;
1569
1570             return NGX_OK;
1571         }
1572     }
1573
1574     r->headers_out.content_type_len = clcf->default_type.len;
1575     r->headers_out.content_type = clcf->default_type;
1576
1577     return NGX_OK;
1578 }
1579
1580
1581 ngx_int_t
1582 ngx_http_set_exten(ngx_http_request_t *r)
1583 {
1584     ngx_int_t  i;
1585
1586     r->exten.len = 0;
1587     r->exten.data = NULL;
1588
1589     for (i = r->uri.len - 1; i > 1; i--) {
1590         if (r->uri.data[i] == '.' && r->uri.data[i - 1] != '/') {
1591
1592             r->exten.len = r->uri.len - i - 1;
1593             r->exten.data = &r->uri.data[i + 1];
1594
1595             break;
1596
1597         } else if (r->uri.data[i] == '/') {
1598             break;
1599         }
1600     }
1601
1602     return NGX_OK;
1603 }
1604
1605
1606 ngx_int_t
1607 ngx_http_send_header(ngx_http_request_t *r)
1608 {
1609     if (r->err_status) {
1610         r->headers_out.status = r->err_status;
1611         r->headers_out.status_line.len = 0;
1612     }
1613
1614     return ngx_http_top_header_filter(r);
1615 }
1616
1617
1618 ngx_int_t
1619 ngx_http_output_filter(ngx_http_request_t *r, ngx_chain_t *in)
1620 {
1621     ngx_int_t  rc;
1622
1623     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1624                    "http output filter \"%V?%V\"", &r->uri, &r->args);
1625
1626     rc = ngx_http_top_body_filter(r, in);
1627
1628     if (rc == NGX_ERROR) {
1629         /* NGX_ERROR may be returned by any filter */
1630         r->connection->error = 1;
1631     }
1632
1633     return rc;
1634 }
1635
1636
1637 u_char *
1638 ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path,
1639     size_t *root_length, size_t reserved)
1640 {
1641     u_char                    *last;
1642     size_t                     alias;
1643     ngx_http_core_loc_conf_t  *clcf;
1644
1645     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1646
1647     alias = clcf->alias ? clcf->name.len : 0;
1648
1649     if (alias && !r->valid_location) {
1650         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
1651                       "\"alias\" could not be used in location \"%V\" "
1652                       "where URI was rewritten", &clcf->name);
1653         return NULL;
1654     }
1655
1656     reserved += r->uri.len - alias + 1;
1657
1658     if (clcf->root_lengths == NULL) {
1659
1660         *root_length = clcf->root.len;
1661
1662         path->len = clcf->root.len + reserved;
1663
1664         path->data = ngx_pnalloc(r->pool, path->len);
1665         if (path->data == NULL) {
1666             return NULL;
1667         }
1668
1669         last = ngx_copy(path->data, clcf->root.data, clcf->root.len);
1670
1671     } else {
1672         if (ngx_http_script_run(r, path, clcf->root_lengths->elts, reserved,
1673                                 clcf->root_values->elts)
1674             == NULL)
1675         {
1676             return NULL;
1677         }
1678
1679         if (ngx_conf_full_name((ngx_cycle_t *) ngx_cycle, path, 0)== NGX_ERROR)
1680         {
1681             return NULL;
1682         }
1683
1684         *root_length = path->len - reserved;
1685         last = path->data + *root_length;
1686     }
1687
1688     last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1);
1689
1690     return last;
1691 }
1692
1693
1694 ngx_int_t
1695 ngx_http_auth_basic_user(ngx_http_request_t *r)
1696 {
1697     ngx_str_t   auth, encoded;
1698     ngx_uint_t  len;
1699
1700     if (r->headers_in.user.len == 0 && r->headers_in.user.data != NULL) {
1701         return NGX_DECLINED;
1702     }
1703
1704     if (r->headers_in.authorization == NULL) {
1705         r->headers_in.user.data = (u_char *) "";
1706         return NGX_DECLINED;
1707     }
1708
1709     encoded = r->headers_in.authorization->value;
1710
1711     if (encoded.len < sizeof("Basic ") - 1
1712         || ngx_strncasecmp(encoded.data, (u_char *) "Basic ",
1713                            sizeof("Basic ") - 1)
1714            != 0)
1715     {
1716         r->headers_in.user.data = (u_char *) "";
1717         return NGX_DECLINED;
1718     }
1719
1720     encoded.len -= sizeof("Basic ") - 1;
1721     encoded.data += sizeof("Basic ") - 1;
1722
1723     while (encoded.len && encoded.data[0] == ' ') {
1724         encoded.len--;
1725         encoded.data++;
1726     }
1727
1728     if (encoded.len == 0) {
1729         r->headers_in.user.data = (u_char *) "";
1730         return NGX_DECLINED;
1731     }
1732
1733     auth.len = ngx_base64_decoded_length(encoded.len);
1734     auth.data = ngx_pnalloc(r->pool, auth.len + 1);
1735     if (auth.data == NULL) {
1736         return NGX_ERROR;
1737     }
1738
1739     if (ngx_decode_base64(&auth, &encoded) != NGX_OK) {
1740         r->headers_in.user.data = (u_char *) "";
1741         return NGX_DECLINED;
1742     }
1743
1744     auth.data[auth.len] = '\0';
1745
1746     for (len = 0; len < auth.len; len++) {
1747         if (auth.data[len] == ':') {
1748             break;
1749         }
1750     }
1751
1752     if (len == 0 || len == auth.len) {
1753         r->headers_in.user.data = (u_char *) "";
1754         return NGX_DECLINED;
1755     }
1756
1757     r->headers_in.user.len = len;
1758     r->headers_in.user.data = auth.data;
1759     r->headers_in.passwd.len = auth.len - len - 1;
1760     r->headers_in.passwd.data = &auth.data[len + 1];
1761
1762     return NGX_OK;
1763 }
1764
1765
1766 ngx_int_t
1767 ngx_http_server_addr(ngx_http_request_t *r, ngx_str_t *s)
1768 {
1769     socklen_t            len;
1770     ngx_connection_t    *c;
1771     struct sockaddr_in   sin;
1772
1773     /* AF_INET only */
1774
1775     c = r->connection;
1776
1777     if (r->in_addr == 0) {
1778         len = sizeof(struct sockaddr_in);
1779         if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
1780             ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1781             return NGX_ERROR;
1782         }
1783
1784         r->in_addr = sin.sin_addr.s_addr;
1785
1786     } else {
1787         sin.sin_family = c->sockaddr->sa_family;
1788         sin.sin_addr.s_addr = r->in_addr;
1789     }
1790
1791     if (s == NULL) {
1792         return NGX_OK;
1793     }
1794
1795     s->len = ngx_sock_ntop((struct sockaddr *) &sin, s->data,
1796                            NGX_INET_ADDRSTRLEN);
1797
1798     return NGX_OK;
1799 }
1800
1801
1802 #if (NGX_HTTP_GZIP)
1803
1804 ngx_int_t
1805 ngx_http_gzip_ok(ngx_http_request_t *r)
1806 {
1807     time_t                     date, expires;
1808     ngx_uint_t                 p;
1809     ngx_array_t               *cc;
1810     ngx_table_elt_t           *e, *d;
1811     ngx_http_core_loc_conf_t  *clcf;
1812
1813     if (r->gzip == 1) {
1814         return NGX_OK;
1815     }
1816
1817     if (r->gzip == 2) {
1818         return NGX_DECLINED;
1819     }
1820
1821     r->gzip = 2;
1822
1823     if (r != r->main
1824         || r->headers_in.accept_encoding == NULL
1825         || ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
1826                            "gzip", 4 - 1)
1827            == NULL
1828
1829         /*
1830          * if the URL (without the "http://" prefix) is longer than 253 bytes,
1831          * then MSIE 4.x can not handle the compressed stream - it waits
1832          * too long, hangs up or crashes
1833          */
1834
1835         || (r->headers_in.msie4 && r->unparsed_uri.len > 200))
1836     {
1837         return NGX_DECLINED;
1838     }
1839
1840     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1841
1842     if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
1843         return NGX_DECLINED;
1844     }
1845
1846     if (r->http_version < clcf->gzip_http_version) {
1847         return NGX_DECLINED;
1848     }
1849
1850     if (r->headers_in.via == NULL) {
1851         goto ok;
1852     }
1853
1854     p = clcf->gzip_proxied;
1855
1856     if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
1857         return NGX_DECLINED;
1858     }
1859
1860     if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
1861         goto ok;
1862     }
1863
1864     if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
1865         goto ok;
1866     }
1867
1868     e = r->headers_out.expires;
1869
1870     if (e) {
1871
1872         if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
1873             return NGX_DECLINED;
1874         }
1875
1876         expires = ngx_http_parse_time(e->value.data, e->value.len);
1877         if (expires == NGX_ERROR) {
1878             return NGX_DECLINED;
1879         }
1880
1881         d = r->headers_out.date;
1882
1883         if (d) {
1884             date = ngx_http_parse_time(d->value.data, d->value.len);
1885             if (date == NGX_ERROR) {
1886                 return NGX_DECLINED;
1887             }
1888
1889         } else {
1890             date = ngx_time();
1891         }
1892
1893         if (expires < date) {
1894             goto ok;
1895         }
1896
1897         return NGX_DECLINED;
1898     }
1899
1900     cc = &r->headers_out.cache_control;
1901
1902     if (cc->elts) {
1903
1904         if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
1905             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
1906                                                  NULL)
1907                >= 0)
1908         {
1909             goto ok;
1910         }
1911
1912         if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
1913             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
1914                                                  NULL)
1915                >= 0)
1916         {
1917             goto ok;
1918         }
1919
1920         if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
1921             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
1922                                                  NULL)
1923                >= 0)
1924         {
1925             goto ok;
1926         }
1927
1928         return NGX_DECLINED;
1929     }
1930
1931     if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
1932         return NGX_DECLINED;
1933     }
1934
1935     if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
1936         return NGX_DECLINED;
1937     }
1938
1939 ok:
1940
1941 #if (NGX_PCRE)
1942
1943     if (clcf->gzip_disable && r->headers_in.user_agent) {
1944
1945         if (ngx_regex_exec_array(clcf->gzip_disable,
1946                                  &r->headers_in.user_agent->value,
1947                                  r->connection->log)
1948             != NGX_DECLINED)
1949         {
1950             return NGX_DECLINED;
1951         }
1952     }
1953
1954 #endif
1955
1956     r->gzip = 1;
1957
1958     return NGX_OK;
1959 }
1960
1961 #endif
1962
1963
1964 ngx_int_t
1965 ngx_http_subrequest(ngx_http_request_t *r,
1966     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
1967     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
1968 {
1969     ngx_connection_t              *c;
1970     ngx_http_request_t            *sr;
1971     ngx_http_core_srv_conf_t      *cscf;
1972     ngx_http_postponed_request_t  *pr, *p;
1973
1974     r->main->subrequests--;
1975
1976     if (r->main->subrequests == 0) {
1977         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1978                       "subrequests cycle while processing \"%V\"", uri);
1979         r->main->subrequests = 1;
1980         return NGX_ERROR;
1981     }
1982
1983     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
1984     if (sr == NULL) {
1985         return NGX_ERROR;
1986     }
1987
1988     sr->signature = NGX_HTTP_MODULE;
1989
1990     c = r->connection;
1991     sr->connection = c;
1992
1993     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
1994     if (sr->ctx == NULL) {
1995         return NGX_ERROR;
1996     }
1997
1998     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
1999                       sizeof(ngx_table_elt_t))
2000         == NGX_ERROR)
2001     {
2002         return NGX_ERROR;
2003     }
2004
2005     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2006     sr->main_conf = cscf->ctx->main_conf;
2007     sr->srv_conf = cscf->ctx->srv_conf;
2008     sr->loc_conf = cscf->ctx->loc_conf;
2009
2010     sr->pool = r->pool;
2011
2012     sr->headers_in = r->headers_in;
2013
2014     ngx_http_clear_content_length(sr);
2015     ngx_http_clear_accept_ranges(sr);
2016     ngx_http_clear_last_modified(sr);
2017
2018     sr->request_body = r->request_body;
2019
2020     sr->method = NGX_HTTP_GET;
2021     sr->http_version = r->http_version;
2022
2023     sr->request_line = r->request_line;
2024     sr->uri = *uri;
2025
2026     if (args) {
2027         sr->args = *args;
2028     }
2029
2030     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2031                    "http subrequest \"%V?%V\"", uri, &sr->args);
2032
2033     sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
2034     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
2035     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
2036
2037     sr->unparsed_uri = r->unparsed_uri;
2038     sr->method_name = ngx_http_core_get_method;
2039     sr->http_protocol = r->http_protocol;
2040
2041     if (ngx_http_set_exten(sr) != NGX_OK) {
2042         return NGX_ERROR;
2043     }
2044
2045     sr->main = r->main;
2046     sr->parent = r;
2047     sr->post_subrequest = ps;
2048     sr->read_event_handler = ngx_http_request_empty_handler;
2049     sr->write_event_handler = ngx_http_handler;
2050
2051     if (c->data == r && r->postponed == NULL) {
2052         c->data = sr;
2053     }
2054
2055     sr->in_addr = r->in_addr;
2056     sr->port = r->port;
2057     sr->port_text = r->port_text;
2058
2059     sr->variables = r->variables;
2060
2061     sr->log_handler = r->log_handler;
2062
2063     pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
2064     if (pr == NULL) {
2065         return NGX_ERROR;
2066     }
2067
2068     pr->request = sr;
2069     pr->out = NULL;
2070     pr->next = NULL;
2071
2072     if (r->postponed) {
2073         for (p = r->postponed; p->next; p = p->next) { /* void */ }
2074         p->next = pr;
2075
2076     } else {
2077         r->postponed = pr;
2078     }
2079
2080     sr->internal = 1;
2081
2082     sr->discard_body = r->discard_body;
2083     sr->expect_tested = 1;
2084     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
2085
2086     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
2087
2088     r->main->subrequests++;
2089
2090     *psr = sr;
2091
2092     return ngx_http_post_request(sr);
2093 }
2094
2095
2096 ngx_int_t
2097 ngx_http_internal_redirect(ngx_http_request_t *r,
2098     ngx_str_t *uri, ngx_str_t *args)
2099 {
2100     ngx_http_core_srv_conf_t  *cscf;
2101
2102     r->uri_changes--;
2103
2104     if (r->uri_changes == 0) {
2105         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2106                       "rewrite or internal redirection cycle "
2107                       "while internal redirect to \"%V\"", uri);
2108
2109         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2110         return NGX_DONE;
2111     }
2112
2113     r->uri = *uri;
2114
2115     if (args) {
2116         r->args = *args;
2117
2118     } else {
2119         r->args.len = 0;
2120         r->args.data = NULL;
2121     }
2122
2123     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2124                    "internal redirect: \"%V?%V\"", uri, &r->args);
2125
2126     if (ngx_http_set_exten(r) != NGX_OK) {
2127         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2128         return NGX_DONE;
2129     }
2130
2131     /* clear the modules contexts */
2132     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2133
2134     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2135     r->loc_conf = cscf->ctx->loc_conf;
2136
2137     ngx_http_update_location_config(r);
2138
2139     r->internal = 1;
2140
2141     ngx_http_handler(r);
2142
2143     return NGX_DONE;
2144 }
2145
2146
2147 ngx_int_t
2148 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
2149 {
2150     ngx_http_core_srv_conf_t    *cscf;
2151     ngx_http_core_loc_conf_t   **clcfp;
2152     ngx_http_core_main_conf_t   *cmcf;
2153
2154     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2155
2156     if (cscf->named_locations) {
2157
2158         for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
2159
2160             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2161                            "test location: \"%V\"", &(*clcfp)->name);
2162
2163             if (name->len != (*clcfp)->name.len
2164                 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
2165             {
2166                 continue;
2167             }
2168
2169             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2170                            "using location: %V \"%V?%V\"",
2171                            name, &r->uri, &r->args);
2172
2173             r->internal = 1;
2174             r->content_handler = NULL;
2175             r->loc_conf = (*clcfp)->loc_conf;
2176
2177             ngx_http_update_location_config(r);
2178
2179             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2180
2181             r->phase_handler = cmcf->phase_engine.location_rewrite_index;
2182
2183             ngx_http_core_run_phases(r);
2184
2185             return NGX_DONE;
2186         }
2187     }
2188
2189     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2190                   "could not find named location \"%V\"", name);
2191
2192     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2193
2194     return NGX_DONE;
2195 }
2196
2197
2198 ngx_http_cleanup_t *
2199 ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
2200 {
2201     ngx_http_cleanup_t  *cln;
2202
2203     r = r->main;
2204
2205     cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
2206     if (cln == NULL) {
2207         return NULL;
2208     }
2209
2210     if (size) {
2211         cln->data = ngx_palloc(r->pool, size);
2212         if (cln->data == NULL) {
2213             return NULL;
2214         }
2215
2216     } else {
2217         cln->data = NULL;
2218     }
2219
2220     cln->handler = NULL;
2221     cln->next = r->cleanup;
2222
2223     r->cleanup = cln;
2224
2225     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2226                    "http cleanup add: %p", cln);
2227
2228     return cln;
2229 }
2230
2231
2232 static char *
2233 ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2234 {
2235     char                        *rv;
2236     void                        *mconf;
2237     ngx_uint_t                   i;
2238     ngx_conf_t                   pcf;
2239     ngx_http_module_t           *module;
2240     ngx_http_conf_ctx_t         *ctx, *http_ctx;
2241     ngx_http_core_srv_conf_t    *cscf, **cscfp;
2242     ngx_http_core_main_conf_t   *cmcf;
2243
2244     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2245     if (ctx == NULL) {
2246         return NGX_CONF_ERROR;
2247     }
2248
2249     http_ctx = cf->ctx;
2250     ctx->main_conf = http_ctx->main_conf;
2251
2252     /* the server{}'s srv_conf */
2253
2254     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2255     if (ctx->srv_conf == NULL) {
2256         return NGX_CONF_ERROR;
2257     }
2258
2259     /* the server{}'s loc_conf */
2260
2261     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2262     if (ctx->loc_conf == NULL) {
2263         return NGX_CONF_ERROR;
2264     }
2265
2266     for (i = 0; ngx_modules[i]; i++) {
2267         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2268             continue;
2269         }
2270
2271         module = ngx_modules[i]->ctx;
2272
2273         if (module->create_srv_conf) {
2274             mconf = module->create_srv_conf(cf);
2275             if (mconf == NULL) {
2276                 return NGX_CONF_ERROR;
2277             }
2278
2279             ctx->srv_conf[ngx_modules[i]->ctx_index] = mconf;
2280         }
2281
2282         if (module->create_loc_conf) {
2283             mconf = module->create_loc_conf(cf);
2284             if (mconf == NULL) {
2285                 return NGX_CONF_ERROR;
2286             }
2287
2288             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
2289         }
2290     }
2291
2292
2293     /* the server configuration context */
2294
2295     cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
2296     cscf->ctx = ctx;
2297
2298
2299     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
2300
2301     cscfp = ngx_array_push(&cmcf->servers);
2302     if (cscfp == NULL) {
2303         return NGX_CONF_ERROR;
2304     }
2305
2306     *cscfp = cscf;
2307
2308
2309     /* parse inside server{} */
2310
2311     pcf = *cf;
2312     cf->ctx = ctx;
2313     cf->cmd_type = NGX_HTTP_SRV_CONF;
2314
2315     rv = ngx_conf_parse(cf, NULL);
2316
2317     *cf = pcf;
2318
2319     return rv;
2320 }
2321
2322
2323 static char *
2324 ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2325 {
2326     char                      *rv;
2327     u_char                    *mod;
2328     size_t                     len;
2329     ngx_str_t                 *value, *name;
2330     ngx_uint_t                 i;
2331     ngx_conf_t                 save;
2332     ngx_http_module_t         *module;
2333     ngx_http_conf_ctx_t       *ctx, *pctx;
2334     ngx_http_core_loc_conf_t  *clcf, *pclcf;
2335
2336     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2337     if (ctx == NULL) {
2338         return NGX_CONF_ERROR;
2339     }
2340
2341     pctx = cf->ctx;
2342     ctx->main_conf = pctx->main_conf;
2343     ctx->srv_conf = pctx->srv_conf;
2344
2345     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2346     if (ctx->loc_conf == NULL) {
2347         return NGX_CONF_ERROR;
2348     }
2349
2350     for (i = 0; ngx_modules[i]; i++) {
2351         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2352             continue;
2353         }
2354
2355         module = ngx_modules[i]->ctx;
2356
2357         if (module->create_loc_conf) {
2358             ctx->loc_conf[ngx_modules[i]->ctx_index] =
2359                                                    module->create_loc_conf(cf);
2360             if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) {
2361                  return NGX_CONF_ERROR;
2362             }
2363         }
2364     }
2365
2366     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
2367     clcf->loc_conf = ctx->loc_conf;
2368
2369     value = cf->args->elts;
2370
2371     if (cf->args->nelts == 3) {
2372
2373         len = value[1].len;
2374         mod = value[1].data;
2375         name = &value[2];
2376
2377         if (len == 1 && mod[0] == '=') {
2378
2379             clcf->name = *name;
2380             clcf->exact_match = 1;
2381
2382         } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
2383
2384             clcf->name = *name;
2385             clcf->noregex = 1;
2386
2387         } else if (len == 1 && mod[0] == '~') {
2388
2389             if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2390                 return NGX_CONF_ERROR;
2391             }
2392
2393         } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
2394
2395             if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2396                 return NGX_CONF_ERROR;
2397             }
2398
2399         } else {
2400             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2401                                "invalid location modifier \"%V\"", &value[1]);
2402             return NGX_CONF_ERROR;
2403         }
2404
2405     } else {
2406
2407         name = &value[1];
2408
2409         if (name->data[0] == '=') {
2410
2411             clcf->name.len = name->len - 1;
2412             clcf->name.data = name->data + 1;
2413             clcf->exact_match = 1;
2414
2415         } else if (name->data[0] == '^' && name->data[1] == '~') {
2416
2417             clcf->name.len = name->len - 2;
2418             clcf->name.data = name->data + 2;
2419             clcf->noregex = 1;
2420
2421         } else if (name->data[0] == '~') {
2422
2423             name->len--;
2424             name->data++;
2425
2426             if (name->data[0] == '*') {
2427
2428                 name->len--;
2429                 name->data++;
2430
2431                 if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2432                     return NGX_CONF_ERROR;
2433                 }
2434
2435             } else {
2436                 if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2437                     return NGX_CONF_ERROR;
2438                 }
2439             }
2440
2441         } else {
2442
2443             clcf->name = *name;
2444
2445             if (name->data[0] == '@') {
2446                 clcf->named = 1;
2447             }
2448         }
2449     }
2450
2451     pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
2452
2453     if (pclcf->name.len) {
2454
2455         /* nested location */
2456
2457 #if 0
2458         clcf->prev_location = pclcf;
2459 #endif
2460
2461         if (pclcf->exact_match) {
2462             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2463                                "location \"%V\" could not be inside "
2464                                "the exact location \"%V\"",
2465                                &clcf->name, &pclcf->name);
2466             return NGX_CONF_ERROR;
2467         }
2468
2469         if (pclcf->named) {
2470             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2471                                "location \"%V\" could not be inside "
2472                                "the named location \"%V\"",
2473                                &clcf->name, &pclcf->name);
2474             return NGX_CONF_ERROR;
2475         }
2476
2477         if (clcf->named) {
2478             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2479                                "named location \"%V\" must be "
2480                                "on server level only",
2481                                &clcf->name);
2482             return NGX_CONF_ERROR;
2483         }
2484
2485         len = pclcf->name.len;
2486
2487 #if (NGX_PCRE)
2488         if (clcf->regex == NULL
2489             && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2490 #else
2491         if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2492 #endif
2493         {
2494             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2495                                "location \"%V\" is outside location \"%V\"",
2496                                &clcf->name, &pclcf->name);
2497             return NGX_CONF_ERROR;
2498         }
2499     }
2500
2501     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
2502         return NGX_CONF_ERROR;
2503     }
2504
2505     save = *cf;
2506     cf->ctx = ctx;
2507     cf->cmd_type = NGX_HTTP_LOC_CONF;
2508
2509     rv = ngx_conf_parse(cf, NULL);
2510
2511     *cf = save;
2512
2513     return rv;
2514 }
2515
2516
2517 static ngx_int_t
2518 ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
2519     ngx_str_t *regex, ngx_uint_t caseless)
2520 {
2521 #if (NGX_PCRE)
2522     ngx_str_t  err;
2523     u_char     errstr[NGX_MAX_CONF_ERRSTR];
2524
2525     err.len = NGX_MAX_CONF_ERRSTR;
2526     err.data = errstr;
2527
2528     clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
2529                                     cf->pool, &err);
2530
2531     if (clcf->regex == NULL) {
2532         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
2533         return NGX_ERROR;
2534     }
2535
2536     clcf->name = *regex;
2537
2538     return NGX_OK;
2539
2540 #else
2541
2542     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2543                        "the using of the regex \"%V\" requires PCRE library",
2544                        regex);
2545     return NGX_ERROR;
2546
2547 #endif
2548 }
2549
2550
2551 static char *
2552 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2553 {
2554     ngx_http_core_loc_conf_t *lcf = conf;
2555
2556     char        *rv;
2557     ngx_conf_t   save;
2558
2559     if (lcf->types == NULL) {
2560         lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
2561         if (lcf->types == NULL) {
2562             return NGX_CONF_ERROR;
2563         }
2564     }
2565
2566     save = *cf;
2567     cf->handler = ngx_http_core_type;
2568     cf->handler_conf = conf;
2569
2570     rv = ngx_conf_parse(cf, NULL);
2571
2572     *cf = save;
2573
2574     return rv;
2575 }
2576
2577
2578 static char *
2579 ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
2580 {
2581     ngx_http_core_loc_conf_t *lcf = conf;
2582
2583     ngx_str_t       *value, *content_type, *old, file;
2584     ngx_uint_t       i, n, hash;
2585     ngx_hash_key_t  *type;
2586
2587     value = cf->args->elts;
2588
2589     if (ngx_strcmp(value[0].data, "include") == 0) {
2590         file = value[1];
2591
2592         if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){
2593             return NGX_CONF_ERROR;
2594         }
2595
2596         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
2597
2598         return ngx_conf_parse(cf, &file);
2599     }
2600
2601     content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
2602     if (content_type == NULL) {
2603         return NGX_CONF_ERROR;
2604     }
2605
2606     *content_type = value[0];
2607
2608     for (i = 1; i < cf->args->nelts; i++) {
2609
2610         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
2611
2612         type = lcf->types->elts;
2613         for (n = 0; n < lcf->types->nelts; n++) {
2614             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
2615                 old = type[n].value;
2616                 type[n].value = content_type;
2617
2618                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2619                                    "duplicate extention \"%V\", "
2620                                    "content type: \"%V\", "
2621                                    "old content type: \"%V\"",
2622                                    &value[i], content_type, old);
2623                 continue;
2624             }
2625         }
2626
2627
2628         type = ngx_array_push(lcf->types);
2629         if (type == NULL) {
2630             return NGX_CONF_ERROR;
2631         }
2632
2633         type->key = value[i];
2634         type->key_hash = hash;
2635         type->value = content_type;
2636     }
2637
2638     return NGX_CONF_OK;
2639 }
2640
2641
2642 static ngx_int_t
2643 ngx_http_core_preconfiguration(ngx_conf_t *cf)
2644 {
2645     return ngx_http_variables_add_core_vars(cf);
2646 }
2647
2648
2649 static void *
2650 ngx_http_core_create_main_conf(ngx_conf_t *cf)
2651 {
2652     ngx_http_core_main_conf_t  *cmcf;
2653
2654     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
2655     if (cmcf == NULL) {
2656         return NGX_CONF_ERROR;
2657     }
2658
2659     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
2660                        sizeof(ngx_http_core_srv_conf_t *))
2661         != NGX_OK)
2662     {
2663         return NGX_CONF_ERROR;
2664     }
2665
2666     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
2667     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
2668
2669     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
2670     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
2671
2672     return cmcf;
2673 }
2674
2675
2676 static char *
2677 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
2678 {
2679     ngx_http_core_main_conf_t *cmcf = conf;
2680
2681     if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
2682         cmcf->server_names_hash_max_size = 512;
2683     }
2684
2685     if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2686         cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
2687     }
2688
2689     cmcf->server_names_hash_bucket_size =
2690             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
2691
2692
2693     if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
2694         cmcf->variables_hash_max_size = 512;
2695     }
2696
2697     if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2698         cmcf->variables_hash_bucket_size = 64;
2699     }
2700
2701     cmcf->variables_hash_bucket_size =
2702                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
2703
2704     return NGX_CONF_OK;
2705 }
2706
2707
2708 static void *
2709 ngx_http_core_create_srv_conf(ngx_conf_t *cf)
2710 {
2711     ngx_http_core_srv_conf_t  *cscf;
2712
2713     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
2714     if (cscf == NULL) {
2715         return NGX_CONF_ERROR;
2716     }
2717
2718     /*
2719      * set by ngx_pcalloc():
2720      *
2721      *     conf->client_large_buffers.num = 0;
2722      */
2723
2724     if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t))
2725         == NGX_ERROR)
2726     {
2727         return NGX_CONF_ERROR;
2728     }
2729
2730     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
2731                        sizeof(ngx_http_server_name_t))
2732         == NGX_ERROR)
2733     {
2734         return NGX_CONF_ERROR;
2735     }
2736
2737     cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
2738     cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
2739     cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
2740     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
2741     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
2742     cscf->merge_slashes = NGX_CONF_UNSET;
2743     cscf->underscores_in_headers = NGX_CONF_UNSET;
2744
2745     return cscf;
2746 }
2747
2748
2749 static char *
2750 ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
2751 {
2752     ngx_http_core_srv_conf_t *prev = parent;
2753     ngx_http_core_srv_conf_t *conf = child;
2754
2755     ngx_http_listen_t       *ls;
2756     ngx_http_server_name_t  *sn;
2757
2758     /* TODO: it does not merge, it inits only */
2759
2760     if (conf->listen.nelts == 0) {
2761         ls = ngx_array_push(&conf->listen);
2762         if (ls == NULL) {
2763             return NGX_CONF_ERROR;
2764         }
2765
2766         ngx_memzero(ls, sizeof(ngx_http_listen_t));
2767
2768         ls->addr = INADDR_ANY;
2769 #if (NGX_WIN32)
2770         ls->port = 80;
2771 #else
2772         /* STUB: getuid() should be cached */
2773         ls->port = (getuid() == 0) ? 80 : 8000;
2774 #endif
2775         ls->family = AF_INET;
2776
2777         ls->conf.backlog = NGX_LISTEN_BACKLOG;
2778         ls->conf.rcvbuf = -1;
2779         ls->conf.sndbuf = -1;
2780     }
2781
2782     if (conf->server_name.data == NULL) {
2783         conf->server_name = cf->cycle->hostname;
2784
2785         sn = ngx_array_push(&conf->server_names);
2786         if (sn == NULL) {
2787             return NGX_CONF_ERROR;
2788         }
2789
2790 #if (NGX_PCRE)
2791         sn->regex = NULL;
2792 #endif
2793         sn->core_srv_conf = conf;
2794         sn->name.len = conf->server_name.len;
2795         sn->name.data = conf->server_name.data;
2796     }
2797
2798     ngx_conf_merge_size_value(conf->connection_pool_size,
2799                               prev->connection_pool_size, 256);
2800     ngx_conf_merge_size_value(conf->request_pool_size,
2801                               prev->request_pool_size, 4096);
2802     ngx_conf_merge_msec_value(conf->client_header_timeout,
2803                               prev->client_header_timeout, 60000);
2804     ngx_conf_merge_size_value(conf->client_header_buffer_size,
2805                               prev->client_header_buffer_size, 1024);
2806     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
2807                               prev->large_client_header_buffers,
2808                               4, ngx_pagesize);
2809
2810     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
2811         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2812                            "the \"large_client_header_buffers\" size must be "
2813                            "equal to or bigger than \"connection_pool_size\"");
2814         return NGX_CONF_ERROR;
2815     }
2816
2817     ngx_conf_merge_value(conf->ignore_invalid_headers,
2818                               prev->ignore_invalid_headers, 1);
2819
2820     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
2821
2822     ngx_conf_merge_value(conf->underscores_in_headers,
2823                               prev->underscores_in_headers, 0);
2824
2825     return NGX_CONF_OK;
2826 }
2827
2828
2829 static void *
2830 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
2831 {
2832     ngx_http_core_loc_conf_t  *lcf;
2833
2834     lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
2835     if (lcf == NULL) {
2836         return NGX_CONF_ERROR;
2837     }
2838
2839     /*
2840      * set by ngx_pcalloc():
2841      *
2842      *     lcf->root = { 0, NULL };
2843      *     lcf->limit_except = 0;
2844      *     lcf->post_action = { 0, NULL };
2845      *     lcf->types = NULL;
2846      *     lcf->default_type = { 0, NULL };
2847      *     lcf->err_log = NULL;
2848      *     lcf->error_pages = NULL;
2849      *     lcf->try_files = NULL;
2850      *     lcf->client_body_path = NULL;
2851      *     lcf->regex = NULL;
2852      *     lcf->exact_match = 0;
2853      *     lcf->auto_redirect = 0;
2854      *     lcf->alias = 0;
2855      *     lcf->gzip_proxied = 0;
2856      */
2857
2858     lcf->client_max_body_size = NGX_CONF_UNSET;
2859     lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
2860     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
2861     lcf->satisfy = NGX_CONF_UNSET_UINT;
2862     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
2863     lcf->internal = NGX_CONF_UNSET;
2864     lcf->client_body_in_file_only = NGX_CONF_UNSET;
2865     lcf->sendfile = NGX_CONF_UNSET;
2866     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
2867     lcf->directio = NGX_CONF_UNSET;
2868     lcf->tcp_nopush = NGX_CONF_UNSET;
2869     lcf->tcp_nodelay = NGX_CONF_UNSET;
2870     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
2871     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
2872     lcf->postpone_output = NGX_CONF_UNSET_SIZE;
2873     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
2874     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
2875     lcf->keepalive_header = NGX_CONF_UNSET;
2876     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
2877     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
2878     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
2879     lcf->reset_timedout_connection = NGX_CONF_UNSET;
2880     lcf->server_name_in_redirect = NGX_CONF_UNSET;
2881     lcf->port_in_redirect = NGX_CONF_UNSET;
2882     lcf->msie_padding = NGX_CONF_UNSET;
2883     lcf->msie_refresh = NGX_CONF_UNSET;
2884     lcf->log_not_found = NGX_CONF_UNSET;
2885     lcf->log_subrequest = NGX_CONF_UNSET;
2886     lcf->recursive_error_pages = NGX_CONF_UNSET;
2887     lcf->server_tokens = NGX_CONF_UNSET;
2888     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
2889     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
2890
2891     lcf->open_file_cache = NGX_CONF_UNSET_PTR;
2892     lcf->open_file_cache_valid = NGX_CONF_UNSET;
2893     lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
2894     lcf->open_file_cache_errors = NGX_CONF_UNSET;
2895     lcf->open_file_cache_events = NGX_CONF_UNSET;
2896
2897 #if (NGX_HTTP_GZIP)
2898     lcf->gzip_vary = NGX_CONF_UNSET;
2899     lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
2900 #if (NGX_PCRE)
2901     lcf->gzip_disable = NGX_CONF_UNSET_PTR;
2902     lcf->gzip_disable_msie6 = 3;
2903 #endif
2904 #endif
2905
2906     return lcf;
2907 }
2908
2909
2910 static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
2911 static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
2912 static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
2913
2914 static ngx_hash_key_t  ngx_http_core_default_types[] = {
2915     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
2916     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
2917     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
2918     { ngx_null_string, 0, NULL }
2919 };
2920
2921
2922 static char *
2923 ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2924 {
2925     ngx_http_core_loc_conf_t *prev = parent;
2926     ngx_http_core_loc_conf_t *conf = child;
2927
2928     ngx_uint_t        i;
2929     ngx_hash_key_t   *type;
2930     ngx_hash_init_t   types_hash;
2931
2932     if (conf->root.data == NULL) {
2933
2934         conf->alias = prev->alias;
2935         conf->root = prev->root;
2936         conf->root_lengths = prev->root_lengths;
2937         conf->root_values = prev->root_values;
2938
2939         if (prev->root.data == NULL) {
2940             conf->root.len = sizeof("html") - 1;
2941             conf->root.data = (u_char *) "html";
2942
2943             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) {
2944                 return NGX_CONF_ERROR;
2945             }
2946         }
2947     }
2948
2949     if (conf->post_action.data == NULL) {
2950         conf->post_action = prev->post_action;
2951     }
2952
2953     ngx_conf_merge_uint_value(conf->types_hash_max_size,
2954                               prev->types_hash_max_size, 1024);
2955
2956     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
2957                               prev->types_hash_bucket_size,
2958                               ngx_cacheline_size);
2959
2960     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
2961                                              ngx_cacheline_size);
2962
2963     /*
2964      * the special handling the "types" directive in the "http" section
2965      * to inherit the http's conf->types_hash to all servers
2966      */
2967
2968     if (prev->types && prev->types_hash.buckets == NULL) {
2969
2970         types_hash.hash = &prev->types_hash;
2971         types_hash.key = ngx_hash_key_lc;
2972         types_hash.max_size = conf->types_hash_max_size;
2973         types_hash.bucket_size = conf->types_hash_bucket_size;
2974         types_hash.name = "types_hash";
2975         types_hash.pool = cf->pool;
2976         types_hash.temp_pool = NULL;
2977
2978         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
2979             != NGX_OK)
2980         {
2981             return NGX_CONF_ERROR;
2982         }
2983     }
2984
2985     if (conf->types == NULL) {
2986         conf->types = prev->types;
2987         conf->types_hash = prev->types_hash;
2988     }
2989
2990     if (conf->types == NULL) {
2991         conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
2992         if (conf->types == NULL) {
2993             return NGX_CONF_ERROR;
2994         }
2995
2996         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
2997             type = ngx_array_push(conf->types);
2998             if (type == NULL) {
2999                 return NGX_CONF_ERROR;
3000             }
3001
3002             type->key = ngx_http_core_default_types[i].key;
3003             type->key_hash =
3004                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3005                                        ngx_http_core_default_types[i].key.len);
3006             type->value = ngx_http_core_default_types[i].value;
3007         }
3008     }
3009
3010     if (conf->types_hash.buckets == NULL) {
3011
3012         types_hash.hash = &conf->types_hash;
3013         types_hash.key = ngx_hash_key_lc;
3014         types_hash.max_size = conf->types_hash_max_size;
3015         types_hash.bucket_size = conf->types_hash_bucket_size;
3016         types_hash.name = "mime_types_hash";
3017         types_hash.pool = cf->pool;
3018         types_hash.temp_pool = NULL;
3019
3020         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3021             != NGX_OK)
3022         {
3023             return NGX_CONF_ERROR;
3024         }
3025     }
3026
3027     if (conf->err_log == NULL) {
3028         if (prev->err_log) {
3029             conf->err_log = prev->err_log;
3030         } else {
3031             conf->err_log = cf->cycle->new_log;
3032         }
3033     }
3034
3035     if (conf->error_pages == NULL && prev->error_pages) {
3036         conf->error_pages = prev->error_pages;
3037     }
3038
3039     ngx_conf_merge_str_value(conf->default_type,
3040                               prev->default_type, "text/plain");
3041
3042     ngx_conf_merge_off_value(conf->client_max_body_size,
3043                               prev->client_max_body_size, 1 * 1024 * 1024);
3044     ngx_conf_merge_size_value(conf->client_body_buffer_size,
3045                               prev->client_body_buffer_size,
3046                               (size_t) 2 * ngx_pagesize);
3047     ngx_conf_merge_msec_value(conf->client_body_timeout,
3048                               prev->client_body_timeout, 60000);
3049
3050     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3051                               NGX_HTTP_SATISFY_ALL);
3052     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3053                               0);
3054     ngx_conf_merge_value(conf->internal, prev->internal, 0);
3055     ngx_conf_merge_value(conf->client_body_in_file_only,
3056                               prev->client_body_in_file_only, 0);
3057     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3058     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3059                               prev->sendfile_max_chunk, 0);
3060     ngx_conf_merge_off_value(conf->directio, prev->directio,
3061                               NGX_MAX_OFF_T_VALUE);
3062     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3063     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3064
3065     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3066     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3067     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3068                               1460);
3069     ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3070     ngx_conf_merge_msec_value(conf->keepalive_timeout,
3071                               prev->keepalive_timeout, 75000);
3072     ngx_conf_merge_sec_value(conf->keepalive_header,
3073                               prev->keepalive_header, 0);
3074     ngx_conf_merge_msec_value(conf->lingering_time,
3075                               prev->lingering_time, 30000);
3076     ngx_conf_merge_msec_value(conf->lingering_timeout,
3077                               prev->lingering_timeout, 5000);
3078     ngx_conf_merge_msec_value(conf->resolver_timeout,
3079                               prev->resolver_timeout, 30000);
3080
3081     if (conf->resolver == NULL) {
3082
3083         if (prev->resolver == NULL) {
3084
3085             /*
3086              * create dummy resolver in http {} context
3087              * to inherit it in all servers
3088              */
3089
3090             prev->resolver = ngx_resolver_create(cf, NULL);
3091             if (prev->resolver == NULL) {
3092                 return NGX_CONF_ERROR;
3093             }
3094         }
3095
3096         conf->resolver = prev->resolver;
3097     }
3098
3099     ngx_conf_merge_path_value(conf->client_body_temp_path,
3100                               prev->client_body_temp_path,
3101                               NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
3102                               ngx_garbage_collector_temp_handler, cf);
3103
3104     ngx_conf_merge_value(conf->reset_timedout_connection,
3105                               prev->reset_timedout_connection, 0);
3106     ngx_conf_merge_value(conf->server_name_in_redirect,
3107                               prev->server_name_in_redirect, 1);
3108     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3109     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3110     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3111     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3112     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3113     ngx_conf_merge_value(conf->recursive_error_pages,
3114                               prev->recursive_error_pages, 0);
3115     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
3116
3117     ngx_conf_merge_ptr_value(conf->open_file_cache,
3118                               prev->open_file_cache, NULL);
3119
3120     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3121                               prev->open_file_cache_valid, 60);
3122
3123     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3124                               prev->open_file_cache_min_uses, 1);
3125
3126     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3127                               prev->open_file_cache_errors, 0);
3128
3129     ngx_conf_merge_sec_value(conf->open_file_cache_events,
3130                               prev->open_file_cache_events, 0);
3131 #if (NGX_HTTP_GZIP)
3132
3133     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3134     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3135                               NGX_HTTP_VERSION_11);
3136     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3137                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3138
3139 #if (NGX_PCRE)
3140     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3141 #endif
3142
3143     if (conf->gzip_disable_msie6 == 3) {
3144         conf->gzip_disable_msie6 =
3145             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3146     }
3147
3148 #endif
3149
3150     return NGX_CONF_OK;
3151 }
3152
3153
3154 /* AF_INET only */
3155
3156 static char *
3157 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3158 {
3159     ngx_http_core_srv_conf_t *scf = conf;
3160
3161     ngx_str_t          *value, size;
3162     ngx_url_t           u;
3163     ngx_uint_t          n;
3164     ngx_http_listen_t  *ls;
3165
3166     /*
3167      * TODO: check duplicate 'listen' directives,
3168      *       add resolved name to server names ???
3169      */
3170
3171     value = cf->args->elts;
3172
3173     ngx_memzero(&u, sizeof(ngx_url_t));
3174
3175     u.url = value[1];
3176     u.listen = 1;
3177     u.default_port = 80;
3178
3179     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3180         if (u.err) {
3181             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3182                                "%s in \"%V\" of the \"listen\" directive",
3183                                u.err, &u.url);
3184         }
3185
3186         return NGX_CONF_ERROR;
3187     }
3188
3189     ls = ngx_array_push(&scf->listen);
3190     if (ls == NULL) {
3191         return NGX_CONF_ERROR;
3192     }
3193
3194     ngx_memzero(ls, sizeof(ngx_http_listen_t));
3195
3196     ls->family = u.family;
3197     ls->addr = u.addr.in_addr;
3198     ls->port = u.port;
3199     ls->file_name = cf->conf_file->file.name.data;
3200     ls->line = cf->conf_file->line;
3201     ls->conf.backlog = NGX_LISTEN_BACKLOG;
3202     ls->conf.rcvbuf = -1;
3203     ls->conf.sndbuf = -1;
3204
3205     n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, NGX_INET_ADDRSTRLEN);
3206     ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port);
3207
3208     if (cf->args->nelts == 2) {
3209         return NGX_CONF_OK;
3210     }
3211
3212     if (ngx_strcmp(value[2].data, "default") == 0) {
3213         ls->conf.default_server = 1;
3214         n = 3;
3215
3216     } else {
3217         n = 2;
3218     }
3219
3220     for ( /* void */ ; n < cf->args->nelts; n++) {
3221
3222         if (ls->conf.default_server == 0) {
3223             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3224                                "\"%V\" parameter can be specified for "
3225                                "the default \"listen\" directive only",
3226                                &value[n]);
3227             return NGX_CONF_ERROR;
3228         }
3229
3230         if (ngx_strcmp(value[n].data, "bind") == 0) {
3231             ls->conf.bind = 1;
3232             continue;
3233         }
3234
3235         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
3236             ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
3237             ls->conf.bind = 1;
3238
3239             if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
3240                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3241                                    "invalid backlog \"%V\"", &value[n]);
3242                 return NGX_CONF_ERROR;
3243             }
3244
3245             continue;
3246         }
3247
3248         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
3249             size.len = value[n].len - 7;
3250             size.data = value[n].data + 7;
3251
3252             ls->conf.rcvbuf = ngx_parse_size(&size);
3253             ls->conf.bind = 1;
3254
3255             if (ls->conf.rcvbuf == NGX_ERROR) {
3256                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3257                                    "invalid rcvbuf \"%V\"", &value[n]);
3258                 return NGX_CONF_ERROR;
3259             }
3260
3261             continue;
3262         }
3263
3264         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
3265             size.len = value[n].len - 7;
3266             size.data = value[n].data + 7;
3267
3268             ls->conf.sndbuf = ngx_parse_size(&size);
3269             ls->conf.bind = 1;
3270
3271             if (ls->conf.sndbuf == NGX_ERROR) {
3272                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3273                                    "invalid sndbuf \"%V\"", &value[n]);
3274                 return NGX_CONF_ERROR;
3275             }
3276
3277             continue;
3278         }
3279
3280         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
3281 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
3282             ls->conf.accept_filter = (char *) &value[n].data[14];
3283             ls->conf.bind = 1;
3284 #else
3285             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3286                                "accept filters \"%V\" are not supported "
3287                                "on this platform, ignored",
3288                                &value[n]);
3289 #endif
3290             continue;
3291         }
3292
3293         if (ngx_strcmp(value[n].data, "deferred") == 0) {
3294 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
3295             ls->conf.deferred_accept = 1;
3296             ls->conf.bind = 1;
3297 #else
3298             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3299                                "the deferred accept is not supported "
3300                                "on this platform, ignored");
3301 #endif
3302             continue;
3303         }
3304
3305         if (ngx_strcmp(value[n].data, "ssl") == 0) {
3306 #if (NGX_HTTP_SSL)
3307             ls->conf.ssl = 1;
3308             continue;
3309 #else
3310             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3311                                "the \"ssl\" parameter requires "
3312                                "ngx_http_ssl_module");
3313             return NGX_CONF_ERROR;
3314 #endif
3315         }
3316
3317         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3318                            "the invalid \"%V\" parameter", &value[n]);
3319         return NGX_CONF_ERROR;
3320     }
3321
3322     return NGX_CONF_OK;
3323 }
3324
3325
3326 static char *
3327 ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3328 {
3329     ngx_http_core_srv_conf_t *cscf = conf;
3330
3331     u_char                   ch;
3332     ngx_str_t               *value, name;
3333     ngx_uint_t               i;
3334     ngx_http_server_name_t  *sn;
3335
3336     value = cf->args->elts;
3337
3338     ch = value[1].data[0];
3339
3340     if (cscf->server_name.data == NULL) {
3341         if (value[1].len) {
3342             name = value[1];
3343
3344             if (ch == '.') {
3345                 name.len--;
3346                 name.data++;
3347             }
3348
3349             cscf->server_name.len = name.len;
3350             cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
3351             if (cscf->server_name.data == NULL) {
3352                 return NGX_CONF_ERROR;
3353             }
3354
3355         } else {
3356             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3357                                "the first server name must not be empty");
3358             return NGX_CONF_ERROR;
3359         }
3360     }
3361
3362     for (i = 1; i < cf->args->nelts; i++) {
3363
3364         ch = value[i].data[0];
3365
3366         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
3367             || (ch == '.' && value[i].len < 2))
3368         {
3369             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3370                                "server name \"%V\" is invalid", &value[i]);
3371             return NGX_CONF_ERROR;
3372         }
3373
3374         if (ngx_strchr(value[i].data, '/')) {
3375             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3376                                "server name \"%V\" has strange symbols",
3377                                &value[i]);
3378         }
3379
3380         if (value[i].len == 1 && ch == '*') {
3381             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3382                                "\"server_name *\" is unsupported, use "
3383                                "\"server_name_in_redirect off\" instead");
3384             return NGX_CONF_ERROR;
3385         }
3386
3387         sn = ngx_array_push(&cscf->server_names);
3388         if (sn == NULL) {
3389             return NGX_CONF_ERROR;
3390         }
3391
3392 #if (NGX_PCRE)
3393         sn->regex = NULL;
3394 #endif
3395         sn->core_srv_conf = cscf;
3396         sn->name = value[i];
3397
3398         if (value[i].data[0] != '~') {
3399             continue;
3400         }
3401
3402 #if (NGX_PCRE)
3403         {
3404         ngx_str_t  err;
3405         u_char     errstr[NGX_MAX_CONF_ERRSTR];
3406
3407         err.len = NGX_MAX_CONF_ERRSTR;
3408         err.data = errstr;
3409
3410         value[i].len--;
3411         value[i].data++;
3412
3413         sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
3414
3415         if (sn->regex == NULL) {
3416             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
3417             return NGX_CONF_ERROR;
3418         }
3419
3420         sn->name = value[i];
3421         }
3422 #else
3423         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3424                            "the using of the regex \"%V\" "
3425                            "requires PCRE library", &value[i]);
3426
3427         return NGX_CONF_ERROR;
3428 #endif
3429     }
3430
3431     return NGX_CONF_OK;
3432 }
3433
3434
3435 static char *
3436 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3437 {
3438     ngx_http_core_loc_conf_t *lcf = conf;
3439
3440     ngx_str_t                  *value;
3441     ngx_uint_t                  alias, n;
3442     ngx_http_script_compile_t   sc;
3443
3444     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
3445
3446     if (lcf->root.data) {
3447
3448         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
3449
3450         if ((ngx_uint_t) lcf->alias == alias) {
3451             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3452                                "\"%V\" directive is duplicate",
3453                                &cmd->name);
3454         } else {
3455             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3456                                "\"%V\" directive is duplicate, "
3457                                "\"%s\" directive is specified before",
3458                                &cmd->name, lcf->alias ? "alias" : "root");
3459         }
3460
3461         return NGX_CONF_ERROR;
3462     }
3463
3464     if (lcf->named && alias) {
3465         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3466                            "the \"alias\" directive may not be used "
3467                            "inside named location");
3468
3469         return NGX_CONF_ERROR;
3470     }
3471
3472 #if (NGX_PCRE)
3473
3474     if (lcf->regex && alias) {
3475         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3476                            "the \"alias\" directive may not be used "
3477                            "inside location given by regular expression");
3478
3479         return NGX_CONF_ERROR;
3480     }
3481
3482 #endif
3483
3484     value = cf->args->elts;
3485
3486     if (ngx_strstr(value[1].data, "$document_root")
3487         || ngx_strstr(value[1].data, "${document_root}"))
3488     {
3489         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3490                            "the $document_root variable may not be used "
3491                            "in the \"%V\" directive",
3492                            &cmd->name);
3493
3494         return NGX_CONF_ERROR;
3495     }
3496
3497     if (ngx_strstr(value[1].data, "$realpath_root")
3498         || ngx_strstr(value[1].data, "${realpath_root}"))
3499     {
3500         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3501                            "the $realpath_root variable may not be used "
3502                            "in the \"%V\" directive",
3503                            &cmd->name);
3504
3505         return NGX_CONF_ERROR;
3506     }
3507
3508     lcf->alias = alias;
3509     lcf->root = value[1];
3510
3511     if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
3512         lcf->root.len--;
3513     }
3514
3515     if (lcf->root.data[0] != '$') {
3516         if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) {
3517             return NGX_CONF_ERROR;
3518         }
3519     }
3520
3521     n = ngx_http_script_variables_count(&lcf->root);
3522
3523     if (n == 0) {
3524         return NGX_CONF_OK;
3525     }
3526
3527     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3528
3529     sc.cf = cf;
3530     sc.source = &lcf->root;
3531     sc.lengths = &lcf->root_lengths;
3532     sc.values = &lcf->root_values;
3533     sc.variables = n;
3534     sc.complete_lengths = 1;
3535     sc.complete_values = 1;
3536
3537     if (ngx_http_script_compile(&sc) != NGX_OK) {
3538         return NGX_CONF_ERROR;
3539     }
3540
3541     return NGX_CONF_OK;
3542 }
3543
3544
3545 static ngx_http_method_name_t  ngx_methods_names[] = {
3546    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
3547    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
3548    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
3549    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
3550    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
3551    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
3552    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
3553    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
3554    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
3555    { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
3556    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
3557    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
3558    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
3559    { NULL, 0 }
3560 };
3561
3562
3563 static char *
3564 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3565 {
3566     ngx_http_core_loc_conf_t *pclcf = conf;
3567
3568     char                      *rv;
3569     void                      *mconf;
3570     ngx_str_t                 *value;
3571     ngx_uint_t                 i;
3572     ngx_conf_t                 save;
3573     ngx_http_module_t         *module;
3574     ngx_http_conf_ctx_t       *ctx, *pctx;
3575     ngx_http_method_name_t    *name;
3576     ngx_http_core_loc_conf_t  *clcf;
3577
3578     if (pclcf->limit_except) {
3579         return "duplicate";
3580     }
3581
3582     pclcf->limit_except = 0xffffffff;
3583
3584     value = cf->args->elts;
3585
3586     for (i = 1; i < cf->args->nelts; i++) {
3587         for (name = ngx_methods_names; name->name; name++) {
3588
3589             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
3590                 pclcf->limit_except &= name->method;
3591                 goto next;
3592             }
3593         }
3594
3595         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3596                            "invalid method \"%V\"", &value[i]);
3597         return NGX_CONF_ERROR;
3598
3599     next:
3600         continue;
3601     }
3602
3603     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
3604         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
3605     }
3606
3607     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3608     if (ctx == NULL) {
3609         return NGX_CONF_ERROR;
3610     }
3611
3612     pctx = cf->ctx;
3613     ctx->main_conf = pctx->main_conf;
3614     ctx->srv_conf = pctx->srv_conf;
3615
3616     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
3617     if (ctx->loc_conf == NULL) {
3618         return NGX_CONF_ERROR;
3619     }
3620
3621     for (i = 0; ngx_modules[i]; i++) {
3622         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
3623             continue;
3624         }
3625
3626         module = ngx_modules[i]->ctx;
3627
3628         if (module->create_loc_conf) {
3629
3630             mconf = module->create_loc_conf(cf);
3631             if (mconf == NULL) {
3632                  return NGX_CONF_ERROR;
3633             }
3634
3635             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
3636         }
3637     }
3638
3639
3640     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
3641     pclcf->limit_except_loc_conf = ctx->loc_conf;
3642     clcf->loc_conf = ctx->loc_conf;
3643     clcf->name = pclcf->name;
3644     clcf->noname = 1;
3645
3646     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
3647         return NGX_CONF_ERROR;
3648     }
3649
3650     save = *cf;
3651     cf->ctx = ctx;
3652     cf->cmd_type = NGX_HTTP_LMT_CONF;
3653
3654     rv = ngx_conf_parse(cf, NULL);
3655
3656     *cf = save;
3657
3658     return rv;
3659 }
3660
3661
3662 static char *
3663 ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3664 {
3665     ngx_http_core_loc_conf_t *clcf = conf;
3666
3667     ngx_str_t  *value;
3668
3669     if (clcf->directio != NGX_CONF_UNSET) {
3670         return "is duplicate";
3671     }
3672
3673     value = cf->args->elts;
3674
3675     if (ngx_strcmp(value[1].data, "off") == 0) {
3676         clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
3677         return NGX_CONF_OK;
3678     }
3679
3680     clcf->directio = ngx_parse_offset(&value[1]);
3681     if (clcf->directio == (off_t) NGX_ERROR) {
3682         return "invalid value";
3683     }
3684
3685     return NGX_CONF_OK;
3686 }
3687
3688
3689 static char *
3690 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3691 {
3692     ngx_http_core_loc_conf_t *lcf = conf;
3693
3694     u_char                     *args;
3695     ngx_int_t                   overwrite;
3696     ngx_str_t                  *value, uri;
3697     ngx_uint_t                  i, n, nvar;
3698     ngx_array_t                *uri_lengths, *uri_values;
3699     ngx_http_err_page_t        *err;
3700     ngx_http_script_compile_t   sc;
3701
3702     if (lcf->error_pages == NULL) {
3703         lcf->error_pages = ngx_array_create(cf->pool, 4,
3704                                             sizeof(ngx_http_err_page_t));
3705         if (lcf->error_pages == NULL) {
3706             return NGX_CONF_ERROR;
3707         }
3708     }
3709
3710     value = cf->args->elts;
3711
3712     i = cf->args->nelts - 2;
3713
3714     if (value[i].data[0] == '=') {
3715         if (i == 1) {
3716             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3717                                "invalid value \"%V\"", &value[i]);
3718             return NGX_CONF_ERROR;
3719         }
3720
3721         if (value[i].len > 1) {
3722             overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
3723
3724             if (overwrite == NGX_ERROR) {
3725                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3726                                    "invalid value \"%V\"", &value[i]);
3727                 return NGX_CONF_ERROR;
3728             }
3729
3730         } else {
3731             overwrite = 0;
3732         }
3733
3734         n = 2;
3735
3736     } else {
3737         overwrite = -1;
3738         n = 1;
3739     }
3740
3741     uri = value[cf->args->nelts - 1];
3742     uri_lengths = NULL;
3743     uri_values = NULL;
3744
3745     nvar = ngx_http_script_variables_count(&uri);
3746
3747     if (nvar) {
3748         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3749
3750         sc.cf = cf;
3751         sc.source = &uri;
3752         sc.lengths = &uri_lengths;
3753         sc.values = &uri_values;
3754         sc.variables = nvar;
3755         sc.complete_lengths = 1;
3756         sc.complete_values = 1;
3757
3758         if (ngx_http_script_compile(&sc) != NGX_OK) {
3759             return NGX_CONF_ERROR;
3760         }
3761     }
3762
3763     args = (u_char *) ngx_strchr(uri.data, '?');
3764
3765     for (i = 1; i < cf->args->nelts - n; i++) {
3766         err = ngx_array_push(lcf->error_pages);
3767         if (err == NULL) {
3768             return NGX_CONF_ERROR;
3769         }
3770
3771         err->status = ngx_atoi(value[i].data, value[i].len);
3772
3773         if (err->status == NGX_ERROR || err->status == 499) {
3774             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3775                                "invalid value \"%V\"", &value[i]);
3776             return NGX_CONF_ERROR;
3777         }
3778
3779         if (err->status < 400 || err->status > 599) {
3780             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3781                                "value \"%V\" must be between 400 and 599",
3782                                &value[i]);
3783             return NGX_CONF_ERROR;
3784         }
3785
3786         if (overwrite >= 0) {
3787             err->overwrite = overwrite;
3788
3789         } else {
3790             switch (err->status) {
3791                 case NGX_HTTP_TO_HTTPS:
3792                 case NGX_HTTPS_CERT_ERROR:
3793                 case NGX_HTTPS_NO_CERT:
3794                     err->overwrite = NGX_HTTP_BAD_REQUEST;
3795                     break;
3796
3797                 default:
3798                     err->overwrite = err->status;
3799                     break;
3800             }
3801         }
3802
3803         if (args) {
3804             err->uri.len = args - uri.data;
3805             err->uri.data = uri.data;
3806             args++;
3807             err->args.len = (uri.data + uri.len) - args;
3808             err->args.data = args;
3809
3810         } else {
3811             err->uri = uri;
3812             err->args.len = 0;
3813             err->args.data = NULL;
3814         }
3815
3816         err->uri_lengths = uri_lengths;
3817         err->uri_values = uri_values;
3818     }
3819
3820     return NGX_CONF_OK;
3821 }
3822
3823
3824 static char *
3825 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3826 {
3827     ngx_http_core_loc_conf_t *clcf = conf;
3828
3829     ngx_str_t                  *value;
3830     ngx_uint_t                  i, n;
3831     ngx_http_try_file_t        *tf;
3832     ngx_http_script_compile_t   sc;
3833     ngx_http_core_main_conf_t  *cmcf;
3834
3835     if (clcf->try_files) {
3836         return "is duplicate";
3837     }
3838
3839     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
3840
3841     cmcf->try_files = 1;
3842
3843     tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
3844     if (tf == NULL) {
3845         return NGX_CONF_ERROR;
3846     }
3847
3848     clcf->try_files = tf;
3849
3850     value = cf->args->elts;
3851
3852     for (i = 0; i < cf->args->nelts - 1; i++) {
3853
3854         tf[i].name = value[i + 1];
3855
3856         n = ngx_http_script_variables_count(&tf[i].name);
3857
3858         if (n) {
3859             ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3860
3861             sc.cf = cf;
3862             sc.source = &tf[i].name;
3863             sc.lengths = &tf[i].lengths;
3864             sc.values = &tf[i].values;
3865             sc.variables = n;
3866             sc.complete_lengths = 1;
3867             sc.complete_values = 1;
3868
3869             if (ngx_http_script_compile(&sc) != NGX_OK) {
3870                 return NGX_CONF_ERROR;
3871             }
3872
3873         } else {
3874             /* add trailing '\0' to length */
3875             tf[i].name.len++;
3876         }
3877     }
3878
3879     return NGX_CONF_OK;
3880 }
3881
3882
3883 static char *
3884 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3885 {
3886     ngx_http_core_loc_conf_t *lcf = conf;
3887
3888     time_t       inactive;
3889     ngx_str_t   *value, s;
3890     ngx_int_t    max;
3891     ngx_uint_t   i;
3892
3893     if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) {
3894         return "is duplicate";
3895     }
3896
3897     value = cf->args->elts;
3898
3899     max = 0;
3900     inactive = 60;
3901
3902     for (i = 1; i < cf->args->nelts; i++) {
3903
3904         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
3905
3906             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
3907             if (max == NGX_ERROR) {
3908                 goto failed;
3909             }
3910
3911             continue;
3912         }
3913
3914         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
3915
3916             s.len = value[i].len - 9;
3917             s.data = value[i].data + 9;
3918
3919             inactive = ngx_parse_time(&s, 1);
3920             if (inactive < 0) {
3921                 goto failed;
3922             }
3923
3924             continue;
3925         }
3926
3927         if (ngx_strcmp(value[i].data, "off") == 0) {
3928
3929             lcf->open_file_cache = NULL;
3930
3931             continue;
3932         }
3933
3934     failed:
3935
3936         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3937                            "invalid \"open_file_cache\" parameter \"%V\"",
3938                            &value[i]);
3939         return NGX_CONF_ERROR;
3940     }
3941
3942     if (lcf->open_file_cache == NULL) {
3943         return NGX_CONF_OK;
3944     }
3945
3946     if (max == 0) {
3947         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3948                            "\"open_file_cache\" must have \"max\" parameter");
3949         return NGX_CONF_ERROR;
3950     }
3951
3952     lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
3953     if (lcf->open_file_cache) {
3954         return NGX_CONF_OK;
3955     }
3956
3957     return NGX_CONF_ERROR;
3958 }
3959
3960
3961 static char *
3962 ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3963 {
3964     ngx_http_core_loc_conf_t *lcf = conf;
3965
3966     lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
3967     if (lcf->err_log == NULL) {
3968         return NGX_CONF_ERROR;
3969     }
3970
3971     return ngx_set_error_log_levels(cf, lcf->err_log);
3972 }
3973
3974
3975 static char *
3976 ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3977 {
3978     ngx_http_core_loc_conf_t *lcf = conf;
3979
3980     ngx_str_t  *value;
3981
3982     if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
3983         return "is duplicate";
3984     }
3985
3986     value = cf->args->elts;
3987
3988     lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
3989
3990     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
3991         return "invalid value";
3992     }
3993
3994     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
3995         return "value must be less than 597 hours";
3996     }
3997
3998     if (cf->args->nelts == 2) {
3999         return NGX_CONF_OK;
4000     }
4001
4002     lcf->keepalive_header = ngx_parse_time(&value[2], 1);
4003
4004     if (lcf->keepalive_header == NGX_ERROR) {
4005         return "invalid value";
4006     }
4007
4008     if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
4009         return "value must be less than 68 years";
4010     }
4011
4012     return NGX_CONF_OK;
4013 }
4014
4015
4016 static char *
4017 ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4018 {
4019     ngx_http_core_loc_conf_t *lcf = conf;
4020
4021     if (lcf->internal != NGX_CONF_UNSET) {
4022         return "is duplicate";
4023     }
4024
4025     lcf->internal = 1;
4026
4027     return NGX_CONF_OK;
4028 }
4029
4030
4031 static char *
4032 ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4033 {
4034     ngx_http_core_loc_conf_t  *clcf = conf;
4035
4036     ngx_url_t   u;
4037     ngx_str_t  *value;
4038
4039     if (clcf->resolver) {
4040         return "is duplicate";
4041     }
4042
4043     value = cf->args->elts;
4044
4045     ngx_memzero(&u, sizeof(ngx_url_t));
4046
4047     u.host = value[1];
4048     u.port = 53;
4049
4050     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
4051         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
4052         return NGX_CONF_ERROR;
4053     }
4054
4055     clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
4056     if (clcf->resolver == NULL) {
4057         return NGX_OK;
4058     }
4059
4060     return NGX_CONF_OK;
4061 }
4062
4063
4064 #if (NGX_HTTP_GZIP)
4065
4066 static char *
4067 ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4068 {
4069     ngx_http_core_loc_conf_t  *clcf = conf;
4070
4071 #if (NGX_PCRE)
4072
4073     ngx_str_t         err, *value;
4074     ngx_uint_t        i;
4075     ngx_regex_elt_t  *re;
4076     u_char            errstr[NGX_MAX_CONF_ERRSTR];
4077
4078     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
4079         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
4080                                               sizeof(ngx_regex_elt_t));
4081         if (clcf->gzip_disable == NULL) {
4082             return NGX_CONF_ERROR;
4083         }
4084     }
4085
4086     value = cf->args->elts;
4087
4088     err.len = NGX_MAX_CONF_ERRSTR;
4089     err.data = errstr;
4090
4091     for (i = 1; i < cf->args->nelts; i++) {
4092
4093         if (ngx_strcmp(value[1].data, "msie6") == 0) {
4094             clcf->gzip_disable_msie6 = 1;
4095             continue;
4096         }
4097
4098         re = ngx_array_push(clcf->gzip_disable);
4099         if (re == NULL) {
4100             return NGX_CONF_ERROR;
4101         }
4102
4103         re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
4104                                       &err);
4105
4106         if (re->regex == NULL) {
4107             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
4108             return NGX_CONF_ERROR;
4109         }
4110
4111         re->name = value[i].data;
4112     }
4113
4114     return NGX_CONF_OK;
4115
4116 #else
4117     ngx_str_t  *value;
4118
4119     value = cf->args->elts;
4120
4121     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) {
4122         clcf->gzip_disable_msie6 = 1;
4123         return NGX_CONF_OK;
4124     }
4125
4126     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4127                        "without PCRE library \"gzip_disable\" supports "
4128                        "builtin \"msie6\" mask only");
4129
4130     return NGX_CONF_ERROR;
4131 #endif
4132 }
4133
4134 #endif
4135
4136
4137 static char *
4138 ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
4139 {
4140 #if (NGX_FREEBSD)
4141     ssize_t *np = data;
4142
4143     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
4144         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4145                            "\"send_lowat\" must be less than %d "
4146                            "(sysctl net.inet.tcp.sendspace)",
4147                            ngx_freebsd_net_inet_tcp_sendspace);
4148
4149         return NGX_CONF_ERROR;
4150     }
4151
4152 #elif !(NGX_HAVE_SO_SNDLOWAT)
4153     ssize_t *np = data;
4154
4155     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4156                        "\"send_lowat\" is not supported, ignored");
4157
4158     *np = 0;
4159
4160 #endif
4161
4162     return NGX_CONF_OK;
4163 }
4164
4165
4166 static char *
4167 ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
4168 {
4169     size_t *sp = data;
4170
4171     if (*sp < NGX_MIN_POOL_SIZE) {
4172         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4173                            "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
4174
4175         return NGX_CONF_ERROR;
4176     }
4177
4178     return NGX_CONF_OK;
4179 }