summaryrefslogtreecommitdiff
path: root/ext/curl
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2013-03-14 05:42:27 +0000
committer <>2013-04-03 16:25:08 +0000
commitc4dd7a1a684490673e25aaf4fabec5df138854c4 (patch)
tree4d57c44caae4480efff02b90b9be86f44bf25409 /ext/curl
downloadphp2-master.tar.gz
Imported from /home/lorry/working-area/delta_php2/php-5.4.13.tar.bz2.HEADphp-5.4.13master
Diffstat (limited to 'ext/curl')
-rw-r--r--ext/curl/CREDITS2
-rw-r--r--ext/curl/config.m4161
-rw-r--r--ext/curl/config.w3228
-rw-r--r--ext/curl/curl.dsp186
-rw-r--r--ext/curl/interface.c2753
-rw-r--r--ext/curl/multi.c371
-rw-r--r--ext/curl/package.xml52
-rw-r--r--ext/curl/php_curl.h192
-rw-r--r--ext/curl/streams.c542
-rw-r--r--ext/curl/tests/bug27023.phpt48
-rw-r--r--ext/curl/tests/bug45161.phpt52
-rw-r--r--ext/curl/tests/bug46711.phpt36
-rw-r--r--ext/curl/tests/bug46739.phpt19
-rw-r--r--ext/curl/tests/bug48203.phpt36
-rw-r--r--ext/curl/tests/bug48203_multi.phpt90
-rw-r--r--ext/curl/tests/bug48207.phpt47
-rw-r--r--ext/curl/tests/bug48514.phpt27
-rw-r--r--ext/curl/tests/bug52202.phpt16
-rw-r--r--ext/curl/tests/bug52827.phpt32
-rw-r--r--ext/curl/tests/bug54798.phpt72
-rw-r--r--ext/curl/tests/bug55767.phpt53
-rw-r--r--ext/curl/tests/bug61948-win32.phpt25
-rw-r--r--ext/curl/tests/bug61948.phpt23
-rw-r--r--ext/curl/tests/bug62839.phpt18
-rw-r--r--ext/curl/tests/bug63363.phpt34
-rw-r--r--ext/curl/tests/bug63795.phpt34
-rw-r--r--ext/curl/tests/curl_CURLOPT_READDATA.phpt44
-rw-r--r--ext/curl/tests/curl_basic_001.phpt45
-rw-r--r--ext/curl/tests/curl_basic_002.phpt41
-rw-r--r--ext/curl/tests/curl_basic_003.phpt56
-rw-r--r--ext/curl/tests/curl_basic_004.phpt41
-rw-r--r--ext/curl/tests/curl_basic_005.phpt41
-rw-r--r--ext/curl/tests/curl_basic_006.phpt41
-rw-r--r--ext/curl/tests/curl_basic_007.phpt24
-rw-r--r--ext/curl/tests/curl_basic_008.phpt29
-rw-r--r--ext/curl/tests/curl_basic_009.phpt23
-rw-r--r--ext/curl/tests/curl_basic_010.phpt30
-rw-r--r--ext/curl/tests/curl_basic_011.phpt38
-rw-r--r--ext/curl/tests/curl_basic_012.phpt38
-rw-r--r--ext/curl/tests/curl_basic_013.phpt38
-rw-r--r--ext/curl/tests/curl_basic_014.phpt15
-rw-r--r--ext/curl/tests/curl_basic_015.phpt16
-rw-r--r--ext/curl/tests/curl_basic_016.phpt63
-rw-r--r--ext/curl/tests/curl_basic_017.phpt69
-rw-r--r--ext/curl/tests/curl_basic_018.phpt72
-rw-r--r--ext/curl/tests/curl_basic_019.phpt28
-rw-r--r--ext/curl/tests/curl_basic_020.phpt25
-rw-r--r--ext/curl/tests/curl_basic_021.phpt24
-rw-r--r--ext/curl/tests/curl_close_basic.phpt19
-rw-r--r--ext/curl/tests/curl_copy_handle_basic.phpt30
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_001.phpt42
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_002.phpt47
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_004.phpt44
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_005.phpt50
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_006.phpt37
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_007.phpt45
-rw-r--r--ext/curl/tests/curl_copy_handle_basic_008.phpt25
-rw-r--r--ext/curl/tests/curl_copy_handle_variation1.phpt32
-rw-r--r--ext/curl/tests/curl_copy_handle_variation2.phpt44
-rw-r--r--ext/curl/tests/curl_error_basic.phpt41
-rw-r--r--ext/curl/tests/curl_file_deleted_before_curl_close.phpt38
-rw-r--r--ext/curl/tests/curl_ftp_pasv.phpt59
-rw-r--r--ext/curl/tests/curl_multi_close_basic.phpt19
-rw-r--r--ext/curl/tests/curl_multi_getcontent_basic3.phpt62
-rw-r--r--ext/curl/tests/curl_multi_getcontent_error1.phpt51
-rw-r--r--ext/curl/tests/curl_multi_getcontent_error2.phpt51
-rw-r--r--ext/curl/tests/curl_multi_getcontent_error3.phpt53
-rw-r--r--ext/curl/tests/curl_multi_getcontent_error4.phpt66
-rw-r--r--ext/curl/tests/curl_multi_init_basic.phpt31
-rw-r--r--ext/curl/tests/curl_multi_segfault.phpt56
-rw-r--r--ext/curl/tests/curl_multi_select_basic1.phpt27
-rw-r--r--ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt22
-rw-r--r--ext/curl/tests/curl_setopt_CURLOPT_READFUNCTION.phpt54
-rw-r--r--ext/curl/tests/curl_setopt_array_basic.phpt56
-rw-r--r--ext/curl/tests/curl_setopt_basic002.phpt52
-rw-r--r--ext/curl/tests/curl_setopt_basic003.phpt43
-rw-r--r--ext/curl/tests/curl_setopt_basic004.phpt44
-rw-r--r--ext/curl/tests/curl_setopt_error.phpt45
-rw-r--r--ext/curl/tests/curl_testdata1.txt1
-rw-r--r--ext/curl/tests/curl_testdata2.txt1
-rw-r--r--ext/curl/tests/curl_version_error.phpt35
-rw-r--r--ext/curl/tests/curl_version_variation1.phpt165
-rw-r--r--ext/curl/tests/curl_write_callback.phpt36
-rw-r--r--ext/curl/tests/curl_write_file.phpt38
-rw-r--r--ext/curl/tests/curl_write_return.phpt33
-rw-r--r--ext/curl/tests/curl_write_stdout.phpt30
-rw-r--r--ext/curl/tests/curl_writeheader_callback.phpt37
-rw-r--r--ext/curl/tests/responder/get.php39
88 files changed, 7490 insertions, 0 deletions
diff --git a/ext/curl/CREDITS b/ext/curl/CREDITS
new file mode 100644
index 0000000..610e036
--- /dev/null
+++ b/ext/curl/CREDITS
@@ -0,0 +1,2 @@
+cURL
+Sterling Hughes
diff --git a/ext/curl/config.m4 b/ext/curl/config.m4
new file mode 100644
index 0000000..fbb4f5b
--- /dev/null
+++ b/ext/curl/config.m4
@@ -0,0 +1,161 @@
+dnl
+dnl $Id$
+dnl
+
+PHP_ARG_WITH(curl, for cURL support,
+[ --with-curl[=DIR] Include cURL support])
+
+dnl Temporary option while we develop this aspect of the extension
+PHP_ARG_WITH(curlwrappers, if we should use cURL for url streams,
+[ --with-curlwrappers EXPERIMENTAL: Use cURL for url streams], no, no)
+
+if test "$PHP_CURL" != "no"; then
+ if test -r $PHP_CURL/include/curl/easy.h; then
+ CURL_DIR=$PHP_CURL
+ else
+ AC_MSG_CHECKING(for cURL in default path)
+ for i in /usr/local /usr; do
+ if test -r $i/include/curl/easy.h; then
+ CURL_DIR=$i
+ AC_MSG_RESULT(found in $i)
+ break
+ fi
+ done
+ fi
+
+ if test -z "$CURL_DIR"; then
+ AC_MSG_RESULT(not found)
+ AC_MSG_ERROR(Please reinstall the libcurl distribution -
+ easy.h should be in <curl-dir>/include/curl/)
+ fi
+
+ CURL_CONFIG="curl-config"
+ AC_MSG_CHECKING(for cURL 7.10.5 or greater)
+
+ if ${CURL_DIR}/bin/curl-config --libs > /dev/null 2>&1; then
+ CURL_CONFIG=${CURL_DIR}/bin/curl-config
+ else
+ if ${CURL_DIR}/curl-config --libs > /dev/null 2>&1; then
+ CURL_CONFIG=${CURL_DIR}/curl-config
+ fi
+ fi
+
+ curl_version_full=`$CURL_CONFIG --version`
+ curl_version=`echo ${curl_version_full} | sed -e 's/libcurl //' | $AWK 'BEGIN { FS = "."; } { printf "%d", ($1 * 1000 + $2) * 1000 + $3;}'`
+ if test "$curl_version" -ge 7010005; then
+ AC_MSG_RESULT($curl_version_full)
+ CURL_LIBS=`$CURL_CONFIG --libs`
+ else
+ AC_MSG_ERROR(cURL version 7.10.5 or later is required to compile php with cURL support)
+ fi
+
+ PHP_ADD_INCLUDE($CURL_DIR/include)
+ PHP_EVAL_LIBLINE($CURL_LIBS, CURL_SHARED_LIBADD)
+ PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/$PHP_LIBDIR, CURL_SHARED_LIBADD)
+
+ AC_MSG_CHECKING([for SSL support in libcurl])
+ CURL_SSL=`$CURL_CONFIG --feature | $EGREP SSL`
+ if test "$CURL_SSL" = "SSL"; then
+ AC_MSG_RESULT([yes])
+ AC_DEFINE([HAVE_CURL_SSL], [1], [Have cURL with SSL support])
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="`$CURL_CONFIG --cflags`"
+
+ AC_PROG_CPP
+ AC_MSG_CHECKING([for openssl support in libcurl])
+ AC_TRY_RUN([
+#include <curl/curl.h>
+
+int main(int argc, char *argv[])
+{
+ curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
+
+ if (data && data->ssl_version && *data->ssl_version) {
+ const char *ptr = data->ssl_version;
+
+ while(*ptr == ' ') ++ptr;
+ return strncasecmp(ptr, "OpenSSL", sizeof("OpenSSL")-1);
+ }
+ return 1;
+}
+ ],[
+ AC_MSG_RESULT([yes])
+ AC_CHECK_HEADERS([openssl/crypto.h], [
+ AC_DEFINE([HAVE_CURL_OPENSSL], [1], [Have cURL with OpenSSL support])
+ ])
+ ], [
+ AC_MSG_RESULT([no])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+
+ AC_MSG_CHECKING([for gnutls support in libcurl])
+ AC_TRY_RUN([
+#include <curl/curl.h>
+
+int main(int argc, char *argv[])
+{
+ curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
+
+ if (data && data->ssl_version && *data->ssl_version) {
+ const char *ptr = data->ssl_version;
+
+ while(*ptr == ' ') ++ptr;
+ return strncasecmp(ptr, "GnuTLS", sizeof("GnuTLS")-1);
+ }
+ return 1;
+}
+], [
+ AC_MSG_RESULT([yes])
+ AC_CHECK_HEADER([gcrypt.h], [
+ AC_DEFINE([HAVE_CURL_GNUTLS], [1], [Have cURL with GnuTLS support])
+ ])
+ ], [
+ AC_MSG_RESULT([no])
+ ], [
+ AC_MSG_RESULT([no])
+ ])
+
+ CFLAGS="$save_CFLAGS"
+ else
+ AC_MSG_RESULT([no])
+ fi
+
+ PHP_CHECK_LIBRARY(curl,curl_easy_perform,
+ [
+ AC_DEFINE(HAVE_CURL,1,[ ])
+ ],[
+ AC_MSG_ERROR(There is something wrong. Please check config.log for more information.)
+ ],[
+ $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
+ ])
+
+ PHP_CHECK_LIBRARY(curl,curl_version_info,
+ [
+ AC_DEFINE(HAVE_CURL_VERSION_INFO,1,[ ])
+ ],[],[
+ $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
+ ])
+
+ PHP_CHECK_LIBRARY(curl,curl_easy_strerror,
+ [
+ AC_DEFINE(HAVE_CURL_EASY_STRERROR,1,[ ])
+ ],[],[
+ $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
+ ])
+
+ PHP_CHECK_LIBRARY(curl,curl_multi_strerror,
+ [
+ AC_DEFINE(HAVE_CURL_MULTI_STRERROR,1,[ ])
+ ],[],[
+ $CURL_LIBS -L$CURL_DIR/$PHP_LIBDIR
+ ])
+
+ if test "$PHP_CURLWRAPPERS" != "no" ; then
+ AC_DEFINE(PHP_CURL_URL_WRAPPERS,1,[ ])
+ fi
+
+ PHP_NEW_EXTENSION(curl, interface.c multi.c streams.c, $ext_shared)
+ PHP_SUBST(CURL_SHARED_LIBADD)
+fi
diff --git a/ext/curl/config.w32 b/ext/curl/config.w32
new file mode 100644
index 0000000..930adcf
--- /dev/null
+++ b/ext/curl/config.w32
@@ -0,0 +1,28 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("curl", "cURL support", "no");
+
+if (PHP_CURL != "no") {
+ if (CHECK_LIB("libcurl_a.lib;libcurl.lib", "curl", PHP_CURL) &&
+ CHECK_HEADER_ADD_INCLUDE("curl/easy.h", "CFLAGS_CURL") &&
+ CHECK_LIB("ssleay32.lib", "curl", PHP_CURL) &&
+ CHECK_LIB("libeay32.lib", "curl", PHP_CURL)
+ && CHECK_LIB("winmm.lib", "curl", PHP_CURL)
+ && CHECK_LIB("wldap32.lib", "curl", PHP_CURL)
+ && (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "curl", PHP_CURL))) ||
+ (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "curl", PHP_CURL)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED)))
+ ) {
+ EXTENSION("curl", "interface.c multi.c streams.c", true);
+ AC_DEFINE('HAVE_CURL', 1, 'Have cURL library');
+ AC_DEFINE('HAVE_CURL_SSL', 1, 'Have SSL suppurt in cURL');
+ AC_DEFINE('HAVE_CURL_EASY_STRERROR', 1, 'Have curl_easy_strerror in cURL');
+ AC_DEFINE('HAVE_CURL_MULTI_STRERROR', 1, 'Have curl_multi_strerror in cURL');
+ AC_DEFINE('HAVE_CURL_VERSION_INFO', 1, 'Have curl_version_info in cURL');
+ ADD_FLAG("CFLAGS_CURL", "/D CURL_STATICLIB");
+ // TODO: check for curl_version_info
+ // AC_DEFINE('PHP_CURL_URL_WRAPPERS', 0, 'Use curl for URL wrappers [experimental]');
+ } else {
+ WARNING("curl not enabled; libraries and headers not found");
+ }
+}
diff --git a/ext/curl/curl.dsp b/ext/curl/curl.dsp
new file mode 100644
index 0000000..81d8231
--- /dev/null
+++ b/ext/curl/curl.dsp
@@ -0,0 +1,186 @@
+# Microsoft Developer Studio Project File - Name="curl" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=curl - Win32 Release_TS
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "curl.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "curl.mak" CFG="curl - Win32 Release_TS"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "curl - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "curl - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "curl - Win32 Debug_TS_SSL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "curl - Win32 Release_TS_SSL" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "curl - Win32 Release_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release_TS"
+# PROP BASE Intermediate_Dir "Release_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS"
+# PROP Intermediate_Dir "Release_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_CURL" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\main" /I "..\..\..\php_build\curl\include" /D "WIN32" /D "CURL_EXPORTS" /D "COMPILE_DL_CURL" /D ZTS=1 /D HAVE_CURL=1 /D ZEND_DEBUG=0 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /machine:I386
+# ADD LINK32 php5ts.lib libcurl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /machine:I386 /nodefaultlib:"MSVCRT" /out:"..\..\Release_TS/php_curl.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" /libpath:"..\..\..\php_build\curl\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "curl - Win32 Debug_TS"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Debug_TS"
+# PROP BASE Intermediate_Dir "Debug_TS"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_TS"
+# PROP Intermediate_Dir "Debug_TS"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "COMPILE_DL_CURL" /D ZTS=1 /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\main" /I "..\..\..\php_build\curl\include" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURL_EXPORTS" /D "COMPILE_DL_CURL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_CURL=1 /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib php5ts.lib /nologo /dll /machine:I386
+# ADD LINK32 php5ts_debug.lib libcurl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib wsock32.lib /nologo /dll /incremental:yes /debug /machine:I386 /nodefaultlib:"MSVCRTD" /out:"..\..\Debug_TS/php_curl.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\curl\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "curl - Win32 Debug_TS_SSL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "curl___Win32_Debug_TS_SSL"
+# PROP BASE Intermediate_Dir "curl___Win32_Debug_TS_SSL"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Debug_TS_SSL"
+# PROP Intermediate_Dir "Debug_TS_SSL"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\main" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURL_EXPORTS" /D "COMPILE_DL_CURL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_CURL=1 /FR /YX /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /ZI /Od /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\main" /I "..\..\..\php_build\curl\include" /D ZEND_DEBUG=1 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CURL_EXPORTS" /D "COMPILE_DL_CURL" /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D HAVE_CURL=1 /FR /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 php5ts_debug.lib libcurl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /incremental:yes /debug /machine:I386 /nodefaultlib:"msvcrtd.lib" /out:"..\..\Debug_TS/php_curl.dll" /libpath:"..\..\Debug_TS"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 php5ts_debug.lib libcurl.lib ssleay32.lib libeay32.lib msvcrt.lib ws2_32.lib winmm.lib zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /incremental:yes /debug /machine:I386 /nodefaultlib:"MSVCRTD" /out:"..\..\Debug_TS/php_curl.dll" /libpath:"..\..\Debug_TS" /libpath:"..\..\..\php_build\curl\lib"
+# SUBTRACT LINK32 /pdb:none /nodefaultlib
+
+!ELSEIF "$(CFG)" == "curl - Win32 Release_TS_SSL"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "curl___Win32_Release_TS_SSL"
+# PROP BASE Intermediate_Dir "curl___Win32_Release_TS_SSL"
+# PROP BASE Ignore_Export_Lib 0
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release_TS_SSL"
+# PROP Intermediate_Dir "Release_TS_SSL"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\main" /D "WIN32" /D "CURL_EXPORTS" /D "COMPILE_DL_CURL" /D ZTS=1 /D HAVE_CURL=1 /D ZEND_DEBUG=0 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /YX /FD /c
+# ADD CPP /nologo /MD /W3 /GX /O2 /I "..\.." /I "..\..\Zend" /I "..\..\..\bindlib_w32" /I "..\..\TSRM" /I "..\..\main" /I "..\..\..\php_build\curl\include" /D "WIN32" /D "CURL_EXPORTS" /D "COMPILE_DL_CURL" /D ZTS=1 /D HAVE_CURL=1 /D ZEND_DEBUG=0 /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZEND_WIN32" /D "PHP_WIN32" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x406 /d "NDEBUG"
+# ADD RSC /l 0x406 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 php5ts.lib libcurl.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /nodefaultlib:"msvcrt.lib" /out:"..\..\Release_TS/php_curl.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline"
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 php5ts.lib libcurl.lib ssleay32.lib libeay32.lib msvcrt.lib ws2_32.lib winmm.lib zlib.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /dll /machine:I386 /nodefaultlib:"MSVCRT" /out:"..\..\Release_TS/php_curl.dll" /libpath:"..\..\Release_TS" /libpath:"..\..\Release_TS_Inline" /libpath:"..\..\..\php_build\curl\lib"
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "curl - Win32 Release_TS"
+# Name "curl - Win32 Debug_TS"
+# Name "curl - Win32 Debug_TS_SSL"
+# Name "curl - Win32 Release_TS_SSL"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\interface.c
+# End Source File
+
+# Begin Source File
+SOURCE=.\multi.c
+# End Source File
+
+# Begin Source File
+SOURCE=.\streams.c
+# End Source File
+
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\php_curl.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# End Target
+# End Project
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
new file mode 100644
index 0000000..531f15b
--- /dev/null
+++ b/ext/curl/interface.c
@@ -0,0 +1,2753 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you 6 copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sterling Hughes <sterling@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if HAVE_CURL
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef PHP_WIN32
+#include <winsock2.h>
+#include <sys/types.h>
+#endif
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+/* As of curl 7.11.1 this is no longer defined inside curl.h */
+#ifndef HttpPost
+#define HttpPost curl_httppost
+#endif
+
+/* {{{ cruft for thread safe SSL crypto locks */
+#if defined(ZTS) && defined(HAVE_CURL_SSL)
+# ifdef PHP_WIN32
+# define PHP_CURL_NEED_OPENSSL_TSL
+# include <openssl/crypto.h>
+# else /* !PHP_WIN32 */
+# if defined(HAVE_CURL_OPENSSL)
+# if defined(HAVE_OPENSSL_CRYPTO_H)
+# define PHP_CURL_NEED_OPENSSL_TSL
+# include <openssl/crypto.h>
+# else
+# warning \
+ "libcurl was compiled with OpenSSL support, but configure could not find " \
+ "openssl/crypto.h; thus no SSL crypto locking callbacks will be set, which may " \
+ "cause random crashes on SSL requests"
+# endif
+# elif defined(HAVE_CURL_GNUTLS)
+# if defined(HAVE_GCRYPT_H)
+# define PHP_CURL_NEED_GNUTLS_TSL
+# include <gcrypt.h>
+# else
+# warning \
+ "libcurl was compiled with GnuTLS support, but configure could not find " \
+ "gcrypt.h; thus no SSL crypto locking callbacks will be set, which may " \
+ "cause random crashes on SSL requests"
+# endif
+# else
+# warning \
+ "libcurl was compiled with SSL support, but configure could not determine which" \
+ "library was used; thus no SSL crypto locking callbacks will be set, which may " \
+ "cause random crashes on SSL requests"
+# endif /* HAVE_CURL_OPENSSL || HAVE_CURL_GNUTLS */
+# endif /* PHP_WIN32 */
+#endif /* ZTS && HAVE_CURL_SSL */
+/* }}} */
+
+#define SMART_STR_PREALLOC 4096
+
+#include "ext/standard/php_smart_str.h"
+#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "ext/standard/url.h"
+#include "php_curl.h"
+
+int le_curl;
+int le_curl_multi_handle;
+
+#ifdef PHP_CURL_NEED_OPENSSL_TSL /* {{{ */
+static MUTEX_T *php_curl_openssl_tsl = NULL;
+
+static void php_curl_ssl_lock(int mode, int n, const char * file, int line)
+{
+ if (mode & CRYPTO_LOCK) {
+ tsrm_mutex_lock(php_curl_openssl_tsl[n]);
+ } else {
+ tsrm_mutex_unlock(php_curl_openssl_tsl[n]);
+ }
+}
+
+static unsigned long php_curl_ssl_id(void)
+{
+ return (unsigned long) tsrm_thread_id();
+}
+#endif
+/* }}} */
+
+#ifdef PHP_CURL_NEED_GNUTLS_TSL /* {{{ */
+static int php_curl_ssl_mutex_create(void **m)
+{
+ if (*((MUTEX_T *) m) = tsrm_mutex_alloc()) {
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+}
+
+static int php_curl_ssl_mutex_destroy(void **m)
+{
+ tsrm_mutex_free(*((MUTEX_T *) m));
+ return SUCCESS;
+}
+
+static int php_curl_ssl_mutex_lock(void **m)
+{
+ return tsrm_mutex_lock(*((MUTEX_T *) m));
+}
+
+static int php_curl_ssl_mutex_unlock(void **m)
+{
+ return tsrm_mutex_unlock(*((MUTEX_T *) m));
+}
+
+static struct gcry_thread_cbs php_curl_gnutls_tsl = {
+ GCRY_THREAD_OPTION_USER,
+ NULL,
+ php_curl_ssl_mutex_create,
+ php_curl_ssl_mutex_destroy,
+ php_curl_ssl_mutex_lock,
+ php_curl_ssl_mutex_unlock
+};
+#endif
+/* }}} */
+
+static void _php_curl_close_ex(php_curl *ch TSRMLS_DC);
+static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
+
+
+#define SAVE_CURL_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
+
+#define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s), (long) v);
+#define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s), (double) v);
+#define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s), (char *) (v ? v : ""), 1);
+#define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s), (zval *) v);
+
+#if defined(PHP_WIN32) || defined(__GNUC__)
+# define php_curl_ret(__ret) RETVAL_FALSE; return __ret;
+#else
+# define php_curl_ret(__ret) RETVAL_FALSE; return;
+#endif
+
+static int php_curl_option_url(php_curl *ch, const char *url, const int len TSRMLS_DC) /* {{{ */
+{
+ CURLcode error = CURLE_OK;
+#if LIBCURL_VERSION_NUM < 0x071100
+ char *copystr = NULL;
+#endif
+ /* Disable file:// if open_basedir are used */
+ if (PG(open_basedir) && *PG(open_basedir)) {
+#if LIBCURL_VERSION_NUM >= 0x071304
+ error = curl_easy_setopt(ch->cp, CURLOPT_PROTOCOLS, CURLPROTO_ALL & ~CURLPROTO_FILE);
+#else
+ php_url *uri;
+
+ if (!(uri = php_url_parse_ex(url, len))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL '%s'", url);
+ return 0;
+ }
+
+ if (uri->scheme && !strncasecmp("file", uri->scheme, sizeof("file"))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Protocol 'file' disabled in cURL");
+ php_url_free(uri);
+ return 0;
+ }
+ php_url_free(uri);
+#endif
+ }
+ /* Strings passed to libcurl as 'char *' arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
+#if LIBCURL_VERSION_NUM >= 0x071100
+ error = curl_easy_setopt(ch->cp, CURLOPT_URL, url);
+#else
+ copystr = estrndup(url, len);
+ error = curl_easy_setopt(ch->cp, CURLOPT_URL, copystr);
+ zend_llist_add_element(&ch->to_free->str, &copystr);
+#endif
+
+ return (error == CURLE_OK ? 1 : 0);
+}
+/* }}} */
+
+int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */
+{
+ php_stream *stream;
+ if (!ch || !ch->handlers) {
+ return 0;
+ }
+
+ if (ch->handlers->std_err) {
+ stream = (php_stream *) zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream == NULL) {
+ if (reporterror) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_STDERR resource has gone away, resetting to stderr");
+ }
+ zval_ptr_dtor(&ch->handlers->std_err);
+ ch->handlers->std_err = NULL;
+
+ curl_easy_setopt(ch->cp, CURLOPT_STDERR, stderr);
+ }
+ }
+ if (ch->handlers->read && ch->handlers->read->stream) {
+ stream = (php_stream *) zend_fetch_resource(&ch->handlers->read->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream == NULL) {
+ if (reporterror) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_INFILE resource has gone away, resetting to default");
+ }
+ zval_ptr_dtor(&ch->handlers->read->stream);
+ ch->handlers->read->fd = 0;
+ ch->handlers->read->fp = 0;
+ ch->handlers->read->stream = NULL;
+
+ curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
+ }
+ }
+ if (ch->handlers->write_header && ch->handlers->write_header->stream) {
+ stream = (php_stream *) zend_fetch_resource(&ch->handlers->write_header->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream == NULL) {
+ if (reporterror) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_WRITEHEADER resource has gone away, resetting to default");
+ }
+ zval_ptr_dtor(&ch->handlers->write_header->stream);
+ ch->handlers->write_header->fp = 0;
+ ch->handlers->write_header->stream = NULL;
+
+ ch->handlers->write_header->method = PHP_CURL_IGNORE;
+ curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
+ }
+ }
+ if (ch->handlers->write && ch->handlers->write->stream) {
+ stream = (php_stream *) zend_fetch_resource(&ch->handlers->write->stream TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream == NULL) {
+ if (reporterror) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FILE resource has gone away, resetting to default");
+ }
+ zval_ptr_dtor(&ch->handlers->write->stream);
+ ch->handlers->write->fp = 0;
+ ch->handlers->write->stream = NULL;
+
+ ch->handlers->write->method = PHP_CURL_STDOUT;
+ ch->handlers->write->type = PHP_CURL_ASCII;
+ curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
+ }
+ }
+ return 1;
+}
+/* }}} */
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_version, 0, 0, 0)
+ ZEND_ARG_INFO(0, version)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_init, 0, 0, 0)
+ ZEND_ARG_INFO(0, url)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_copy_handle, 0)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt, 0)
+ ZEND_ARG_INFO(0, ch)
+ ZEND_ARG_INFO(0, option)
+ ZEND_ARG_INFO(0, value)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_setopt_array, 0)
+ ZEND_ARG_INFO(0, ch)
+ ZEND_ARG_ARRAY_INFO(0, options, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_exec, 0)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_getinfo, 0, 0, 1)
+ ZEND_ARG_INFO(0, ch)
+ ZEND_ARG_INFO(0, option)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_error, 0)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_errno, 0)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_close, 0)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_init, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_add_handle, 0)
+ ZEND_ARG_INFO(0, mh)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_remove_handle, 0)
+ ZEND_ARG_INFO(0, mh)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_select, 0, 0, 1)
+ ZEND_ARG_INFO(0, mh)
+ ZEND_ARG_INFO(0, timeout)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_exec, 0, 0, 1)
+ ZEND_ARG_INFO(0, mh)
+ ZEND_ARG_INFO(1, still_running)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_getcontent, 0)
+ ZEND_ARG_INFO(0, ch)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_curl_multi_info_read, 0, 0, 1)
+ ZEND_ARG_INFO(0, mh)
+ ZEND_ARG_INFO(1, msgs_in_queue)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
+ ZEND_ARG_INFO(0, mh)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+/* {{{ curl_functions[]
+ */
+const zend_function_entry curl_functions[] = {
+ PHP_FE(curl_init, arginfo_curl_init)
+ PHP_FE(curl_copy_handle, arginfo_curl_copy_handle)
+ PHP_FE(curl_version, arginfo_curl_version)
+ PHP_FE(curl_setopt, arginfo_curl_setopt)
+ PHP_FE(curl_setopt_array, arginfo_curl_setopt_array)
+ PHP_FE(curl_exec, arginfo_curl_exec)
+ PHP_FE(curl_getinfo, arginfo_curl_getinfo)
+ PHP_FE(curl_error, arginfo_curl_error)
+ PHP_FE(curl_errno, arginfo_curl_errno)
+ PHP_FE(curl_close, arginfo_curl_close)
+ PHP_FE(curl_multi_init, arginfo_curl_multi_init)
+ PHP_FE(curl_multi_add_handle, arginfo_curl_multi_add_handle)
+ PHP_FE(curl_multi_remove_handle, arginfo_curl_multi_remove_handle)
+ PHP_FE(curl_multi_select, arginfo_curl_multi_select)
+ PHP_FE(curl_multi_exec, arginfo_curl_multi_exec)
+ PHP_FE(curl_multi_getcontent, arginfo_curl_multi_getcontent)
+ PHP_FE(curl_multi_info_read, arginfo_curl_multi_info_read)
+ PHP_FE(curl_multi_close, arginfo_curl_multi_close)
+ PHP_FE_END
+};
+/* }}} */
+
+/* {{{ curl_module_entry
+ */
+zend_module_entry curl_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "curl",
+ curl_functions,
+ PHP_MINIT(curl),
+ PHP_MSHUTDOWN(curl),
+ NULL,
+ NULL,
+ PHP_MINFO(curl),
+ NO_VERSION_YET,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+#ifdef COMPILE_DL_CURL
+ZEND_GET_MODULE (curl)
+#endif
+
+/* {{{ PHP_INI_BEGIN */
+PHP_INI_BEGIN()
+ PHP_INI_ENTRY("curl.cainfo", "", PHP_INI_SYSTEM, NULL)
+PHP_INI_END()
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(curl)
+{
+ curl_version_info_data *d;
+ char **p;
+ char str[1024];
+ size_t n = 0;
+
+ d = curl_version_info(CURLVERSION_NOW);
+ php_info_print_table_start();
+ php_info_print_table_row(2, "cURL support", "enabled");
+ php_info_print_table_row(2, "cURL Information", d->version);
+ sprintf(str, "%d", d->age);
+ php_info_print_table_row(2, "Age", str);
+
+ /* To update on each new cURL release using src/main.c in cURL sources */
+ if (d->features) {
+ struct feat {
+ const char *name;
+ int bitmask;
+ };
+
+ unsigned int i;
+
+ static const struct feat feats[] = {
+#if LIBCURL_VERSION_NUM > 0x070a06 /* 7.10.7 */
+ {"AsynchDNS", CURL_VERSION_ASYNCHDNS},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070a05 /* 7.10.6 */
+ {"Debug", CURL_VERSION_DEBUG},
+ {"GSS-Negotiate", CURL_VERSION_GSSNEGOTIATE},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070b02 /* 7.12.0 */
+ {"IDN", CURL_VERSION_IDN},
+#endif
+#ifdef CURL_VERSION_IPV6
+ {"IPv6", CURL_VERSION_IPV6},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070b00 /* 7.11.1 */
+ {"Largefile", CURL_VERSION_LARGEFILE},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070a05 /* 7.10.6 */
+ {"NTLM", CURL_VERSION_NTLM},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070a07 /* 7.10.8 */
+ {"SPNEGO", CURL_VERSION_SPNEGO},
+#endif
+#ifdef CURL_VERSION_SSL
+ {"SSL", CURL_VERSION_SSL},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070d01 /* 7.13.2 */
+ {"SSPI", CURL_VERSION_SSPI},
+#endif
+#ifdef CURL_VERSION_KERBEROS4
+ {"krb4", CURL_VERSION_KERBEROS4},
+#endif
+#ifdef CURL_VERSION_LIBZ
+ {"libz", CURL_VERSION_LIBZ},
+#endif
+#if LIBCURL_VERSION_NUM > 0x070f03 /* 7.15.4 */
+ {"CharConv", CURL_VERSION_CONV},
+#endif
+ {NULL, 0}
+ };
+
+ php_info_print_table_row(1, "Features");
+ for(i=0; i<sizeof(feats)/sizeof(feats[0]); i++) {
+ if (feats[i].name) {
+ php_info_print_table_row(2, feats[i].name, d->features & feats[i].bitmask ? "Yes" : "No");
+ }
+ }
+ }
+
+ n = 0;
+ p = (char **) d->protocols;
+ while (*p != NULL) {
+ n += sprintf(str + n, "%s%s", *p, *(p + 1) != NULL ? ", " : "");
+ p++;
+ }
+ php_info_print_table_row(2, "Protocols", str);
+
+ php_info_print_table_row(2, "Host", d->host);
+
+ if (d->ssl_version) {
+ php_info_print_table_row(2, "SSL Version", d->ssl_version);
+ }
+
+ if (d->libz_version) {
+ php_info_print_table_row(2, "ZLib Version", d->libz_version);
+ }
+
+#if defined(CURLVERSION_SECOND) && CURLVERSION_NOW >= CURLVERSION_SECOND
+ if (d->ares) {
+ php_info_print_table_row(2, "ZLib Version", d->ares);
+ }
+#endif
+
+#if defined(CURLVERSION_THIRD) && CURLVERSION_NOW >= CURLVERSION_THIRD
+ if (d->libidn) {
+ php_info_print_table_row(2, "libIDN Version", d->libidn);
+ }
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x071300
+
+ if (d->iconv_ver_num) {
+ php_info_print_table_row(2, "IconV Version", d->iconv_ver_num);
+ }
+
+ if (d->libssh_version) {
+ php_info_print_table_row(2, "libSSH Version", d->libssh_version);
+ }
+#endif
+ php_info_print_table_end();
+}
+/* }}} */
+
+#define REGISTER_CURL_CONSTANT(__c) REGISTER_LONG_CONSTANT(#__c, __c, CONST_CS | CONST_PERSISTENT)
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(curl)
+{
+ le_curl = zend_register_list_destructors_ex(_php_curl_close, NULL, "curl", module_number);
+ le_curl_multi_handle = zend_register_list_destructors_ex(_php_curl_multi_close, NULL, "curl_multi", module_number);
+
+ REGISTER_INI_ENTRIES();
+
+ /* See http://curl.haxx.se/lxr/source/docs/libcurl/symbols-in-versions
+ or curl src/docs/libcurl/symbols-in-versions for a (almost) complete list
+ of options and which version they were introduced */
+
+ /* Constants for curl_setopt() */
+#if LIBCURL_VERSION_NUM > 0x070a07 /* CURLOPT_IPRESOLVE is available since curl 7.10.8 */
+ REGISTER_CURL_CONSTANT(CURLOPT_IPRESOLVE);
+ REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_WHATEVER);
+ REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V4);
+ REGISTER_CURL_CONSTANT(CURL_IPRESOLVE_V6);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
+ REGISTER_CURL_CONSTANT(CURLOPT_DNS_CACHE_TIMEOUT);
+ REGISTER_CURL_CONSTANT(CURLOPT_PORT);
+ REGISTER_CURL_CONSTANT(CURLOPT_FILE);
+ REGISTER_CURL_CONSTANT(CURLOPT_READDATA);
+ REGISTER_CURL_CONSTANT(CURLOPT_INFILE);
+ REGISTER_CURL_CONSTANT(CURLOPT_INFILESIZE);
+ REGISTER_CURL_CONSTANT(CURLOPT_URL);
+ REGISTER_CURL_CONSTANT(CURLOPT_PROXY);
+ REGISTER_CURL_CONSTANT(CURLOPT_VERBOSE);
+ REGISTER_CURL_CONSTANT(CURLOPT_HEADER);
+ REGISTER_CURL_CONSTANT(CURLOPT_HTTPHEADER);
+ REGISTER_CURL_CONSTANT(CURLOPT_NOPROGRESS);
+ REGISTER_CURL_CONSTANT(CURLOPT_PROGRESSFUNCTION);
+ REGISTER_CURL_CONSTANT(CURLOPT_NOBODY);
+ REGISTER_CURL_CONSTANT(CURLOPT_FAILONERROR);
+ REGISTER_CURL_CONSTANT(CURLOPT_UPLOAD);
+ REGISTER_CURL_CONSTANT(CURLOPT_POST);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTPLISTONLY);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTPAPPEND);
+ REGISTER_CURL_CONSTANT(CURLOPT_NETRC);
+ REGISTER_CURL_CONSTANT(CURLOPT_FOLLOWLOCATION);
+#if CURLOPT_FTPASCII != 0
+ REGISTER_CURL_CONSTANT(CURLOPT_FTPASCII);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_PUT);
+#if CURLOPT_MUTE != 0
+ REGISTER_CURL_CONSTANT(CURLOPT_MUTE);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_USERPWD);
+ REGISTER_CURL_CONSTANT(CURLOPT_PROXYUSERPWD);
+ REGISTER_CURL_CONSTANT(CURLOPT_RANGE);
+ REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT);
+#if LIBCURL_VERSION_NUM > 0x071002
+ REGISTER_CURL_CONSTANT(CURLOPT_TIMEOUT_MS);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_POSTFIELDS);
+ REGISTER_CURL_CONSTANT(CURLOPT_REFERER);
+ REGISTER_CURL_CONSTANT(CURLOPT_USERAGENT);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTPPORT);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPSV);
+ REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_LIMIT);
+ REGISTER_CURL_CONSTANT(CURLOPT_LOW_SPEED_TIME);
+ REGISTER_CURL_CONSTANT(CURLOPT_RESUME_FROM);
+ REGISTER_CURL_CONSTANT(CURLOPT_COOKIE);
+ REGISTER_CURL_CONSTANT(CURLOPT_COOKIESESSION);
+ REGISTER_CURL_CONSTANT(CURLOPT_AUTOREFERER);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLCERT);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTPASSWD);
+ REGISTER_CURL_CONSTANT(CURLOPT_WRITEHEADER);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYHOST);
+ REGISTER_CURL_CONSTANT(CURLOPT_COOKIEFILE);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLVERSION);
+ REGISTER_CURL_CONSTANT(CURLOPT_TIMECONDITION);
+ REGISTER_CURL_CONSTANT(CURLOPT_TIMEVALUE);
+ REGISTER_CURL_CONSTANT(CURLOPT_CUSTOMREQUEST);
+ REGISTER_CURL_CONSTANT(CURLOPT_STDERR);
+ REGISTER_CURL_CONSTANT(CURLOPT_TRANSFERTEXT);
+ REGISTER_CURL_CONSTANT(CURLOPT_RETURNTRANSFER);
+ REGISTER_CURL_CONSTANT(CURLOPT_QUOTE);
+ REGISTER_CURL_CONSTANT(CURLOPT_POSTQUOTE);
+ REGISTER_CURL_CONSTANT(CURLOPT_INTERFACE);
+ REGISTER_CURL_CONSTANT(CURLOPT_KRB4LEVEL);
+ REGISTER_CURL_CONSTANT(CURLOPT_HTTPPROXYTUNNEL);
+ REGISTER_CURL_CONSTANT(CURLOPT_FILETIME);
+ REGISTER_CURL_CONSTANT(CURLOPT_WRITEFUNCTION);
+ REGISTER_CURL_CONSTANT(CURLOPT_READFUNCTION);
+#if CURLOPT_PASSWDFUNCTION != 0
+ REGISTER_CURL_CONSTANT(CURLOPT_PASSWDFUNCTION);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_HEADERFUNCTION);
+ REGISTER_CURL_CONSTANT(CURLOPT_MAXREDIRS);
+ REGISTER_CURL_CONSTANT(CURLOPT_MAXCONNECTS);
+ REGISTER_CURL_CONSTANT(CURLOPT_CLOSEPOLICY);
+ REGISTER_CURL_CONSTANT(CURLOPT_FRESH_CONNECT);
+ REGISTER_CURL_CONSTANT(CURLOPT_FORBID_REUSE);
+ REGISTER_CURL_CONSTANT(CURLOPT_RANDOM_FILE);
+ REGISTER_CURL_CONSTANT(CURLOPT_EGDSOCKET);
+ REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT);
+#if LIBCURL_VERSION_NUM > 0x071002
+ REGISTER_CURL_CONSTANT(CURLOPT_CONNECTTIMEOUT_MS);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_SSL_VERIFYPEER);
+ REGISTER_CURL_CONSTANT(CURLOPT_CAINFO);
+ REGISTER_CURL_CONSTANT(CURLOPT_CAPATH);
+ REGISTER_CURL_CONSTANT(CURLOPT_COOKIEJAR);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSL_CIPHER_LIST);
+ REGISTER_CURL_CONSTANT(CURLOPT_BINARYTRANSFER);
+ REGISTER_CURL_CONSTANT(CURLOPT_NOSIGNAL);
+ REGISTER_CURL_CONSTANT(CURLOPT_PROXYTYPE);
+ REGISTER_CURL_CONSTANT(CURLOPT_BUFFERSIZE);
+ REGISTER_CURL_CONSTANT(CURLOPT_HTTPGET);
+ REGISTER_CURL_CONSTANT(CURLOPT_HTTP_VERSION);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLKEY);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYTYPE);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLKEYPASSWD);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLENGINE_DEFAULT);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSLCERTTYPE);
+ REGISTER_CURL_CONSTANT(CURLOPT_CRLF);
+ REGISTER_CURL_CONSTANT(CURLOPT_ENCODING);
+ REGISTER_CURL_CONSTANT(CURLOPT_PROXYPORT);
+ REGISTER_CURL_CONSTANT(CURLOPT_UNRESTRICTED_AUTH);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTP_USE_EPRT);
+#if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
+ REGISTER_CURL_CONSTANT(CURLOPT_TCP_NODELAY);
+#endif
+ REGISTER_CURL_CONSTANT(CURLOPT_HTTP200ALIASES);
+ REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFMODSINCE);
+ REGISTER_CURL_CONSTANT(CURL_TIMECOND_IFUNMODSINCE);
+ REGISTER_CURL_CONSTANT(CURL_TIMECOND_LASTMOD);
+
+#if LIBCURL_VERSION_NUM > 0x070f04 /* CURLOPT_MAX_RECV_SPEED_LARGE & CURLOPT_MAX_SEND_SPEED_LARGE are available since curl 7.15.5 */
+ REGISTER_CURL_CONSTANT(CURLOPT_MAX_RECV_SPEED_LARGE);
+ REGISTER_CURL_CONSTANT(CURLOPT_MAX_SEND_SPEED_LARGE);
+#endif
+
+#if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
+ REGISTER_CURL_CONSTANT(CURLOPT_HTTPAUTH);
+ /* http authentication options */
+ REGISTER_CURL_CONSTANT(CURLAUTH_BASIC);
+ REGISTER_CURL_CONSTANT(CURLAUTH_DIGEST);
+ REGISTER_CURL_CONSTANT(CURLAUTH_GSSNEGOTIATE);
+ REGISTER_CURL_CONSTANT(CURLAUTH_NTLM);
+ REGISTER_CURL_CONSTANT(CURLAUTH_ANY);
+ REGISTER_CURL_CONSTANT(CURLAUTH_ANYSAFE);
+#endif
+
+#if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
+ REGISTER_CURL_CONSTANT(CURLOPT_PROXYAUTH);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTP_CREATE_MISSING_DIRS);
+#endif
+
+ REGISTER_CURL_CONSTANT(CURLOPT_PRIVATE);
+
+ /* Constants effecting the way CURLOPT_CLOSEPOLICY works */
+ REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
+ REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_LEAST_TRAFFIC);
+ REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_SLOWEST);
+ REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_CALLBACK);
+ REGISTER_CURL_CONSTANT(CURLCLOSEPOLICY_OLDEST);
+
+ /* Info constants */
+ REGISTER_CURL_CONSTANT(CURLINFO_EFFECTIVE_URL);
+ REGISTER_CURL_CONSTANT(CURLINFO_HTTP_CODE);
+ REGISTER_CURL_CONSTANT(CURLINFO_HEADER_SIZE);
+ REGISTER_CURL_CONSTANT(CURLINFO_REQUEST_SIZE);
+ REGISTER_CURL_CONSTANT(CURLINFO_TOTAL_TIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_NAMELOOKUP_TIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_CONNECT_TIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_PRETRANSFER_TIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_SIZE_UPLOAD);
+ REGISTER_CURL_CONSTANT(CURLINFO_SIZE_DOWNLOAD);
+ REGISTER_CURL_CONSTANT(CURLINFO_SPEED_DOWNLOAD);
+ REGISTER_CURL_CONSTANT(CURLINFO_SPEED_UPLOAD);
+ REGISTER_CURL_CONSTANT(CURLINFO_FILETIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_SSL_VERIFYRESULT);
+ REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_DOWNLOAD);
+ REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_LENGTH_UPLOAD);
+ REGISTER_CURL_CONSTANT(CURLINFO_STARTTRANSFER_TIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_CONTENT_TYPE);
+ REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_TIME);
+ REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
+ REGISTER_CURL_CONSTANT(CURLINFO_HEADER_OUT);
+ REGISTER_CURL_CONSTANT(CURLINFO_PRIVATE);
+#if LIBCURL_VERSION_NUM > 0x071301
+ REGISTER_CURL_CONSTANT(CURLINFO_CERTINFO);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071202
+ REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_URL);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */
+ REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_IP);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */
+ REGISTER_CURL_CONSTANT(CURLINFO_PRIMARY_PORT);
+ REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_IP);
+ REGISTER_CURL_CONSTANT(CURLINFO_LOCAL_PORT);
+#endif
+
+
+ /* cURL protocol constants (curl_version) */
+ REGISTER_CURL_CONSTANT(CURL_VERSION_IPV6);
+ REGISTER_CURL_CONSTANT(CURL_VERSION_KERBEROS4);
+ REGISTER_CURL_CONSTANT(CURL_VERSION_SSL);
+ REGISTER_CURL_CONSTANT(CURL_VERSION_LIBZ);
+
+ /* version constants */
+ REGISTER_CURL_CONSTANT(CURLVERSION_NOW);
+
+ /* Error Constants */
+ REGISTER_CURL_CONSTANT(CURLE_OK);
+ REGISTER_CURL_CONSTANT(CURLE_UNSUPPORTED_PROTOCOL);
+ REGISTER_CURL_CONSTANT(CURLE_FAILED_INIT);
+ REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT);
+ REGISTER_CURL_CONSTANT(CURLE_URL_MALFORMAT_USER);
+ REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_PROXY);
+ REGISTER_CURL_CONSTANT(CURLE_COULDNT_RESOLVE_HOST);
+ REGISTER_CURL_CONSTANT(CURLE_COULDNT_CONNECT);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_SERVER_REPLY);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_ACCESS_DENIED);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_USER_PASSWORD_INCORRECT);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASS_REPLY);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_USER_REPLY);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_PASV_REPLY);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_WEIRD_227_FORMAT);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_GET_HOST);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_CANT_RECONNECT);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_BINARY);
+ REGISTER_CURL_CONSTANT(CURLE_PARTIAL_FILE);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_RETR_FILE);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_WRITE_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_QUOTE_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_HTTP_NOT_FOUND);
+ REGISTER_CURL_CONSTANT(CURLE_WRITE_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_MALFORMAT_USER);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_STOR_FILE);
+ REGISTER_CURL_CONSTANT(CURLE_READ_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_OUT_OF_MEMORY);
+ REGISTER_CURL_CONSTANT(CURLE_OPERATION_TIMEOUTED);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_SET_ASCII);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_PORT_FAILED);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_USE_REST);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_COULDNT_GET_SIZE);
+ REGISTER_CURL_CONSTANT(CURLE_HTTP_RANGE_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_HTTP_POST_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_CONNECT_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_FTP_BAD_DOWNLOAD_RESUME);
+ REGISTER_CURL_CONSTANT(CURLE_FILE_COULDNT_READ_FILE);
+ REGISTER_CURL_CONSTANT(CURLE_LDAP_CANNOT_BIND);
+ REGISTER_CURL_CONSTANT(CURLE_LDAP_SEARCH_FAILED);
+ REGISTER_CURL_CONSTANT(CURLE_LIBRARY_NOT_FOUND);
+ REGISTER_CURL_CONSTANT(CURLE_FUNCTION_NOT_FOUND);
+ REGISTER_CURL_CONSTANT(CURLE_ABORTED_BY_CALLBACK);
+ REGISTER_CURL_CONSTANT(CURLE_BAD_FUNCTION_ARGUMENT);
+ REGISTER_CURL_CONSTANT(CURLE_BAD_CALLING_ORDER);
+ REGISTER_CURL_CONSTANT(CURLE_HTTP_PORT_FAILED);
+ REGISTER_CURL_CONSTANT(CURLE_BAD_PASSWORD_ENTERED);
+ REGISTER_CURL_CONSTANT(CURLE_TOO_MANY_REDIRECTS);
+ REGISTER_CURL_CONSTANT(CURLE_UNKNOWN_TELNET_OPTION);
+ REGISTER_CURL_CONSTANT(CURLE_TELNET_OPTION_SYNTAX);
+ REGISTER_CURL_CONSTANT(CURLE_OBSOLETE);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
+ REGISTER_CURL_CONSTANT(CURLE_GOT_NOTHING);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_NOTFOUND);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_ENGINE_SETFAILED);
+ REGISTER_CURL_CONSTANT(CURLE_SEND_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_RECV_ERROR);
+ REGISTER_CURL_CONSTANT(CURLE_SHARE_IN_USE);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_CERTPROBLEM);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_CIPHER);
+ REGISTER_CURL_CONSTANT(CURLE_SSL_CACERT);
+ REGISTER_CURL_CONSTANT(CURLE_BAD_CONTENT_ENCODING);
+#if LIBCURL_VERSION_NUM >= 0x070a08
+ REGISTER_CURL_CONSTANT(CURLE_LDAP_INVALID_URL);
+ REGISTER_CURL_CONSTANT(CURLE_FILESIZE_EXCEEDED);
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070b00
+ REGISTER_CURL_CONSTANT(CURLE_FTP_SSL_FAILED);
+#endif
+ REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
+ REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS4);
+ REGISTER_CURL_CONSTANT(CURLPROXY_SOCKS5);
+
+ REGISTER_CURL_CONSTANT(CURL_NETRC_OPTIONAL);
+ REGISTER_CURL_CONSTANT(CURL_NETRC_IGNORED);
+ REGISTER_CURL_CONSTANT(CURL_NETRC_REQUIRED);
+
+ REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_NONE);
+ REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_0);
+ REGISTER_CURL_CONSTANT(CURL_HTTP_VERSION_1_1);
+
+ REGISTER_CURL_CONSTANT(CURLM_CALL_MULTI_PERFORM);
+ REGISTER_CURL_CONSTANT(CURLM_OK);
+ REGISTER_CURL_CONSTANT(CURLM_BAD_HANDLE);
+ REGISTER_CURL_CONSTANT(CURLM_BAD_EASY_HANDLE);
+ REGISTER_CURL_CONSTANT(CURLM_OUT_OF_MEMORY);
+ REGISTER_CURL_CONSTANT(CURLM_INTERNAL_ERROR);
+
+ REGISTER_CURL_CONSTANT(CURLMSG_DONE);
+
+#if LIBCURL_VERSION_NUM >= 0x070c02
+ REGISTER_CURL_CONSTANT(CURLOPT_FTPSSLAUTH);
+ REGISTER_CURL_CONSTANT(CURLFTPAUTH_DEFAULT);
+ REGISTER_CURL_CONSTANT(CURLFTPAUTH_SSL);
+ REGISTER_CURL_CONSTANT(CURLFTPAUTH_TLS);
+#endif
+
+#if LIBCURL_VERSION_NUM > 0x070b00
+ REGISTER_CURL_CONSTANT(CURLOPT_FTP_SSL);
+ REGISTER_CURL_CONSTANT(CURLFTPSSL_NONE);
+ REGISTER_CURL_CONSTANT(CURLFTPSSL_TRY);
+ REGISTER_CURL_CONSTANT(CURLFTPSSL_CONTROL);
+ REGISTER_CURL_CONSTANT(CURLFTPSSL_ALL);
+#endif
+
+#if LIBCURL_VERSION_NUM > 0x071301
+ REGISTER_CURL_CONSTANT(CURLOPT_CERTINFO);
+ REGISTER_CURL_CONSTANT(CURLOPT_POSTREDIR);
+#endif
+
+/* SSH support works in 7.19.0+ using libssh2 */
+#if LIBCURL_VERSION_NUM >= 0x071300
+ REGISTER_CURL_CONSTANT(CURLSSH_AUTH_NONE);
+ REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PUBLICKEY);
+ REGISTER_CURL_CONSTANT(CURLSSH_AUTH_PASSWORD);
+ REGISTER_CURL_CONSTANT(CURLSSH_AUTH_HOST);
+ REGISTER_CURL_CONSTANT(CURLSSH_AUTH_KEYBOARD);
+ REGISTER_CURL_CONSTANT(CURLSSH_AUTH_DEFAULT);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSH_AUTH_TYPES);
+ REGISTER_CURL_CONSTANT(CURLOPT_KEYPASSWD);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSH_PUBLIC_KEYFILE);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSH_PRIVATE_KEYFILE);
+ REGISTER_CURL_CONSTANT(CURLOPT_SSH_HOST_PUBLIC_KEY_MD5);
+ REGISTER_CURL_CONSTANT(CURLE_SSH);
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x071304
+ REGISTER_CURL_CONSTANT(CURLOPT_REDIR_PROTOCOLS);
+ REGISTER_CURL_CONSTANT(CURLOPT_PROTOCOLS);
+ REGISTER_CURL_CONSTANT(CURLPROTO_HTTP);
+ REGISTER_CURL_CONSTANT(CURLPROTO_HTTPS);
+ REGISTER_CURL_CONSTANT(CURLPROTO_FTP);
+ REGISTER_CURL_CONSTANT(CURLPROTO_FTPS);
+ REGISTER_CURL_CONSTANT(CURLPROTO_SCP);
+ REGISTER_CURL_CONSTANT(CURLPROTO_SFTP);
+ REGISTER_CURL_CONSTANT(CURLPROTO_TELNET);
+ REGISTER_CURL_CONSTANT(CURLPROTO_LDAP);
+ REGISTER_CURL_CONSTANT(CURLPROTO_LDAPS);
+ REGISTER_CURL_CONSTANT(CURLPROTO_DICT);
+ REGISTER_CURL_CONSTANT(CURLPROTO_FILE);
+ REGISTER_CURL_CONSTANT(CURLPROTO_TFTP);
+ REGISTER_CURL_CONSTANT(CURLPROTO_ALL);
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x070f01
+ REGISTER_CURL_CONSTANT(CURLOPT_FTP_FILEMETHOD);
+ REGISTER_CURL_CONSTANT(CURLOPT_FTP_SKIP_PASV_IP);
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x071001
+ REGISTER_CURL_CONSTANT(CURLFTPMETHOD_MULTICWD);
+ REGISTER_CURL_CONSTANT(CURLFTPMETHOD_NOCWD);
+ REGISTER_CURL_CONSTANT(CURLFTPMETHOD_SINGLECWD);
+#endif
+
+#ifdef PHP_CURL_NEED_OPENSSL_TSL
+ if (!CRYPTO_get_id_callback()) {
+ int i, c = CRYPTO_num_locks();
+
+ php_curl_openssl_tsl = malloc(c * sizeof(MUTEX_T));
+ if (!php_curl_openssl_tsl) {
+ return FAILURE;
+ }
+
+ for (i = 0; i < c; ++i) {
+ php_curl_openssl_tsl[i] = tsrm_mutex_alloc();
+ }
+
+ CRYPTO_set_id_callback(php_curl_ssl_id);
+ CRYPTO_set_locking_callback(php_curl_ssl_lock);
+ }
+#endif
+#ifdef PHP_CURL_NEED_GNUTLS_TSL
+ gcry_control(GCRYCTL_SET_THREAD_CBS, &php_curl_gnutls_tsl);
+#endif
+
+ if (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) {
+ return FAILURE;
+ }
+
+#ifdef PHP_CURL_URL_WRAPPERS
+# if HAVE_CURL_VERSION_INFO
+ {
+ curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
+ char **p = (char **)info->protocols;
+
+ while (*p != NULL) {
+ /* Do not enable cURL "file" protocol and make sure cURL is always used when --with-curlwrappers is enabled */
+ if (strncasecmp(*p, "file", sizeof("file")-1) != 0) {
+ php_unregister_url_stream_wrapper(*p TSRMLS_CC);
+ php_register_url_stream_wrapper(*p, &php_curl_wrapper TSRMLS_CC);
+ }
+ (void) *p++;
+ }
+ }
+# else
+ php_unregister_url_stream_wrapper("http");
+ php_register_url_stream_wrapper("http", &php_curl_wrapper TSRMLS_CC);
+ php_unregister_url_stream_wrapper("https");
+ php_register_url_stream_wrapper("https", &php_curl_wrapper TSRMLS_CC);
+ php_unregister_url_stream_wrapper("ftp");
+ php_register_url_stream_wrapper("ftp", &php_curl_wrapper TSRMLS_CC);
+ php_unregister_url_stream_wrapper("ftps");
+ php_register_url_stream_wrapper("ftps", &php_curl_wrapper TSRMLS_CC);
+ php_unregister_url_stream_wrapper("ldap");
+ php_register_url_stream_wrapper("ldap", &php_curl_wrapper TSRMLS_CC);
+# endif
+#endif
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MSHUTDOWN_FUNCTION
+ */
+PHP_MSHUTDOWN_FUNCTION(curl)
+{
+#ifdef PHP_CURL_URL_WRAPPERS
+ php_unregister_url_stream_wrapper("http" TSRMLS_CC);
+ php_unregister_url_stream_wrapper("https" TSRMLS_CC);
+ php_unregister_url_stream_wrapper("ftp" TSRMLS_CC);
+ php_unregister_url_stream_wrapper("ldap" TSRMLS_CC);
+#endif
+ curl_global_cleanup();
+#ifdef PHP_CURL_NEED_OPENSSL_TSL
+ if (php_curl_openssl_tsl) {
+ int i, c = CRYPTO_num_locks();
+
+ CRYPTO_set_id_callback(NULL);
+ CRYPTO_set_locking_callback(NULL);
+
+ for (i = 0; i < c; ++i) {
+ tsrm_mutex_free(php_curl_openssl_tsl[i]);
+ }
+
+ free(php_curl_openssl_tsl);
+ php_curl_openssl_tsl = NULL;
+ }
+#endif
+ UNREGISTER_INI_ENTRIES();
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ curl_write_nothing
+ * Used as a work around. See _php_curl_close_ex
+ */
+static size_t curl_write_nothing(char *data, size_t size, size_t nmemb, void *ctx)
+{
+ return size * nmemb;
+}
+/* }}} */
+
+/* {{{ curl_write
+ */
+static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
+{
+ php_curl *ch = (php_curl *) ctx;
+ php_curl_write *t = ch->handlers->write;
+ size_t length = size * nmemb;
+ TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
+
+#if PHP_CURL_DEBUG
+ fprintf(stderr, "curl_write() called\n");
+ fprintf(stderr, "data = %s, size = %d, nmemb = %d, ctx = %x\n", data, size, nmemb, ctx);
+#endif
+
+ switch (t->method) {
+ case PHP_CURL_STDOUT:
+ PHPWRITE(data, length);
+ break;
+ case PHP_CURL_FILE:
+ return fwrite(data, size, nmemb, t->fp);
+ case PHP_CURL_RETURN:
+ if (length > 0) {
+ smart_str_appendl(&t->buf, data, (int) length);
+ }
+ break;
+ case PHP_CURL_USER: {
+ zval **argv[2];
+ zval *retval_ptr = NULL;
+ zval *handle = NULL;
+ zval *zdata = NULL;
+ int error;
+ zend_fcall_info fci;
+
+ MAKE_STD_ZVAL(handle);
+ ZVAL_RESOURCE(handle, ch->id);
+ zend_list_addref(ch->id);
+ argv[0] = &handle;
+
+ MAKE_STD_ZVAL(zdata);
+ ZVAL_STRINGL(zdata, data, length, 1);
+ argv[1] = &zdata;
+
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.object_ptr = NULL;
+ fci.function_name = t->func_name;
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = 2;
+ fci.params = argv;
+ fci.no_separation = 0;
+ fci.symbol_table = NULL;
+
+ ch->in_callback = 1;
+ error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+ ch->in_callback = 0;
+ if (error == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_WRITEFUNCTION");
+ length = -1;
+ } else if (retval_ptr) {
+ if (Z_TYPE_P(retval_ptr) != IS_LONG) {
+ convert_to_long_ex(&retval_ptr);
+ }
+ length = Z_LVAL_P(retval_ptr);
+ zval_ptr_dtor(&retval_ptr);
+ }
+
+ zval_ptr_dtor(argv[0]);
+ zval_ptr_dtor(argv[1]);
+ break;
+ }
+ }
+
+ return length;
+}
+/* }}} */
+
+/* {{{ curl_progress
+ */
+static size_t curl_progress(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+ php_curl *ch = (php_curl *) clientp;
+ php_curl_progress *t = ch->handlers->progress;
+ int length = -1;
+ size_t rval = 0;
+
+#if PHP_CURL_DEBUG
+ fprintf(stderr, "curl_progress() called\n");
+ fprintf(stderr, "clientp = %x, dltotal = %f, dlnow = %f, ultotal = %f, ulnow = %f\n", clientp, dltotal, dlnow, ultotal, ulnow);
+#endif
+
+ switch (t->method) {
+ case PHP_CURL_USER: {
+ zval **argv[4];
+ zval *zdltotal = NULL;
+ zval *zdlnow = NULL;
+ zval *zultotal = NULL;
+ zval *zulnow = NULL;
+ zval *retval_ptr;
+ int error;
+ zend_fcall_info fci;
+ TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
+
+ MAKE_STD_ZVAL(zdltotal);
+ MAKE_STD_ZVAL(zdlnow);
+ MAKE_STD_ZVAL(zultotal);
+ MAKE_STD_ZVAL(zulnow);
+
+ ZVAL_LONG(zdltotal, (long) dltotal);
+ ZVAL_LONG(zdlnow, (long) dlnow);
+ ZVAL_LONG(zultotal, (long) ultotal);
+ ZVAL_LONG(zulnow, (long) ulnow);
+
+ argv[0] = &zdltotal;
+ argv[1] = &zdlnow;
+ argv[2] = &zultotal;
+ argv[3] = &zulnow;
+
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.function_name = t->func_name;
+ fci.object_ptr = NULL;
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = 4;
+ fci.params = argv;
+ fci.no_separation = 0;
+ fci.symbol_table = NULL;
+
+ ch->in_callback = 1;
+ error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+ ch->in_callback = 0;
+ if (error == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_PROGRESSFUNCTION");
+ length = -1;
+ } else if (retval_ptr) {
+ if (Z_TYPE_P(retval_ptr) != IS_LONG) {
+ convert_to_long_ex(&retval_ptr);
+ }
+ if (0 != Z_LVAL_P(retval_ptr)) {
+ rval = 1;
+ }
+ zval_ptr_dtor(&retval_ptr);
+ }
+ zval_ptr_dtor(argv[0]);
+ zval_ptr_dtor(argv[1]);
+ zval_ptr_dtor(argv[2]);
+ zval_ptr_dtor(argv[3]);
+ break;
+ }
+ }
+ return rval;
+}
+/* }}} */
+
+/* {{{ curl_read
+ */
+static size_t curl_read(char *data, size_t size, size_t nmemb, void *ctx)
+{
+ php_curl *ch = (php_curl *) ctx;
+ php_curl_read *t = ch->handlers->read;
+ int length = 0;
+
+ switch (t->method) {
+ case PHP_CURL_DIRECT:
+ if (t->fp) {
+ length = fread(data, size, nmemb, t->fp);
+ }
+ break;
+ case PHP_CURL_USER: {
+ zval **argv[3];
+ zval *handle = NULL;
+ zval *zfd = NULL;
+ zval *zlength = NULL;
+ zval *retval_ptr;
+ int error;
+ zend_fcall_info fci;
+ TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
+
+ MAKE_STD_ZVAL(handle);
+ MAKE_STD_ZVAL(zfd);
+ MAKE_STD_ZVAL(zlength);
+
+ ZVAL_RESOURCE(handle, ch->id);
+ zend_list_addref(ch->id);
+ ZVAL_RESOURCE(zfd, t->fd);
+ zend_list_addref(t->fd);
+ ZVAL_LONG(zlength, (int) size * nmemb);
+
+ argv[0] = &handle;
+ argv[1] = &zfd;
+ argv[2] = &zlength;
+
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.function_name = t->func_name;
+ fci.object_ptr = NULL;
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = 3;
+ fci.params = argv;
+ fci.no_separation = 0;
+ fci.symbol_table = NULL;
+
+ ch->in_callback = 1;
+ error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+ ch->in_callback = 0;
+ if (error == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot call the CURLOPT_READFUNCTION");
+#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
+ length = CURL_READFUNC_ABORT;
+#endif
+ } else if (retval_ptr) {
+ if (Z_TYPE_P(retval_ptr) == IS_STRING) {
+ length = MIN((int) (size * nmemb), Z_STRLEN_P(retval_ptr));
+ memcpy(data, Z_STRVAL_P(retval_ptr), length);
+ }
+ zval_ptr_dtor(&retval_ptr);
+ }
+
+ zval_ptr_dtor(argv[0]);
+ zval_ptr_dtor(argv[1]);
+ zval_ptr_dtor(argv[2]);
+ break;
+ }
+ }
+
+ return length;
+}
+/* }}} */
+
+/* {{{ curl_write_header
+ */
+static size_t curl_write_header(char *data, size_t size, size_t nmemb, void *ctx)
+{
+ php_curl *ch = (php_curl *) ctx;
+ php_curl_write *t = ch->handlers->write_header;
+ size_t length = size * nmemb;
+ TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
+
+ switch (t->method) {
+ case PHP_CURL_STDOUT:
+ /* Handle special case write when we're returning the entire transfer
+ */
+ if (ch->handlers->write->method == PHP_CURL_RETURN && length > 0) {
+ smart_str_appendl(&ch->handlers->write->buf, data, (int) length);
+ } else {
+ PHPWRITE(data, length);
+ }
+ break;
+ case PHP_CURL_FILE:
+ return fwrite(data, size, nmemb, t->fp);
+ case PHP_CURL_USER: {
+ zval **argv[2];
+ zval *handle = NULL;
+ zval *zdata = NULL;
+ zval *retval_ptr;
+ int error;
+ zend_fcall_info fci;
+
+ MAKE_STD_ZVAL(handle);
+ MAKE_STD_ZVAL(zdata);
+
+ ZVAL_RESOURCE(handle, ch->id);
+ zend_list_addref(ch->id);
+ ZVAL_STRINGL(zdata, data, length, 1);
+
+ argv[0] = &handle;
+ argv[1] = &zdata;
+
+ fci.size = sizeof(fci);
+ fci.function_table = EG(function_table);
+ fci.function_name = t->func_name;
+ fci.symbol_table = NULL;
+ fci.object_ptr = NULL;
+ fci.retval_ptr_ptr = &retval_ptr;
+ fci.param_count = 2;
+ fci.params = argv;
+ fci.no_separation = 0;
+
+ ch->in_callback = 1;
+ error = zend_call_function(&fci, &t->fci_cache TSRMLS_CC);
+ ch->in_callback = 0;
+ if (error == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_HEADERFUNCTION");
+ length = -1;
+ } else if (retval_ptr) {
+ if (Z_TYPE_P(retval_ptr) != IS_LONG) {
+ convert_to_long_ex(&retval_ptr);
+ }
+ length = Z_LVAL_P(retval_ptr);
+ zval_ptr_dtor(&retval_ptr);
+ }
+ zval_ptr_dtor(argv[0]);
+ zval_ptr_dtor(argv[1]);
+ break;
+ }
+
+ case PHP_CURL_IGNORE:
+ return length;
+
+ default:
+ return -1;
+ }
+
+ return length;
+}
+/* }}} */
+
+static int curl_debug(CURL *cp, curl_infotype type, char *buf, size_t buf_len, void *ctx) /* {{{ */
+{
+ php_curl *ch = (php_curl *) ctx;
+
+ if (type == CURLINFO_HEADER_OUT) {
+ if (ch->header.str_len) {
+ efree(ch->header.str);
+ }
+ if (buf_len > 0) {
+ ch->header.str = estrndup(buf, buf_len);
+ ch->header.str_len = buf_len;
+ }
+ }
+
+ return 0;
+}
+/* }}} */
+
+#if CURLOPT_PASSWDFUNCTION != 0
+/* {{{ curl_passwd
+ */
+static size_t curl_passwd(void *ctx, char *prompt, char *buf, int buflen)
+{
+ php_curl *ch = (php_curl *) ctx;
+ zval *func = ch->handlers->passwd;
+ zval *argv[3];
+ zval *retval = NULL;
+ int error;
+ int ret = -1;
+ TSRMLS_FETCH_FROM_CTX(ch->thread_ctx);
+
+ MAKE_STD_ZVAL(argv[0]);
+ MAKE_STD_ZVAL(argv[1]);
+ MAKE_STD_ZVAL(argv[2]);
+
+ ZVAL_RESOURCE(argv[0], ch->id);
+ zend_list_addref(ch->id);
+ ZVAL_STRING(argv[1], prompt, 1);
+ ZVAL_LONG(argv[2], buflen);
+
+ error = call_user_function(EG(function_table), NULL, func, retval, 2, argv TSRMLS_CC);
+ if (error == FAILURE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not call the CURLOPT_PASSWDFUNCTION");
+ } else if (Z_TYPE_P(retval) == IS_STRING) {
+ if (Z_STRLEN_P(retval) > buflen) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Returned password is too long for libcurl to handle");
+ } else {
+ strlcpy(buf, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "User handler '%s' did not return a string", Z_STRVAL_P(func));
+ }
+
+ zval_ptr_dtor(&argv[0]);
+ zval_ptr_dtor(&argv[1]);
+ zval_ptr_dtor(&argv[2]);
+ zval_ptr_dtor(&retval);
+
+ return ret;
+}
+/* }}} */
+#endif
+
+/* {{{ curl_free_string
+ */
+static void curl_free_string(void **string)
+{
+ efree(*string);
+}
+/* }}} */
+
+/* {{{ curl_free_post
+ */
+static void curl_free_post(void **post)
+{
+ curl_formfree((struct HttpPost *) *post);
+}
+/* }}} */
+
+/* {{{ curl_free_slist
+ */
+static void curl_free_slist(void **slist)
+{
+ curl_slist_free_all((struct curl_slist *) *slist);
+}
+/* }}} */
+
+/* {{{ proto array curl_version([int version])
+ Return cURL version information. */
+PHP_FUNCTION(curl_version)
+{
+ curl_version_info_data *d;
+ long uversion = CURLVERSION_NOW;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &uversion) == FAILURE) {
+ return;
+ }
+
+ d = curl_version_info(uversion);
+ if (d == NULL) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ CAAL("version_number", d->version_num);
+ CAAL("age", d->age);
+ CAAL("features", d->features);
+ CAAL("ssl_version_number", d->ssl_version_num);
+ CAAS("version", d->version);
+ CAAS("host", d->host);
+ CAAS("ssl_version", d->ssl_version);
+ CAAS("libz_version", d->libz_version);
+ /* Add an array of protocols */
+ {
+ char **p = (char **) d->protocols;
+ zval *protocol_list = NULL;
+
+ MAKE_STD_ZVAL(protocol_list);
+ array_init(protocol_list);
+
+ while (*p != NULL) {
+ add_next_index_string(protocol_list, *p, 1);
+ p++;
+ }
+ CAAZ("protocols", protocol_list);
+ }
+}
+/* }}} */
+
+/* {{{ alloc_curl_handle
+ */
+static void alloc_curl_handle(php_curl **ch)
+{
+ *ch = emalloc(sizeof(php_curl));
+ (*ch)->to_free = ecalloc(1, sizeof(struct _php_curl_free));
+ (*ch)->handlers = ecalloc(1, sizeof(php_curl_handlers));
+ (*ch)->handlers->write = ecalloc(1, sizeof(php_curl_write));
+ (*ch)->handlers->write_header = ecalloc(1, sizeof(php_curl_write));
+ (*ch)->handlers->read = ecalloc(1, sizeof(php_curl_read));
+ (*ch)->handlers->progress = ecalloc(1, sizeof(php_curl_progress));
+
+ (*ch)->in_callback = 0;
+ (*ch)->header.str_len = 0;
+
+ memset(&(*ch)->err, 0, sizeof((*ch)->err));
+ (*ch)->handlers->write->stream = NULL;
+ (*ch)->handlers->write_header->stream = NULL;
+ (*ch)->handlers->read->stream = NULL;
+
+ zend_llist_init(&(*ch)->to_free->str, sizeof(char *), (llist_dtor_func_t) curl_free_string, 0);
+ zend_llist_init(&(*ch)->to_free->slist, sizeof(struct curl_slist), (llist_dtor_func_t) curl_free_slist, 0);
+ zend_llist_init(&(*ch)->to_free->post, sizeof(struct HttpPost), (llist_dtor_func_t) curl_free_post, 0);
+}
+/* }}} */
+
+#if LIBCURL_VERSION_NUM > 0x071301
+/* {{{ split_certinfo
+ */
+static void split_certinfo(char *string, zval *hash)
+{
+ char *org = estrdup(string);
+ char *s = org;
+ char *split;
+
+ if(org) {
+ do {
+ char *key;
+ char *val;
+ char *tmp;
+
+ split = strstr(s, "; ");
+ if(split)
+ *split = '\0';
+
+ key = s;
+ tmp = memchr(key, '=', 64);
+ if(tmp) {
+ *tmp = '\0';
+ val = tmp+1;
+ add_assoc_string(hash, key, val, 1);
+ }
+ s = split+2;
+ } while(split);
+ efree(org);
+ }
+}
+/* }}} */
+
+/* {{{ create_certinfo
+ */
+static void create_certinfo(struct curl_certinfo *ci, zval *listcode TSRMLS_DC)
+{
+ int i;
+
+ if(ci) {
+ zval *certhash = NULL;
+
+ for(i=0; i<ci->num_of_certs; i++) {
+ struct curl_slist *slist;
+
+ MAKE_STD_ZVAL(certhash);
+ array_init(certhash);
+ for(slist = ci->certinfo[i]; slist; slist = slist->next) {
+ int len;
+ char s[64];
+ char *tmp;
+ strncpy(s, slist->data, 64);
+ tmp = memchr(s, ':', 64);
+ if(tmp) {
+ *tmp = '\0';
+ len = strlen(s);
+ if(!strcmp(s, "Subject") || !strcmp(s, "Issuer")) {
+ zval *hash;
+
+ MAKE_STD_ZVAL(hash);
+ array_init(hash);
+
+ split_certinfo(&slist->data[len+1], hash);
+ add_assoc_zval(certhash, s, hash);
+ } else {
+ add_assoc_string(certhash, s, &slist->data[len+1], 1);
+ }
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not extract hash key from certificate info");
+ }
+ }
+ add_next_index_zval(listcode, certhash);
+ }
+ }
+}
+/* }}} */
+#endif
+
+/* {{{ proto resource curl_init([string url])
+ Initialize a cURL session */
+PHP_FUNCTION(curl_init)
+{
+ php_curl *ch;
+ CURL *cp;
+ zval *clone;
+ char *url = NULL;
+ int url_len = 0;
+ char *cainfo;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &url, &url_len) == FAILURE) {
+ return;
+ }
+
+ cp = curl_easy_init();
+ if (!cp) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize a new cURL handle");
+ RETURN_FALSE;
+ }
+
+ alloc_curl_handle(&ch);
+ TSRMLS_SET_CTX(ch->thread_ctx);
+
+ ch->cp = cp;
+
+ ch->handlers->write->method = PHP_CURL_STDOUT;
+ ch->handlers->write->type = PHP_CURL_ASCII;
+ ch->handlers->read->method = PHP_CURL_DIRECT;
+ ch->handlers->write_header->method = PHP_CURL_IGNORE;
+
+ ch->uses = 0;
+
+ MAKE_STD_ZVAL(clone);
+ ch->clone = clone;
+
+ curl_easy_setopt(ch->cp, CURLOPT_NOPROGRESS, 1);
+ curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
+ curl_easy_setopt(ch->cp, CURLOPT_ERRORBUFFER, ch->err.str);
+ curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write);
+ curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
+ curl_easy_setopt(ch->cp, CURLOPT_READFUNCTION, curl_read);
+ curl_easy_setopt(ch->cp, CURLOPT_INFILE, (void *) ch);
+ curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_header);
+ curl_easy_setopt(ch->cp, CURLOPT_WRITEHEADER, (void *) ch);
+ curl_easy_setopt(ch->cp, CURLOPT_DNS_USE_GLOBAL_CACHE, 1);
+ curl_easy_setopt(ch->cp, CURLOPT_DNS_CACHE_TIMEOUT, 120);
+ curl_easy_setopt(ch->cp, CURLOPT_MAXREDIRS, 20); /* prevent infinite redirects */
+
+ cainfo = INI_STR("curl.cainfo");
+ if (cainfo && strlen(cainfo) > 0) {
+ curl_easy_setopt(ch->cp, CURLOPT_CAINFO, cainfo);
+ }
+
+#if defined(ZTS)
+ curl_easy_setopt(ch->cp, CURLOPT_NOSIGNAL, 1);
+#endif
+
+ if (url) {
+ if (!php_curl_option_url(ch, url, url_len TSRMLS_CC)) {
+ _php_curl_close_ex(ch TSRMLS_CC);
+ RETURN_FALSE;
+ }
+ }
+
+ ZEND_REGISTER_RESOURCE(return_value, ch, le_curl);
+ ch->id = Z_LVAL_P(return_value);
+}
+/* }}} */
+
+/* {{{ proto resource curl_copy_handle(resource ch)
+ Copy a cURL handle along with all of it's preferences */
+PHP_FUNCTION(curl_copy_handle)
+{
+ CURL *cp;
+ zval *zid;
+ php_curl *ch, *dupch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ cp = curl_easy_duphandle(ch->cp);
+ if (!cp) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot duplicate cURL handle");
+ RETURN_FALSE;
+ }
+
+ alloc_curl_handle(&dupch);
+ TSRMLS_SET_CTX(dupch->thread_ctx);
+
+ dupch->cp = cp;
+ dupch->uses = 0;
+ ch->uses++;
+ if (ch->handlers->write->stream) {
+ Z_ADDREF_P(ch->handlers->write->stream);
+ }
+ dupch->handlers->write->stream = ch->handlers->write->stream;
+ dupch->handlers->write->method = ch->handlers->write->method;
+ dupch->handlers->write->type = ch->handlers->write->type;
+ if (ch->handlers->read->stream) {
+ Z_ADDREF_P(ch->handlers->read->stream);
+ }
+ dupch->handlers->read->stream = ch->handlers->read->stream;
+ dupch->handlers->read->method = ch->handlers->read->method;
+ dupch->handlers->write_header->method = ch->handlers->write_header->method;
+ if (ch->handlers->write_header->stream) {
+ Z_ADDREF_P(ch->handlers->write_header->stream);
+ }
+ dupch->handlers->write_header->stream = ch->handlers->write_header->stream;
+
+ dupch->handlers->write->fp = ch->handlers->write->fp;
+ dupch->handlers->write_header->fp = ch->handlers->write_header->fp;
+ dupch->handlers->read->fp = ch->handlers->read->fp;
+ dupch->handlers->read->fd = ch->handlers->read->fd;
+#if CURLOPT_PASSWDDATA != 0
+ if (ch->handlers->passwd) {
+ zval_add_ref(&ch->handlers->passwd);
+ dupch->handlers->passwd = ch->handlers->passwd;
+ curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) dupch);
+ }
+#endif
+ if (ch->handlers->write->func_name) {
+ zval_add_ref(&ch->handlers->write->func_name);
+ dupch->handlers->write->func_name = ch->handlers->write->func_name;
+ }
+ if (ch->handlers->read->func_name) {
+ zval_add_ref(&ch->handlers->read->func_name);
+ dupch->handlers->read->func_name = ch->handlers->read->func_name;
+ }
+ if (ch->handlers->write_header->func_name) {
+ zval_add_ref(&ch->handlers->write_header->func_name);
+ dupch->handlers->write_header->func_name = ch->handlers->write_header->func_name;
+ }
+
+ if (ch->handlers->progress->func_name) {
+ zval_add_ref(&ch->handlers->progress->func_name);
+ dupch->handlers->progress->func_name = ch->handlers->progress->func_name;
+ }
+ dupch->handlers->progress->method = ch->handlers->progress->method;
+
+ curl_easy_setopt(dupch->cp, CURLOPT_ERRORBUFFER, dupch->err.str);
+ curl_easy_setopt(dupch->cp, CURLOPT_FILE, (void *) dupch);
+ curl_easy_setopt(dupch->cp, CURLOPT_INFILE, (void *) dupch);
+ curl_easy_setopt(dupch->cp, CURLOPT_WRITEHEADER, (void *) dupch);
+ curl_easy_setopt(dupch->cp, CURLOPT_PROGRESSDATA, (void *) dupch);
+
+ efree(dupch->to_free);
+ dupch->to_free = ch->to_free;
+
+ /* Keep track of cloned copies to avoid invoking curl destructors for every clone */
+ Z_ADDREF_P(ch->clone);
+ dupch->clone = ch->clone;
+
+ ZEND_REGISTER_RESOURCE(return_value, dupch, le_curl);
+ dupch->id = Z_LVAL_P(return_value);
+}
+/* }}} */
+
+static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *return_value TSRMLS_DC) /* {{{ */
+{
+ CURLcode error=CURLE_OK;
+
+ switch (option) {
+ /* Long options */
+ case CURLOPT_SSL_VERIFYHOST:
+ if(Z_BVAL_PP(zvalue) == 1) {
+#if LIBCURL_VERSION_NUM <= 0x071c00 /* 7.28.0 */
+ php_error_docref(NULL TSRMLS_CC, 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");
+#else
+ php_error_docref(NULL TSRMLS_CC, E_NOTICE, "CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead");
+ error = curl_easy_setopt(ch->cp, option, 2);
+ break;
+#endif
+ }
+ case CURLOPT_INFILESIZE:
+ case CURLOPT_VERBOSE:
+ case CURLOPT_HEADER:
+ case CURLOPT_NOPROGRESS:
+ case CURLOPT_NOBODY:
+ case CURLOPT_FAILONERROR:
+ case CURLOPT_UPLOAD:
+ case CURLOPT_POST:
+ case CURLOPT_FTPLISTONLY:
+ case CURLOPT_FTPAPPEND:
+ case CURLOPT_NETRC:
+ case CURLOPT_PUT:
+#if CURLOPT_MUTE != 0
+ case CURLOPT_MUTE:
+#endif
+ case CURLOPT_TIMEOUT:
+#if LIBCURL_VERSION_NUM > 0x071002
+ case CURLOPT_TIMEOUT_MS:
+#endif
+ case CURLOPT_FTP_USE_EPSV:
+ case CURLOPT_LOW_SPEED_LIMIT:
+ case CURLOPT_SSLVERSION:
+ case CURLOPT_LOW_SPEED_TIME:
+ case CURLOPT_RESUME_FROM:
+ case CURLOPT_TIMEVALUE:
+ case CURLOPT_TIMECONDITION:
+ case CURLOPT_TRANSFERTEXT:
+ case CURLOPT_HTTPPROXYTUNNEL:
+ case CURLOPT_FILETIME:
+ case CURLOPT_MAXREDIRS:
+ case CURLOPT_MAXCONNECTS:
+ case CURLOPT_CLOSEPOLICY:
+ case CURLOPT_FRESH_CONNECT:
+ case CURLOPT_FORBID_REUSE:
+ case CURLOPT_CONNECTTIMEOUT:
+#if LIBCURL_VERSION_NUM > 0x071002
+ case CURLOPT_CONNECTTIMEOUT_MS:
+#endif
+ case CURLOPT_SSL_VERIFYPEER:
+ case CURLOPT_DNS_USE_GLOBAL_CACHE:
+ case CURLOPT_NOSIGNAL:
+ case CURLOPT_PROXYTYPE:
+ case CURLOPT_BUFFERSIZE:
+ case CURLOPT_HTTPGET:
+ case CURLOPT_HTTP_VERSION:
+ case CURLOPT_CRLF:
+ case CURLOPT_DNS_CACHE_TIMEOUT:
+ case CURLOPT_PROXYPORT:
+ case CURLOPT_FTP_USE_EPRT:
+#if LIBCURL_VERSION_NUM > 0x070a05 /* CURLOPT_HTTPAUTH is available since curl 7.10.6 */
+ case CURLOPT_HTTPAUTH:
+#endif
+#if LIBCURL_VERSION_NUM > 0x070a06 /* CURLOPT_PROXYAUTH & CURLOPT_FTP_CREATE_MISSING_DIRS are available since curl 7.10.7 */
+ case CURLOPT_PROXYAUTH:
+ case CURLOPT_FTP_CREATE_MISSING_DIRS:
+#endif
+
+#if LIBCURL_VERSION_NUM >= 0x070c02
+ case CURLOPT_FTPSSLAUTH:
+#endif
+#if LIBCURL_VERSION_NUM > 0x070b00
+ case CURLOPT_FTP_SSL:
+#endif
+ case CURLOPT_UNRESTRICTED_AUTH:
+ case CURLOPT_PORT:
+ case CURLOPT_AUTOREFERER:
+ case CURLOPT_COOKIESESSION:
+#if LIBCURL_VERSION_NUM > 0x070b01 /* CURLOPT_TCP_NODELAY is available since curl 7.11.2 */
+ case CURLOPT_TCP_NODELAY:
+#endif
+#if LIBCURL_VERSION_NUM >= 0x71304
+ case CURLOPT_REDIR_PROTOCOLS:
+ case CURLOPT_PROTOCOLS:
+#endif
+#if LIBCURL_VERSION_NUM > 0x070a07 /* CURLOPT_IPRESOLVE is available since curl 7.10.8 */
+ case CURLOPT_IPRESOLVE:
+#endif
+#if LIBCURL_VERSION_NUM >= 0x070f01
+ case CURLOPT_FTP_FILEMETHOD:
+ case CURLOPT_FTP_SKIP_PASV_IP:
+#endif
+#if LIBCURL_VERSION_NUM > 0x071301
+ case CURLOPT_CERTINFO:
+#endif
+ convert_to_long_ex(zvalue);
+#if LIBCURL_VERSION_NUM >= 0x71304
+ if ((option == CURLOPT_PROTOCOLS || option == CURLOPT_REDIR_PROTOCOLS) &&
+ (PG(open_basedir) && *PG(open_basedir)) && (Z_LVAL_PP(zvalue) & CURLPROTO_FILE)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLPROTO_FILE cannot be activated when an open_basedir is set");
+ RETVAL_FALSE;
+ return 1;
+ }
+#endif
+ error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
+ break;
+#if LIBCURL_VERSION_NUM > 0x070f04
+ case CURLOPT_MAX_RECV_SPEED_LARGE:
+ case CURLOPT_MAX_SEND_SPEED_LARGE:
+ convert_to_long_ex(zvalue);
+ error = curl_easy_setopt(ch->cp, option, (curl_off_t)Z_LVAL_PP(zvalue));
+ break;
+#endif
+ case CURLOPT_FOLLOWLOCATION:
+ convert_to_long_ex(zvalue);
+ if (PG(open_basedir) && *PG(open_basedir)) {
+ if (Z_LVAL_PP(zvalue) != 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set");
+ RETVAL_FALSE;
+ return 1;
+ }
+ }
+ error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
+ break;
+#if LIBCURL_VERSION_NUM > 0x071301
+ case CURLOPT_POSTREDIR:
+ convert_to_long_ex(zvalue);
+ error = curl_easy_setopt(ch->cp, CURLOPT_POSTREDIR, Z_LVAL_PP(zvalue) & CURL_REDIR_POST_ALL);
+ break;
+#endif
+ case CURLOPT_PRIVATE:
+ case CURLOPT_URL:
+ case CURLOPT_PROXY:
+ case CURLOPT_USERPWD:
+ case CURLOPT_PROXYUSERPWD:
+ case CURLOPT_RANGE:
+ case CURLOPT_CUSTOMREQUEST:
+ case CURLOPT_USERAGENT:
+ case CURLOPT_FTPPORT:
+ case CURLOPT_COOKIE:
+ case CURLOPT_REFERER:
+ case CURLOPT_INTERFACE:
+ case CURLOPT_KRB4LEVEL:
+ case CURLOPT_EGDSOCKET:
+ case CURLOPT_CAINFO:
+ case CURLOPT_CAPATH:
+ case CURLOPT_SSL_CIPHER_LIST:
+ case CURLOPT_SSLKEY:
+ case CURLOPT_SSLKEYTYPE:
+ case CURLOPT_SSLKEYPASSWD:
+ case CURLOPT_SSLENGINE:
+ case CURLOPT_SSLENGINE_DEFAULT:
+ case CURLOPT_SSLCERTTYPE:
+ case CURLOPT_ENCODING:
+#if LIBCURL_VERSION_NUM >= 0x071300
+ case CURLOPT_SSH_PUBLIC_KEYFILE:
+ case CURLOPT_SSH_PRIVATE_KEYFILE:
+#endif
+ {
+ convert_to_string_ex(zvalue);
+#if LIBCURL_VERSION_NUM >= 0x071300
+ if (
+ option == CURLOPT_SSH_PUBLIC_KEYFILE || option == CURLOPT_SSH_PRIVATE_KEYFILE
+
+ ) {
+ if (php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) {
+ RETVAL_FALSE;
+ return 1;
+ }
+ }
+#endif
+ if (option == CURLOPT_URL) {
+ if (!php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue) TSRMLS_CC)) {
+ RETVAL_FALSE;
+ return 1;
+ }
+ } else {
+ if (option == CURLOPT_PRIVATE) {
+ char *copystr;
+#if LIBCURL_VERSION_NUM < 0x071100
+string_copy:
+#endif
+ copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
+ error = curl_easy_setopt(ch->cp, option, copystr);
+ zend_llist_add_element(&ch->to_free->str, &copystr);
+ } else {
+#if LIBCURL_VERSION_NUM >= 0x071100
+ /* Strings passed to libcurl as ’char *’ arguments, are copied by the library... NOTE: before 7.17.0 strings were not copied. */
+ error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
+#else
+ goto string_copy;
+#endif
+ }
+ }
+ break;
+ }
+ case CURLOPT_FILE:
+ case CURLOPT_INFILE:
+ case CURLOPT_WRITEHEADER:
+ case CURLOPT_STDERR: {
+ FILE *fp = NULL;
+ int type;
+ void * what;
+
+ what = zend_fetch_resource(zvalue TSRMLS_CC, -1, "File-Handle", &type, 1, php_file_le_stream(), php_file_le_pstream());
+ if (!what) {
+ RETVAL_FALSE;
+ return 1;
+ }
+
+ if (FAILURE == php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
+ RETVAL_FALSE;
+ return 1;
+ }
+
+ if (!fp) {
+ RETVAL_FALSE;
+ return 1;
+ }
+
+ error = CURLE_OK;
+ switch (option) {
+ case CURLOPT_FILE:
+ if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
+ if (ch->handlers->write->stream) {
+ Z_DELREF_P(ch->handlers->write->stream);
+ }
+ Z_ADDREF_PP(zvalue);
+ ch->handlers->write->fp = fp;
+ ch->handlers->write->method = PHP_CURL_FILE;
+ ch->handlers->write->stream = *zvalue;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
+ RETVAL_FALSE;
+ return 1;
+ }
+ break;
+ case CURLOPT_WRITEHEADER:
+ if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
+ if (ch->handlers->write_header->stream) {
+ Z_DELREF_P(ch->handlers->write_header->stream);
+ }
+ Z_ADDREF_PP(zvalue);
+ ch->handlers->write_header->fp = fp;
+ ch->handlers->write_header->method = PHP_CURL_FILE;
+ ch->handlers->write_header->stream = *zvalue;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
+ RETVAL_FALSE;
+ return 1;
+ }
+ break;
+ case CURLOPT_INFILE:
+ if (ch->handlers->read->stream) {
+ Z_DELREF_P(ch->handlers->read->stream);
+ }
+ Z_ADDREF_PP(zvalue);
+ ch->handlers->read->fp = fp;
+ ch->handlers->read->fd = Z_LVAL_PP(zvalue);
+ ch->handlers->read->stream = *zvalue;
+ break;
+ case CURLOPT_STDERR:
+ if (((php_stream *) what)->mode[0] != 'r' || ((php_stream *) what)->mode[1] == '+') {
+ if (ch->handlers->std_err) {
+ zval_ptr_dtor(&ch->handlers->std_err);
+ }
+ zval_add_ref(zvalue);
+ ch->handlers->std_err = *zvalue;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "the provided file handle is not writable");
+ RETVAL_FALSE;
+ return 1;
+ }
+ /* break omitted intentionally */
+ default:
+ error = curl_easy_setopt(ch->cp, option, fp);
+ break;
+ }
+
+ break;
+ }
+ case CURLOPT_RETURNTRANSFER:
+ convert_to_long_ex(zvalue);
+
+ if (Z_LVAL_PP(zvalue)) {
+ ch->handlers->write->method = PHP_CURL_RETURN;
+ } else {
+ ch->handlers->write->method = PHP_CURL_STDOUT;
+ }
+ break;
+ case CURLOPT_BINARYTRANSFER:
+ convert_to_long_ex(zvalue);
+
+ if (Z_LVAL_PP(zvalue)) {
+ ch->handlers->write->type = PHP_CURL_BINARY;
+ } else {
+ ch->handlers->write->type = PHP_CURL_ASCII;
+ }
+ break;
+ case CURLOPT_WRITEFUNCTION:
+ if (ch->handlers->write->func_name) {
+ zval_ptr_dtor(&ch->handlers->write->func_name);
+ ch->handlers->write->fci_cache = empty_fcall_info_cache;
+ }
+ zval_add_ref(zvalue);
+ ch->handlers->write->func_name = *zvalue;
+ ch->handlers->write->method = PHP_CURL_USER;
+ break;
+ case CURLOPT_READFUNCTION:
+ if (ch->handlers->read->func_name) {
+ zval_ptr_dtor(&ch->handlers->read->func_name);
+ ch->handlers->read->fci_cache = empty_fcall_info_cache;
+ }
+ zval_add_ref(zvalue);
+ ch->handlers->read->func_name = *zvalue;
+ ch->handlers->read->method = PHP_CURL_USER;
+ break;
+ case CURLOPT_PROGRESSFUNCTION:
+ curl_easy_setopt(ch->cp, CURLOPT_PROGRESSFUNCTION, curl_progress);
+ curl_easy_setopt(ch->cp, CURLOPT_PROGRESSDATA, ch);
+ if (ch->handlers->progress->func_name) {
+ zval_ptr_dtor(&ch->handlers->progress->func_name);
+ ch->handlers->progress->fci_cache = empty_fcall_info_cache;
+ }
+ zval_add_ref(zvalue);
+ ch->handlers->progress->func_name = *zvalue;
+ ch->handlers->progress->method = PHP_CURL_USER;
+ break;
+ case CURLOPT_HEADERFUNCTION:
+ if (ch->handlers->write_header->func_name) {
+ zval_ptr_dtor(&ch->handlers->write_header->func_name);
+ ch->handlers->write_header->fci_cache = empty_fcall_info_cache;
+ }
+ zval_add_ref(zvalue);
+ ch->handlers->write_header->func_name = *zvalue;
+ ch->handlers->write_header->method = PHP_CURL_USER;
+ break;
+#if CURLOPT_PASSWDFUNCTION != 0
+ case CURLOPT_PASSWDFUNCTION:
+ if (ch->handlers->passwd) {
+ zval_ptr_dtor(&ch->handlers->passwd);
+ }
+ zval_add_ref(zvalue);
+ ch->handlers->passwd = *zvalue;
+ error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDFUNCTION, curl_passwd);
+ error = curl_easy_setopt(ch->cp, CURLOPT_PASSWDDATA, (void *) ch);
+ break;
+#endif
+ case CURLOPT_POSTFIELDS:
+ if (Z_TYPE_PP(zvalue) == IS_ARRAY || Z_TYPE_PP(zvalue) == IS_OBJECT) {
+ zval **current;
+ HashTable *postfields;
+ struct HttpPost *first = NULL;
+ struct HttpPost *last = NULL;
+
+ postfields = HASH_OF(*zvalue);
+ if (!postfields) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't get HashTable in CURLOPT_POSTFIELDS");
+ RETVAL_FALSE;
+ return 1;
+ }
+
+ for (zend_hash_internal_pointer_reset(postfields);
+ zend_hash_get_current_data(postfields, (void **) &current) == SUCCESS;
+ zend_hash_move_forward(postfields)
+ ) {
+ char *postval;
+ char *string_key = NULL;
+ uint string_key_len;
+ ulong num_key;
+ int numeric_key;
+
+ SEPARATE_ZVAL(current);
+ convert_to_string_ex(current);
+
+ zend_hash_get_current_key_ex(postfields, &string_key, &string_key_len, &num_key, 0, NULL);
+
+ /* Pretend we have a string_key here */
+ if(!string_key) {
+ spprintf(&string_key, 0, "%ld", num_key);
+ string_key_len = strlen(string_key)+1;
+ numeric_key = 1;
+ } else {
+ numeric_key = 0;
+ }
+
+ postval = Z_STRVAL_PP(current);
+
+ /* The arguments after _NAMELENGTH and _CONTENTSLENGTH
+ * must be explicitly cast to long in curl_formadd
+ * use since curl needs a long not an int. */
+ if (*postval == '@') {
+ char *type, *filename;
+ ++postval;
+
+ if ((type = php_memnstr(postval, ";type=", sizeof(";type=") - 1, postval + Z_STRLEN_PP(current)))) {
+ *type = '\0';
+ }
+ if ((filename = php_memnstr(postval, ";filename=", sizeof(";filename=") - 1, postval + Z_STRLEN_PP(current)))) {
+ *filename = '\0';
+ }
+ /* open_basedir check */
+ if (php_check_open_basedir(postval TSRMLS_CC)) {
+ RETVAL_FALSE;
+ return 1;
+ }
+ error = curl_formadd(&first, &last,
+ CURLFORM_COPYNAME, string_key,
+ CURLFORM_NAMELENGTH, (long)string_key_len - 1,
+ CURLFORM_FILENAME, filename ? filename + sizeof(";filename=") - 1 : postval,
+ CURLFORM_CONTENTTYPE, type ? type + sizeof(";type=") - 1 : "application/octet-stream",
+ CURLFORM_FILE, postval,
+ CURLFORM_END);
+ if (type) {
+ *type = ';';
+ }
+ if (filename) {
+ *filename = ';';
+ }
+ } else {
+ error = curl_formadd(&first, &last,
+ CURLFORM_COPYNAME, string_key,
+ CURLFORM_NAMELENGTH, (long)string_key_len - 1,
+ CURLFORM_COPYCONTENTS, postval,
+ CURLFORM_CONTENTSLENGTH, (long)Z_STRLEN_PP(current),
+ CURLFORM_END);
+ }
+
+ if (numeric_key) {
+ efree(string_key);
+ }
+ }
+
+ SAVE_CURL_ERROR(ch, error);
+ if (error != CURLE_OK) {
+ RETVAL_FALSE;
+ return 1;
+ }
+
+ if (Z_REFCOUNT_P(ch->clone) <= 1) {
+ zend_llist_clean(&ch->to_free->post);
+ }
+ zend_llist_add_element(&ch->to_free->post, &first);
+ error = curl_easy_setopt(ch->cp, CURLOPT_HTTPPOST, first);
+
+ } else {
+#if LIBCURL_VERSION_NUM >= 0x071101
+ convert_to_string_ex(zvalue);
+ /* with curl 7.17.0 and later, we can use COPYPOSTFIELDS, but we have to provide size before */
+ error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
+ error = curl_easy_setopt(ch->cp, CURLOPT_COPYPOSTFIELDS, Z_STRVAL_PP(zvalue));
+#else
+ char *post = NULL;
+
+ convert_to_string_ex(zvalue);
+ post = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
+ zend_llist_add_element(&ch->to_free->str, &post);
+
+ error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
+ error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
+#endif
+ }
+ break;
+ case CURLOPT_HTTPHEADER:
+ case CURLOPT_QUOTE:
+ case CURLOPT_HTTP200ALIASES:
+ case CURLOPT_POSTQUOTE: {
+ zval **current;
+ HashTable *ph;
+ struct curl_slist *slist = NULL;
+
+ ph = HASH_OF(*zvalue);
+ if (!ph) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must pass either an object or an array with the CURLOPT_HTTPHEADER, CURLOPT_QUOTE, CURLOPT_HTTP200ALIASES and CURLOPT_POSTQUOTE arguments");
+ RETVAL_FALSE;
+ return 1;
+ }
+
+ for (zend_hash_internal_pointer_reset(ph);
+ zend_hash_get_current_data(ph, (void **) &current) == SUCCESS;
+ zend_hash_move_forward(ph)
+ ) {
+ SEPARATE_ZVAL(current);
+ convert_to_string_ex(current);
+
+ slist = curl_slist_append(slist, Z_STRVAL_PP(current));
+ if (!slist) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not build curl_slist");
+ RETVAL_FALSE;
+ return 1;
+ }
+ }
+ zend_llist_add_element(&ch->to_free->slist, &slist);
+
+ error = curl_easy_setopt(ch->cp, option, slist);
+
+ break;
+ }
+ /* the following options deal with files, therefore the open_basedir check
+ * is required.
+ */
+ case CURLOPT_COOKIEJAR:
+ case CURLOPT_SSLCERT:
+ case CURLOPT_RANDOM_FILE:
+ case CURLOPT_COOKIEFILE: {
+#if LIBCURL_VERSION_NUM < 0x071100
+ char *copystr = NULL;
+#endif
+
+ convert_to_string_ex(zvalue);
+
+ if (Z_STRLEN_PP(zvalue) && php_check_open_basedir(Z_STRVAL_PP(zvalue) TSRMLS_CC)) {
+ RETVAL_FALSE;
+ return 1;
+ }
+
+#if LIBCURL_VERSION_NUM >= 0x071100
+ error = curl_easy_setopt(ch->cp, option, Z_STRVAL_PP(zvalue));
+#else
+ copystr = estrndup(Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue));
+
+ error = curl_easy_setopt(ch->cp, option, copystr);
+ zend_llist_add_element(&ch->to_free->str, &copystr);
+#endif
+ break;
+ }
+ case CURLINFO_HEADER_OUT:
+ convert_to_long_ex(zvalue);
+ if (Z_LVAL_PP(zvalue) == 1) {
+ curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, curl_debug);
+ curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, (void *)ch);
+ curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 1);
+ } else {
+ curl_easy_setopt(ch->cp, CURLOPT_DEBUGFUNCTION, NULL);
+ curl_easy_setopt(ch->cp, CURLOPT_DEBUGDATA, NULL);
+ curl_easy_setopt(ch->cp, CURLOPT_VERBOSE, 0);
+ }
+ break;
+ }
+
+ SAVE_CURL_ERROR(ch, error);
+ if (error != CURLE_OK) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool curl_setopt(resource ch, int option, mixed value)
+ Set an option for a cURL transfer */
+PHP_FUNCTION(curl_setopt)
+{
+ zval *zid, **zvalue;
+ long options;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rlZ", &zid, &options, &zvalue) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ if (options <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid curl configuration option");
+ RETURN_FALSE;
+ }
+
+ if (!_php_curl_setopt(ch, options, zvalue, return_value TSRMLS_CC)) {
+ RETURN_TRUE;
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto bool curl_setopt_array(resource ch, array options)
+ Set an array of option for a cURL transfer */
+PHP_FUNCTION(curl_setopt_array)
+{
+ zval *zid, *arr, **entry;
+ php_curl *ch;
+ ulong option;
+ HashPosition pos;
+ char *string_key;
+ uint str_key_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za", &zid, &arr) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(arr), &pos);
+ while (zend_hash_get_current_data_ex(Z_ARRVAL_P(arr), (void **)&entry, &pos) == SUCCESS) {
+ if (zend_hash_get_current_key_ex(Z_ARRVAL_P(arr), &string_key, &str_key_len, &option, 0, &pos) != HASH_KEY_IS_LONG) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Array keys must be CURLOPT constants or equivalent integer values");
+ RETURN_FALSE;
+ }
+ if (_php_curl_setopt(ch, (long) option, entry, return_value TSRMLS_CC)) {
+ RETURN_FALSE;
+ }
+ zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ _php_curl_cleanup_handle(ch)
+ Cleanup an execution phase */
+void _php_curl_cleanup_handle(php_curl *ch)
+{
+ if (ch->handlers->write->buf.len > 0) {
+ smart_str_free(&ch->handlers->write->buf);
+ }
+ if (ch->header.str_len) {
+ efree(ch->header.str);
+ ch->header.str_len = 0;
+ }
+
+ memset(ch->err.str, 0, CURL_ERROR_SIZE + 1);
+ ch->err.no = 0;
+}
+/* }}} */
+
+/* {{{ proto bool curl_exec(resource ch)
+ Perform a cURL session */
+PHP_FUNCTION(curl_exec)
+{
+ CURLcode error;
+ zval *zid;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
+
+ _php_curl_cleanup_handle(ch);
+
+ error = curl_easy_perform(ch->cp);
+ SAVE_CURL_ERROR(ch, error);
+ /* CURLE_PARTIAL_FILE is returned by HEAD requests */
+ if (error != CURLE_OK && error != CURLE_PARTIAL_FILE) {
+ if (ch->handlers->write->buf.len > 0) {
+ smart_str_free(&ch->handlers->write->buf);
+ }
+ RETURN_FALSE;
+ }
+
+ if (ch->handlers->std_err) {
+ php_stream *stream;
+ stream = (php_stream*)zend_fetch_resource(&ch->handlers->std_err TSRMLS_CC, -1, NULL, NULL, 2, php_file_le_stream(), php_file_le_pstream());
+ if (stream) {
+ php_stream_flush(stream);
+ }
+ }
+
+ if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
+ smart_str_0(&ch->handlers->write->buf);
+ RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
+ }
+
+ /* flush the file handle, so any remaining data is synched to disk */
+ if (ch->handlers->write->method == PHP_CURL_FILE && ch->handlers->write->fp) {
+ fflush(ch->handlers->write->fp);
+ }
+ if (ch->handlers->write_header->method == PHP_CURL_FILE && ch->handlers->write_header->fp) {
+ fflush(ch->handlers->write_header->fp);
+ }
+
+ if (ch->handlers->write->method == PHP_CURL_RETURN) {
+ RETURN_EMPTY_STRING();
+ } else {
+ RETURN_TRUE;
+ }
+}
+/* }}} */
+
+/* {{{ proto mixed curl_getinfo(resource ch [, int option])
+ Get information regarding a specific transfer */
+PHP_FUNCTION(curl_getinfo)
+{
+ zval *zid;
+ php_curl *ch;
+ long option = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zid, &option) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ if (ZEND_NUM_ARGS() < 2) {
+ char *s_code;
+ long l_code;
+ double d_code;
+#if LIBCURL_VERSION_NUM > 0x071301
+ struct curl_certinfo *ci = NULL;
+ zval *listcode;
+#endif
+
+ array_init(return_value);
+
+ if (curl_easy_getinfo(ch->cp, CURLINFO_EFFECTIVE_URL, &s_code) == CURLE_OK) {
+ CAAS("url", s_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_TYPE, &s_code) == CURLE_OK) {
+ if (s_code != NULL) {
+ CAAS("content_type", s_code);
+ } else {
+ zval *retnull;
+ MAKE_STD_ZVAL(retnull);
+ ZVAL_NULL(retnull);
+ CAAZ("content_type", retnull);
+ }
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_HTTP_CODE, &l_code) == CURLE_OK) {
+ CAAL("http_code", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_HEADER_SIZE, &l_code) == CURLE_OK) {
+ CAAL("header_size", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_REQUEST_SIZE, &l_code) == CURLE_OK) {
+ CAAL("request_size", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_FILETIME, &l_code) == CURLE_OK) {
+ CAAL("filetime", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_SSL_VERIFYRESULT, &l_code) == CURLE_OK) {
+ CAAL("ssl_verify_result", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_COUNT, &l_code) == CURLE_OK) {
+ CAAL("redirect_count", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_TOTAL_TIME, &d_code) == CURLE_OK) {
+ CAAD("total_time", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_NAMELOOKUP_TIME, &d_code) == CURLE_OK) {
+ CAAD("namelookup_time", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_CONNECT_TIME, &d_code) == CURLE_OK) {
+ CAAD("connect_time", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_PRETRANSFER_TIME, &d_code) == CURLE_OK) {
+ CAAD("pretransfer_time", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_UPLOAD, &d_code) == CURLE_OK) {
+ CAAD("size_upload", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_SIZE_DOWNLOAD, &d_code) == CURLE_OK) {
+ CAAD("size_download", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_DOWNLOAD, &d_code) == CURLE_OK) {
+ CAAD("speed_download", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_SPEED_UPLOAD, &d_code) == CURLE_OK) {
+ CAAD("speed_upload", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d_code) == CURLE_OK) {
+ CAAD("download_content_length", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_CONTENT_LENGTH_UPLOAD, &d_code) == CURLE_OK) {
+ CAAD("upload_content_length", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_STARTTRANSFER_TIME, &d_code) == CURLE_OK) {
+ CAAD("starttransfer_time", d_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_TIME, &d_code) == CURLE_OK) {
+ CAAD("redirect_time", d_code);
+ }
+#if LIBCURL_VERSION_NUM > 0x071301
+ if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
+ MAKE_STD_ZVAL(listcode);
+ array_init(listcode);
+ create_certinfo(ci, listcode TSRMLS_CC);
+ CAAZ("certinfo", listcode);
+ }
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */
+ if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_IP, &s_code) == CURLE_OK) {
+ CAAS("primary_ip", s_code);
+ }
+#endif
+#if LIBCURL_VERSION_NUM > 0x071500
+ if (curl_easy_getinfo(ch->cp, CURLINFO_PRIMARY_PORT, &l_code) == CURLE_OK) {
+ CAAL("primary_port", l_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_IP, &s_code) == CURLE_OK) {
+ CAAS("local_ip", s_code);
+ }
+ if (curl_easy_getinfo(ch->cp, CURLINFO_LOCAL_PORT, &l_code) == CURLE_OK) {
+ CAAL("local_port", l_code);
+ }
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071202
+ if (curl_easy_getinfo(ch->cp, CURLINFO_REDIRECT_URL, &s_code) == CURLE_OK) {
+ CAAS("redirect_url", s_code);
+ }
+#endif
+ if (ch->header.str_len > 0) {
+ CAAS("request_header", ch->header.str);
+ }
+ } else {
+ switch (option) {
+ /* string variable types */
+#if LIBCURL_VERSION_NUM >= 0x071300 /* 7.19.0 */
+ case CURLINFO_PRIMARY_IP:
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */
+ case CURLINFO_LOCAL_IP:
+#endif
+ case CURLINFO_PRIVATE:
+ case CURLINFO_EFFECTIVE_URL:
+ case CURLINFO_CONTENT_TYPE:
+#if LIBCURL_VERSION_NUM >= 0x071202
+ case CURLINFO_REDIRECT_URL:
+#endif
+ {
+ char *s_code = NULL;
+
+ if (curl_easy_getinfo(ch->cp, option, &s_code) == CURLE_OK && s_code) {
+ RETURN_STRING(s_code, 1);
+ } else {
+ RETURN_FALSE;
+ }
+ break;
+ }
+ /* Long variable types */
+#if LIBCURL_VERSION_NUM >= 0x071500 /* 7.21.0 */
+ case CURLINFO_PRIMARY_PORT:
+ case CURLINFO_LOCAL_PORT:
+#endif
+ case CURLINFO_HTTP_CODE:
+ case CURLINFO_HEADER_SIZE:
+ case CURLINFO_REQUEST_SIZE:
+ case CURLINFO_FILETIME:
+ case CURLINFO_SSL_VERIFYRESULT:
+ case CURLINFO_REDIRECT_COUNT: {
+ long code = 0;
+
+ if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
+ RETURN_LONG(code);
+ } else {
+ RETURN_FALSE;
+ }
+ break;
+ }
+ /* Double variable types */
+ case CURLINFO_TOTAL_TIME:
+ case CURLINFO_NAMELOOKUP_TIME:
+ case CURLINFO_CONNECT_TIME:
+ case CURLINFO_PRETRANSFER_TIME:
+ case CURLINFO_SIZE_UPLOAD:
+ case CURLINFO_SIZE_DOWNLOAD:
+ case CURLINFO_SPEED_DOWNLOAD:
+ case CURLINFO_SPEED_UPLOAD:
+ case CURLINFO_CONTENT_LENGTH_DOWNLOAD:
+ case CURLINFO_CONTENT_LENGTH_UPLOAD:
+ case CURLINFO_STARTTRANSFER_TIME:
+ case CURLINFO_REDIRECT_TIME: {
+ double code = 0.0;
+
+ if (curl_easy_getinfo(ch->cp, option, &code) == CURLE_OK) {
+ RETURN_DOUBLE(code);
+ } else {
+ RETURN_FALSE;
+ }
+ break;
+ }
+ case CURLINFO_HEADER_OUT:
+ if (ch->header.str_len > 0) {
+ RETURN_STRINGL(ch->header.str, ch->header.str_len, 1);
+ } else {
+ RETURN_FALSE;
+ }
+#if LIBCURL_VERSION_NUM > 0x071301
+ case CURLINFO_CERTINFO: {
+ struct curl_certinfo *ci = NULL;
+
+ array_init(return_value);
+
+ if (curl_easy_getinfo(ch->cp, CURLINFO_CERTINFO, &ci) == CURLE_OK) {
+ create_certinfo(ci, return_value TSRMLS_CC);
+ } else {
+ RETURN_FALSE;
+ }
+ break;
+ }
+#endif
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto string curl_error(resource ch)
+ Return a string contain the last error for the current session */
+PHP_FUNCTION(curl_error)
+{
+ zval *zid;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ ch->err.str[CURL_ERROR_SIZE] = 0;
+ RETURN_STRING(ch->err.str, 1);
+}
+/* }}} */
+
+/* {{{ proto int curl_errno(resource ch)
+ Return an integer containing the last error number */
+PHP_FUNCTION(curl_errno)
+{
+ zval *zid;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ RETURN_LONG(ch->err.no);
+}
+/* }}} */
+
+/* {{{ proto void curl_close(resource ch)
+ Close a cURL session */
+PHP_FUNCTION(curl_close)
+{
+ zval *zid;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zid) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &zid, -1, le_curl_name, le_curl);
+
+ if (ch->in_callback) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Attempt to close cURL handle from a callback");
+ return;
+ }
+
+ if (ch->uses) {
+ ch->uses--;
+ } else {
+ zend_list_delete(Z_LVAL_P(zid));
+ }
+}
+/* }}} */
+
+/* {{{ _php_curl_close()
+ List destructor for curl handles */
+static void _php_curl_close_ex(php_curl *ch TSRMLS_DC)
+{
+#if PHP_CURL_DEBUG
+ fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
+#endif
+
+ _php_curl_verify_handlers(ch, 0 TSRMLS_CC);
+
+ /*
+ * Libcurl is doing connection caching. When easy handle is cleaned up,
+ * if the handle was previously used by the curl_multi_api, the connection
+ * remains open un the curl multi handle is cleaned up. Some protocols are
+ * sending content like the FTP one, and libcurl try to use the
+ * WRITEFUNCTION or the HEADERFUNCTION. Since structures used in those
+ * callback are freed, we need to use an other callback to which avoid
+ * segfaults.
+ *
+ * Libcurl commit d021f2e8a00 fix this issue and should be part of 7.28.2
+ */
+ curl_easy_setopt(ch->cp, CURLOPT_HEADERFUNCTION, curl_write_nothing);
+ curl_easy_setopt(ch->cp, CURLOPT_WRITEFUNCTION, curl_write_nothing);
+
+ curl_easy_cleanup(ch->cp);
+
+ /* cURL destructors should be invoked only by last curl handle */
+ if (Z_REFCOUNT_P(ch->clone) <= 1) {
+ zend_llist_clean(&ch->to_free->str);
+ zend_llist_clean(&ch->to_free->slist);
+ zend_llist_clean(&ch->to_free->post);
+ efree(ch->to_free);
+ FREE_ZVAL(ch->clone);
+ } else {
+ Z_DELREF_P(ch->clone);
+ }
+
+ if (ch->handlers->write->buf.len > 0) {
+ smart_str_free(&ch->handlers->write->buf);
+ }
+ if (ch->handlers->write->func_name) {
+ zval_ptr_dtor(&ch->handlers->write->func_name);
+ }
+ if (ch->handlers->read->func_name) {
+ zval_ptr_dtor(&ch->handlers->read->func_name);
+ }
+ if (ch->handlers->write_header->func_name) {
+ zval_ptr_dtor(&ch->handlers->write_header->func_name);
+ }
+ if (ch->handlers->progress->func_name) {
+ zval_ptr_dtor(&ch->handlers->progress->func_name);
+ }
+ if (ch->handlers->passwd) {
+ zval_ptr_dtor(&ch->handlers->passwd);
+ }
+ if (ch->handlers->std_err) {
+ zval_ptr_dtor(&ch->handlers->std_err);
+ }
+ if (ch->header.str_len > 0) {
+ efree(ch->header.str);
+ }
+
+ if (ch->handlers->write_header->stream) {
+ zval_ptr_dtor(&ch->handlers->write_header->stream);
+ }
+ if (ch->handlers->write->stream) {
+ zval_ptr_dtor(&ch->handlers->write->stream);
+ }
+ if (ch->handlers->read->stream) {
+ zval_ptr_dtor(&ch->handlers->read->stream);
+ }
+
+ efree(ch->handlers->write);
+ efree(ch->handlers->write_header);
+ efree(ch->handlers->read);
+ efree(ch->handlers->progress);
+ efree(ch->handlers);
+ efree(ch);
+}
+/* }}} */
+
+/* {{{ _php_curl_close()
+ List destructor for curl handles */
+static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+{
+ php_curl *ch = (php_curl *) rsrc->ptr;
+ _php_curl_close_ex(ch TSRMLS_CC);
+}
+/* }}} */
+
+#endif /* HAVE_CURL */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: fdm=marker
+ * vim: noet sw=4 ts=4
+ */
diff --git a/ext/curl/multi.c b/ext/curl/multi.c
new file mode 100644
index 0000000..38c1f1a
--- /dev/null
+++ b/ext/curl/multi.c
@@ -0,0 +1,371 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sterling Hughes <sterling@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+
+#if HAVE_CURL
+
+#include "php_curl.h"
+
+#include <curl/curl.h>
+#include <curl/multi.h>
+
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#endif
+
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* {{{ proto resource curl_multi_init(void)
+ Returns a new cURL multi handle */
+PHP_FUNCTION(curl_multi_init)
+{
+ php_curlm *mh;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ mh = ecalloc(1, sizeof(php_curlm));
+ mh->multi = curl_multi_init();
+
+ zend_llist_init(&mh->easyh, sizeof(zval), _php_curl_multi_cleanup_list, 0);
+
+ ZEND_REGISTER_RESOURCE(return_value, mh, le_curl_multi_handle);
+}
+/* }}} */
+
+/* {{{ proto int curl_multi_add_handle(resource mh, resource ch)
+ Add a normal cURL handle to a cURL multi handle */
+PHP_FUNCTION(curl_multi_add_handle)
+{
+ zval *z_mh;
+ zval *z_ch;
+ php_curlm *mh;
+ php_curl *ch;
+ zval tmp_val;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &z_mh, &z_ch) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
+
+ _php_curl_cleanup_handle(ch);
+ ch->uses++;
+
+ /* we want to create a copy of this zval that we store in the multihandle structure element "easyh" */
+ tmp_val = *z_ch;
+ zval_copy_ctor(&tmp_val);
+
+ zend_llist_add_element(&mh->easyh, &tmp_val);
+
+ RETURN_LONG((long) curl_multi_add_handle(mh->multi, ch->cp));
+}
+/* }}} */
+
+void _php_curl_multi_cleanup_list(void *data) /* {{{ */
+{
+ zval *z_ch = (zval *)data;
+ php_curl *ch;
+ TSRMLS_FETCH();
+
+ if (!z_ch) {
+ return;
+ }
+
+ ch = (php_curl *) zend_fetch_resource(&z_ch TSRMLS_CC, -1, le_curl_name, NULL, 1, le_curl);
+ if (!ch) {
+ return;
+ }
+
+ if (ch->uses) {
+ ch->uses--;
+ } else {
+ zend_list_delete(Z_LVAL_P(z_ch));
+ }
+}
+/* }}} */
+
+/* Used internally as comparison routine passed to zend_list_del_element */
+static int curl_compare_resources( zval *z1, zval **z2 ) /* {{{ */
+{
+ return (Z_TYPE_P( z1 ) == Z_TYPE_PP( z2 ) &&
+ Z_TYPE_P( z1 ) == IS_RESOURCE &&
+ Z_LVAL_P( z1 ) == Z_LVAL_PP( z2 ) );
+}
+/* }}} */
+
+/* {{{ proto int curl_multi_remove_handle(resource mh, resource ch)
+ Remove a multi handle from a set of cURL handles */
+PHP_FUNCTION(curl_multi_remove_handle)
+{
+ zval *z_mh;
+ zval *z_ch;
+ php_curlm *mh;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr", &z_mh, &z_ch) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
+
+ --ch->uses;
+
+ zend_llist_del_element( &mh->easyh, &z_ch,
+ (int (*)(void *, void *)) curl_compare_resources );
+
+ RETURN_LONG((long) curl_multi_remove_handle(mh->multi, ch->cp));
+}
+/* }}} */
+
+static void _make_timeval_struct(struct timeval *to, double timeout) /* {{{ */
+{
+ unsigned long conv;
+
+ conv = (unsigned long) (timeout * 1000000.0);
+ to->tv_sec = conv / 1000000;
+ to->tv_usec = conv % 1000000;
+}
+/* }}} */
+
+/* {{{ proto int curl_multi_select(resource mh[, double timeout])
+ Get all the sockets associated with the cURL extension, which can then be "selected" */
+PHP_FUNCTION(curl_multi_select)
+{
+ zval *z_mh;
+ php_curlm *mh;
+ fd_set readfds;
+ fd_set writefds;
+ fd_set exceptfds;
+ int maxfd;
+ double timeout = 1.0;
+ struct timeval to;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|d", &z_mh, &timeout) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+
+ _make_timeval_struct(&to, timeout);
+
+ FD_ZERO(&readfds);
+ FD_ZERO(&writefds);
+ FD_ZERO(&exceptfds);
+
+ curl_multi_fdset(mh->multi, &readfds, &writefds, &exceptfds, &maxfd);
+ if (maxfd == -1) {
+ RETURN_LONG(-1);
+ }
+ RETURN_LONG(select(maxfd + 1, &readfds, &writefds, &exceptfds, &to));
+}
+/* }}} */
+
+/* {{{ proto int curl_multi_exec(resource mh, int &still_running)
+ Run the sub-connections of the current cURL handle */
+PHP_FUNCTION(curl_multi_exec)
+{
+ zval *z_mh;
+ zval *z_still_running;
+ php_curlm *mh;
+ int still_running;
+ int result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz", &z_mh, &z_still_running) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+
+ {
+ zend_llist_position pos;
+ php_curl *ch;
+ zval *pz_ch;
+
+ for(pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
+ pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &pz_ch, -1, le_curl_name, le_curl);
+ _php_curl_verify_handlers(ch, 1 TSRMLS_CC);
+ }
+ }
+
+ convert_to_long_ex(&z_still_running);
+ still_running = Z_LVAL_P(z_still_running);
+ result = curl_multi_perform(mh->multi, &still_running);
+ ZVAL_LONG(z_still_running, still_running);
+
+ RETURN_LONG(result);
+}
+/* }}} */
+
+/* {{{ proto string curl_multi_getcontent(resource ch)
+ Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set */
+PHP_FUNCTION(curl_multi_getcontent)
+{
+ zval *z_ch;
+ php_curl *ch;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_ch) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &z_ch, -1, le_curl_name, le_curl);
+
+ if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
+ smart_str_0(&ch->handlers->write->buf);
+ RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
+ }
+}
+/* }}} */
+
+/* {{{ proto array curl_multi_info_read(resource mh [, long msgs_in_queue])
+ Get information about the current transfers */
+PHP_FUNCTION(curl_multi_info_read)
+{
+ zval *z_mh;
+ php_curlm *mh;
+ CURLMsg *tmp_msg;
+ int queued_msgs;
+ zval *zmsgs_in_queue = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|z", &z_mh, &zmsgs_in_queue) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+
+ tmp_msg = curl_multi_info_read(mh->multi, &queued_msgs);
+ if (tmp_msg == NULL) {
+ RETURN_FALSE;
+ }
+ if (zmsgs_in_queue) {
+ zval_dtor(zmsgs_in_queue);
+ ZVAL_LONG(zmsgs_in_queue, queued_msgs);
+ }
+
+ array_init(return_value);
+ add_assoc_long(return_value, "msg", tmp_msg->msg);
+ add_assoc_long(return_value, "result", tmp_msg->data.result);
+
+ /* find the original easy curl handle */
+ {
+ zend_llist_position pos;
+ php_curl *ch;
+ zval *pz_ch;
+
+ /* search the list of easy handles hanging off the multi-handle */
+ for(pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
+ pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
+ ZEND_FETCH_RESOURCE(ch, php_curl *, &pz_ch, -1, le_curl_name, le_curl);
+ if (ch->cp == tmp_msg->easy_handle) {
+
+ /* we are adding a reference to the underlying php_curl
+ resource, so we need to add one to the resource's refcount
+ in order to ensure it doesn't get destroyed when the
+ underlying curl easy handle goes out of scope.
+ Normally you would call zval_copy_ctor( pz_ch ), or
+ SEPARATE_ZVAL, but those create new zvals, which is already
+ being done in add_assoc_resource */
+
+ zend_list_addref( Z_RESVAL_P( pz_ch ) );
+
+ /* add_assoc_resource automatically creates a new zval to
+ wrap the "resource" represented by the current pz_ch */
+
+ add_assoc_resource(return_value, "handle", Z_RESVAL_P(pz_ch));
+
+ break;
+ }
+ }
+ }
+}
+/* }}} */
+
+/* {{{ proto void curl_multi_close(resource mh)
+ Close a set of cURL handles */
+PHP_FUNCTION(curl_multi_close)
+{
+ zval *z_mh;
+ php_curlm *mh;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &z_mh) == FAILURE) {
+ return;
+ }
+
+ ZEND_FETCH_RESOURCE(mh, php_curlm *, &z_mh, -1, le_curl_multi_handle_name, le_curl_multi_handle);
+
+ zend_list_delete(Z_LVAL_P(z_mh));
+}
+/* }}} */
+
+void _php_curl_multi_close(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
+{
+ php_curlm *mh = (php_curlm *) rsrc->ptr;
+ if (mh) {
+ zend_llist_position pos;
+ php_curl *ch;
+ zval *pz_ch;
+
+ for(pz_ch = (zval *)zend_llist_get_first_ex(&mh->easyh, &pos); pz_ch;
+ pz_ch = (zval *)zend_llist_get_next_ex(&mh->easyh, &pos)) {
+
+ ch = (php_curl *) zend_fetch_resource(&pz_ch TSRMLS_CC, -1, le_curl_name, NULL, 1, le_curl);
+ _php_curl_verify_handlers(ch, 0 TSRMLS_CC);
+ }
+
+ curl_multi_cleanup(mh->multi);
+ zend_llist_clean(&mh->easyh);
+ efree(mh);
+ rsrc->ptr = NULL;
+ }
+}
+/* }}} */
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/curl/package.xml b/ext/curl/package.xml
new file mode 100644
index 0000000..85cb634
--- /dev/null
+++ b/ext/curl/package.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="ISO-8859-1" ?>
+<!DOCTYPE package SYSTEM "../pear/package.dtd">
+<package>
+ <name>curl</name>
+ <summary>Clib PDF functions</summary>
+ <maintainers>
+ <maintainer>
+ <user>sterling</user>
+ <name>Sterling Hughes</name>
+ <email>sterling@php.net</email>
+ <role>lead</role>
+ </maintainer>
+ </maintainers>
+ <description>
+PHP supports libcurl, a library created by Daniel Stenberg,
+that allows you to connect and communicate to many different
+types of servers with many different types of protocols.
+libcurl currently supports the http, https, ftp, gopher,
+telnet, dict, file, and ldap protocols. libcurl also supports
+HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading (this
+can also be done with PHP's ftp extension), HTTP form based
+upload, proxies, cookies, and user+password authentication.
+ </description>
+ <license>PHP</license>
+ <release>
+ <state>beta</state>
+ <version>5.0rc1</version>
+ <date>2004-03-19</date>
+ <notes>
+package.xml added to support installation using pear installer
+ </notes>
+ <configureoptions>
+ <configureoption name="with-curl" default="autodetect" prompt="path to curl installation?"/>
+ </configureoptions>
+ <filelist>
+ <file role="doc" name="CREDITS"/>
+ <file role="src" name="config.m4"/>
+ <file role="src" name="config.mw32"/>
+ <file role="src" name="curl.dsp"/>
+ <file role="src" name="interface.c"/>
+ <file role="src" name="multi.c"/>
+ <file role="src" name="streams.c"/>
+ <file role="src" name="php_curl.h"/>
+ </filelist>
+ <deps>
+ <dep type="php" rel="ge" version="5" />
+ </deps>
+ </release>
+</package>
+<!--
+vim:et:ts=1:sw=1
+-->
diff --git a/ext/curl/php_curl.h b/ext/curl/php_curl.h
new file mode 100644
index 0000000..945f0a4
--- /dev/null
+++ b/ext/curl/php_curl.h
@@ -0,0 +1,192 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sterling Hughes <sterling@php.net> |
+ | Wez Furlong <wez@thebrainroom.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef _PHP_CURL_H
+#define _PHP_CURL_H
+
+#include "php.h"
+#include "ext/standard/php_smart_str.h"
+
+#ifdef COMPILE_DL_CURL
+#undef HAVE_CURL
+#define HAVE_CURL 1
+#endif
+
+#if HAVE_CURL
+
+#define PHP_CURL_DEBUG 0
+
+#include <curl/curl.h>
+#include <curl/multi.h>
+
+extern zend_module_entry curl_module_entry;
+#define curl_module_ptr &curl_module_entry
+
+#define CURLOPT_RETURNTRANSFER 19913
+#define CURLOPT_BINARYTRANSFER 19914
+#define PHP_CURL_STDOUT 0
+#define PHP_CURL_FILE 1
+#define PHP_CURL_USER 2
+#define PHP_CURL_DIRECT 3
+#define PHP_CURL_RETURN 4
+#define PHP_CURL_ASCII 5
+#define PHP_CURL_BINARY 6
+#define PHP_CURL_IGNORE 7
+
+extern int le_curl;
+#define le_curl_name "cURL handle"
+extern int le_curl_multi_handle;
+#define le_curl_multi_handle_name "cURL Multi Handle"
+
+PHP_MINIT_FUNCTION(curl);
+PHP_MSHUTDOWN_FUNCTION(curl);
+PHP_MINFO_FUNCTION(curl);
+PHP_FUNCTION(curl_version);
+PHP_FUNCTION(curl_init);
+PHP_FUNCTION(curl_copy_handle);
+PHP_FUNCTION(curl_setopt);
+PHP_FUNCTION(curl_setopt_array);
+PHP_FUNCTION(curl_exec);
+PHP_FUNCTION(curl_getinfo);
+PHP_FUNCTION(curl_error);
+PHP_FUNCTION(curl_errno);
+PHP_FUNCTION(curl_close);
+PHP_FUNCTION(curl_multi_init);
+PHP_FUNCTION(curl_multi_add_handle);
+PHP_FUNCTION(curl_multi_remove_handle);
+PHP_FUNCTION(curl_multi_select);
+PHP_FUNCTION(curl_multi_exec);
+PHP_FUNCTION(curl_multi_getcontent);
+PHP_FUNCTION(curl_multi_info_read);
+PHP_FUNCTION(curl_multi_close);
+void _php_curl_multi_close(zend_rsrc_list_entry * TSRMLS_DC);
+
+typedef struct {
+ zval *func_name;
+ zend_fcall_info_cache fci_cache;
+ FILE *fp;
+ smart_str buf;
+ int method;
+ int type;
+ zval *stream;
+} php_curl_write;
+
+typedef struct {
+ zval *func_name;
+ zend_fcall_info_cache fci_cache;
+ FILE *fp;
+ long fd;
+ int method;
+ zval *stream;
+} php_curl_read;
+
+typedef struct {
+ zval *func_name;
+ zend_fcall_info_cache fci_cache;
+ int method;
+} php_curl_progress;
+
+typedef struct {
+ php_curl_write *write;
+ php_curl_write *write_header;
+ php_curl_read *read;
+ zval *passwd;
+ zval *std_err;
+ php_curl_progress *progress;
+} php_curl_handlers;
+
+struct _php_curl_error {
+ char str[CURL_ERROR_SIZE + 1];
+ int no;
+};
+
+struct _php_curl_send_headers {
+ char *str;
+ size_t str_len;
+};
+
+struct _php_curl_free {
+ zend_llist str;
+ zend_llist post;
+ zend_llist slist;
+};
+
+typedef struct {
+ struct _php_curl_error err;
+ struct _php_curl_free *to_free;
+ struct _php_curl_send_headers header;
+ void ***thread_ctx;
+ CURL *cp;
+ php_curl_handlers *handlers;
+ long id;
+ unsigned int uses;
+ zend_bool in_callback;
+ zval *clone;
+} php_curl;
+
+typedef struct {
+ int still_running;
+ CURLM *multi;
+ zend_llist easyh;
+} php_curlm;
+
+void _php_curl_cleanup_handle(php_curl *);
+void _php_curl_multi_cleanup_list(void *data);
+int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC);
+
+/* streams support */
+
+extern php_stream_ops php_curl_stream_ops;
+#define PHP_STREAM_IS_CURL &php_curl_stream_ops
+
+php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename, char *mode,
+ int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC);
+
+extern php_stream_wrapper php_curl_wrapper;
+
+struct php_curl_buffer {
+ off_t readpos, writepos;
+ php_stream *buf;
+};
+
+typedef struct {
+ CURL *curl;
+ CURLM *multi;
+ char *url;
+ struct php_curl_buffer readbuffer; /* holds downloaded data */
+ struct php_curl_buffer writebuffer; /* holds data to upload */
+
+ fd_set readfds, writefds, excfds;
+ int maxfd;
+
+ char errstr[CURL_ERROR_SIZE + 1];
+ CURLMcode mcode;
+ int pending;
+ zval *headers;
+ struct curl_slist *headers_slist; /* holds custom headers sent out in the request */
+} php_curl_stream;
+
+
+#else
+#define curl_module_ptr NULL
+#endif /* HAVE_CURL */
+#define phpext_curl_ptr curl_module_ptr
+#endif /* _PHP_CURL_H */
diff --git a/ext/curl/streams.c b/ext/curl/streams.c
new file mode 100644
index 0000000..2683ae0
--- /dev/null
+++ b/ext/curl/streams.c
@@ -0,0 +1,542 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2013 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Wez Furlong <wez@thebrainroom.com> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+/* This file implements cURL based wrappers.
+ * NOTE: If you are implementing your own streams that are intended to
+ * work independently of wrappers, this is not a good example to follow!
+ **/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_memory_streams.h"
+
+#if HAVE_CURL
+
+#include <stdio.h>
+#include <string.h>
+
+#ifdef PHP_WIN32
+#include <winsock2.h>
+#include <sys/types.h>
+#endif
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+#define SMART_STR_PREALLOC 4096
+
+#include "ext/standard/php_smart_str.h"
+#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "ext/standard/php_string.h"
+#include "php_curl.h"
+
+static size_t on_data_available(char *data, size_t size, size_t nmemb, void *ctx)
+{
+ php_stream *stream = (php_stream *) ctx;
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+ size_t wrote;
+ TSRMLS_FETCH();
+
+ /* TODO: I'd like to deprecate this.
+ * This code is here because until we start getting real data, we don't know
+ * if we have had all of the headers
+ * */
+ if (curlstream->readbuffer.writepos == 0) {
+ zval *sym;
+
+ if (!EG(active_symbol_table)) {
+ zend_rebuild_symbol_table(TSRMLS_C);
+ }
+ MAKE_STD_ZVAL(sym);
+ *sym = *curlstream->headers;
+ zval_copy_ctor(sym);
+ ZEND_SET_SYMBOL(EG(active_symbol_table), "http_response_header", sym);
+ }
+
+ php_stream_seek(curlstream->readbuffer.buf, curlstream->readbuffer.writepos, SEEK_SET);
+ wrote = php_stream_write(curlstream->readbuffer.buf, data, size * nmemb);
+ curlstream->readbuffer.writepos = php_stream_tell(curlstream->readbuffer.buf);
+
+ return wrote;
+}
+
+/* cURL guarantees that headers are written as complete lines, with this function
+ * called once for each header */
+static size_t on_header_available(char *data, size_t size, size_t nmemb, void *ctx)
+{
+ size_t length = size * nmemb;
+ zval *header;
+ php_stream *stream = (php_stream *) ctx;
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+ TSRMLS_FETCH();
+
+ if (length < 2) {
+ /* invalid header ? */
+ return length;
+ }
+
+ if (!(length == 2 && data[0] == '\r' && data[1] == '\n')) {
+ MAKE_STD_ZVAL(header);
+ Z_STRLEN_P(header) = length;
+ Z_STRVAL_P(header) = estrndup(data, length);
+ if (Z_STRVAL_P(header)[length-1] == '\n') {
+ Z_STRVAL_P(header)[length-1] = '\0';
+ Z_STRLEN_P(header)--;
+
+ if (Z_STRVAL_P(header)[length-2] == '\r') {
+ Z_STRVAL_P(header)[length-2] = '\0';
+ Z_STRLEN_P(header)--;
+ }
+ }
+ Z_TYPE_P(header) = IS_STRING;
+ zend_hash_next_index_insert(Z_ARRVAL_P(curlstream->headers), &header, sizeof(zval *), NULL);
+
+ /* based on the header, we might need to trigger a notification */
+ if (!strncasecmp(data, "Location: ", 10)) {
+ php_stream_notify_info(stream->context, PHP_STREAM_NOTIFY_REDIRECTED, data + 10, 0);
+ } else if (!strncasecmp(data, "Content-Type: ", 14)) {
+ php_stream_notify_info(stream->context, PHP_STREAM_NOTIFY_MIME_TYPE_IS, data + 14, 0);
+ } else if (!strncasecmp(data, "Context-Length: ", 16)) {
+ php_stream_notify_file_size(stream->context, atoi(data + 16), data, 0);
+ php_stream_notify_progress_init(stream->context, 0, 0);
+ }
+ }
+ return length;
+
+}
+
+static int on_progress_avail(php_stream *stream, double dltotal, double dlnow, double ultotal, double ulnow)
+{
+ TSRMLS_FETCH();
+
+ /* our notification system only works in a single direction; we should detect which
+ * direction is important and use the correct values in this call */
+ php_stream_notify_progress(stream->context, (size_t) dlnow, (size_t) dltotal);
+ return 0;
+}
+
+static size_t php_curl_stream_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
+{
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+
+ if (curlstream->writebuffer.buf) {
+ return php_stream_write(curlstream->writebuffer.buf, buf, count);
+ }
+
+ return 0;
+}
+
+static size_t php_curl_stream_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
+{
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+ size_t didread = 0;
+
+ if (curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending) {
+ /* we need to read some more data */
+ struct timeval tv;
+
+ /* fire up the connection */
+ if (curlstream->readbuffer.writepos == 0) {
+ while (CURLM_CALL_MULTI_PERFORM == curl_multi_perform(curlstream->multi, &curlstream->pending));
+ }
+
+ do {
+ FD_ZERO(&curlstream->readfds);
+ FD_ZERO(&curlstream->writefds);
+ FD_ZERO(&curlstream->excfds);
+
+ /* get the descriptors from curl */
+ curl_multi_fdset(curlstream->multi, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &curlstream->maxfd);
+
+ /* if we are in blocking mode, set a timeout */
+ tv.tv_usec = 0;
+ tv.tv_sec = 15; /* TODO: allow this to be configured from the script */
+
+ /* wait for data */
+ switch ((curlstream->maxfd < 0) ? 1 :
+ select(curlstream->maxfd + 1, &curlstream->readfds, &curlstream->writefds, &curlstream->excfds, &tv)) {
+ case -1:
+ /* error */
+ return 0;
+ case 0:
+ /* no data yet: timed-out */
+ return 0;
+ default:
+ /* fetch the data */
+ do {
+ curlstream->mcode = curl_multi_perform(curlstream->multi, &curlstream->pending);
+ } while (curlstream->mcode == CURLM_CALL_MULTI_PERFORM);
+ }
+ } while (curlstream->maxfd >= 0 &&
+ curlstream->readbuffer.readpos >= curlstream->readbuffer.writepos && curlstream->pending > 0);
+
+ }
+
+ /* if there is data in the buffer, try and read it */
+ if (curlstream->readbuffer.writepos > 0 && curlstream->readbuffer.readpos < curlstream->readbuffer.writepos) {
+ php_stream_seek(curlstream->readbuffer.buf, curlstream->readbuffer.readpos, SEEK_SET);
+ didread = php_stream_read(curlstream->readbuffer.buf, buf, count);
+ curlstream->readbuffer.readpos = php_stream_tell(curlstream->readbuffer.buf);
+ }
+
+ if (didread == 0) {
+ stream->eof = 1;
+ }
+
+ return didread;
+}
+
+static int php_curl_stream_close(php_stream *stream, int close_handle TSRMLS_DC)
+{
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+
+ /* TODO: respect the close_handle flag here, so that casting to a FILE* on
+ * systems without fopencookie will work properly */
+
+ curl_multi_remove_handle(curlstream->multi, curlstream->curl);
+ curl_easy_cleanup(curlstream->curl);
+ curl_multi_cleanup(curlstream->multi);
+
+ if (curlstream->headers_slist) {
+ curl_slist_free_all(curlstream->headers_slist);
+ }
+
+ /* we are not closing curlstream->readbuf here, because we export
+ * it as a zval with the wrapperdata - the engine will garbage collect it */
+
+ efree(curlstream->url);
+ efree(curlstream);
+
+ return 0;
+}
+
+static int php_curl_stream_flush(php_stream *stream TSRMLS_DC)
+{
+#ifdef ilia_0
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+#endif
+ return 0;
+}
+
+static int php_curl_stream_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC)
+{
+ /* TODO: fill in details based on Data: and Content-Length: headers, and/or data
+ * from curl_easy_getinfo().
+ * For now, return -1 to indicate that it doesn't make sense to stat this stream */
+ return -1;
+}
+
+static int php_curl_stream_cast(php_stream *stream, int castas, void **ret TSRMLS_DC)
+{
+ php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
+ /* delegate to the readbuffer stream */
+ return php_stream_cast(curlstream->readbuffer.buf, castas, ret, 0);
+}
+
+php_stream_ops php_curl_stream_ops = {
+ php_curl_stream_write,
+ php_curl_stream_read,
+ php_curl_stream_close,
+ php_curl_stream_flush,
+ "cURL",
+ NULL, /* seek */
+ php_curl_stream_cast, /* cast */
+ php_curl_stream_stat /* stat */
+};
+
+
+php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename, char *mode,
+ int options, char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
+{
+ php_stream *stream;
+ php_curl_stream *curlstream;
+ zval *tmp, **ctx_opt = NULL;
+
+ curlstream = emalloc(sizeof(php_curl_stream));
+ memset(curlstream, 0, sizeof(php_curl_stream));
+
+ stream = php_stream_alloc(&php_curl_stream_ops, curlstream, 0, mode);
+ php_stream_context_set(stream, context);
+
+ curlstream->curl = curl_easy_init();
+ curlstream->multi = curl_multi_init();
+ curlstream->pending = 1;
+ curlstream->headers_slist = NULL;
+
+ /* if opening for an include statement, ensure that the local storage will
+ * have a FILE* associated with it.
+ * Otherwise, use the "smart" memory stream that will turn itself into a file
+ * when it gets large */
+#ifndef HAVE_FOPENCOOKIE
+ if (options & STREAM_WILL_CAST) {
+ curlstream->readbuffer.buf = php_stream_fopen_tmpfile();
+ } else
+#endif
+ {
+ curlstream->readbuffer.buf = php_stream_temp_new();
+ }
+
+ /* curl requires the URL to be valid throughout it's operation, so dup it */
+ curlstream->url = estrdup(filename);
+ curl_easy_setopt(curlstream->curl, CURLOPT_URL, curlstream->url);
+
+ /* feed curl data into our read buffer */
+ curl_easy_setopt(curlstream->curl, CURLOPT_WRITEFUNCTION, on_data_available);
+ curl_easy_setopt(curlstream->curl, CURLOPT_FILE, stream);
+
+ /* feed headers */
+ curl_easy_setopt(curlstream->curl, CURLOPT_HEADERFUNCTION, on_header_available);
+ curl_easy_setopt(curlstream->curl, CURLOPT_WRITEHEADER, stream);
+
+ curl_easy_setopt(curlstream->curl, CURLOPT_ERRORBUFFER, curlstream->errstr);
+ curl_easy_setopt(curlstream->curl, CURLOPT_VERBOSE, 0);
+
+ /* enable progress notification */
+ curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSFUNCTION, on_progress_avail);
+ curl_easy_setopt(curlstream->curl, CURLOPT_PROGRESSDATA, stream);
+ curl_easy_setopt(curlstream->curl, CURLOPT_NOPROGRESS, 0);
+
+ curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, FG(user_agent) ? FG(user_agent) : "PHP/" PHP_VERSION);
+
+ /* TODO: read cookies and options from context */
+ if (context && !strncasecmp(filename, "http", sizeof("http")-1)) {
+ /* Protocol version */
+ if (SUCCESS == php_stream_context_get_option(context, "http", "protocol_version", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_DOUBLE) {
+ if (Z_DVAL_PP(ctx_opt) == 1.1) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ }
+ }
+
+ if (SUCCESS == php_stream_context_get_option(context, "http", "curl_verify_ssl_host", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 2);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "http", "curl_verify_ssl_peer", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+
+ /* HTTP(S) */
+ if (SUCCESS == php_stream_context_get_option(context, "http", "user_agent", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_USERAGENT, Z_STRVAL_PP(ctx_opt));
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "http", "header", &ctx_opt)) {
+ if (Z_TYPE_PP(ctx_opt) == IS_ARRAY) {
+ HashPosition pos;
+ zval **header = NULL;
+
+ for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(ctx_opt), &pos);
+ SUCCESS == zend_hash_get_current_data_ex(Z_ARRVAL_PP(ctx_opt), (void *)&header, &pos);
+ zend_hash_move_forward_ex(Z_ARRVAL_PP(ctx_opt), &pos)
+ ) {
+ if (Z_TYPE_PP(header) == IS_STRING) {
+ curlstream->headers_slist = curl_slist_append(curlstream->headers_slist, Z_STRVAL_PP(header));
+ }
+ }
+ } else if (Z_TYPE_PP(ctx_opt) == IS_STRING && Z_STRLEN_PP(ctx_opt)) {
+ char *p, *token, *trimmed, *copy_ctx_opt;
+
+ copy_ctx_opt = php_trim(Z_STRVAL_PP(ctx_opt), Z_STRLEN_PP(ctx_opt), NULL, 0, NULL, 3 TSRMLS_CC);
+ p = php_strtok_r(copy_ctx_opt, "\r\n", &token);
+ while (p) {
+ trimmed = php_trim(p, strlen(p), NULL, 0, NULL, 3 TSRMLS_CC);
+ curlstream->headers_slist = curl_slist_append(curlstream->headers_slist, trimmed);
+ efree(trimmed);
+ p = php_strtok_r(NULL, "\r\n", &token);
+ }
+ efree(copy_ctx_opt);
+ }
+ if (curlstream->headers_slist) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_HTTPHEADER, curlstream->headers_slist);
+ }
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "http", "method", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
+ if (strcasecmp(Z_STRVAL_PP(ctx_opt), "get")) {
+ if (!strcasecmp(Z_STRVAL_PP(ctx_opt), "head")) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_NOBODY, 1);
+ } else {
+ if (!strcasecmp(Z_STRVAL_PP(ctx_opt), "post")) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_POST, 1);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_CUSTOMREQUEST, Z_STRVAL_PP(ctx_opt));
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "http", "content", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_POSTFIELDS, Z_STRVAL_PP(ctx_opt));
+ curl_easy_setopt(curlstream->curl, CURLOPT_POSTFIELDSIZE, (long)Z_STRLEN_PP(ctx_opt));
+ }
+ }
+ }
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "http", "proxy", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_STRING) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_PROXY, Z_STRVAL_PP(ctx_opt));
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "http", "max_redirects", &ctx_opt)) {
+ long mr = 20;
+ if (Z_TYPE_PP(ctx_opt) != IS_STRING || !is_numeric_string(Z_STRVAL_PP(ctx_opt), Z_STRLEN_PP(ctx_opt), &mr, NULL, 1)) {
+ if (Z_TYPE_PP(ctx_opt) == IS_LONG) {
+ mr = Z_LVAL_PP(ctx_opt);
+ }
+ }
+ if (mr > 1) {
+ if (PG(open_basedir) && *PG(open_basedir)) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
+ }
+ curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, mr);
+ }
+ } else {
+ if (PG(open_basedir) && *PG(open_basedir)) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
+ }
+ curl_easy_setopt(curlstream->curl, CURLOPT_MAXREDIRS, 20L);
+ }
+ } else if (context && !strncasecmp(filename, "ftps", sizeof("ftps")-1)) {
+ if (SUCCESS == php_stream_context_get_option(context, "ftp", "curl_verify_ssl_host", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 2);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYHOST, 0);
+ }
+ if (SUCCESS == php_stream_context_get_option(context, "ftp", "curl_verify_ssl_peer", &ctx_opt) && Z_TYPE_PP(ctx_opt) == IS_BOOL && Z_LVAL_PP(ctx_opt) == 1) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 1);
+ } else {
+ curl_easy_setopt(curlstream->curl, CURLOPT_SSL_VERIFYPEER, 0);
+ }
+ }
+
+ /* prepare for "pull" mode */
+ curl_multi_add_handle(curlstream->multi, curlstream->curl);
+
+ /* Prepare stuff for file_get_wrapper_data: the data is an array:
+ *
+ * data = array(
+ * "headers" => array("Content-Type: text/html", "Xxx: Yyy"),
+ * "readbuf" => resource (equivalent to curlstream->readbuffer)
+ * );
+ * */
+ MAKE_STD_ZVAL(stream->wrapperdata);
+ array_init(stream->wrapperdata);
+
+ MAKE_STD_ZVAL(curlstream->headers);
+ array_init(curlstream->headers);
+
+ add_assoc_zval(stream->wrapperdata, "headers", curlstream->headers);
+
+ MAKE_STD_ZVAL(tmp);
+ php_stream_to_zval(curlstream->readbuffer.buf, tmp);
+ add_assoc_zval(stream->wrapperdata, "readbuf", tmp);
+
+#ifndef HAVE_FOPENCOOKIE
+ if (options & STREAM_WILL_CAST) {
+ /* we will need to download the whole resource now,
+ * since we cannot get the actual FD for the download,
+ * so we won't be able to drive curl via stdio. */
+
+/* TODO: this needs finishing */
+
+ curl_easy_perform(curlstream->curl);
+ }
+ else
+#endif
+ {
+ /* fire up the connection; we need to detect a connection error here,
+ * otherwise the curlstream we return ends up doing nothing useful. */
+ CURLMcode m;
+ CURLMsg *msg;
+ int msgs_left, msg_found = 0;
+
+ while (CURLM_CALL_MULTI_PERFORM == (m = curl_multi_perform(curlstream->multi, &curlstream->pending))) {
+ ; /* spin */
+ }
+
+ if (m != CURLM_OK) {
+#if HAVE_CURL_MULTI_STRERROR
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_multi_strerror(m));
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "There was an error mcode=%d", m);
+#endif
+ goto exit_fail;
+ }
+
+ /* we have only one curl handle here, even though we use multi syntax,
+ * so it's ok to fail on any error */
+ while ((msg = curl_multi_info_read(curlstream->multi, &msgs_left))) {
+ if (msg->data.result == CURLE_OK) {
+ continue;
+ } else {
+#if HAVE_CURL_EASY_STRERROR
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", curl_easy_strerror(msg->data.result));
+#else
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "There was an error mcode=%d", msg->data.result);
+#endif
+ msg_found++;
+ }
+ }
+ if (msg_found) {
+ goto exit_fail;
+ }
+ }
+
+ return stream;
+
+exit_fail:
+ php_stream_close(stream);
+ return NULL;
+}
+
+static php_stream_wrapper_ops php_curl_wrapper_ops = {
+ php_curl_stream_opener,
+ NULL, /* stream_close: curl streams know how to clean themselves up */
+ NULL, /* stream_stat: curl streams know how to stat themselves */
+ NULL, /* stat url */
+ NULL, /* opendir */
+ "cURL", /* label */
+ NULL, /* unlink */
+ NULL, /* rename */
+ NULL, /* mkdir */
+ NULL /* rmdir */
+};
+
+php_stream_wrapper php_curl_wrapper = {
+ &php_curl_wrapper_ops,
+ NULL,
+ 1 /* is_url */
+};
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/curl/tests/bug27023.phpt b/ext/curl/tests/bug27023.phpt
new file mode 100644
index 0000000..b738c95
--- /dev/null
+++ b/ext/curl/tests/bug27023.phpt
@@ -0,0 +1,48 @@
+--TEST--
+Bug #27023 (CURLOPT_POSTFIELDS does not parse content types for files)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+?>
+--FILE--
+<?php
+
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_URL, "{$host}/get.php?test=file");
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+$params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt');
+curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+var_dump(curl_exec($ch));
+
+$params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt;type=text/plain');
+curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+var_dump(curl_exec($ch));
+
+$params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt;filename=foo.txt');
+curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+var_dump(curl_exec($ch));
+
+$params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt;type=text/plain;filename=foo.txt');
+curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+var_dump(curl_exec($ch));
+
+$params = array('file' => '@' . __DIR__ . '/curl_testdata1.txt;filename=foo.txt;type=text/plain');
+curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+var_dump(curl_exec($ch));
+
+
+curl_close($ch);
+?>
+--EXPECTF--
+string(%d) "curl_testdata1.txt|application/octet-stream"
+string(%d) "curl_testdata1.txt|text/plain"
+string(%d) "foo.txt|application/octet-stream"
+string(%d) "foo.txt|text/plain"
+string(%d) "foo.txt|text/plain"
diff --git a/ext/curl/tests/bug45161.phpt b/ext/curl/tests/bug45161.phpt
new file mode 100644
index 0000000..9fdc7a7
--- /dev/null
+++ b/ext/curl/tests/bug45161.phpt
@@ -0,0 +1,52 @@
+--TEST--
+Bug #45161 (Reusing a curl handle leaks memory)
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ exit("skip not for Windows");
+}
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+$curl_version = curl_version();
+if ($curl_version['version_number'] < 0x071100) {
+ exit("skip: test works only with curl >= 7.17.0");
+}
+?>
+--FILE--
+<?php
+
+// Fill memory for test
+$ch = curl_init();
+$fp = fopen('/dev/null', 'w');
+
+/*
+$i = $start = $end = 100000.00;
+for ($i = 0; $i < 100; $i++) {
+ curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:9/');
+ curl_setopt($ch, CURLOPT_FILE, $fp);
+ curl_exec($ch);
+}
+*/
+
+// Start actual test
+$start = memory_get_usage() + 1024;
+for($i = 0; $i < 1024; $i++) {
+ curl_setopt($ch, CURLOPT_URL, 'http://127.0.0.1:9/');
+ curl_setopt($ch, CURLOPT_FILE, $fp);
+ curl_exec($ch);
+}
+if ($start < memory_get_usage()) {
+ echo 'FAIL';
+} else {
+ echo 'PASS';
+}
+echo "\n";
+fclose($fp);
+unset($fp);
+?>
+--EXPECT--
+PASS
diff --git a/ext/curl/tests/bug46711.phpt b/ext/curl/tests/bug46711.phpt
new file mode 100644
index 0000000..8eef556
--- /dev/null
+++ b/ext/curl/tests/bug46711.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #46711 (lost memory when foreach is used for values passed to curl_setopt())
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+?>
+--FILE--
+<?php
+$ch = curl_init();
+
+$opt = array(
+ CURLOPT_AUTOREFERER => TRUE,
+ CURLOPT_BINARYTRANSFER => TRUE
+);
+
+curl_setopt( $ch, CURLOPT_AUTOREFERER , TRUE );
+
+foreach( $opt as $option => $value ) {
+ curl_setopt( $ch, $option, $value );
+}
+
+var_dump($opt); // with this bug, $opt[58] becomes NULL
+
+?>
+--EXPECT--
+array(2) {
+ [58]=>
+ bool(true)
+ [19914]=>
+ bool(true)
+}
diff --git a/ext/curl/tests/bug46739.phpt b/ext/curl/tests/bug46739.phpt
new file mode 100644
index 0000000..895bba7
--- /dev/null
+++ b/ext/curl/tests/bug46739.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #46739 (array returned by curl_getinfo should contain content_type key)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+?>
+--FILE--
+<?php
+$ch = curl_init('http://127.0.0.1:9/');
+
+curl_exec($ch);
+$info = curl_getinfo($ch);
+
+echo (array_key_exists('content_type', $info)) ? "set" : "not set";
+?>
+--EXPECT--
+set
diff --git a/ext/curl/tests/bug48203.phpt b/ext/curl/tests/bug48203.phpt
new file mode 100644
index 0000000..d8f4d22
--- /dev/null
+++ b/ext/curl/tests/bug48203.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Bug #48203 (Crash when CURLOPT_STDERR is set to regular file)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+?>
+--FILE--
+<?php
+
+$fp = fopen(dirname(__FILE__) . '/bug48203.tmp', 'w');
+
+$ch = curl_init();
+
+curl_setopt($ch, CURLOPT_VERBOSE, 1);
+curl_setopt($ch, CURLOPT_STDERR, $fp);
+curl_setopt($ch, CURLOPT_URL, getenv('PHP_CURL_HTTP_REMOTE_SERVER'));
+
+fclose($fp); // <-- premature close of $fp caused a crash!
+
+curl_exec($ch);
+curl_close($ch);
+
+echo "Ok\n";
+
+?>
+--CLEAN--
+<?php @unlink(dirname(__FILE__) . '/bug48203.tmp'); ?>
+--EXPECTF--
+Warning: curl_exec(): CURLOPT_STDERR resource has gone away, resetting to stderr in %sbug48203.php on line %d
+%A
+Ok
diff --git a/ext/curl/tests/bug48203_multi.phpt b/ext/curl/tests/bug48203_multi.phpt
new file mode 100644
index 0000000..7d4ee47
--- /dev/null
+++ b/ext/curl/tests/bug48203_multi.phpt
@@ -0,0 +1,90 @@
+--TEST--
+Variation of bug #48203 with curl_multi_exec (Crash when file pointers passed to curl are closed before calling curl_multi_exec)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+?>
+--FILE--
+<?php
+
+function checkForClosedFilePointer($curl_option, $description) {
+ $fp = fopen(dirname(__FILE__) . '/bug48203.tmp', 'w');
+
+ $ch1 = curl_init();
+ $ch2 = curl_init();
+
+ $options = array(
+ CURLOPT_RETURNTRANSFER => 1,
+ $curl_option => $fp,
+ CURLOPT_URL => getenv("PHP_CURL_HTTP_REMOTE_SERVER")
+ );
+
+ // we also need to set CURLOPT_VERBOSE to test CURLOPT_STDERR properly
+ if (CURLOPT_STDERR == $curl_option) {
+ $options[CURLOPT_VERBOSE] = 1;
+ }
+
+ if (CURLOPT_INFILE == $curl_option) {
+ $options[CURLOPT_UPLOAD] = 1;
+ }
+
+ curl_setopt_array($ch1, $options);
+ curl_setopt_array($ch2, $options);
+
+ fclose($fp); // <-- premature close of $fp caused a crash!
+
+ $mh = curl_multi_init();
+
+ curl_multi_add_handle($mh, $ch1);
+ curl_multi_add_handle($mh, $ch2);
+
+ $active = 0;
+ do {
+ curl_multi_exec($mh, $active);
+ } while ($active > 0);
+
+ curl_multi_remove_handle($mh, $ch1);
+ curl_multi_remove_handle($mh, $ch2);
+ curl_multi_close($mh);
+
+ echo "Ok for $description\n";
+}
+
+$options_to_check = array(
+ "CURLOPT_STDERR", "CURLOPT_WRITEHEADER", "CURLOPT_FILE", "CURLOPT_INFILE"
+);
+
+foreach($options_to_check as $option) {
+ checkForClosedFilePointer(constant($option), $option);
+}
+
+?>
+--CLEAN--
+<?php @unlink(dirname(__FILE__) . '/bug48203.tmp'); ?>
+--EXPECTF--
+Warning: curl_multi_exec(): CURLOPT_STDERR resource has gone away, resetting to stderr in %sbug48203_multi.php on line 36
+
+Warning: curl_multi_exec(): CURLOPT_STDERR resource has gone away, resetting to stderr in %sbug48203_multi.php on line 36
+%A
+Ok for CURLOPT_STDERR
+%A
+Warning: curl_multi_exec(): CURLOPT_WRITEHEADER resource has gone away, resetting to default in %sbug48203_multi.php on line 36
+
+Warning: curl_multi_exec(): CURLOPT_WRITEHEADER resource has gone away, resetting to default in %sbug48203_multi.php on line 36
+Ok for CURLOPT_WRITEHEADER
+
+Warning: curl_multi_exec(): CURLOPT_FILE resource has gone away, resetting to default in %sbug48203_multi.php on line 36
+
+Warning: curl_multi_exec(): CURLOPT_FILE resource has gone away, resetting to default in %sbug48203_multi.php on line 36
+%A
+Ok for CURLOPT_FILE
+
+Warning: curl_multi_exec(): CURLOPT_INFILE resource has gone away, resetting to default in %sbug48203_multi.php on line 36
+
+Warning: curl_multi_exec(): CURLOPT_INFILE resource has gone away, resetting to default in %sbug48203_multi.php on line 36
+Ok for CURLOPT_INFILE
diff --git a/ext/curl/tests/bug48207.phpt b/ext/curl/tests/bug48207.phpt
new file mode 100644
index 0000000..6ac16f5
--- /dev/null
+++ b/ext/curl/tests/bug48207.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Test curl_setopt() CURLOPT_FILE readonly file handle
+--CREDITS--
+Mark van der Velden
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+/*
+ * Description : Adds a file which stores the received data from curl_exec();
+ * Source code : ext/curl/multi.c
+ * Test documentation: http://wiki.php.net/qa/temp/ext/curl
+ */
+
+// Figure out what handler to use
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+if(!empty($host)) {
+
+ // Use the set Environment variable
+ $url = "$host/get.php?test=1";
+
+} else {
+
+ // Create a temporary file for the test
+ $tempname = tempnam(sys_get_temp_dir(), 'CURL_HANDLE');
+ $url = 'file://'. $tempname;
+
+ // add the test data to the file
+ file_put_contents($tempname, "Hello World!\nHello World!");
+}
+
+
+$tempfile = tempnam(sys_get_temp_dir(), 'CURL_FILE_HANDLE');
+
+$ch = curl_init($url);
+$fp = fopen($tempfile, "r"); // Opening 'fubar' with the incorrect readonly flag
+curl_setopt($ch, CURLOPT_FILE, $fp);
+curl_exec($ch);
+curl_close($ch);
+is_file($tempfile) and @unlink($tempfile);
+isset($tempname) and is_file($tempname) and @unlink($tempname);
+?>
+--EXPECTF--
+Warning: curl_setopt(): the provided file handle is not writable in %s on line %d
+Hello World!
+Hello World!
diff --git a/ext/curl/tests/bug48514.phpt b/ext/curl/tests/bug48514.phpt
new file mode 100644
index 0000000..0ea2575
--- /dev/null
+++ b/ext/curl/tests/bug48514.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #48514 (cURL extension uses same resource name for simple and multi APIs)
+--SKIPIF--
+<?php
+
+if (!extension_loaded('curl')) {
+ exit("skip curl extension not loaded");
+}
+
+?>
+--FILE--
+<?php
+
+$ch1 = curl_init();
+var_dump($ch1);
+var_dump(get_resource_type($ch1));
+
+$ch2 = curl_multi_init();
+var_dump($ch2);
+var_dump(get_resource_type($ch2));
+
+?>
+--EXPECTF--
+resource(%d) of type (curl)
+%string|unicode%(4) "curl"
+resource(%d) of type (curl_multi)
+%string|unicode%(10) "curl_multi"
diff --git a/ext/curl/tests/bug52202.phpt b/ext/curl/tests/bug52202.phpt
new file mode 100644
index 0000000..a304d7f
--- /dev/null
+++ b/ext/curl/tests/bug52202.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #52202 (CURLOPT_PRIVATE gets clobbered)
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) exit("skip curl extension not loaded");
+?>
+--FILE--
+<?php
+$curl = curl_init("http://www.google.com");
+curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+curl_setopt($curl, CURLOPT_PRIVATE, "123");
+curl_exec($curl);
+
+var_dump(curl_getinfo($curl, CURLINFO_PRIVATE));
+--EXPECT--
+string(3) "123"
diff --git a/ext/curl/tests/bug52827.phpt b/ext/curl/tests/bug52827.phpt
new file mode 100644
index 0000000..85a73fa
--- /dev/null
+++ b/ext/curl/tests/bug52827.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #52827 (curl_setopt with CURLOPT_STDERR erroneously increments the resource refcount)
+--SKIPIF--
+<?php
+
+if (!extension_loaded('curl')) {
+ exit("skip curl extension not loaded");
+}
+
+?>
+--FILE--
+<?php
+$s = fopen('php://temp/maxmemory=1024','wb+');
+
+/* force conversion of inner stream to STDIO.
+ * This is not necessary in Windows because the
+ * cast to a FILE* handle in curl_setopt already
+ * forces the conversion in that platform. The
+ * reason for this conversion is that the memory
+ * stream has an ugly but working mechanism to
+ * prevent being double freed when it's encapsulated,
+ * while STDIO streams don't. */
+$i = 0;
+while ($i++ < 5000) {
+fwrite($s, str_repeat('a',1024));
+}
+$handle=curl_init('http://www.example.com');
+curl_setopt($handle, CURLOPT_STDERR, $s);
+
+echo "Done.";
+--EXPECTF--
+Done.
diff --git a/ext/curl/tests/bug54798.phpt b/ext/curl/tests/bug54798.phpt
new file mode 100644
index 0000000..7ec84ad
--- /dev/null
+++ b/ext/curl/tests/bug54798.phpt
@@ -0,0 +1,72 @@
+--TEST--
+Bug #54798 (Segfault when CURLOPT_STDERR file pointer is closed before calling curl_exec)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+?>
+--FILE--
+<?php
+
+function checkForClosedFilePointer($host, $curl_option, $description) {
+ $fp = fopen(dirname(__FILE__) . '/bug54798.tmp', 'w+');
+
+ $ch = curl_init();
+
+ // we also need CURLOPT_VERBOSE to be set to test CURLOPT_STDERR properly
+ if (CURLOPT_STDERR == $curl_option) {
+ curl_setopt($ch, CURLOPT_VERBOSE, 1);
+ }
+
+ if (CURLOPT_INFILE == $curl_option) {
+ curl_setopt($ch, CURLOPT_UPLOAD, 1);
+ }
+
+ curl_setopt($ch, $curl_option, $fp);
+
+ curl_setopt($ch, CURLOPT_URL, $host);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+ fclose($fp); // <-- premature close of $fp caused a crash!
+
+ curl_exec($ch);
+
+ curl_close($ch);
+
+ echo "Ok for $description\n";
+}
+
+$options_to_check = array(
+ "CURLOPT_STDERR",
+ "CURLOPT_WRITEHEADER",
+ "CURLOPT_FILE",
+ "CURLOPT_INFILE"
+);
+
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+foreach($options_to_check as $option) {
+ checkForClosedFilePointer($host, constant($option), $option);
+}
+
+?>
+--CLEAN--
+<?php @unlink(dirname(__FILE__) . '/bug54798.tmp'); ?>
+--EXPECTF--
+Warning: curl_exec(): CURLOPT_STDERR resource has gone away, resetting to stderr in %sbug54798.php on line %d
+* About to connect() %a
+* Closing connection #%d
+Ok for CURLOPT_STDERR
+
+Warning: curl_exec(): CURLOPT_WRITEHEADER resource has gone away, resetting to default in %sbug54798.php on line 24
+Ok for CURLOPT_WRITEHEADER
+
+Warning: curl_exec(): CURLOPT_FILE resource has gone away, resetting to default in %sbug54798.php on line 24
+%a
+Ok for CURLOPT_FILE
+
+Warning: curl_exec(): CURLOPT_INFILE resource has gone away, resetting to default in %sbug54798.php on line %d
+Ok for CURLOPT_INFILE
diff --git a/ext/curl/tests/bug55767.phpt b/ext/curl/tests/bug55767.phpt
new file mode 100644
index 0000000..321f67b
--- /dev/null
+++ b/ext/curl/tests/bug55767.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Test curl_opt() function with POST params from array with a numeric key
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl sending through GET an POST ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost&get_param=Hello%20World";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, array('Hello'=>'World','Foo'=>'Bar',100=>'John Doe'));
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl sending through GET an POST ***
+string(203) "array(2) {
+ ["test"]=>
+ string(7) "getpost"
+ ["get_param"]=>
+ string(11) "Hello World"
+}
+array(3) {
+ ["Hello"]=>
+ string(5) "World"
+ ["Foo"]=>
+ string(3) "Bar"
+ [100]=>
+ string(8) "John Doe"
+}
+"
+===DONE===
diff --git a/ext/curl/tests/bug61948-win32.phpt b/ext/curl/tests/bug61948-win32.phpt
new file mode 100644
index 0000000..dc86526
--- /dev/null
+++ b/ext/curl/tests/bug61948-win32.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #61948 (CURLOPT_COOKIEFILE '' raises open_basedir restriction)
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip";
+if(substr(PHP_OS, 0, 3) != 'WIN' )
+ die("skip Not Valid for Linux");
+?>
+--INI--
+open_basedir="c:/tmp"
+--FILE--
+<?php
+ $ch = curl_init();
+ var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, ""));
+ var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "c:/tmp/foo"));
+ var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "c:/xxx/bar"));
+ curl_close($ch);
+?>
+--EXPECTF--
+%a
+
+Warning: curl_setopt(): open_basedir restriction in effect. File(c:/tmp/foo) is not within the allowed path(s): (c:/tmp) in %sbug61948-win32.php on line %d
+bool(false)
+
+Warning: curl_setopt(): open_basedir restriction in effect. File(c:/xxx/bar) is not within the allowed path(s): (c:/tmp) in %sbug61948-win32.php on line %d
+bool(false)
diff --git a/ext/curl/tests/bug61948.phpt b/ext/curl/tests/bug61948.phpt
new file mode 100644
index 0000000..00df07d
--- /dev/null
+++ b/ext/curl/tests/bug61948.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #61948 (CURLOPT_COOKIEFILE '' raises open_basedir restriction)
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip";
+if(substr(PHP_OS, 0, 3) == 'WIN' )
+ die("skip Not Valid for Windows");
+?>
+--INI--
+open_basedir="/tmp"
+--FILE--
+<?php
+ $ch = curl_init();
+ var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, ""));
+ var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/foo"));
+ var_dump(curl_setopt($ch, CURLOPT_COOKIEFILE, "/xxx/bar"));
+ curl_close($ch);
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+
+Warning: curl_setopt(): open_basedir restriction in effect. File(/xxx/bar) is not within the allowed path(s): (/tmp) in %sbug61948.php on line %d
+bool(false)
diff --git a/ext/curl/tests/bug62839.phpt b/ext/curl/tests/bug62839.phpt
new file mode 100644
index 0000000..e6988d6
--- /dev/null
+++ b/ext/curl/tests/bug62839.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #62839 (curl_copy_handle segfault with CURLOPT_FILE)
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip";
+?>
+--FILE--
+<?php
+$curl = curl_init();
+
+$fd = tmpfile();
+curl_setopt($curl, CURLOPT_FILE, $fd);
+
+curl_copy_handle($curl);
+
+echo 'DONE!';
+?>
+--EXPECTF--
+DONE!
diff --git a/ext/curl/tests/bug63363.phpt b/ext/curl/tests/bug63363.phpt
new file mode 100644
index 0000000..36abc5e
--- /dev/null
+++ b/ext/curl/tests/bug63363.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #63363 (CURL silently accepts boolean value for SSL_VERIFYHOST)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+$curl_version = curl_version();
+if ($curl_version['version_number'] >= 0x071c01) {
+ exit("skip: test valid for libcurl < 7.28.1");
+}
+?>
+--FILE--
+<?php
+$ch = curl_init();
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false));
+/* Case that should throw an error */
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2));
+
+curl_close($ch);
+?>
+--EXPECTF--
+bool(true)
+
+Notice: curl_setopt(): 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 in %s on line %d
+bool(true)
+bool(true)
+
+Notice: curl_setopt(): 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 in %s on line %d
+bool(true)
+bool(true)
diff --git a/ext/curl/tests/bug63795.phpt b/ext/curl/tests/bug63795.phpt
new file mode 100644
index 0000000..798faa6
--- /dev/null
+++ b/ext/curl/tests/bug63795.phpt
@@ -0,0 +1,34 @@
+--TEST--
+Bug #63795 (CURL >= 7.28.0 no longer support value 1 for CURLOPT_SSL_VERIFYHOST)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+$curl_version = curl_version();
+if ($curl_version['version_number'] < 0x071c01) {
+ exit("skip: test valid for libcurl >= 7.28.1");
+}
+?>
+--FILE--
+<?php
+$ch = curl_init();
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false));
+/* Case that should throw an error */
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 1));
+var_dump(curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2));
+
+curl_close($ch);
+?>
+--EXPECTF--
+bool(true)
+
+Notice: curl_setopt(): CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead in %s on line %d
+bool(true)
+bool(true)
+
+Notice: curl_setopt(): CURLOPT_SSL_VERIFYHOST no longer accepts the value 1, value 2 will be used instead in %s on line %d
+bool(true)
+bool(true)
diff --git a/ext/curl/tests/curl_CURLOPT_READDATA.phpt b/ext/curl/tests/curl_CURLOPT_READDATA.phpt
new file mode 100644
index 0000000..ea63d44
--- /dev/null
+++ b/ext/curl/tests/curl_CURLOPT_READDATA.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Test CURLOPT_READDATA without a callback function
+--CREDITS--
+Mattijs Hoitink mattijshoitink@gmail.com
+#Testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+// The URL to POST to
+$url = getenv('PHP_CURL_HTTP_REMOTE_SERVER') . '/get.php?test=post';
+
+// Create a temporary file to read the data from
+$tempname = tempnam(sys_get_temp_dir(), 'CURL_DATA');
+$datalen = file_put_contents($tempname, "hello=world&smurf=blue");
+
+ob_start();
+
+$ch = curl_init($url);
+curl_setopt($ch, CURLOPT_URL, $url);
+curl_setopt($ch, CURLOPT_POST, true);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+curl_setopt($ch, CURLOPT_READDATA, fopen($tempname, 'rb'));
+curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:', "Content-Length: {$datalen}"));
+
+if (false === $response = curl_exec($ch)) {
+ echo 'Error #' . curl_errno($ch) . ': ' . curl_error($ch);
+} else {
+ echo $response;
+}
+
+curl_close($ch);
+
+// Clean the temporary file
+@unlink($tempname);
+
+--EXPECT--
+array(2) {
+ ["hello"]=>
+ string(5) "world"
+ ["smurf"]=>
+ string(4) "blue"
+}
diff --git a/ext/curl/tests/curl_basic_001.phpt b/ext/curl/tests/curl_basic_001.phpt
new file mode 100644
index 0000000..fa362b3
--- /dev/null
+++ b/ext/curl/tests/curl_basic_001.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Test curl_exec() function with basic functionality
+--CREDITS--
+Sebastian Deutsch <sebastian.deutsch@9elements.com>
+TestFest 2009 - AFUP - Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_exec(resource ch)
+ * Description: Perform a cURL session
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo "*** Testing curl_exec() : basic functionality ***\n";
+
+ $url = "{$host}/get.php?test=get";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+ $ok = curl_exec($ch);
+ curl_close($ch);
+ $curl_content = ob_get_contents();
+ ob_end_clean();
+
+ if($ok) {
+ var_dump( $curl_content );
+ } else {
+ echo "curl_exec returned false";
+ }
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_exec() : basic functionality ***
+string(25) "Hello World!
+Hello World!"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_002.phpt b/ext/curl/tests/curl_basic_002.phpt
new file mode 100644
index 0000000..e46f323
--- /dev/null
+++ b/ext/curl/tests/curl_basic_002.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Test curl_opt() function with CURLOPT_RETURNTRANSFER parameter set to 1
+--CREDITS--
+Sebastian Deutsch <sebastian.deutsch@9elements.com>
+TestFest 2009 - AFUP - Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ***' . "\n";
+
+ $url = "{$host}/get.php?test=get";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); ***
+string(25) "Hello World!
+Hello World!"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_003.phpt b/ext/curl/tests/curl_basic_003.phpt
new file mode 100644
index 0000000..eb2aecd
--- /dev/null
+++ b/ext/curl/tests/curl_basic_003.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Test curl_opt() function with POST parameters
+--CREDITS--
+Sebastian Deutsch <sebastian.deutsch@9elements.com>
+TestFest 2009 - AFUP - Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl sending through GET an POST ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost&get_param=Hello%20World";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, "Hello=World&Foo=Bar&Person=John%20Doe");
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl sending through GET an POST ***
+string(208) "array(2) {
+ ["test"]=>
+ string(7) "getpost"
+ ["get_param"]=>
+ string(11) "Hello World"
+}
+array(3) {
+ ["Hello"]=>
+ string(5) "World"
+ ["Foo"]=>
+ string(3) "Bar"
+ ["Person"]=>
+ string(8) "John Doe"
+}
+"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_004.phpt b/ext/curl/tests/curl_basic_004.phpt
new file mode 100644
index 0000000..ea2eeca
--- /dev/null
+++ b/ext/curl/tests/curl_basic_004.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Test curl_opt() function with setting referer
+--CREDITS--
+Sebastian Deutsch <sebastian.deutsch@9elements.com>
+TestFest 2009 - AFUP - Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl setting referer ***' . "\n";
+
+ $url = "{$host}/get.php?test=referer";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_REFERER, 'http://www.refer.er');
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl setting referer ***
+string(19) "http://www.refer.er"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_005.phpt b/ext/curl/tests/curl_basic_005.phpt
new file mode 100644
index 0000000..9285c10
--- /dev/null
+++ b/ext/curl/tests/curl_basic_005.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Test curl_opt() function with user agent
+--CREDITS--
+Sebastian Deutsch <sebastian.deutsch@9elements.com>
+TestFest 2009 - AFUP - Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl with user agent ***' . "\n";
+
+ $url = "{$host}/get.php?test=useragent";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'cURL phpt');
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl with user agent ***
+string(9) "cURL phpt"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_006.phpt b/ext/curl/tests/curl_basic_006.phpt
new file mode 100644
index 0000000..5f1a4f4
--- /dev/null
+++ b/ext/curl/tests/curl_basic_006.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Test curl_opt() function with CURLOPT_WRITEFUNCTION parameter set to a closure
+--CREDITS--
+?
+TestFest 2009 - AFUP - Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl_setopt($ch, CURLOPT_WRITEFUNCTION, <closure>); ***' . "\n";
+
+ $url = "{$host}/get.php?test=get";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+ curl_setopt($ch, CURLOPT_WRITEFUNCTION, function ($ch, $data) {
+ echo 'Data: '.$data;
+ return strlen ($data);
+ });
+
+ curl_exec($ch);
+ curl_close($ch);
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_setopt($ch, CURLOPT_WRITEFUNCTION, <closure>); ***
+Data: Hello World!
+Hello World!===DONE===
diff --git a/ext/curl/tests/curl_basic_007.phpt b/ext/curl/tests/curl_basic_007.phpt
new file mode 100644
index 0000000..b7eba4b
--- /dev/null
+++ b/ext/curl/tests/curl_basic_007.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test curl_error() & curl_errno() function without url
+--CREDITS--
+TestFest 2009 - AFUP - Perrick Penet <perrick@noparking.net>
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+
+//In January 2008 , level 7.18.0 of the curl lib, many of the messages changed.
+//The final crlf was removed. This test is coded to work with or without the crlf.
+
+$ch = curl_init();
+
+curl_exec($ch);
+var_dump(curl_error($ch));
+var_dump(curl_errno($ch));
+curl_close($ch);
+
+
+?>
+--EXPECTF--
+%string|unicode%(%d) "No URL set!%w"
+int(3)
diff --git a/ext/curl/tests/curl_basic_008.phpt b/ext/curl/tests/curl_basic_008.phpt
new file mode 100644
index 0000000..29e3343
--- /dev/null
+++ b/ext/curl/tests/curl_basic_008.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Test curl_error() & curl_errno() function with problematic host
+--CREDITS--
+TestFest 2009 - AFUP - Perrick Penet <perrick@noparking.net>
+--SKIPIF--
+<?php
+ if (!extension_loaded("curl")) print "skip";
+ $addr = "www.".uniqid().".".uniqid();
+ if (gethostbyname($addr) != $addr) {
+ print "skip catch all dns";
+ }
+?>
+--FILE--
+<?php
+
+$url = "http://www.".uniqid().".".uniqid();
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_URL, $url);
+
+curl_exec($ch);
+var_dump(curl_error($ch));
+var_dump(curl_errno($ch));
+curl_close($ch);
+
+
+?>
+--EXPECTF--
+%unicode|string%(%d) "%r(Couldn't resolve host|Could not resolve host:)%r %Swww.%s"
+int(6)
diff --git a/ext/curl/tests/curl_basic_009.phpt b/ext/curl/tests/curl_basic_009.phpt
new file mode 100644
index 0000000..529e590
--- /dev/null
+++ b/ext/curl/tests/curl_basic_009.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Test curl_error() & curl_errno() function with problematic protocol
+--CREDITS--
+TestFest 2009 - AFUP - Perrick Penet <perrick@noparking.net>
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+
+$url = uniqid()."://www.".uniqid().".".uniqid();
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_URL, $url);
+
+curl_exec($ch);
+var_dump(curl_error($ch));
+var_dump(curl_errno($ch));
+curl_close($ch);
+
+
+?>
+--EXPECTF--
+%unicode|string%(%d) "%Srotocol%s"
+int(1)
diff --git a/ext/curl/tests/curl_basic_010.phpt b/ext/curl/tests/curl_basic_010.phpt
new file mode 100644
index 0000000..0fc2fe6
--- /dev/null
+++ b/ext/curl/tests/curl_basic_010.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test curl_error() & curl_errno() function with problematic proxy
+--CREDITS--
+TestFest 2009 - AFUP - Perrick Penet <perrick@noparking.net>
+--SKIPIF--
+<?php
+ if (!extension_loaded("curl")) print "skip";
+ $addr = "www.".uniqid().".".uniqid();
+ if (gethostbyname($addr) != $addr) {
+ print "skip catch all dns";
+ }
+?>
+--FILE--
+<?php
+
+$url = "http://www.example.org";
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_PROXY, uniqid().":".uniqid());
+curl_setopt($ch, CURLOPT_URL, $url);
+
+curl_exec($ch);
+var_dump(curl_error($ch));
+var_dump(curl_errno($ch));
+curl_close($ch);
+
+
+?>
+--EXPECTF--
+%unicode|string%(%d) "%r(Couldn't resolve proxy|Could not resolve proxy:|Could not resolve host:)%r %s"
+int(5)
diff --git a/ext/curl/tests/curl_basic_011.phpt b/ext/curl/tests/curl_basic_011.phpt
new file mode 100644
index 0000000..10c90b1
--- /dev/null
+++ b/ext/curl/tests/curl_basic_011.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Test curl_opt() function with COOKIE
+--CREDITS--
+TestFest 2009 - AFUP - Xavier Gorse <xgorse@elao.com>
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv(b'PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl with cookie ***' . "\n";
+
+ $url = "{$host}/get.php?test=cookie";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_COOKIE, 'foo=bar');
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl with cookie ***
+string(3) "bar"
+===DONE===
+
diff --git a/ext/curl/tests/curl_basic_012.phpt b/ext/curl/tests/curl_basic_012.phpt
new file mode 100644
index 0000000..e4706fa
--- /dev/null
+++ b/ext/curl/tests/curl_basic_012.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Test curl_opt() function with CURLOPT_HTTP_VERSION/CURL_HTTP_VERSION_1_0
+--CREDITS--
+TestFest 2009 - AFUP - Xavier Gorse <xgorse@elao.com>
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv(b'PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl with HTTP/1.0 ***' . "\n";
+
+ $url = "{$host}/get.php?test=httpversion";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl with HTTP/1.0 ***
+string(8) "HTTP/1.0"
+===DONE===
+ \ No newline at end of file
diff --git a/ext/curl/tests/curl_basic_013.phpt b/ext/curl/tests/curl_basic_013.phpt
new file mode 100644
index 0000000..c49d187
--- /dev/null
+++ b/ext/curl/tests/curl_basic_013.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Test curl_opt() function with CURLOPT_HTTP_VERSION/CURL_HTTP_VERSION_1_1
+--CREDITS--
+TestFest 2009 - AFUP - Xavier Gorse <xgorse@elao.com>
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv(b'PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo '*** Testing curl with HTTP/1.1 ***' . "\n";
+
+ $url = "{$host}/get.php?test=httpversion";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $curl_content = curl_exec($ch);
+ curl_close($ch);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl with HTTP/1.1 ***
+string(8) "HTTP/1.1"
+===DONE===
+ \ No newline at end of file
diff --git a/ext/curl/tests/curl_basic_014.phpt b/ext/curl/tests/curl_basic_014.phpt
new file mode 100644
index 0000000..4037970
--- /dev/null
+++ b/ext/curl/tests/curl_basic_014.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Test curl_init() function with basic functionality
+--CREDITS--
+Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php if (!extension_loaded("curl")) exit("skip curl extension not loaded"); ?>
+--FILE--
+<?php
+ $ch = curl_init();
+ var_dump($ch);
+?>
+===DONE===
+--EXPECTF--
+resource(%d) of type (curl)
+===DONE===
diff --git a/ext/curl/tests/curl_basic_015.phpt b/ext/curl/tests/curl_basic_015.phpt
new file mode 100644
index 0000000..e8e43e5
--- /dev/null
+++ b/ext/curl/tests/curl_basic_015.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Test curl_init() function with $url parameter defined
+--CREDITS--
+Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php if (!extension_loaded("curl")) exit("skip curl extension not loaded"); ?>
+--FILE--
+<?php
+ $url = 'http://www.example.com/';
+ $ch = curl_init($url);
+ var_dump($url == curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
+?>
+===DONE===
+--EXPECTF--
+bool(true)
+===DONE===
diff --git a/ext/curl/tests/curl_basic_016.phpt b/ext/curl/tests/curl_basic_016.phpt
new file mode 100644
index 0000000..b5890c0
--- /dev/null
+++ b/ext/curl/tests/curl_basic_016.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Test curl_getinfo() function with basic functionality
+--CREDITS--
+Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+$curl_version = curl_version();
+if ($curl_version['version_number'] > 0x071201) {
+ exit("skip: tests works only on older versions of curl");
+}
+?>
+--FILE--
+<?php
+ $ch = curl_init();
+ $info = curl_getinfo($ch);
+ var_dump($info);
+?>
+===DONE===
+--EXPECTF--
+array(2%d) {
+ [%u|b%"url"]=>
+ string(0) ""
+ ["content_type"]=>
+ NULL
+ ["http_code"]=>
+ int(0)
+ ["header_size"]=>
+ int(0)
+ ["request_size"]=>
+ int(0)
+ ["filetime"]=>
+ int(0)
+ ["ssl_verify_result"]=>
+ int(0)
+ ["redirect_count"]=>
+ int(0)
+ ["total_time"]=>
+ float(0)
+ ["namelookup_time"]=>
+ float(0)
+ ["connect_time"]=>
+ float(0)
+ ["pretransfer_time"]=>
+ float(0)
+ ["size_upload"]=>
+ float(0)
+ ["size_download"]=>
+ float(0)
+ ["speed_download"]=>
+ float(0)
+ ["speed_upload"]=>
+ float(0)
+ ["download_content_length"]=>
+ float(%f)
+ ["upload_content_length"]=>
+ float(%f)
+ ["starttransfer_time"]=>
+ float(0)
+ ["redirect_time"]=>
+ float(0)
+}
+===DONE===
diff --git a/ext/curl/tests/curl_basic_017.phpt b/ext/curl/tests/curl_basic_017.phpt
new file mode 100644
index 0000000..09247b2
--- /dev/null
+++ b/ext/curl/tests/curl_basic_017.phpt
@@ -0,0 +1,69 @@
+--TEST--
+Test curl_multi_exec() function with basic functionality
+--CREDITS--
+TestFest 2009 - AFUP - Thomas Rabaix <thomas.rabaix@gmail.com>
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?>
+--FILE--
+<?php
+/* Prototype : bool curl_multi_exec(resource ch)
+ * Description: Perform a cURL session
+ * Source code: ext/curl/multi.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo "*** Testing curl_exec() : basic functionality ***\n";
+
+ $url = "{$host}/get.php?test=get";
+ $chs = array(
+ 0 => curl_init(),
+ 1 => curl_init(),
+ 2 => curl_init(),
+ );
+
+ ob_start(); // start output buffering
+
+ curl_setopt($chs[0], CURLOPT_URL, $url); //set the url we want to use
+ curl_setopt($chs[1], CURLOPT_URL, $url); //set the url we want to use
+ curl_setopt($chs[2], CURLOPT_URL, $url); //set the url we want to use
+
+ $mh = curl_multi_init();
+
+ // add handlers
+ curl_multi_add_handle($mh, $chs[0]);
+ curl_multi_add_handle($mh, $chs[1]);
+ curl_multi_add_handle($mh, $chs[2]);
+
+ $running=null;
+ //execute the handles
+ $state = null;
+ do {
+ $state = curl_multi_exec($mh, $running);
+ } while ($running > 0);
+
+ //close the handles
+ curl_multi_remove_handle($mh, $chs[0]);
+ curl_multi_remove_handle($mh, $chs[1]);
+ curl_multi_remove_handle($mh, $chs[2]);
+ curl_multi_close($mh);
+
+ $curl_content = ob_get_contents();
+ ob_end_clean();
+
+ if($state === CURLM_OK) {
+ var_dump( $curl_content );
+ } else {
+ echo "curl_exec returned false";
+ }
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_exec() : basic functionality ***
+string(75) "Hello World!
+Hello World!Hello World!
+Hello World!Hello World!
+Hello World!"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_018.phpt b/ext/curl/tests/curl_basic_018.phpt
new file mode 100644
index 0000000..7cffb89
--- /dev/null
+++ b/ext/curl/tests/curl_basic_018.phpt
@@ -0,0 +1,72 @@
+--TEST--
+Test curl_setopt() with curl_multi function with basic functionality
+--CREDITS--
+TestFest 2009 - AFUP - Thomas Rabaix <thomas.rabaix@gmail.com>
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?>
+--FILE--
+<?php
+/* Prototype : bool curl_setopt(resource ch, int option, mixed value)
+ * Description: Set an option for a cURL transfer
+ * Source code: ext/curl/interface.c
+ * Alias to functions:
+ */
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ // start testing
+ echo "*** Testing curl_exec() : basic functionality ***\n";
+
+ $url = "{$host}/get.php?test=get";
+ $chs = array(
+ 0 => curl_init(),
+ 1 => curl_init(),
+ 2 => curl_init(),
+ );
+
+ ob_start(); // start output buffering
+
+ $options = array(
+ CURLOPT_RETURNTRANSFER => 1,
+ CURLOPT_URL => $url,
+ );
+
+ curl_setopt_array($chs[0], $options); //set the options
+ curl_setopt_array($chs[1], $options); //set the options
+ curl_setopt_array($chs[2], $options); //set the options
+
+ $mh = curl_multi_init();
+
+ // add handlers
+ curl_multi_add_handle($mh, $chs[0]);
+ curl_multi_add_handle($mh, $chs[1]);
+ curl_multi_add_handle($mh, $chs[2]);
+
+ $running=null;
+ //execute the handles
+ do {
+ curl_multi_exec($mh, $running);
+ } while ($running > 0);
+
+ $curl_content = '';
+ $curl_content .= curl_multi_getcontent($chs[0]);
+ $curl_content .= curl_multi_getcontent($chs[1]);
+ $curl_content .= curl_multi_getcontent($chs[2]);
+
+ //close the handles
+ curl_multi_remove_handle($mh, $chs[0]);
+ curl_multi_remove_handle($mh, $chs[1]);
+ curl_multi_remove_handle($mh, $chs[2]);
+ curl_multi_close($mh);
+
+ var_dump( $curl_content );
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_exec() : basic functionality ***
+%unicode|string%(75) "Hello World!
+Hello World!Hello World!
+Hello World!Hello World!
+Hello World!"
+===DONE===
diff --git a/ext/curl/tests/curl_basic_019.phpt b/ext/curl/tests/curl_basic_019.phpt
new file mode 100644
index 0000000..ab605a8
--- /dev/null
+++ b/ext/curl/tests/curl_basic_019.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Test curl_getinfo() function with CURLINFO_EFFECTIVE_URL parameter
+--CREDITS--
+Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ $url = "{$host}/get.php?test=";
+ $ch = curl_init();
+
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_exec($ch);
+ $info = curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
+ var_dump($url == $info);
+
+ curl_close($ch);
+?>
+===DONE===
+--EXPECTF--
+Hello World!
+Hello World!bool(true)
+===DONE===
diff --git a/ext/curl/tests/curl_basic_020.phpt b/ext/curl/tests/curl_basic_020.phpt
new file mode 100644
index 0000000..d622053
--- /dev/null
+++ b/ext/curl/tests/curl_basic_020.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Test curl_getinfo() function with CURLINFO_HTTP_CODE parameter
+--CREDITS--
+Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ $url = "{$host}/get.php?test=";
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_exec($ch);
+ var_dump(curl_getinfo($ch, CURLINFO_HTTP_CODE));
+ curl_close($ch);
+?>
+===DONE===
+--EXPECTF--
+Hello World!
+Hello World!int(200)
+===DONE===
diff --git a/ext/curl/tests/curl_basic_021.phpt b/ext/curl/tests/curl_basic_021.phpt
new file mode 100644
index 0000000..3b4798d
--- /dev/null
+++ b/ext/curl/tests/curl_basic_021.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Test curl_getinfo() function with CURLINFO_CONTENT_TYPE parameter
+--CREDITS--
+Jean-Marc Fontaine <jmf@durcommefaire.net>
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+ $url = "{$host}/get.php?test=contenttype";
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_exec($ch);
+ var_dump(curl_getinfo($ch, CURLINFO_CONTENT_TYPE));
+ curl_close($ch);
+?>
+===DONE===
+--EXPECTF--
+%unicode|string%(24) "text/plain;charset=utf-8"
+===DONE===
diff --git a/ext/curl/tests/curl_close_basic.phpt b/ext/curl/tests/curl_close_basic.phpt
new file mode 100644
index 0000000..9c01b02
--- /dev/null
+++ b/ext/curl/tests/curl_close_basic.phpt
@@ -0,0 +1,19 @@
+--TEST--
+curl_close
+--CREDITS--
+Stefan Koopmanschap <stefan@php.net>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip';
+?>
+--FILE--
+<?php
+$ch = curl_init();
+curl_close($ch);
+var_dump($ch);
+?>
+===DONE===
+--EXPECTF--
+resource(%d) of type (Unknown)
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic.phpt b/ext/curl/tests/curl_copy_handle_basic.phpt
new file mode 100644
index 0000000..1a6ff41
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test curl_copy_handle() function with basic functionality
+--CREDITS--
+Francesco Fullone ff@ideato.it
+#PHPTestFest Cesena Italia on 2009-06-20
+--SKIPIF--
+<?php
+ if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+?>
+--FILE--
+<?php
+echo "*** Testing curl_copy_handle(): basic ***\n";
+
+// create a new cURL resource
+$ch = curl_init();
+
+// set URL and other appropriate options
+curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/');
+curl_setopt($ch, CURLOPT_HEADER, 0);
+
+// copy the handle
+$ch2 = curl_copy_handle($ch);
+
+var_dump(curl_getinfo($ch) === curl_getinfo($ch2));
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_copy_handle(): basic ***
+bool(true)
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_001.phpt b/ext/curl/tests/curl_copy_handle_basic_001.phpt
new file mode 100644
index 0000000..f1b4db3
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_001.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Test curl_copy_handle() with simple get
+--CREDITS--
+Rick Buitenman <rick@meritos.nl>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ echo '*** Testing curl copy handle with simple GET ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost&get_param=Hello%20World";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $copy = curl_copy_handle($ch);
+ curl_close($ch);
+
+ $curl_content = curl_exec($copy);
+ curl_close($copy);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl copy handle with simple GET ***
+string(106) "array(2) {
+ ["test"]=>
+ string(7) "getpost"
+ ["get_param"]=>
+ string(11) "Hello World"
+}
+array(0) {
+}
+"
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_002.phpt b/ext/curl/tests/curl_copy_handle_basic_002.phpt
new file mode 100644
index 0000000..9ab3363
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_002.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Test curl_copy_handle() with simple POST
+--CREDITS--
+Rick Buitenman <rick@meritos.nl>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ echo '*** Testing curl copy handle with simple POST ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, "Hello=World&Foo=Bar&Person=John%20Doe");
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $copy = curl_copy_handle($ch);
+ curl_close($ch);
+
+ $curl_content = curl_exec($copy);
+ curl_close($copy);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl copy handle with simple POST ***
+string(163) "array(1) {
+ ["test"]=>
+ string(7) "getpost"
+}
+array(3) {
+ ["Hello"]=>
+ string(5) "World"
+ ["Foo"]=>
+ string(3) "Bar"
+ ["Person"]=>
+ string(8) "John Doe"
+}
+"
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_004.phpt b/ext/curl/tests/curl_copy_handle_basic_004.phpt
new file mode 100644
index 0000000..9b794e9
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_004.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Test curl_copy_handle() after exec()
+--CREDITS--
+Rick Buitenman <rick@meritos.nl>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ echo '*** Test curl_copy_handle() after exec() ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost&get_param=Hello%20World";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+
+ $curl_content = curl_exec($ch);
+ $copy = curl_copy_handle($ch);
+ curl_close($ch);
+
+ $curl_content_copy = curl_exec($copy);
+ curl_close($copy);
+
+ var_dump( $curl_content_copy );
+?>
+===DONE===
+--EXPECTF--
+*** Test curl_copy_handle() after exec() ***
+string(106) "array(2) {
+ ["test"]=>
+ string(7) "getpost"
+ ["get_param"]=>
+ string(11) "Hello World"
+}
+array(0) {
+}
+"
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_005.phpt b/ext/curl/tests/curl_copy_handle_basic_005.phpt
new file mode 100644
index 0000000..aa9e2fa
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_005.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Test curl_copy_handle() after exec() with POST
+--CREDITS--
+Rick Buitenman <rick@meritos.nl>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ echo '*** Test curl_copy_handle() after exec() with POST ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, "Hello=World&Foo=Bar&Person=John%20Doe");
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+
+ $curl_content = curl_exec($ch);
+ $copy = curl_copy_handle($ch);
+ curl_close($ch);
+
+ $curl_content_copy = curl_exec($copy);
+ curl_close($copy);
+
+ var_dump( $curl_content_copy );
+?>
+===DONE===
+--EXPECTF--
+*** Test curl_copy_handle() after exec() with POST ***
+string(163) "array(1) {
+ ["test"]=>
+ string(7) "getpost"
+}
+array(3) {
+ ["Hello"]=>
+ string(5) "World"
+ ["Foo"]=>
+ string(3) "Bar"
+ ["Person"]=>
+ string(8) "John Doe"
+}
+"
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_006.phpt b/ext/curl/tests/curl_copy_handle_basic_006.phpt
new file mode 100644
index 0000000..defc0f2
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_006.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Test curl_copy_handle() with User Agent
+--CREDITS--
+Rick Buitenman <rick@meritos.nl>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ echo '*** Testing curl copy handle with User Agent ***' . "\n";
+
+ $url = "{$host}/get.php?test=useragent";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_USERAGENT, 'cURL phpt');
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $copy = curl_copy_handle($ch);
+
+ var_dump( curl_exec($ch) );
+ var_dump( curl_exec($copy) );
+
+ curl_close($ch); // can not close original handle before curl_exec($copy) since it causes char * inputs to be invalid (see also: http://curl.haxx.se/libcurl/c/curl_easy_duphandle.html)
+ curl_close($copy);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl copy handle with User Agent ***
+string(9) "cURL phpt"
+string(9) "cURL phpt"
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_007.phpt b/ext/curl/tests/curl_copy_handle_basic_007.phpt
new file mode 100644
index 0000000..aa7306c
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_007.phpt
@@ -0,0 +1,45 @@
+--TEST--
+Test curl_copy_handle() with simple POST
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ echo '*** Testing curl copy handle with simple POST using array as arguments ***' . "\n";
+
+ $url = "{$host}/get.php?test=getpost";
+ $ch = curl_init();
+
+ ob_start(); // start output buffering
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, array("Hello" => "World", "Foo" => "Bar", "Person" => "John Doe"));
+ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:')); // Disable Expect: header (lighttpd does not support it :)
+ curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+
+ $copy = curl_copy_handle($ch);
+ curl_close($ch);
+
+ $curl_content = curl_exec($copy);
+ curl_close($copy);
+
+ var_dump( $curl_content );
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl copy handle with simple POST using array as arguments ***
+string(163) "array(1) {
+ ["test"]=>
+ string(7) "getpost"
+}
+array(3) {
+ ["Hello"]=>
+ string(5) "World"
+ ["Foo"]=>
+ string(3) "Bar"
+ ["Person"]=>
+ string(8) "John Doe"
+}
+"
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_basic_008.phpt b/ext/curl/tests/curl_copy_handle_basic_008.phpt
new file mode 100644
index 0000000..692c2df
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_basic_008.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Test curl_copy_handle() with CURLOPT_PROGRESSFUNCTION
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+ $url = "{$host}/get.php";
+ $ch = curl_init($url);
+
+ curl_setopt($ch, CURLOPT_NOPROGRESS, 0);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function() { });
+ $ch2 = curl_copy_handle($ch);
+ echo curl_exec($ch), PHP_EOL;
+ unset($ch);
+ echo curl_exec($ch2);
+
+?>
+--EXPECTF--
+Hello World!
+Hello World!
+Hello World!
+Hello World!
diff --git a/ext/curl/tests/curl_copy_handle_variation1.phpt b/ext/curl/tests/curl_copy_handle_variation1.phpt
new file mode 100644
index 0000000..da45221
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_variation1.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Test curl_copy_handle() change options in one handle
+--CREDITS--
+Francesco Fullone ff@ideato.it
+#PHPTestFest Cesena Italia on 2009-06-20
+--SKIPIF--
+<?php
+ if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+?>
+--FILE--
+<?php
+echo "*** Testing curl_copy_handle(): basic ***\n";
+
+// create a new cURL resource
+$ch = curl_init();
+
+// set URL and other appropriate options
+curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/');
+
+// copy the handle
+$ch2 = curl_copy_handle($ch);
+
+// change the CURLOPT_URL for the second handle
+curl_setopt($ch2, CURLOPT_URL, 'http://www.bar.com/');
+
+var_dump(curl_getinfo($ch) === curl_getinfo($ch2));
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_copy_handle(): basic ***
+bool(false)
+===DONE===
diff --git a/ext/curl/tests/curl_copy_handle_variation2.phpt b/ext/curl/tests/curl_copy_handle_variation2.phpt
new file mode 100644
index 0000000..924bf6a
--- /dev/null
+++ b/ext/curl/tests/curl_copy_handle_variation2.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Test curl_copy_handle() add options to the handles
+--CREDITS--
+Francesco Fullone ff@ideato.it
+#PHPTestFest Cesena Italia on 2009-06-20
+--SKIPIF--
+<?php
+ if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+?>
+--COMMENT--
+the only way to test if a option is setten on a curl handle is using the curl_getinfo() function.
+but this can only check on a limited amount of options...
+--FILE--
+<?php
+echo "*** Testing curl_copy_handle(): add options after copy ***\n";
+
+// create a new cURL resource
+$ch = curl_init();
+
+// copy the handle
+$ch2 = curl_copy_handle($ch);
+var_dump(curl_getinfo($ch) === curl_getinfo($ch2));
+
+// add some CURLOPT to the second handle
+curl_setopt($ch2, CURLOPT_URL, 'http://www.example.com/');
+
+var_dump(curl_getinfo($ch) === curl_getinfo($ch2));
+
+// add same CURLOPT to the first handle
+curl_setopt($ch, CURLOPT_URL, 'http://www.example.com/');
+var_dump(curl_getinfo($ch) === curl_getinfo($ch2));
+
+// change a CURLOPT in the second handle
+curl_setopt($ch2, CURLOPT_URL, 'http://www.bar.com/');
+var_dump(curl_getinfo($ch) === curl_getinfo($ch2));
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_copy_handle(): add options after copy ***
+bool(true)
+bool(false)
+bool(true)
+bool(false)
+===DONE===
diff --git a/ext/curl/tests/curl_error_basic.phpt b/ext/curl/tests/curl_error_basic.phpt
new file mode 100644
index 0000000..3d35023
--- /dev/null
+++ b/ext/curl/tests/curl_error_basic.phpt
@@ -0,0 +1,41 @@
+--TEST--
+curl_error() function - basic test for curl_error using a fake url
+--CREDITS--
+Mattijs Hoitink mattijshoitink@gmail.com
+#Testfest Utrecht 2009
+--SKIPIF--
+<?php
+
+if (!extension_loaded("curl")) die("skip\n");
+
+$url = "fakeURL";
+$ip = gethostbyname($url);
+if ($ip != $url) die("skip 'fakeURL' resolves to $ip\n");
+
+?>
+--FILE--
+<?php
+/*
+ * Prototype: string curl_error(resource $ch)
+ * Description: Returns a clear text error message for the last cURL operation.
+ * Source: ext/curl/interface.c
+ * Documentation: http://wiki.php.net/qa/temp/ext/curl
+ */
+
+// Fake URL to trigger an error
+$url = "fakeURL";
+
+echo "== Testing curl_error with a fake URL ==\n";
+
+// cURL handler
+$ch = curl_init($url);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+curl_exec($ch);
+var_dump(curl_error($ch));
+curl_close($ch);
+
+?>
+--EXPECTF--
+== Testing curl_error with a fake URL ==
+string(%d) "%sfakeURL%S"
diff --git a/ext/curl/tests/curl_file_deleted_before_curl_close.phpt b/ext/curl/tests/curl_file_deleted_before_curl_close.phpt
new file mode 100644
index 0000000..592f110
--- /dev/null
+++ b/ext/curl/tests/curl_file_deleted_before_curl_close.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Memory corruption error if fp of just created file is closed before curl_close.
+--CREDITS--
+Alexey Shein <confik@gmail.com>
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip"; ?>
+--FILE--
+<?php
+
+$ch = curl_init(getenv('PHP_CURL_HTTP_REMOTE_SERVER'));
+
+$temp_file = dirname(__FILE__) . '/curl_file_deleted_before_curl_close.tmp';
+if (file_exists($temp_file)) {
+ unlink($temp_file); // file should not exist before test
+}
+
+$handle = fopen($temp_file, 'w');
+
+curl_setopt($ch, CURLOPT_STDERR, $handle);
+curl_setopt($ch, CURLOPT_VERBOSE, 1);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+curl_exec($ch);
+
+fclose($handle); // causes glibc memory error
+
+//unlink($temp_file); // uncomment to test segfault (file not found on iowrite.c)
+
+curl_close($ch);
+echo "Closed correctly\n";
+?>
+--CLEAN--
+<?php
+unlink(dirname(__FILE__) . '/curl_file_deleted_before_curl_close.tmp');
+?>
+--EXPECTF--
+* Closing connection #%d
+Closed correctly
diff --git a/ext/curl/tests/curl_ftp_pasv.phpt b/ext/curl/tests/curl_ftp_pasv.phpt
new file mode 100644
index 0000000..6cd7429
--- /dev/null
+++ b/ext/curl/tests/curl_ftp_pasv.phpt
@@ -0,0 +1,59 @@
+--TEST--
+Test curl_exec() function with basic functionality
+--CREDITS--
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_FTP_REMOTE_SERVER')) exit("skip PHP_CURL_FTP_REMOTE_SERVER env variable is not defined");
+if (false === getenv('PHP_CURL_FTP_REMOTE_USER')) exit("skip PHP_CURL_FTP_REMOTE_USER env variable is not defined");
+if (false === getenv('PHP_CURL_FTP_REMOTE_PASSWD')) exit("skip PHP_CURL_FTP_REMOTE_PASSWD env variable is not defined");
+?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_FTP_REMOTE_SERVER');
+ $username = getenv('PHP_CURL_FTP_REMOTE_USER');
+ $password = getenv('PHP_CURL_FTP_REMOTE_PASSWD');
+
+ // FTP this script to a server
+ $fp = fopen ( __FILE__ , "r" );
+ $url = "ftp://$username:$password@$host/test.phpt" ;
+
+ $ch = curl_init ();
+
+ // enable below to get the output in verbose mode.
+ // curl_setopt ( $ch , CURLOPT_VERBOSE, 1 );
+
+ /* Without enabling SKIP_PASV_IP flag, the following output will be seen..
+ < 227 Entering Passive Mode (10,5,80,146,100,199)
+ * Trying 10.5.80.146... * connected
+ * Connecting to 10.5.80.146 (10.5.80.146) port 25799
+ */
+
+ /* After enabling SKIP_PASV_IP flag, the following output will be seen..
+ < 227 Entering Passive Mode (10,5,80,146,50,229)
+ * Skips 10.5.80.146 for data connection, uses 10.5.80.146 instead
+ * Trying 10.5.80.146... * connected
+ */
+
+ curl_setopt ( $ch , CURLOPT_URL, $url );
+ curl_setopt ( $ch , CURLOPT_TRANSFERTEXT, 1 );
+
+ //force passive connection
+ curl_setopt ( $ch , CURLOPT_FTP_USE_EPSV, 0 );
+ curl_setopt ( $ch , CURLOPT_FTP_SKIP_PASV_IP, 1 );
+
+ // mark the file for upload..
+ curl_setopt ( $ch , CURLOPT_INFILE, $fp );
+ curl_setopt ( $ch , CURLOPT_INFILESIZE, filesize(__FILE__) );
+ curl_setopt ( $ch , CURLOPT_PUT, 1 );
+ curl_setopt ( $ch , CURLOPT_UPLOAD, 1 );
+
+ $result = curl_exec ( $ch );
+ var_dump ( $result );
+ curl_close ( $ch );
+
+?>
+===DONE===
+--EXPECTF--
+bool(true)
+===DONE===
diff --git a/ext/curl/tests/curl_multi_close_basic.phpt b/ext/curl/tests/curl_multi_close_basic.phpt
new file mode 100644
index 0000000..28865bc
--- /dev/null
+++ b/ext/curl/tests/curl_multi_close_basic.phpt
@@ -0,0 +1,19 @@
+--TEST--
+curl_multi_close
+--CREDITS--
+Stefan Koopmanschap <stefan@php.net>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip';
+?>
+--FILE--
+<?php
+$ch = curl_multi_init();
+curl_multi_close($ch);
+var_dump($ch);
+?>
+===DONE===
+--EXPECTF--
+resource(%d) of type (Unknown)
+===DONE===
diff --git a/ext/curl/tests/curl_multi_getcontent_basic3.phpt b/ext/curl/tests/curl_multi_getcontent_basic3.phpt
new file mode 100644
index 0000000..ac2a371
--- /dev/null
+++ b/ext/curl/tests/curl_multi_getcontent_basic3.phpt
@@ -0,0 +1,62 @@
+--TEST--
+Curl_multi_getcontent() basic test with different sources (local file/http)
+--CREDITS--
+Rein Velt (rein@velt.org)
+#TestFest Utrecht 20090509
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip need ext/curl';
+if (false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ exit("skip PHP_CURL_HTTP_REMOTE_SERVER env variable is not defined");
+}
+?>
+--FILE--
+<?php
+ //CURL_MULTI_GETCONTENT TEST
+
+ //CREATE RESOURCES
+ $ch1=curl_init();
+ $ch2=curl_init();
+
+ //SET URL AND OTHER OPTIONS
+ $host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+ curl_setopt($ch1, CURLOPT_URL, "{$host}/get.php?test=getpost&get_param=Hello%20World");
+ curl_setopt($ch2, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata2.txt");
+ curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
+
+ //CREATE MULTIPLE CURL HANDLE
+ $mh=curl_multi_init();
+
+ //ADD THE 2 HANDLES
+ curl_multi_add_handle($mh,$ch1);
+ curl_multi_add_handle($mh,$ch2);
+
+ //EXECUTE
+ $running=0;
+ do {
+ curl_multi_exec($mh,$running);
+ } while ($running>0);
+
+ $results1=curl_multi_getcontent($ch1);
+ $results2=curl_multi_getcontent($ch2);
+
+ //CLOSE
+ curl_multi_remove_handle($mh,$ch1);
+ curl_multi_remove_handle($mh,$ch2);
+ curl_multi_close($mh);
+
+ echo $results1;
+ echo $results2;
+
+?>
+--EXPECTF--
+array(2) {
+ ["test"]=>
+ string(7) "getpost"
+ ["get_param"]=>
+ string(11) "Hello World"
+}
+array(0) {
+}
+CURL2
diff --git a/ext/curl/tests/curl_multi_getcontent_error1.phpt b/ext/curl/tests/curl_multi_getcontent_error1.phpt
new file mode 100644
index 0000000..2fb11b3
--- /dev/null
+++ b/ext/curl/tests/curl_multi_getcontent_error1.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Curl_multi_getcontent() error test
+--CREDITS--
+Rein Velt (rein@velt.org)
+#TestFest Utrecht 20090509
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip';
+?>
+--FILE--
+<?php
+ //CURL_MULTI_GETCONTENT TEST
+
+ //CREATE RESOURCES
+ $ch1=curl_init();
+ $ch2=curl_init();
+
+ //SET URL AND OTHER OPTIONS
+ curl_setopt($ch1, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata1.txt");
+ curl_setopt($ch2, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata2.txt");
+ curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
+
+ //CREATE MULTIPLE CURL HANDLE
+ $mh=curl_multi_init();
+
+ //ADD THE 2 HANDLES
+ curl_multi_add_handle($mh,$ch1);
+ curl_multi_add_handle($mh,$ch2);
+
+ //EXECUTE
+ $running=0;
+ do {
+ curl_multi_exec($mh,$running);
+ } while ($running>0);
+
+ $results1=curl_multi_getcontent(); //no parameter
+ $results2=curl_multi_getcontent($ch2);
+
+ //CLOSE
+ curl_multi_remove_handle($mh,$ch1);
+ curl_multi_remove_handle($mh,$ch2);
+ curl_multi_close($mh);
+
+ echo $results1;
+ echo $results2;
+
+?>
+--EXPECTF--
+Warning: curl_multi_getcontent() expects exactly 1 parameter, 0 given in %s on line %d
+CURL2
diff --git a/ext/curl/tests/curl_multi_getcontent_error2.phpt b/ext/curl/tests/curl_multi_getcontent_error2.phpt
new file mode 100644
index 0000000..0145d6a
--- /dev/null
+++ b/ext/curl/tests/curl_multi_getcontent_error2.phpt
@@ -0,0 +1,51 @@
+--TEST--
+Curl_multi_getcontent() error test
+--CREDITS--
+Rein Velt (rein@velt.org)
+#TestFest Utrecht 20090509
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip';
+?>
+--FILE--
+<?php
+ //CURL_MULTI_GETCONTENT TEST
+
+ //CREATE RESOURCES
+ $ch1=curl_init();
+ $ch2=curl_init();
+
+ //SET URL AND OTHER OPTIONS
+ curl_setopt($ch1, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata1.txt");
+ curl_setopt($ch2, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata2.txt");
+ curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
+
+ //CREATE MULTIPLE CURL HANDLE
+ $mh=curl_multi_init();
+
+ //ADD THE 2 HANDLES
+ curl_multi_add_handle($mh,$ch1);
+ curl_multi_add_handle($mh,$ch2);
+
+ //EXECUTE
+ $running=0;
+ do {
+ curl_multi_exec($mh,$running);
+ } while ($running>0);
+
+ $results1=curl_multi_getcontent($ch1,$ch2); //no parameter
+ $results2=curl_multi_getcontent($ch2);
+
+ //CLOSE
+ curl_multi_remove_handle($mh,$ch1);
+ curl_multi_remove_handle($mh,$ch2);
+ curl_multi_close($mh);
+
+ echo $results1;
+ echo $results2;
+
+?>
+--EXPECTF--
+Warning: curl_multi_getcontent() expects exactly 1 parameter, 2 given in %s on line %d
+CURL2
diff --git a/ext/curl/tests/curl_multi_getcontent_error3.phpt b/ext/curl/tests/curl_multi_getcontent_error3.phpt
new file mode 100644
index 0000000..2ad1480
--- /dev/null
+++ b/ext/curl/tests/curl_multi_getcontent_error3.phpt
@@ -0,0 +1,53 @@
+--TEST--
+Curl_multi_getcontent() error test
+--CREDITS--
+Rein Velt (rein@velt.org)
+#TestFest Utrecht 20090509
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip';
+?>
+--FILE--
+<?php
+ //CURL_MULTI_GETCONTENT TEST
+
+ //CREATE RESOURCES
+ $ch1=curl_init();
+ $ch2=curl_init();
+
+ //SET URL AND OTHER OPTIONS
+ curl_setopt($ch1, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata1.txt");
+ curl_setopt($ch2, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata2.txt");
+ curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
+
+ //CREATE MULTIPLE CURL HANDLE
+ $mh=curl_multi_init();
+
+ //ADD THE 2 HANDLES
+ curl_multi_add_handle($mh,$ch1);
+ curl_multi_add_handle($mh,$ch2);
+
+ //EXECUTE
+ $running=0;
+ do {
+ curl_multi_exec($mh,$running);
+ } while ($running>0);
+
+ $ch1="string";
+
+ $results1=curl_multi_getcontent($ch1); //incorrect parameter type
+ $results2=curl_multi_getcontent($ch2);
+
+ //CLOSE
+ //curl_multi_remove_handle($mh,$ch1);
+ curl_multi_remove_handle($mh,$ch2);
+ curl_multi_close($mh);
+
+ echo $results1;
+ echo $results2;
+
+?>
+--EXPECTF--
+Warning: curl_multi_getcontent() expects parameter 1 to be resource, %unicode_string_optional% given in %s on line %d
+CURL2
diff --git a/ext/curl/tests/curl_multi_getcontent_error4.phpt b/ext/curl/tests/curl_multi_getcontent_error4.phpt
new file mode 100644
index 0000000..68bda37
--- /dev/null
+++ b/ext/curl/tests/curl_multi_getcontent_error4.phpt
@@ -0,0 +1,66 @@
+--TEST--
+Curl_multi_getcontent() error test with undefined handle
+--CREDITS--
+Rein Velt (rein@velt.org)
+#TestFest Utrecht 20090509
+--SKIPIF--
+<?php
+if (!extension_loaded('curl')) print 'skip';
+?>
+--FILE--
+<?php
+ //CURL_MULTI_GETCONTENT TEST
+
+ //CREATE RESOURCES
+ //$ch1=undefined;
+ $ch2=curl_init();
+
+ //SET URL AND OTHER OPTIONS
+ curl_setopt($ch1, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata1.txt");
+ curl_setopt($ch2, CURLOPT_URL, "file://".dirname(__FILE__). DIRECTORY_SEPARATOR . "curl_testdata2.txt");
+ curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
+
+ //CREATE MULTIPLE CURL HANDLE
+ $mh=curl_multi_init();
+
+ //ADD THE 2 HANDLES
+ curl_multi_add_handle($mh,$ch1);
+ curl_multi_add_handle($mh,$ch2);
+
+ //EXECUTE
+ $running=0;
+ do {
+ curl_multi_exec($mh,$running);
+ } while ($running>0);
+
+
+ $results1=curl_multi_getcontent($ch1); //incorrect parameter type
+ $results2=curl_multi_getcontent($ch2);
+
+ //CLOSE
+ //curl_multi_remove_handle($mh,$ch1);
+ curl_multi_remove_handle($mh,$ch2);
+ curl_multi_close($mh);
+
+ echo $results1;
+ echo $results2;
+
+?>
+--EXPECTF--
+Notice: Undefined variable: ch1 in %s on line %d
+
+Warning: curl_setopt() expects parameter 1 to be resource, null given in %s on line %d
+
+Notice: Undefined variable: ch1 in %s on line %d
+
+Warning: curl_setopt() expects parameter 1 to be resource, null given in %s on line %d
+
+Notice: Undefined variable: ch1 in %s on line %d
+
+Warning: curl_multi_add_handle() expects parameter 2 to be resource, null given in %s on line %d
+
+Notice: Undefined variable: ch1 in %s on line %d
+
+Warning: curl_multi_getcontent() expects parameter 1 to be resource, null given in %s on line %d
+CURL2
diff --git a/ext/curl/tests/curl_multi_init_basic.phpt b/ext/curl/tests/curl_multi_init_basic.phpt
new file mode 100644
index 0000000..0fd865d
--- /dev/null
+++ b/ext/curl/tests/curl_multi_init_basic.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Test curl_multi_init()
+--CREDITS--
+Mark van der Velden
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+/* Prototype : resource curl_multi_init(void)
+ * Description : Returns a new cURL multi handle
+ * Source code : ext/curl/multi.c
+ * Test documentation: http://wiki.php.net/qa/temp/ext/curl
+ */
+
+// start testing
+echo "*** Testing curl_multi_init(void); ***\n";
+
+//create the multiple cURL handle
+$mh = curl_multi_init();
+var_dump($mh);
+
+curl_multi_close($mh);
+var_dump($mh);
+?>
+===DONE===
+--EXPECTF--
+*** Testing curl_multi_init(void); ***
+resource(%d) of type (curl_multi)
+resource(%d) of type (Unknown)
+===DONE===
diff --git a/ext/curl/tests/curl_multi_segfault.phpt b/ext/curl/tests/curl_multi_segfault.phpt
new file mode 100644
index 0000000..dde8189
--- /dev/null
+++ b/ext/curl/tests/curl_multi_segfault.phpt
@@ -0,0 +1,56 @@
+--TEST--
+Segfault due to libcurl connection caching
+--CREDITS--
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) exit("skip curl extension not loaded");
+if (false === getenv('PHP_CURL_FTP_REMOTE_SERVER')) exit("skip PHP_CURL_FTP_REMOTE_SERVER env variable is not defined");
+if (false === getenv('PHP_CURL_FTP_REMOTE_USER')) exit("skip PHP_CURL_FTP_REMOTE_USER env variable is not defined");
+if (false === getenv('PHP_CURL_FTP_REMOTE_PASSWD')) exit("skip PHP_CURL_FTP_REMOTE_PASSWD env variable is not defined");
+?>
+--FILE--
+<?php
+ $host = getenv('PHP_CURL_FTP_REMOTE_SERVER');
+ $username = getenv('PHP_CURL_FTP_REMOTE_USER');
+ $password = getenv('PHP_CURL_FTP_REMOTE_PASSWD');
+
+ // FTP this script to a server
+ $fp = fopen ( __FILE__ , "r" );
+ $url = "ftp://$username:$password@$host/" ;
+
+ $ch = curl_init ();
+
+ curl_setopt ( $ch , CURLOPT_URL, $url );
+ curl_setopt ( $ch , CURLOPT_RETURNTRANSFER, 1 );
+
+ //force passive connection
+ curl_setopt ( $ch , CURLOPT_FTP_USE_EPSV, 0 );
+ curl_setopt ( $ch , CURLOPT_FTP_SKIP_PASV_IP, 1 );
+
+ $cmh = curl_multi_init();
+ curl_multi_add_handle($cmh, $ch);
+
+ $active = null;
+
+ do {
+ $mrc = curl_multi_exec($cmh, $active);
+ } while ($mrc == CURLM_CALL_MULTI_PERFORM);
+
+
+ while ($active && $mrc == CURLM_OK) {
+ if (curl_multi_select($cmh) != -1) {
+ do {
+ $mrc = curl_multi_exec($cmh, $active);
+ } while ($mrc == CURLM_CALL_MULTI_PERFORM);
+ }
+ }
+
+ var_dump(is_string(curl_multi_getcontent($ch)));
+ curl_multi_remove_handle($cmh, $ch);
+ curl_close($ch);
+ curl_multi_close($cmh);
+?>
+===DONE===
+--EXPECTF--
+bool(true)
+===DONE===
diff --git a/ext/curl/tests/curl_multi_select_basic1.phpt b/ext/curl/tests/curl_multi_select_basic1.phpt
new file mode 100644
index 0000000..7ae8124
--- /dev/null
+++ b/ext/curl/tests/curl_multi_select_basic1.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Test curl_multi_select()
+--CREDITS--
+Ivo Jansch <ivo@ibuildings.com>
+#testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+/* Prototype : resource curl_multi_select($mh, $timeout=1.0])
+ * Description : Get all the sockets associated with the cURL extension, which can then be
+ * "selected"
+ * Source code : ?
+ * Test documentation: http://wiki.php.net/qa/temp/ext/curl
+ */
+
+
+//create the multiple cURL handle
+$mh = curl_multi_init();
+echo curl_multi_select($mh)."\n";
+
+curl_multi_close($mh);
+?>
+===DONE===
+--EXPECTF--
+%r(0|-1)%r
+===DONE===
diff --git a/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt
new file mode 100644
index 0000000..7a778f3
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_CURLOPT_FOLLOWLOCATION_open_basedir.phpt
@@ -0,0 +1,22 @@
+--TEST--
+CURLOPT_FOLLOWLOCATION case check open_basedir
+--CREDITS--
+WHITE new media architects - Dennis
+--INI--
+open_basedir = DIRECTORY_SEPARATOR."tmp";
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) print "skip cURL not loaded";
+?>
+--FILE--
+<?php
+print (ini_get("OPEN_BASEDIR"));
+$ch = curl_init();
+$succes = curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
+curl_close($ch);
+var_dump($succes);
+?>
+--EXPECTF--
+Warning: curl_setopt(): CURLOPT_FOLLOWLOCATION cannot be activated when an open_basedir is set in %s.php on line %d
+bool(false)
+
diff --git a/ext/curl/tests/curl_setopt_CURLOPT_READFUNCTION.phpt b/ext/curl/tests/curl_setopt_CURLOPT_READFUNCTION.phpt
new file mode 100644
index 0000000..9de2c0f
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_CURLOPT_READFUNCTION.phpt
@@ -0,0 +1,54 @@
+--TEST--
+cURL option CURLOPT_READFUNCTION
+--CREDITS--
+WHITE new media architects - Jeroen Vermeulen
+#testfest Utrecht 2009
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) print "skip cURL extension not loaded";
+?>
+--FILE--
+<?php
+function custom_readfunction($oCurl, $hReadHandle, $iMaxOut)
+{
+ $sData = fread($hReadHandle,$iMaxOut-10); # -10 to have space to add "custom:"
+ if (!empty($sData))
+ {
+ $sData = "custom:".$sData;
+ }
+ return $sData;
+}
+
+$sFileBase = dirname(__FILE__).DIRECTORY_SEPARATOR.'curl_opt_CURLOPT_READFUNCTION';
+$sReadFile = $sFileBase.'_in.tmp';
+$sWriteFile = $sFileBase.'_out.tmp';
+$sWriteUrl = 'file://'.$sWriteFile;
+
+file_put_contents($sReadFile,'contents of tempfile');
+$hReadHandle = fopen($sReadFile, 'r');
+
+$oCurl = curl_init();
+curl_setopt($oCurl, CURLOPT_URL, $sWriteUrl);
+curl_setopt($oCurl, CURLOPT_UPLOAD, 1);
+curl_setopt($oCurl, CURLOPT_READFUNCTION, "custom_readfunction" );
+curl_setopt($oCurl, CURLOPT_INFILE, $hReadHandle );
+curl_exec($oCurl);
+curl_close($oCurl);
+
+fclose ($hReadHandle);
+
+$sOutput = file_get_contents($sWriteFile);
+var_dump($sOutput);
+?>
+===DONE===
+--CLEAN--
+<?php
+$sFileBase = dirname(__FILE__).DIRECTORY_SEPARATOR.'curl_opt_CURLOPT_READFUNCTION';
+$sReadFile = $sFileBase.'_in.tmp';
+$sWriteFile = $sFileBase.'_out.tmp';
+unlink($sReadFile);
+unlink($sWriteFile);
+?>
+--EXPECT--
+string(27) "custom:contents of tempfile"
+===DONE===
diff --git a/ext/curl/tests/curl_setopt_array_basic.phpt b/ext/curl/tests/curl_setopt_array_basic.phpt
new file mode 100644
index 0000000..427de7f
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_array_basic.phpt
@@ -0,0 +1,56 @@
+--TEST--
+curl_setopt_array() function - tests setting multiple cURL options with curl_setopt_array()
+--CREDITS--
+Mattijs Hoitink mattijshoitink@gmail.com
+#Testfest Utrecht 2009
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+/*
+ * Prototype: bool curl_setopt_array(resource $ch, array $options)
+ * Description: Sets multiple options for a cURL session.
+ * Source: ext/curl/interface.c
+ * Documentation: http://wiki.php.net/qa/temp/ext/curl
+ */
+
+// Figure out what handler to use
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+if (!empty($host)) {
+ // Use the set Environment variable
+ $url = "{$host}/get.php?test=get";
+} else {
+ // Create a temporary file for the test
+ $tempname = tempnam(sys_get_temp_dir(), 'CURL_HANDLE');
+ $url = 'file://'. $tempname;
+ // add the test data to the file
+ file_put_contents($tempname, "Hello World!\nHello World!");
+}
+
+// Start the test
+echo '== Starting test curl_setopt_array($ch, $options); ==' . "\n";
+
+// curl handler
+$ch = curl_init();
+
+// options for the curl handler
+$options = array (
+ CURLOPT_URL => $url,
+ CURLOPT_RETURNTRANSFER => 1
+);
+
+ob_start(); // start output buffering
+
+curl_setopt_array($ch, $options);
+$returnContent = curl_exec($ch);
+curl_close($ch);
+
+var_dump($returnContent);
+isset($tempname) and is_file($tempname) and @unlink($tempname);
+
+?>
+--EXPECT--
+== Starting test curl_setopt_array($ch, $options); ==
+string(25) "Hello World!
+Hello World!"
+
diff --git a/ext/curl/tests/curl_setopt_basic002.phpt b/ext/curl/tests/curl_setopt_basic002.phpt
new file mode 100644
index 0000000..d90ecb7
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_basic002.phpt
@@ -0,0 +1,52 @@
+--TEST--
+curl_setopt basic tests with CURLOPT_STDERR.
+--CREDITS--
+Paul Sohier
+#phptestfest utrecht
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+// start testing
+echo "*** Testing curl_setopt with CURLOPT_STDERR\n";
+
+$temp_file = tempnam(sys_get_temp_dir(), 'CURL_STDERR');
+
+$handle = fopen($temp_file, 'w');
+
+$url = "{$host}/";
+$ch = curl_init();
+
+curl_setopt($ch, CURLOPT_VERBOSE, 1);
+curl_setopt($ch, CURLOPT_STDERR, $handle);
+$curl_content = curl_exec($ch);
+
+fclose($handle);
+unset($handle);
+var_dump(preg_replace('/[\r\n]/', ' ', file_get_contents($temp_file)));
+@unlink($temp_file);
+
+ob_start(); // start output buffering
+$handle = fopen($temp_file, 'w');
+curl_setopt($ch, CURLOPT_URL, $url); //set the url we want to use
+curl_setopt($ch, CURLOPT_STDERR, $handle);
+$data = curl_exec($ch);
+ob_end_clean();
+
+fclose($handle);
+unset($handle);
+var_dump(preg_replace('/[\r\n]/', ' ', file_get_contents($temp_file)));
+@unlink($temp_file);
+
+curl_close($ch);
+
+?>
+--EXPECTF--
+*** Testing curl_setopt with CURLOPT_STDERR
+string(%d) "%S"
+string(%d) "%S"
+* Closing connection #%d
+
diff --git a/ext/curl/tests/curl_setopt_basic003.phpt b/ext/curl/tests/curl_setopt_basic003.phpt
new file mode 100644
index 0000000..7849140
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_basic003.phpt
@@ -0,0 +1,43 @@
+--TEST--
+curl_setopt() call with CURLOPT_HTTPHEADER
+--CREDITS--
+Paul Sohier
+#phptestfest utrecht
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+// start testing
+echo "*** curl_setopt() call with CURLOPT_HTTPHEADER\n";
+
+$url = "{$host}/";
+$ch = curl_init();
+
+curl_setopt($ch, CURLOPT_HTTPHEADER, 1);
+
+$curl_content = curl_exec($ch);
+curl_close($ch);
+
+var_dump( $curl_content );
+
+$ch = curl_init();
+
+ob_start(); // start output buffering
+curl_setopt($ch, CURLOPT_HTTPHEADER, array());
+curl_setopt($ch, CURLOPT_URL, $host);
+
+$curl_content = curl_exec($ch);
+ob_end_clean();
+curl_close($ch);
+
+var_dump( $curl_content );
+?>
+--EXPECTF--
+*** curl_setopt() call with CURLOPT_HTTPHEADER
+
+Warning: curl_setopt(): You must pass either an object or an array with the CURLOPT_HTTPHEADER, CURLOPT_QUOTE, CURLOPT_HTTP200ALIASES and CURLOPT_POSTQUOTE arguments in %s on line %d
+bool(false)
+bool(true)
diff --git a/ext/curl/tests/curl_setopt_basic004.phpt b/ext/curl/tests/curl_setopt_basic004.phpt
new file mode 100644
index 0000000..97b4115
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_basic004.phpt
@@ -0,0 +1,44 @@
+--TEST--
+curl_setopt() call with CURLOPT_RETURNTRANSFER
+--CREDITS--
+Paul Sohier
+#phptestfest utrecht
+--SKIPIF--
+<?php if (!extension_loaded("curl") || false === getenv('PHP_CURL_HTTP_REMOTE_SERVER')) print "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable"; ?>
+--FILE--
+<?php
+
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+// start testing
+echo "*** curl_setopt() call with CURLOPT_RETURNTRANSFER set to 1\n";
+
+$url = "{$host}/";
+$ch = curl_init();
+
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_URL, $url);
+
+$curl_content = curl_exec($ch);
+curl_close($ch);
+
+var_dump( $curl_content );
+
+echo "*** curl_setopt() call with CURLOPT_RETURNTRANSFER set to 0\n";
+
+$ch = curl_init();
+
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
+curl_setopt($ch, CURLOPT_URL, $url);
+ob_start();
+$curl_content = curl_exec($ch);
+ob_end_clean();
+curl_close($ch);
+
+var_dump( $curl_content );
+?>
+--EXPECTF--
+*** curl_setopt() call with CURLOPT_RETURNTRANSFER set to 1
+string(%d) "%a"
+*** curl_setopt() call with CURLOPT_RETURNTRANSFER set to 0
+bool(true)
diff --git a/ext/curl/tests/curl_setopt_error.phpt b/ext/curl/tests/curl_setopt_error.phpt
new file mode 100644
index 0000000..ad73318
--- /dev/null
+++ b/ext/curl/tests/curl_setopt_error.phpt
@@ -0,0 +1,45 @@
+--TEST--
+curl_setopt() basic parameter test
+--CREDITS--
+Paul Sohier
+#phptestfest utrecht
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+echo "*** curl_setopt() call with incorrect parameters\n";
+$ch = curl_init();
+curl_setopt();
+curl_setopt(false);
+
+curl_setopt($ch);
+curl_setopt($ch, false);
+curl_setopt($ch, -1);
+curl_setopt($ch, '');
+curl_setopt($ch, 1, false);
+
+curl_setopt(false, false, false);
+curl_setopt($ch, '', false);
+curl_setopt($ch, 1, '');
+curl_setopt($ch, -1, 0);
+?>
+--EXPECTF--
+*** curl_setopt() call with incorrect parameters
+
+Warning: curl_setopt() expects exactly 3 parameters, 0 given in %s on line %d
+
+Warning: curl_setopt() expects exactly 3 parameters, 1 given in %s on line %d
+
+Warning: curl_setopt() expects exactly 3 parameters, 1 given in %s on line %d
+
+Warning: curl_setopt() expects exactly 3 parameters, 2 given in %s on line %d
+
+Warning: curl_setopt() expects exactly 3 parameters, 2 given in %s on line %d
+
+Warning: curl_setopt() expects exactly 3 parameters, 2 given in %s on line %d
+
+Warning: curl_setopt() expects parameter 1 to be resource, boolean given in %s on line %d
+
+Warning: curl_setopt() expects parameter 2 to be long, %unicode_string_optional% given in %s on line %d
+
+Warning: curl_setopt(): Invalid curl configuration option in %scurl_setopt_error.php on line %d
diff --git a/ext/curl/tests/curl_testdata1.txt b/ext/curl/tests/curl_testdata1.txt
new file mode 100644
index 0000000..dc1e446
--- /dev/null
+++ b/ext/curl/tests/curl_testdata1.txt
@@ -0,0 +1 @@
+CURL1
diff --git a/ext/curl/tests/curl_testdata2.txt b/ext/curl/tests/curl_testdata2.txt
new file mode 100644
index 0000000..3b9f76f
--- /dev/null
+++ b/ext/curl/tests/curl_testdata2.txt
@@ -0,0 +1 @@
+CURL2
diff --git a/ext/curl/tests/curl_version_error.phpt b/ext/curl/tests/curl_version_error.phpt
new file mode 100644
index 0000000..fb4793a
--- /dev/null
+++ b/ext/curl/tests/curl_version_error.phpt
@@ -0,0 +1,35 @@
+--TEST--
+Test curl_version() function : error conditions
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ die('skip - curl extension not available in this build');
+}
+if (!getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ echo "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable";
+}
+?>
+--FILE--
+<?php
+
+/* Prototype : array curl_version ([ int $age ] )
+ * Description: Returns information about the cURL version.
+ * Source code: ext/curl/interface.c
+*/
+
+echo "*** Testing curl_version() : error conditions ***\n";
+
+echo "\n-- Testing curl_version() function with more than expected no. of arguments --\n";
+$extra_arg = 10;
+var_dump( curl_version(1, $extra_arg) );
+
+?>
+===Done===
+--EXPECTF--
+*** Testing curl_version() : error conditions ***
+
+-- Testing curl_version() function with more than expected no. of arguments --
+
+Warning: curl_version() expects at most 1 parameter, 2 given in %s on line %d
+NULL
+===Done===
diff --git a/ext/curl/tests/curl_version_variation1.phpt b/ext/curl/tests/curl_version_variation1.phpt
new file mode 100644
index 0000000..cd912c4
--- /dev/null
+++ b/ext/curl/tests/curl_version_variation1.phpt
@@ -0,0 +1,165 @@
+--TEST--
+Test curl_version() function : usage variations - test values for $ascii argument
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ echo "skip - curl extension not available in this build";
+}
+if (!getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ echo "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable";
+}
+?>
+--FILE--
+<?php
+
+/* Prototype : array curl_version ([ int $age ] )
+ * Description: Returns information about the cURL version.
+ * Source code: ext/curl/interface.c
+*/
+
+echo "*** Testing curl_version() function: with unexpected inputs for 'age' argument ***\n";
+
+//get an unset variable
+$unset_var = 'string_val';
+unset($unset_var);
+
+//defining a class
+class sample {
+ public function __toString() {
+ return "sample object";
+ }
+}
+
+//getting the resource
+$file_handle = fopen(__FILE__, "r");
+
+// array with different values for $input
+$inputs = array (
+
+ // integer values
+ 0,
+ 1,
+ 255,
+ 256,
+ PHP_INT_MAX,
+ -PHP_INT_MAX,
+
+ // float values
+ 10.5,
+ -20.5,
+ 10.1234567e10,
+
+ // array values
+ array(),
+ array(0),
+ array(1, 2),
+
+ //string values
+ "ABC",
+ 'abc',
+ "2abc",
+
+ // boolean values
+ true,
+ false,
+ TRUE,
+ FALSE,
+
+ // null values
+ NULL,
+ null,
+
+ // objects
+ new sample(),
+
+ // resource
+ $file_handle,
+
+ // undefined variable
+ @$undefined_var,
+
+ // unset variable
+ @$unset_var
+);
+
+// loop through with each element of the $inputs array to test curl_version() function
+$count = 1;
+foreach($inputs as $input) {
+ echo "-- Iteration $count --\n";
+ var_dump( is_array(curl_version($input)) );
+ $count ++;
+}
+
+fclose($file_handle); //closing the file handle
+
+?>
+===Done===
+--EXPECTF--
+*** Testing curl_version() function: with unexpected inputs for 'age' argument ***
+-- Iteration 1 --
+bool(true)
+-- Iteration 2 --
+bool(true)
+-- Iteration 3 --
+bool(true)
+-- Iteration 4 --
+bool(true)
+-- Iteration 5 --
+bool(true)
+-- Iteration 6 --
+bool(true)
+-- Iteration 7 --
+bool(true)
+-- Iteration 8 --
+bool(true)
+-- Iteration 9 --
+bool(true)
+-- Iteration 10 --
+
+Warning: curl_version() expects parameter 1 to be long, array given in %s on line %d
+bool(false)
+-- Iteration 11 --
+
+Warning: curl_version() expects parameter 1 to be long, array given in %s on line %d
+bool(false)
+-- Iteration 12 --
+
+Warning: curl_version() expects parameter 1 to be long, array given in %s on line %d
+bool(false)
+-- Iteration 13 --
+
+Warning: curl_version() expects parameter 1 to be long, string given in %s on line %d
+bool(false)
+-- Iteration 14 --
+
+Warning: curl_version() expects parameter 1 to be long, string given in %s on line %d
+bool(false)
+-- Iteration 15 --
+
+Notice: A non well formed numeric value encountered in %s on line %d
+bool(true)
+-- Iteration 16 --
+bool(true)
+-- Iteration 17 --
+bool(true)
+-- Iteration 18 --
+bool(true)
+-- Iteration 19 --
+bool(true)
+-- Iteration 20 --
+bool(true)
+-- Iteration 21 --
+bool(true)
+-- Iteration 22 --
+
+Warning: curl_version() expects parameter 1 to be long, object given in %s on line %d
+bool(false)
+-- Iteration 23 --
+
+Warning: curl_version() expects parameter 1 to be long, resource given in %s on line %d
+bool(false)
+-- Iteration 24 --
+bool(true)
+-- Iteration 25 --
+bool(true)
+===Done===
diff --git a/ext/curl/tests/curl_write_callback.phpt b/ext/curl/tests/curl_write_callback.phpt
new file mode 100644
index 0000000..c0b733e
--- /dev/null
+++ b/ext/curl/tests/curl_write_callback.phpt
@@ -0,0 +1,36 @@
+--TEST--
+Test curl option CURLOPT_WRITEFUNCTION
+--CREDITS--
+Mathieu Kooiman <mathieuk@gmail.com>
+Dutch UG, TestFest 2009, Utrecht
+--DESCRIPTION--
+Writes the value 'test' to a temporary file. Use curl to access this file, passing the output into a callback. Tests the PHP_CURL_USER case in curl_write.
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+
+function curl_callback($curl_handle, $received_data)
+{
+ echo $received_data;
+ return strlen($received_data);
+}
+
+$log_file = tempnam(sys_get_temp_dir(), 'php-curl-test');
+
+$fp = fopen($log_file, 'w+');
+fwrite($fp, "test");
+fclose($fp);
+
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'curl_callback');
+curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file);
+curl_exec($ch);
+curl_close($ch);
+
+// cleanup
+unlink($log_file);
+
+?>
+--EXPECT--
+test
diff --git a/ext/curl/tests/curl_write_file.phpt b/ext/curl/tests/curl_write_file.phpt
new file mode 100644
index 0000000..95d2b0e
--- /dev/null
+++ b/ext/curl/tests/curl_write_file.phpt
@@ -0,0 +1,38 @@
+--TEST--
+Test curl option CURLOPT_FILE
+--CREDITS--
+Mathieu Kooiman <mathieuk@gmail.com>
+Dutch UG, TestFest 2009, Utrecht
+--DESCRIPTION--
+Writes the value 'test' to a temporary file. Use curl to access this file and store the output in another temporary file. Tests the PHP_CURL_FILE case in curl_write().
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+
+$test_file = tempnam(sys_get_temp_dir(), 'php-curl-test');
+$log_file = tempnam(sys_get_temp_dir(), 'php-curl-test');
+
+$fp = fopen($log_file, 'w+');
+fwrite($fp, "test");
+fclose($fp);
+
+$testfile_fp = fopen($test_file, 'w+');
+
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_FILE, $testfile_fp);
+curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file);
+curl_exec($ch);
+curl_close($ch);
+
+fclose($testfile_fp);
+
+echo file_get_contents($test_file);
+
+// cleanup
+unlink($test_file);
+unlink($log_file);
+
+?>
+--EXPECT--
+test
diff --git a/ext/curl/tests/curl_write_return.phpt b/ext/curl/tests/curl_write_return.phpt
new file mode 100644
index 0000000..1ddc551
--- /dev/null
+++ b/ext/curl/tests/curl_write_return.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Test curl option CURLOPT_RETURNTRANSFER
+--CREDITS--
+Mathieu Kooiman <mathieuk@gmail.com>
+Dutch UG, TestFest 2009, Utrecht
+--DESCRIPTION--
+Writes the value 'test' to a temporary file. Use curl to access this file and have it return the content from curl_exec(). Tests the PHP_CURL_RETURN case
+of curl_write().
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+
+$log_file = tempnam(sys_get_temp_dir(), 'php-curl-test');
+
+$fp = fopen($log_file, 'w+');
+fwrite($fp, "test");
+fclose($fp);
+
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file);
+$result = curl_exec($ch);
+curl_close($ch);
+
+echo $result;
+
+// cleanup
+unlink($log_file);
+
+?>
+--EXPECT--
+test
diff --git a/ext/curl/tests/curl_write_stdout.phpt b/ext/curl/tests/curl_write_stdout.phpt
new file mode 100644
index 0000000..893b27e
--- /dev/null
+++ b/ext/curl/tests/curl_write_stdout.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test curl option CURLOPT_FILE with STDOUT handle
+--CREDITS--
+Mathieu Kooiman <mathieuk@gmail.com>
+Dutch UG, TestFest 2009, Utrecht
+--DESCRIPTION--
+Writes the value 'test' to a temporary file. Use curl to access this file and store the output in another temporary file. Tests the PHP_CURL_FILE case in curl_write().
+--SKIPIF--
+<?php if (!extension_loaded("curl")) print "skip"; ?>
+--FILE--
+<?php
+
+$log_file = tempnam(sys_get_temp_dir(), 'php-curl-test');
+
+$fp = fopen($log_file, 'w+');
+fwrite($fp, "test");
+fclose($fp);
+
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_FILE, STDOUT);
+curl_setopt($ch, CURLOPT_URL, 'file://' . $log_file);
+curl_exec($ch);
+curl_close($ch);
+
+// cleanup
+unlink($log_file);
+
+?>
+--EXPECT--
+test
diff --git a/ext/curl/tests/curl_writeheader_callback.phpt b/ext/curl/tests/curl_writeheader_callback.phpt
new file mode 100644
index 0000000..fa27363
--- /dev/null
+++ b/ext/curl/tests/curl_writeheader_callback.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Test curl option CURLOPT_HEADERFUNCTION
+--CREDITS--
+Mathieu Kooiman <mathieuk@gmail.com>
+Dutch UG, TestFest 2009, Utrecht
+--DESCRIPTION--
+Hit the host identified by PHP_CURL_HTTP_REMOTE_SERVER and determine that the headers are sent to the callback specified for CURLOPT_HEADERFUNCTION. Different test servers specified for PHP_CURL_HTTP_REMOTE_SERVER might return different sets of headers. Just test for HTTP/1.1 200 OK.
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ echo "skip - curl extension not available in this build";
+}
+if (!getenv('PHP_CURL_HTTP_REMOTE_SERVER')) {
+ echo "skip need PHP_CURL_HTTP_REMOTE_SERVER environment variable";
+}
+?>
+--FILE--
+<?php
+
+function curl_header_callback($curl_handle, $data)
+{
+ if (strtolower(substr($data,0, 4)) == 'http')
+ echo $data;
+}
+
+$host = getenv('PHP_CURL_HTTP_REMOTE_SERVER');
+
+$ch = curl_init();
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'curl_header_callback');
+curl_setopt($ch, CURLOPT_URL, $host);
+curl_exec($ch);
+curl_close($ch);
+
+?>
+--EXPECTF--
+HTTP/1.1 %d %s
diff --git a/ext/curl/tests/responder/get.php b/ext/curl/tests/responder/get.php
new file mode 100644
index 0000000..9e13d6a
--- /dev/null
+++ b/ext/curl/tests/responder/get.php
@@ -0,0 +1,39 @@
+<?php
+ $test = isset($_GET['test']) ? $_GET['test'] : null;
+ switch($test) {
+ case 'post':
+ var_dump($_POST);
+ break;
+ case 'getpost':
+ var_dump($_GET);
+ var_dump($_POST);
+ break;
+ case 'referer':
+ echo $_SERVER['HTTP_REFERER'];
+ break;
+ case 'useragent':
+ echo $_SERVER['HTTP_USER_AGENT'];
+ break;
+ case 'httpversion':
+ echo $_SERVER['SERVER_PROTOCOL'];
+ break;
+ case 'cookie':
+ echo $_COOKIE['foo'];
+ break;
+ case 'encoding':
+ echo $_SERVER['HTTP_ACCEPT_ENCODING'];
+ break;
+ case 'contenttype':
+ header('Content-Type: text/plain;charset=utf-8');
+ break;
+ case 'file':
+ if (isset($_FILES['file'])) {
+ echo $_FILES['file']['name'] . '|' . $_FILES['file']['type'];
+ }
+ break;
+ default:
+ echo "Hello World!\n";
+ echo "Hello World!";
+ break;
+ }
+?>