merge raphf branch
[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 void php_http_client_datashare_object_write_prop(zval *object, zval *member, zval *value 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 zend_bool enable = i_zend_is_true(value);
235 php_http_client_datashare_setopt_opt_t opt;
236 php_http_client_datashare_object_t *obj = zend_object_store_get_object(object TSRMLS_CC);
237
238 if (!strcmp(pi->name, "cookie")) {
239 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_COOKIES;
240 } else if (!strcmp(pi->name, "dns")) {
241 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_RESOLVER;
242 } else if (!strcmp(pi->name, "ssl")) {
243 opt = PHP_HTTP_CLIENT_DATASHARE_OPT_SSLSESSIONS;
244 } else {
245 return;
246 }
247
248 if (SUCCESS != php_http_client_datashare_setopt(obj->share, opt, &enable)) {
249 return;
250 }
251 }
252
253 zend_get_std_object_handlers()->write_property(object, member, value PHP_HTTP_ZEND_LITERAL_CC TSRMLS_CC);
254 }
255
256 static zval **php_http_client_datashare_object_get_prop_ptr(zval *object, zval *member PHP_HTTP_ZEND_LITERAL_DC TSRMLS_DC)
257 {
258 zend_property_info *pi;
259
260 if ((pi = zend_get_property_info(php_http_client_datashare_class_entry, member, 1 TSRMLS_CC))) {
261 return &php_http_property_proxy_init(NULL, object, member, NULL TSRMLS_CC)->myself;
262 }
263
264 return zend_get_std_object_handlers()->get_property_ptr_ptr(object, member PHP_HTTP_ZEND_LITERAL_CC TSRMLS_CC);
265 }
266
267
268 PHP_METHOD(HttpClientDataShare, __destruct)
269 {
270 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
271 /* FIXME: move to php_http_client_datashare_dtor */
272 if (SUCCESS == zend_parse_parameters_none()) {
273 ; /* we always want to clean up */
274 }
275
276 php_http_client_datashare_reset(obj->share);
277 }
278
279 PHP_METHOD(HttpClientDataShare, count)
280 {
281 if (SUCCESS == zend_parse_parameters_none()) {
282 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
283
284 RETURN_LONG(zend_llist_count(&obj->share->clients));
285 }
286 RETURN_FALSE;
287 }
288
289
290 PHP_METHOD(HttpClientDataShare, attach)
291 {
292 zval *client;
293
294 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &client, php_http_client_get_class_entry())) {
295 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
296
297 RETURN_SUCCESS(php_http_client_datashare_attach(obj->share, client));
298 }
299 RETURN_FALSE;
300
301 }
302
303 PHP_METHOD(HttpClientDataShare, detach)
304 {
305 zval *client;
306
307 if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O", &client, php_http_client_get_class_entry())) {
308 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
309
310 RETURN_SUCCESS(php_http_client_datashare_detach(obj->share, client));
311 }
312 RETURN_FALSE;
313 }
314
315 PHP_METHOD(HttpClientDataShare, reset)
316 {
317 if (SUCCESS == zend_parse_parameters_none()) {
318 php_http_client_datashare_object_t *obj = zend_object_store_get_object(getThis() TSRMLS_CC);
319
320 php_http_client_datashare_reset(obj->share);
321 RETURN_TRUE;
322 }
323 RETURN_FALSE;
324 }
325
326 PHP_METHOD(HttpClientDataShare, __sleep)
327 {
328 php_http_error(HE_THROW, PHP_HTTP_E_CLIENT_DATASHARE, "cannot serialize a client datashare");
329 }
330
331 PHP_MINIT_FUNCTION(http_client_datashare)
332 {
333 PHP_HTTP_REGISTER_CLASS(http\\Client\\DataShare, AbstractDataShare, http_client_datashare, php_http_object_get_class_entry(), ZEND_ACC_EXPLICIT_ABSTRACT_CLASS);
334 php_http_client_datashare_class_entry->create_object = php_http_client_datashare_object_new;
335 memcpy(&php_http_client_datashare_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
336 php_http_client_datashare_object_handlers.clone_obj = NULL;
337 php_http_client_datashare_object_handlers.write_property = php_http_client_datashare_object_write_prop;
338 php_http_client_datashare_object_handlers.get_property_ptr_ptr = php_http_client_datashare_object_get_prop_ptr;
339
340 zend_class_implements(php_http_client_datashare_class_entry TSRMLS_CC, 1, spl_ce_Countable);
341
342 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("cookie"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
343 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("dns"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
344 zend_declare_property_bool(php_http_client_datashare_class_entry, ZEND_STRL("ssl"), 0, ZEND_ACC_PUBLIC TSRMLS_CC);
345
346 return SUCCESS;
347 }
348
349 /*
350 * Local variables:
351 * tab-width: 4
352 * c-basic-offset: 4
353 * End:
354 * vim600: noet sw=4 ts=4 fdm=marker
355 * vim<600: noet sw=4 ts=4
356 */
357