Fixed bug #15800
[m6w6/ext-http] / http_request_body_api.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-2007, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 /* $Id$ */
14
15 #define HTTP_WANT_CURL
16 #include "php_http.h"
17
18 #ifdef HTTP_HAVE_CURL
19
20 #include "php_http_api.h"
21 #include "php_http_url_api.h"
22 #include "php_http_request_body_api.h"
23
24 /* {{{ http_request_body *http_request_body_new() */
25 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)
26 {
27 if (!body) {
28 body = emalloc_rel(sizeof(http_request_body));
29 }
30
31 body->type = type;
32 body->free = free;
33 body->priv = 0;
34 body->data = data;
35 body->size = size;
36
37 return body;
38 }
39 /* }}} */
40
41 /* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */
42 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)
43 {
44 if (files && (zend_hash_num_elements(files) > 0)) {
45 HashKey key = initHashKey(0);
46 zval **data_ptr;
47 HashPosition pos;
48 struct curl_httppost *http_post_data[2] = {NULL, NULL};
49
50 /* normal data */
51 if (fields) {
52 FOREACH_HASH_KEYVAL(pos, fields, key, data_ptr) {
53 if (key.type == HASH_KEY_IS_STRING) {
54 CURLcode err;
55 zval *data = http_zsep(IS_STRING, *data_ptr);
56
57 err = curl_formadd(&http_post_data[0], &http_post_data[1],
58 CURLFORM_COPYNAME, key.str,
59 CURLFORM_COPYCONTENTS, Z_STRVAL_P(data),
60 CURLFORM_CONTENTSLENGTH, (long) Z_STRLEN_P(data),
61 CURLFORM_END
62 );
63
64 zval_ptr_dtor(&data);
65
66 if (CURLE_OK != err) {
67 http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err));
68 curl_formfree(http_post_data[0]);
69 return NULL;
70 }
71 }
72 }
73 }
74
75 /* file data */
76 FOREACH_HASH_VAL(pos, files, data_ptr) {
77 zval **file_ptr, **type_ptr, **name_ptr;
78
79 if (Z_TYPE_PP(data_ptr) != IS_ARRAY) {
80 http_error(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry");
81 } else if ( SUCCESS != zend_hash_find(Z_ARRVAL_PP(data_ptr), "name", sizeof("name"), (void *) &name_ptr) ||
82 SUCCESS != zend_hash_find(Z_ARRVAL_PP(data_ptr), "type", sizeof("type"), (void *) &type_ptr) ||
83 SUCCESS != zend_hash_find(Z_ARRVAL_PP(data_ptr), "file", sizeof("file"), (void *) &file_ptr)) {
84 http_error(HE_NOTICE, HTTP_E_INVALID_PARAM, "Post file array entry misses either 'name', 'type' or 'file' entry");
85 } else {
86 CURLcode err;
87 const char *path;
88 zval *file = http_zsep(IS_STRING, *file_ptr);
89 zval *type = http_zsep(IS_STRING, *type_ptr);
90 zval *name = http_zsep(IS_STRING, *name_ptr);
91
92 HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_P(file), curl_formfree(http_post_data[0]); return NULL);
93
94 /* this is blatant but should be sufficient for most cases */
95 if (strncasecmp(Z_STRVAL_P(file), "file://", lenof("file://"))) {
96 path = Z_STRVAL_P(file);
97 } else {
98 path = Z_STRVAL_P(file) + lenof("file://");
99 }
100
101 err = curl_formadd(&http_post_data[0], &http_post_data[1],
102 CURLFORM_COPYNAME, Z_STRVAL_P(name),
103 CURLFORM_FILE, path,
104 CURLFORM_CONTENTTYPE, Z_STRVAL_P(type),
105 CURLFORM_END
106 );
107
108 zval_ptr_dtor(&file);
109 zval_ptr_dtor(&type);
110 zval_ptr_dtor(&name);
111
112 if (CURLE_OK != err) {
113 http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err));
114 curl_formfree(http_post_data[0]);
115 return NULL;
116 }
117 }
118 }
119
120 return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CURLPOST, http_post_data[0], 0, 1);
121
122 } else if (fields) {
123 char *encoded;
124 size_t encoded_len;
125
126 if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) {
127 http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data");
128 return NULL;
129 }
130
131 return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, encoded, encoded_len, 1);
132 } else {
133 return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, estrndup("", 0), 0, 1);
134 }
135 }
136
137 /* STATUS http_request_body_encode(http_request_body *, char**, size_t *) */
138 PHP_HTTP_API STATUS _http_request_body_encode(http_request_body *body, char **buf, size_t *len TSRMLS_DC)
139 {
140 switch (body->type) {
141 case HTTP_REQUEST_BODY_CURLPOST:
142 {
143 #ifdef HAVE_CURL_FORMGET
144 phpstr str;
145
146 phpstr_init_ex(&str, 0x8000, 0);
147 if (curl_formget(body->data, &str, (curl_formget_callback) phpstr_append)) {
148 phpstr_dtor(&str);
149 } else {
150 phpstr_fix(&str);
151 *buf = PHPSTR_VAL(&str);
152 *len = PHPSTR_LEN(&str);
153 return SUCCESS;
154 }
155 #endif
156 break;
157 }
158
159 case HTTP_REQUEST_BODY_CSTRING:
160 *buf = estrndup(body->data, *len = body->size);
161 return SUCCESS;
162
163 default:
164 break;
165 }
166 return FAILURE;
167 }
168 /* }}} */
169
170 /* {{{ void http_request_body_dtor(http_request_body *) */
171 PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC)
172 {
173 if (body) {
174 if (body->free) {
175 switch (body->type) {
176 case HTTP_REQUEST_BODY_CSTRING:
177 if (body->data) {
178 efree(body->data);
179 }
180 break;
181
182 case HTTP_REQUEST_BODY_CURLPOST:
183 curl_formfree(body->data);
184 break;
185
186 case HTTP_REQUEST_BODY_UPLOADFILE:
187 php_stream_close(body->data);
188 break;
189 }
190 }
191 memset(body, 0, sizeof(http_request_body));
192 }
193 }
194 /* }}} */
195
196 /* {{{ void http_request_body_free(http_request_body *) */
197 PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC)
198 {
199 if (*body) {
200 http_request_body_dtor(*body);
201 efree(*body);
202 *body = NULL;
203 }
204 }
205 /* }}} */
206
207 #endif /* HTTP_HAVE_CURL */
208
209 /*
210 * Local variables:
211 * tab-width: 4
212 * c-basic-offset: 4
213 * End:
214 * vim600: noet sw=4 ts=4 fdm=marker
215 * vim<600: noet sw=4 ts=4
216 */