upstream nginx-0.7.35
[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
1781     /* AF_INET only */
1782
1783     c = r->connection;
1784
1785     if (r->in_addr == 0) {
1786         len = sizeof(struct sockaddr_in);
1787         if (getsockname(c->fd, (struct sockaddr *) &sin, &len) == -1) {
1788             ngx_connection_error(c, ngx_socket_errno, "getsockname() failed");
1789             return NGX_ERROR;
1790         }
1791
1792         r->in_addr = sin.sin_addr.s_addr;
1793
1794     } else {
1795         sin.sin_family = c->sockaddr->sa_family;
1796         sin.sin_addr.s_addr = r->in_addr;
1797     }
1798
1799     if (s == NULL) {
1800         return NGX_OK;
1801     }
1802
1803     s->len = ngx_sock_ntop((struct sockaddr *) &sin, s->data,
1804                            NGX_INET_ADDRSTRLEN);
1805
1806     return NGX_OK;
1807 }
1808
1809
1810 #if (NGX_HTTP_GZIP)
1811
1812 ngx_int_t
1813 ngx_http_gzip_ok(ngx_http_request_t *r)
1814 {
1815     time_t                     date, expires;
1816     ngx_uint_t                 p;
1817     ngx_array_t               *cc;
1818     ngx_table_elt_t           *e, *d;
1819     ngx_http_core_loc_conf_t  *clcf;
1820
1821     if (r->gzip == 1) {
1822         return NGX_OK;
1823     }
1824
1825     if (r->gzip == 2) {
1826         return NGX_DECLINED;
1827     }
1828
1829     r->gzip = 2;
1830
1831     if (r != r->main
1832         || r->headers_in.accept_encoding == NULL
1833         || ngx_strcasestrn(r->headers_in.accept_encoding->value.data,
1834                            "gzip", 4 - 1)
1835            == NULL
1836
1837         /*
1838          * if the URL (without the "http://" prefix) is longer than 253 bytes,
1839          * then MSIE 4.x can not handle the compressed stream - it waits
1840          * too long, hangs up or crashes
1841          */
1842
1843         || (r->headers_in.msie4 && r->unparsed_uri.len > 200))
1844     {
1845         return NGX_DECLINED;
1846     }
1847
1848     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
1849
1850     if (r->headers_in.msie6 && clcf->gzip_disable_msie6) {
1851         return NGX_DECLINED;
1852     }
1853
1854     if (r->http_version < clcf->gzip_http_version) {
1855         return NGX_DECLINED;
1856     }
1857
1858     if (r->headers_in.via == NULL) {
1859         goto ok;
1860     }
1861
1862     p = clcf->gzip_proxied;
1863
1864     if (p & NGX_HTTP_GZIP_PROXIED_OFF) {
1865         return NGX_DECLINED;
1866     }
1867
1868     if (p & NGX_HTTP_GZIP_PROXIED_ANY) {
1869         goto ok;
1870     }
1871
1872     if (r->headers_in.authorization && (p & NGX_HTTP_GZIP_PROXIED_AUTH)) {
1873         goto ok;
1874     }
1875
1876     e = r->headers_out.expires;
1877
1878     if (e) {
1879
1880         if (!(p & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
1881             return NGX_DECLINED;
1882         }
1883
1884         expires = ngx_http_parse_time(e->value.data, e->value.len);
1885         if (expires == NGX_ERROR) {
1886             return NGX_DECLINED;
1887         }
1888
1889         d = r->headers_out.date;
1890
1891         if (d) {
1892             date = ngx_http_parse_time(d->value.data, d->value.len);
1893             if (date == NGX_ERROR) {
1894                 return NGX_DECLINED;
1895             }
1896
1897         } else {
1898             date = ngx_time();
1899         }
1900
1901         if (expires < date) {
1902             goto ok;
1903         }
1904
1905         return NGX_DECLINED;
1906     }
1907
1908     cc = &r->headers_out.cache_control;
1909
1910     if (cc->elts) {
1911
1912         if ((p & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
1913             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_cache,
1914                                                  NULL)
1915                >= 0)
1916         {
1917             goto ok;
1918         }
1919
1920         if ((p & NGX_HTTP_GZIP_PROXIED_NO_STORE)
1921             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_no_store,
1922                                                  NULL)
1923                >= 0)
1924         {
1925             goto ok;
1926         }
1927
1928         if ((p & NGX_HTTP_GZIP_PROXIED_PRIVATE)
1929             && ngx_http_parse_multi_header_lines(cc, &ngx_http_gzip_private,
1930                                                  NULL)
1931                >= 0)
1932         {
1933             goto ok;
1934         }
1935
1936         return NGX_DECLINED;
1937     }
1938
1939     if ((p & NGX_HTTP_GZIP_PROXIED_NO_LM) && r->headers_out.last_modified) {
1940         return NGX_DECLINED;
1941     }
1942
1943     if ((p & NGX_HTTP_GZIP_PROXIED_NO_ETAG) && r->headers_out.etag) {
1944         return NGX_DECLINED;
1945     }
1946
1947 ok:
1948
1949 #if (NGX_PCRE)
1950
1951     if (clcf->gzip_disable && r->headers_in.user_agent) {
1952
1953         if (ngx_regex_exec_array(clcf->gzip_disable,
1954                                  &r->headers_in.user_agent->value,
1955                                  r->connection->log)
1956             != NGX_DECLINED)
1957         {
1958             return NGX_DECLINED;
1959         }
1960     }
1961
1962 #endif
1963
1964     r->gzip = 1;
1965
1966     return NGX_OK;
1967 }
1968
1969 #endif
1970
1971
1972 ngx_int_t
1973 ngx_http_subrequest(ngx_http_request_t *r,
1974     ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr,
1975     ngx_http_post_subrequest_t *ps, ngx_uint_t flags)
1976 {
1977     ngx_connection_t              *c;
1978     ngx_http_request_t            *sr;
1979     ngx_http_core_srv_conf_t      *cscf;
1980     ngx_http_postponed_request_t  *pr, *p;
1981
1982     r->main->subrequests--;
1983
1984     if (r->main->subrequests == 0) {
1985         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
1986                       "subrequests cycle while processing \"%V\"", uri);
1987         r->main->subrequests = 1;
1988         return NGX_ERROR;
1989     }
1990
1991     sr = ngx_pcalloc(r->pool, sizeof(ngx_http_request_t));
1992     if (sr == NULL) {
1993         return NGX_ERROR;
1994     }
1995
1996     sr->signature = NGX_HTTP_MODULE;
1997
1998     c = r->connection;
1999     sr->connection = c;
2000
2001     sr->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module);
2002     if (sr->ctx == NULL) {
2003         return NGX_ERROR;
2004     }
2005
2006     if (ngx_list_init(&sr->headers_out.headers, r->pool, 20,
2007                       sizeof(ngx_table_elt_t))
2008         == NGX_ERROR)
2009     {
2010         return NGX_ERROR;
2011     }
2012
2013     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2014     sr->main_conf = cscf->ctx->main_conf;
2015     sr->srv_conf = cscf->ctx->srv_conf;
2016     sr->loc_conf = cscf->ctx->loc_conf;
2017
2018     sr->pool = r->pool;
2019
2020     sr->headers_in = r->headers_in;
2021
2022     ngx_http_clear_content_length(sr);
2023     ngx_http_clear_accept_ranges(sr);
2024     ngx_http_clear_last_modified(sr);
2025
2026     sr->request_body = r->request_body;
2027
2028     sr->method = NGX_HTTP_GET;
2029     sr->http_version = r->http_version;
2030
2031     sr->request_line = r->request_line;
2032     sr->uri = *uri;
2033
2034     if (args) {
2035         sr->args = *args;
2036     }
2037
2038     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
2039                    "http subrequest \"%V?%V\"", uri, &sr->args);
2040
2041     sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
2042     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
2043     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
2044
2045     sr->unparsed_uri = r->unparsed_uri;
2046     sr->method_name = ngx_http_core_get_method;
2047     sr->http_protocol = r->http_protocol;
2048
2049     if (ngx_http_set_exten(sr) != NGX_OK) {
2050         return NGX_ERROR;
2051     }
2052
2053     sr->main = r->main;
2054     sr->parent = r;
2055     sr->post_subrequest = ps;
2056     sr->read_event_handler = ngx_http_request_empty_handler;
2057     sr->write_event_handler = ngx_http_handler;
2058
2059     if (c->data == r && r->postponed == NULL) {
2060         c->data = sr;
2061     }
2062
2063     sr->in_addr = r->in_addr;
2064     sr->port = r->port;
2065     sr->port_text = r->port_text;
2066
2067     sr->variables = r->variables;
2068
2069     sr->log_handler = r->log_handler;
2070
2071     pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
2072     if (pr == NULL) {
2073         return NGX_ERROR;
2074     }
2075
2076     pr->request = sr;
2077     pr->out = NULL;
2078     pr->next = NULL;
2079
2080     if (r->postponed) {
2081         for (p = r->postponed; p->next; p = p->next) { /* void */ }
2082         p->next = pr;
2083
2084     } else {
2085         r->postponed = pr;
2086     }
2087
2088     sr->internal = 1;
2089
2090     sr->discard_body = r->discard_body;
2091     sr->expect_tested = 1;
2092     sr->main_filter_need_in_memory = r->main_filter_need_in_memory;
2093
2094     sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1;
2095
2096     r->main->subrequests++;
2097
2098     *psr = sr;
2099
2100     return ngx_http_post_request(sr);
2101 }
2102
2103
2104 ngx_int_t
2105 ngx_http_internal_redirect(ngx_http_request_t *r,
2106     ngx_str_t *uri, ngx_str_t *args)
2107 {
2108     ngx_http_core_srv_conf_t  *cscf;
2109
2110     r->uri_changes--;
2111
2112     if (r->uri_changes == 0) {
2113         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2114                       "rewrite or internal redirection cycle "
2115                       "while internal redirect to \"%V\"", uri);
2116
2117         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2118         return NGX_DONE;
2119     }
2120
2121     r->uri = *uri;
2122
2123     if (args) {
2124         r->args = *args;
2125
2126     } else {
2127         r->args.len = 0;
2128         r->args.data = NULL;
2129     }
2130
2131     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2132                    "internal redirect: \"%V?%V\"", uri, &r->args);
2133
2134     if (ngx_http_set_exten(r) != NGX_OK) {
2135         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2136         return NGX_DONE;
2137     }
2138
2139     /* clear the modules contexts */
2140     ngx_memzero(r->ctx, sizeof(void *) * ngx_http_max_module);
2141
2142     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2143     r->loc_conf = cscf->ctx->loc_conf;
2144
2145     ngx_http_update_location_config(r);
2146
2147     r->internal = 1;
2148
2149     ngx_http_handler(r);
2150
2151     return NGX_DONE;
2152 }
2153
2154
2155 ngx_int_t
2156 ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
2157 {
2158     ngx_http_core_srv_conf_t    *cscf;
2159     ngx_http_core_loc_conf_t   **clcfp;
2160     ngx_http_core_main_conf_t   *cmcf;
2161
2162     cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
2163
2164     if (cscf->named_locations) {
2165
2166         for (clcfp = cscf->named_locations; *clcfp; clcfp++) {
2167
2168             ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2169                            "test location: \"%V\"", &(*clcfp)->name);
2170
2171             if (name->len != (*clcfp)->name.len
2172                 || ngx_strncmp(name->data, (*clcfp)->name.data, name->len) != 0)
2173             {
2174                 continue;
2175             }
2176
2177             ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2178                            "using location: %V \"%V?%V\"",
2179                            name, &r->uri, &r->args);
2180
2181             r->internal = 1;
2182             r->content_handler = NULL;
2183             r->loc_conf = (*clcfp)->loc_conf;
2184
2185             ngx_http_update_location_config(r);
2186
2187             cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
2188
2189             r->phase_handler = cmcf->phase_engine.location_rewrite_index;
2190
2191             ngx_http_core_run_phases(r);
2192
2193             return NGX_DONE;
2194         }
2195     }
2196
2197     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
2198                   "could not find named location \"%V\"", name);
2199
2200     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
2201
2202     return NGX_DONE;
2203 }
2204
2205
2206 ngx_http_cleanup_t *
2207 ngx_http_cleanup_add(ngx_http_request_t *r, size_t size)
2208 {
2209     ngx_http_cleanup_t  *cln;
2210
2211     r = r->main;
2212
2213     cln = ngx_palloc(r->pool, sizeof(ngx_http_cleanup_t));
2214     if (cln == NULL) {
2215         return NULL;
2216     }
2217
2218     if (size) {
2219         cln->data = ngx_palloc(r->pool, size);
2220         if (cln->data == NULL) {
2221             return NULL;
2222         }
2223
2224     } else {
2225         cln->data = NULL;
2226     }
2227
2228     cln->handler = NULL;
2229     cln->next = r->cleanup;
2230
2231     r->cleanup = cln;
2232
2233     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
2234                    "http cleanup add: %p", cln);
2235
2236     return cln;
2237 }
2238
2239
2240 static char *
2241 ngx_http_core_server(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2242 {
2243     char                        *rv;
2244     void                        *mconf;
2245     ngx_uint_t                   i;
2246     ngx_conf_t                   pcf;
2247     ngx_http_module_t           *module;
2248     ngx_http_conf_ctx_t         *ctx, *http_ctx;
2249     ngx_http_core_srv_conf_t    *cscf, **cscfp;
2250     ngx_http_core_main_conf_t   *cmcf;
2251
2252     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2253     if (ctx == NULL) {
2254         return NGX_CONF_ERROR;
2255     }
2256
2257     http_ctx = cf->ctx;
2258     ctx->main_conf = http_ctx->main_conf;
2259
2260     /* the server{}'s srv_conf */
2261
2262     ctx->srv_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2263     if (ctx->srv_conf == NULL) {
2264         return NGX_CONF_ERROR;
2265     }
2266
2267     /* the server{}'s loc_conf */
2268
2269     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2270     if (ctx->loc_conf == NULL) {
2271         return NGX_CONF_ERROR;
2272     }
2273
2274     for (i = 0; ngx_modules[i]; i++) {
2275         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2276             continue;
2277         }
2278
2279         module = ngx_modules[i]->ctx;
2280
2281         if (module->create_srv_conf) {
2282             mconf = module->create_srv_conf(cf);
2283             if (mconf == NULL) {
2284                 return NGX_CONF_ERROR;
2285             }
2286
2287             ctx->srv_conf[ngx_modules[i]->ctx_index] = mconf;
2288         }
2289
2290         if (module->create_loc_conf) {
2291             mconf = module->create_loc_conf(cf);
2292             if (mconf == NULL) {
2293                 return NGX_CONF_ERROR;
2294             }
2295
2296             ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
2297         }
2298     }
2299
2300
2301     /* the server configuration context */
2302
2303     cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
2304     cscf->ctx = ctx;
2305
2306
2307     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
2308
2309     cscfp = ngx_array_push(&cmcf->servers);
2310     if (cscfp == NULL) {
2311         return NGX_CONF_ERROR;
2312     }
2313
2314     *cscfp = cscf;
2315
2316
2317     /* parse inside server{} */
2318
2319     pcf = *cf;
2320     cf->ctx = ctx;
2321     cf->cmd_type = NGX_HTTP_SRV_CONF;
2322
2323     rv = ngx_conf_parse(cf, NULL);
2324
2325     *cf = pcf;
2326
2327     return rv;
2328 }
2329
2330
2331 static char *
2332 ngx_http_core_location(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy)
2333 {
2334     char                      *rv;
2335     u_char                    *mod;
2336     size_t                     len;
2337     ngx_str_t                 *value, *name;
2338     ngx_uint_t                 i;
2339     ngx_conf_t                 save;
2340     ngx_http_module_t         *module;
2341     ngx_http_conf_ctx_t       *ctx, *pctx;
2342     ngx_http_core_loc_conf_t  *clcf, *pclcf;
2343
2344     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
2345     if (ctx == NULL) {
2346         return NGX_CONF_ERROR;
2347     }
2348
2349     pctx = cf->ctx;
2350     ctx->main_conf = pctx->main_conf;
2351     ctx->srv_conf = pctx->srv_conf;
2352
2353     ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
2354     if (ctx->loc_conf == NULL) {
2355         return NGX_CONF_ERROR;
2356     }
2357
2358     for (i = 0; ngx_modules[i]; i++) {
2359         if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
2360             continue;
2361         }
2362
2363         module = ngx_modules[i]->ctx;
2364
2365         if (module->create_loc_conf) {
2366             ctx->loc_conf[ngx_modules[i]->ctx_index] =
2367                                                    module->create_loc_conf(cf);
2368             if (ctx->loc_conf[ngx_modules[i]->ctx_index] == NULL) {
2369                  return NGX_CONF_ERROR;
2370             }
2371         }
2372     }
2373
2374     clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
2375     clcf->loc_conf = ctx->loc_conf;
2376
2377     value = cf->args->elts;
2378
2379     if (cf->args->nelts == 3) {
2380
2381         len = value[1].len;
2382         mod = value[1].data;
2383         name = &value[2];
2384
2385         if (len == 1 && mod[0] == '=') {
2386
2387             clcf->name = *name;
2388             clcf->exact_match = 1;
2389
2390         } else if (len == 2 && mod[0] == '^' && mod[1] == '~') {
2391
2392             clcf->name = *name;
2393             clcf->noregex = 1;
2394
2395         } else if (len == 1 && mod[0] == '~') {
2396
2397             if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2398                 return NGX_CONF_ERROR;
2399             }
2400
2401         } else if (len == 2 && mod[0] == '~' && mod[1] == '*') {
2402
2403             if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2404                 return NGX_CONF_ERROR;
2405             }
2406
2407         } else {
2408             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2409                                "invalid location modifier \"%V\"", &value[1]);
2410             return NGX_CONF_ERROR;
2411         }
2412
2413     } else {
2414
2415         name = &value[1];
2416
2417         if (name->data[0] == '=') {
2418
2419             clcf->name.len = name->len - 1;
2420             clcf->name.data = name->data + 1;
2421             clcf->exact_match = 1;
2422
2423         } else if (name->data[0] == '^' && name->data[1] == '~') {
2424
2425             clcf->name.len = name->len - 2;
2426             clcf->name.data = name->data + 2;
2427             clcf->noregex = 1;
2428
2429         } else if (name->data[0] == '~') {
2430
2431             name->len--;
2432             name->data++;
2433
2434             if (name->data[0] == '*') {
2435
2436                 name->len--;
2437                 name->data++;
2438
2439                 if (ngx_http_core_regex_location(cf, clcf, name, 1) != NGX_OK) {
2440                     return NGX_CONF_ERROR;
2441                 }
2442
2443             } else {
2444                 if (ngx_http_core_regex_location(cf, clcf, name, 0) != NGX_OK) {
2445                     return NGX_CONF_ERROR;
2446                 }
2447             }
2448
2449         } else {
2450
2451             clcf->name = *name;
2452
2453             if (name->data[0] == '@') {
2454                 clcf->named = 1;
2455             }
2456         }
2457     }
2458
2459     pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
2460
2461     if (pclcf->name.len) {
2462
2463         /* nested location */
2464
2465 #if 0
2466         clcf->prev_location = pclcf;
2467 #endif
2468
2469         if (pclcf->exact_match) {
2470             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2471                                "location \"%V\" could not be inside "
2472                                "the exact location \"%V\"",
2473                                &clcf->name, &pclcf->name);
2474             return NGX_CONF_ERROR;
2475         }
2476
2477         if (pclcf->named) {
2478             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2479                                "location \"%V\" could not be inside "
2480                                "the named location \"%V\"",
2481                                &clcf->name, &pclcf->name);
2482             return NGX_CONF_ERROR;
2483         }
2484
2485         if (clcf->named) {
2486             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2487                                "named location \"%V\" must be "
2488                                "on server level only",
2489                                &clcf->name);
2490             return NGX_CONF_ERROR;
2491         }
2492
2493         len = pclcf->name.len;
2494
2495 #if (NGX_PCRE)
2496         if (clcf->regex == NULL
2497             && ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2498 #else
2499         if (ngx_strncmp(clcf->name.data, pclcf->name.data, len) != 0)
2500 #endif
2501         {
2502             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2503                                "location \"%V\" is outside location \"%V\"",
2504                                &clcf->name, &pclcf->name);
2505             return NGX_CONF_ERROR;
2506         }
2507     }
2508
2509     if (ngx_http_add_location(cf, &pclcf->locations, clcf) != NGX_OK) {
2510         return NGX_CONF_ERROR;
2511     }
2512
2513     save = *cf;
2514     cf->ctx = ctx;
2515     cf->cmd_type = NGX_HTTP_LOC_CONF;
2516
2517     rv = ngx_conf_parse(cf, NULL);
2518
2519     *cf = save;
2520
2521     return rv;
2522 }
2523
2524
2525 static ngx_int_t
2526 ngx_http_core_regex_location(ngx_conf_t *cf, ngx_http_core_loc_conf_t *clcf,
2527     ngx_str_t *regex, ngx_uint_t caseless)
2528 {
2529 #if (NGX_PCRE)
2530     ngx_str_t  err;
2531     u_char     errstr[NGX_MAX_CONF_ERRSTR];
2532
2533     err.len = NGX_MAX_CONF_ERRSTR;
2534     err.data = errstr;
2535
2536     clcf->regex = ngx_regex_compile(regex, caseless ? NGX_REGEX_CASELESS: 0,
2537                                     cf->pool, &err);
2538
2539     if (clcf->regex == NULL) {
2540         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
2541         return NGX_ERROR;
2542     }
2543
2544     clcf->name = *regex;
2545
2546     return NGX_OK;
2547
2548 #else
2549
2550     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2551                        "the using of the regex \"%V\" requires PCRE library",
2552                        regex);
2553     return NGX_ERROR;
2554
2555 #endif
2556 }
2557
2558
2559 static char *
2560 ngx_http_core_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
2561 {
2562     ngx_http_core_loc_conf_t *lcf = conf;
2563
2564     char        *rv;
2565     ngx_conf_t   save;
2566
2567     if (lcf->types == NULL) {
2568         lcf->types = ngx_array_create(cf->pool, 64, sizeof(ngx_hash_key_t));
2569         if (lcf->types == NULL) {
2570             return NGX_CONF_ERROR;
2571         }
2572     }
2573
2574     save = *cf;
2575     cf->handler = ngx_http_core_type;
2576     cf->handler_conf = conf;
2577
2578     rv = ngx_conf_parse(cf, NULL);
2579
2580     *cf = save;
2581
2582     return rv;
2583 }
2584
2585
2586 static char *
2587 ngx_http_core_type(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
2588 {
2589     ngx_http_core_loc_conf_t *lcf = conf;
2590
2591     ngx_str_t       *value, *content_type, *old, file;
2592     ngx_uint_t       i, n, hash;
2593     ngx_hash_key_t  *type;
2594
2595     value = cf->args->elts;
2596
2597     if (ngx_strcmp(value[0].data, "include") == 0) {
2598         file = value[1];
2599
2600         if (ngx_conf_full_name(cf->cycle, &file, 1) == NGX_ERROR){
2601             return NGX_CONF_ERROR;
2602         }
2603
2604         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cf->log, 0, "include %s", file.data);
2605
2606         return ngx_conf_parse(cf, &file);
2607     }
2608
2609     content_type = ngx_palloc(cf->pool, sizeof(ngx_str_t));
2610     if (content_type == NULL) {
2611         return NGX_CONF_ERROR;
2612     }
2613
2614     *content_type = value[0];
2615
2616     for (i = 1; i < cf->args->nelts; i++) {
2617
2618         hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
2619
2620         type = lcf->types->elts;
2621         for (n = 0; n < lcf->types->nelts; n++) {
2622             if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
2623                 old = type[n].value;
2624                 type[n].value = content_type;
2625
2626                 ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
2627                                    "duplicate extention \"%V\", "
2628                                    "content type: \"%V\", "
2629                                    "old content type: \"%V\"",
2630                                    &value[i], content_type, old);
2631                 continue;
2632             }
2633         }
2634
2635
2636         type = ngx_array_push(lcf->types);
2637         if (type == NULL) {
2638             return NGX_CONF_ERROR;
2639         }
2640
2641         type->key = value[i];
2642         type->key_hash = hash;
2643         type->value = content_type;
2644     }
2645
2646     return NGX_CONF_OK;
2647 }
2648
2649
2650 static ngx_int_t
2651 ngx_http_core_preconfiguration(ngx_conf_t *cf)
2652 {
2653     return ngx_http_variables_add_core_vars(cf);
2654 }
2655
2656
2657 static void *
2658 ngx_http_core_create_main_conf(ngx_conf_t *cf)
2659 {
2660     ngx_http_core_main_conf_t  *cmcf;
2661
2662     cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
2663     if (cmcf == NULL) {
2664         return NGX_CONF_ERROR;
2665     }
2666
2667     if (ngx_array_init(&cmcf->servers, cf->pool, 4,
2668                        sizeof(ngx_http_core_srv_conf_t *))
2669         != NGX_OK)
2670     {
2671         return NGX_CONF_ERROR;
2672     }
2673
2674     cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT;
2675     cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT;
2676
2677     cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT;
2678     cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT;
2679
2680     return cmcf;
2681 }
2682
2683
2684 static char *
2685 ngx_http_core_init_main_conf(ngx_conf_t *cf, void *conf)
2686 {
2687     ngx_http_core_main_conf_t *cmcf = conf;
2688
2689     if (cmcf->server_names_hash_max_size == NGX_CONF_UNSET_UINT) {
2690         cmcf->server_names_hash_max_size = 512;
2691     }
2692
2693     if (cmcf->server_names_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2694         cmcf->server_names_hash_bucket_size = ngx_cacheline_size;
2695     }
2696
2697     cmcf->server_names_hash_bucket_size =
2698             ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size);
2699
2700
2701     if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) {
2702         cmcf->variables_hash_max_size = 512;
2703     }
2704
2705     if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) {
2706         cmcf->variables_hash_bucket_size = 64;
2707     }
2708
2709     cmcf->variables_hash_bucket_size =
2710                ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);
2711
2712     return NGX_CONF_OK;
2713 }
2714
2715
2716 static void *
2717 ngx_http_core_create_srv_conf(ngx_conf_t *cf)
2718 {
2719     ngx_http_core_srv_conf_t  *cscf;
2720
2721     cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
2722     if (cscf == NULL) {
2723         return NGX_CONF_ERROR;
2724     }
2725
2726     /*
2727      * set by ngx_pcalloc():
2728      *
2729      *     conf->client_large_buffers.num = 0;
2730      */
2731
2732     if (ngx_array_init(&cscf->listen, cf->pool, 4, sizeof(ngx_http_listen_t))
2733         == NGX_ERROR)
2734     {
2735         return NGX_CONF_ERROR;
2736     }
2737
2738     if (ngx_array_init(&cscf->server_names, cf->temp_pool, 4,
2739                        sizeof(ngx_http_server_name_t))
2740         == NGX_ERROR)
2741     {
2742         return NGX_CONF_ERROR;
2743     }
2744
2745     cscf->connection_pool_size = NGX_CONF_UNSET_SIZE;
2746     cscf->request_pool_size = NGX_CONF_UNSET_SIZE;
2747     cscf->client_header_timeout = NGX_CONF_UNSET_MSEC;
2748     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
2749     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
2750     cscf->merge_slashes = NGX_CONF_UNSET;
2751     cscf->underscores_in_headers = NGX_CONF_UNSET;
2752
2753     return cscf;
2754 }
2755
2756
2757 static char *
2758 ngx_http_core_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
2759 {
2760     ngx_http_core_srv_conf_t *prev = parent;
2761     ngx_http_core_srv_conf_t *conf = child;
2762
2763     ngx_http_listen_t       *ls;
2764     ngx_http_server_name_t  *sn;
2765
2766     /* TODO: it does not merge, it inits only */
2767
2768     if (conf->listen.nelts == 0) {
2769         ls = ngx_array_push(&conf->listen);
2770         if (ls == NULL) {
2771             return NGX_CONF_ERROR;
2772         }
2773
2774         ngx_memzero(ls, sizeof(ngx_http_listen_t));
2775
2776         ls->addr = INADDR_ANY;
2777 #if (NGX_WIN32)
2778         ls->port = 80;
2779 #else
2780         /* STUB: getuid() should be cached */
2781         ls->port = (getuid() == 0) ? 80 : 8000;
2782 #endif
2783         ls->family = AF_INET;
2784
2785         ls->conf.backlog = NGX_LISTEN_BACKLOG;
2786         ls->conf.rcvbuf = -1;
2787         ls->conf.sndbuf = -1;
2788     }
2789
2790     if (conf->server_name.data == NULL) {
2791         conf->server_name = cf->cycle->hostname;
2792
2793         sn = ngx_array_push(&conf->server_names);
2794         if (sn == NULL) {
2795             return NGX_CONF_ERROR;
2796         }
2797
2798 #if (NGX_PCRE)
2799         sn->regex = NULL;
2800 #endif
2801         sn->core_srv_conf = conf;
2802         sn->name.len = conf->server_name.len;
2803         sn->name.data = conf->server_name.data;
2804     }
2805
2806     ngx_conf_merge_size_value(conf->connection_pool_size,
2807                               prev->connection_pool_size, 256);
2808     ngx_conf_merge_size_value(conf->request_pool_size,
2809                               prev->request_pool_size, 4096);
2810     ngx_conf_merge_msec_value(conf->client_header_timeout,
2811                               prev->client_header_timeout, 60000);
2812     ngx_conf_merge_size_value(conf->client_header_buffer_size,
2813                               prev->client_header_buffer_size, 1024);
2814     ngx_conf_merge_bufs_value(conf->large_client_header_buffers,
2815                               prev->large_client_header_buffers,
2816                               4, ngx_pagesize);
2817
2818     if (conf->large_client_header_buffers.size < conf->connection_pool_size) {
2819         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
2820                            "the \"large_client_header_buffers\" size must be "
2821                            "equal to or bigger than \"connection_pool_size\"");
2822         return NGX_CONF_ERROR;
2823     }
2824
2825     ngx_conf_merge_value(conf->ignore_invalid_headers,
2826                               prev->ignore_invalid_headers, 1);
2827
2828     ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
2829
2830     ngx_conf_merge_value(conf->underscores_in_headers,
2831                               prev->underscores_in_headers, 0);
2832
2833     return NGX_CONF_OK;
2834 }
2835
2836
2837 static void *
2838 ngx_http_core_create_loc_conf(ngx_conf_t *cf)
2839 {
2840     ngx_http_core_loc_conf_t  *lcf;
2841
2842     lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
2843     if (lcf == NULL) {
2844         return NGX_CONF_ERROR;
2845     }
2846
2847     /*
2848      * set by ngx_pcalloc():
2849      *
2850      *     lcf->root = { 0, NULL };
2851      *     lcf->limit_except = 0;
2852      *     lcf->post_action = { 0, NULL };
2853      *     lcf->types = NULL;
2854      *     lcf->default_type = { 0, NULL };
2855      *     lcf->err_log = NULL;
2856      *     lcf->error_pages = NULL;
2857      *     lcf->try_files = NULL;
2858      *     lcf->client_body_path = NULL;
2859      *     lcf->regex = NULL;
2860      *     lcf->exact_match = 0;
2861      *     lcf->auto_redirect = 0;
2862      *     lcf->alias = 0;
2863      *     lcf->gzip_proxied = 0;
2864      */
2865
2866     lcf->client_max_body_size = NGX_CONF_UNSET;
2867     lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE;
2868     lcf->client_body_timeout = NGX_CONF_UNSET_MSEC;
2869     lcf->satisfy = NGX_CONF_UNSET_UINT;
2870     lcf->if_modified_since = NGX_CONF_UNSET_UINT;
2871     lcf->internal = NGX_CONF_UNSET;
2872     lcf->client_body_in_file_only = NGX_CONF_UNSET;
2873     lcf->sendfile = NGX_CONF_UNSET;
2874     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
2875     lcf->directio = NGX_CONF_UNSET;
2876     lcf->tcp_nopush = NGX_CONF_UNSET;
2877     lcf->tcp_nodelay = NGX_CONF_UNSET;
2878     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
2879     lcf->send_lowat = NGX_CONF_UNSET_SIZE;
2880     lcf->postpone_output = NGX_CONF_UNSET_SIZE;
2881     lcf->limit_rate = NGX_CONF_UNSET_SIZE;
2882     lcf->keepalive_timeout = NGX_CONF_UNSET_MSEC;
2883     lcf->keepalive_header = NGX_CONF_UNSET;
2884     lcf->lingering_time = NGX_CONF_UNSET_MSEC;
2885     lcf->lingering_timeout = NGX_CONF_UNSET_MSEC;
2886     lcf->resolver_timeout = NGX_CONF_UNSET_MSEC;
2887     lcf->reset_timedout_connection = NGX_CONF_UNSET;
2888     lcf->server_name_in_redirect = NGX_CONF_UNSET;
2889     lcf->port_in_redirect = NGX_CONF_UNSET;
2890     lcf->msie_padding = NGX_CONF_UNSET;
2891     lcf->msie_refresh = NGX_CONF_UNSET;
2892     lcf->log_not_found = NGX_CONF_UNSET;
2893     lcf->log_subrequest = NGX_CONF_UNSET;
2894     lcf->recursive_error_pages = NGX_CONF_UNSET;
2895     lcf->server_tokens = NGX_CONF_UNSET;
2896     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
2897     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
2898
2899     lcf->open_file_cache = NGX_CONF_UNSET_PTR;
2900     lcf->open_file_cache_valid = NGX_CONF_UNSET;
2901     lcf->open_file_cache_min_uses = NGX_CONF_UNSET_UINT;
2902     lcf->open_file_cache_errors = NGX_CONF_UNSET;
2903     lcf->open_file_cache_events = NGX_CONF_UNSET;
2904
2905 #if (NGX_HTTP_GZIP)
2906     lcf->gzip_vary = NGX_CONF_UNSET;
2907     lcf->gzip_http_version = NGX_CONF_UNSET_UINT;
2908 #if (NGX_PCRE)
2909     lcf->gzip_disable = NGX_CONF_UNSET_PTR;
2910     lcf->gzip_disable_msie6 = 3;
2911 #endif
2912 #endif
2913
2914     return lcf;
2915 }
2916
2917
2918 static ngx_str_t  ngx_http_core_text_html_type = ngx_string("text/html");
2919 static ngx_str_t  ngx_http_core_image_gif_type = ngx_string("image/gif");
2920 static ngx_str_t  ngx_http_core_image_jpeg_type = ngx_string("image/jpeg");
2921
2922 static ngx_hash_key_t  ngx_http_core_default_types[] = {
2923     { ngx_string("html"), 0, &ngx_http_core_text_html_type },
2924     { ngx_string("gif"), 0, &ngx_http_core_image_gif_type },
2925     { ngx_string("jpg"), 0, &ngx_http_core_image_jpeg_type },
2926     { ngx_null_string, 0, NULL }
2927 };
2928
2929
2930 static char *
2931 ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
2932 {
2933     ngx_http_core_loc_conf_t *prev = parent;
2934     ngx_http_core_loc_conf_t *conf = child;
2935
2936     ngx_uint_t        i;
2937     ngx_hash_key_t   *type;
2938     ngx_hash_init_t   types_hash;
2939
2940     if (conf->root.data == NULL) {
2941
2942         conf->alias = prev->alias;
2943         conf->root = prev->root;
2944         conf->root_lengths = prev->root_lengths;
2945         conf->root_values = prev->root_values;
2946
2947         if (prev->root.data == NULL) {
2948             conf->root.len = sizeof("html") - 1;
2949             conf->root.data = (u_char *) "html";
2950
2951             if (ngx_conf_full_name(cf->cycle, &conf->root, 0) == NGX_ERROR) {
2952                 return NGX_CONF_ERROR;
2953             }
2954         }
2955     }
2956
2957     if (conf->post_action.data == NULL) {
2958         conf->post_action = prev->post_action;
2959     }
2960
2961     ngx_conf_merge_uint_value(conf->types_hash_max_size,
2962                               prev->types_hash_max_size, 1024);
2963
2964     ngx_conf_merge_uint_value(conf->types_hash_bucket_size,
2965                               prev->types_hash_bucket_size,
2966                               ngx_cacheline_size);
2967
2968     conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size,
2969                                              ngx_cacheline_size);
2970
2971     /*
2972      * the special handling the "types" directive in the "http" section
2973      * to inherit the http's conf->types_hash to all servers
2974      */
2975
2976     if (prev->types && prev->types_hash.buckets == NULL) {
2977
2978         types_hash.hash = &prev->types_hash;
2979         types_hash.key = ngx_hash_key_lc;
2980         types_hash.max_size = conf->types_hash_max_size;
2981         types_hash.bucket_size = conf->types_hash_bucket_size;
2982         types_hash.name = "types_hash";
2983         types_hash.pool = cf->pool;
2984         types_hash.temp_pool = NULL;
2985
2986         if (ngx_hash_init(&types_hash, prev->types->elts, prev->types->nelts)
2987             != NGX_OK)
2988         {
2989             return NGX_CONF_ERROR;
2990         }
2991     }
2992
2993     if (conf->types == NULL) {
2994         conf->types = prev->types;
2995         conf->types_hash = prev->types_hash;
2996     }
2997
2998     if (conf->types == NULL) {
2999         conf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_hash_key_t));
3000         if (conf->types == NULL) {
3001             return NGX_CONF_ERROR;
3002         }
3003
3004         for (i = 0; ngx_http_core_default_types[i].key.len; i++) {
3005             type = ngx_array_push(conf->types);
3006             if (type == NULL) {
3007                 return NGX_CONF_ERROR;
3008             }
3009
3010             type->key = ngx_http_core_default_types[i].key;
3011             type->key_hash =
3012                        ngx_hash_key_lc(ngx_http_core_default_types[i].key.data,
3013                                        ngx_http_core_default_types[i].key.len);
3014             type->value = ngx_http_core_default_types[i].value;
3015         }
3016     }
3017
3018     if (conf->types_hash.buckets == NULL) {
3019
3020         types_hash.hash = &conf->types_hash;
3021         types_hash.key = ngx_hash_key_lc;
3022         types_hash.max_size = conf->types_hash_max_size;
3023         types_hash.bucket_size = conf->types_hash_bucket_size;
3024         types_hash.name = "mime_types_hash";
3025         types_hash.pool = cf->pool;
3026         types_hash.temp_pool = NULL;
3027
3028         if (ngx_hash_init(&types_hash, conf->types->elts, conf->types->nelts)
3029             != NGX_OK)
3030         {
3031             return NGX_CONF_ERROR;
3032         }
3033     }
3034
3035     if (conf->err_log == NULL) {
3036         if (prev->err_log) {
3037             conf->err_log = prev->err_log;
3038         } else {
3039             conf->err_log = cf->cycle->new_log;
3040         }
3041     }
3042
3043     if (conf->error_pages == NULL && prev->error_pages) {
3044         conf->error_pages = prev->error_pages;
3045     }
3046
3047     ngx_conf_merge_str_value(conf->default_type,
3048                               prev->default_type, "text/plain");
3049
3050     ngx_conf_merge_off_value(conf->client_max_body_size,
3051                               prev->client_max_body_size, 1 * 1024 * 1024);
3052     ngx_conf_merge_size_value(conf->client_body_buffer_size,
3053                               prev->client_body_buffer_size,
3054                               (size_t) 2 * ngx_pagesize);
3055     ngx_conf_merge_msec_value(conf->client_body_timeout,
3056                               prev->client_body_timeout, 60000);
3057
3058     ngx_conf_merge_uint_value(conf->satisfy, prev->satisfy,
3059                               NGX_HTTP_SATISFY_ALL);
3060     ngx_conf_merge_uint_value(conf->if_modified_since, prev->if_modified_since,
3061                               NGX_HTTP_IMS_EXACT);
3062     ngx_conf_merge_value(conf->internal, prev->internal, 0);
3063     ngx_conf_merge_value(conf->client_body_in_file_only,
3064                               prev->client_body_in_file_only, 0);
3065     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
3066     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
3067                               prev->sendfile_max_chunk, 0);
3068     ngx_conf_merge_off_value(conf->directio, prev->directio,
3069                               NGX_MAX_OFF_T_VALUE);
3070     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
3071     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
3072
3073     ngx_conf_merge_msec_value(conf->send_timeout, prev->send_timeout, 60000);
3074     ngx_conf_merge_size_value(conf->send_lowat, prev->send_lowat, 0);
3075     ngx_conf_merge_size_value(conf->postpone_output, prev->postpone_output,
3076                               1460);
3077     ngx_conf_merge_size_value(conf->limit_rate, prev->limit_rate, 0);
3078     ngx_conf_merge_msec_value(conf->keepalive_timeout,
3079                               prev->keepalive_timeout, 75000);
3080     ngx_conf_merge_sec_value(conf->keepalive_header,
3081                               prev->keepalive_header, 0);
3082     ngx_conf_merge_msec_value(conf->lingering_time,
3083                               prev->lingering_time, 30000);
3084     ngx_conf_merge_msec_value(conf->lingering_timeout,
3085                               prev->lingering_timeout, 5000);
3086     ngx_conf_merge_msec_value(conf->resolver_timeout,
3087                               prev->resolver_timeout, 30000);
3088
3089     if (conf->resolver == NULL) {
3090
3091         if (prev->resolver == NULL) {
3092
3093             /*
3094              * create dummy resolver in http {} context
3095              * to inherit it in all servers
3096              */
3097
3098             prev->resolver = ngx_resolver_create(cf, NULL);
3099             if (prev->resolver == NULL) {
3100                 return NGX_CONF_ERROR;
3101             }
3102         }
3103
3104         conf->resolver = prev->resolver;
3105     }
3106
3107     ngx_conf_merge_path_value(conf->client_body_temp_path,
3108                               prev->client_body_temp_path,
3109                               NGX_HTTP_CLIENT_TEMP_PATH, 0, 0, 0,
3110                               ngx_garbage_collector_temp_handler, cf);
3111
3112     ngx_conf_merge_value(conf->reset_timedout_connection,
3113                               prev->reset_timedout_connection, 0);
3114     ngx_conf_merge_value(conf->server_name_in_redirect,
3115                               prev->server_name_in_redirect, 1);
3116     ngx_conf_merge_value(conf->port_in_redirect, prev->port_in_redirect, 1);
3117     ngx_conf_merge_value(conf->msie_padding, prev->msie_padding, 1);
3118     ngx_conf_merge_value(conf->msie_refresh, prev->msie_refresh, 0);
3119     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
3120     ngx_conf_merge_value(conf->log_subrequest, prev->log_subrequest, 0);
3121     ngx_conf_merge_value(conf->recursive_error_pages,
3122                               prev->recursive_error_pages, 0);
3123     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
3124
3125     ngx_conf_merge_ptr_value(conf->open_file_cache,
3126                               prev->open_file_cache, NULL);
3127
3128     ngx_conf_merge_sec_value(conf->open_file_cache_valid,
3129                               prev->open_file_cache_valid, 60);
3130
3131     ngx_conf_merge_uint_value(conf->open_file_cache_min_uses,
3132                               prev->open_file_cache_min_uses, 1);
3133
3134     ngx_conf_merge_sec_value(conf->open_file_cache_errors,
3135                               prev->open_file_cache_errors, 0);
3136
3137     ngx_conf_merge_sec_value(conf->open_file_cache_events,
3138                               prev->open_file_cache_events, 0);
3139 #if (NGX_HTTP_GZIP)
3140
3141     ngx_conf_merge_value(conf->gzip_vary, prev->gzip_vary, 0);
3142     ngx_conf_merge_uint_value(conf->gzip_http_version, prev->gzip_http_version,
3143                               NGX_HTTP_VERSION_11);
3144     ngx_conf_merge_bitmask_value(conf->gzip_proxied, prev->gzip_proxied,
3145                               (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
3146
3147 #if (NGX_PCRE)
3148     ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL);
3149 #endif
3150
3151     if (conf->gzip_disable_msie6 == 3) {
3152         conf->gzip_disable_msie6 =
3153             (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6;
3154     }
3155
3156 #endif
3157
3158     return NGX_CONF_OK;
3159 }
3160
3161
3162 /* AF_INET only */
3163
3164 static char *
3165 ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3166 {
3167     ngx_http_core_srv_conf_t *scf = conf;
3168
3169     ngx_str_t          *value, size;
3170     ngx_url_t           u;
3171     ngx_uint_t          n;
3172     ngx_http_listen_t  *ls;
3173
3174     /*
3175      * TODO: check duplicate 'listen' directives,
3176      *       add resolved name to server names ???
3177      */
3178
3179     value = cf->args->elts;
3180
3181     ngx_memzero(&u, sizeof(ngx_url_t));
3182
3183     u.url = value[1];
3184     u.listen = 1;
3185     u.default_port = 80;
3186
3187     if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
3188         if (u.err) {
3189             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3190                                "%s in \"%V\" of the \"listen\" directive",
3191                                u.err, &u.url);
3192         }
3193
3194         return NGX_CONF_ERROR;
3195     }
3196
3197     ls = ngx_array_push(&scf->listen);
3198     if (ls == NULL) {
3199         return NGX_CONF_ERROR;
3200     }
3201
3202     ngx_memzero(ls, sizeof(ngx_http_listen_t));
3203
3204     ls->family = u.family;
3205     ls->addr = u.addr.in_addr;
3206     ls->port = u.port;
3207     ls->file_name = cf->conf_file->file.name.data;
3208     ls->line = cf->conf_file->line;
3209     ls->conf.backlog = NGX_LISTEN_BACKLOG;
3210     ls->conf.rcvbuf = -1;
3211     ls->conf.sndbuf = -1;
3212
3213     n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, NGX_INET_ADDRSTRLEN);
3214     ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port);
3215
3216     if (cf->args->nelts == 2) {
3217         return NGX_CONF_OK;
3218     }
3219
3220     if (ngx_strcmp(value[2].data, "default") == 0) {
3221         ls->conf.default_server = 1;
3222         n = 3;
3223
3224     } else {
3225         n = 2;
3226     }
3227
3228     for ( /* void */ ; n < cf->args->nelts; n++) {
3229
3230         if (ls->conf.default_server == 0) {
3231             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3232                                "\"%V\" parameter can be specified for "
3233                                "the default \"listen\" directive only",
3234                                &value[n]);
3235             return NGX_CONF_ERROR;
3236         }
3237
3238         if (ngx_strcmp(value[n].data, "bind") == 0) {
3239             ls->conf.bind = 1;
3240             continue;
3241         }
3242
3243         if (ngx_strncmp(value[n].data, "backlog=", 8) == 0) {
3244             ls->conf.backlog = ngx_atoi(value[n].data + 8, value[n].len - 8);
3245             ls->conf.bind = 1;
3246
3247             if (ls->conf.backlog == NGX_ERROR || ls->conf.backlog == 0) {
3248                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3249                                    "invalid backlog \"%V\"", &value[n]);
3250                 return NGX_CONF_ERROR;
3251             }
3252
3253             continue;
3254         }
3255
3256         if (ngx_strncmp(value[n].data, "rcvbuf=", 7) == 0) {
3257             size.len = value[n].len - 7;
3258             size.data = value[n].data + 7;
3259
3260             ls->conf.rcvbuf = ngx_parse_size(&size);
3261             ls->conf.bind = 1;
3262
3263             if (ls->conf.rcvbuf == NGX_ERROR) {
3264                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3265                                    "invalid rcvbuf \"%V\"", &value[n]);
3266                 return NGX_CONF_ERROR;
3267             }
3268
3269             continue;
3270         }
3271
3272         if (ngx_strncmp(value[n].data, "sndbuf=", 7) == 0) {
3273             size.len = value[n].len - 7;
3274             size.data = value[n].data + 7;
3275
3276             ls->conf.sndbuf = ngx_parse_size(&size);
3277             ls->conf.bind = 1;
3278
3279             if (ls->conf.sndbuf == NGX_ERROR) {
3280                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3281                                    "invalid sndbuf \"%V\"", &value[n]);
3282                 return NGX_CONF_ERROR;
3283             }
3284
3285             continue;
3286         }
3287
3288         if (ngx_strncmp(value[n].data, "accept_filter=", 14) == 0) {
3289 #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER)
3290             ls->conf.accept_filter = (char *) &value[n].data[14];
3291             ls->conf.bind = 1;
3292 #else
3293             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3294                                "accept filters \"%V\" are not supported "
3295                                "on this platform, ignored",
3296                                &value[n]);
3297 #endif
3298             continue;
3299         }
3300
3301         if (ngx_strcmp(value[n].data, "deferred") == 0) {
3302 #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT)
3303             ls->conf.deferred_accept = 1;
3304             ls->conf.bind = 1;
3305 #else
3306             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3307                                "the deferred accept is not supported "
3308                                "on this platform, ignored");
3309 #endif
3310             continue;
3311         }
3312
3313         if (ngx_strcmp(value[n].data, "ssl") == 0) {
3314 #if (NGX_HTTP_SSL)
3315             ls->conf.ssl = 1;
3316             continue;
3317 #else
3318             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3319                                "the \"ssl\" parameter requires "
3320                                "ngx_http_ssl_module");
3321             return NGX_CONF_ERROR;
3322 #endif
3323         }
3324
3325         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3326                            "the invalid \"%V\" parameter", &value[n]);
3327         return NGX_CONF_ERROR;
3328     }
3329
3330     return NGX_CONF_OK;
3331 }
3332
3333
3334 static char *
3335 ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3336 {
3337     ngx_http_core_srv_conf_t *cscf = conf;
3338
3339     u_char                   ch;
3340     ngx_str_t               *value, name;
3341     ngx_uint_t               i;
3342     ngx_http_server_name_t  *sn;
3343
3344     value = cf->args->elts;
3345
3346     ch = value[1].data[0];
3347
3348     if (cscf->server_name.data == NULL) {
3349         if (value[1].len) {
3350             name = value[1];
3351
3352             if (ch == '.') {
3353                 name.len--;
3354                 name.data++;
3355             }
3356
3357             cscf->server_name.len = name.len;
3358             cscf->server_name.data = ngx_pstrdup(cf->pool, &name);
3359             if (cscf->server_name.data == NULL) {
3360                 return NGX_CONF_ERROR;
3361             }
3362
3363         } else {
3364             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3365                                "the first server name must not be empty");
3366             return NGX_CONF_ERROR;
3367         }
3368     }
3369
3370     for (i = 1; i < cf->args->nelts; i++) {
3371
3372         ch = value[i].data[0];
3373
3374         if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.'))
3375             || (ch == '.' && value[i].len < 2))
3376         {
3377             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3378                                "server name \"%V\" is invalid", &value[i]);
3379             return NGX_CONF_ERROR;
3380         }
3381
3382         if (ngx_strchr(value[i].data, '/')) {
3383             ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
3384                                "server name \"%V\" has strange symbols",
3385                                &value[i]);
3386         }
3387
3388         if (value[i].len == 1 && ch == '*') {
3389             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3390                                "\"server_name *\" is unsupported, use "
3391                                "\"server_name_in_redirect off\" instead");
3392             return NGX_CONF_ERROR;
3393         }
3394
3395         sn = ngx_array_push(&cscf->server_names);
3396         if (sn == NULL) {
3397             return NGX_CONF_ERROR;
3398         }
3399
3400 #if (NGX_PCRE)
3401         sn->regex = NULL;
3402 #endif
3403         sn->core_srv_conf = cscf;
3404         sn->name = value[i];
3405
3406         if (value[i].data[0] != '~') {
3407             continue;
3408         }
3409
3410 #if (NGX_PCRE)
3411         {
3412         ngx_str_t  err;
3413         u_char     errstr[NGX_MAX_CONF_ERRSTR];
3414
3415         err.len = NGX_MAX_CONF_ERRSTR;
3416         err.data = errstr;
3417
3418         value[i].len--;
3419         value[i].data++;
3420
3421         sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err);
3422
3423         if (sn->regex == NULL) {
3424             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
3425             return NGX_CONF_ERROR;
3426         }
3427
3428         sn->name = value[i];
3429         }
3430 #else
3431         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3432                            "the using of the regex \"%V\" "
3433                            "requires PCRE library", &value[i]);
3434
3435         return NGX_CONF_ERROR;
3436 #endif
3437     }
3438
3439     return NGX_CONF_OK;
3440 }
3441
3442
3443 static char *
3444 ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3445 {
3446     ngx_http_core_loc_conf_t *lcf = conf;
3447
3448     ngx_str_t                  *value;
3449     ngx_uint_t                  alias, n;
3450     ngx_http_script_compile_t   sc;
3451
3452     alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0;
3453
3454     if (lcf->root.data) {
3455
3456         /* the (ngx_uint_t) cast is required by gcc 2.7.2.3 */
3457
3458         if ((ngx_uint_t) lcf->alias == alias) {
3459             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3460                                "\"%V\" directive is duplicate",
3461                                &cmd->name);
3462         } else {
3463             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3464                                "\"%V\" directive is duplicate, "
3465                                "\"%s\" directive is specified before",
3466                                &cmd->name, lcf->alias ? "alias" : "root");
3467         }
3468
3469         return NGX_CONF_ERROR;
3470     }
3471
3472     if (lcf->named && alias) {
3473         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3474                            "the \"alias\" directive may not be used "
3475                            "inside named location");
3476
3477         return NGX_CONF_ERROR;
3478     }
3479
3480 #if (NGX_PCRE)
3481
3482     if (lcf->regex && alias) {
3483         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3484                            "the \"alias\" directive may not be used "
3485                            "inside location given by regular expression");
3486
3487         return NGX_CONF_ERROR;
3488     }
3489
3490 #endif
3491
3492     value = cf->args->elts;
3493
3494     if (ngx_strstr(value[1].data, "$document_root")
3495         || ngx_strstr(value[1].data, "${document_root}"))
3496     {
3497         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3498                            "the $document_root variable may not be used "
3499                            "in the \"%V\" directive",
3500                            &cmd->name);
3501
3502         return NGX_CONF_ERROR;
3503     }
3504
3505     if (ngx_strstr(value[1].data, "$realpath_root")
3506         || ngx_strstr(value[1].data, "${realpath_root}"))
3507     {
3508         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3509                            "the $realpath_root variable may not be used "
3510                            "in the \"%V\" directive",
3511                            &cmd->name);
3512
3513         return NGX_CONF_ERROR;
3514     }
3515
3516     lcf->alias = alias;
3517     lcf->root = value[1];
3518
3519     if (!alias && lcf->root.data[lcf->root.len - 1] == '/') {
3520         lcf->root.len--;
3521     }
3522
3523     if (lcf->root.data[0] != '$') {
3524         if (ngx_conf_full_name(cf->cycle, &lcf->root, 0) == NGX_ERROR) {
3525             return NGX_CONF_ERROR;
3526         }
3527     }
3528
3529     n = ngx_http_script_variables_count(&lcf->root);
3530
3531     if (n == 0) {
3532         return NGX_CONF_OK;
3533     }
3534
3535     ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
3536
3537     sc.cf = cf;
3538     sc.source = &lcf->root;
3539     sc.lengths = &lcf->root_lengths;
3540     sc.values = &lcf->root_values;
3541     sc.variables = n;
3542     sc.complete_lengths = 1;
3543     sc.complete_values = 1;
3544
3545     if (ngx_http_script_compile(&sc) != NGX_OK) {
3546         return NGX_CONF_ERROR;
3547     }
3548
3549     return NGX_CONF_OK;
3550 }
3551
3552
3553 static ngx_http_method_name_t  ngx_methods_names[] = {
3554    { (u_char *) "GET",       (uint32_t) ~NGX_HTTP_GET },
3555    { (u_char *) "HEAD",      (uint32_t) ~NGX_HTTP_HEAD },
3556    { (u_char *) "POST",      (uint32_t) ~NGX_HTTP_POST },
3557    { (u_char *) "PUT",       (uint32_t) ~NGX_HTTP_PUT },
3558    { (u_char *) "DELETE",    (uint32_t) ~NGX_HTTP_DELETE },
3559    { (u_char *) "MKCOL",     (uint32_t) ~NGX_HTTP_MKCOL },
3560    { (u_char *) "COPY",      (uint32_t) ~NGX_HTTP_COPY },
3561    { (u_char *) "MOVE",      (uint32_t) ~NGX_HTTP_MOVE },
3562    { (u_char *) "OPTIONS",   (uint32_t) ~NGX_HTTP_OPTIONS },
3563    { (u_char *) "PROPFIND" , (uint32_t) ~NGX_HTTP_PROPFIND },
3564    { (u_char *) "PROPPATCH", (uint32_t) ~NGX_HTTP_PROPPATCH },
3565    { (u_char *) "LOCK",      (uint32_t) ~NGX_HTTP_LOCK },
3566    { (u_char *) "UNLOCK",    (uint32_t) ~NGX_HTTP_UNLOCK },
3567    { NULL, 0 }
3568 };
3569
3570
3571 static char *
3572 ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
3573 {
3574     ngx_http_core_loc_conf_t *pclcf = conf;
3575
3576     char                      *rv;
3577     void                      *mconf;
3578     ngx_str_t                 *value;
3579     ngx_uint_t                 i;
3580     ngx_conf_t                 save;
3581     ngx_http_module_t         *module;
3582     ngx_http_conf_ctx_t       *ctx, *pctx;
3583     ngx_http_method_name_t    *name;
3584     ngx_http_core_loc_conf_t  *clcf;
3585
3586     if (pclcf->limit_except) {
3587         return "duplicate";
3588     }
3589
3590     pclcf->limit_except = 0xffffffff;
3591
3592     value = cf->args->elts;
3593
3594     for (i = 1; i < cf->args->nelts; i++) {
3595         for (name = ngx_methods_names; name->name; name++) {
3596
3597             if (ngx_strcasecmp(value[i].data, name->name) == 0) {
3598                 pclcf->limit_except &= name->method;
3599                 goto next;
3600             }
3601         }
3602
3603         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
3604                            "invalid method \"%V\"", &value[i]);
3605         return NGX_CONF_ERROR;
3606
3607     next:
3608         continue;
3609     }
3610
3611     if (!(pclcf->limit_except & NGX_HTTP_GET)) {
3612         pclcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
3613     }
3614
3615     ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
3616     if (ctx == NULL) {
3617         return NGX_CONF_ERROR;
3618     }
3619