- need module number for registering constants
[m6w6/ext-http] / http.c
1 /*
2 +----------------------------------------------------------------------+
3 | PECL :: http |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.0 of the PHP license, that |
6 | is bundled with this package in the file LICENSE, and is available |
7 | through the world-wide-web at http://www.php.net/license/3_0.txt. |
8 | If you did not receive a copy of the PHP license and are unable to |
9 | obtain it through the world-wide-web, please send a note to |
10 | license@php.net so we can mail you a copy immediately. |
11 +----------------------------------------------------------------------+
12 | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
13 +----------------------------------------------------------------------+
14 */
15
16 /* $Id$ */
17
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #ifdef HTTP_HAVE_CURL
24 # ifdef PHP_WIN32
25 # include <winsock2.h>
26 # endif
27 # include <curl/curl.h>
28 #endif
29
30 #include <ctype.h>
31
32 #include "php.h"
33 #include "php_ini.h"
34 #include "ext/standard/info.h"
35
36 #include "SAPI.h"
37
38 #include "php_http.h"
39 #include "php_http_std_defs.h"
40 #include "php_http_api.h"
41 #include "php_http_send_api.h"
42
43 #ifdef ZEND_ENGINE_2
44 # include "php_http_util_object.h"
45 # include "php_http_message_object.h"
46 # include "php_http_response_object.h"
47 # ifdef HTTP_HAVE_CURL
48 # include "php_http_request_object.h"
49 # endif
50 # include "php_http_exception_object.h"
51 #endif
52
53 #include "phpstr/phpstr.h"
54
55 #ifdef HTTP_HAVE_CURL
56 #ifdef ZEND_ENGINE_2
57 static
58 ZEND_BEGIN_ARG_INFO(http_request_info_ref_3, 0)
59 ZEND_ARG_PASS_INFO(0)
60 ZEND_ARG_PASS_INFO(0)
61 ZEND_ARG_PASS_INFO(1)
62 ZEND_END_ARG_INFO();
63
64 static
65 ZEND_BEGIN_ARG_INFO(http_request_info_ref_4, 0)
66 ZEND_ARG_PASS_INFO(0)
67 ZEND_ARG_PASS_INFO(0)
68 ZEND_ARG_PASS_INFO(0)
69 ZEND_ARG_PASS_INFO(1)
70 ZEND_END_ARG_INFO();
71
72 static
73 ZEND_BEGIN_ARG_INFO(http_request_info_ref_5, 0)
74 ZEND_ARG_PASS_INFO(0)
75 ZEND_ARG_PASS_INFO(0)
76 ZEND_ARG_PASS_INFO(0)
77 ZEND_ARG_PASS_INFO(0)
78 ZEND_ARG_PASS_INFO(1)
79 ZEND_END_ARG_INFO();
80 #else
81 static unsigned char http_request_info_ref_3[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
82 static unsigned char http_request_info_ref_4[] = {4, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
83 static unsigned char http_request_info_ref_5[] = {5, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_NONE, BYREF_FORCE};
84 #endif /* ZEND_ENGINE_2 */
85 #endif /* HTTP_HAVE_CURL */
86
87 ZEND_DECLARE_MODULE_GLOBALS(http)
88
89 #ifdef COMPILE_DL_HTTP
90 ZEND_GET_MODULE(http)
91 #endif
92
93 /* {{{ http_functions[] */
94 function_entry http_functions[] = {
95 PHP_FE(http_test, NULL)
96 PHP_FE(http_date, NULL)
97 PHP_FE(http_absolute_uri, NULL)
98 PHP_FE(http_negotiate_language, NULL)
99 PHP_FE(http_negotiate_charset, NULL)
100 PHP_FE(http_redirect, NULL)
101 PHP_FE(http_throttle, NULL)
102 PHP_FE(http_send_status, NULL)
103 PHP_FE(http_send_last_modified, NULL)
104 PHP_FE(http_send_content_type, NULL)
105 PHP_FE(http_send_content_disposition, NULL)
106 PHP_FE(http_match_modified, NULL)
107 PHP_FE(http_match_etag, NULL)
108 PHP_FE(http_cache_last_modified, NULL)
109 PHP_FE(http_cache_etag, NULL)
110 PHP_FE(http_send_data, NULL)
111 PHP_FE(http_send_file, NULL)
112 PHP_FE(http_send_stream, NULL)
113 PHP_FE(http_chunked_decode, NULL)
114 PHP_FE(http_split_response, NULL)
115 PHP_FE(http_parse_headers, NULL)
116 PHP_FE(http_get_request_headers, NULL)
117 #ifdef HTTP_HAVE_CURL
118 PHP_FE(http_get, http_request_info_ref_3)
119 PHP_FE(http_head, http_request_info_ref_3)
120 PHP_FE(http_post_data, http_request_info_ref_4)
121 PHP_FE(http_post_fields, http_request_info_ref_5)
122 PHP_FE(http_put_file, http_request_info_ref_4)
123 PHP_FE(http_put_stream, http_request_info_ref_4)
124 PHP_FE(http_request_method_register, NULL)
125 PHP_FE(http_request_method_unregister, NULL)
126 PHP_FE(http_request_method_exists, NULL)
127 PHP_FE(http_request_method_name, NULL)
128 #endif
129 PHP_FE(http_auth_basic, NULL)
130 PHP_FE(http_auth_basic_cb, NULL)
131 #ifndef ZEND_ENGINE_2
132 PHP_FE(http_build_query, NULL)
133 #endif
134 PHP_FE(ob_etaghandler, NULL)
135 {NULL, NULL, NULL}
136 };
137 /* }}} */
138
139 /* {{{ http_module_entry */
140 zend_module_entry http_module_entry = {
141 #if ZEND_MODULE_API_NO >= 20010901
142 STANDARD_MODULE_HEADER,
143 #endif
144 "http",
145 http_functions,
146 PHP_MINIT(http),
147 PHP_MSHUTDOWN(http),
148 PHP_RINIT(http),
149 PHP_RSHUTDOWN(http),
150 PHP_MINFO(http),
151 #if ZEND_MODULE_API_NO >= 20010901
152 HTTP_PEXT_VERSION,
153 #endif
154 STANDARD_MODULE_PROPERTIES
155 };
156 /* }}} */
157
158 int http_module_number;
159
160 #ifdef HTTP_HAVE_CURL
161 # ifdef HTTP_CURL_USE_ZEND_MM
162 static void http_curl_free(void *p) { efree(p); }
163 static char *http_curl_strdup(const char *p) { return estrdup(p); }
164 static void *http_curl_malloc(size_t s) { return emalloc(s); }
165 static void *http_curl_realloc(void *p, size_t s) { return erealloc(p, s); }
166 static void *http_curl_calloc(size_t n, size_t s) { return ecalloc(n, s); }
167 # endif /* HTTP_CURL_USE_ZEND_MM */
168 static void http_curl_freestr(void *s) { efree(*(char **)s); }
169 #endif /* HTTP_HAVE_CURL */
170
171 /* {{{ http_globals */
172 static inline void http_globals_init(zend_http_globals *G)
173 {
174 memset(G, 0, sizeof(zend_http_globals));
175 G->send.buffer_size = HTTP_SENDBUF_SIZE;
176 zend_hash_init(&G->request.methods.custom, 0, NULL, ZVAL_PTR_DTOR, 0);
177 #ifdef HTTP_HAVE_CURL
178 zend_llist_init(&G->request.curl.copies, sizeof(char *), http_curl_freestr, 0);
179 #endif
180 }
181 static inline void http_globals_free(zend_http_globals *G)
182 {
183 STR_FREE(G->send.content_type);
184 STR_FREE(G->send.unquoted_etag);
185 zend_hash_destroy(&G->request.methods.custom);
186 }
187 /* }}} */
188
189 /* {{{ static inline void http_check_allowed_methods(char *, int) */
190 #define http_check_allowed_methods(m, l) _http_check_allowed_methods((m), (l) TSRMLS_CC)
191 static inline void _http_check_allowed_methods(char *methods, int length TSRMLS_DC)
192 {
193 if (length && SG(request_info).request_method) {
194 if (SUCCESS != http_check_method_ex(SG(request_info).request_method, methods)) {
195 char *header = emalloc(length + sizeof("Allow: "));
196 sprintf(header, "Allow: %s", methods);
197 http_exit(405, header);
198 }
199 }
200 }
201 /* }}} */
202
203 /* {{{ PHP_INI */
204 PHP_INI_MH(http_update_allowed_methods)
205 {
206 http_check_allowed_methods(new_value, new_value_length);
207 return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
208 }
209
210 PHP_INI_BEGIN()
211 HTTP_PHP_INI_ENTRY("http.allowed_methods", NULL, PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
212 HTTP_PHP_INI_ENTRY("http.cache_log", NULL, PHP_INI_ALL, OnUpdateString, log.cache)
213 PHP_INI_END()
214 /* }}} */
215
216
217 /* {{{ PHP_MINIT_FUNCTION */
218 PHP_MINIT_FUNCTION(http)
219 {
220 http_module_number = module_number;
221
222 ZEND_INIT_MODULE_GLOBALS(http, NULL, NULL);
223 REGISTER_INI_ENTRIES();
224
225 #ifdef HTTP_HAVE_CURL
226 # ifdef HTTP_CURL_USE_ZEND_MM
227 if (CURLE_OK != curl_global_init_mem(CURL_GLOBAL_ALL,
228 http_curl_malloc,
229 http_curl_free,
230 http_curl_realloc,
231 http_curl_strdup,
232 http_curl_calloc)) {
233 return FAILURE;
234 }
235 # endif /* HTTP_CURL_USE_ZEND_MM */
236 #endif /* HTTP_HAVE_CURL */
237
238 #ifdef ZEND_ENGINE_2
239 http_util_object_init();
240 http_message_object_init();
241 http_response_object_init();
242 # ifdef HTTP_HAVE_CURL
243 http_request_object_init();
244 # endif /* HTTP_HAVE_CURL */
245 http_exception_object_init();
246 #endif /* ZEND_ENGINE_2 */
247
248 return SUCCESS;
249 }
250 /* }}} */
251
252 /* {{{ PHP_MSHUTDOWN_FUNCTION */
253 PHP_MSHUTDOWN_FUNCTION(http)
254 {
255 UNREGISTER_INI_ENTRIES();
256 #ifdef HTTP_HAVE_CURL
257 curl_global_cleanup();
258 #endif
259 return SUCCESS;
260 }
261 /* }}} */
262
263 /* {{{ PHP_RINIT_FUNCTION */
264 PHP_RINIT_FUNCTION(http)
265 {
266 char *m;
267
268 if (m = INI_STR("http.allowed_methods")) {
269 http_check_allowed_methods(m, strlen(m));
270 }
271
272 http_globals_init(HTTP_GLOBALS);
273 return SUCCESS;
274 }
275 /* }}} */
276
277 /* {{{ PHP_RSHUTDOWN_FUNCTION */
278 PHP_RSHUTDOWN_FUNCTION(http)
279 {
280 http_globals_free(HTTP_GLOBALS);
281 return SUCCESS;
282 }
283 /* }}} */
284
285 /* {{{ PHP_MINFO_FUNCTION */
286 PHP_MINFO_FUNCTION(http)
287 {
288 #ifdef ZEND_ENGINE_2
289 # define HTTP_FUNC_AVAIL(CLASS) "procedural, object oriented (" CLASS ")"
290 #else
291 # define HTTP_FUNC_AVAIL(CLASS) "procedural"
292 #endif
293
294 #ifdef HTTP_HAVE_CURL
295 # define HTTP_CURL_VERSION curl_version()
296 # ifdef ZEND_ENGINE_2
297 # define HTTP_CURL_AVAIL(CLASS) "procedural, object oriented (" CLASS ")"
298 # else
299 # define HTTP_CURL_AVAIL(CLASS) "procedural"
300 # endif
301 #else
302 # define HTTP_CURL_VERSION "libcurl not available"
303 # define HTTP_CURL_AVAIL(CLASS) "libcurl not available"
304 #endif
305
306 #include "php_http_request_api.h"
307
308 php_info_print_table_start();
309 {
310 char full_version_string[1024] = {0};
311 snprintf(full_version_string, 1023, "%s (%s)", HTTP_PEXT_VERSION, HTTP_CURL_VERSION);
312
313 php_info_print_table_row(2, "Extended HTTP support:", "enabled");
314 php_info_print_table_row(2, "Extension Version:", full_version_string);
315 }
316 php_info_print_table_end();
317
318 php_info_print_table_start();
319 {
320 unsigned i;
321 zval **custom_method;
322 phpstr *known_request_methods = phpstr_new();
323 phpstr *custom_request_methods = phpstr_new();
324
325 for (i = HTTP_NO_REQUEST_METHOD+1; i < HTTP_MAX_REQUEST_METHOD; ++i) {
326 phpstr_appendl(known_request_methods, http_request_method_name(i));
327 phpstr_appends(known_request_methods, ", ");
328 }
329 FOREACH_HASH_VAL(&HTTP_G(request).methods.custom, custom_method) {
330 phpstr_append(custom_request_methods, Z_STRVAL_PP(custom_method), Z_STRLEN_PP(custom_method));
331 phpstr_appends(custom_request_methods, ", ");
332 }
333
334 phpstr_append(known_request_methods, PHPSTR_VAL(custom_request_methods), PHPSTR_LEN(custom_request_methods));
335 phpstr_fix(known_request_methods);
336 phpstr_fix(custom_request_methods);
337
338 php_info_print_table_row(2, "Known Request Methods:", PHPSTR_VAL(known_request_methods));
339 php_info_print_table_row(2, "Custom Request Methods:",
340 PHPSTR_LEN(custom_request_methods) ? PHPSTR_VAL(custom_request_methods) : "none registered");
341
342 phpstr_free(known_request_methods);
343 phpstr_free(custom_request_methods);
344 }
345 php_info_print_table_end();
346
347 php_info_print_table_start();
348 {
349 php_info_print_table_header(2, "Functionality", "Availability");
350 php_info_print_table_row(2, "Miscellaneous Utilities:", HTTP_FUNC_AVAIL("HttpUtil, HttpMessage"));
351 php_info_print_table_row(2, "Extended HTTP Responses:", HTTP_FUNC_AVAIL("HttpResponse"));
352 php_info_print_table_row(2, "Extended HTTP Requests:", HTTP_CURL_AVAIL("HttpRequest"));
353 }
354 php_info_print_table_end();
355
356 DISPLAY_INI_ENTRIES();
357 }
358 /* }}} */
359
360 /*
361 * Local variables:
362 * tab-width: 4
363 * c-basic-offset: 4
364 * End:
365 * vim600: noet sw=4 ts=4 fdm=marker
366 * vim<600: noet sw=4 ts=4
367 */
368