avoid serialization
[m6w6/ext-http] / php_http_client_datashare.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-2011, Michael Wallner <mike@php.net> |
10 +--------------------------------------------------------------------+
11 */
12
13 #include "php_http_api.h"
14 #include "php_http_client_datashare.h"
15
16 static int php_http_client_datashare_compare_handles(void *h1, void *h2);
17
18 PHP_HTTP_API php_http_client_datashare_t *php_http_client_datashare_init(php_http_client_datashare_t *h, php_http_client_datashare_ops_t *ops, php_http_resource_factory_t *rf, void *init_arg TSRMLS_DC)
19 {
20 php_http_client_datashare_t *free_h = NULL;
21
22 if (!h) {
23 free_h = h = emalloc(sizeof(*h));
24 }
25 memset(h, sizeof(*h), 0);
26
27 zend_llist_init(&h->clients, sizeof(zval *), ZVAL_PTR_DTOR, 0);
28 h->ops = ops;
29 if (rf) {
30 h->rf = rf;
31 } else if (ops->rsrc) {
32 h->rf = php_http_resource_factory_init(NULL, h->ops->rsrc, h, NULL);
33 }
34 TSRMLS_SET_CTX(h->ts);
35
36 if (h->ops->init) {
37 if (!(h = h->ops->init(h, init_arg))) {
38 if (free_h) {
39 efree(free_h);
40 }
41 }
42 }
43
44 return h;
45 }
46
47 PHP_HTTP_API php_http_client_datashare_t *php_http_client_datashare_copy(php_http_client_datashare_t *from, php_http_client_datashare_t *to)
48 {
49 if (from->ops->copy) {
50 return from->ops->copy(from, to);
51 }
52
53 return NULL;
54 }
55
56 PHP_HTTP_API void php_http_client_datashare_dtor(php_http_client_datashare_t *h)
57 {
58 if (h->ops->dtor) {
59 h->ops->dtor(h);
60 }
61 zend_llist_destroy(&h->clients);
62 php_http_resource_factory_free(&h->rf);
63 }
64
65 PHP_HTTP_API void php_http_client_datashare_free(php_http_client_datashare_t **h)
66 {
67 php_http_client_datashare_dtor(*h);
68 efree(*h);
69 *h = NULL;
70 }
71
72 PHP_HTTP_API STATUS php_http_client_datashare_attach(php_http_client_datashare_t *h, zval *client)
73 {
74 TSRMLS_FETCH_FROM_CTX(h->ts);
75
76 if (h->ops->attach) {
77 php_http_client_object_t *obj = zend_object_store_get_object(client TSRMLS_CC);
78
79 if (SUCCESS == h->ops->attach(h, obj->client)) {
80 Z_ADDREF_P(client);
81 zend_llist_add_element(&h->clients, &client);
82 return SUCCESS;
83 }
84 }
85
86 return FAILURE;
87 }
88
89 static int php_http_client_datashare_compare_handles(void *h1, void *h2)
90 {
91 return (Z_OBJ_HANDLE_PP((zval **) h1) == Z_OBJ_HANDLE_P((zval *) h2));
92 }
93
94 PHP_HTTP_API STATUS php_http_client_datashare_detach(php_http_client_datashare_t *h, zval *client)
95 {
96 TSRMLS_FETCH_FROM_CTX(h->ts);
97
98 if (h->ops->detach) {
99 php_http_client_object_t *obj = zend_object_store_get_object(client TSRMLS_CC);
100
101 if (SUCCESS == h->ops->detach(h, obj->client)) {
102 zend_llist_del_element(&h->clients, client, php_http_client_datashare_compare_handles);
103 return SUCCESS;
104 }
105 }
106 return FAILURE;
107 }
108
109 PHP_HTTP_API STATUS php_http_client_datashare_setopt(php_http_client_datashare_t *h, php_http_client_datashare_setopt_opt_t opt, void *arg)
110 {
111 if (h->ops->setopt) {
112 return h->ops->setopt(h, opt, arg);
113 }
114 return FAILURE;
115 }
116
117 static void detach(void *r, void *h TSRMLS_DC)
118 {
119 ((php_http_client_datashare_t *) h)->ops->detach(h, ((php_http_client_object_t *) zend_object_store_get_object(*((zval **) r) TSRMLS_CC))->client);
120 }
121
122 PHP_HTTP_API void php_http_client_datashare_reset(php_http_client_datashare_t *h)
123 {
124 TSRMLS_FETCH_FROM_CTX(h->ts);
125
126 if (h->ops->reset) {
127 h->ops->reset(h);
128 } else if (h->ops->detach) {
129 zend_llist_apply_with_argument(&h->clients, detach, h TSRMLS_CC);
130 }
131
132 zend_llist_clean(&h->clients);
133 }
134
135 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpClientDataShare, method, 0, req_args)
136 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpClientDataShare, method, 0)
137 #define PHP_HTTP_RSHARE_ME(method, visibility) PHP_ME(HttpClientDataShare, method, PHP_HTTP_ARGS(HttpClientDataShare, method), visibility)
138
139 PHP_HTTP_EMPTY_ARGS(__destruct);
140 PHP_HTTP_EMPTY_ARGS(reset);
141 PHP_HTTP_EMPTY_ARGS(count);
142
143 PHP_HTTP_BEGIN_ARGS(attach, 1)
144 PHP_HTTP_ARG_OBJ(http\\Client, client, 0)
145 PHP_HTTP_END_ARGS;
146 PHP_HTTP_BEGIN_ARGS(detach, 1)
147 PHP_HTTP_ARG_OBJ(http\\Client, client, 0)
148 PHP_HTTP_END_ARGS;
149
150 static void php_http_client_datashare_object_write_prop(zval *object, zval *member, zval *value
151 #if PHP_VERSION_ID >= 50400
152 , const zend_literal *literal_key
153 #endif
154 TSRMLS_DC);
155
156 static zend_class_entry *php_http_client_datashare_class_entry;
157
158 zend_class_entry *php_http_client_datashare_get_class_entry(void)
159 {
160 return php_http_client_datashare_class_entry;
161 }
162
163 static zend_function_entry php_http_client_datashare_method_entry[] = {
164 PHP_HTTP_RSHARE_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
165 PHP_HTTP_RSHARE_ME(count, ZEND_ACC_PUBLIC)
166 PHP_HTTP_RSHARE_ME(attach, ZEND_ACC_PUBLIC)
167 PHP_HTTP_RSHARE_ME(detach, ZEND_ACC_PUBLIC)
168 PHP_HTTP_RSHARE_ME(reset, ZEND_ACC_PUBLIC)
169 EMPTY_FUNCTION_ENTRY
170 };
171
172 static zend_object_handlers php_http_client_datashare_object_handlers;
173
174 zend_object_handlers *php_http_client_datashare_get_object_handlers(void)
175 {
176 return &php_http_client_datashare_object_handlers;
177 }
178 static STATUS setopt(struct php_http_client_datashare *h, php_http_client_datashare_setopt_opt_t opt, void *arg)
179 {
180 return SUCCESS;
181 }
182
183 static php_http_client_datashare_ops_t php_http_client_datashare_user_ops = {
184 NULL,
185 NULL,
186 NULL,
187 NULL,
188 NULL,
189 NULL,
190 NULL,
191 setopt,
192 (php_http_new_t) php_http_client_datashare_object_new_ex,
193 php_http_client_datashare_get_class_entry
194
195 };
196 zend_object_value php_http_client_datashare_object_new(zend_class_entry *ce TSRMLS_DC)
197 {
198 return php_http_client_datashare_object_new_ex(ce, NULL, NULL TSRMLS_CC);
199 }
200
201 zend_object_value php_http_client_datashare_object_new_ex(zend_class_entry *ce, php_http_client_datashare_t *share, php_http_client_datashare_object_t **ptr TSRMLS_DC)
202 {
203 zend_object_value ov;
204 php_http_client_datashare_object_t *o;
205
206 o = ecalloc(1, sizeof(*o));
207 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
208 #if PHP_VERSION_ID < 50339
209 zend_hash_copy(((zend_object *) o)->properties, &(ce->default_properties), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval*));
210 #else
211 object_properties_init((zend_object *) o, ce);
212 #endif
213
214 ov.handle = zend_objects_store_put(o, NULL, php_http_client_datashare_object_free, NULL TSRMLS_CC);
215 ov.handlers = &php_http_client_datashare_object_handlers;
216
217 if (!(o->share = share)) {
218 o->share = php_http_client_datashare_init(NULL, &php_http_client_datashare_user_ops, NULL, &ov TSRMLS_CC);
219 }
220
221 if (ptr) {
222 *ptr = o;
223 }
224
225 return ov;
226 }
227
228 void php_http_client_datashare_object_free(void *object TSRMLS_DC)
229 {
230 php_http_client_datashare_object_t *o = (php_http_client_datashare_object_t *) object;
231
232 php_http_client_datashare_free(&o->share);
233 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
234 efree(o);
235 }
236
237 static void php_http_client_datashare_object_write_prop(zval *object, zval *member, zval *value
238 #if PHP_VERSION_ID >= 50400
239 , const zend_literal *literal_key
240 #endif
241 TSRMLS_DC)
242 {
243 zend_property_info *pi;
244
245 if ((pi = zend_get_property_info(php_http_client_datashare_class_entry, member, 1 TSRMLS_CC))) {
246 zend_bool enable = i_zend_is_true(value);
247 php_http_client_datashare_setopt_opt_t opt;
248 php_http_client_datashare_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
249
250 if (!strcmp(pi->name, "cookie")) {
251 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_COOKIES;
252 } else if (!strcmp(pi->name, "dns")) {
253 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_RESOLVER;
254 } else if (!strcmp(pi->name, "ssl")) {
255 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_SSLSESSIONS;
256 } else {
257 return;
258 }
259
260 if (SUCCESS != php_http_client_datashare_setopt(obj->share, opt, &enable)) {
261 return;
262 }
263 }
264
265 zend_get_std_object_handlers()->write_property(object, member, value
266 #if PHP_VERSION_ID >= 50400
267 , literal_key
268 #endif
269 TSRMLS_CC);
270 }
271
272 static zval **php_http_client_datashare_object_get_prop_ptr(zval *object, zval *member
273 #if PHP_VERSION_ID >= 50400
274 , const zend_literal *literal_key
275 #endif
276 TSRMLS_DC)
277 {
278 zend_property_info *pi;
279
280 if ((pi = zend_get_property_info(php_http_client_datashare_class_entry, member, 1 TSRMLS_CC))) {
281 return &php_http_property_proxy_init(NULL, object, member, NULL TSRMLS_CC)->myself;
282 }
283
284 return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member
285 #if PHP_VERSION_ID >= 50400
286 , literal_key
287 #endif
288 TSRMLS_CC);
289 }
290
291
292 PHP_METHOD(HttpClientDataShare, __destruct)
293 {
294 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
295 /* FIXME: move to php_http_client_datashare_dtor */
296 if (SUCCESS == zend_parse_parameters_none()) {
297 ; /* we always want to clean up */
298 }
299
300 php_http_client_datashare_reset(obj->share);
301 }
302
303 PHP_METHOD(HttpClientDataShare, count)
304 {
305 if (SUCCESS == zend_parse_parameters_none()) {
306 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
307
308 RETURN_LONG(zend_llist_count(&obj->share->clients));
309 }
310 RETURN_FALSE;
311 }
312
313
314 PHP_METHOD(HttpClientDataShare, attach)
315 {
316 zval *client;
317
318 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &client, php_http_client_get_class_entry())) {
319 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
320
321 RETURN_SUCCESS(php_http_client_datashare_attach(obj->share, client));
322 }
323 RETURN_FALSE;
324
325 }
326
327 PHP_METHOD(HttpClientDataShare, detach)
328 {
329 zval *client;
330
331 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &client, php_http_client_get_class_entry())) {
332 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
333
334 RETURN_SUCCESS(php_http_client_datashare_detach(obj->share, client));
335 }
336 RETURN_FALSE;
337 }
338
339 PHP_METHOD(HttpClientDataShare, reset)
340 {
341 if (SUCCESS == zend_parse_parameters_none()) {
342 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
343
344 php_http_client_datashare_reset(obj->share);
345 RETURN_TRUE;
346 }
347 RETURN_FALSE;
348 }
349
350 PHP_METHOD(HttpClientDataShare, __sleep)
351 {
352 php_http_error(HE_THROW, PHP_HTTP_E_CLIENT_DATASHARE, "cannot serialize a client datashare");
353 }
354
355 PHP_MINIT_FUNCTION(http_client_datashare)
356 {
357 PHP_HTTP_REGISTER_CLASS(http\\Client\\DataShare, AbstractDataShare, http_client_datashare, php_http_object_get_class_entry(), ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
358 php_http_client_datashare_class_entry->create_object = php_http_client_datashare_object_new;
359 memcpy(&php_http_client_datashare_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
360 php_http_client_datashare_object_handlers.clone_obj = NULL;
361 php_http_client_datashare_object_handlers.write_property = php_http_client_datashare_object_write_prop;
362 php_http_client_datashare_object_handlers.get_property_ptr_ptr = php_http_client_datashare_object_get_prop_ptr;
363
364 zend_class_implements(php_http_client_datashare_class_entry TSRMLS_CC, 1, spl_ce_Countable);
365
366 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("cookie"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
367 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("dns"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
368 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("ssl"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
369
370 return SUCCESS;
371 }
372
373 /*
374 * Local variables:
375 * tab-width: 4
376 * c-basic-offset: 4
377 * End:
378 * vim600: noet sw=4 ts=4 fdm=marker
379 * vim<600: noet sw=4 ts=4
380 */
381