21
21
#endif
22
22
23
23
#include "php.h"
24
+ #include "Zend/zend_exceptions.h"
24
25
25
26
#include "curl_private.h"
26
27
27
28
#include <curl/curl.h>
28
29
29
30
#define SAVE_CURLSH_ERROR (__handle , __err ) (__handle)->err.no = (int) __err;
30
31
32
+ /**
33
+ * Free a persistent curl share handle.
34
+ */
31
35
void curl_share_free_persistent (zval * data )
32
36
{
33
37
CURLSH * handle = Z_PTR_P (data );
@@ -39,84 +43,104 @@ void curl_share_free_persistent(zval *data)
39
43
curl_share_cleanup (handle );
40
44
}
41
45
42
- /* {{{ Initialize a persistent curl share handle */
43
- PHP_FUNCTION (curl_share_init_persistent )
46
+ /**
47
+ * Initialize a share curl handle, optionally with share options and a persistent ID.
48
+ */
49
+ PHP_FUNCTION (curl_share_init )
44
50
{
45
- zend_string * id ;
46
-
47
- zval * persisted ;
51
+ zval * share_opts = NULL , * entry ;
52
+ zend_string * persistent_id ;
48
53
49
54
php_curlsh * sh ;
50
55
51
- zval * arr , * entry ;
52
56
CURLSHcode error ;
53
57
54
- ZEND_PARSE_PARAMETERS_START (2 , 2 )
55
- Z_PARAM_STR_EX (id , 1 , 0 )
56
- Z_PARAM_ARRAY (arr )
58
+ ZEND_PARSE_PARAMETERS_START (0 , 2 )
59
+ Z_PARAM_OPTIONAL
60
+ Z_PARAM_ARRAY (share_opts )
61
+ Z_PARAM_STR_OR_NULL (persistent_id )
57
62
ZEND_PARSE_PARAMETERS_END ();
58
63
59
64
object_init_ex (return_value , curl_share_ce );
60
65
sh = Z_CURL_SHARE_P (return_value );
61
66
62
- if ((persisted = zend_hash_find (& CURL_G (persistent_share_handles ), id )) != NULL ) {
63
- sh -> share = Z_PTR_P (persisted );
64
- sh -> persistent = 1 ;
65
- } else {
66
- sh -> share = curl_share_init ();
67
+ if (persistent_id ) {
68
+ zval * persisted = zend_hash_find (& CURL_G (persistent_share_handles ), persistent_id );
69
+
70
+ if (persisted ) {
71
+ sh -> share = Z_PTR_P (persisted );
72
+ sh -> persistent_id = zend_string_copy (persistent_id );
73
+
74
+ return ;
75
+ }
76
+ }
77
+
78
+ // The user did not provide a persistent share ID, or we could not find an existing share handle, so we'll have to
79
+ // create one.
80
+ sh -> share = curl_share_init ();
67
81
68
- ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (arr ), entry ) {
82
+ if (share_opts ) {
83
+ ZEND_HASH_FOREACH_VAL (Z_ARRVAL_P (share_opts ), entry ) {
69
84
ZVAL_DEREF (entry );
70
85
71
- error = curl_share_setopt (sh -> share , CURLSHOPT_SHARE , zval_get_long (entry ));
86
+ error = curl_share_setopt (sh -> share , CURLSHOPT_SHARE , zval_get_long_ex (entry , true ));
72
87
73
88
if (error != CURLSHE_OK ) {
74
- php_error_docref (NULL , E_WARNING , "could not construct persistent curl share: %s" , curl_share_strerror (error ));
89
+ zend_throw_exception_ex (
90
+ NULL ,
91
+ 0 ,
92
+ "Could not construct cURL share handle: %s" ,
93
+ curl_share_strerror (error )
94
+ );
75
95
76
96
goto error ;
77
97
}
78
98
} ZEND_HASH_FOREACH_END ();
99
+ }
79
100
101
+ if (persistent_id ) {
80
102
// It's important not to mark this as persistent until *after* we've successfully set all of the share options,
81
103
// as otherwise the curl_share_free_obj in the error handler won't free the CURLSH.
82
- sh -> persistent = 1 ;
83
-
84
- zend_hash_str_add_new_ptr (& CURL_G (persistent_share_handles ), ZSTR_VAL (id ), ZSTR_LEN (id ), sh -> share );
104
+ sh -> persistent_id = zend_string_copy (persistent_id );
105
+
106
+ // We use the zend_hash_str form here, since we want to ensure it allocates a new persistent string, instead of
107
+ // using the request-bound persistent_id.
108
+ zend_hash_str_add_new_ptr (
109
+ & CURL_G (persistent_share_handles ),
110
+ ZSTR_VAL (persistent_id ),
111
+ ZSTR_LEN (persistent_id ),
112
+ sh -> share
113
+ );
85
114
}
86
115
87
116
return ;
88
117
89
118
error :
90
119
zval_ptr_dtor (return_value );
91
120
92
- RETURN_FALSE ;
121
+ RETURN_THROWS () ;
93
122
}
94
- /* }}} */
95
-
96
- /* {{{ Initialize a share curl handle */
97
- PHP_FUNCTION (curl_share_init )
98
- {
99
- php_curlsh * sh ;
100
-
101
- ZEND_PARSE_PARAMETERS_NONE ();
102
123
103
- object_init_ex (return_value , curl_share_ce );
104
- sh = Z_CURL_SHARE_P (return_value );
105
-
106
- sh -> share = curl_share_init ();
107
- }
108
- /* }}} */
109
-
110
- /* {{{ Close a set of cURL handles */
124
+ /**
125
+ * Close a persistent curl share handle. NOP for non-persistent share handles.
126
+ */
111
127
PHP_FUNCTION (curl_share_close )
112
128
{
113
129
zval * z_sh ;
114
130
131
+ php_curlsh * sh ;
132
+
115
133
ZEND_PARSE_PARAMETERS_START (1 ,1 )
116
134
Z_PARAM_OBJECT_OF_CLASS (z_sh , curl_share_ce )
117
135
ZEND_PARSE_PARAMETERS_END ();
136
+
137
+ sh = Z_CURL_SHARE_P (z_sh );
138
+
139
+ if (sh -> persistent_id ) {
140
+ // Deleting the share from the hash table will trigger curl_share_free_persistent, so no need to call it here.
141
+ zend_hash_del (& CURL_G (persistent_share_handles ), sh -> persistent_id );
142
+ }
118
143
}
119
- /* }}} */
120
144
121
145
static bool _php_curl_share_setopt (php_curlsh * sh , zend_long option , zval * zvalue , zval * return_value ) /* {{{ */
122
146
{
@@ -138,9 +162,10 @@ static bool _php_curl_share_setopt(php_curlsh *sh, zend_long option, zval *zvalu
138
162
139
163
return error == CURLSHE_OK ;
140
164
}
141
- /* }}} */
142
165
143
- /* {{{ Set an option for a cURL transfer */
166
+ /**
167
+ * Set an option for a cURL transfer.
168
+ */
144
169
PHP_FUNCTION (curl_share_setopt )
145
170
{
146
171
zval * z_sh , * zvalue ;
@@ -161,9 +186,10 @@ PHP_FUNCTION(curl_share_setopt)
161
186
RETURN_FALSE ;
162
187
}
163
188
}
164
- /* }}} */
165
189
166
- /* {{{ Return an integer containing the last share curl error number */
190
+ /**
191
+ * Return an integer containing the last share curl error number.
192
+ */
167
193
PHP_FUNCTION (curl_share_errno )
168
194
{
169
195
zval * z_sh ;
@@ -177,10 +203,11 @@ PHP_FUNCTION(curl_share_errno)
177
203
178
204
RETURN_LONG (sh -> err .no );
179
205
}
180
- /* }}} */
181
206
182
207
183
- /* {{{ return string describing error code */
208
+ /**
209
+ * Return a string describing the error code.
210
+ */
184
211
PHP_FUNCTION (curl_share_strerror )
185
212
{
186
213
zend_long code ;
@@ -197,7 +224,6 @@ PHP_FUNCTION(curl_share_strerror)
197
224
RETURN_NULL ();
198
225
}
199
226
}
200
- /* }}} */
201
227
202
228
/* CurlShareHandle class */
203
229
@@ -219,8 +245,10 @@ void curl_share_free_obj(zend_object *object)
219
245
{
220
246
php_curlsh * sh = curl_share_from_obj (object );
221
247
222
- if (!sh -> persistent ) {
248
+ if (!sh -> persistent_id ) {
223
249
curl_share_cleanup (sh -> share );
250
+ } else {
251
+ zend_string_release (sh -> persistent_id );
224
252
}
225
253
226
254
zend_object_std_dtor (& sh -> std );
0 commit comments