- consistent usage of HTTP_G macro (only)
[m6w6/ext-http] / http.c
1 /*
2 +--------------------------------------------------------------------+
3 | PECL :: http |
4 +--------------------------------------------------------------------+
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the conditions mentioned |
7 | in the accompanying LICENSE file are met. |
8 +--------------------------------------------------------------------+
9 | Copyright (c) 2004-2006, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id$ */
14
15 #define HTTP_WANT_SAPI
16 #define HTTP_WANT_CURL
17 #define HTTP_WANT_ZLIB
18 #define HTTP_WANT_MAGIC
19 #include "php_http.h"
20
21 #include "php_ini.h"
22 #include "ext/standard/info.h"
23 #include "zend_extensions.h"
24
25 #include "php_http_api.h"
26 #include "php_http_send_api.h"
27 #include "php_http_cache_api.h"
28 #include "php_http_send_api.h"
29 #include "php_http_message_api.h"
30 #include "php_http_request_method_api.h"
31 #ifdef HTTP_HAVE_CURL
32 # include "php_http_request_api.h"
33 #endif
34 #ifdef HTTP_HAVE_ZLIB
35 # include "php_http_encoding_api.h"
36 #endif
37 #include "php_http_url_api.h"
38
39 #ifdef ZEND_ENGINE_2
40 # include "php_http_filter_api.h"
41 # include "php_http_util_object.h"
42 # include "php_http_message_object.h"
43 # include "php_http_querystring_object.h"
44 # ifndef WONKY
45 # include "php_http_response_object.h"
46 # endif
47 # ifdef HTTP_HAVE_CURL
48 # include "php_http_request_object.h"
49 # include "php_http_requestpool_object.h"
50 # endif
51 # ifdef HTTP_HAVE_ZLIB
52 # include "php_http_deflatestream_object.h"
53 # include "php_http_inflatestream_object.h"
54 # endif
55 # include "php_http_exception_object.h"
56 #endif
57
58
59 ZEND_DECLARE_MODULE_GLOBALS(http);
60 HTTP_DECLARE_ARG_PASS_INFO();
61
62 #ifdef COMPILE_DL_HTTP
63 ZEND_GET_MODULE(http)
64 #endif
65
66 /* {{{ http_functions[] */
67 zend_function_entry http_functions[] = {
68 PHP_FE(http_test, NULL)
69 PHP_FE(http_date, NULL)
70 PHP_FE(http_build_url, http_arg_pass_ref_4)
71 PHP_FE(http_build_str, NULL)
72 #ifndef ZEND_ENGINE_2
73 PHP_FALIAS(http_build_query, http_build_str)
74 #endif
75 PHP_FE(http_negotiate_language, http_arg_pass_ref_2)
76 PHP_FE(http_negotiate_charset, http_arg_pass_ref_2)
77 PHP_FE(http_negotiate_content_type, http_arg_pass_ref_2)
78 PHP_FE(http_redirect, NULL)
79 PHP_FE(http_throttle, NULL)
80 PHP_FE(http_send_status, NULL)
81 PHP_FE(http_send_last_modified, NULL)
82 PHP_FE(http_send_content_type, NULL)
83 PHP_FE(http_send_content_disposition, NULL)
84 PHP_FE(http_match_modified, NULL)
85 PHP_FE(http_match_etag, NULL)
86 PHP_FE(http_cache_last_modified, NULL)
87 PHP_FE(http_cache_etag, NULL)
88 PHP_FE(http_send_data, NULL)
89 PHP_FE(http_send_file, NULL)
90 PHP_FE(http_send_stream, NULL)
91 PHP_FE(http_chunked_decode, NULL)
92 PHP_FE(http_parse_message, NULL)
93 PHP_FE(http_parse_headers, NULL)
94 PHP_FE(http_parse_cookie, NULL)
95 PHP_FE(http_get_request_headers, NULL)
96 PHP_FE(http_get_request_body, NULL)
97 PHP_FE(http_get_request_body_stream, NULL)
98 PHP_FE(http_match_request_header, NULL)
99 #ifdef HTTP_HAVE_CURL
100 PHP_FE(http_get, http_arg_pass_ref_3)
101 PHP_FE(http_head, http_arg_pass_ref_3)
102 PHP_FE(http_post_data, http_arg_pass_ref_4)
103 PHP_FE(http_post_fields, http_arg_pass_ref_5)
104 PHP_FE(http_put_file, http_arg_pass_ref_4)
105 PHP_FE(http_put_stream, http_arg_pass_ref_4)
106 #endif
107 PHP_FE(http_request_method_register, NULL)
108 PHP_FE(http_request_method_unregister, NULL)
109 PHP_FE(http_request_method_exists, NULL)
110 PHP_FE(http_request_method_name, NULL)
111 PHP_FE(ob_etaghandler, NULL)
112 #ifdef HTTP_HAVE_ZLIB
113 PHP_FE(http_deflate, NULL)
114 PHP_FE(http_inflate, NULL)
115 PHP_FE(ob_deflatehandler, NULL)
116 PHP_FE(ob_inflatehandler, NULL)
117 #endif
118 PHP_FE(http_support, NULL)
119
120 EMPTY_FUNCTION_ENTRY
121 };
122 /* }}} */
123
124 /* {{{ http_module_dep */
125 #if ZEND_EXTENSION_API_NO >= 220050617
126 static zend_module_dep http_module_dep[] = {
127 # ifdef HAVE_SPL
128 ZEND_MOD_REQUIRED("spl")
129 # endif
130 # ifdef HTTP_HAVE_EXT_HASH
131 ZEND_MOD_REQUIRED("hash")
132 # endif
133 # ifdef HAVE_PHP_SESSION
134 ZEND_MOD_REQUIRED("session")
135 # endif
136 {NULL, NULL, NULL, 0}
137 };
138 #endif
139 /* }}} */
140
141 /* {{{ http_module_entry */
142 zend_module_entry http_module_entry = {
143 #if ZEND_EXTENSION_API_NO >= 220050617
144 STANDARD_MODULE_HEADER_EX, NULL,
145 http_module_dep,
146 #else
147 STANDARD_MODULE_HEADER,
148 #endif
149 "http",
150 http_functions,
151 PHP_MINIT(http),
152 PHP_MSHUTDOWN(http),
153 PHP_RINIT(http),
154 PHP_RSHUTDOWN(http),
155 PHP_MINFO(http),
156 PHP_EXT_HTTP_VERSION,
157 STANDARD_MODULE_PROPERTIES
158 };
159 /* }}} */
160
161 int http_module_number;
162
163 /* {{{ http_globals */
164 static void http_globals_init_once(zend_http_globals *G)
165 {
166 memset(G, 0, sizeof(zend_http_globals));
167 }
168
169 #define http_globals_init(g) _http_globals_init((g) TSRMLS_CC)
170 static inline void _http_globals_init(zend_http_globals *G TSRMLS_DC)
171 {
172 G->send.buffer_size = HTTP_SENDBUF_SIZE;
173 #ifndef HTTP_HAVE_SAPI_RTIME
174 G->request_time = time(NULL);
175 #endif
176 G->read_post_data = 0;
177 }
178
179 #define http_globals_free(g) _http_globals_free((g) TSRMLS_CC)
180 static inline void _http_globals_free(zend_http_globals *G TSRMLS_DC)
181 {
182 STR_SET(G->send.content_type, NULL);
183 STR_SET(G->send.unquoted_etag, NULL);
184 }
185 /* }}} */
186
187 /* {{{ static inline void http_check_allowed_methods(char *, int) */
188 #define http_check_allowed_methods(m, l) _http_check_allowed_methods((m), (l) TSRMLS_CC)
189 static inline void _http_check_allowed_methods(char *methods, int length TSRMLS_DC)
190 {
191 if (length && SG(request_info).request_method) {
192 if (SUCCESS != http_check_method_ex(SG(request_info).request_method, methods)) {
193 char *header = emalloc(length + sizeof("Allow: "));
194 sprintf(header, "Allow: %s", methods);
195 http_exit(405, header);
196 }
197 }
198 }
199 /* }}} */
200
201 /* {{{ PHP_INI */
202 PHP_INI_MH(http_update_allowed_methods)
203 {
204 http_check_allowed_methods(new_value, new_value_length);
205 return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
206 }
207
208 #ifndef ZEND_ENGINE_2
209 # define OnUpdateLong OnUpdateInt
210 #endif
211
212 PHP_INI_BEGIN()
213 HTTP_PHP_INI_ENTRY("http.allowed_methods", "", PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
214 HTTP_PHP_INI_ENTRY("http.cache_log", "", PHP_INI_ALL, OnUpdateString, log.cache)
215 HTTP_PHP_INI_ENTRY("http.redirect_log", "", PHP_INI_ALL, OnUpdateString, log.redirect)
216 HTTP_PHP_INI_ENTRY("http.allowed_methods_log", "", PHP_INI_ALL, OnUpdateString, log.allowed_methods)
217 HTTP_PHP_INI_ENTRY("http.composite_log", "", PHP_INI_ALL, OnUpdateString, log.composite)
218 HTTP_PHP_INI_ENTRY("http.etag_mode", "MD5", PHP_INI_ALL, OnUpdateString, etag.mode)
219 #ifdef ZEND_ENGINE_2
220 HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions)
221 #endif
222 HTTP_PHP_INI_ENTRY("http.force_exit", "1", PHP_INI_ALL, OnUpdateBool, force_exit)
223 #ifdef HTTP_HAVE_ZLIB
224 HTTP_PHP_INI_ENTRY("http.ob_inflate_auto", "0", PHP_INI_PERDIR, OnUpdateBool, send.inflate.start_auto)
225 HTTP_PHP_INI_ENTRY("http.ob_inflate_flags", "0", PHP_INI_ALL, OnUpdateLong, send.inflate.start_flags)
226 HTTP_PHP_INI_ENTRY("http.ob_deflate_auto", "0", PHP_INI_PERDIR, OnUpdateBool, send.deflate.start_auto)
227 HTTP_PHP_INI_ENTRY("http.ob_deflate_flags", "0", PHP_INI_ALL, OnUpdateLong, send.deflate.start_flags)
228 #endif
229 PHP_INI_END()
230 /* }}} */
231
232 /* {{{ PHP_MINIT_FUNCTION */
233 PHP_MINIT_FUNCTION(http)
234 {
235 http_module_number = module_number;
236
237 ZEND_INIT_MODULE_GLOBALS(http, http_globals_init_once, NULL)
238
239 REGISTER_INI_ENTRIES();
240
241 if ( (SUCCESS != PHP_MINIT_CALL(http_support)) ||
242 (SUCCESS != PHP_MINIT_CALL(http_send)) ||
243 (SUCCESS != PHP_MINIT_CALL(http_url)) ||
244 #ifdef HTTP_HAVE_CURL
245 (SUCCESS != PHP_MINIT_CALL(http_request)) ||
246 #endif /* HTTP_HAVE_CURL */
247 #ifdef HTTP_HAVE_ZLIB
248 (SUCCESS != PHP_MINIT_CALL(http_encoding)) ||
249 #endif
250 (SUCCESS != PHP_MINIT_CALL(http_request_method))) {
251 return FAILURE;
252 }
253
254 #ifdef ZEND_ENGINE_2
255 if ( (SUCCESS != PHP_MINIT_CALL(http_filter)) ||
256 (SUCCESS != PHP_MINIT_CALL(http_util_object)) ||
257 (SUCCESS != PHP_MINIT_CALL(http_message_object)) ||
258 (SUCCESS != PHP_MINIT_CALL(http_querystring_object))||
259 # ifndef WONKY
260 (SUCCESS != PHP_MINIT_CALL(http_response_object)) ||
261 # endif /* WONKY */
262 # ifdef HTTP_HAVE_CURL
263 (SUCCESS != PHP_MINIT_CALL(http_request_object)) ||
264 (SUCCESS != PHP_MINIT_CALL(http_requestpool_object))||
265 # endif /* HTTP_HAVE_CURL */
266 # ifdef HTTP_HAVE_ZLIB
267 (SUCCESS != PHP_MINIT_CALL(http_deflatestream_object)) ||
268 (SUCCESS != PHP_MINIT_CALL(http_inflatestream_object)) ||
269 # endif /* HTTP_HAVE_ZLIB */
270 (SUCCESS != PHP_MINIT_CALL(http_exception_object))) {
271 return FAILURE;
272 }
273 #endif /* ZEND_ENGINE_2 */
274
275 return SUCCESS;
276 }
277 /* }}} */
278
279 /* {{{ PHP_MSHUTDOWN_FUNCTION */
280 PHP_MSHUTDOWN_FUNCTION(http)
281 {
282 UNREGISTER_INI_ENTRIES();
283 #ifdef HTTP_HAVE_CURL
284 return PHP_MSHUTDOWN_CALL(http_request);
285 #endif
286 return SUCCESS;
287 }
288 /* }}} */
289
290 /* {{{ PHP_RINIT_FUNCTION */
291 PHP_RINIT_FUNCTION(http)
292 {
293 http_globals_init(HTTP_G);
294
295 if (HTTP_G->request.methods.allowed) {
296 http_check_allowed_methods(HTTP_G->request.methods.allowed,
297 strlen(HTTP_G->request.methods.allowed));
298 }
299
300 if ( (SUCCESS != PHP_RINIT_CALL(http_request_method))
301 #ifdef HTTP_HAVE_ZLIB
302 || (SUCCESS != PHP_RINIT_CALL(http_encoding))
303 #endif
304 ) {
305 return FAILURE;
306 }
307
308 return SUCCESS;
309 }
310 /* }}} */
311
312 /* {{{ PHP_RSHUTDOWN_FUNCTION */
313 PHP_RSHUTDOWN_FUNCTION(http)
314 {
315 STATUS status = SUCCESS;
316
317 if ( (SUCCESS != PHP_RSHUTDOWN_CALL(http_request_method))
318 #ifdef HTTP_HAVE_ZLIB
319 || (SUCCESS != PHP_RSHUTDOWN_CALL(http_encoding))
320 #endif
321 ) {
322 status = FAILURE;
323 }
324
325 http_globals_free(HTTP_G);
326 return status;
327 }
328 /* }}} */
329
330 /* {{{ PHP_MINFO_FUNCTION */
331 PHP_MINFO_FUNCTION(http)
332 {
333 php_info_print_table_start();
334 {
335 php_info_print_table_row(2, "HTTP Support", "enabled");
336 php_info_print_table_row(2, "Extension Version", PHP_EXT_HTTP_VERSION);
337 php_info_print_table_row(2, "Registered Classes",
338 #ifndef ZEND_ENGINE_2
339 "none"
340 #else
341 "HttpUtil, "
342 "HttpMessage, "
343 # ifdef HTTP_HAVE_CURL
344 "HttpRequest, "
345 "HttpRequestPool, "
346 # endif
347 # ifdef HTTP_HAVE_ZLIB
348 "HttpDeflateStream, "
349 "HttpInflateStream, "
350 # endif
351 # ifndef WONKY
352 "HttpResponse, "
353 # endif
354 "HttpQueryString"
355 #endif
356 );
357 php_info_print_table_row(2, "Output Handlers", "ob_deflatehandler, ob_inflatehandler, ob_etaghandler");
358 php_info_print_table_row(2, "Stream Filters",
359 #ifndef ZEND_ENGINE_2
360 "none"
361 #else
362 "http.chunked_decode, http.chunked_encode, http.deflate, http.inflate"
363 #endif
364 );
365 }
366 php_info_print_table_end();
367
368 php_info_print_table_start();
369 php_info_print_table_header(3, "Used Library", "Compiled", "Linked");
370 {
371 #ifdef HTTP_HAVE_CURL
372 curl_version_info_data *cv = curl_version_info(CURLVERSION_NOW);
373 php_info_print_table_row(3, "libcurl", LIBCURL_VERSION, cv->version);
374 #else
375 php_info_print_table_row(2, "libcurl", "disabled", "disabled");
376 #endif
377 #ifdef HTTP_HAVE_ZLIB
378 php_info_print_table_row(3, "libz", ZLIB_VERSION, zlibVersion());
379 #else
380 php_info_print_table_row(3, "libz", "disabled", "disabled");
381 #endif
382 #if defined(HTTP_HAVE_MAGIC) && !defined(WONKY)
383 php_info_print_table_row(3, "libmagic", "unknown", "unknown");
384 #else
385 php_info_print_table_row(3, "libmagic", "disabled", "disabled");
386 #endif
387 }
388 php_info_print_table_end();
389
390 php_info_print_table_start();
391 php_info_print_table_colspan_header(2, "Request Methods");
392 {
393 int i;
394 phpstr *custom_request_methods = phpstr_new();
395 phpstr *known_request_methods = phpstr_from_string(HTTP_KNOWN_METHODS, lenof(HTTP_KNOWN_METHODS));
396 http_request_method_entry **ptr = HTTP_G->request.methods.custom.entries;
397
398 for (i = 0; i < HTTP_G->request.methods.custom.count; ++i) {
399 if (ptr[i]) {
400 phpstr_appendf(custom_request_methods, "%s, ", ptr[i]->name);
401 }
402 }
403
404 phpstr_append(known_request_methods, PHPSTR_VAL(custom_request_methods), PHPSTR_LEN(custom_request_methods));
405 phpstr_fix(known_request_methods);
406 phpstr_fix(custom_request_methods);
407
408 php_info_print_table_row(2, "Known", PHPSTR_VAL(known_request_methods));
409 php_info_print_table_row(2, "Custom",
410 PHPSTR_LEN(custom_request_methods) ? PHPSTR_VAL(custom_request_methods) : "none registered");
411 php_info_print_table_row(2, "Allowed", strlen(HTTP_G->request.methods.allowed) ? HTTP_G->request.methods.allowed : "(ANY)");
412
413 phpstr_free(&known_request_methods);
414 phpstr_free(&custom_request_methods);
415 }
416 php_info_print_table_end();
417
418 DISPLAY_INI_ENTRIES();
419 }
420 /* }}} */
421
422 /*
423 * Local variables:
424 * tab-width: 4
425 * c-basic-offset: 4
426 * End:
427 * vim600: noet sw=4 ts=4 fdm=marker
428 * vim<600: noet sw=4 ts=4
429 */
430