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-2006, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
15 #define HTTP_WANT_CURL
20 #include "php_http_api.h"
21 #include "php_http_url_api.h"
22 #include "php_http_request_body_api.h"
24 #if defined(HAVE_CURL_GETFORMDATA) && !defined(HAVE_CURL_FORMGET)
26 struct FormData
*next
;
32 CURLcode
Curl_getFormData(struct FormData
**, struct curl_httppost
*post
, curl_off_t
*size
);
34 static char *file_get_contents(char *file
, size_t *len TSRMLS_DC
)
39 if ((s
= php_stream_open_wrapper_ex(file
, "rb", REPORT_ERRORS
|ENFORCE_SAFE_MODE
, NULL
, HTTP_DEFAULT_STREAM_CONTEXT
))) {
40 *len
= php_stream_copy_to_mem(s
, &buf
, (size_t) -1, 0);
48 static int curl_formget(struct FormData
*post
, phpstr
*str TSRMLS_DC
)
53 struct FormData
*next
, *pptr
= post
;
60 if ((fdata
= file_get_contents(pptr
->line
, &fsize TSRMLS_CC
))) {
61 phpstr_append(str
, fdata
, fsize
);
67 phpstr_append(str
, pptr
->line
, pptr
->length
);
71 curl_free(pptr
->line
);
81 /* {{{ http_request_body *http_request_body_new() */
82 PHP_HTTP_API http_request_body
*_http_request_body_init_ex(http_request_body
*body
, int type
, void *data
, size_t size
, zend_bool free ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC
)
85 body
= emalloc_rel(sizeof(http_request_body
));
98 /* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */
99 PHP_HTTP_API http_request_body
*_http_request_body_fill(http_request_body
*body
, HashTable
*fields
, HashTable
*files ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC TSRMLS_DC
)
101 if (files
&& (zend_hash_num_elements(files
) > 0)) {
102 HashKey key
= initHashKey(0);
105 struct curl_httppost
*http_post_data
[2] = {NULL
, NULL
};
109 FOREACH_HASH_KEYVAL(pos
, fields
, key
, data
) {
110 if (key
.type
== HASH_KEY_IS_STRING
) {
114 convert_to_string_ex(data
);
115 err
= curl_formadd(&http_post_data
[0], &http_post_data
[1],
116 CURLFORM_COPYNAME
, key
.str
,
117 CURLFORM_COPYCONTENTS
, Z_STRVAL_PP(data
),
118 CURLFORM_CONTENTSLENGTH
, (long) Z_STRLEN_PP(data
),
126 if (CURLE_OK
!= err
) {
127 http_error_ex(HE_WARNING
, HTTP_E_ENCODING
, "Could not encode post fields: %s", curl_easy_strerror(err
));
128 curl_formfree(http_post_data
[0]);
136 FOREACH_HASH_VAL(pos
, files
, data
) {
137 zval
**file
, **type
, **name
;
139 if (Z_TYPE_PP(data
) != IS_ARRAY
) {
140 http_error(HE_NOTICE
, HTTP_E_INVALID_PARAM
, "Unrecognized type of post file array entry");
141 } else if ( SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(data
), "name", sizeof("name"), (void *) &name
) ||
142 SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(data
), "type", sizeof("type"), (void *) &type
) ||
143 SUCCESS
!= zend_hash_find(Z_ARRVAL_PP(data
), "file", sizeof("file"), (void *) &file
)) {
144 http_error(HE_NOTICE
, HTTP_E_INVALID_PARAM
, "Post file array entry misses either 'name', 'type' or 'file' entry");
148 zval
*ofile
= *file
, *otype
= *type
, *oname
= *name
;
150 convert_to_string_ex(file
);
151 convert_to_string_ex(type
);
152 convert_to_string_ex(name
);
154 HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(file
), curl_formfree(http_post_data
[0]); return NULL
);
156 /* this is blatant but should be sufficient for most cases */
157 if (strncasecmp(Z_STRVAL_PP(file
), "file://", lenof("file://"))) {
158 path
= Z_STRVAL_PP(file
);
160 path
= Z_STRVAL_PP(file
) + lenof("file://");
163 err
= curl_formadd(&http_post_data
[0], &http_post_data
[1],
164 CURLFORM_COPYNAME
, Z_STRVAL_PP(name
),
166 CURLFORM_CONTENTTYPE
, Z_STRVAL_PP(type
),
170 if (ofile
!= *file
) zval_ptr_dtor(file
);
171 if (otype
!= *type
) zval_ptr_dtor(type
);
172 if (oname
!= *name
) zval_ptr_dtor(name
);
174 if (CURLE_OK
!= err
) {
175 http_error_ex(HE_WARNING
, HTTP_E_ENCODING
, "Could not encode post files: %s", curl_easy_strerror(err
));
176 curl_formfree(http_post_data
[0]);
182 return http_request_body_init_rel(body
, HTTP_REQUEST_BODY_CURLPOST
, http_post_data
[0], 0, 1);
188 if (SUCCESS
!= http_urlencode_hash_ex(fields
, 1, NULL
, 0, &encoded
, &encoded_len
)) {
189 http_error(HE_WARNING
, HTTP_E_ENCODING
, "Could not encode post data");
193 return http_request_body_init_rel(body
, HTTP_REQUEST_BODY_CSTRING
, encoded
, encoded_len
, 1);
195 return http_request_body_init_rel(body
, HTTP_REQUEST_BODY_CSTRING
, estrndup("", 0), 0, 1);
199 /* STATUS http_request_body_encode(http_request_body *, char**, size_t *) */
200 PHP_HTTP_API STATUS
_http_request_body_encode(http_request_body
*body
, char **buf
, size_t *len TSRMLS_DC
)
202 switch (body
->type
) {
203 case HTTP_REQUEST_BODY_CURLPOST
:
205 #if defined(HAVE_CURL_FORMGET)
208 phpstr_init_ex(&str
, 0x8000, 0);
209 if (curl_formget(body
->data
, &str
, (curl_formget_callback
) phpstr_append
)) {
213 *buf
= PHPSTR_VAL(&str
);
214 *len
= PHPSTR_LEN(&str
);
217 #elif defined(HAVE_CURL_GETFORMDATA)
218 struct FormData
*data
;
221 if (!Curl_getFormData(&data
, body
->data
, &size
)) {
224 phpstr_init_ex(&str
, (size_t) size
, 0);
225 if (curl_formget(data
, &str TSRMLS_CC
)) {
229 *buf
= PHPSTR_VAL(&str
);
230 *len
= PHPSTR_LEN(&len
);
238 case HTTP_REQUEST_BODY_CSTRING
:
239 *buf
= estrndup(body
->data
, *len
= body
->size
);
249 /* {{{ void http_request_body_dtor(http_request_body *) */
250 PHP_HTTP_API
void _http_request_body_dtor(http_request_body
*body TSRMLS_DC
)
254 switch (body
->type
) {
255 case HTTP_REQUEST_BODY_CSTRING
:
261 case HTTP_REQUEST_BODY_CURLPOST
:
262 curl_formfree(body
->data
);
265 case HTTP_REQUEST_BODY_UPLOADFILE
:
266 php_stream_close(body
->data
);
270 memset(body
, 0, sizeof(http_request_body
));
275 /* {{{ void http_request_body_free(http_request_body *) */
276 PHP_HTTP_API
void _http_request_body_free(http_request_body
**body TSRMLS_DC
)
279 http_request_body_dtor(*body
);
286 #endif /* HTTP_HAVE_CURL */
293 * vim600: noet sw=4 ts=4 fdm=marker
294 * vim<600: noet sw=4 ts=4