- might want to use HTTP_STATIC_ME_ALIAS() for other classes too
[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 #ifdef HTTP_HAVE_CURL
159 # ifdef HTTP_CURL_USE_ZEND_MM
160 static void http_curl_free(void *p) { efree(p); }
161 static char *http_curl_strdup(const char *p) { return estrdup(p); }
162 static void *http_curl_malloc(size_t s) { return emalloc(s); }
163 static void *http_curl_realloc(void *p, size_t s) { return erealloc(p, s); }
164 static void *http_curl_calloc(size_t n, size_t s) { return ecalloc(n, s); }
165 # endif /* HTTP_CURL_USE_ZEND_MM */
166 static void http_curl_freestr(void *s) { efree(*(char **)s); }
167 #endif /* HTTP_HAVE_CURL */
168
169 /* {{{ http_globals */
170 static inline void http_globals_init(zend_http_globals *G)
171 {
172 memset(G, 0, sizeof(zend_http_globals));
173 G->send.buffer_size = HTTP_SENDBUF_SIZE;
174 zend_hash_init(&G->request.methods.custom, 0, NULL, ZVAL_PTR_DTOR, 0);
175 #ifdef HTTP_HAVE_CURL
176 zend_llist_init(&G->request.curl.copies, sizeof(char *), http_curl_freestr, 0);
177 #endif
178 }
179 static inline void http_globals_free(zend_http_globals *G)
180 {
181 STR_FREE(G->send.content_type);
182 STR_FREE(G->send.unquoted_etag);
183 zend_hash_destroy(&G->request.methods.custom);
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 PHP_INI_BEGIN()
209 HTTP_PHP_INI_ENTRY("http.allowed_methods", NULL, PHP_INI_ALL, http_update_allowed_methods, request.methods.allowed)
210 HTTP_PHP_INI_ENTRY("http.cache_log", NULL, PHP_INI_ALL, OnUpdateString, log.cache)
211 PHP_INI_END()
212 /* }}} */
213
214
215 /* {{{ PHP_MINIT_FUNCTION */
216 PHP_MINIT_FUNCTION(http)
217 {
218 ZEND_INIT_MODULE_GLOBALS(http, NULL, NULL);
219 REGISTER_INI_ENTRIES();
220
221 #ifdef HTTP_HAVE_CURL
222 # ifdef HTTP_CURL_USE_ZEND_MM
223 if (CURLE_OK != curl_global_init_mem(CURL_GLOBAL_ALL,
224 http_curl_malloc,
225 http_curl_free,
226 http_curl_realloc,
227 http_curl_strdup,
228 http_curl_calloc)) {
229 return FAILURE;
230 }
231 # endif /* HTTP_CURL_USE_ZEND_MM */
232 #endif /* HTTP_HAVE_CURL */
233
234 #ifdef ZEND_ENGINE_2
235 http_util_object_init();
236 http_message_object_init();
237 http_response_object_init();
238 # ifdef HTTP_HAVE_CURL
239 http_request_object_init();
240 # endif /* HTTP_HAVE_CURL */
241 http_exception_object_init();
242 #endif /* ZEND_ENGINE_2 */
243
244 return SUCCESS;
245 }
246 /* }}} */
247
248 /* {{{ PHP_MSHUTDOWN_FUNCTION */
249 PHP_MSHUTDOWN_FUNCTION(http)
250 {
251 UNREGISTER_INI_ENTRIES();
252 #ifdef HTTP_HAVE_CURL
253 curl_global_cleanup();
254 #endif
255 return SUCCESS;
256 }
257 /* }}} */
258
259 /* {{{ PHP_RINIT_FUNCTION */
260 PHP_RINIT_FUNCTION(http)
261 {
262 char *m;
263
264 if (m = INI_STR("http.allowed_methods")) {
265 http_check_allowed_methods(m, strlen(m));
266 }
267
268 http_globals_init(HTTP_GLOBALS);
269 return SUCCESS;
270 }
271 /* }}} */
272
273 /* {{{ PHP_RSHUTDOWN_FUNCTION */
274 PHP_RSHUTDOWN_FUNCTION(http)
275 {
276 http_globals_free(HTTP_GLOBALS);
277 return SUCCESS;
278 }
279 /* }}} */
280
281 /* {{{ PHP_MINFO_FUNCTION */
282 PHP_MINFO_FUNCTION(http)
283 {
284 #ifdef ZEND_ENGINE_2
285 # define HTTP_FUNC_AVAIL(CLASS) "procedural, object oriented (" CLASS ")"
286 #else
287 # define HTTP_FUNC_AVAIL(CLASS) "procedural"
288 #endif
289
290 #ifdef HTTP_HAVE_CURL
291 # define HTTP_CURL_VERSION curl_version()
292 # ifdef ZEND_ENGINE_2
293 # define HTTP_CURL_AVAIL(CLASS) "procedural, object oriented (" CLASS ")"
294 # else
295 # define HTTP_CURL_AVAIL(CLASS) "procedural"
296 # endif
297 #else
298 # define HTTP_CURL_VERSION "libcurl not available"
299 # define HTTP_CURL_AVAIL(CLASS) "libcurl not available"
300 #endif
301
302 #include "php_http_request_api.h"
303
304 php_info_print_table_start();
305 {
306 char full_version_string[1024] = {0};
307 snprintf(full_version_string, 1023, "%s (%s)", HTTP_PEXT_VERSION, HTTP_CURL_VERSION);
308
309 php_info_print_table_row(2, "Extended HTTP support:", "enabled");
310 php_info_print_table_row(2, "Extension Version:", full_version_string);
311 }
312 php_info_print_table_end();
313
314 php_info_print_table_start();
315 {
316 unsigned i;
317 zval **custom_method;
318 phpstr *known_request_methods = phpstr_new();
319 phpstr *custom_request_methods = phpstr_new();
320
321 for (i = HTTP_NO_REQUEST_METHOD+1; i < HTTP_MAX_REQUEST_METHOD; ++i) {
322 phpstr_appendl(known_request_methods, http_request_method_name(i));
323 phpstr_appends(known_request_methods, ", ");
324 }
325 FOREACH_HASH_VAL(&HTTP_G(request).methods.custom, custom_method) {
326 phpstr_append(custom_request_methods, Z_STRVAL_PP(custom_method), Z_STRLEN_PP(custom_method));
327 phpstr_appends(custom_request_methods, ", ");
328 }
329
330 phpstr_append(known_request_methods, PHPSTR_VAL(custom_request_methods), PHPSTR_LEN(custom_request_methods));
331 phpstr_fix(known_request_methods);
332 phpstr_fix(custom_request_methods);
333
334 php_info_print_table_row(2, "Known Request Methods:", PHPSTR_VAL(known_request_methods));
335 php_info_print_table_row(2, "Custom Request Methods:",
336 PHPSTR_LEN(custom_request_methods) ? PHPSTR_VAL(custom_request_methods) : "none registered");
337
338 phpstr_free(known_request_methods);
339 phpstr_free(custom_request_methods);
340 }
341 php_info_print_table_end();
342
343 php_info_print_table_start();
344 {
345 php_info_print_table_header(2, "Functionality", "Availability");
346 php_info_print_table_row(2, "Miscellaneous Utilities:", HTTP_FUNC_AVAIL("HttpUtil, HttpMessage"));
347 php_info_print_table_row(2, "Extended HTTP Responses:", HTTP_FUNC_AVAIL("HttpResponse"));
348 php_info_print_table_row(2, "Extended HTTP Requests:", HTTP_CURL_AVAIL("HttpRequest"));
349 }
350 php_info_print_table_end();
351
352 DISPLAY_INI_ENTRIES();
353 }
354 /* }}} */
355
356 /*
357 * Local variables:
358 * tab-width: 4
359 * c-basic-offset: 4
360 * End:
361 * vim600: noet sw=4 ts=4 fdm=marker
362 * vim<600: noet sw=4 ts=4
363 */
364