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