1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2018 The PHP Group                                |
6   +----------------------------------------------------------------------+
7   | This source file is subject to version 3.01 of the PHP license,      |
8   | that is bundled with this package in the file LICENSE, and is        |
9   | available through the world-wide-web at the following url:           |
10   | http://www.php.net/license/3_01.txt                                  |
11   | If you did not receive a copy of the PHP license and are unable to   |
12   | obtain it through the world-wide-web, please send a note to          |
13   | license@php.net so we can mail you a copy immediately.               |
14   +----------------------------------------------------------------------+
15   | Author: Sterling Hughes <sterling@php.net>                           |
16   +----------------------------------------------------------------------+
17*/
18
19#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "php.h"
26
27#if HAVE_CURL
28
29#include <stdio.h>
30#include <string.h>
31
32#ifdef PHP_WIN32
33#include <winsock2.h>
34#include <sys/types.h>
35#endif
36
37#include <curl/curl.h>
38#include <curl/easy.h>
39
40/* As of curl 7.11.1 this is no longer defined inside curl.h */
41#ifndef HttpPost
42#define HttpPost curl_httppost
43#endif
44
45/* {{{ cruft for thread safe SSL crypto locks */
46#if defined(ZTS) && defined(HAVE_CURL_SSL)
47# ifdef PHP_WIN32
48#  define PHP_CURL_NEED_OPENSSL_TSL
49#  include <openssl/crypto.h>
50# else /* !PHP_WIN32 */
51#  if defined(HAVE_CURL_OPENSSL)
52#   if defined(HAVE_OPENSSL_CRYPTO_H)
53#    define PHP_CURL_NEED_OPENSSL_TSL
54#    include <openssl/crypto.h>
55#   else
56#    warning \
57	"libcurl was compiled with OpenSSL support, but configure could not find " \
58	"openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \
59	"cause random crashes on SSL requests"
60#   endif
61#  elif defined(HAVE_CURL_GNUTLS)
62#   if defined(HAVE_GCRYPT_H)
63#    define PHP_CURL_NEED_GNUTLS_TSL
64#    include <gcrypt.h>
65#   else
66#    warning \
67	"libcurl was compiled with GnuTLS support, but configure could not find " \
68	"gcrypt.h; thus no SSL crypto locking callbacks will be set, which may " \
69	"cause random crashes on SSL requests"
70#   endif
71#  else
72#   warning \
73	"libcurl was compiled with SSL support, but configure could not determine which" \
74	"library was used; thus no SSL crypto locking callbacks will be set, which may " \
75	"cause random crashes on SSL requests"
76#  endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
77# endif /* PHP_WIN32 */
78#endif /* ZTS && HAVE_CURL_SSL */
79/* }}} */
80
81#define SMART_STR_PREALLOC 4096
82
83#include "zend_smart_str.h"
84#include "ext/standard/info.h"
85#include "ext/standard/file.h"
86#include "ext/standard/url.h"
87#include "php_curl.h"
88
89int  le_curl;
90int  le_curl_multi_handle;
91int  le_curl_share_handle;
92
93#ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */
94static MUTEX_T *php_curl_openssl_tsl = NULL;
95
96static void php_curl_ssl_lock(int mode, int n, const char * file, int line)
97{
98	if (mode & CRYPTO_LOCK) {
99		tsrm_mutex_lock(php_curl_openssl_tsl[n]);
100	} else {
101		tsrm_mutex_unlock(php_curl_openssl_tsl[n]);
102	}
103}
104
105static unsigned long php_curl_ssl_id(void)
106{
107	return (unsigned long) tsrm_thread_id();
108}
109#endif
110/* }}} */
111
112#ifdef PHP_CURL_NEED_GNUTLS_TSL /* {{{ */
113static int php_curl_ssl_mutex_create(void **m)
114{
115	if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
116		return SUCCESS;
117	} else {
118		return FAILURE;
119	}
120}
121
122static int php_curl_ssl_mutex_destroy(void **m)
123{
124	tsrm_mutex_free(*((MUTEX_T *) m));
125	return SUCCESS;
126}
127
128static int php_curl_ssl_mutex_lock(void **m)
129{
130	return tsrm_mutex_lock(*((MUTEX_T *) m));
131}
132
133static int php_curl_ssl_mutex_unlock(void **m)
134{
135	return tsrm_mutex_unlock(*((MUTEX_T *) m));
136}
137
138static struct gcry_thread_cbs php_curl_gnutls_tsl = {
139	GCRY_THREAD_OPTION_USER,
140	NULL,
141	php_curl_ssl_mutex_create,
142	php_curl_ssl_mutex_destroy,
143	php_curl_ssl_mutex_lock,
144	php_curl_ssl_mutex_unlock
145};
146#endif
147/* }}} */
148
149static void _php_curl_close_ex(php_curl *ch);
150static void _php_curl_close(zend_resource *rsrc);
151
152
153#define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v);
154#define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v);
155#define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : ""));
156#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, \
157		v ? zend_string_copy(v) : ZSTR_EMPTY_ALLOC());
158#define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s) -1 , (zval *) v);
159
160#if defined(PHP_WIN32) || defined(__GNUC__)
161# define php_curl_ret(__ret) RETVAL_FALSE; return __ret;
162#else
163# define php_curl_ret(__ret) RETVAL_FALSE; return;
164#endif
165
166static int php_curl_option_str(php_curl *ch, zend_long option, const char *str, const size_t len, zend_bool make_copy)
167{
168	CURLcode error = CURLE_OK;
169
170	if (strlen(str) != len) {
171		php_error_docref(NULL, E_WARNING, "Curl option contains invalid characters (\\0)");
172		return FAILURE;
173	}
174
175#if LIBCURL_VERSION_NUM >= 0x071100
176	if (make_copy) {
177#endif
178		char *copystr;
179
180		/* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */
181		copystr = estrndup(str, len);
182		error = curl_easy_setopt(ch->cp, option, copystr);
183		zend_llist_add_element(&ch->to_free->str, &copystr);
184#if LIBCURL_VERSION_NUM >= 0x071100
185	} else {
186		error = curl_easy_setopt(ch->cp, option, str);
187	}
188#endif
189
190	SAVE_CURL_ERROR(ch, error)
191
192	return error == CURLE_OK ? SUCCESS : FAILURE;
193}
194
195static int php_curl_option_url(php_curl *ch, const char *url, const size_t len) /* {{{ */
196{
197	/* Disable file:// if open_basedir are used */
198	if (PG(open_basedir) && *PG(open_basedir)) {
199#if LIBCURL_VERSION_NUM >= 0x071304
200		curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
201#else
202		php_url *uri;
203
204		if (!(uri = php_url_parse_ex(url, len))) {
205			php_error_docref(NULL, E_WARNING, "Invalid URL '%s'", url);
206			return FAILURE;
207		}
208
209		if (uri->scheme && zend_string_equals_literal_ci(uri->scheme, "file")) {
210			php_error_docref(NULL, E_WARNING, "Protocol 'file' disabled in cURL");
211			php_url_free(uri);
212			return FAILURE;
213		}
214		php_url_free(uri);
215#endif
216	}
217
218#if LIBCURL_VERSION_NUM > 0x073800 && defined(PHP_WIN32)
219	if (len > sizeof("file://") - 1 && '/' != url[sizeof("file://") - 1] && !strncmp("file://", url, sizeof("file://") - 1) && len < MAXPATHLEN - 2) {
220		char _tmp[MAXPATHLEN] = {0};
221
222		memmove(_tmp, "file:///", sizeof("file:///") - 1);
223		memmove(_tmp + sizeof("file:///") - 1, url + sizeof("file://") - 1, len - sizeof("file://") + 1);
224
225		return php_curl_option_str(ch, CURLOPT_URL, _tmp, len + 1, 0);
226	}
227#endif
228
229	return php_curl_option_str(ch, CURLOPT_URL, url, len, 0);
230}
231/* }}} */
232
233void _php_curl_verify_handlers(php_curl *ch, int reporterror) /* {{{ */
234{
235	php_stream *stream;
236
237	ZEND_ASSERT(ch && ch->handlers);
238
239	if (!Z_ISUNDEF(ch->handlers->std_err)) {
240		stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream());
241		if (stream == NULL) {
242			if (reporterror) {
243				php_error_docref(NULL, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr");
244			}
245			zval_ptr_dtor(&ch->handlers->std_err);
246			ZVAL_UNDEF(&ch->handlers->std_err);
247
248			curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr);
249		}
250	}
251	if (ch->handlers->read && !Z_ISUNDEF(ch->handlers->read->stream)) {
252		stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->read->stream, NULL, php_file_le_stream(), php_file_le_pstream());
253		if (stream == NULL) {
254			if (reporterror) {
255				php_error_docref(NULL, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default");
256			}
257			zval_ptr_dtor(&ch->handlers->read->stream);
258			ZVAL_UNDEF(&ch->handlers->read->stream);
259			ch->handlers->read->res = NULL;
260			ch->handlers->read->fp = 0;
261
262			curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
263		}
264	}
265	if (ch->handlers->write_header && !Z_ISUNDEF(ch->handlers->write_header->stream)) {
266		stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->write_header->stream, NULL, php_file_le_stream(), php_file_le_pstream());
267		if (stream == NULL) {
268			if (reporterror) {
269				php_error_docref(NULL, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default");
270			}
271			zval_ptr_dtor(&ch->handlers->write_header->stream);
272			ZVAL_UNDEF(&ch->handlers->write_header->stream);
273			ch->handlers->write_header->fp = 0;
274
275			ch->handlers->write_header->method = PHP_CURL_IGNORE;
276			curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
277		}
278	}
279	if (ch->handlers->write && !Z_ISUNDEF(ch->handlers->write->stream)) {
280		stream = (php_stream *)zend_fetch_resource2_ex(&ch->handlers->write->stream, NULL, php_file_le_stream(), php_file_le_pstream());
281		if (stream == NULL) {
282			if (reporterror) {
283				php_error_docref(NULL, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default");
284			}
285			zval_ptr_dtor(&ch->handlers->write->stream);
286			ZVAL_UNDEF(&ch->handlers->write->stream);
287			ch->handlers->write->fp = 0;
288
289			ch->handlers->write->method = PHP_CURL_STDOUT;
290			curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
291		}
292	}
293	return;
294}
295/* }}} */
296
297/* {{{ arginfo */
298ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0)
299	ZEND_ARG_INFO(0, version)
300ZEND_END_ARG_INFO()
301
302ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0)
303	ZEND_ARG_INFO(0, url)
304ZEND_END_ARG_INFO()
305
306ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0)
307	ZEND_ARG_INFO(0, ch)
308ZEND_END_ARG_INFO()
309
310ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0)
311	ZEND_ARG_INFO(0, ch)
312	ZEND_ARG_INFO(0, option)
313	ZEND_ARG_INFO(0, value)
314ZEND_END_ARG_INFO()
315
316ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0)
317	ZEND_ARG_INFO(0, ch)
318	ZEND_ARG_ARRAY_INFO(0, options, 0)
319ZEND_END_ARG_INFO()
320
321ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0)
322	ZEND_ARG_INFO(0, ch)
323ZEND_END_ARG_INFO()
324
325ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1)
326	ZEND_ARG_INFO(0, ch)
327	ZEND_ARG_INFO(0, option)
328ZEND_END_ARG_INFO()
329
330ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0)
331	ZEND_ARG_INFO(0, ch)
332ZEND_END_ARG_INFO()
333
334ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0)
335	ZEND_ARG_INFO(0, ch)
336ZEND_END_ARG_INFO()
337
338ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0)
339	ZEND_ARG_INFO(0, ch)
340ZEND_END_ARG_INFO()
341
342ZEND_BEGIN_ARG_INFO(arginfo_curl_reset, 0)
343	ZEND_ARG_INFO(0, ch)
344ZEND_END_ARG_INFO()
345
346ZEND_BEGIN_ARG_INFO(arginfo_curl_escape, 0)
347	ZEND_ARG_INFO(0, ch)
348	ZEND_ARG_INFO(0, str)
349ZEND_END_ARG_INFO()
350
351ZEND_BEGIN_ARG_INFO(arginfo_curl_unescape, 0)
352	ZEND_ARG_INFO(0, ch)
353	ZEND_ARG_INFO(0, str)
354ZEND_END_ARG_INFO()
355
356ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_setopt, 0)
357	ZEND_ARG_INFO(0, sh)
358	ZEND_ARG_INFO(0, option)
359	ZEND_ARG_INFO(0, value)
360ZEND_END_ARG_INFO()
361
362ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0)
363ZEND_END_ARG_INFO()
364
365ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0)
366	ZEND_ARG_INFO(0, mh)
367	ZEND_ARG_INFO(0, ch)
368ZEND_END_ARG_INFO()
369
370ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
371	ZEND_ARG_INFO(0, mh)
372	ZEND_ARG_INFO(0, ch)
373ZEND_END_ARG_INFO()
374
375ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
376	ZEND_ARG_INFO(0, mh)
377	ZEND_ARG_INFO(0, timeout)
378ZEND_END_ARG_INFO()
379
380ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1)
381	ZEND_ARG_INFO(0, mh)
382	ZEND_ARG_INFO(1, still_running)
383ZEND_END_ARG_INFO()
384
385ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0)
386	ZEND_ARG_INFO(0, ch)
387ZEND_END_ARG_INFO()
388
389ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1)
390	ZEND_ARG_INFO(0, mh)
391	ZEND_ARG_INFO(1, msgs_in_queue)
392ZEND_END_ARG_INFO()
393
394ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
395	ZEND_ARG_INFO(0, mh)
396ZEND_END_ARG_INFO()
397
398ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_errno, 0)
399	ZEND_ARG_INFO(0, mh)
400ZEND_END_ARG_INFO()
401
402ZEND_BEGIN_ARG_INFO(arginfo_curl_strerror, 0)
403	ZEND_ARG_INFO(0, errornum)
404ZEND_END_ARG_INFO()
405
406ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_strerror, 0)
407	ZEND_ARG_INFO(0, errornum)
408ZEND_END_ARG_INFO()
409
410ZEND_BEGIN_ARG_INFO(arginfo_curl_share_strerror, 0)
411	ZEND_ARG_INFO(0, errornum)
412ZEND_END_ARG_INFO()
413
414ZEND_BEGIN_ARG_INFO(arginfo_curl_share_init, 0)
415ZEND_END_ARG_INFO()
416
417ZEND_BEGIN_ARG_INFO(arginfo_curl_share_close, 0)
418	ZEND_ARG_INFO(0, sh)
419ZEND_END_ARG_INFO()
420
421ZEND_BEGIN_ARG_INFO(arginfo_curl_share_setopt, 0)
422	ZEND_ARG_INFO(0, sh)
423	ZEND_ARG_INFO(0, option)
424	ZEND_ARG_INFO(0, value)
425ZEND_END_ARG_INFO()
426
427ZEND_BEGIN_ARG_INFO(arginfo_curl_share_errno, 0)
428	ZEND_ARG_INFO(0, sh)
429ZEND_END_ARG_INFO()
430
431#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
432ZEND_BEGIN_ARG_INFO(arginfo_curl_pause, 0)
433	ZEND_ARG_INFO(0, ch)
434	ZEND_ARG_INFO(0, bitmask)
435ZEND_END_ARG_INFO()
436#endif
437
438ZEND_BEGIN_ARG_INFO_EX(arginfo_curlfile_create, 0, 0, 1)
439	ZEND_ARG_INFO(0, filename)
440	ZEND_ARG_INFO(0, mimetype)
441	ZEND_ARG_INFO(0, postname)
442ZEND_END_ARG_INFO()
443/* }}} */
444
445/* {{{ curl_functions[]
446 */
447static const zend_function_entry curl_functions[] = {
448	PHP_FE(curl_init,                arginfo_curl_init)
449	PHP_FE(curl_copy_handle,         arginfo_curl_copy_handle)
450	PHP_FE(curl_version,             arginfo_curl_version)
451	PHP_FE(curl_setopt,              arginfo_curl_setopt)
452	PHP_FE(curl_setopt_array,        arginfo_curl_setopt_array)
453	PHP_FE(curl_exec,                arginfo_curl_exec)
454	PHP_FE(curl_getinfo,             arginfo_curl_getinfo)
455	PHP_FE(curl_error,               arginfo_curl_error)
456	PHP_FE(curl_errno,               arginfo_curl_errno)
457	PHP_FE(curl_close,               arginfo_curl_close)
458	PHP_FE(curl_strerror,            arginfo_curl_strerror)
459	PHP_FE(curl_multi_strerror,      arginfo_curl_multi_strerror)
460	PHP_FE(curl_share_strerror,      arginfo_curl_share_strerror)
461	PHP_FE(curl_reset,               arginfo_curl_reset)
462	PHP_FE(curl_escape,              arginfo_curl_escape)
463	PHP_FE(curl_unescape,            arginfo_curl_unescape)
464#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
465	PHP_FE(curl_pause,               arginfo_curl_pause)
466#endif
467	PHP_FE(curl_multi_init,          arginfo_curl_multi_init)
468	PHP_FE(curl_multi_add_handle,    arginfo_curl_multi_add_handle)
469	PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
470	PHP_FE(curl_multi_select,        arginfo_curl_multi_select)
471	PHP_FE(curl_multi_exec,          arginfo_curl_multi_exec)
472	PHP_FE(curl_multi_getcontent,    arginfo_curl_multi_getcontent)
473	PHP_FE(curl_multi_info_read,     arginfo_curl_multi_info_read)
474	PHP_FE(curl_multi_close,         arginfo_curl_multi_close)
475	PHP_FE(curl_multi_errno,         arginfo_curl_multi_errno)
476	PHP_FE(curl_multi_setopt,        arginfo_curl_multi_setopt)
477	PHP_FE(curl_share_init,          arginfo_curl_share_init)
478	PHP_FE(curl_share_close,         arginfo_curl_share_close)
479	PHP_FE(curl_share_setopt,        arginfo_curl_share_setopt)
480	PHP_FE(curl_share_errno,         arginfo_curl_share_errno)
481	PHP_FE(curl_file_create,         arginfo_curlfile_create)
482	PHP_FE_END
483};
484/* }}} */
485
486/* {{{ curl_module_entry
487 */
488zend_module_entry curl_module_entry = {
489	STANDARD_MODULE_HEADER,
490	"curl",
491	curl_functions,
492	PHP_MINIT(curl),
493	PHP_MSHUTDOWN(curl),
494	NULL,
495	NULL,
496	PHP_MINFO(curl),
497	PHP_CURL_VERSION,
498	STANDARD_MODULE_PROPERTIES
499};
500/* }}} */
501
502#ifdef COMPILE_DL_CURL
503ZEND_GET_MODULE (curl)
504#endif
505
506/* {{{ PHP_INI_BEGIN */
507PHP_INI_BEGIN()
508	PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL)
509PHP_INI_END()
510/* }}} */
511
512/* {{{ PHP_MINFO_FUNCTION
513 */
514PHP_MINFO_FUNCTION(curl)
515{
516	curl_version_info_data *d;
517	char **p;
518	char str[1024];
519	size_t n = 0;
520
521	d = curl_version_info(CURLVERSION_NOW);
522	php_info_print_table_start();
523	php_info_print_table_row(2, "cURL support",    "enabled");
524	php_info_print_table_row(2, "cURL Information", d->version);
525	sprintf(str, "%d", d->age);
526	php_info_print_table_row(2, "Age", str);
527
528	/* To update on each new cURL release using src/main.c in cURL sources */
529	if (d->features) {
530		struct feat {
531			const char *name;
532			int bitmask;
533		};
534
535		unsigned int i;
536
537		static const struct feat feats[] = {
538			{"AsynchDNS", CURL_VERSION_ASYNCHDNS},
539			{"CharConv", CURL_VERSION_CONV},
540			{"Debug", CURL_VERSION_DEBUG},
541			{"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
542			{"IDN", CURL_VERSION_IDN},
543			{"IPv6", CURL_VERSION_IPV6},
544			{"krb4", CURL_VERSION_KERBEROS4},
545			{"Largefile", CURL_VERSION_LARGEFILE},
546			{"libz", CURL_VERSION_LIBZ},
547			{"NTLM", CURL_VERSION_NTLM},
548#if LIBCURL_VERSION_NUM >= 0x071600 /* 7.22.0 */
549			{"NTLMWB", CURL_VERSION_NTLM_WB},
550#endif
551			{"SPNEGO", CURL_VERSION_SPNEGO},
552			{"SSL",  CURL_VERSION_SSL},
553			{"SSPI",  CURL_VERSION_SSPI},
554#if LIBCURL_VERSION_NUM >= 0x071504 /* 7.21.4 */
555			{"TLS-SRP", CURL_VERSION_TLSAUTH_SRP},
556#endif
557#if LIBCURL_VERSION_NUM >= 0x072100 /* 7.33.0 */
558			{"HTTP2", CURL_VERSION_HTTP2},
559#endif
560#if LIBCURL_VERSION_NUM >= 0x072600 /* 7.38.0 */
561			{"GSSAPI", CURL_VERSION_GSSAPI},
562#endif
563#if LIBCURL_VERSION_NUM >= 0x072800 /* 7.40.0 */
564			{"KERBEROS5", CURL_VERSION_KERBEROS5},
565			{"UNIX_SOCKETS", CURL_VERSION_UNIX_SOCKETS},
566#endif
567#if LIBCURL_VERSION_NUM >= 0x072f00 /* 7.47.0 */
568			{"PSL", CURL_VERSION_PSL},
569#endif
570#if LIBCURL_VERSION_NUM >= 0x073400 /* 7.52.0 */
571			{"HTTPS_PROXY", CURL_VERSION_HTTPS_PROXY},
572#endif
573#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
574			{"MULTI_SSL", CURL_VERSION_MULTI_SSL},
575#endif
576#if LIBCURL_VERSION_NUM >= 0x073900 /* 7.57.0 */
577			{"BROTLI", CURL_VERSION_BROTLI},
578#endif
579			{NULL, 0}
580		};
581
582		php_info_print_table_row(1, "Features");
583		for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
584			if (feats[i].name) {
585				php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No");
586			}
587		}
588	}
589
590	n = 0;
591	p = (char **) d->protocols;
592	while (*p != NULL) {
593			n += sprintf(str + n, "%s%s", *p, *(p + 1) != NULL ? ", " : "");
594			p++;
595	}
596	php_info_print_table_row(2, "Protocols", str);
597
598	php_info_print_table_row(2, "Host", d->host);
599
600	if (d->ssl_version) {
601		php_info_print_table_row(2, "SSL Version", d->ssl_version);
602	}
603
604	if (d->libz_version) {
605		php_info_print_table_row(2, "ZLib Version", d->libz_version);
606	}
607
608#if defined(CURLVERSION_SECOND) && CURLVERSION_NOW >= CURLVERSION_SECOND
609	if (d->ares) {
610		php_info_print_table_row(2, "ZLib Version", d->ares);
611	}
612#endif
613
614#if defined(CURLVERSION_THIRD) && CURLVERSION_NOW >= CURLVERSION_THIRD
615	if (d->libidn) {
616		php_info_print_table_row(2, "libIDN Version", d->libidn);
617	}
618#endif
619
620#if LIBCURL_VERSION_NUM >= 0x071300
621
622	if (d->iconv_ver_num) {
623		php_info_print_table_row(2, "IconV Version", d->iconv_ver_num);
624	}
625
626	if (d->libssh_version) {
627		php_info_print_table_row(2, "libSSH Version", d->libssh_version);
628	}
629#endif
630	php_info_print_table_end();
631
632	DISPLAY_INI_ENTRIES();
633}
634/* }}} */
635
636#define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)
637
638/* {{{ PHP_MINIT_FUNCTION
639 */
640PHP_MINIT_FUNCTION(curl)
641{
642	le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number);
643	le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number);
644	le_curl_share_handle = zend_register_list_destructors_ex(_php_curl_share_close, NULL, "curl_share", module_number);
645
646	REGISTER_INI_ENTRIES();
647
648	/* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions
649	   or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list
650	   of options and which version they were introduced */
651
652	/* Constants for curl_setopt() */
653	REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER);
654	REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER);
655	REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE);
656	REGISTER_CURL_CONSTANT(CURLOPT_CAINFO);
657	REGISTER_CURL_CONSTANT(CURLOPT_CAPATH);
658	REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT);
659	REGISTER_CURL_CONSTANT(CURLOPT_COOKIE);
660	REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE);
661	REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR);
662	REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION);
663	REGISTER_CURL_CONSTANT(CURLOPT_CRLF);
664	REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST);
665	REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT);
666	REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
667	REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET);
668	REGISTER_CURL_CONSTANT(CURLOPT_ENCODING);
669	REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR);
670	REGISTER_CURL_CONSTANT(CURLOPT_FILE);
671	REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
672	REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION);
673	REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE);
674	REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT);
675	REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND);
676	REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY);
677	REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT);
678	REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT);
679	REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV);
680	REGISTER_CURL_CONSTANT(CURLOPT_HEADER);
681	REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION);
682	REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES);
683	REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET);
684	REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER);
685	REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL);
686	REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION);
687	REGISTER_CURL_CONSTANT(CURLOPT_INFILE);
688	REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE);
689	REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE);
690	REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL);
691	REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT);
692	REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME);
693	REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS);
694	REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS);
695	REGISTER_CURL_CONSTANT(CURLOPT_NETRC);
696	REGISTER_CURL_CONSTANT(CURLOPT_NOBODY);
697	REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS);
698	REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL);
699	REGISTER_CURL_CONSTANT(CURLOPT_PORT);
700	REGISTER_CURL_CONSTANT(CURLOPT_POST);
701	REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS);
702	REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE);
703	REGISTER_CURL_CONSTANT(CURLOPT_PREQUOTE);
704	REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE);
705	REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION);
706	REGISTER_CURL_CONSTANT(CURLOPT_PROXY);
707	REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT);
708	REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE);
709	REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD);
710	REGISTER_CURL_CONSTANT(CURLOPT_PUT);
711	REGISTER_CURL_CONSTANT(CURLOPT_QUOTE);
712	REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE);
713	REGISTER_CURL_CONSTANT(CURLOPT_RANGE);
714	REGISTER_CURL_CONSTANT(CURLOPT_READDATA);
715	REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
716	REGISTER_CURL_CONSTANT(CURLOPT_REFERER);
717	REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM);
718	REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER);
719	REGISTER_CURL_CONSTANT(CURLOPT_SHARE);
720	REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT);
721	REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD);
722	REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE);
723	REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE);
724	REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT);
725	REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY);
726	REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD);
727	REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE);
728	REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION);
729	REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST);
730	REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST);
731	REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER);
732	REGISTER_CURL_CONSTANT(CURLOPT_STDERR);
733	REGISTER_CURL_CONSTANT(CURLOPT_TELNETOPTIONS);
734	REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION);
735	REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT);
736	REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE);
737	REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT);
738	REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH);
739	REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD);
740	REGISTER_CURL_CONSTANT(CURLOPT_URL);
741	REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT);
742	REGISTER_CURL_CONSTANT(CURLOPT_USERPWD);
743	REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
744	REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
745	REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
746
747	/* */
748	REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
749	REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER);
750	REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING);
751	REGISTER_CURL_CONSTANT(CURLE_BAD_DOWNLOAD_RESUME);
752	REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT);
753	REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED);
754	REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT);
755	REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST);
756	REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY);
757	REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT);
758	REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE);
759	REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED);
760	REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME);
761	REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST);
762	REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT);
763	REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE);
764	REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE);
765	REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII);
766	REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY);
767	REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE);
768	REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST);
769	REGISTER_CURL_CONSTANT(CURLE_FTP_PARTIAL_FILE);
770	REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED);
771	REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR);
772	REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT);
773	REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT);
774	REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY);
775	REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY);
776	REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY);
777	REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY);
778	REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR);
779	REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND);
780	REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING);
781	REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND);
782	REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED);
783	REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR);
784	REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR);
785	REGISTER_CURL_CONSTANT(CURLE_HTTP_RETURNED_ERROR);
786	REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND);
787	REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED);
788	REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND);
789	REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER);
790	REGISTER_CURL_CONSTANT(CURLE_OBSOLETE);
791	REGISTER_CURL_CONSTANT(CURLE_OK);
792	REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEDOUT);
793	REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED);
794	REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY);
795	REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE);
796	REGISTER_CURL_CONSTANT(CURLE_READ_ERROR);
797	REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR);
798	REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR);
799	REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE);
800	REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT);
801	REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM);
802	REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER);
803	REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR);
804	REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND);
805	REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED);
806	REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
807#if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */
808	REGISTER_CURL_CONSTANT(CURLE_SSL_PINNEDPUBKEYNOTMATCH);
809#endif
810	REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX);
811	REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS);
812	REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION);
813	REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
814	REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT);
815	REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER);
816	REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR);
817
818	/* cURL info constants */
819	REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME);
820	REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
821	REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD);
822	REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE);
823	REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL);
824	REGISTER_CURL_CONSTANT(CURLINFO_FILETIME);
825	REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT);
826	REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE);
827	REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE);
828	REGISTER_CURL_CONSTANT(CURLINFO_LASTONE);
829	REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME);
830	REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME);
831	REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE);
832	REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
833	REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME);
834	REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE);
835	REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD);
836	REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD);
837	REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD);
838	REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD);
839	REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT);
840	REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME);
841	REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME);
842
843	/* Other */
844	REGISTER_CURL_CONSTANT(CURLMSG_DONE);
845	REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
846
847	/* Curl Multi Constants */
848	REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE);
849	REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE);
850	REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM);
851	REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR);
852	REGISTER_CURL_CONSTANT(CURLM_OK);
853	REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY);
854#if LIBCURL_VERSION_NUM >= 0x072001 /* Available since 7.32.1 */
855	REGISTER_CURL_CONSTANT(CURLM_ADDED_ALREADY);
856#endif
857
858	/* Curl proxy constants */
859	REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
860	REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
861	REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
862
863	/* Curl Share constants */
864	REGISTER_CURL_CONSTANT(CURLSHOPT_NONE);
865	REGISTER_CURL_CONSTANT(CURLSHOPT_SHARE);
866	REGISTER_CURL_CONSTANT(CURLSHOPT_UNSHARE);
867
868	/* Curl Http Version constants (CURLOPT_HTTP_VERSION) */
869	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0);
870	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1);
871	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE);
872
873	/* Curl Lock constants */
874	REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_COOKIE);
875	REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_DNS);
876	REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_SSL_SESSION);
877
878	/* Curl NETRC constants (CURLOPT_NETRC) */
879	REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED);
880	REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL);
881	REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED);
882
883	/* Curl SSL Version constants (CURLOPT_SSLVERSION) */
884	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_DEFAULT);
885	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_SSLv2);
886	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_SSLv3);
887	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1);
888
889	/* Curl TIMECOND constants (CURLOPT_TIMECONDITION) */
890	REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE);
891	REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE);
892	REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD);
893	REGISTER_CURL_CONSTANT(CURL_TIMECOND_NONE);
894
895	/* Curl version constants */
896	REGISTER_CURL_CONSTANT(CURL_VERSION_ASYNCHDNS);
897	REGISTER_CURL_CONSTANT(CURL_VERSION_CONV);
898	REGISTER_CURL_CONSTANT(CURL_VERSION_DEBUG);
899	REGISTER_CURL_CONSTANT(CURL_VERSION_GSSNEGOTIATE);
900	REGISTER_CURL_CONSTANT(CURL_VERSION_IDN);
901	REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
902	REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
903	REGISTER_CURL_CONSTANT(CURL_VERSION_LARGEFILE);
904	REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ);
905	REGISTER_CURL_CONSTANT(CURL_VERSION_NTLM);
906	REGISTER_CURL_CONSTANT(CURL_VERSION_SPNEGO);
907	REGISTER_CURL_CONSTANT(CURL_VERSION_SSL);
908	REGISTER_CURL_CONSTANT(CURL_VERSION_SSPI);
909
910	/* Available since 7.10.6 */
911	REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH);
912	/* http authentication options */
913	REGISTER_CURL_CONSTANT(CURLAUTH_ANY);
914	REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE);
915	REGISTER_CURL_CONSTANT(CURLAUTH_BASIC);
916	REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST);
917	REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE);
918	REGISTER_CURL_CONSTANT(CURLAUTH_NONE);
919	REGISTER_CURL_CONSTANT(CURLAUTH_NTLM);
920
921	/* Available since 7.10.7 */
922	REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CONNECTCODE);
923	REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS);
924	REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH);
925
926	/* Available since 7.10.8 */
927	REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED);
928	REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL);
929	REGISTER_CURL_CONSTANT(CURLINFO_HTTPAUTH_AVAIL);
930	REGISTER_CURL_CONSTANT(CURLINFO_RESPONSE_CODE);
931	REGISTER_CURL_CONSTANT(CURLINFO_PROXYAUTH_AVAIL);
932	REGISTER_CURL_CONSTANT(CURLOPT_FTP_RESPONSE_TIMEOUT);
933	REGISTER_CURL_CONSTANT(CURLOPT_IPRESOLVE);
934	REGISTER_CURL_CONSTANT(CURLOPT_MAXFILESIZE);
935	REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V4);
936	REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V6);
937	REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_WHATEVER);
938
939	/* Available since 7.11.0 */
940	REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED);
941	REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL);
942	REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL);
943	REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE);
944	REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY);
945	REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL);
946	REGISTER_CURL_CONSTANT(CURLOPT_NETRC_FILE);
947
948	/* Available since 7.11.2 */
949	REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY);
950
951	/* Available since 7.12.2 */
952	REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT);
953	REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL);
954	REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS);
955	REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH);
956
957	/* Available since 7.13.0 */
958	REGISTER_CURL_CONSTANT(CURLOPT_FTP_ACCOUNT);
959
960	/* Available since 7.12.2 */
961	REGISTER_CURL_CONSTANT(CURLINFO_OS_ERRNO);
962
963	/* Available since 7.12.3 */
964	REGISTER_CURL_CONSTANT(CURLINFO_NUM_CONNECTS);
965	REGISTER_CURL_CONSTANT(CURLINFO_SSL_ENGINES);
966
967	/* Available since 7.14.1 */
968	REGISTER_CURL_CONSTANT(CURLINFO_COOKIELIST);
969	REGISTER_CURL_CONSTANT(CURLOPT_COOKIELIST);
970	REGISTER_CURL_CONSTANT(CURLOPT_IGNORE_CONTENT_LENGTH);
971
972	/* Available since 7.15.0 */
973	REGISTER_CURL_CONSTANT(CURLOPT_FTP_SKIP_PASV_IP);
974
975	/* Available since 7.15.1 */
976	REGISTER_CURL_CONSTANT(CURLOPT_FTP_FILEMETHOD);
977
978	/* Available since 7.15.2 */
979	REGISTER_CURL_CONSTANT(CURLOPT_CONNECT_ONLY);
980	REGISTER_CURL_CONSTANT(CURLOPT_LOCALPORT);
981	REGISTER_CURL_CONSTANT(CURLOPT_LOCALPORTRANGE);
982
983	/* Available since 7.15.3 */
984	REGISTER_CURL_CONSTANT(CURLFTPMETHOD_MULTICWD);
985	REGISTER_CURL_CONSTANT(CURLFTPMETHOD_NOCWD);
986	REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD);
987
988	/* Available since 7.15.4 */
989	REGISTER_CURL_CONSTANT(CURLINFO_FTP_ENTRY_PATH);
990
991	/* Available since 7.15.5 */
992	REGISTER_CURL_CONSTANT(CURLOPT_FTP_ALTERNATIVE_TO_USER);
993	REGISTER_CURL_CONSTANT(CURLOPT_MAX_RECV_SPEED_LARGE);
994	REGISTER_CURL_CONSTANT(CURLOPT_MAX_SEND_SPEED_LARGE);
995
996#if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */
997	REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT_BADFILE);
998	REGISTER_CURL_CONSTANT(CURLOPT_SSL_SESSIONID_CACHE);
999	REGISTER_CURL_CONSTANT(CURLMOPT_PIPELINING);
1000#endif
1001
1002#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
1003	REGISTER_CURL_CONSTANT(CURLE_SSH);
1004	REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL_CCC);
1005	REGISTER_CURL_CONSTANT(CURLOPT_SSH_AUTH_TYPES);
1006	REGISTER_CURL_CONSTANT(CURLOPT_SSH_PRIVATE_KEYFILE);
1007	REGISTER_CURL_CONSTANT(CURLOPT_SSH_PUBLIC_KEYFILE);
1008	REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_ACTIVE);
1009	REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_NONE);
1010	REGISTER_CURL_CONSTANT(CURLFTPSSL_CCC_PASSIVE);
1011#endif
1012
1013#if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */
1014	REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS);
1015	REGISTER_CURL_CONSTANT(CURLOPT_HTTP_CONTENT_DECODING);
1016	REGISTER_CURL_CONSTANT(CURLOPT_HTTP_TRANSFER_DECODING);
1017	REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS);
1018#endif
1019
1020#if LIBCURL_VERSION_NUM >= 0x071003 /* Available since 7.16.3 */
1021	REGISTER_CURL_CONSTANT(CURLMOPT_MAXCONNECTS);
1022#endif
1023
1024#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
1025	REGISTER_CURL_CONSTANT(CURLOPT_KRBLEVEL);
1026	REGISTER_CURL_CONSTANT(CURLOPT_NEW_DIRECTORY_PERMS);
1027	REGISTER_CURL_CONSTANT(CURLOPT_NEW_FILE_PERMS);
1028#endif
1029
1030#if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */
1031	REGISTER_CURL_CONSTANT(CURLOPT_APPEND);
1032	REGISTER_CURL_CONSTANT(CURLOPT_DIRLISTONLY);
1033	REGISTER_CURL_CONSTANT(CURLOPT_USE_SSL);
1034	/* Curl SSL Constants */
1035	REGISTER_CURL_CONSTANT(CURLUSESSL_ALL);
1036	REGISTER_CURL_CONSTANT(CURLUSESSL_CONTROL);
1037	REGISTER_CURL_CONSTANT(CURLUSESSL_NONE);
1038	REGISTER_CURL_CONSTANT(CURLUSESSL_TRY);
1039#endif
1040
1041#if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */
1042	REGISTER_CURL_CONSTANT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
1043#endif
1044
1045#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
1046	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TRANSFER_MODE);
1047	REGISTER_CURL_CONSTANT(CURLPAUSE_ALL);
1048	REGISTER_CURL_CONSTANT(CURLPAUSE_CONT);
1049	REGISTER_CURL_CONSTANT(CURLPAUSE_RECV);
1050	REGISTER_CURL_CONSTANT(CURLPAUSE_RECV_CONT);
1051	REGISTER_CURL_CONSTANT(CURLPAUSE_SEND);
1052	REGISTER_CURL_CONSTANT(CURLPAUSE_SEND_CONT);
1053	REGISTER_CURL_CONSTANT(CURL_READFUNC_PAUSE);
1054	REGISTER_CURL_CONSTANT(CURL_WRITEFUNC_PAUSE);
1055
1056	REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4A);
1057	REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5_HOSTNAME);
1058#endif
1059
1060#if LIBCURL_VERSION_NUM >= 0x071202 /* Available since 7.18.2 */
1061	REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL);
1062#endif
1063
1064#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
1065	REGISTER_CURL_CONSTANT(CURLINFO_APPCONNECT_TIME);
1066	REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_IP);
1067
1068	REGISTER_CURL_CONSTANT(CURLOPT_ADDRESS_SCOPE);
1069	REGISTER_CURL_CONSTANT(CURLOPT_CRLFILE);
1070	REGISTER_CURL_CONSTANT(CURLOPT_ISSUERCERT);
1071	REGISTER_CURL_CONSTANT(CURLOPT_KEYPASSWD);
1072
1073	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_ANY);
1074	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_DEFAULT);
1075	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_HOST);
1076	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_KEYBOARD);
1077	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_NONE);
1078	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PASSWORD);
1079	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PUBLICKEY);
1080#endif
1081
1082#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
1083	REGISTER_CURL_CONSTANT(CURLINFO_CERTINFO);
1084	REGISTER_CURL_CONSTANT(CURLOPT_CERTINFO);
1085	REGISTER_CURL_CONSTANT(CURLOPT_PASSWORD);
1086	REGISTER_CURL_CONSTANT(CURLOPT_POSTREDIR);
1087	REGISTER_CURL_CONSTANT(CURLOPT_PROXYPASSWORD);
1088	REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERNAME);
1089	REGISTER_CURL_CONSTANT(CURLOPT_USERNAME);
1090	REGISTER_CURL_CONSTANT(CURL_REDIR_POST_301);
1091	REGISTER_CURL_CONSTANT(CURL_REDIR_POST_302);
1092	REGISTER_CURL_CONSTANT(CURL_REDIR_POST_ALL);
1093#endif
1094
1095#if LIBCURL_VERSION_NUM >= 0x071303 /* Available since 7.19.3 */
1096	REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST_IE);
1097#endif
1098
1099#if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */
1100	REGISTER_CURL_CONSTANT(CURLINFO_CONDITION_UNMET);
1101
1102	REGISTER_CURL_CONSTANT(CURLOPT_NOPROXY);
1103	REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS);
1104	REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS);
1105	REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_GSSAPI_NEC);
1106	REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_GSSAPI_SERVICE);
1107	REGISTER_CURL_CONSTANT(CURLOPT_TFTP_BLKSIZE);
1108
1109	REGISTER_CURL_CONSTANT(CURLPROTO_ALL);
1110	REGISTER_CURL_CONSTANT(CURLPROTO_DICT);
1111	REGISTER_CURL_CONSTANT(CURLPROTO_FILE);
1112	REGISTER_CURL_CONSTANT(CURLPROTO_FTP);
1113	REGISTER_CURL_CONSTANT(CURLPROTO_FTPS);
1114	REGISTER_CURL_CONSTANT(CURLPROTO_HTTP);
1115	REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS);
1116	REGISTER_CURL_CONSTANT(CURLPROTO_LDAP);
1117	REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS);
1118	REGISTER_CURL_CONSTANT(CURLPROTO_SCP);
1119	REGISTER_CURL_CONSTANT(CURLPROTO_SFTP);
1120	REGISTER_CURL_CONSTANT(CURLPROTO_TELNET);
1121	REGISTER_CURL_CONSTANT(CURLPROTO_TFTP);
1122
1123	REGISTER_CURL_CONSTANT(CURLPROXY_HTTP_1_0);
1124
1125	REGISTER_CURL_CONSTANT(CURLFTP_CREATE_DIR);
1126	REGISTER_CURL_CONSTANT(CURLFTP_CREATE_DIR_NONE);
1127	REGISTER_CURL_CONSTANT(CURLFTP_CREATE_DIR_RETRY);
1128#endif
1129
1130#if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */
1131	REGISTER_CURL_CONSTANT(CURL_VERSION_CURLDEBUG);
1132	REGISTER_CURL_CONSTANT(CURLOPT_SSH_KNOWNHOSTS);
1133#endif
1134
1135#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
1136	REGISTER_CURL_CONSTANT(CURLINFO_RTSP_CLIENT_CSEQ);
1137	REGISTER_CURL_CONSTANT(CURLINFO_RTSP_CSEQ_RECV);
1138	REGISTER_CURL_CONSTANT(CURLINFO_RTSP_SERVER_CSEQ);
1139	REGISTER_CURL_CONSTANT(CURLINFO_RTSP_SESSION_ID);
1140	REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_PRET);
1141	REGISTER_CURL_CONSTANT(CURLOPT_MAIL_FROM);
1142	REGISTER_CURL_CONSTANT(CURLOPT_MAIL_RCPT);
1143	REGISTER_CURL_CONSTANT(CURLOPT_RTSP_CLIENT_CSEQ);
1144	REGISTER_CURL_CONSTANT(CURLOPT_RTSP_REQUEST);
1145	REGISTER_CURL_CONSTANT(CURLOPT_RTSP_SERVER_CSEQ);
1146	REGISTER_CURL_CONSTANT(CURLOPT_RTSP_SESSION_ID);
1147	REGISTER_CURL_CONSTANT(CURLOPT_RTSP_STREAM_URI);
1148	REGISTER_CURL_CONSTANT(CURLOPT_RTSP_TRANSPORT);
1149	REGISTER_CURL_CONSTANT(CURLPROTO_IMAP);
1150	REGISTER_CURL_CONSTANT(CURLPROTO_IMAPS);
1151	REGISTER_CURL_CONSTANT(CURLPROTO_POP3);
1152	REGISTER_CURL_CONSTANT(CURLPROTO_POP3S);
1153	REGISTER_CURL_CONSTANT(CURLPROTO_RTSP);
1154	REGISTER_CURL_CONSTANT(CURLPROTO_SMTP);
1155	REGISTER_CURL_CONSTANT(CURLPROTO_SMTPS);
1156	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_ANNOUNCE);
1157	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_DESCRIBE);
1158	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_GET_PARAMETER);
1159	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_OPTIONS);
1160	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_PAUSE);
1161	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_PLAY);
1162	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_RECEIVE);
1163	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_RECORD);
1164	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_SET_PARAMETER);
1165	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_SETUP);
1166	REGISTER_CURL_CONSTANT(CURL_RTSPREQ_TEARDOWN);
1167#endif
1168
1169#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
1170	REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_IP);
1171	REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT);
1172	REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_PORT);
1173	REGISTER_CURL_CONSTANT(CURLOPT_FNMATCH_FUNCTION);
1174	REGISTER_CURL_CONSTANT(CURLOPT_WILDCARDMATCH);
1175	REGISTER_CURL_CONSTANT(CURLPROTO_RTMP);
1176	REGISTER_CURL_CONSTANT(CURLPROTO_RTMPE);
1177	REGISTER_CURL_CONSTANT(CURLPROTO_RTMPS);
1178	REGISTER_CURL_CONSTANT(CURLPROTO_RTMPT);
1179	REGISTER_CURL_CONSTANT(CURLPROTO_RTMPTE);
1180	REGISTER_CURL_CONSTANT(CURLPROTO_RTMPTS);
1181	REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_FAIL);
1182	REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_MATCH);
1183	REGISTER_CURL_CONSTANT(CURL_FNMATCHFUNC_NOMATCH);
1184#endif
1185
1186#if LIBCURL_VERSION_NUM >= 0x071502 /* Available since 7.21.2 */
1187	REGISTER_CURL_CONSTANT(CURLPROTO_GOPHER);
1188#endif
1189
1190#if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */
1191	REGISTER_CURL_CONSTANT(CURLAUTH_ONLY);
1192	REGISTER_CURL_CONSTANT(CURLOPT_RESOLVE);
1193#endif
1194
1195#if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */
1196	REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_PASSWORD);
1197	REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_TYPE);
1198	REGISTER_CURL_CONSTANT(CURLOPT_TLSAUTH_USERNAME);
1199	REGISTER_CURL_CONSTANT(CURL_TLSAUTH_SRP);
1200	REGISTER_CURL_CONSTANT(CURL_VERSION_TLSAUTH_SRP);
1201#endif
1202
1203#if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */
1204	REGISTER_CURL_CONSTANT(CURLOPT_ACCEPT_ENCODING);
1205	REGISTER_CURL_CONSTANT(CURLOPT_TRANSFER_ENCODING);
1206#endif
1207
1208#if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */
1209	REGISTER_CURL_CONSTANT(CURLAUTH_NTLM_WB);
1210	REGISTER_CURL_CONSTANT(CURLGSSAPI_DELEGATION_FLAG);
1211	REGISTER_CURL_CONSTANT(CURLGSSAPI_DELEGATION_POLICY_FLAG);
1212	REGISTER_CURL_CONSTANT(CURLOPT_GSSAPI_DELEGATION);
1213	REGISTER_CURL_CONSTANT(CURL_VERSION_NTLM_WB);
1214#endif
1215
1216#if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */
1217	REGISTER_CURL_CONSTANT(CURLOPT_ACCEPTTIMEOUT_MS);
1218	REGISTER_CURL_CONSTANT(CURLOPT_DNS_SERVERS);
1219#endif
1220
1221#if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */
1222	REGISTER_CURL_CONSTANT(CURLOPT_MAIL_AUTH);
1223	REGISTER_CURL_CONSTANT(CURLOPT_SSL_OPTIONS);
1224	REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPALIVE);
1225	REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPIDLE);
1226	REGISTER_CURL_CONSTANT(CURLOPT_TCP_KEEPINTVL);
1227	REGISTER_CURL_CONSTANT(CURLSSLOPT_ALLOW_BEAST);
1228#endif
1229
1230#if LIBCURL_VERSION_NUM >= 0x071901 /* Available since 7.25.1 */
1231	REGISTER_CURL_CONSTANT(CURL_REDIR_POST_303);
1232#endif
1233
1234#if LIBCURL_VERSION_NUM >= 0x071c00 /* Available since 7.28.0 */
1235	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_AGENT);
1236#endif
1237
1238#if LIBCURL_VERSION_NUM >= 0x071e00 /* Available since 7.30.0 */
1239	REGISTER_CURL_CONSTANT(CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE);
1240	REGISTER_CURL_CONSTANT(CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE);
1241	REGISTER_CURL_CONSTANT(CURLMOPT_MAX_HOST_CONNECTIONS);
1242	REGISTER_CURL_CONSTANT(CURLMOPT_MAX_PIPELINE_LENGTH);
1243	REGISTER_CURL_CONSTANT(CURLMOPT_MAX_TOTAL_CONNECTIONS);
1244#endif
1245
1246#if LIBCURL_VERSION_NUM >= 0x071f00 /* Available since 7.31.0 */
1247	REGISTER_CURL_CONSTANT(CURLOPT_SASL_IR);
1248#endif
1249
1250#if LIBCURL_VERSION_NUM >= 0x072100 /* Available since 7.33.0 */
1251	REGISTER_CURL_CONSTANT(CURLOPT_DNS_INTERFACE);
1252	REGISTER_CURL_CONSTANT(CURLOPT_DNS_LOCAL_IP4);
1253	REGISTER_CURL_CONSTANT(CURLOPT_DNS_LOCAL_IP6);
1254	REGISTER_CURL_CONSTANT(CURLOPT_XOAUTH2_BEARER);
1255
1256	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2_0);
1257	REGISTER_CURL_CONSTANT(CURL_VERSION_HTTP2);
1258#endif
1259
1260#if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */
1261	REGISTER_CURL_CONSTANT(CURLOPT_LOGIN_OPTIONS);
1262
1263	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_0);
1264	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_1);
1265	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_2);
1266#endif
1267
1268#if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */
1269	REGISTER_CURL_CONSTANT(CURLOPT_EXPECT_100_TIMEOUT_MS);
1270	REGISTER_CURL_CONSTANT(CURLOPT_SSL_ENABLE_ALPN);
1271	REGISTER_CURL_CONSTANT(CURLOPT_SSL_ENABLE_NPN);
1272#endif
1273
1274#if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
1275	REGISTER_CURL_CONSTANT(CURLHEADER_SEPARATE);
1276	REGISTER_CURL_CONSTANT(CURLHEADER_UNIFIED);
1277	REGISTER_CURL_CONSTANT(CURLOPT_HEADEROPT);
1278	REGISTER_CURL_CONSTANT(CURLOPT_PROXYHEADER);
1279#endif
1280
1281#if LIBCURL_VERSION_NUM >= 0x072600 /* Available since 7.38.0 */
1282	REGISTER_CURL_CONSTANT(CURLAUTH_NEGOTIATE);
1283	REGISTER_CURL_CONSTANT(CURL_VERSION_GSSAPI);
1284#endif
1285
1286#if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */
1287	REGISTER_CURL_CONSTANT(CURLOPT_PINNEDPUBLICKEY);
1288#endif
1289
1290#if LIBCURL_VERSION_NUM >= 0x072800 /* Available since 7.40.0 */
1291	REGISTER_CURL_CONSTANT(CURLOPT_UNIX_SOCKET_PATH);
1292	REGISTER_CURL_CONSTANT(CURLPROTO_SMB);
1293	REGISTER_CURL_CONSTANT(CURLPROTO_SMBS);
1294	REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS5);
1295	REGISTER_CURL_CONSTANT(CURL_VERSION_UNIX_SOCKETS);
1296#endif
1297
1298#if LIBCURL_VERSION_NUM >= 0x072900 /* Available since 7.41.0 */
1299	REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYSTATUS);
1300#endif
1301
1302#if LIBCURL_VERSION_NUM >= 0x072a00 /* Available since 7.42.0 */
1303	REGISTER_CURL_CONSTANT(CURLOPT_PATH_AS_IS);
1304	REGISTER_CURL_CONSTANT(CURLOPT_SSL_FALSESTART);
1305#endif
1306
1307#if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */
1308	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2);
1309
1310	REGISTER_CURL_CONSTANT(CURLOPT_PIPEWAIT);
1311	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SERVICE_NAME);
1312	REGISTER_CURL_CONSTANT(CURLOPT_SERVICE_NAME);
1313
1314	REGISTER_CURL_CONSTANT(CURLPIPE_NOTHING);
1315	REGISTER_CURL_CONSTANT(CURLPIPE_HTTP1);
1316	REGISTER_CURL_CONSTANT(CURLPIPE_MULTIPLEX);
1317#endif
1318
1319#if LIBCURL_VERSION_NUM >= 0x072c00 /* Available since 7.44.0 */
1320	REGISTER_CURL_CONSTANT(CURLSSLOPT_NO_REVOKE);
1321#endif
1322
1323#if LIBCURL_VERSION_NUM >= 0x072d00 /* Available since 7.45.0 */
1324	REGISTER_CURL_CONSTANT(CURLOPT_DEFAULT_PROTOCOL);
1325#endif
1326
1327#if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */
1328	REGISTER_CURL_CONSTANT(CURLOPT_STREAM_WEIGHT);
1329	REGISTER_CURL_CONSTANT(CURLMOPT_PUSHFUNCTION);
1330	REGISTER_CURL_CONSTANT(CURL_PUSH_OK);
1331	REGISTER_CURL_CONSTANT(CURL_PUSH_DENY);
1332#endif
1333
1334#if LIBCURL_VERSION_NUM >= 0x072f00 /* Available since 7.47.0 */
1335	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2TLS);
1336	REGISTER_CURL_CONSTANT(CURL_VERSION_PSL);
1337#endif
1338
1339#if LIBCURL_VERSION_NUM >= 0x073000 /* Available since 7.48.0 */
1340	REGISTER_CURL_CONSTANT(CURLOPT_TFTP_NO_OPTIONS);
1341#endif
1342
1343#if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
1344	REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE);
1345	REGISTER_CURL_CONSTANT(CURLOPT_CONNECT_TO);
1346	REGISTER_CURL_CONSTANT(CURLOPT_TCP_FASTOPEN);
1347#endif
1348
1349#if LIBCURL_VERSION_NUM >= 0x073200 /* Available since 7.50.0 */
1350	REGISTER_CURL_CONSTANT(CURLINFO_HTTP_VERSION);
1351#endif
1352
1353#if LIBCURL_VERSION_NUM >= 0x073300 /* Available since 7.51.0 */
1354	REGISTER_CURL_CONSTANT(CURLE_WEIRD_SERVER_REPLY);
1355	REGISTER_CURL_CONSTANT(CURLOPT_KEEP_SENDING_ON_ERROR);
1356#endif
1357
1358#if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
1359	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_TLSv1_3);
1360	REGISTER_CURL_CONSTANT(CURL_VERSION_HTTPS_PROXY);
1361	REGISTER_CURL_CONSTANT(CURLINFO_PROTOCOL);
1362	REGISTER_CURL_CONSTANT(CURLINFO_PROXY_SSL_VERIFYRESULT);
1363	REGISTER_CURL_CONSTANT(CURLINFO_SCHEME);
1364	REGISTER_CURL_CONSTANT(CURLOPT_PRE_PROXY);
1365	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_CAINFO);
1366	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_CAPATH);
1367	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_CRLFILE);
1368	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_KEYPASSWD);
1369	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_PINNEDPUBLICKEY);
1370	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_CIPHER_LIST);
1371	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_OPTIONS);
1372	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_VERIFYHOST);
1373	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSL_VERIFYPEER);
1374	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLCERT);
1375	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLCERTTYPE);
1376	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLKEY);
1377	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLKEYTYPE);
1378	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_SSLVERSION);
1379	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLSAUTH_PASSWORD);
1380	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLSAUTH_TYPE);
1381	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLSAUTH_USERNAME);
1382	REGISTER_CURL_CONSTANT(CURLPROXY_HTTPS);
1383#endif
1384
1385#if LIBCURL_VERSION_NUM >= 0x073500 /* Available since 7.53.0 */
1386	REGISTER_CURL_CONSTANT(CURL_MAX_READ_SIZE);
1387	REGISTER_CURL_CONSTANT(CURLOPT_ABSTRACT_UNIX_SOCKET);
1388#endif
1389
1390#if LIBCURL_VERSION_NUM >= 0x073600 /* Available since 7.54.0 */
1391	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_DEFAULT);
1392	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_NONE);
1393	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_0);
1394	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_1);
1395	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_2);
1396	REGISTER_CURL_CONSTANT(CURL_SSLVERSION_MAX_TLSv1_3);
1397	REGISTER_CURL_CONSTANT(CURLOPT_SUPPRESS_CONNECT_HEADERS);
1398#endif
1399
1400#if LIBCURL_VERSION_NUM >= 0x073601 /* Available since 7.54.1 */
1401	REGISTER_CURL_CONSTANT(CURLAUTH_GSSAPI);
1402#endif
1403
1404#if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
1405	REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD_T);
1406	REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD_T);
1407	REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD_T);
1408	REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD_T);
1409	REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD_T);
1410	REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD_T);
1411	REGISTER_CURL_CONSTANT(CURLOPT_REQUEST_TARGET);
1412	REGISTER_CURL_CONSTANT(CURLOPT_SOCKS5_AUTH);
1413#endif
1414
1415#if LIBCURL_VERSION_NUM >= 0x073800 /* Available since 7.56.0 */
1416	REGISTER_CURL_CONSTANT(CURLOPT_SSH_COMPRESSION);
1417	REGISTER_CURL_CONSTANT(CURL_VERSION_MULTI_SSL);
1418#endif
1419
1420#if LIBCURL_VERSION_NUM >= 0x073900 /* Available since 7.57.0 */
1421	REGISTER_CURL_CONSTANT(CURL_VERSION_BROTLI);
1422	REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_CONNECT);
1423#endif
1424
1425#if LIBCURL_VERSION_NUM >= 0x073a00 /* Available since 7.58.0 */
1426	REGISTER_CURL_CONSTANT(CURLSSH_AUTH_GSSAPI);
1427#endif
1428
1429#if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */
1430	REGISTER_CURL_CONSTANT(CURLINFO_FILETIME_T);
1431	REGISTER_CURL_CONSTANT(CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS);
1432	REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE_LARGE);
1433#endif
1434
1435#if LIBCURL_VERSION_NUM >= 0x073c00 /* Available since 7.60.0 */
1436	REGISTER_CURL_CONSTANT(CURLOPT_DNS_SHUFFLE_ADDRESSES);
1437	REGISTER_CURL_CONSTANT(CURLOPT_HAPROXYPROTOCOL);
1438#endif
1439
1440#if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
1441	REGISTER_CURL_CONSTANT(CURL_LOCK_DATA_PSL);
1442	REGISTER_CURL_CONSTANT(CURLAUTH_BEARER);
1443	REGISTER_CURL_CONSTANT(CURLINFO_APPCONNECT_TIME_T);
1444	REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME_T);
1445	REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME_T);
1446	REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME_T);
1447	REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME_T);
1448	REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME_T);
1449	REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME_T);
1450	REGISTER_CURL_CONSTANT(CURLOPT_DISALLOW_USERNAME_IN_URL);
1451	REGISTER_CURL_CONSTANT(CURLOPT_PROXY_TLS13_CIPHERS);
1452	REGISTER_CURL_CONSTANT(CURLOPT_TLS13_CIPHERS);
1453#endif
1454
1455#if LIBCURL_VERSION_NUM >= 0x074000 /* Available since 7.64.0 */
1456	REGISTER_CURL_CONSTANT(CURLOPT_HTTP09_ALLOWED);
1457#endif
1458
1459#if LIBCURL_VERSION_NUM >= 0x074001 /* Available since 7.64.1 */
1460	REGISTER_CURL_CONSTANT(CURL_VERSION_ALTSVC);
1461#endif
1462
1463	REGISTER_CURL_CONSTANT(CURLOPT_SAFE_UPLOAD);
1464
1465#ifdef PHP_CURL_NEED_OPENSSL_TSL
1466	if (!CRYPTO_get_id_callback()) {
1467		int i, c = CRYPTO_num_locks();
1468
1469		php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
1470		if (!php_curl_openssl_tsl) {
1471			return FAILURE;
1472		}
1473
1474		for (i = 0; i < c; ++i) {
1475			php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
1476		}
1477
1478		CRYPTO_set_id_callback(php_curl_ssl_id);
1479		CRYPTO_set_locking_callback(php_curl_ssl_lock);
1480	}
1481#endif
1482#ifdef PHP_CURL_NEED_GNUTLS_TSL
1483	gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl);
1484#endif
1485
1486	if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) {
1487		return FAILURE;
1488	}
1489
1490	curlfile_register_class();
1491
1492	return SUCCESS;
1493}
1494/* }}} */
1495
1496/* {{{ PHP_MSHUTDOWN_FUNCTION
1497 */
1498PHP_MSHUTDOWN_FUNCTION(curl)
1499{
1500	curl_global_cleanup();
1501#ifdef PHP_CURL_NEED_OPENSSL_TSL
1502	if (php_curl_openssl_tsl) {
1503		int i, c = CRYPTO_num_locks();
1504
1505		CRYPTO_set_id_callback(NULL);
1506		CRYPTO_set_locking_callback(NULL);
1507
1508		for (i = 0; i < c; ++i) {
1509			tsrm_mutex_free(php_curl_openssl_tsl[i]);
1510		}
1511
1512		free(php_curl_openssl_tsl);
1513		php_curl_openssl_tsl = NULL;
1514	}
1515#endif
1516	UNREGISTER_INI_ENTRIES();
1517	return SUCCESS;
1518}
1519/* }}} */
1520
1521/* {{{ curl_write_nothing
1522 * Used as a work around. See _php_curl_close_ex
1523 */
1524static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx)
1525{
1526	return size * nmemb;
1527}
1528/* }}} */
1529
1530/* {{{ curl_write
1531 */
1532static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
1533{
1534	php_curl *ch = (php_curl *) ctx;
1535	php_curl_write *t = ch->handlers->write;
1536	size_t length = size * nmemb;
1537
1538#if PHP_CURL_DEBUG
1539	fprintf(stderr, "curl_write() called\n");
1540	fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx);
1541#endif
1542
1543	switch (t->method) {
1544		case PHP_CURL_STDOUT:
1545			PHPWRITE(data, length);
1546			break;
1547		case PHP_CURL_FILE:
1548			return fwrite(data, size, nmemb, t->fp);
1549		case PHP_CURL_RETURN:
1550			if (length > 0) {
1551				smart_str_appendl(&t->buf, data, (int) length);
1552			}
1553			break;
1554		case PHP_CURL_USER: {
1555			zval argv[2];
1556			zval retval;
1557			int  error;
1558			zend_fcall_info fci;
1559
1560			GC_ADDREF(ch->res);
1561			ZVAL_RES(&argv[0], ch->res);
1562			ZVAL_STRINGL(&argv[1], data, length);
1563
1564			fci.size = sizeof(fci);
1565			fci.object = NULL;
1566			ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1567			fci.retval = &retval;
1568			fci.param_count = 2;
1569			fci.params = argv;
1570			fci.no_separation = 0;
1571
1572			ch->in_callback = 1;
1573			error = zend_call_function(&fci, &t->fci_cache);
1574			ch->in_callback = 0;
1575			if (error == FAILURE) {
1576				php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
1577				length = -1;
1578			} else if (!Z_ISUNDEF(retval)) {
1579				_php_curl_verify_handlers(ch, 1);
1580				length = zval_get_long(&retval);
1581			}
1582
1583			zval_ptr_dtor(&argv[0]);
1584			zval_ptr_dtor(&argv[1]);
1585			break;
1586		}
1587	}
1588
1589	return length;
1590}
1591/* }}} */
1592
1593#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
1594/* {{{ curl_fnmatch
1595 */
1596static int curl_fnmatch(void *ctx, const char *pattern, const char *string)
1597{
1598	php_curl *ch = (php_curl *) ctx;
1599	php_curl_fnmatch *t = ch->handlers->fnmatch;
1600	int rval = CURL_FNMATCHFUNC_FAIL;
1601	switch (t->method) {
1602		case PHP_CURL_USER: {
1603			zval argv[3];
1604			zval retval;
1605			int  error;
1606			zend_fcall_info fci;
1607
1608			GC_ADDREF(ch->res);
1609			ZVAL_RES(&argv[0], ch->res);
1610			ZVAL_STRING(&argv[1], pattern);
1611			ZVAL_STRING(&argv[2], string);
1612
1613			fci.size = sizeof(fci);
1614			ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1615			fci.object = NULL;
1616			fci.retval = &retval;
1617			fci.param_count = 3;
1618			fci.params = argv;
1619			fci.no_separation = 0;
1620
1621			ch->in_callback = 1;
1622			error = zend_call_function(&fci, &t->fci_cache);
1623			ch->in_callback = 0;
1624			if (error == FAILURE) {
1625				php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_FNMATCH_FUNCTION");
1626			} else if (!Z_ISUNDEF(retval)) {
1627				_php_curl_verify_handlers(ch, 1);
1628				rval = zval_get_long(&retval);
1629			}
1630			zval_ptr_dtor(&argv[0]);
1631			zval_ptr_dtor(&argv[1]);
1632			zval_ptr_dtor(&argv[2]);
1633			break;
1634		}
1635	}
1636	return rval;
1637}
1638/* }}} */
1639#endif
1640
1641/* {{{ curl_progress
1642 */
1643static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
1644{
1645	php_curl *ch = (php_curl *)clientp;
1646	php_curl_progress *t = ch->handlers->progress;
1647	size_t	rval = 0;
1648
1649#if PHP_CURL_DEBUG
1650	fprintf(stderr, "curl_progress() called\n");
1651	fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow);
1652#endif
1653
1654	switch (t->method) {
1655		case PHP_CURL_USER: {
1656			zval argv[5];
1657			zval retval;
1658			int  error;
1659			zend_fcall_info fci;
1660
1661			GC_ADDREF(ch->res);
1662			ZVAL_RES(&argv[0], ch->res);
1663			ZVAL_LONG(&argv[1], (zend_long)dltotal);
1664			ZVAL_LONG(&argv[2], (zend_long)dlnow);
1665			ZVAL_LONG(&argv[3], (zend_long)ultotal);
1666			ZVAL_LONG(&argv[4], (zend_long)ulnow);
1667
1668			fci.size = sizeof(fci);
1669			ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1670			fci.object = NULL;
1671			fci.retval = &retval;
1672			fci.param_count = 5;
1673			fci.params = argv;
1674			fci.no_separation = 0;
1675
1676			ch->in_callback = 1;
1677			error = zend_call_function(&fci, &t->fci_cache);
1678			ch->in_callback = 0;
1679			if (error == FAILURE) {
1680				php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION");
1681			} else if (!Z_ISUNDEF(retval)) {
1682				_php_curl_verify_handlers(ch, 1);
1683				if (0 != zval_get_long(&retval)) {
1684					rval = 1;
1685				}
1686			}
1687			zval_ptr_dtor(&argv[0]);
1688			break;
1689		}
1690	}
1691	return rval;
1692}
1693/* }}} */
1694
1695/* {{{ curl_read
1696 */
1697static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
1698{
1699	php_curl *ch = (php_curl *)ctx;
1700	php_curl_read *t = ch->handlers->read;
1701	int length = 0;
1702
1703	switch (t->method) {
1704		case PHP_CURL_DIRECT:
1705			if (t->fp) {
1706				length = fread(data, size, nmemb, t->fp);
1707			}
1708			break;
1709		case PHP_CURL_USER: {
1710			zval argv[3];
1711			zval retval;
1712			int  error;
1713			zend_fcall_info fci;
1714
1715			GC_ADDREF(ch->res);
1716			ZVAL_RES(&argv[0], ch->res);
1717			if (t->res) {
1718				GC_ADDREF(t->res);
1719				ZVAL_RES(&argv[1], t->res);
1720			} else {
1721				ZVAL_NULL(&argv[1]);
1722			}
1723			ZVAL_LONG(&argv[2], (int)size * nmemb);
1724
1725			fci.size = sizeof(fci);
1726			ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1727			fci.object = NULL;
1728			fci.retval = &retval;
1729			fci.param_count = 3;
1730			fci.params = argv;
1731			fci.no_separation = 0;
1732
1733			ch->in_callback = 1;
1734			error = zend_call_function(&fci, &t->fci_cache);
1735			ch->in_callback = 0;
1736			if (error == FAILURE) {
1737				php_error_docref(NULL, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
1738				length = CURL_READFUNC_ABORT;
1739			} else if (!Z_ISUNDEF(retval)) {
1740				_php_curl_verify_handlers(ch, 1);
1741				if (Z_TYPE(retval) == IS_STRING) {
1742					length = MIN((int) (size * nmemb), Z_STRLEN(retval));
1743					memcpy(data, Z_STRVAL(retval), length);
1744				}
1745				zval_ptr_dtor(&retval);
1746			}
1747
1748			zval_ptr_dtor(&argv[0]);
1749			zval_ptr_dtor(&argv[1]);
1750			break;
1751		}
1752	}
1753
1754	return length;
1755}
1756/* }}} */
1757
1758/* {{{ curl_write_header
1759 */
1760static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
1761{
1762	php_curl *ch = (php_curl *) ctx;
1763	php_curl_write *t = ch->handlers->write_header;
1764	size_t length = size * nmemb;
1765
1766	switch (t->method) {
1767		case PHP_CURL_STDOUT:
1768			/* Handle special case write when we're returning the entire transfer
1769			 */
1770			if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) {
1771				smart_str_appendl(&ch->handlers->write->buf, data, (int) length);
1772			} else {
1773				PHPWRITE(data, length);
1774			}
1775			break;
1776		case PHP_CURL_FILE:
1777			return fwrite(data, size, nmemb, t->fp);
1778		case PHP_CURL_USER: {
1779			zval argv[2];
1780			zval retval;
1781			int  error;
1782			zend_fcall_info fci;
1783
1784			GC_ADDREF(ch->res);
1785			ZVAL_RES(&argv[0], ch->res);
1786			ZVAL_STRINGL(&argv[1], data, length);
1787
1788			fci.size = sizeof(fci);
1789			ZVAL_COPY_VALUE(&fci.function_name, &t->func_name);
1790			fci.object = NULL;
1791			fci.retval = &retval;
1792			fci.param_count = 2;
1793			fci.params = argv;
1794			fci.no_separation = 0;
1795
1796			ch->in_callback = 1;
1797			error = zend_call_function(&fci, &t->fci_cache);
1798			ch->in_callback = 0;
1799			if (error == FAILURE) {
1800				php_error_docref(NULL, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
1801				length = -1;
1802			} else if (!Z_ISUNDEF(retval)) {
1803				_php_curl_verify_handlers(ch, 1);
1804				length = zval_get_long(&retval);
1805			}
1806			zval_ptr_dtor(&argv[0]);
1807			zval_ptr_dtor(&argv[1]);
1808			break;
1809		}
1810
1811		case PHP_CURL_IGNORE:
1812			return length;
1813
1814		default:
1815			return -1;
1816	}
1817
1818	return length;
1819}
1820/* }}} */
1821
1822static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */
1823{
1824	php_curl *ch = (php_curl *)ctx;
1825
1826	if (type == CURLINFO_HEADER_OUT) {
1827		if (ch->header.str) {
1828			zend_string_release_ex(ch->header.str, 0);
1829		}
1830		if (buf_len > 0) {
1831			ch->header.str = zend_string_init(buf, buf_len, 0);
1832		}
1833	}
1834
1835	return 0;
1836}
1837/* }}} */
1838
1839/* {{{ curl_free_string
1840 */
1841static void curl_free_string(void **string)
1842{
1843	efree((char *)*string);
1844}
1845/* }}} */
1846
1847/* {{{ curl_free_post
1848 */
1849static void curl_free_post(void **post)
1850{
1851#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
1852	curl_mime_free((curl_mime *)*post);
1853#else
1854	curl_formfree((struct HttpPost *)*post);
1855#endif
1856}
1857/* }}} */
1858
1859/* {{{ curl_free_slist
1860 */
1861static void curl_free_slist(zval *el)
1862{
1863	curl_slist_free_all(((struct curl_slist *)Z_PTR_P(el)));
1864}
1865/* }}} */
1866
1867/* {{{ proto array curl_version([int version])
1868   Return cURL version information. */
1869PHP_FUNCTION(curl_version)
1870{
1871	curl_version_info_data *d;
1872	zend_long uversion = CURLVERSION_NOW;
1873
1874	ZEND_PARSE_PARAMETERS_START(0, 1)
1875		Z_PARAM_OPTIONAL
1876		Z_PARAM_LONG(uversion)
1877	ZEND_PARSE_PARAMETERS_END();
1878
1879	d = curl_version_info(uversion);
1880	if (d == NULL) {
1881		RETURN_FALSE;
1882	}
1883
1884	array_init(return_value);
1885
1886	CAAL("version_number", d->version_num);
1887	CAAL("age", d->age);
1888	CAAL("features", d->features);
1889	CAAL("ssl_version_number", d->ssl_version_num);
1890	CAAS("version", d->version);
1891	CAAS("host", d->host);
1892	CAAS("ssl_version", d->ssl_version);
1893	CAAS("libz_version", d->libz_version);
1894	/* Add an array of protocols */
1895	{
1896		char **p = (char **) d->protocols;
1897		zval protocol_list;
1898
1899		array_init(&protocol_list);
1900
1901		while (*p != NULL) {
1902			add_next_index_string(&protocol_list, *p);
1903			p++;
1904		}
1905		CAAZ("protocols", &protocol_list);
1906	}
1907	if (d->age >= 1) {
1908		CAAS("ares", d->ares);
1909		CAAL("ares_num", d->ares_num);
1910	}
1911	if (d->age >= 2) {
1912		CAAS("libidn", d->libidn);
1913	}
1914#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
1915	if (d->age >= 3) {
1916		CAAL("iconv_ver_num", d->iconv_ver_num);
1917		CAAS("libssh_version", d->libssh_version);
1918	}
1919#endif
1920#if LIBCURL_VERSION_NUM >= 0x073900 /* Available since 7.57.0 */
1921	if (d->age >= 4) {
1922		CAAL("brotli_ver_num", d->brotli_ver_num);
1923		CAAS("brotli_version", d->brotli_version);
1924	}
1925#endif
1926}
1927/* }}} */
1928
1929/* {{{ alloc_curl_handle
1930 */
1931php_curl *alloc_curl_handle()
1932{
1933	php_curl *ch               = ecalloc(1, sizeof(php_curl));
1934	ch->to_free                = ecalloc(1, sizeof(struct _php_curl_free));
1935	ch->handlers               = ecalloc(1, sizeof(php_curl_handlers));
1936	ch->handlers->write        = ecalloc(1, sizeof(php_curl_write));
1937	ch->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
1938	ch->handlers->read         = ecalloc(1, sizeof(php_curl_read));
1939	ch->handlers->progress     = NULL;
1940#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
1941	ch->handlers->fnmatch      = NULL;
1942#endif
1943	ch->clone 				   = emalloc(sizeof(uint32_t));
1944	*ch->clone                 = 1;
1945
1946	memset(&ch->err, 0, sizeof(struct _php_curl_error));
1947
1948	zend_llist_init(&ch->to_free->str,   sizeof(char *),          (llist_dtor_func_t)curl_free_string, 0);
1949	zend_llist_init(&ch->to_free->post,  sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post,   0);
1950
1951	ch->to_free->slist = emalloc(sizeof(HashTable));
1952	zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0);
1953
1954	return ch;
1955}
1956/* }}} */
1957
1958#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
1959/* {{{ create_certinfo
1960 */
1961static void create_certinfo(struct curl_certinfo *ci, zval *listcode)
1962{
1963	int i;
1964
1965	if (ci) {
1966		zval certhash;
1967
1968		for (i=0; i<ci->num_of_certs; i++) {
1969			struct curl_slist *slist;
1970
1971			array_init(&certhash);
1972			for (slist = ci->certinfo[i]; slist; slist = slist->next) {
1973				int len;
1974				char s[64];
1975				char *tmp;
1976				strncpy(s, slist->data, sizeof(s));
1977				s[sizeof(s)-1] = '\0';
1978				tmp = memchr(s, ':', sizeof(s));
1979				if(tmp) {
1980					*tmp = '\0';
1981					len = strlen(s);
1982					add_assoc_string(&certhash, s, &slist->data[len+1]);
1983				} else {
1984					php_error_docref(NULL, E_WARNING, "Could not extract hash key from certificate info");
1985				}
1986			}
1987			add_next_index_zval(listcode, &certhash);
1988		}
1989	}
1990}
1991/* }}} */
1992#endif
1993
1994/* {{{ _php_curl_set_default_options()
1995   Set default options for a handle */
1996static void _php_curl_set_default_options(php_curl *ch)
1997{
1998	char *cainfo;
1999
2000	curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS,        1);
2001	curl_easy_setopt(ch->cp, CURLOPT_VERBOSE,           0);
2002	curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
2003	curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION,     curl_write);
2004	curl_easy_setopt(ch->cp, CURLOPT_FILE,              (void *) ch);
2005	curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION,      curl_read);
2006	curl_easy_setopt(ch->cp, CURLOPT_INFILE,            (void *) ch);
2007	curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION,    curl_write_header);
2008	curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER,       (void *) ch);
2009#if !defined(ZTS)
2010	curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1);
2011#endif
2012	curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
2013	curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */
2014
2015	cainfo = INI_STR("openssl.cafile");
2016	if (!(cainfo && cainfo[0] != '\0')) {
2017		cainfo = INI_STR("curl.cainfo");
2018	}
2019	if (cainfo && cainfo[0] != '\0') {
2020		curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo);
2021	}
2022
2023#if defined(ZTS)
2024	curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1);
2025#endif
2026}
2027/* }}} */
2028
2029/* {{{ proto resource curl_init([string url])
2030   Initialize a cURL session */
2031PHP_FUNCTION(curl_init)
2032{
2033	php_curl *ch;
2034	CURL 	 *cp;
2035	zend_string *url = NULL;
2036
2037	ZEND_PARSE_PARAMETERS_START(0,1)
2038		Z_PARAM_OPTIONAL
2039		Z_PARAM_STR(url)
2040	ZEND_PARSE_PARAMETERS_END();
2041
2042	cp = curl_easy_init();
2043	if (!cp) {
2044		php_error_docref(NULL, E_WARNING, "Could not initialize a new cURL handle");
2045		RETURN_FALSE;
2046	}
2047
2048	ch = alloc_curl_handle();
2049
2050	ch->cp = cp;
2051
2052	ch->handlers->write->method = PHP_CURL_STDOUT;
2053	ch->handlers->read->method  = PHP_CURL_DIRECT;
2054	ch->handlers->write_header->method = PHP_CURL_IGNORE;
2055
2056	_php_curl_set_default_options(ch);
2057
2058	if (url) {
2059		if (php_curl_option_url(ch, ZSTR_VAL(url), ZSTR_LEN(url)) == FAILURE) {
2060			_php_curl_close_ex(ch);
2061			RETURN_FALSE;
2062		}
2063	}
2064
2065	ZVAL_RES(return_value, zend_register_resource(ch, le_curl));
2066	ch->res = Z_RES_P(return_value);
2067}
2068/* }}} */
2069
2070void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source)
2071{
2072	if (!Z_ISUNDEF(source->handlers->write->stream)) {
2073		Z_ADDREF(source->handlers->write->stream);
2074	}
2075	ch->handlers->write->stream = source->handlers->write->stream;
2076	ch->handlers->write->method = source->handlers->write->method;
2077	if (!Z_ISUNDEF(source->handlers->read->stream)) {
2078		Z_ADDREF(source->handlers->read->stream);
2079	}
2080	ch->handlers->read->stream  = source->handlers->read->stream;
2081	ch->handlers->read->method  = source->handlers->read->method;
2082	ch->handlers->write_header->method = source->handlers->write_header->method;
2083	if (!Z_ISUNDEF(source->handlers->write_header->stream)) {
2084		Z_ADDREF(source->handlers->write_header->stream);
2085	}
2086	ch->handlers->write_header->stream = source->handlers->write_header->stream;
2087
2088	ch->handlers->write->fp = source->handlers->write->fp;
2089	ch->handlers->write_header->fp = source->handlers->write_header->fp;
2090	ch->handlers->read->fp = source->handlers->read->fp;
2091	ch->handlers->read->res = source->handlers->read->res;
2092#if CURLOPT_PASSWDDATA != 0
2093	if (!Z_ISUNDEF(source->handlers->passwd)) {
2094		ZVAL_COPY(&ch->handlers->passwd, &source->handlers->passwd);
2095		curl_easy_setopt(source->cp, CURLOPT_PASSWDDATA, (void *) ch);
2096	}
2097#endif
2098	if (!Z_ISUNDEF(source->handlers->write->func_name)) {
2099		ZVAL_COPY(&ch->handlers->write->func_name, &source->handlers->write->func_name);
2100	}
2101	if (!Z_ISUNDEF(source->handlers->read->func_name)) {
2102		ZVAL_COPY(&ch->handlers->read->func_name, &source->handlers->read->func_name);
2103	}
2104	if (!Z_ISUNDEF(source->handlers->write_header->func_name)) {
2105		ZVAL_COPY(&ch->handlers->write_header->func_name, &source->handlers->write_header->func_name);
2106	}
2107
2108	curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER,       ch->err.str);
2109	curl_easy_setopt(ch->cp, CURLOPT_FILE,              (void *) ch);
2110	curl_easy_setopt(ch->cp, CURLOPT_INFILE,            (void *) ch);
2111	curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER,       (void *) ch);
2112
2113	if (source->handlers->progress) {
2114		ch->handlers->progress = ecalloc(1, sizeof(php_curl_progress));
2115		if (!Z_ISUNDEF(source->handlers->progress->func_name)) {
2116			ZVAL_COPY(&ch->handlers->progress->func_name, &source->handlers->progress->func_name);
2117		}
2118		ch->handlers->progress->method = source->handlers->progress->method;
2119		curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, (void *) ch);
2120	}
2121
2122#if LIBCURL_VERSION_NUM >= 0x071500
2123	if (source->handlers->fnmatch) {
2124		ch->handlers->fnmatch = ecalloc(1, sizeof(php_curl_fnmatch));
2125		if (!Z_ISUNDEF(source->handlers->fnmatch->func_name)) {
2126			ZVAL_COPY(&ch->handlers->fnmatch->func_name, &source->handlers->fnmatch->func_name);
2127		}
2128		ch->handlers->fnmatch->method = source->handlers->fnmatch->method;
2129		curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, (void *) ch);
2130	}
2131#endif
2132
2133	efree(ch->to_free->slist);
2134	efree(ch->to_free);
2135	ch->to_free = source->to_free;
2136	efree(ch->clone);
2137	ch->clone = source->clone;
2138
2139	/* Keep track of cloned copies to avoid invoking curl destructors for every clone */
2140	(*source->clone)++;
2141}
2142
2143/* {{{ proto resource curl_copy_handle(resource ch)
2144   Copy a cURL handle along with all of it's preferences */
2145PHP_FUNCTION(curl_copy_handle)
2146{
2147	CURL		*cp;
2148	zval		*zid;
2149	php_curl	*ch, *dupch;
2150
2151	ZEND_PARSE_PARAMETERS_START(1,1)
2152		Z_PARAM_RESOURCE(zid)
2153	ZEND_PARSE_PARAMETERS_END();
2154
2155	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
2156		RETURN_FALSE;
2157	}
2158
2159	cp = curl_easy_duphandle(ch->cp);
2160	if (!cp) {
2161		php_error_docref(NULL, E_WARNING, "Cannot duplicate cURL handle");
2162		RETURN_FALSE;
2163	}
2164
2165	dupch = alloc_curl_handle();
2166	dupch->cp = cp;
2167
2168	_php_setup_easy_copy_handlers(dupch, ch);
2169
2170	ZVAL_RES(return_value, zend_register_resource(dupch, le_curl));
2171	dupch->res = Z_RES_P(return_value);
2172}
2173/* }}} */
2174
2175static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ */
2176{
2177	CURLcode error = CURLE_OK;
2178	zend_long lval;
2179
2180	switch (option) {
2181		/* Long options */
2182		case CURLOPT_SSL_VERIFYHOST:
2183			lval = zval_get_long(zvalue);
2184			if (lval == 1) {
2185#if LIBCURL_VERSION_NUM <= 0x071c00 /* 7.28.0 */
2186				php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST with value 1 is deprecated and will be removed as of libcurl 7.28.1. It is recommended to use value 2 instead");
2187#else
2188				php_error_docref(NULL, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead");
2189				error = curl_easy_setopt(ch->cp, option, 2);
2190				break;
2191#endif
2192			}
2193		case CURLOPT_AUTOREFERER:
2194		case CURLOPT_BUFFERSIZE:
2195		case CURLOPT_CONNECTTIMEOUT:
2196		case CURLOPT_COOKIESESSION:
2197		case CURLOPT_CRLF:
2198		case CURLOPT_DNS_CACHE_TIMEOUT:
2199		case CURLOPT_DNS_USE_GLOBAL_CACHE:
2200		case CURLOPT_FAILONERROR:
2201		case CURLOPT_FILETIME:
2202		case CURLOPT_FORBID_REUSE:
2203		case CURLOPT_FRESH_CONNECT:
2204		case CURLOPT_FTP_USE_EPRT:
2205		case CURLOPT_FTP_USE_EPSV:
2206		case CURLOPT_HEADER:
2207		case CURLOPT_HTTPGET:
2208		case CURLOPT_HTTPPROXYTUNNEL:
2209		case CURLOPT_HTTP_VERSION:
2210		case CURLOPT_INFILESIZE:
2211		case CURLOPT_LOW_SPEED_LIMIT:
2212		case CURLOPT_LOW_SPEED_TIME:
2213		case CURLOPT_MAXCONNECTS:
2214		case CURLOPT_MAXREDIRS:
2215		case CURLOPT_NETRC:
2216		case CURLOPT_NOBODY:
2217		case CURLOPT_NOPROGRESS:
2218		case CURLOPT_NOSIGNAL:
2219		case CURLOPT_PORT:
2220		case CURLOPT_POST:
2221		case CURLOPT_PROXYPORT:
2222		case CURLOPT_PROXYTYPE:
2223		case CURLOPT_PUT:
2224		case CURLOPT_RESUME_FROM:
2225		case CURLOPT_SSLVERSION:
2226		case CURLOPT_SSL_VERIFYPEER:
2227		case CURLOPT_TIMECONDITION:
2228		case CURLOPT_TIMEOUT:
2229		case CURLOPT_TIMEVALUE:
2230		case CURLOPT_TRANSFERTEXT:
2231		case CURLOPT_UNRESTRICTED_AUTH:
2232		case CURLOPT_UPLOAD:
2233		case CURLOPT_VERBOSE:
2234		case CURLOPT_HTTPAUTH:
2235		case CURLOPT_FTP_CREATE_MISSING_DIRS:
2236		case CURLOPT_PROXYAUTH:
2237		case CURLOPT_FTP_RESPONSE_TIMEOUT:
2238		case CURLOPT_IPRESOLVE:
2239		case CURLOPT_MAXFILESIZE:
2240		case CURLOPT_TCP_NODELAY:
2241		case CURLOPT_FTPSSLAUTH:
2242		case CURLOPT_IGNORE_CONTENT_LENGTH:
2243		case CURLOPT_FTP_SKIP_PASV_IP:
2244		case CURLOPT_FTP_FILEMETHOD:
2245		case CURLOPT_CONNECT_ONLY:
2246		case CURLOPT_LOCALPORT:
2247		case CURLOPT_LOCALPORTRANGE:
2248#if LIBCURL_VERSION_NUM >= 0x071000 /* Available since 7.16.0 */
2249		case CURLOPT_SSL_SESSIONID_CACHE:
2250#endif
2251#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
2252		case CURLOPT_FTP_SSL_CCC:
2253		case CURLOPT_SSH_AUTH_TYPES:
2254#endif
2255#if LIBCURL_VERSION_NUM >= 0x071002 /* Available since 7.16.2 */
2256		case CURLOPT_CONNECTTIMEOUT_MS:
2257		case CURLOPT_HTTP_CONTENT_DECODING:
2258		case CURLOPT_HTTP_TRANSFER_DECODING:
2259		case CURLOPT_TIMEOUT_MS:
2260#endif
2261#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
2262		case CURLOPT_NEW_DIRECTORY_PERMS:
2263		case CURLOPT_NEW_FILE_PERMS:
2264#endif
2265#if LIBCURL_VERSION_NUM >= 0x071100 /* Available since 7.17.0 */
2266		case CURLOPT_USE_SSL:
2267		case CURLOPT_APPEND:
2268		case CURLOPT_DIRLISTONLY:
2269#else
2270		case CURLOPT_FTP_SSL:
2271		case CURLOPT_FTPAPPEND:
2272		case CURLOPT_FTPLISTONLY:
2273#endif
2274#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
2275		case CURLOPT_PROXY_TRANSFER_MODE:
2276#endif
2277#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
2278		case CURLOPT_ADDRESS_SCOPE:
2279#endif
2280#if LIBCURL_VERSION_NUM >  0x071301 /* Available since 7.19.1 */
2281		case CURLOPT_CERTINFO:
2282#endif
2283#if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */
2284		case CURLOPT_PROTOCOLS:
2285		case CURLOPT_REDIR_PROTOCOLS:
2286		case CURLOPT_SOCKS5_GSSAPI_NEC:
2287		case CURLOPT_TFTP_BLKSIZE:
2288#endif
2289#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2290		case CURLOPT_FTP_USE_PRET:
2291		case CURLOPT_RTSP_CLIENT_CSEQ:
2292		case CURLOPT_RTSP_REQUEST:
2293		case CURLOPT_RTSP_SERVER_CSEQ:
2294#endif
2295#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
2296		case CURLOPT_WILDCARDMATCH:
2297#endif
2298#if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */
2299		case CURLOPT_TLSAUTH_TYPE:
2300#endif
2301#if LIBCURL_VERSION_NUM >= 0x071600 /* Available since 7.22.0 */
2302		case CURLOPT_GSSAPI_DELEGATION:
2303#endif
2304#if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */
2305		case CURLOPT_ACCEPTTIMEOUT_MS:
2306#endif
2307#if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */
2308		case CURLOPT_SSL_OPTIONS:
2309		case CURLOPT_TCP_KEEPALIVE:
2310		case CURLOPT_TCP_KEEPIDLE:
2311		case CURLOPT_TCP_KEEPINTVL:
2312#endif
2313#if LIBCURL_VERSION_NUM >= 0x071f00 /* Available since 7.31.0 */
2314		case CURLOPT_SASL_IR:
2315#endif
2316#if LIBCURL_VERSION_NUM >= 0x072400 /* Available since 7.36.0 */
2317		case CURLOPT_EXPECT_100_TIMEOUT_MS:
2318		case CURLOPT_SSL_ENABLE_ALPN:
2319		case CURLOPT_SSL_ENABLE_NPN:
2320#endif
2321#if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
2322		case CURLOPT_HEADEROPT:
2323#endif
2324#if LIBCURL_VERSION_NUM >= 0x072900 /* Available since 7.41.0 */
2325		case CURLOPT_SSL_VERIFYSTATUS:
2326#endif
2327#if LIBCURL_VERSION_NUM >= 0x072a00 /* Available since 7.42.0 */
2328		case CURLOPT_PATH_AS_IS:
2329		case CURLOPT_SSL_FALSESTART:
2330#endif
2331#if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */
2332		case CURLOPT_PIPEWAIT:
2333#endif
2334#if LIBCURL_VERSION_NUM >= 0x072e00 /* Available since 7.46.0 */
2335		case CURLOPT_STREAM_WEIGHT:
2336#endif
2337#if LIBCURL_VERSION_NUM >= 0x073000 /* Available since 7.48.0 */
2338		case CURLOPT_TFTP_NO_OPTIONS:
2339#endif
2340#if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
2341		case CURLOPT_TCP_FASTOPEN:
2342#endif
2343#if LIBCURL_VERSION_NUM >= 0x073300 /* Available since 7.51.0 */
2344		case CURLOPT_KEEP_SENDING_ON_ERROR:
2345#endif
2346#if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
2347		case CURLOPT_PROXY_SSL_OPTIONS:
2348		case CURLOPT_PROXY_SSL_VERIFYHOST:
2349		case CURLOPT_PROXY_SSL_VERIFYPEER:
2350		case CURLOPT_PROXY_SSLVERSION:
2351#endif
2352#if LIBCURL_VERSION_NUM >= 0x073600 /* Available since 7.54.0 */
2353		case CURLOPT_SUPPRESS_CONNECT_HEADERS:
2354#endif
2355#if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
2356		case CURLOPT_SOCKS5_AUTH:
2357#endif
2358#if LIBCURL_VERSION_NUM >= 0x073800 /* Available since 7.56.0 */
2359		case CURLOPT_SSH_COMPRESSION:
2360#endif
2361#if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */
2362		case CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS:
2363#endif
2364#if LIBCURL_VERSION_NUM >= 0x073c00 /* Available since 7.60.0 */
2365		case CURLOPT_DNS_SHUFFLE_ADDRESSES:
2366		case CURLOPT_HAPROXYPROTOCOL:
2367#endif
2368#if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
2369		case CURLOPT_DISALLOW_USERNAME_IN_URL:
2370#endif
2371#if LIBCURL_VERSION_NUM >= 0x074000 /* Available since 7.64.0 */
2372		case CURLOPT_HTTP09_ALLOWED:
2373#endif
2374			lval = zval_get_long(zvalue);
2375#if LIBCURL_VERSION_NUM >= 0x071304
2376			if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
2377				(PG(open_basedir) && *PG(open_basedir)) && (lval & CURLPROTO_FILE)) {
2378					php_error_docref(NULL, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set");
2379					return 1;
2380			}
2381#endif
2382# if defined(ZTS)
2383			if (option == CURLOPT_DNS_USE_GLOBAL_CACHE && lval) {
2384				php_error_docref(NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled");
2385				return 1;
2386			}
2387# endif
2388			error = curl_easy_setopt(ch->cp, option, lval);
2389			break;
2390		case CURLOPT_SAFE_UPLOAD:
2391			if (!zend_is_true(zvalue)) {
2392				php_error_docref(NULL, E_WARNING, "Disabling safe uploads is no longer supported");
2393				return FAILURE;
2394			}
2395			break;
2396
2397		/* String options */
2398		case CURLOPT_CAINFO:
2399		case CURLOPT_CAPATH:
2400		case CURLOPT_COOKIE:
2401		case CURLOPT_EGDSOCKET:
2402		case CURLOPT_INTERFACE:
2403		case CURLOPT_PROXY:
2404		case CURLOPT_PROXYUSERPWD:
2405		case CURLOPT_REFERER:
2406		case CURLOPT_SSLCERTTYPE:
2407		case CURLOPT_SSLENGINE:
2408		case CURLOPT_SSLENGINE_DEFAULT:
2409		case CURLOPT_SSLKEY:
2410		case CURLOPT_SSLKEYPASSWD:
2411		case CURLOPT_SSLKEYTYPE:
2412		case CURLOPT_SSL_CIPHER_LIST:
2413		case CURLOPT_USERAGENT:
2414		case CURLOPT_USERPWD:
2415		case CURLOPT_COOKIELIST:
2416		case CURLOPT_FTP_ALTERNATIVE_TO_USER:
2417#if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */
2418		case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
2419#endif
2420#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
2421		case CURLOPT_PASSWORD:
2422		case CURLOPT_PROXYPASSWORD:
2423		case CURLOPT_PROXYUSERNAME:
2424		case CURLOPT_USERNAME:
2425#endif
2426#if LIBCURL_VERSION_NUM >= 0x071304 /* Available since 7.19.4 */
2427		case CURLOPT_NOPROXY:
2428		case CURLOPT_SOCKS5_GSSAPI_SERVICE:
2429#endif
2430#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2431		case CURLOPT_MAIL_FROM:
2432		case CURLOPT_RTSP_STREAM_URI:
2433		case CURLOPT_RTSP_TRANSPORT:
2434#endif
2435#if LIBCURL_VERSION_NUM >= 0x071504 /* Available since 7.21.4 */
2436		case CURLOPT_TLSAUTH_PASSWORD:
2437		case CURLOPT_TLSAUTH_USERNAME:
2438#endif
2439#if LIBCURL_VERSION_NUM >= 0x071506 /* Available since 7.21.6 */
2440		case CURLOPT_ACCEPT_ENCODING:
2441		case CURLOPT_TRANSFER_ENCODING:
2442#else
2443		case CURLOPT_ENCODING:
2444#endif
2445#if LIBCURL_VERSION_NUM >= 0x071800 /* Available since 7.24.0 */
2446		case CURLOPT_DNS_SERVERS:
2447#endif
2448#if LIBCURL_VERSION_NUM >= 0x071900 /* Available since 7.25.0 */
2449		case CURLOPT_MAIL_AUTH:
2450#endif
2451#if LIBCURL_VERSION_NUM >= 0x072200 /* Available since 7.34.0 */
2452		case CURLOPT_LOGIN_OPTIONS:
2453#endif
2454#if LIBCURL_VERSION_NUM >= 0x072700 /* Available since 7.39.0 */
2455		case CURLOPT_PINNEDPUBLICKEY:
2456#endif
2457#if LIBCURL_VERSION_NUM >= 0x072b00 /* Available since 7.43.0 */
2458		case CURLOPT_PROXY_SERVICE_NAME:
2459		case CURLOPT_SERVICE_NAME:
2460#endif
2461#if LIBCURL_VERSION_NUM >= 0x072d00 /* Available since 7.45.0 */
2462		case CURLOPT_DEFAULT_PROTOCOL:
2463#endif
2464#if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
2465		case CURLOPT_PRE_PROXY:
2466		case CURLOPT_PROXY_CAINFO:
2467		case CURLOPT_PROXY_CAPATH:
2468		case CURLOPT_PROXY_CRLFILE:
2469		case CURLOPT_PROXY_KEYPASSWD:
2470		case CURLOPT_PROXY_PINNEDPUBLICKEY:
2471		case CURLOPT_PROXY_SSL_CIPHER_LIST:
2472		case CURLOPT_PROXY_SSLCERT:
2473		case CURLOPT_PROXY_SSLCERTTYPE:
2474		case CURLOPT_PROXY_SSLKEY:
2475		case CURLOPT_PROXY_SSLKEYTYPE:
2476		case CURLOPT_PROXY_TLSAUTH_PASSWORD:
2477		case CURLOPT_PROXY_TLSAUTH_TYPE:
2478		case CURLOPT_PROXY_TLSAUTH_USERNAME:
2479#endif
2480#if LIBCURL_VERSION_NUM >= 0x073500 /* Available since 7.53.0 */
2481		case CURLOPT_ABSTRACT_UNIX_SOCKET:
2482#endif
2483#if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
2484		case CURLOPT_REQUEST_TARGET:
2485#endif
2486#if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
2487		case CURLOPT_PROXY_TLS13_CIPHERS:
2488		case CURLOPT_TLS13_CIPHERS:
2489#endif
2490		{
2491			zend_string *tmp_str;
2492			zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2493			int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2494			zend_tmp_string_release(tmp_str);
2495			return ret;
2496		}
2497
2498		/* Curl nullable string options */
2499		case CURLOPT_CUSTOMREQUEST:
2500		case CURLOPT_FTPPORT:
2501		case CURLOPT_RANGE:
2502		case CURLOPT_FTP_ACCOUNT:
2503#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2504		case CURLOPT_RTSP_SESSION_ID:
2505#endif
2506#if LIBCURL_VERSION_NUM >= 0x072100 /* Available since 7.33.0 */
2507		case CURLOPT_DNS_INTERFACE:
2508		case CURLOPT_DNS_LOCAL_IP4:
2509		case CURLOPT_DNS_LOCAL_IP6:
2510		case CURLOPT_XOAUTH2_BEARER:
2511#endif
2512#if LIBCURL_VERSION_NUM >= 0x072800 /* Available since 7.40.0 */
2513		case CURLOPT_UNIX_SOCKET_PATH:
2514#endif
2515#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
2516		case CURLOPT_KRBLEVEL:
2517#else
2518		case CURLOPT_KRB4LEVEL:
2519#endif
2520		{
2521			if (Z_ISNULL_P(zvalue)) {
2522				error = curl_easy_setopt(ch->cp, option, NULL);
2523			} else {
2524				zend_string *tmp_str;
2525				zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2526				int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
2527				zend_tmp_string_release(tmp_str);
2528				return ret;
2529			}
2530			break;
2531		}
2532
2533		/* Curl private option */
2534		case CURLOPT_PRIVATE:
2535		{
2536			zend_string *tmp_str;
2537			zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2538			int ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 1);
2539			zend_tmp_string_release(tmp_str);
2540			return ret;
2541		}
2542
2543		/* Curl url option */
2544		case CURLOPT_URL:
2545		{
2546			zend_string *tmp_str;
2547			zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2548			int ret = php_curl_option_url(ch, ZSTR_VAL(str), ZSTR_LEN(str));
2549			zend_tmp_string_release(tmp_str);
2550			return ret;
2551		}
2552
2553		/* Curl file handle options */
2554		case CURLOPT_FILE:
2555		case CURLOPT_INFILE:
2556		case CURLOPT_STDERR:
2557		case CURLOPT_WRITEHEADER: {
2558			FILE *fp = NULL;
2559			php_stream *what = NULL;
2560
2561			if (Z_TYPE_P(zvalue) != IS_NULL) {
2562				what = (php_stream *)zend_fetch_resource2_ex(zvalue, "File-Handle", php_file_le_stream(), php_file_le_pstream());
2563				if (!what) {
2564					return FAILURE;
2565				}
2566
2567				if (FAILURE == php_stream_cast(what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
2568					return FAILURE;
2569				}
2570
2571				if (!fp) {
2572					return FAILURE;
2573				}
2574			}
2575
2576			error = CURLE_OK;
2577			switch (option) {
2578				case CURLOPT_FILE:
2579					if (!what) {
2580						if (!Z_ISUNDEF(ch->handlers->write->stream)) {
2581							zval_ptr_dtor(&ch->handlers->write->stream);
2582							ZVAL_UNDEF(&ch->handlers->write->stream);
2583						}
2584						ch->handlers->write->fp = NULL;
2585						ch->handlers->write->method = PHP_CURL_STDOUT;
2586					} else if (what->mode[0] != 'r' || what->mode[1] == '+') {
2587						zval_ptr_dtor(&ch->handlers->write->stream);
2588						ch->handlers->write->fp = fp;
2589						ch->handlers->write->method = PHP_CURL_FILE;
2590						ZVAL_COPY(&ch->handlers->write->stream, zvalue);
2591					} else {
2592						php_error_docref(NULL, E_WARNING, "the provided file handle is not writable");
2593						return FAILURE;
2594					}
2595					break;
2596				case CURLOPT_WRITEHEADER:
2597					if (!what) {
2598						if (!Z_ISUNDEF(ch->handlers->write_header->stream)) {
2599							zval_ptr_dtor(&ch->handlers->write_header->stream);
2600							ZVAL_UNDEF(&ch->handlers->write_header->stream);
2601						}
2602						ch->handlers->write_header->fp = NULL;
2603						ch->handlers->write_header->method = PHP_CURL_IGNORE;
2604					} else if (what->mode[0] != 'r' || what->mode[1] == '+') {
2605						zval_ptr_dtor(&ch->handlers->write_header->stream);
2606						ch->handlers->write_header->fp = fp;
2607						ch->handlers->write_header->method = PHP_CURL_FILE;
2608						ZVAL_COPY(&ch->handlers->write_header->stream, zvalue);
2609					} else {
2610						php_error_docref(NULL, E_WARNING, "the provided file handle is not writable");
2611						return FAILURE;
2612					}
2613					break;
2614				case CURLOPT_INFILE:
2615					if (!what) {
2616						if (!Z_ISUNDEF(ch->handlers->read->stream)) {
2617							zval_ptr_dtor(&ch->handlers->read->stream);
2618							ZVAL_UNDEF(&ch->handlers->read->stream);
2619						}
2620						ch->handlers->read->fp = NULL;
2621						ch->handlers->read->res = NULL;
2622					} else {
2623						zval_ptr_dtor(&ch->handlers->read->stream);
2624						ch->handlers->read->fp = fp;
2625						ch->handlers->read->res = Z_RES_P(zvalue);
2626						ZVAL_COPY(&ch->handlers->read->stream, zvalue);
2627					}
2628					break;
2629				case CURLOPT_STDERR:
2630					if (!what) {
2631						if (!Z_ISUNDEF(ch->handlers->std_err)) {
2632							zval_ptr_dtor(&ch->handlers->std_err);
2633							ZVAL_UNDEF(&ch->handlers->std_err);
2634						}
2635					} else if (what->mode[0] != 'r' || what->mode[1] == '+') {
2636						zval_ptr_dtor(&ch->handlers->std_err);
2637						ZVAL_COPY(&ch->handlers->std_err, zvalue);
2638					} else {
2639						php_error_docref(NULL, E_WARNING, "the provided file handle is not writable");
2640						return FAILURE;
2641					}
2642					/* break omitted intentionally */
2643				default:
2644					error = curl_easy_setopt(ch->cp, option, fp);
2645					break;
2646			}
2647			break;
2648		}
2649
2650		/* Curl linked list options */
2651		case CURLOPT_HTTP200ALIASES:
2652		case CURLOPT_HTTPHEADER:
2653		case CURLOPT_POSTQUOTE:
2654		case CURLOPT_PREQUOTE:
2655		case CURLOPT_QUOTE:
2656		case CURLOPT_TELNETOPTIONS:
2657#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2658		case CURLOPT_MAIL_RCPT:
2659#endif
2660#if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */
2661		case CURLOPT_RESOLVE:
2662#endif
2663#if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
2664		case CURLOPT_PROXYHEADER:
2665#endif
2666#if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
2667		case CURLOPT_CONNECT_TO:
2668#endif
2669		{
2670			zval *current;
2671			HashTable *ph;
2672			zend_string *val, *tmp_val;
2673			struct curl_slist *slist = NULL;
2674
2675			ph = HASH_OF(zvalue);
2676			if (!ph) {
2677				char *name = NULL;
2678				switch (option) {
2679					case CURLOPT_HTTPHEADER:
2680						name = "CURLOPT_HTTPHEADER";
2681						break;
2682					case CURLOPT_QUOTE:
2683						name = "CURLOPT_QUOTE";
2684						break;
2685					case CURLOPT_HTTP200ALIASES:
2686						name = "CURLOPT_HTTP200ALIASES";
2687						break;
2688					case CURLOPT_POSTQUOTE:
2689						name = "CURLOPT_POSTQUOTE";
2690						break;
2691					case CURLOPT_PREQUOTE:
2692						name = "CURLOPT_PREQUOTE";
2693						break;
2694					case CURLOPT_TELNETOPTIONS:
2695						name = "CURLOPT_TELNETOPTIONS";
2696						break;
2697#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
2698					case CURLOPT_MAIL_RCPT:
2699						name = "CURLOPT_MAIL_RCPT";
2700						break;
2701#endif
2702#if LIBCURL_VERSION_NUM >= 0x071503 /* Available since 7.21.3 */
2703					case CURLOPT_RESOLVE:
2704						name = "CURLOPT_RESOLVE";
2705						break;
2706#endif
2707#if LIBCURL_VERSION_NUM >= 0x072500 /* Available since 7.37.0 */
2708					case CURLOPT_PROXYHEADER:
2709						name = "CURLOPT_PROXYHEADER";
2710						break;
2711#endif
2712#if LIBCURL_VERSION_NUM >= 0x073100 /* Available since 7.49.0 */
2713					case CURLOPT_CONNECT_TO:
2714						name = "CURLOPT_CONNECT_TO";
2715						break;
2716#endif
2717				}
2718				php_error_docref(NULL, E_WARNING, "You must pass either an object or an array with the %s argument", name);
2719				return FAILURE;
2720			}
2721
2722			ZEND_HASH_FOREACH_VAL_IND(ph, current) {
2723				ZVAL_DEREF(current);
2724				val = zval_get_tmp_string(current, &tmp_val);
2725				slist = curl_slist_append(slist, ZSTR_VAL(val));
2726				zend_tmp_string_release(tmp_val);
2727				if (!slist) {
2728					php_error_docref(NULL, E_WARNING, "Could not build curl_slist");
2729					return 1;
2730				}
2731			} ZEND_HASH_FOREACH_END();
2732
2733			if (slist) {
2734				if ((*ch->clone) == 1) {
2735					zend_hash_index_update_ptr(ch->to_free->slist, option, slist);
2736				} else {
2737					zend_hash_next_index_insert_ptr(ch->to_free->slist, slist);
2738				}
2739			}
2740
2741			error = curl_easy_setopt(ch->cp, option, slist);
2742
2743			break;
2744		}
2745
2746		case CURLOPT_BINARYTRANSFER:
2747			/* Do nothing, just backward compatibility */
2748			break;
2749
2750		case CURLOPT_FOLLOWLOCATION:
2751			lval = zend_is_true(zvalue);
2752#if LIBCURL_VERSION_NUM < 0x071304
2753			if (lval && PG(open_basedir) && *PG(open_basedir)) {
2754				php_error_docref(NULL, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set");
2755				return FAILURE;
2756			}
2757#endif
2758			error = curl_easy_setopt(ch->cp, option, lval);
2759			break;
2760
2761		case CURLOPT_HEADERFUNCTION:
2762			if (!Z_ISUNDEF(ch->handlers->write_header->func_name)) {
2763				zval_ptr_dtor(&ch->handlers->write_header->func_name);
2764				ch->handlers->write_header->fci_cache = empty_fcall_info_cache;
2765			}
2766			ZVAL_COPY(&ch->handlers->write_header->func_name, zvalue);
2767			ch->handlers->write_header->method = PHP_CURL_USER;
2768			break;
2769
2770		case CURLOPT_POSTFIELDS:
2771			if (Z_TYPE_P(zvalue) == IS_ARRAY || Z_TYPE_P(zvalue) == IS_OBJECT) {
2772				zval *current;
2773				HashTable *postfields;
2774				zend_string *string_key;
2775				zend_ulong  num_key;
2776#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2777				curl_mime *mime = NULL;
2778				curl_mimepart *part;
2779				CURLcode form_error;
2780#else
2781				struct HttpPost *first = NULL;
2782				struct HttpPost *last  = NULL;
2783				CURLFORMcode form_error;
2784#endif
2785				postfields = HASH_OF(zvalue);
2786				if (!postfields) {
2787					php_error_docref(NULL, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS");
2788					return FAILURE;
2789				}
2790
2791#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2792				if (zend_hash_num_elements(postfields) > 0) {
2793					mime = curl_mime_init(ch->cp);
2794					if (mime == NULL) {
2795						return FAILURE;
2796					}
2797				}
2798#endif
2799
2800				ZEND_HASH_FOREACH_KEY_VAL_IND(postfields, num_key, string_key, current) {
2801					zend_string *postval, *tmp_postval;
2802					/* Pretend we have a string_key here */
2803					if (!string_key) {
2804						string_key = zend_long_to_str(num_key);
2805					} else {
2806						zend_string_addref(string_key);
2807					}
2808
2809					ZVAL_DEREF(current);
2810					if (Z_TYPE_P(current) == IS_OBJECT &&
2811							instanceof_function(Z_OBJCE_P(current), curl_CURLFile_class)) {
2812						/* new-style file upload */
2813						zval *prop, rv;
2814						char *type = NULL, *filename = NULL;
2815
2816						prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv);
2817						if (Z_TYPE_P(prop) != IS_STRING) {
2818							php_error_docref(NULL, E_WARNING, "Invalid filename for key %s", ZSTR_VAL(string_key));
2819						} else {
2820							postval = Z_STR_P(prop);
2821
2822							if (php_check_open_basedir(ZSTR_VAL(postval))) {
2823								return 1;
2824							}
2825
2826							prop = zend_read_property(curl_CURLFile_class, current, "mime", sizeof("mime")-1, 0, &rv);
2827							if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
2828								type = Z_STRVAL_P(prop);
2829							}
2830							prop = zend_read_property(curl_CURLFile_class, current, "postname", sizeof("postname")-1, 0, &rv);
2831							if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
2832								filename = Z_STRVAL_P(prop);
2833							}
2834
2835#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2836							part = curl_mime_addpart(mime);
2837							if (part == NULL) {
2838								zend_string_release_ex(string_key, 0);
2839								return FAILURE;
2840							}
2841							if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK
2842								|| (form_error = curl_mime_filedata(part, ZSTR_VAL(postval))) != CURLE_OK
2843								|| (form_error = curl_mime_filename(part, filename ? filename : ZSTR_VAL(postval))) != CURLE_OK
2844								|| (form_error = curl_mime_type(part, type ? type : "application/octet-stream")) != CURLE_OK) {
2845								error = form_error;
2846							}
2847#else
2848							form_error = curl_formadd(&first, &last,
2849											CURLFORM_COPYNAME, ZSTR_VAL(string_key),
2850											CURLFORM_NAMELENGTH, ZSTR_LEN(string_key),
2851											CURLFORM_FILENAME, filename ? filename : ZSTR_VAL(postval),
2852											CURLFORM_CONTENTTYPE, type ? type : "application/octet-stream",
2853											CURLFORM_FILE, ZSTR_VAL(postval),
2854											CURLFORM_END);
2855							if (form_error != CURL_FORMADD_OK) {
2856								/* Not nice to convert between enums but we only have place for one error type */
2857								error = (CURLcode)form_error;
2858							}
2859#endif
2860						}
2861
2862						zend_string_release_ex(string_key, 0);
2863						continue;
2864					}
2865
2866					postval = zval_get_tmp_string(current, &tmp_postval);
2867
2868#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2869					part = curl_mime_addpart(mime);
2870					if (part == NULL) {
2871						zend_tmp_string_release(tmp_postval);
2872						zend_string_release_ex(string_key, 0);
2873						return FAILURE;
2874					}
2875					if ((form_error = curl_mime_name(part, ZSTR_VAL(string_key))) != CURLE_OK
2876						|| (form_error = curl_mime_data(part, ZSTR_VAL(postval), ZSTR_LEN(postval))) != CURLE_OK) {
2877						error = form_error;
2878					}
2879#else
2880					/* The arguments after _NAMELENGTH and _CONTENTSLENGTH
2881					 * must be explicitly cast to long in curl_formadd
2882					 * use since curl needs a long not an int. */
2883					form_error = curl_formadd(&first, &last,
2884										 CURLFORM_COPYNAME, ZSTR_VAL(string_key),
2885										 CURLFORM_NAMELENGTH, ZSTR_LEN(string_key),
2886										 CURLFORM_COPYCONTENTS, ZSTR_VAL(postval),
2887										 CURLFORM_CONTENTSLENGTH, ZSTR_LEN(postval),
2888										 CURLFORM_END);
2889
2890					if (form_error != CURL_FORMADD_OK) {
2891						/* Not nice to convert between enums but we only have place for one error type */
2892						error = (CURLcode)form_error;
2893					}
2894#endif
2895					zend_tmp_string_release(tmp_postval);
2896					zend_string_release_ex(string_key, 0);
2897				} ZEND_HASH_FOREACH_END();
2898
2899				SAVE_CURL_ERROR(ch, error);
2900				if (error != CURLE_OK) {
2901					return FAILURE;
2902				}
2903
2904				if ((*ch->clone) == 1) {
2905					zend_llist_clean(&ch->to_free->post);
2906				}
2907#if LIBCURL_VERSION_NUM >= 0x073800 /* 7.56.0 */
2908				zend_llist_add_element(&ch->to_free->post, &mime);
2909				error = curl_easy_setopt(ch->cp, CURLOPT_MIMEPOST, mime);
2910#else
2911				zend_llist_add_element(&ch->to_free->post, &first);
2912				error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
2913#endif
2914			} else {
2915#if LIBCURL_VERSION_NUM >= 0x071101
2916				zend_string *tmp_str;
2917				zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2918				/* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
2919				error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str));
2920				error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, ZSTR_VAL(str));
2921				zend_tmp_string_release(tmp_str);
2922#else
2923				char *post = NULL;
2924				zend_string *tmp_str;
2925				zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
2926
2927				post = estrndup(ZSTR_VAL(str), ZSTR_LEN(str));
2928				zend_llist_add_element(&ch->to_free->str, &post);
2929
2930				curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
2931				error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, ZSTR_LEN(str));
2932				zend_tmp_string_release(tmp_str);
2933#endif
2934			}
2935			break;
2936
2937		case CURLOPT_PROGRESSFUNCTION:
2938			curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION,	curl_progress);
2939			curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch);
2940			if (ch->handlers->progress == NULL) {
2941				ch->handlers->progress = ecalloc(1, sizeof(php_curl_progress));
2942			} else if (!Z_ISUNDEF(ch->handlers->progress->func_name)) {
2943				zval_ptr_dtor(&ch->handlers->progress->func_name);
2944				ch->handlers->progress->fci_cache = empty_fcall_info_cache;
2945			}
2946			ZVAL_COPY(&ch->handlers->progress->func_name, zvalue);
2947			ch->handlers->progress->method = PHP_CURL_USER;
2948			break;
2949
2950		case CURLOPT_READFUNCTION:
2951			if (!Z_ISUNDEF(ch->handlers->read->func_name)) {
2952				zval_ptr_dtor(&ch->handlers->read->func_name);
2953				ch->handlers->read->fci_cache = empty_fcall_info_cache;
2954			}
2955			ZVAL_COPY(&ch->handlers->read->func_name, zvalue);
2956			ch->handlers->read->method = PHP_CURL_USER;
2957			break;
2958
2959		case CURLOPT_RETURNTRANSFER:
2960			if (zend_is_true(zvalue)) {
2961				ch->handlers->write->method = PHP_CURL_RETURN;
2962			} else {
2963				ch->handlers->write->method = PHP_CURL_STDOUT;
2964			}
2965			break;
2966
2967		case CURLOPT_WRITEFUNCTION:
2968			if (!Z_ISUNDEF(ch->handlers->write->func_name)) {
2969				zval_ptr_dtor(&ch->handlers->write->func_name);
2970				ch->handlers->write->fci_cache = empty_fcall_info_cache;
2971			}
2972			ZVAL_COPY(&ch->handlers->write->func_name, zvalue);
2973			ch->handlers->write->method = PHP_CURL_USER;
2974			break;
2975
2976		/* Curl off_t options */
2977		case CURLOPT_MAX_RECV_SPEED_LARGE:
2978		case CURLOPT_MAX_SEND_SPEED_LARGE:
2979#if LIBCURL_VERSION_NUM >= 0x073b00 /* Available since 7.59.0 */
2980		case CURLOPT_TIMEVALUE_LARGE:
2981#endif
2982			lval = zval_get_long(zvalue);
2983			error = curl_easy_setopt(ch->cp, option, (curl_off_t)lval);
2984			break;
2985
2986#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
2987		case CURLOPT_POSTREDIR:
2988			lval = zval_get_long(zvalue);
2989			error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, lval & CURL_REDIR_POST_ALL);
2990			break;
2991#endif
2992
2993		/* the following options deal with files, therefore the open_basedir check
2994		 * is required.
2995		 */
2996		case CURLOPT_COOKIEFILE:
2997		case CURLOPT_COOKIEJAR:
2998		case CURLOPT_RANDOM_FILE:
2999		case CURLOPT_SSLCERT:
3000		case CURLOPT_NETRC_FILE:
3001#if LIBCURL_VERSION_NUM >= 0x071001 /* Available since 7.16.1 */
3002		case CURLOPT_SSH_PRIVATE_KEYFILE:
3003		case CURLOPT_SSH_PUBLIC_KEYFILE:
3004#endif
3005#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
3006		case CURLOPT_CRLFILE:
3007		case CURLOPT_ISSUERCERT:
3008#endif
3009#if LIBCURL_VERSION_NUM >= 0x071306 /* Available since 7.19.6 */
3010		case CURLOPT_SSH_KNOWNHOSTS:
3011#endif
3012		{
3013		    zend_string *tmp_str;
3014			zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
3015			int ret;
3016
3017			if (ZSTR_LEN(str) && php_check_open_basedir(ZSTR_VAL(str))) {
3018				zend_tmp_string_release(tmp_str);
3019				return FAILURE;
3020			}
3021
3022			ret = php_curl_option_str(ch, option, ZSTR_VAL(str), ZSTR_LEN(str), 0);
3023			zend_tmp_string_release(tmp_str);
3024			return ret;
3025		}
3026
3027		case CURLINFO_HEADER_OUT:
3028			if (zend_is_true(zvalue)) {
3029				curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
3030				curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch);
3031				curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1);
3032			} else {
3033				curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL);
3034				curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL);
3035				curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
3036			}
3037			break;
3038
3039		case CURLOPT_SHARE:
3040			{
3041				php_curlsh *sh;
3042				if ((sh = (php_curlsh *)zend_fetch_resource_ex(zvalue, le_curl_share_handle_name, le_curl_share_handle))) {
3043					curl_easy_setopt(ch->cp, CURLOPT_SHARE, sh->share);
3044				}
3045			}
3046			break;
3047
3048#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3049		case CURLOPT_FNMATCH_FUNCTION:
3050			curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_FUNCTION, curl_fnmatch);
3051			curl_easy_setopt(ch->cp, CURLOPT_FNMATCH_DATA, ch);
3052			if (ch->handlers->fnmatch == NULL) {
3053				ch->handlers->fnmatch = ecalloc(1, sizeof(php_curl_fnmatch));
3054			} else if (!Z_ISUNDEF(ch->handlers->fnmatch->func_name)) {
3055				zval_ptr_dtor(&ch->handlers->fnmatch->func_name);
3056				ch->handlers->fnmatch->fci_cache = empty_fcall_info_cache;
3057			}
3058			ZVAL_COPY(&ch->handlers->fnmatch->func_name, zvalue);
3059			ch->handlers->fnmatch->method = PHP_CURL_USER;
3060			break;
3061#endif
3062
3063	}
3064
3065	SAVE_CURL_ERROR(ch, error);
3066	if (error != CURLE_OK) {
3067		return FAILURE;
3068	} else {
3069		return SUCCESS;
3070	}
3071}
3072/* }}} */
3073
3074/* {{{ proto bool curl_setopt(resource ch, int option, mixed value)
3075   Set an option for a cURL transfer */
3076PHP_FUNCTION(curl_setopt)
3077{
3078	zval       *zid, *zvalue;
3079	zend_long        options;
3080	php_curl   *ch;
3081
3082	ZEND_PARSE_PARAMETERS_START(3, 3)
3083		Z_PARAM_RESOURCE(zid)
3084		Z_PARAM_LONG(options)
3085		Z_PARAM_ZVAL(zvalue)
3086	ZEND_PARSE_PARAMETERS_END();
3087
3088	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3089		RETURN_FALSE;
3090	}
3091
3092	if (options <= 0 && options != CURLOPT_SAFE_UPLOAD) {
3093		php_error_docref(NULL, E_WARNING, "Invalid curl configuration option");
3094		RETURN_FALSE;
3095	}
3096
3097	if (_php_curl_setopt(ch, options, zvalue) == SUCCESS) {
3098		RETURN_TRUE;
3099	} else {
3100		RETURN_FALSE;
3101	}
3102}
3103/* }}} */
3104
3105/* {{{ proto bool curl_setopt_array(resource ch, array options)
3106   Set an array of option for a cURL transfer */
3107PHP_FUNCTION(curl_setopt_array)
3108{
3109	zval		*zid, *arr, *entry;
3110	php_curl	*ch;
3111	zend_ulong	option;
3112	zend_string	*string_key;
3113
3114	ZEND_PARSE_PARAMETERS_START(2, 2)
3115		Z_PARAM_RESOURCE(zid)
3116		Z_PARAM_ARRAY(arr)
3117	ZEND_PARSE_PARAMETERS_END();
3118
3119	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3120		RETURN_FALSE;
3121	}
3122
3123	ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(arr), option, string_key, entry) {
3124		if (string_key) {
3125			php_error_docref(NULL, E_WARNING,
3126					"Array keys must be CURLOPT constants or equivalent integer values");
3127			RETURN_FALSE;
3128		}
3129		ZVAL_DEREF(entry);
3130		if (_php_curl_setopt(ch, (zend_long) option, entry) == FAILURE) {
3131			RETURN_FALSE;
3132		}
3133	} ZEND_HASH_FOREACH_END();
3134
3135	RETURN_TRUE;
3136}
3137/* }}} */
3138
3139/* {{{ _php_curl_cleanup_handle(ch)
3140   Cleanup an execution phase */
3141void _php_curl_cleanup_handle(php_curl *ch)
3142{
3143	smart_str_free(&ch->handlers->write->buf);
3144	if (ch->header.str) {
3145		zend_string_release_ex(ch->header.str, 0);
3146		ch->header.str = NULL;
3147	}
3148
3149	memset(ch->err.str, 0, CURL_ERROR_SIZE + 1);
3150	ch->err.no = 0;
3151}
3152/* }}} */
3153
3154/* {{{ proto bool curl_exec(resource ch)
3155   Perform a cURL session */
3156PHP_FUNCTION(curl_exec)
3157{
3158	CURLcode	error;
3159	zval		*zid;
3160	php_curl	*ch;
3161
3162	ZEND_PARSE_PARAMETERS_START(1, 1)
3163		Z_PARAM_RESOURCE(zid)
3164	ZEND_PARSE_PARAMETERS_END();
3165
3166	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3167		RETURN_FALSE;
3168	}
3169
3170	_php_curl_verify_handlers(ch, 1);
3171
3172	_php_curl_cleanup_handle(ch);
3173
3174	error = curl_easy_perform(ch->cp);
3175	SAVE_CURL_ERROR(ch, error);
3176	/* CURLE_PARTIAL_FILE is returned by HEAD requests */
3177	if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) {
3178		smart_str_free(&ch->handlers->write->buf);
3179		RETURN_FALSE;
3180	}
3181
3182	if (!Z_ISUNDEF(ch->handlers->std_err)) {
3183		php_stream  *stream;
3184		stream = (php_stream*)zend_fetch_resource2_ex(&ch->handlers->std_err, NULL, php_file_le_stream(), php_file_le_pstream());
3185		if (stream) {
3186			php_stream_flush(stream);
3187		}
3188	}
3189
3190	if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.s) {
3191		smart_str_0(&ch->handlers->write->buf);
3192		RETURN_STR_COPY(ch->handlers->write->buf.s);
3193	}
3194
3195	/* flush the file handle, so any remaining data is synched to disk */
3196	if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) {
3197		fflush(ch->handlers->write->fp);
3198	}
3199	if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) {
3200		fflush(ch->handlers->write_header->fp);
3201	}
3202
3203	if (ch->handlers->write->method == PHP_CURL_RETURN) {
3204		RETURN_EMPTY_STRING();
3205	} else {
3206		RETURN_TRUE;
3207	}
3208}
3209/* }}} */
3210
3211/* {{{ proto mixed curl_getinfo(resource ch [, int option])
3212   Get information regarding a specific transfer */
3213PHP_FUNCTION(curl_getinfo)
3214{
3215	zval		*zid;
3216	php_curl	*ch;
3217	zend_long	option = 0;
3218
3219	ZEND_PARSE_PARAMETERS_START(1, 2)
3220		Z_PARAM_RESOURCE(zid)
3221		Z_PARAM_OPTIONAL
3222		Z_PARAM_LONG(option)
3223	ZEND_PARSE_PARAMETERS_END();
3224
3225	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3226		RETURN_FALSE;
3227	}
3228
3229	if (ZEND_NUM_ARGS() < 2) {
3230		char *s_code;
3231		/* libcurl expects long datatype. So far no cases are known where
3232		   it would be an issue. Using zend_long would truncate a 64-bit
3233		   var on Win64, so the exact long datatype fits everywhere, as
3234		   long as there's no 32-bit int overflow. */
3235		long l_code;
3236		double d_code;
3237#if LIBCURL_VERSION_NUM > 0x071301 /* 7.19.1 */
3238		struct curl_certinfo *ci = NULL;
3239		zval listcode;
3240#endif
3241#if LIBCURL_VERSION_NUM >= 0x073700 /* 7.55.0 */
3242		curl_off_t co;
3243#endif
3244
3245		array_init(return_value);
3246
3247		if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
3248			CAAS("url", s_code);
3249		}
3250		if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) {
3251			if (s_code != NULL) {
3252				CAAS("content_type", s_code);
3253			} else {
3254				zval retnull;
3255				ZVAL_NULL(&retnull);
3256				CAAZ("content_type", &retnull);
3257			}
3258		}
3259		if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) {
3260			CAAL("http_code", l_code);
3261		}
3262		if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
3263			CAAL("header_size", l_code);
3264		}
3265		if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
3266			CAAL("request_size", l_code);
3267		}
3268		if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
3269			CAAL("filetime", l_code);
3270		}
3271		if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
3272			CAAL("ssl_verify_result", l_code);
3273		}
3274		if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
3275			CAAL("redirect_count", l_code);
3276		}
3277		if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) {
3278			CAAD("total_time", d_code);
3279		}
3280		if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
3281			CAAD("namelookup_time", d_code);
3282		}
3283		if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
3284			CAAD("connect_time", d_code);
3285		}
3286		if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
3287			CAAD("pretransfer_time", d_code);
3288		}
3289		if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) {
3290			CAAD("size_upload", d_code);
3291		}
3292		if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
3293			CAAD("size_download", d_code);
3294		}
3295		if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
3296			CAAD("speed_download", d_code);
3297		}
3298		if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) {
3299			CAAD("speed_upload", d_code);
3300		}
3301		if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
3302			CAAD("download_content_length", d_code);
3303		}
3304		if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
3305			CAAD("upload_content_length", d_code);
3306		}
3307		if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) {
3308			CAAD("starttransfer_time", d_code);
3309		}
3310		if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) {
3311			CAAD("redirect_time", d_code);
3312		}
3313#if LIBCURL_VERSION_NUM >= 0x071202 /* Available since 7.18.2 */
3314		if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) {
3315			CAAS("redirect_url", s_code);
3316		}
3317#endif
3318#if LIBCURL_VERSION_NUM >= 0x071300 /* Available since 7.19.0 */
3319		if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_IP, &s_code) == CURLE_OK) {
3320			CAAS("primary_ip", s_code);
3321		}
3322#endif
3323#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
3324		if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
3325			array_init(&listcode);
3326			create_certinfo(ci, &listcode);
3327			CAAZ("certinfo", &listcode);
3328		}
3329#endif
3330#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3331		if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_PORT, &l_code) == CURLE_OK) {
3332			CAAL("primary_port", l_code);
3333		}
3334		if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_IP, &s_code) == CURLE_OK) {
3335			CAAS("local_ip", s_code);
3336		}
3337		if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_PORT, &l_code) == CURLE_OK) {
3338			CAAL("local_port", l_code);
3339		}
3340#endif
3341#if LIBCURL_VERSION_NUM >= 0x073200 /* Available since 7.50.0 */
3342		if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_VERSION, &l_code) == CURLE_OK) {
3343			CAAL("http_version", l_code);
3344		}
3345#endif
3346#if LIBCURL_VERSION_NUM >= 0x073400 /* Available since 7.52.0 */
3347		if (curl_easy_getinfo(ch->cp, CURLINFO_PROTOCOL, &l_code) == CURLE_OK) {
3348			CAAL("protocol", l_code);
3349		}
3350		if (curl_easy_getinfo(ch->cp, CURLINFO_PROXY_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
3351			CAAL("ssl_verifyresult", l_code);
3352		}
3353		if (curl_easy_getinfo(ch->cp, CURLINFO_SCHEME, &s_code) == CURLE_OK) {
3354			CAAS("scheme", s_code);
3355		}
3356#endif
3357#if LIBCURL_VERSION_NUM >= 0x073d00 /* Available since 7.61.0 */
3358		if (curl_easy_getinfo(ch->cp, CURLINFO_APPCONNECT_TIME_T, &co) == CURLE_OK) {
3359			CAAL("appconnect_time_us", co);
3360		}
3361		if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME_T, &co) == CURLE_OK) {
3362			CAAL("connect_time_us", co);
3363		}
3364		if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME_T, &co) == CURLE_OK) {
3365			CAAL("namelookup_time_us", co);
3366		}
3367		if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME_T, &co) == CURLE_OK) {
3368			CAAL("pretransfer_time_us", co);
3369		}
3370		if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME_T, &co) == CURLE_OK) {
3371			CAAL("redirect_time_us", co);
3372		}
3373		if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME_T, &co) == CURLE_OK) {
3374			CAAL("starttransfer_time_us", co);
3375		}
3376		if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME_T, &co) == CURLE_OK) {
3377			CAAL("total_time_us", co);
3378		}
3379#endif
3380		if (ch->header.str) {
3381			CAASTR("request_header", ch->header.str);
3382		}
3383	} else {
3384		switch (option) {
3385			case CURLINFO_HEADER_OUT:
3386				if (ch->header.str) {
3387					RETURN_STR_COPY(ch->header.str);
3388				} else {
3389					RETURN_FALSE;
3390				}
3391#if LIBCURL_VERSION_NUM >= 0x071301 /* Available since 7.19.1 */
3392			case CURLINFO_CERTINFO: {
3393				struct curl_certinfo *ci = NULL;
3394
3395				array_init(return_value);
3396
3397				if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
3398					create_certinfo(ci, return_value);
3399				} else {
3400					RETURN_FALSE;
3401				}
3402				break;
3403			}
3404#endif
3405			default: {
3406				int type = CURLINFO_TYPEMASK & option;
3407				switch (type) {
3408					case CURLINFO_STRING:
3409					{
3410						char *s_code = NULL;
3411
3412						if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) {
3413							RETURN_STRING(s_code);
3414						} else {
3415							RETURN_FALSE;
3416						}
3417						break;
3418					}
3419					case CURLINFO_LONG:
3420					{
3421						zend_long code = 0;
3422
3423						if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
3424							RETURN_LONG(code);
3425						} else {
3426							RETURN_FALSE;
3427						}
3428						break;
3429					}
3430					case CURLINFO_DOUBLE:
3431					{
3432						double code = 0.0;
3433
3434						if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
3435							RETURN_DOUBLE(code);
3436						} else {
3437							RETURN_FALSE;
3438						}
3439						break;
3440					}
3441					case CURLINFO_SLIST:
3442					{
3443						struct curl_slist *slist;
3444						array_init(return_value);
3445						if (curl_easy_getinfo(ch->cp, option, &slist) == CURLE_OK) {
3446							while (slist) {
3447								add_next_index_string(return_value, slist->data);
3448								slist = slist->next;
3449							}
3450							curl_slist_free_all(slist);
3451						} else {
3452							RETURN_FALSE;
3453						}
3454						break;
3455					}
3456#if LIBCURL_VERSION_NUM >= 0x073700 /* Available since 7.55.0 */
3457					case CURLINFO_OFF_T:
3458					{
3459						curl_off_t c_off;
3460						if (curl_easy_getinfo(ch->cp, option, &c_off) == CURLE_OK) {
3461							RETURN_LONG((long) c_off);
3462						} else {
3463							RETURN_FALSE;
3464						}
3465						break;
3466					}
3467#endif
3468					default:
3469						RETURN_FALSE;
3470				}
3471			}
3472		}
3473	}
3474}
3475/* }}} */
3476
3477/* {{{ proto string curl_error(resource ch)
3478   Return a string contain the last error for the current session */
3479PHP_FUNCTION(curl_error)
3480{
3481	zval		*zid;
3482	php_curl	*ch;
3483
3484	ZEND_PARSE_PARAMETERS_START(1, 1)
3485		Z_PARAM_RESOURCE(zid)
3486	ZEND_PARSE_PARAMETERS_END();
3487
3488	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3489		RETURN_FALSE;
3490	}
3491
3492	if (ch->err.no) {
3493		ch->err.str[CURL_ERROR_SIZE] = 0;
3494		RETURN_STRING(ch->err.str);
3495	} else {
3496		RETURN_EMPTY_STRING();
3497	}
3498}
3499/* }}} */
3500
3501/* {{{ proto int curl_errno(resource ch)
3502   Return an integer containing the last error number */
3503PHP_FUNCTION(curl_errno)
3504{
3505	zval		*zid;
3506	php_curl	*ch;
3507
3508	ZEND_PARSE_PARAMETERS_START(1,1)
3509		Z_PARAM_RESOURCE(zid)
3510	ZEND_PARSE_PARAMETERS_END();
3511
3512	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3513		RETURN_FALSE;
3514	}
3515
3516	RETURN_LONG(ch->err.no);
3517}
3518/* }}} */
3519
3520/* {{{ proto void curl_close(resource ch)
3521   Close a cURL session */
3522PHP_FUNCTION(curl_close)
3523{
3524	zval		*zid;
3525	php_curl	*ch;
3526
3527	ZEND_PARSE_PARAMETERS_START(1, 1)
3528		Z_PARAM_RESOURCE(zid)
3529	ZEND_PARSE_PARAMETERS_END();
3530
3531	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3532		RETURN_FALSE;
3533	}
3534
3535	if (ch->in_callback) {
3536		php_error_docref(NULL, E_WARNING, "Attempt to close cURL handle from a callback");
3537		return;
3538	}
3539
3540	zend_list_close(Z_RES_P(zid));
3541}
3542/* }}} */
3543
3544/* {{{ _php_curl_close_ex()
3545   List destructor for curl handles */
3546static void _php_curl_close_ex(php_curl *ch)
3547{
3548#if PHP_CURL_DEBUG
3549	fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
3550#endif
3551
3552	_php_curl_verify_handlers(ch, 0);
3553
3554	/*
3555	 * Libcurl is doing connection caching. When easy handle is cleaned up,
3556	 * if the handle was previously used by the curl_multi_api, the connection
3557	 * remains open un the curl multi handle is cleaned up. Some protocols are
3558	 * sending content like the FTP one, and libcurl try to use the
3559	 * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those
3560	 * callback are freed, we need to use an other callback to which avoid
3561	 * segfaults.
3562	 *
3563	 * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2
3564	 */
3565	if (ch->cp != NULL) {
3566		curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing);
3567		curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing);
3568
3569		curl_easy_cleanup(ch->cp);
3570	}
3571
3572	/* cURL destructors should be invoked only by last curl handle */
3573	if (--(*ch->clone) == 0) {
3574		zend_llist_clean(&ch->to_free->str);
3575		zend_llist_clean(&ch->to_free->post);
3576		zend_hash_destroy(ch->to_free->slist);
3577		efree(ch->to_free->slist);
3578		efree(ch->to_free);
3579		efree(ch->clone);
3580	}
3581
3582	smart_str_free(&ch->handlers->write->buf);
3583	zval_ptr_dtor(&ch->handlers->write->func_name);
3584	zval_ptr_dtor(&ch->handlers->read->func_name);
3585	zval_ptr_dtor(&ch->handlers->write_header->func_name);
3586	zval_ptr_dtor(&ch->handlers->std_err);
3587	if (ch->header.str) {
3588		zend_string_release_ex(ch->header.str, 0);
3589	}
3590
3591	zval_ptr_dtor(&ch->handlers->write_header->stream);
3592	zval_ptr_dtor(&ch->handlers->write->stream);
3593	zval_ptr_dtor(&ch->handlers->read->stream);
3594
3595	efree(ch->handlers->write);
3596	efree(ch->handlers->write_header);
3597	efree(ch->handlers->read);
3598
3599	if (ch->handlers->progress) {
3600		zval_ptr_dtor(&ch->handlers->progress->func_name);
3601		efree(ch->handlers->progress);
3602	}
3603
3604#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3605	if (ch->handlers->fnmatch) {
3606		zval_ptr_dtor(&ch->handlers->fnmatch->func_name);
3607		efree(ch->handlers->fnmatch);
3608	}
3609#endif
3610
3611	efree(ch->handlers);
3612	efree(ch);
3613}
3614/* }}} */
3615
3616/* {{{ _php_curl_close()
3617   List destructor for curl handles */
3618static void _php_curl_close(zend_resource *rsrc)
3619{
3620	php_curl *ch = (php_curl *) rsrc->ptr;
3621	_php_curl_close_ex(ch);
3622}
3623/* }}} */
3624
3625/* {{{ proto bool curl_strerror(int code)
3626      return string describing error code */
3627PHP_FUNCTION(curl_strerror)
3628{
3629	zend_long code;
3630	const char *str;
3631
3632	ZEND_PARSE_PARAMETERS_START(1, 1)
3633		Z_PARAM_LONG(code)
3634	ZEND_PARSE_PARAMETERS_END();
3635
3636	str = curl_easy_strerror(code);
3637	if (str) {
3638		RETURN_STRING(str);
3639	} else {
3640		RETURN_NULL();
3641	}
3642}
3643/* }}} */
3644
3645/* {{{ _php_curl_reset_handlers()
3646   Reset all handlers of a given php_curl */
3647static void _php_curl_reset_handlers(php_curl *ch)
3648{
3649	if (!Z_ISUNDEF(ch->handlers->write->stream)) {
3650		zval_ptr_dtor(&ch->handlers->write->stream);
3651		ZVAL_UNDEF(&ch->handlers->write->stream);
3652	}
3653	ch->handlers->write->fp = NULL;
3654	ch->handlers->write->method = PHP_CURL_STDOUT;
3655
3656	if (!Z_ISUNDEF(ch->handlers->write_header->stream)) {
3657		zval_ptr_dtor(&ch->handlers->write_header->stream);
3658		ZVAL_UNDEF(&ch->handlers->write_header->stream);
3659	}
3660	ch->handlers->write_header->fp = NULL;
3661	ch->handlers->write_header->method = PHP_CURL_IGNORE;
3662
3663	if (!Z_ISUNDEF(ch->handlers->read->stream)) {
3664		zval_ptr_dtor(&ch->handlers->read->stream);
3665		ZVAL_UNDEF(&ch->handlers->read->stream);
3666	}
3667	ch->handlers->read->fp = NULL;
3668	ch->handlers->read->res = NULL;
3669	ch->handlers->read->method  = PHP_CURL_DIRECT;
3670
3671	if (!Z_ISUNDEF(ch->handlers->std_err)) {
3672		zval_ptr_dtor(&ch->handlers->std_err);
3673		ZVAL_UNDEF(&ch->handlers->std_err);
3674	}
3675
3676	if (ch->handlers->progress) {
3677		zval_ptr_dtor(&ch->handlers->progress->func_name);
3678		efree(ch->handlers->progress);
3679		ch->handlers->progress = NULL;
3680	}
3681
3682#if LIBCURL_VERSION_NUM >= 0x071500 /* Available since 7.21.0 */
3683	if (ch->handlers->fnmatch) {
3684		zval_ptr_dtor(&ch->handlers->fnmatch->func_name);
3685		efree(ch->handlers->fnmatch);
3686		ch->handlers->fnmatch = NULL;
3687	}
3688#endif
3689
3690}
3691/* }}} */
3692
3693/* {{{ proto void curl_reset(resource ch)
3694   Reset all options of a libcurl session handle */
3695PHP_FUNCTION(curl_reset)
3696{
3697	zval       *zid;
3698	php_curl   *ch;
3699
3700	ZEND_PARSE_PARAMETERS_START(1, 1)
3701		Z_PARAM_RESOURCE(zid)
3702	ZEND_PARSE_PARAMETERS_END();
3703
3704	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3705		RETURN_FALSE;
3706	}
3707
3708	if (ch->in_callback) {
3709		php_error_docref(NULL, E_WARNING, "Attempt to reset cURL handle from a callback");
3710		return;
3711	}
3712
3713	curl_easy_reset(ch->cp);
3714	_php_curl_reset_handlers(ch);
3715	_php_curl_set_default_options(ch);
3716}
3717/* }}} */
3718
3719/* {{{ proto void curl_escape(resource ch, string str)
3720   URL encodes the given string */
3721PHP_FUNCTION(curl_escape)
3722{
3723	zend_string *str;
3724	char        *res;
3725	zval        *zid;
3726	php_curl    *ch;
3727
3728	ZEND_PARSE_PARAMETERS_START(2,2)
3729		Z_PARAM_RESOURCE(zid)
3730		Z_PARAM_STR(str)
3731	ZEND_PARSE_PARAMETERS_END();
3732
3733	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3734		RETURN_FALSE;
3735	}
3736
3737	if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) {
3738		RETURN_FALSE;
3739	}
3740
3741	if ((res = curl_easy_escape(ch->cp, ZSTR_VAL(str), ZSTR_LEN(str)))) {
3742		RETVAL_STRING(res);
3743		curl_free(res);
3744	} else {
3745		RETURN_FALSE;
3746	}
3747}
3748/* }}} */
3749
3750/* {{{ proto void curl_unescape(resource ch, string str)
3751   URL decodes the given string */
3752PHP_FUNCTION(curl_unescape)
3753{
3754	char        *out = NULL;
3755	int          out_len;
3756	zval        *zid;
3757	zend_string *str;
3758	php_curl    *ch;
3759
3760	ZEND_PARSE_PARAMETERS_START(2,2)
3761		Z_PARAM_RESOURCE(zid)
3762		Z_PARAM_STR(str)
3763	ZEND_PARSE_PARAMETERS_END();
3764
3765	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3766		RETURN_FALSE;
3767	}
3768
3769	if (ZEND_SIZE_T_INT_OVFL(ZSTR_LEN(str))) {
3770		RETURN_FALSE;
3771	}
3772
3773	if ((out = curl_easy_unescape(ch->cp, ZSTR_VAL(str), ZSTR_LEN(str), &out_len))) {
3774		RETVAL_STRINGL(out, out_len);
3775		curl_free(out);
3776	} else {
3777		RETURN_FALSE;
3778	}
3779}
3780/* }}} */
3781
3782#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
3783/* {{{ proto void curl_pause(resource ch, int bitmask)
3784       pause and unpause a connection */
3785PHP_FUNCTION(curl_pause)
3786{
3787	zend_long       bitmask;
3788	zval       *zid;
3789	php_curl   *ch;
3790
3791	ZEND_PARSE_PARAMETERS_START(2,2)
3792		Z_PARAM_RESOURCE(zid)
3793		Z_PARAM_LONG(bitmask)
3794	ZEND_PARSE_PARAMETERS_END();
3795
3796	if ((ch = (php_curl*)zend_fetch_resource(Z_RES_P(zid), le_curl_name, le_curl)) == NULL) {
3797		RETURN_FALSE;
3798	}
3799
3800	RETURN_LONG(curl_easy_pause(ch->cp, bitmask));
3801}
3802/* }}} */
3803#endif
3804
3805#endif /* HAVE_CURL */
3806
3807/*
3808 * Local variables:
3809 * tab-width: 4
3810 * c-basic-offset: 4
3811 * End:
3812 * vim600: fdm=marker
3813 * vim: noet sw=4 ts=4
3814 */
3815