extesion deps
[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_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, 0, sizeof(*h));
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_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_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 PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC);
151
152 static zend_class_entry *php_http_client_datashare_class_entry;
153
154 zend_class_entry *php_http_client_datashare_get_class_entry(void)
155 {
156 return php_http_client_datashare_class_entry;
157 }
158
159 static zend_function_entry php_http_client_datashare_method_entry[] = {
160 PHP_HTTP_RSHARE_ME(__destruct, ZEND_ACC_PUBLIC|ZEND_ACC_DTOR)
161 PHP_HTTP_RSHARE_ME(count, ZEND_ACC_PUBLIC)
162 PHP_HTTP_RSHARE_ME(attach, ZEND_ACC_PUBLIC)
163 PHP_HTTP_RSHARE_ME(detach, ZEND_ACC_PUBLIC)
164 PHP_HTTP_RSHARE_ME(reset, ZEND_ACC_PUBLIC)
165 EMPTY_FUNCTION_ENTRY
166 };
167
168 static zend_object_handlers php_http_client_datashare_object_handlers;
169
170 zend_object_handlers *php_http_client_datashare_get_object_handlers(void)
171 {
172 return &php_http_client_datashare_object_handlers;
173 }
174 static STATUS setopt(struct php_http_client_datashare *h, php_http_client_datashare_setopt_opt_t opt, void *arg)
175 {
176 return SUCCESS;
177 }
178
179 static php_http_client_datashare_ops_t php_http_client_datashare_user_ops = {
180 NULL,
181 NULL,
182 NULL,
183 NULL,
184 NULL,
185 NULL,
186 NULL,
187 setopt,
188 (php_http_new_t) php_http_client_datashare_object_new_ex,
189 php_http_client_datashare_get_class_entry
190
191 };
192 zend_object_value php_http_client_datashare_object_new(zend_class_entry *ce TSRMLS_DC)
193 {
194 return php_http_client_datashare_object_new_ex(ce, NULL, NULL TSRMLS_CC);
195 }
196
197 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)
198 {
199 zend_object_value ov;
200 php_http_client_datashare_object_t *o;
201
202 o = ecalloc(1, sizeof(*o));
203 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
204 object_properties_init((zend_object *) o, ce);
205
206 ov.handle = zend_objects_store_put(o, NULL, php_http_client_datashare_object_free, NULL TSRMLS_CC);
207 ov.handlers = &php_http_client_datashare_object_handlers;
208
209 if (!(o->share = share)) {
210 o->share = php_http_client_datashare_init(NULL, &php_http_client_datashare_user_ops, NULL, &ov TSRMLS_CC);
211 }
212
213 if (ptr) {
214 *ptr = o;
215 }
216
217 return ov;
218 }
219
220 void php_http_client_datashare_object_free(void *object TSRMLS_DC)
221 {
222 php_http_client_datashare_object_t *o = (php_http_client_datashare_object_t *) object;
223
224 php_http_client_datashare_free(&o->share);
225 zend_object_std_dtor((zend_object *) o TSRMLS_CC);
226 efree(o);
227 }
228
229 static zval *php_http_client_datashare_object_read_prop(zval *object, zval *member, int type PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC)
230 {
231 zend_property_info *pi;
232
233 if ((pi = zend_get_property_info(php_http_client_datashare_class_entry, member, 1 TSRMLS_CC))) {
234 if (type != BP_VAR_R) {
235 zval *zproxy;
236 php_property_proxy_t *proxy;
237
238 proxy = php_property_proxy_init(object, pi->name, pi->name_length TSRMLS_CC);
239
240 MAKE_STD_ZVAL(zproxy);
241 #ifdef Z_SET_REFCOUNT_P
242 Z_SET_REFCOUNT_P(zproxy, 0);
243 #else
244 zproxy->refcount = 0;
245 #endif
246 ZVAL_OBJVAL(zproxy, php_property_proxy_object_new_ex(php_property_proxy_get_class_entry(), proxy, NULL TSRMLS_CC), 0);
247 return zproxy;
248 }
249 }
250 return zend_get_std_object_handlers()->read_property(object, member, type PHP_HTTP_ZEND_LITERAL_CC TSRMLS_CC);
251 }
252
253 static void php_http_client_datashare_object_write_prop(zval *object, zval *member, zval *value PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC)
254 {
255 zend_property_info *pi;
256
257 if ((pi = zend_get_property_info(php_http_client_datashare_class_entry, member, 1 TSRMLS_CC))) {
258 zend_bool enable = i_zend_is_true(value);
259 php_http_client_datashare_setopt_opt_t opt;
260 php_http_client_datashare_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
261
262 if (!strcmp(pi->name, "cookie")) {
263 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_COOKIES;
264 } else if (!strcmp(pi->name, "dns")) {
265 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_RESOLVER;
266 } else if (!strcmp(pi->name, "ssl")) {
267 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_SSLSESSIONS;
268 } else {
269 return;
270 }
271
272 if (SUCCESS != php_http_client_datashare_setopt(obj->share, opt, &enable)) {
273 return;
274 }
275 }
276
277 zend_get_std_object_handlers()->write_property(object, member, value PHP_HTTP_ZEND_LITERAL_CC TSRMLS_CC);
278 }
279
280 PHP_METHOD(HttpClientDataShare, __destruct)
281 {
282 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
283 /* FIXME: move to php_http_client_datashare_dtor */
284 if (SUCCESS == zend_parse_parameters_none()) {
285 ; /* we always want to clean up */
286 }
287
288 php_http_client_datashare_reset(obj->share);
289 }
290
291 PHP_METHOD(HttpClientDataShare, count)
292 {
293 if (SUCCESS == zend_parse_parameters_none()) {
294 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
295
296 RETURN_LONG(zend_llist_count(&obj->share->clients));
297 }
298 RETURN_FALSE;
299 }
300
301
302 PHP_METHOD(HttpClientDataShare, attach)
303 {
304 zval *client;
305
306 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &client, php_http_client_get_class_entry())) {
307 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
308
309 RETURN_SUCCESS(php_http_client_datashare_attach(obj->share, client));
310 }
311 RETURN_FALSE;
312
313 }
314
315 PHP_METHOD(HttpClientDataShare, detach)
316 {
317 zval *client;
318
319 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &client, php_http_client_get_class_entry())) {
320 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
321
322 RETURN_SUCCESS(php_http_client_datashare_detach(obj->share, client));
323 }
324 RETURN_FALSE;
325 }
326
327 PHP_METHOD(HttpClientDataShare, reset)
328 {
329 if (SUCCESS == zend_parse_parameters_none()) {
330 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
331
332 php_http_client_datashare_reset(obj->share);
333 RETURN_TRUE;
334 }
335 RETURN_FALSE;
336 }
337
338 PHP_METHOD(HttpClientDataShare, __sleep)
339 {
340 php_http_error(HE_THROW, PHP_HTTP_E_CLIENT_DATASHARE, "cannot serialize a client datashare");
341 }
342
343 PHP_MINIT_FUNCTION(http_client_datashare)
344 {
345 PHP_HTTP_REGISTER_CLASS(http\\Client\\DataShare, AbstractDataShare, http_client_datashare, php_http_object_get_class_entry(), ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
346 php_http_client_datashare_class_entry->create_object = php_http_client_datashare_object_new;
347 memcpy(&php_http_client_datashare_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
348 php_http_client_datashare_object_handlers.clone_obj = NULL;
349 php_http_client_datashare_object_handlers.read_property = php_http_client_datashare_object_read_prop;
350 php_http_client_datashare_object_handlers.write_property = php_http_client_datashare_object_write_prop;
351 php_http_client_datashare_object_handlers.get_property_ptr_ptr = NULL;
352
353 zend_class_implements(php_http_client_datashare_class_entry TSRMLS_CC, 1, spl_ce_Countable);
354
355 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("cookie"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
356 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("dns"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
357 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("ssl"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
358
359 return SUCCESS;
360 }
361
362 /*
363 * Local variables:
364 * tab-width: 4
365 * c-basic-offset: 4
366 * End:
367 * vim600: noet sw=4 ts=4 fdm=marker
368 * vim<600: noet sw=4 ts=4
369 */
370