don't crash if user extends abstract classes
[m6w6/ext-http] / php_http_client_datashare_curl.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
15 #if PHP_HTTP_HAVE_CURL
16
17 typedef struct php_http_client_datashare_curl {
18 CURLSH *handle;
19 } php_http_client_datashare_curl_t;
20
21
22 static void *php_http_curlsh_ctor(void *opaque TSRMLS_DC)
23 {
24 return curl_share_init();
25 }
26
27 static void php_http_curlsh_dtor(void *opaque, void *handle TSRMLS_DC)
28 {
29 curl_share_cleanup(handle);
30 }
31
32
33 /* datashare handler ops */
34
35 static php_http_client_datashare_t *php_http_client_datashare_curl_init(php_http_client_datashare_t *h, void *handle)
36 {
37 php_http_client_datashare_curl_t *curl;
38 TSRMLS_FETCH_FROM_CTX(h->ts);
39
40 if (!handle && !(handle = php_http_resource_factory_handle_ctor(h->rf TSRMLS_CC))) {
41 php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT_DATASHARE, "could not initialize curl share handle");
42 return NULL;
43 }
44
45 curl = ecalloc(1, sizeof(*curl));
46 curl->handle = handle;
47 h->ctx = curl;
48
49 return h;
50 }
51
52 static void php_http_client_datashare_curl_dtor(php_http_client_datashare_t *h)
53 {
54 php_http_client_datashare_curl_t *curl = h->ctx;
55 TSRMLS_FETCH_FROM_CTX(h->ts);
56
57 php_http_resource_factory_handle_dtor(h->rf, curl->handle TSRMLS_CC);
58
59 efree(curl);
60 h->ctx = NULL;
61 }
62
63 static STATUS php_http_client_datashare_curl_attach(php_http_client_datashare_t *h, php_http_client_t *r)
64 {
65 CURLcode rc;
66 php_http_client_datashare_curl_t *curl = h->ctx;
67 php_http_client_curl_t *recurl = r->ctx;
68 TSRMLS_FETCH_FROM_CTX(h->ts);
69
70 if (CURLE_OK != (rc = curl_easy_setopt(recurl->handle, CURLOPT_SHARE, curl->handle))) {
71 php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT_DATASHARE, "Could not attach request to the datashare: %s", curl_easy_strerror(rc));
72 return FAILURE;
73 }
74 return SUCCESS;
75 }
76
77 static STATUS php_http_client_datashare_curl_detach(php_http_client_datashare_t *h, php_http_client_t *r)
78 {
79 CURLcode rc;
80 php_http_client_curl_t *recurl = r->ctx;
81 TSRMLS_FETCH_FROM_CTX(h->ts);
82
83
84 if (CURLE_OK != (rc = curl_easy_setopt(recurl->handle, CURLOPT_SHARE, NULL))) {
85 php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT_DATASHARE, "Could not detach request from the datashare: %s", curl_share_strerror(rc));
86 return FAILURE;
87 }
88 return SUCCESS;
89 }
90
91 static STATUS php_http_client_datashare_curl_setopt(php_http_client_datashare_t *h, php_http_client_datashare_setopt_opt_t opt, void *arg)
92 {
93 CURLSHcode rc;
94 php_http_client_datashare_curl_t *curl = h->ctx;
95
96 switch (opt) {
97 case PHP_HTTP_CLIENT_DATASHARE_OPT_COOKIES:
98 if (CURLSHE_OK != (rc = curl_share_setopt(curl->handle, *((zend_bool *) arg) ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, CURL_LOCK_DATA_COOKIE))) {
99 TSRMLS_FETCH_FROM_CTX(h->ts);
100
101 php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT_DATASHARE, "Could not %s sharing of cookie data: %s", *((zend_bool *) arg) ? "enable" : "disable", curl_share_strerror(rc));
102 return FAILURE;
103 }
104 break;
105
106 case PHP_HTTP_CLIENT_DATASHARE_OPT_RESOLVER:
107 if (CURLSHE_OK != (rc = curl_share_setopt(curl->handle, *((zend_bool *) arg) ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, CURL_LOCK_DATA_DNS))) {
108 TSRMLS_FETCH_FROM_CTX(h->ts);
109
110 php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT_DATASHARE, "Could not %s sharing of resolver data: %s", *((zend_bool *) arg) ? "enable" : "disable", curl_share_strerror(rc));
111 return FAILURE;
112 }
113 break;
114
115 #if PHP_HTTP_CURL_VERSION(7,23,0)
116 case PHP_HTTP_CLIENT_DATASHARE_OPT_SSLSESSIONS:
117 if (CURLSHE_OK != (rc = curl_share_setopt(curl->handle, *((zend_bool *) arg) ? CURLSHOPT_SHARE : CURLSHOPT_UNSHARE, CURL_LOCK_DATA_SSL_SESSION))) {
118 TSRMLS_FETCH_FROM_CTX(h->ts);
119
120 php_http_error(HE_WARNING, PHP_HTTP_E_CLIENT_DATASHARE, "Could not %s sharing of SSL session data: %s", *((zend_bool *) arg) ? "enable" : "disable", curl_share_strerror(rc));
121 return FAILURE;
122 }
123 break;
124 #endif
125
126 default:
127 return FAILURE;
128 }
129
130 return SUCCESS;
131 }
132
133 static php_http_resource_factory_ops_t php_http_curlsh_resource_factory_ops = {
134 php_http_curlsh_ctor,
135 NULL,
136 php_http_curlsh_dtor
137 };
138
139 static zend_class_entry *get_class_entry(void)
140 {
141 return php_http_client_datashare_curl_class_entry;
142 }
143
144 static php_http_client_datashare_ops_t php_http_client_datashare_curl_ops = {
145 &php_http_curlsh_resource_factory_ops,
146 php_http_client_datashare_curl_init,
147 NULL /* copy */,
148 php_http_client_datashare_curl_dtor,
149 NULL /*reset */,
150 php_http_client_datashare_curl_attach,
151 php_http_client_datashare_curl_detach,
152 php_http_client_datashare_curl_setopt,
153 (php_http_new_t) php_http_client_datashare_curl_object_new_ex,
154 get_class_entry
155 };
156
157 PHP_HTTP_API php_http_client_datashare_ops_t *php_http_client_datashare_curl_get_ops(void)
158 {
159 return &php_http_client_datashare_curl_ops;
160 }
161
162 #define PHP_HTTP_BEGIN_ARGS(method, req_args) PHP_HTTP_BEGIN_ARGS_EX(HttpClientDataShare, method, 0, req_args)
163 #define PHP_HTTP_EMPTY_ARGS(method) PHP_HTTP_EMPTY_ARGS_EX(HttpClientDataShare, method, 0)
164 #define PHP_HTTP_RSHARE_ME(method, visibility) PHP_ME(HttpClientDataShare, method, PHP_HTTP_ARGS(HttpClientDataShare, method), visibility)
165
166 zend_class_entry *php_http_client_datashare_curl_class_entry;
167 zend_function_entry php_http_client_datashare_curl_method_entry[] = {
168 EMPTY_FUNCTION_ENTRY
169 };
170
171 zend_object_value php_http_client_datashare_curl_object_new(zend_class_entry *ce TSRMLS_DC)
172 {
173 return php_http_client_datashare_curl_object_new_ex(ce, NULL, NULL TSRMLS_CC);
174 }
175
176 zend_object_value php_http_client_datashare_curl_object_new_ex(zend_class_entry *ce, php_http_client_datashare_t *share, php_http_client_datashare_object_t **ptr TSRMLS_DC)
177 {
178 zend_object_value ov;
179 php_http_client_datashare_object_t *o;
180
181 o = ecalloc(1, sizeof(*o));
182 zend_object_std_init((zend_object *) o, ce TSRMLS_CC);
183 object_properties_init((zend_object *) o, ce);
184
185 if (share) {
186 o->share = share;
187 } else {
188 o->share = php_http_client_datashare_init(NULL, &php_http_client_datashare_curl_ops, NULL, NULL TSRMLS_CC);
189 }
190
191 if (ptr) {
192 *ptr = o;
193 }
194
195 ov.handle = zend_objects_store_put(o, NULL, php_http_client_datashare_object_free, NULL TSRMLS_CC);
196 ov.handlers = php_http_client_datashare_get_object_handlers();
197
198 return ov;
199 }
200
201
202 PHP_MINIT_FUNCTION(http_client_datashare_curl)
203 {
204 if (SUCCESS != php_http_persistent_handle_provide(ZEND_STRL("http_client_datashare.curl"), &php_http_curlsh_resource_factory_ops, NULL, NULL)) {
205 return FAILURE;
206 }
207
208 PHP_HTTP_REGISTER_CLASS(http\\Client\\DataShare, CURL, http_client_datashare_curl, php_http_client_datashare_get_class_entry(), 0);
209 php_http_client_datashare_curl_class_entry->create_object = php_http_client_datashare_curl_object_new;
210 return SUCCESS;
211 }
212
213 #endif /* PHP_HTTP_HAVE_CURL */
214
215 /*
216 * Local variables:
217 * tab-width: 4
218 * c-basic-offset: 4
219 * End:
220 * vim600: noet sw=4 ts=4 fdm=marker
221 * vim<600: noet sw=4 ts=4
222 */
223