- solve that another way
[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-2006, 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->data = data;
34 body->size = size;
35
36 return body;
37 }
38 /* }}} */
39
40 /* {{{ http_request_body *http_request_body_fill(http_request_body *body, HashTable *, HashTable *) */
41 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)
42 {
43 if (files && (zend_hash_num_elements(files) > 0)) {
44 char *key = NULL;
45 ulong idx;
46 zval **data;
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, idx, data) {
53 if (key) {
54 CURLcode err;
55 zval *orig = *data;
56
57 convert_to_string_ex(data);
58 err = curl_formadd(&http_post_data[0], &http_post_data[1],
59 CURLFORM_COPYNAME, key,
60 CURLFORM_COPYCONTENTS, Z_STRVAL_PP(data),
61 CURLFORM_CONTENTSLENGTH, (long) Z_STRLEN_PP(data),
62 CURLFORM_END
63 );
64
65 if (orig != *data) {
66 zval_ptr_dtor(data);
67 }
68
69 if (CURLE_OK != err) {
70 http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post fields: %s", curl_easy_strerror(err));
71 curl_formfree(http_post_data[0]);
72 return NULL;
73 }
74
75 /* reset */
76 key = NULL;
77 }
78 }
79 }
80
81 /* file data */
82 FOREACH_HASH_VAL(pos, files, data) {
83 zval **file, **type, **name;
84
85 if (Z_TYPE_PP(data) != IS_ARRAY) {
86 http_error(HE_NOTICE, HTTP_E_INVALID_PARAM, "Unrecognized type of post file array entry");
87 } else if ( SUCCESS != zend_hash_find(Z_ARRVAL_PP(data), "name", sizeof("name"), (void **) &name) ||
88 SUCCESS != zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &type) ||
89 SUCCESS != zend_hash_find(Z_ARRVAL_PP(data), "file", sizeof("file"), (void **) &file)) {
90 http_error(HE_NOTICE, HTTP_E_INVALID_PARAM, "Post file array entry misses either 'name', 'type' or 'file' entry");
91 } else {
92 CURLcode err;
93 const char *path;
94 zval *ofile = *file, *otype = *type, *oname = *name;
95
96 convert_to_string_ex(file);
97 convert_to_string_ex(type);
98 convert_to_string_ex(name);
99
100 HTTP_CHECK_OPEN_BASEDIR(Z_STRVAL_PP(file), curl_formfree(http_post_data[0]); return NULL);
101
102 /* this is blatant but should be sufficient for most cases */
103 if (strncasecmp(Z_STRVAL_PP(file), "file://", lenof("file://"))) {
104 path = Z_STRVAL_PP(file);
105 } else {
106 path = Z_STRVAL_PP(file) + lenof("file://");
107 }
108
109 err = curl_formadd(&http_post_data[0], &http_post_data[1],
110 CURLFORM_COPYNAME, Z_STRVAL_PP(name),
111 CURLFORM_FILE, path,
112 CURLFORM_CONTENTTYPE, Z_STRVAL_PP(type),
113 CURLFORM_END
114 );
115
116 if (ofile != *file) zval_ptr_dtor(file);
117 if (otype != *type) zval_ptr_dtor(type);
118 if (oname != *name) zval_ptr_dtor(name);
119
120 if (CURLE_OK != err) {
121 http_error_ex(HE_WARNING, HTTP_E_ENCODING, "Could not encode post files: %s", curl_easy_strerror(err));
122 curl_formfree(http_post_data[0]);
123 return NULL;
124 }
125 }
126 }
127
128 return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CURLPOST, http_post_data[0], 0, 1);
129
130 } else if (fields) {
131 char *encoded;
132 size_t encoded_len;
133
134 if (SUCCESS != http_urlencode_hash_ex(fields, 1, NULL, 0, &encoded, &encoded_len)) {
135 http_error(HE_WARNING, HTTP_E_ENCODING, "Could not encode post data");
136 return NULL;
137 }
138
139 return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, encoded, encoded_len, 1);
140 } else {
141 return http_request_body_init_rel(body, HTTP_REQUEST_BODY_CSTRING, estrndup("", 0), 0, 1);
142 }
143 }
144
145
146 /* {{{ void http_request_body_dtor(http_request_body *) */
147 PHP_HTTP_API void _http_request_body_dtor(http_request_body *body TSRMLS_DC)
148 {
149 if (body) {
150 if (body->free) {
151 switch (body->type)
152 {
153 case HTTP_REQUEST_BODY_CSTRING:
154 if (body->data) {
155 efree(body->data);
156 }
157 break;
158
159 case HTTP_REQUEST_BODY_CURLPOST:
160 curl_formfree(body->data);
161 break;
162
163 case HTTP_REQUEST_BODY_UPLOADFILE:
164 php_stream_close(body->data);
165 break;
166 }
167 }
168 memset(body, 0, sizeof(http_request_body));
169 }
170 }
171 /* }}} */
172
173 /* {{{ void http_request_body_free(http_request_body *) */
174 PHP_HTTP_API void _http_request_body_free(http_request_body **body TSRMLS_DC)
175 {
176 if (*body) {
177 http_request_body_dtor(*body);
178 efree(*body);
179 *body = NULL;
180 }
181 }
182 /* }}} */
183
184 #endif /* HTTP_HAVE_CURL */
185
186 /*
187 * Local variables:
188 * tab-width: 4
189 * c-basic-offset: 4
190 * End:
191 * vim600: noet sw=4 ts=4 fdm=marker
192 * vim<600: noet sw=4 ts=4
193 */