fix leaks
[m6w6/ext-http] / php_http_client_request.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-2014, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14
15 void php_http_client_options_set_subr(zval *this_ptr, char *key, size_t len, zval *opts, int overwrite);
16 void php_http_client_options_set(zval *this_ptr, zval *opts);
17 void php_http_client_options_get_subr(zval *this_ptr, char *key, size_t len, zval *return_value);
18
19 #define PHP_HTTP_CLIENT_REQUEST_OBJECT_INIT(obj) \
20 do { \
21 if (!obj->message) { \
22 obj->message = php_http_message_init(NULL, PHP_HTTP_REQUEST, NULL); \
23 } \
24 } while(0)
25
26 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest___construct, 0, 0, 0)
27 ZEND_ARG_INFO(0, method)
28 ZEND_ARG_INFO(0, url)
29 ZEND_ARG_ARRAY_INFO(0, headers, 1)
30 ZEND_ARG_OBJ_INFO(0, body, http\\Message\\Body, 1)
31 ZEND_END_ARG_INFO();
32 static PHP_METHOD(HttpClientRequest, __construct)
33 {
34 char *meth_str = NULL;
35 size_t meth_len = 0;
36 zval *zheaders = NULL, *zbody = NULL, *zurl = NULL;
37 php_http_message_object_t *obj;
38
39 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|s!z!a!O!", &meth_str, &meth_len, &zurl, &zheaders, &zbody, php_http_message_body_class_entry), invalid_arg, return);
40
41 obj = PHP_HTTP_OBJ(NULL, getThis());
42
43 if (obj->message) {
44 php_http_message_set_type(obj->message, PHP_HTTP_REQUEST);
45 } else {
46 obj->message = php_http_message_init(NULL, PHP_HTTP_REQUEST, NULL);
47 }
48
49 if (zbody) {
50 php_http_expect(SUCCESS == php_http_message_object_set_body(obj, zbody), unexpected_val, return);
51 }
52 if (meth_str && meth_len) {
53 PHP_HTTP_INFO(obj->message).request.method = estrndup(meth_str, meth_len);
54 }
55 if (zurl) {
56 PHP_HTTP_INFO(obj->message).request.url = php_http_url_from_zval(zurl, ~0);
57 }
58 if (zheaders) {
59 array_copy(Z_ARRVAL_P(zheaders), &obj->message->hdrs);
60 }
61 }
62
63 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_setContentType, 0, 0, 1)
64 ZEND_ARG_INFO(0, content_type)
65 ZEND_END_ARG_INFO();
66 static PHP_METHOD(HttpClientRequest, setContentType)
67 {
68 zend_string *ct_str;
69 php_http_message_object_t *obj;
70 zval zct;
71
72 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "S", &ct_str), invalid_arg, return);
73
74 if (ct_str->len && !strchr(ct_str->val, '/')) {
75 php_http_throw(unexpected_val, "Content type \"%s\" does not seem to contain a primary and a secondary part", ct_str->val);
76 return;
77 }
78
79 obj = PHP_HTTP_OBJ(NULL, getThis());
80 PHP_HTTP_CLIENT_REQUEST_OBJECT_INIT(obj);
81
82 ZVAL_STR_COPY(&zct, ct_str);
83 zend_hash_str_update(&obj->message->hdrs, "Content-Type", lenof("Content-Type"), &zct);
84
85 RETVAL_ZVAL(getThis(), 1, 0);
86 }
87
88 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_getContentType, 0, 0, 0)
89 ZEND_END_ARG_INFO();
90 static PHP_METHOD(HttpClientRequest, getContentType)
91 {
92 if (SUCCESS == zend_parse_parameters_none()) {
93 php_http_message_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
94 zval *zct;
95
96 PHP_HTTP_CLIENT_REQUEST_OBJECT_INIT(obj);
97
98 php_http_message_update_headers(obj->message);
99 zct = php_http_message_header(obj->message, ZEND_STRL("Content-Type"));
100 if (zct) {
101 RETURN_ZVAL(zct, 1, 0);
102 }
103 }
104 }
105
106 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_setQuery, 0, 0, 0)
107 ZEND_ARG_INFO(0, query_data)
108 ZEND_END_ARG_INFO();
109 static PHP_METHOD(HttpClientRequest, setQuery)
110 {
111 zval *qdata = NULL, arr, str;
112 php_http_message_object_t *obj;
113 php_http_url_t *old_url = NULL, new_url = {NULL};
114 unsigned flags = PHP_HTTP_URL_REPLACE;
115
116 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z!", &qdata), invalid_arg, return);
117
118 obj = PHP_HTTP_OBJ(NULL, getThis());
119 PHP_HTTP_CLIENT_REQUEST_OBJECT_INIT(obj);
120
121 ZVAL_NULL(&str);
122 if (qdata) {
123 array_init(&arr);
124
125 php_http_expect(SUCCESS == php_http_querystring_update(&arr, qdata, &str), bad_querystring,
126 zval_dtor(&arr);
127 return;
128 );
129
130 new_url.query = Z_STRVAL(str);
131 zval_dtor(&arr);
132 } else {
133 flags = PHP_HTTP_URL_STRIP_QUERY;
134 }
135
136 if (obj->message->http.info.request.url) {
137 old_url = obj->message->http.info.request.url;
138 }
139
140 obj->message->http.info.request.url = php_http_url_mod(old_url, &new_url, flags);
141
142 if (old_url) {
143 php_http_url_free(&old_url);
144 }
145 zval_ptr_dtor(&str);
146
147 RETVAL_ZVAL(getThis(), 1, 0);
148 }
149
150 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_getQuery, 0, 0, 0)
151 ZEND_END_ARG_INFO();
152 static PHP_METHOD(HttpClientRequest, getQuery)
153 {
154 if (SUCCESS == zend_parse_parameters_none()) {
155 php_http_message_object_t *obj = PHP_HTTP_OBJ(NULL, getThis());
156
157 PHP_HTTP_CLIENT_REQUEST_OBJECT_INIT(obj);
158
159 if (obj->message->http.info.request.url && obj->message->http.info.request.url->query) {
160 RETVAL_STRING(obj->message->http.info.request.url->query);
161 }
162 }
163 }
164
165 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_addQuery, 0, 0, 1)
166 ZEND_ARG_INFO(0, query_data)
167 ZEND_END_ARG_INFO();
168 static PHP_METHOD(HttpClientRequest, addQuery)
169 {
170 zval *qdata, arr, str;
171 php_http_message_object_t *obj;
172 php_http_url_t *old_url = NULL, new_url = {NULL};
173
174 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "z", &qdata), invalid_arg, return);
175
176 obj = PHP_HTTP_OBJ(NULL, getThis());
177 PHP_HTTP_CLIENT_REQUEST_OBJECT_INIT(obj);
178
179 array_init(&arr);
180 ZVAL_NULL(&str);
181
182 php_http_expect(SUCCESS == php_http_querystring_update(&arr, qdata, &str), bad_querystring,
183 zval_dtor(&arr);
184 return;
185 );
186 new_url.query = Z_STRVAL(str);
187 zval_dtor(&arr);
188
189 if (obj->message->http.info.request.url) {
190 old_url = obj->message->http.info.request.url;
191 }
192
193 obj->message->http.info.request.url = php_http_url_mod(old_url, &new_url, PHP_HTTP_URL_JOIN_QUERY);
194
195 if (old_url) {
196 php_http_url_free(&old_url);
197 }
198 zval_ptr_dtor(&str);
199
200 RETVAL_ZVAL(getThis(), 1, 0);
201 }
202
203 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_setOptions, 0, 0, 0)
204 ZEND_ARG_ARRAY_INFO(0, options, 1)
205 ZEND_END_ARG_INFO();
206 static PHP_METHOD(HttpClientRequest, setOptions)
207 {
208 zval *opts = NULL;
209
210 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
211
212 php_http_client_options_set(getThis(), opts);
213
214 RETVAL_ZVAL(getThis(), 1, 0);
215 }
216
217 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_getOptions, 0, 0, 0)
218 ZEND_END_ARG_INFO();
219 static PHP_METHOD(HttpClientRequest, getOptions)
220 {
221 if (SUCCESS == zend_parse_parameters_none()) {
222 zval tmp, *zoptions = zend_read_property(php_http_client_request_class_entry, getThis(), ZEND_STRL("options"), 0, &tmp);
223 RETURN_ZVAL(zoptions, 1, 0);
224 }
225 }
226
227 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_setSslOptions, 0, 0, 0)
228 ZEND_ARG_ARRAY_INFO(0, ssl_options, 1)
229 ZEND_END_ARG_INFO();
230 static PHP_METHOD(HttpClientRequest, setSslOptions)
231 {
232 zval *opts = NULL;
233
234 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
235
236 php_http_client_options_set_subr(getThis(), ZEND_STRL("ssl"), opts, 1);
237
238 RETVAL_ZVAL(getThis(), 1, 0);
239 }
240
241 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_addSslOptions, 0, 0, 0)
242 ZEND_ARG_ARRAY_INFO(0, ssl_options, 1)
243 ZEND_END_ARG_INFO();
244 static PHP_METHOD(HttpClientRequest, addSslOptions)
245 {
246 zval *opts = NULL;
247
248 php_http_expect(SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS(), "|a!/", &opts), invalid_arg, return);
249
250 php_http_client_options_set_subr(getThis(), ZEND_STRL("ssl"), opts, 0);
251
252 RETVAL_ZVAL(getThis(), 1, 0);
253 }
254
255 ZEND_BEGIN_ARG_INFO_EX(ai_HttpClientRequest_getSslOptions, 0, 0, 0)
256 ZEND_END_ARG_INFO();
257 static PHP_METHOD(HttpClientRequest, getSslOptions)
258 {
259 if (SUCCESS == zend_parse_parameters_none()) {
260 php_http_client_options_get_subr(getThis(), ZEND_STRL("ssl"), return_value);
261 }
262 }
263
264 static zend_function_entry php_http_client_request_methods[] = {
265 PHP_ME(HttpClientRequest, __construct, ai_HttpClientRequest___construct, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
266 PHP_ME(HttpClientRequest, setContentType, ai_HttpClientRequest_setContentType, ZEND_ACC_PUBLIC)
267 PHP_ME(HttpClientRequest, getContentType, ai_HttpClientRequest_getContentType, ZEND_ACC_PUBLIC)
268 PHP_ME(HttpClientRequest, setQuery, ai_HttpClientRequest_setQuery, ZEND_ACC_PUBLIC)
269 PHP_ME(HttpClientRequest, getQuery, ai_HttpClientRequest_getQuery, ZEND_ACC_PUBLIC)
270 PHP_ME(HttpClientRequest, addQuery, ai_HttpClientRequest_addQuery, ZEND_ACC_PUBLIC)
271 PHP_ME(HttpClientRequest, setOptions, ai_HttpClientRequest_setOptions, ZEND_ACC_PUBLIC)
272 PHP_ME(HttpClientRequest, getOptions, ai_HttpClientRequest_getOptions, ZEND_ACC_PUBLIC)
273 PHP_ME(HttpClientRequest, setSslOptions, ai_HttpClientRequest_setSslOptions, ZEND_ACC_PUBLIC)
274 PHP_ME(HttpClientRequest, getSslOptions, ai_HttpClientRequest_getSslOptions, ZEND_ACC_PUBLIC)
275 PHP_ME(HttpClientRequest, addSslOptions, ai_HttpClientRequest_addSslOptions, ZEND_ACC_PUBLIC)
276 EMPTY_FUNCTION_ENTRY
277 };
278
279 zend_class_entry *php_http_client_request_class_entry;
280
281 PHP_MINIT_FUNCTION(http_client_request)
282 {
283 zend_class_entry ce = {0};
284
285 INIT_NS_CLASS_ENTRY(ce, "http\\Client", "Request", php_http_client_request_methods);
286 php_http_client_request_class_entry = zend_register_internal_class_ex(&ce, php_http_message_class_entry);
287
288 zend_declare_property_null(php_http_client_request_class_entry, ZEND_STRL("options"), ZEND_ACC_PROTECTED);
289
290 return SUCCESS;
291 }
292
293 /*
294 * Local variables:
295 * tab-width: 4
296 * c-basic-offset: 4
297 * End:
298 * vim600: noet sw=4 ts=4 fdm=marker
299 * vim<600: noet sw=4 ts=4
300 */
301