upstream nginx-0.7.36
[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->conf.backlog = NGX_LISTEN_BACKLOG;
2794         ls->conf.rcvbuf = -1;
2795         ls->conf.sndbuf = -1;
2796     }
2797
2798     if (conf->server_name.data == NULL) {
2799         conf->server_name = cf->cycle->hostname;
2800
2801         sn = ngx_array_push(&conf->server_names);
2802         if (sn == NULL) {
2803             return NGX_CONF_ERROR;
2804         }
2805
2806 #if (NGX_PCRE)
2807         sn->regex = NULL;
2808 #endif
2809         sn->core_srv_conf = conf;
2810         sn->name.len = conf->server_name.len;
2811         sn->name.data = conf->server_name.data;
2812     }
2813
2814     ngx_conf_merge_size_value(conf->connection_pool_size,
2815                               prev->connection_pool_size, 256);
2816     ngx_conf_merge_size_value(conf->request_pool_size,
2817                               prev->request_pool_size, 4096);
2818     ngx_conf_merge_msec_value(conf->client_header_timeout,
2819                               prev->client_header_timeout, 60000);
2820     ngx_conf_merge_size_value(conf->client_header_buffer_size,
2821                               prev->client_header_buffer_size, 1024);
2822     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
2823                               prev->large_client_header_buffers,
2824                               4, ngx_pagesize);
2825
2826     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
2827         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2828                            "the \"large_client_header_buffers\" size must be "
2829                            "equal to or bigger than \"connection_pool_size\"");
2830         return NGX_CONF_ERROR;
2831     }
2832
2833     ngx_conf_merge_value(conf->ignore_invalid_headers,
2834                               prev->ignore_invalid_headers, 1);
2835
2836     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
2837
2838     ngx_conf_merge_value(conf->underscores_in_headers,
2839                               prev->underscores_in_headers, 0);
2840
2841     return NGX_CONF_OK;
2842 }
2843
2844
2845 static void *
2846 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
2847 {
2848     ngx_http_core_loc_conf_t  *lcf;
2849
2850     lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
2851     if (lcf == NULL) {
2852         return NGX_CONF_ERROR;
2853     }
2854
2855     /*
2856      * set by ngx_pcalloc():
2857      *
2858      *     lcf->root = { 0, NULL };
2859      *     lcf->limit_except = 0;
2860      *     lcf->post_action = { 0, NULL };
2861      *     lcf->types = NULL;
2862      *     lcf->default_type = { 0, NULL };
2863      *     lcf->err_log = NULL;
2864      *     lcf->error_pages = NULL;
2865      *     lcf->try_files = NULL;
2866      *     lcf->client_body_path = NULL;
2867      *     lcf->regex = NULL;
2868      *     lcf->exact_match = 0;
2869      *     lcf->auto_redirect = 0;
2870      *     lcf->alias = 0;
2871      *     lcf->gzip_proxied = 0;
2872      */
2873
2874     lcf->client_max_body_size = NGX_CONF_UNSET;
2875     lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
2876     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
2877     lcf->satisfy = NGX_CONF_UNSET_UINT;
2878     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
2879     lcf->internal = NGX_CONF_UNSET;
2880     lcf->client_body_in_file_only = NGX_CONF_UNSET;
2881     lcf->sendfile = NGX_CONF_UNSET;
2882     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
2883     lcf->directio = NGX_CONF_UNSET;
2884     lcf->tcp_nopush = NGX_CONF_UNSET;
2885     lcf->tcp_nodelay = NGX_CONF_UNSET;
2886     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
2887     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
2888     lcf->postpone_output = NGX_CONF_UNSET_SIZE;
2889     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
2890     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
2891     lcf->keepalive_header = NGX_CONF_UNSET;
2892     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
2893     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
2894     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
2895     lcf->reset_timedout_connection = NGX_CONF_UNSET;
2896     lcf->server_name_in_redirect = NGX_CONF_UNSET;
2897     lcf->port_in_redirect = NGX_CONF_UNSET;
2898     lcf->msie_padding = NGX_CONF_UNSET;
2899     lcf->msie_refresh = NGX_CONF_UNSET;
2900     lcf->log_not_found = NGX_CONF_UNSET;
2901     lcf->log_subrequest = NGX_CONF_UNSET;
2902     lcf->recursive_error_pages = NGX_CONF_UNSET;
2903     lcf->server_tokens = NGX_CONF_UNSET;
2904     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
2905     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
2906
2907     lcf->open_file_cache = NGX_CONF_UNSET_PTR;
2908     lcf->open_file_cache_valid = NGX_CONF_UNSET;
2909     lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
2910     lcf->open_file_cache_errors = NGX_CONF_UNSET;
2911     lcf->open_file_cache_events = NGX_CONF_UNSET;
2912
2913 #if (NGX_HTTP_GZIP)
2914     lcf->gzip_vary = NGX_CONF_UNSET;
2915     lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
2916 #if (NGX_PCRE)
2917     lcf->gzip_disable = NGX_CONF_UNSET_PTR;
2918     lcf->gzip_disable_msie6 = 3;
2919 #endif
2920 #endif
2921
2922     return lcf;
2923 }
2924
2925
2926 static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
2927 static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
2928 static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
2929
2930 static ngx_hash_key_t  ngx_http_core_default_types[] = {
2931     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
2932     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
2933     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
2934     { ngx_null_string, 0, NULL }
2935 };
2936
2937
2938 static char *
2939 ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2940 {
2941     ngx_http_core_loc_conf_t *prev = parent;
2942     ngx_http_core_loc_conf_t *conf = child;
2943
2944     ngx_uint_t        i;
2945     ngx_hash_key_t   *type;
2946     ngx_hash_init_t   types_hash;
2947
2948     if (conf->root.data == NULL) {
2949
2950         conf->alias = prev->alias;
2951         conf->root = prev->root;
2952         conf->root_lengths = prev->root_lengths;
2953         conf->root_values = prev->root_values;
2954
2955         if (prev->root.data == NULL) {
2956             conf->root.len = sizeof("html") - 1;
2957             conf->root.data = (u_char *) "html";
2958
2959             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) {
2960                 return NGX_CONF_ERROR;
2961             }
2962         }
2963     }
2964
2965     if (conf->post_action.data == NULL) {
2966         conf->post_action = prev->post_action;
2967     }
2968
2969     ngx_conf_merge_uint_value(conf->types_hash_max_size,
2970                               prev->types_hash_max_size, 1024);
2971
2972     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
2973                               prev->types_hash_bucket_size,
2974                               ngx_cacheline_size);
2975
2976     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
2977                                              ngx_cacheline_size);
2978
2979     /*
2980      * the special handling the "types" directive in the "http" section
2981      * to inherit the http's conf->types_hash to all servers
2982      */
2983
2984     if (prev->types && prev->types_hash.buckets == NULL) {
2985
2986         types_hash.hash = &prev->types_hash;
2987         types_hash.key = ngx_hash_key_lc;
2988         types_hash.max_size = conf->types_hash_max_size;
2989         types_hash.bucket_size = conf->types_hash_bucket_size;
2990         types_hash.name = "types_hash";
2991         types_hash.pool = cf->pool;
2992         types_hash.temp_pool = NULL;
2993
2994         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
2995             != NGX_OK)
2996         {
2997             return NGX_CONF_ERROR;
2998         }
2999     }
3000
3001     if (conf->types == NULL) {
3002         conf->types = prev->types;
3003         conf->types_hash = prev->types_hash;
3004     }
3005
3006     if (conf->types == NULL) {
3007         conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
3008         if (conf->types == NULL) {
3009             return NGX_CONF_ERROR;
3010         }
3011
3012         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
3013             type = ngx_array_push(conf->types);
3014             if (type == NULL) {
3015                 return NGX_CONF_ERROR;
3016             }
3017
3018             type->key = ngx_http_core_default_types[i].key;
3019             type->key_hash =
3020                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3021                                        ngx_http_core_default_types[i].key.len);
3022             type->value = ngx_http_core_default_types[i].value;
3023         }
3024     }
3025
3026     if (conf->types_hash.buckets == NULL) {
3027
3028         types_hash.hash = &conf->types_hash;
3029         types_hash.key = ngx_hash_key_lc;
3030         types_hash.max_size = conf->types_hash_max_size;
3031         types_hash.bucket_size = conf->types_hash_bucket_size;
3032         types_hash.name = "mime_types_hash";
3033         types_hash.pool = cf->pool;
3034         types_hash.temp_pool = NULL;
3035
3036         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3037             != NGX_OK)
3038         {
3039             return NGX_CONF_ERROR;
3040         }
3041     }
3042
3043     if (conf->err_log == NULL) {
3044         if (prev->err_log) {
3045             conf->err_log = prev->err_log;
3046         } else {
3047             conf->err_log = cf->cycle->new_log;
3048         }
3049     }
3050
3051     if (conf->error_pages == NULL && prev->error_pages) {
3052         conf->error_pages = prev->error_pages;
3053     }
3054
3055     ngx_conf_merge_str_value(conf->default_type,
3056                               prev->default_type, "text/plain");
3057
3058     ngx_conf_merge_off_value(conf->client_max_body_size,
3059                               prev->client_max_body_size, 1 * 1024 * 1024);
3060     ngx_conf_merge_size_value(conf->client_body_buffer_size,
3061                               prev->client_body_buffer_size,
3062                               (size_t) 2 * ngx_pagesize);
3063     ngx_conf_merge_msec_value(conf->client_body_timeout,
3064                               prev->client_body_timeout, 60000);
3065
3066     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3067                               NGX_HTTP_SATISFY_ALL);
3068     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3069                               NGX_HTTP_IMS_EXACT);
3070     ngx_conf_merge_value(conf->internal, prev->internal, 0);
3071     ngx_conf_merge_value(conf->client_body_in_file_only,
3072                               prev->client_body_in_file_only, 0);
3073     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3074     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3075                               prev->sendfile_max_chunk, 0);
3076     ngx_conf_merge_off_value(conf->directio, prev->directio,
3077                               NGX_MAX_OFF_T_VALUE);
3078     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3079     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3080
3081     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3082     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3083     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3084                               1460);
3085     ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3086     ngx_conf_merge_msec_value(conf->keepalive_timeout,
3087                               prev->keepalive_timeout, 75000);
3088     ngx_conf_merge_sec_value(conf->keepalive_header,
3089                               prev->keepalive_header, 0);
3090     ngx_conf_merge_msec_value(conf->lingering_time,
3091                               prev->lingering_time, 30000);
3092     ngx_conf_merge_msec_value(conf->lingering_timeout,
3093                               prev->lingering_timeout, 5000);
3094     ngx_conf_merge_msec_value(conf->resolver_timeout,
3095                               prev->resolver_timeout, 30000);
3096
3097     if (conf->resolver == NULL) {
3098
3099         if (prev->resolver == NULL) {
3100
3101             /*
3102              * create dummy resolver in http {} context
3103              * to inherit it in all servers
3104              */
3105
3106             prev->resolver = ngx_resolver_create(cf, NULL);
3107             if (prev->resolver == NULL) {
3108                 return NGX_CONF_ERROR;
3109             }
3110         }
3111
3112         conf->resolver = prev->resolver;
3113     }
3114
3115     ngx_conf_merge_path_value(conf->client_body_temp_path,
3116                               prev->client_body_temp_path,
3117                               NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
3118                               ngx_garbage_collector_temp_handler, cf);
3119
3120     ngx_conf_merge_value(conf->reset_timedout_connection,
3121                               prev->reset_timedout_connection, 0);
3122     ngx_conf_merge_value(conf->server_name_in_redirect,
3123                               prev->server_name_in_redirect, 1);
3124     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3125     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3126     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3127     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3128     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3129     ngx_conf_merge_value(conf->recursive_error_pages,
3130                               prev->recursive_error_pages, 0);
3131     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
3132
3133     ngx_conf_merge_ptr_value(conf->open_file_cache,
3134                               prev->open_file_cache, NULL);
3135
3136     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3137                               prev->open_file_cache_valid, 60);
3138
3139     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3140                               prev->open_file_cache_min_uses, 1);
3141
3142     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3143                               prev->open_file_cache_errors, 0);
3144
3145     ngx_conf_merge_sec_value(conf->open_file_cache_events,
3146                               prev->open_file_cache_events, 0);
3147 #if (NGX_HTTP_GZIP)
3148
3149     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3150     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3151                               NGX_HTTP_VERSION_11);
3152     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3153                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3154
3155 #if (NGX_PCRE)
3156     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3157 #endif
3158
3159     if (conf->gzip_disable_msie6 == 3) {
3160         conf->gzip_disable_msie6 =
3161             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3162     }
3163
3164 #endif
3165
3166     return NGX_CONF_OK;
3167 }
3168
3169
3170 static char *
3171 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3172 {
3173     ngx_http_core_srv_conf_t *scf = conf;
3174
3175     ngx_str_t          *value, size;
3176     ngx_url_t           u;
3177     ngx_uint_t          n;
3178     ngx_http_listen_t  *ls;
3179
3180     /*
3181      * TODO: check duplicate 'listen' directives,
3182      *       add resolved name to server names ???
3183      */
3184
3185     value = cf->args->elts;
3186
3187     ngx_memzero(&u, sizeof(ngx_url_t));
3188
3189     u.url = value[1];
3190     u.listen = 1;
3191     u.default_port = 80;
3192
3193     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3194         if (u.err) {
3195             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3196                                "%s in \"%V\" of the \"listen\" directive",
3197                                u.err, &u.url);
3198         }
3199
3200         return NGX_CONF_ERROR;
3201     }
3202
3203     ls = ngx_array_push(&scf->listen);
3204     if (ls == NULL) {
3205         return NGX_CONF_ERROR;
3206     }
3207
3208     ngx_memzero(ls, sizeof(ngx_http_listen_t));
3209
3210     ngx_memcpy(ls->sockaddr, u.sockaddr, u.socklen);
3211
3212     ls->socklen = u.socklen;
3213     ls->file_name = cf->conf_file->file.name.data;
3214     ls->line = cf->conf_file->line;
3215     ls->conf.backlog = NGX_LISTEN_BACKLOG;
3216     ls->conf.rcvbuf = -1;
3217     ls->conf.sndbuf = -1;
3218     ls->conf.wildcard = u.wildcard;
3219
3220     (void) ngx_sock_ntop((struct sockaddr *) &ls->sockaddr, ls->conf.addr,
3221                          NGX_SOCKADDR_STRLEN, 1);
3222
3223     if (cf->args->nelts == 2) {
3224         return NGX_CONF_OK;
3225     }
3226
3227     if (ngx_strcmp(value[2].data, "default") == 0) {
3228         ls->conf.default_server = 1;
3229         n = 3;
3230
3231     } else {
3232         n = 2;
3233     }
3234
3235     for ( /* void */ ; n < cf->args->nelts; n++) {
3236
3237         if (ls->conf.default_server == 0) {
3238             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3239                                "\"%V\" parameter can be specified for "
3240                                "the default \"listen\" directive only",
3241                                &value[n]);
3242             return NGX_CONF_ERROR;
3243         }
3244
3245         if (ngx_strcmp(value[n].data, "bind") == 0) {
3246             ls->conf.bind = 1;
3247             continue;
3248         }
3249
3250         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
3251             ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
3252             ls->conf.bind = 1;
3253
3254             if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
3255                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3256                                    "invalid backlog \"%V\"", &value[n]);
3257                 return NGX_CONF_ERROR;
3258             }
3259
3260             continue;
3261         }
3262
3263         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
3264             size.len = value[n].len - 7;
3265             size.data = value[n].data + 7;
3266
3267             ls->conf.rcvbuf = ngx_parse_size(&size);
3268             ls->conf.bind = 1;
3269
3270             if (ls->conf.rcvbuf == NGX_ERROR) {
3271                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3272                                    "invalid rcvbuf \"%V\"", &value[n]);
3273                 return NGX_CONF_ERROR;
3274             }
3275
3276             continue;
3277         }
3278
3279         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
3280             size.len = value[n].len - 7;
3281             size.data = value[n].data + 7;
3282
3283             ls->conf.sndbuf = ngx_parse_size(&size);
3284             ls->conf.bind = 1;
3285
3286             if (ls->conf.sndbuf == NGX_ERROR) {
3287                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3288                                    "invalid sndbuf \"%V\"", &value[n]);
3289                 return NGX_CONF_ERROR;
3290             }
3291
3292             continue;
3293         }
3294
3295         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
3296 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
3297             ls->conf.accept_filter = (char *) &value[n].data[14];
3298             ls->conf.bind = 1;
3299 #else
3300             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3301                                "accept filters \"%V\" are not supported "
3302                                "on this platform, ignored",
3303                                &value[n]);
3304 #endif
3305             continue;
3306         }
3307
3308         if (ngx_strcmp(value[n].data, "deferred") == 0) {
3309 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
3310             ls->conf.deferred_accept = 1;
3311             ls->conf.bind = 1;
3312 #else
3313             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3314                                "the deferred accept is not supported "
3315                                "on this platform, ignored");
3316 #endif
3317             continue;
3318         }
3319
3320         if (ngx_strcmp(value[n].data, "ssl") == 0) {
3321 #if (NGX_HTTP_SSL)
3322             ls->conf.ssl = 1;
3323             continue;
3324 #else
3325             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3326                                "the \"ssl\" parameter requires "
3327                                "ngx_http_ssl_module");
3328             return NGX_CONF_ERROR;
3329 #endif
3330         }
3331
3332         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3333                            "the invalid \"%V\" parameter", &value[n]);
3334         return NGX_CONF_ERROR;
3335     }
3336
3337     return NGX_CONF_OK;
3338 }
3339
3340
3341 static char *
3342 ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3343 {
3344     ngx_http_core_srv_conf_t *cscf = conf;
3345
3346     u_char                   ch;
3347     ngx_str_t               *value, name;
3348     ngx_uint_t               i;
3349     ngx_http_server_name_t  *sn;
3350
3351     value = cf->args->elts;
3352
3353     ch = value[1].data[0];
3354
3355     if (cscf->server_name.data == NULL) {
3356         if (value[1].len) {
3357             name = value[1];
3358
3359             if (ch == '.') {
3360                 name.len--;
3361                 name.data++;
3362             }
3363
3364             cscf->server_name.len = name.len;
3365             cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
3366             if (cscf->server_name.data == NULL) {
3367                 return NGX_CONF_ERROR;
3368             }
3369
3370         } else {
3371             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3372                                "the first server name must not be empty");
3373             return NGX_CONF_ERROR;
3374         }
3375     }
3376
3377     for (i = 1; i < cf->args->nelts; i++) {
3378
3379         ch = value[i].data[0];
3380
3381         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
3382             || (ch == '.' && value[i].len < 2))
3383         {
3384             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3385                                "server name \"%V\" is invalid", &value[i]);
3386             return NGX_CONF_ERROR;
3387         }
3388
3389         if (ngx_strchr(value[i].data, '/')) {
3390             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3391                                "server name \"%V\" has strange symbols",
3392                                &value[i]);
3393         }
3394
3395         if (value[i].len == 1 && ch == '*') {
3396             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3397                                "\"server_name *\" is unsupported, use "
3398                                "\"server_name_in_redirect off\" instead");
3399             return NGX_CONF_ERROR;
3400         }
3401
3402         sn = ngx_array_push(&cscf->server_names);
3403         if (sn == NULL) {
3404             return NGX_CONF_ERROR;
3405         }
3406
3407 #if (NGX_PCRE)
3408         sn->regex = NULL;
3409 #endif
3410         sn->core_srv_conf = cscf;
3411         sn->name = value[i];
3412
3413         if (value[i].data[0] != '~') {
3414             continue;
3415         }
3416
3417 #if (NGX_PCRE)
3418         {
3419         ngx_str_t  err;
3420         u_char     errstr[NGX_MAX_CONF_ERRSTR];
3421
3422         err.len = NGX_MAX_CONF_ERRSTR;
3423         err.data = errstr;
3424
3425         value[i].len--;
3426         value[i].data++;
3427
3428         sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
3429
3430         if (sn->regex == NULL) {
3431             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
3432             return NGX_CONF_ERROR;
3433         }
3434
3435         sn->name = value[i];
3436         }
3437 #else
3438         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3439                            "the using of the regex \"%V\" "
3440                            "requires PCRE library", &value[i]);
3441
3442         return NGX_CONF_ERROR;
3443 #endif
3444     }
3445
3446     return NGX_CONF_OK;
3447 }
3448
3449
3450 static char *
3451 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3452 {
3453     ngx_http_core_loc_conf_t *lcf = conf;
3454
3455     ngx_str_t                  *value;
3456     ngx_uint_t                  alias, n;
3457     ngx_http_script_compile_t   sc;
3458
3459     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
3460
3461     if (lcf->root.data) {
3462
3463         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
3464
3465         if ((ngx_uint_t) lcf->alias == alias) {
3466             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3467                                "\"%V\" directive is duplicate",
3468                                &cmd->name);
3469         } else {
3470             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3471                                "\"%V\" directive is duplicate, "
3472                                "\"%s\" directive is specified before",
3473                                &cmd->name, lcf->alias ? "alias" : "root");
3474         }
3475
3476         return NGX_CONF_ERROR;
3477     }
3478
3479     if (lcf->named && alias) {
3480         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3481                            "the \"alias\" directive may not be used "
3482                            "inside named location");
3483
3484         return NGX_CONF_ERROR;
3485     }
3486
3487 #if (NGX_PCRE)
3488
3489     if (lcf->regex && alias) {
3490         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3491                            "the \"alias\" directive may not be used "
3492                            "inside location given by regular expression");
3493
3494         return NGX_CONF_ERROR;
3495     }
3496
3497 #endif
3498
3499     value = cf->args->elts;
3500
3501     if (ngx_strstr(value[1].data, "$document_root")
3502         || ngx_strstr(value[1].data, "${document_root}"))
3503     {
3504         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3505                            "the $document_root variable may not be used "
3506                            "in the \"%V\" directive",
3507                            &cmd->name);
3508
3509         return NGX_CONF_ERROR;
3510     }
3511
3512     if (ngx_strstr(value[1].data, "$realpath_root")
3513         || ngx_strstr(value[1].data, "${realpath_root}"))
3514     {
3515         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3516                            "the $realpath_root variable may not be used "
3517                            "in the \"%V\" directive",
3518                            &cmd->name);
3519
3520         return NGX_CONF_ERROR;
3521     }
3522
3523     lcf->alias = alias;
3524     lcf->root = value[1];
3525
3526     if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
3527         lcf->root.len--;
3528     }
3529
3530     if (lcf->root.data[0] != '$') {
3531         if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) {
3532             return NGX_CONF_ERROR;
3533         }
3534     }
3535
3536     n = ngx_http_script_variables_count(&lcf->root);
3537
3538     if (n == 0) {
3539         return NGX_CONF_OK;
3540     }
3541
3542     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3543
3544     sc.cf = cf;
3545     sc.source = &lcf->root;
3546     sc.lengths = &lcf->root_lengths;
3547     sc.values = &lcf->root_values;
3548     sc.variables = n;
3549     sc.complete_lengths = 1;
3550     sc.complete_values = 1;
3551
3552     if (ngx_http_script_compile(&sc) != NGX_OK) {
3553         return NGX_CONF_ERROR;
3554     }
3555
3556     return NGX_CONF_OK;
3557 }
3558
3559
3560 static ngx_http_method_name_t  ngx_methods_names[] = {
3561    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
3562    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
3563    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
3564    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
3565    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
3566    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
3567    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
3568    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
3569    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
3570    { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
3571    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
3572    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
3573    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
3574    { NULL, 0 }
3575 };
3576
3577
3578 static char *
3579 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3580 {
3581     ngx_http_core_loc_conf_t *pclcf = conf;
3582
3583     char                      *rv;
3584     void                      *mconf;
3585     ngx_str_t                 *value;
3586     ngx_uint_t                 i;
3587     ngx_conf_t                 save;
3588     ngx_http_module_t         *module;
3589     ngx_http_conf_ctx_t       *ctx, *pctx;
3590     ngx_http_method_name_t    *name;
3591     ngx_http_core_loc_conf_t  *clcf;
3592
3593     if (pclcf->limit_except) {
3594         return "duplicate";
3595     }
3596
3597     pclcf->limit_except = 0xffffffff;
3598
3599     value = cf->args->elts;
3600
3601     for (i = 1; i < cf->args->nelts; i++) {
3602         for (name = ngx_methods_names; name->name; name++) {
3603
3604             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
3605                 pclcf->limit_except &= name->method;
3606                 goto next;
3607             }
3608         }
3609
3610         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3611                            "invalid method \"%V\"", &value[i]);
3612         return NGX_CONF_ERROR;
3613
3614     next:
3615         continue;
3616     }
3617
3618     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
3619         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
3620     }
3621
3622     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3623     if (ctx == NULL) {
3624         return NGX_CONF_ERROR;
3625     }
3626
3627     pctx = cf->ctx;
3628     ctx->main_conf = pctx->main_conf;
3629     ctx->srv_conf = pctx->srv_conf;
3630
3631     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
3632     if (ctx->loc_conf == NULL) {
3633         return NGX_CONF_ERROR;
3634     }
3635
3636     for (i = 0; ngx_modules[i]; i++) {
3637         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
3638             continue;
3639         }
3640
3641         module = ngx_modules[i]->ctx;
3642
3643         if (module->create_loc_conf) {
3644
3645             mconf = module->create_loc_conf(cf);
3646             if (mconf == NULL) {
3647                  return NGX_CONF_ERROR;
3648             }
3649
3650             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
3651         }
3652     }
3653
3654
3655     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
3656     pclcf->limit_except_loc_conf = ctx->loc_conf;
3657     clcf->loc_conf = ctx->loc_conf;
3658     clcf->name = pclcf->name;
3659     clcf->noname = 1;
3660
3661     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
3662         return NGX_CONF_ERROR;
3663     }
3664
3665     save = *cf;
3666     cf->ctx = ctx;
3667     cf->cmd_type = NGX_HTTP_LMT_CONF;
3668
3669     rv = ngx_conf_parse(cf, NULL);
3670
3671     *cf = save;
3672
3673     return rv;
3674 }
3675
3676
3677 static char *
3678 ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3679 {
3680     ngx_http_core_loc_conf_t *clcf = conf;
3681
3682     ngx_str_t  *value;
3683
3684     if (clcf->directio != NGX_CONF_UNSET) {
3685         return "is duplicate";
3686     }
3687
3688     value = cf->args->elts;
3689
3690     if (ngx_strcmp(value[1].data, "off") == 0) {
3691         clcf->directio = NGX_OPEN_FILE_DIRECTIO_OFF;
3692         return NGX_CONF_OK;
3693     }
3694
3695     clcf->directio = ngx_parse_offset(&value[1]);
3696     if (clcf->directio == (off_t) NGX_ERROR) {
3697         return "invalid value";
3698     }
3699
3700     return NGX_CONF_OK;
3701 }
3702
3703
3704 static char *
3705 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3706 {
3707     ngx_http_core_loc_conf_t *lcf = conf;
3708
3709     u_char                     *args;
3710     ngx_int_t                   overwrite;
3711     ngx_str_t                  *value, uri;
3712     ngx_uint_t                  i, n, nvar;
3713     ngx_array_t                *uri_lengths, *uri_values;
3714     ngx_http_err_page_t        *err;
3715     ngx_http_script_compile_t   sc;
3716
3717     if (lcf->error_pages == NULL) {
3718         lcf->error_pages = ngx_array_create(cf->pool, 4,
3719                                             sizeof(ngx_http_err_page_t));
3720         if (lcf->error_pages == NULL) {
3721             return NGX_CONF_ERROR;
3722         }
3723     }
3724
3725     value = cf->args->elts;
3726
3727     i = cf->args->nelts - 2;
3728
3729     if (value[i].data[0] == '=') {
3730         if (i == 1) {
3731             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3732                                "invalid value \"%V\"", &value[i]);
3733             return NGX_CONF_ERROR;
3734         }
3735
3736         if (value[i].len > 1) {
3737             overwrite = ngx_atoi(&value[i].data[1], value[i].len - 1);
3738
3739             if (overwrite == NGX_ERROR) {
3740                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3741                                    "invalid value \"%V\"", &value[i]);
3742                 return NGX_CONF_ERROR;
3743             }
3744
3745         } else {
3746             overwrite = 0;
3747         }
3748
3749         n = 2;
3750
3751     } else {
3752         overwrite = -1;
3753         n = 1;
3754     }
3755
3756     uri = value[cf->args->nelts - 1];
3757     uri_lengths = NULL;
3758     uri_values = NULL;
3759
3760     nvar = ngx_http_script_variables_count(&uri);
3761
3762     if (nvar) {
3763         ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3764
3765         sc.cf = cf;
3766         sc.source = &uri;
3767         sc.lengths = &uri_lengths;
3768         sc.values = &uri_values;
3769         sc.variables = nvar;
3770         sc.complete_lengths = 1;
3771         sc.complete_values = 1;
3772
3773         if (ngx_http_script_compile(&sc) != NGX_OK) {
3774             return NGX_CONF_ERROR;
3775         }
3776     }
3777
3778     args = (u_char *) ngx_strchr(uri.data, '?');
3779
3780     for (i = 1; i < cf->args->nelts - n; i++) {
3781         err = ngx_array_push(lcf->error_pages);
3782         if (err == NULL) {
3783             return NGX_CONF_ERROR;
3784         }
3785
3786         err->status = ngx_atoi(value[i].data, value[i].len);
3787
3788         if (err->status == NGX_ERROR || err->status == 499) {
3789             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3790                                "invalid value \"%V\"", &value[i]);
3791             return NGX_CONF_ERROR;
3792         }
3793
3794         if (err->status < 400 || err->status > 599) {
3795             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3796                                "value \"%V\" must be between 400 and 599",
3797                                &value[i]);
3798             return NGX_CONF_ERROR;
3799         }
3800
3801         if (overwrite >= 0) {
3802             err->overwrite = overwrite;
3803
3804         } else {
3805             switch (err->status) {
3806                 case NGX_HTTP_TO_HTTPS:
3807                 case NGX_HTTPS_CERT_ERROR:
3808                 case NGX_HTTPS_NO_CERT:
3809                     err->overwrite = NGX_HTTP_BAD_REQUEST;
3810                     break;
3811
3812                 default:
3813                     err->overwrite = err->status;
3814                     break;
3815             }
3816         }
3817
3818         if (args) {
3819             err->uri.len = args - uri.data;
3820             err->uri.data = uri.data;
3821             args++;
3822             err->args.len = (uri.data + uri.len) - args;
3823             err->args.data = args;
3824
3825         } else {
3826             err->uri = uri;
3827             err->args.len = 0;
3828             err->args.data = NULL;
3829         }
3830
3831         err->uri_lengths = uri_lengths;
3832         err->uri_values = uri_values;
3833     }
3834
3835     return NGX_CONF_OK;
3836 }
3837
3838
3839 static char *
3840 ngx_http_core_try_files(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3841 {
3842     ngx_http_core_loc_conf_t *clcf = conf;
3843
3844     ngx_str_t                  *value;
3845     ngx_uint_t                  i, n;
3846     ngx_http_try_file_t        *tf;
3847     ngx_http_script_compile_t   sc;
3848     ngx_http_core_main_conf_t  *cmcf;
3849
3850     if (clcf->try_files) {
3851         return "is duplicate";
3852     }
3853
3854     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
3855
3856     cmcf->try_files = 1;
3857
3858     tf = ngx_pcalloc(cf->pool, cf->args->nelts * sizeof(ngx_http_try_file_t));
3859     if (tf == NULL) {
3860         return NGX_CONF_ERROR;
3861     }
3862
3863     clcf->try_files = tf;
3864
3865     value = cf->args->elts;
3866
3867     for (i = 0; i < cf->args->nelts - 1; i++) {
3868
3869         tf[i].name = value[i + 1];
3870
3871         if (tf[i].name.data[tf[i].name.len - 1] == '/') {
3872             tf[i].test_dir = 1;
3873             tf[i].name.len--;
3874         }
3875
3876         n = ngx_http_script_variables_count(&tf[i].name);
3877
3878         if (n) {
3879             ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3880
3881             sc.cf = cf;
3882             sc.source = &tf[i].name;
3883             sc.lengths = &tf[i].lengths;
3884             sc.values = &tf[i].values;
3885             sc.variables = n;
3886             sc.complete_lengths = 1;
3887             sc.complete_values = 1;
3888
3889             if (ngx_http_script_compile(&sc) != NGX_OK) {
3890                 return NGX_CONF_ERROR;
3891             }
3892
3893         } else {
3894             /* add trailing '\0' to length */
3895             tf[i].name.len++;
3896         }
3897     }
3898
3899     return NGX_CONF_OK;
3900 }
3901
3902
3903 static char *
3904 ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3905 {
3906     ngx_http_core_loc_conf_t *lcf = conf;
3907
3908     time_t       inactive;
3909     ngx_str_t   *value, s;
3910     ngx_int_t    max;
3911     ngx_uint_t   i;
3912
3913     if (lcf->open_file_cache != NGX_CONF_UNSET_PTR) {
3914         return "is duplicate";
3915     }
3916
3917     value = cf->args->elts;
3918
3919     max = 0;
3920     inactive = 60;
3921
3922     for (i = 1; i < cf->args->nelts; i++) {
3923
3924         if (ngx_strncmp(value[i].data, "max=", 4) == 0) {
3925
3926             max = ngx_atoi(value[i].data + 4, value[i].len - 4);
3927             if (max == NGX_ERROR) {
3928                 goto failed;
3929             }
3930
3931             continue;
3932         }
3933
3934         if (ngx_strncmp(value[i].data, "inactive=", 9) == 0) {
3935
3936             s.len = value[i].len - 9;
3937             s.data = value[i].data + 9;
3938
3939             inactive = ngx_parse_time(&s, 1);
3940             if (inactive < 0) {
3941                 goto failed;
3942             }
3943
3944             continue;
3945         }
3946
3947         if (ngx_strcmp(value[i].data, "off") == 0) {
3948
3949             lcf->open_file_cache = NULL;
3950
3951             continue;
3952         }
3953
3954     failed:
3955
3956         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3957                            "invalid \"open_file_cache\" parameter \"%V\"",
3958                            &value[i]);
3959         return NGX_CONF_ERROR;
3960     }
3961
3962     if (lcf->open_file_cache == NULL) {
3963         return NGX_CONF_OK;
3964     }
3965
3966     if (max == 0) {
3967         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3968                            "\"open_file_cache\" must have \"max\" parameter");
3969         return NGX_CONF_ERROR;
3970     }
3971
3972     lcf->open_file_cache = ngx_open_file_cache_init(cf->pool, max, inactive);
3973     if (lcf->open_file_cache) {
3974         return NGX_CONF_OK;
3975     }
3976
3977     return NGX_CONF_ERROR;
3978 }
3979
3980
3981 static char *
3982 ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3983 {
3984     ngx_http_core_loc_conf_t *lcf = conf;
3985
3986     lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
3987     if (lcf->err_log == NULL) {
3988         return NGX_CONF_ERROR;
3989     }
3990
3991     return ngx_set_error_log_levels(cf, lcf->err_log);
3992 }
3993
3994
3995 static char *
3996 ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3997 {
3998     ngx_http_core_loc_conf_t *lcf = conf;
3999
4000     ngx_str_t  *value;
4001
4002     if (lcf->keepalive_timeout != NGX_CONF_UNSET_MSEC) {
4003         return "is duplicate";
4004     }
4005
4006     value = cf->args->elts;
4007
4008     lcf->keepalive_timeout = ngx_parse_time(&value[1], 0);
4009
4010     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_ERROR) {
4011         return "invalid value";
4012     }
4013
4014     if (lcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
4015         return "value must be less than 597 hours";
4016     }
4017
4018     if (cf->args->nelts == 2) {
4019         return NGX_CONF_OK;
4020     }
4021
4022     lcf->keepalive_header = ngx_parse_time(&value[2], 1);
4023
4024     if (lcf->keepalive_header == NGX_ERROR) {
4025         return "invalid value";
4026     }
4027
4028     if (lcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
4029         return "value must be less than 68 years";
4030     }
4031
4032     return NGX_CONF_OK;
4033 }
4034
4035
4036 static char *
4037 ngx_http_core_internal(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4038 {
4039     ngx_http_core_loc_conf_t *lcf = conf;
4040
4041     if (lcf->internal != NGX_CONF_UNSET) {
4042         return "is duplicate";
4043     }
4044
4045     lcf->internal = 1;
4046
4047     return NGX_CONF_OK;
4048 }
4049
4050
4051 static char *
4052 ngx_http_core_resolver(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4053 {
4054     ngx_http_core_loc_conf_t  *clcf = conf;
4055
4056     ngx_url_t   u;
4057     ngx_str_t  *value;
4058
4059     if (clcf->resolver) {
4060         return "is duplicate";
4061     }
4062
4063     value = cf->args->elts;
4064
4065     ngx_memzero(&u, sizeof(ngx_url_t));
4066
4067     u.host = value[1];
4068     u.port = 53;
4069
4070     if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
4071         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%V: %s", &u.host, u.err);
4072         return NGX_CONF_ERROR;
4073     }
4074
4075     clcf->resolver = ngx_resolver_create(cf, &u.addrs[0]);
4076     if (clcf->resolver == NULL) {
4077         return NGX_OK;
4078     }
4079
4080     return NGX_CONF_OK;
4081 }
4082
4083
4084 #if (NGX_HTTP_GZIP)
4085
4086 static char *
4087 ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
4088 {
4089     ngx_http_core_loc_conf_t  *clcf = conf;
4090
4091 #if (NGX_PCRE)
4092
4093     ngx_str_t         err, *value;
4094     ngx_uint_t        i;
4095     ngx_regex_elt_t  *re;
4096     u_char            errstr[NGX_MAX_CONF_ERRSTR];
4097
4098     if (clcf->gzip_disable == NGX_CONF_UNSET_PTR) {
4099         clcf->gzip_disable = ngx_array_create(cf->pool, 2,
4100                                               sizeof(ngx_regex_elt_t));
4101         if (clcf->gzip_disable == NULL) {
4102             return NGX_CONF_ERROR;
4103         }
4104     }
4105
4106     value = cf->args->elts;
4107
4108     err.len = NGX_MAX_CONF_ERRSTR;
4109     err.data = errstr;
4110
4111     for (i = 1; i < cf->args->nelts; i++) {
4112
4113         if (ngx_strcmp(value[1].data, "msie6") == 0) {
4114             clcf->gzip_disable_msie6 = 1;
4115             continue;
4116         }
4117
4118         re = ngx_array_push(clcf->gzip_disable);
4119         if (re == NULL) {
4120             return NGX_CONF_ERROR;
4121         }
4122
4123         re->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool,
4124                                       &err);
4125
4126         if (re->regex == NULL) {
4127             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
4128             return NGX_CONF_ERROR;
4129         }
4130
4131         re->name = value[i].data;
4132     }
4133
4134     return NGX_CONF_OK;
4135
4136 #else
4137     ngx_str_t  *value;
4138
4139     value = cf->args->elts;
4140
4141     if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) {
4142         clcf->gzip_disable_msie6 = 1;
4143         return NGX_CONF_OK;
4144     }
4145
4146     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4147                        "without PCRE library \"gzip_disable\" supports "
4148                        "builtin \"msie6\" mask only");
4149
4150     return NGX_CONF_ERROR;
4151 #endif
4152 }
4153
4154 #endif
4155
4156
4157 static char *
4158 ngx_http_core_lowat_check(ngx_conf_t *cf, void *post, void *data)
4159 {
4160 #if (NGX_FREEBSD)
4161     ssize_t *np = data;
4162
4163     if ((u_long) *np >= ngx_freebsd_net_inet_tcp_sendspace) {
4164         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4165                            "\"send_lowat\" must be less than %d "
4166                            "(sysctl net.inet.tcp.sendspace)",
4167                            ngx_freebsd_net_inet_tcp_sendspace);
4168
4169         return NGX_CONF_ERROR;
4170     }
4171
4172 #elif !(NGX_HAVE_SO_SNDLOWAT)
4173     ssize_t *np = data;
4174
4175     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
4176                        "\"send_lowat\" is not supported, ignored");
4177
4178     *np = 0;
4179
4180 #endif
4181
4182     return NGX_CONF_OK;
4183 }
4184
4185
4186 static char *
4187 ngx_http_core_pool_size(ngx_conf_t *cf, void *post, void *data)
4188 {
4189     size_t *sp = data;
4190
4191     if (*sp < NGX_MIN_POOL_SIZE) {
4192         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
4193                            "pool must be no less than %uz", NGX_MIN_POOL_SIZE);
4194
4195         return NGX_CONF_ERROR;
4196     }
4197
4198     return NGX_CONF_OK;
4199 }