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