2 +--------------------------------------------------------------------+
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-2005, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
19 #define HTTP_WANT_CURL
22 #if defined(HTTP_HAVE_CURL) && defined(HTTP_HAVE_WRAPPER)
24 #include "php_streams.h"
26 #include "php_http_api.h"
27 #include "php_http_wrapper_api.h"
28 #include "php_http_request_api.h"
29 #include "php_http_headers_api.h"
30 #include "php_http_message_api.h"
31 #include "php_http_url_api.h"
33 ZEND_EXTERN_MODULE_GLOBALS(http
);
40 static php_stream_ops http_stream_ops
;
42 PHP_MINIT_FUNCTION(http_wrapper
)
44 php_unregister_url_stream_wrapper("http" TSRMLS_CC
);
45 return php_register_url_stream_wrapper("http", &http_wrapper TSRMLS_CC
);
48 php_stream
*http_wrapper_ex(php_stream_wrapper
*wrapper
, char *path
, char *mode
, int options
, char **opened_path
, php_stream_context
*context STREAMS_DC TSRMLS_DC
)
50 zval opt_array
, **opt_elem
, *ssl_opt
;
54 if (strpbrk(mode
, "awx+")) {
55 php_stream_wrapper_log_error(wrapper
, options TSRMLS_CC
, "HTTP wrapper does not support writeable connections.");
59 INIT_PZVAL(&opt_array
);
60 array_init(&opt_array
);
62 http_request_init(&request
);
63 request
.url
= estrdup(path
);
70 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "method", &opt_elem
)) {
71 switch (Z_TYPE_PP(opt_elem
))
74 if (http_request_method_exists(0, Z_LVAL_PP(opt_elem
), NULL
)) {
75 request
.meth
= Z_LVAL_PP(opt_elem
);
81 zval
*orig
= *opt_elem
;
82 convert_to_string_ex(opt_elem
);
83 if ((method
= http_request_method_exists(1, 0, Z_STRVAL_PP(opt_elem
)))) {
84 request
.meth
= method
;
86 if (orig
!= *opt_elem
) zval_ptr_dtor(opt_elem
);
93 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "header", &opt_elem
)) {
94 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
97 MAKE_STD_ZVAL(headers
);
99 if (SUCCESS
== http_parse_headers(Z_STRVAL_PP(opt_elem
), headers
)) {
100 add_assoc_zval(&opt_array
, "headers", headers
);
102 zval_ptr_dtor(&headers
);
108 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "user_agent", &opt_elem
)) {
109 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
110 add_assoc_stringl(&opt_array
, "useragent", Z_STRVAL_PP(opt_elem
), Z_STRLEN_PP(opt_elem
), 1);
115 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "proxy", &opt_elem
)) {
116 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
117 if (strstr(Z_STRVAL_PP(opt_elem
), "://")) {
118 if (!strncasecmp(Z_STRVAL_PP(opt_elem
), "tcp://", lenof("tcp://"))) {
122 phpstr_appends(&proxy
, "http://");
123 phpstr_append(&proxy
, Z_STRVAL_PP(opt_elem
)+lenof("tcp://"), Z_STRLEN_PP(opt_elem
)-lenof("tcp://"));
126 add_assoc_stringl(&opt_array
, "proxy", PHPSTR_VAL(&proxy
), PHPSTR_LEN(&proxy
), 0);
129 ZVAL_ADDREF(*opt_elem
);
130 add_assoc_zval(&opt_array
, "proxy", *opt_elem
);
136 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "max_redirects", &opt_elem
)) {
137 zval
*orig
= *opt_elem
;
139 convert_to_long_ex(opt_elem
);
140 if (0 < Z_LVAL_PP(opt_elem
)) {
141 add_assoc_long(&opt_array
, "redirect", Z_LVAL_PP(opt_elem
)-1);
143 if (orig
!= *opt_elem
) {
144 zval_ptr_dtor(opt_elem
);
149 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "content", &opt_elem
)) {
150 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
151 request
.body
= http_request_body_init_ex(request
.body
, HTTP_REQUEST_BODY_CSTRING
,
152 estrndup(Z_STRVAL_PP(opt_elem
), Z_STRLEN_PP(opt_elem
)), Z_STRLEN_PP(opt_elem
), 1);
160 MAKE_STD_ZVAL(ssl_opt
);
164 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "verify_peer", &opt_elem
)) {
165 if (zval_is_true(*opt_elem
)) {
166 add_assoc_bool(ssl_opt
, "verifypeer", 1);
171 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "cafile", &opt_elem
)) {
172 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
173 ZVAL_ADDREF(*opt_elem
);
174 add_assoc_zval(ssl_opt
, "cainfo", *opt_elem
);
179 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "capath", &opt_elem
)) {
180 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
181 ZVAL_ADDREF(*opt_elem
);
182 add_assoc_zval(ssl_opt
, "capath", *opt_elem
);
187 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "local_cert", &opt_elem
)) {
188 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
191 ZVAL_ADDREF(*opt_elem
);
192 add_assoc_zval(ssl_opt
, "cert", *opt_elem
);
194 if (SUCCESS
== php_stream_context_get_option(context
, wrapper
->wops
->label
, "passphrase", &opt_elem
)) {
195 if (Z_TYPE_PP(opt_elem
) == IS_STRING
&& Z_STRLEN_PP(opt_elem
)) {
196 ZVAL_ADDREF(*opt_elem
);
197 add_assoc_zval(ssl_opt
, "certpasswd", *opt_elem
);
203 add_assoc_zval(&opt_array
, "ssl", ssl_opt
);
205 if (SUCCESS
== http_request_prepare(&request
, Z_ARRVAL(opt_array
))) {
208 http_request_exec(&request
);
212 if (CURLE_OK
== curl_easy_getinfo(request
.ch
, CURLINFO_EFFECTIVE_URL
, &url
) && url
) {
213 *opened_path
= estrdup(url
);
219 if ((msg
= http_message_parse(PHPSTR_VAL(&request
.conv
.response
), PHPSTR_LEN(&request
.conv
.response
)))) {
220 http_wrapper_t
*w
= emalloc(sizeof(http_wrapper_t
));
224 phpstr_append(&w
->b
, PHPSTR_VAL(&msg
->body
), PHPSTR_LEN(&msg
->body
));
226 stream
= php_stream_alloc(&http_stream_ops
, w
, NULL
, mode
);
228 http_message_free(&msg
);
232 http_request_dtor(&request
);
234 zval_dtor(&opt_array
);
238 static size_t http_wrapper_write(php_stream
*stream
, const char *buf
, size_t count TSRMLS_DC
)
243 static size_t http_wrapper_read(php_stream
*stream
, char *buf
, size_t count TSRMLS_DC
)
245 http_wrapper_t
*w
= (http_wrapper_t
*) stream
->abstract
;
246 size_t len
= MIN(count
, w
->b
.used
- w
->p
);
249 memcpy(buf
, w
->b
.data
+ w
->p
, len
);
256 static int http_wrapper_close(php_stream
*stream
, int close_handle TSRMLS_DC
)
258 phpstr_dtor(&((http_wrapper_t
*)stream
->abstract
)->b
);
259 efree(stream
->abstract
);
260 stream
->abstract
= NULL
;
264 static int http_wrapper_flush(php_stream
*stream TSRMLS_DC
)
269 static int http_wrapper_seek(php_stream
*stream
, off_t offset
, int whence
, off_t
*newoffset TSRMLS_DC
)
271 http_wrapper_t
*w
= (http_wrapper_t
*) stream
->abstract
;
279 if (offset
< 0 || offset
> w
->b
.used
) {
286 o
= w
->b
.used
+ offset
;
287 if (o
< 0 || o
> w
->b
.used
) {
295 if (o
< 0 || o
> w
->b
.used
) {
311 static php_stream_ops http_stream_ops
= {
323 static php_stream_wrapper_ops http_wrapper_ops
= {
336 PHP_HTTP_API php_stream_wrapper http_wrapper
= {
342 #endif /* HTTP_HAVE_CURL */
349 * vim600: noet sw=4 ts=4 fdm=marker
350 * vim<600: noet sw=4 ts=4