-CURL
+cURL
Sterling Hughes
dnl
-dnl $Id$
+dnl $Id$
dnl
PHP_ARG_WITH(curl, for CURL support,
fi
CURL_CONFIG="curl-config"
- AC_MSG_CHECKING(for cURL 7.9.8 or greater)
+ AC_MSG_CHECKING(for cURL 7.10.2 or greater)
if ${CURL_DIR}/bin/curl-config --libs print > /dev/null 2>&1; then
CURL_CONFIG=${CURL_DIR}/bin/curl-config
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 7009008; then
+ if test "$curl_version" -ge 7010002; then
AC_MSG_RESULT($curl_version_full)
CURL_LIBS=`$CURL_CONFIG --libs`
else
- AC_MSG_ERROR(cURL version 7.9.8 or later is required to compile php with cURL support)
+ AC_MSG_ERROR(cURL version 7.10.2 or later is required to compile php with cURL support)
fi
PHP_ADD_INCLUDE($CURL_DIR/include)
dnl AC_DEFINE(PHP_CURL_URL_WRAPPERS,1,[ ])
dnl fi
- PHP_NEW_EXTENSION(curl, curl.c curlstreams.c, $ext_shared)
+ PHP_NEW_EXTENSION(curl, interface.c multi.c streams.c, $ext_shared)
PHP_SUBST(CURL_SHARED_LIBADD)
fi
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
# Begin Source File\r
\r
-SOURCE=.\curl.c\r
+SOURCE=.\interface.c\r
# End Source File\r
+\r
+# Begin Source File\r
+SOURCE=.\multi.c\r
+# End Source File\r
+\r
+# Begin Source File\r
+SOURCE=.\streams.c\r
+# End Source File\r
+\r
# End Group\r
# Begin Group "Header Files"\r
\r
#include "ext/standard/file.h"
#include "php_curl.h"
-static int le_curl;
-#define le_curl_name "cURL handle"
+static unsigned char second_arg_force_ref[] = {2, BYREF_NONE, BYREF_FORCE};
static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
/* {{{ curl_functions[]
*/
function_entry curl_functions[] = {
- PHP_FE(curl_init, NULL)
- PHP_FE(curl_version, NULL)
- PHP_FE(curl_setopt, NULL)
- PHP_FE(curl_exec, NULL)
- PHP_FE(curl_getinfo, NULL)
- PHP_FE(curl_error, NULL)
- PHP_FE(curl_errno, NULL)
- PHP_FE(curl_close, NULL)
+ PHP_FE(curl_init, NULL)
+ PHP_FE(curl_version, NULL)
+ PHP_FE(curl_setopt, NULL)
+ PHP_FE(curl_exec, NULL)
+ PHP_FE(curl_getinfo, NULL)
+ PHP_FE(curl_error, NULL)
+ PHP_FE(curl_errno, NULL)
+ PHP_FE(curl_close, NULL)
+ PHP_FE(curl_multi_init, NULL)
+ PHP_FE(curl_multi_add_handle, NULL)
+ PHP_FE(curl_multi_remove_handle, NULL)
+ PHP_FE(curl_multi_select, NULL)
+ PHP_FE(curl_multi_exec, second_arg_force_ref)
+ PHP_FE(curl_multi_getcontent, NULL)
+ PHP_FE(curl_multi_info_read, NULL)
+ PHP_FE(curl_multi_close, NULL)
{NULL, NULL, NULL}
};
/* }}} */
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", module_number);
/* Constants for curl_setopt() */
REGISTER_CURL_CONSTANT(CURLOPT_DNS_USE_GLOBAL_CACHE);
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(CURLINFO_REDIRECT_TIME);
REGISTER_CURL_CONSTANT(CURLINFO_REDIRECT_COUNT);
+ /* 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_OBSOLETE);
REGISTER_CURL_CONSTANT(CURLE_SSL_PEER_CERTIFICATE);
+ REGISTER_CURL_CONSTANT(CURLPROXY_HTTP);
+ 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_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 (curl_global_init(CURL_GLOBAL_SSL) != CURLE_OK) {
return FAILURE;
}
/* }}} */
-#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
-
/* {{{ curl_write
*/
static size_t curl_write(char *data, size_t size, size_t nmemb, void *ctx)
size_t length = size * nmemb;
TSRMLS_FETCH();
+#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:
PUTS(data);
/* }}} */
-/* {{{ proto array curl_version(void)
+/* {{{ proto array curl_version([int version])
Return cURL version information. */
PHP_FUNCTION(curl_version)
{
- if (ZEND_NUM_ARGS() != 0) {
- WRONG_PARAM_COUNT;
+ 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;
}
- RETURN_STRING(curl_version(), 1);
+ 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);
+ }
+ CAAZ("protocols", protocol_list);
+ }
}
/* }}} */
case CURLOPT_SSL_VERIFYHOST:
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:
}
/* }}} */
-/* {{{ cleanup_handle(ch)
+/* {{{ _php_curl_cleanup_handle(ch)
Cleanup an execution phase */
-static void
-cleanup_handle(php_curl *ch)
+void
+_php_curl_cleanup_handle(php_curl *ch)
{
if (ch->uses < 1) {
return;
}
ZEND_FETCH_RESOURCE(ch, php_curl *, zid, -1, le_curl_name, le_curl);
- cleanup_handle(ch);
+ _php_curl_cleanup_handle(ch);
error = curl_easy_perform(ch->cp);
SAVE_CURL_ERROR(ch, error);
if (ch->handlers->write->method == PHP_CURL_RETURN && ch->handlers->write->buf.len > 0) {
if (ch->handlers->write->type != PHP_CURL_BINARY)
smart_str_0(&ch->handlers->write->buf);
- RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 1);
+ RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 0);
}
RETURN_TRUE;
{
php_curl *ch = (php_curl *) rsrc->ptr;
+#if PHP_CURL_DEBUG
+ fprintf(stderr, "DTOR CALLED, ch = %x\n", ch);
+#endif
+
curl_easy_cleanup(ch->cp);
zend_llist_clean(&ch->to_free.str);
zend_llist_clean(&ch->to_free.slist);
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 4 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2002 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.02 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.php.net/license/2_02.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: */
+
+#include "php.h"
+
+#if HAVE_CURL
+
+#include "php_curl.h"
+
+#include <curl/curl.h>
+#include <curl/multi.h>
+
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+/* {{{ proto resource curl_multi_init(void)
+ Returns a new cURL multi handle */
+PHP_FUNCTION(curl_multi_init)
+{
+ php_curlm *mh;
+
+ if (ZEND_NUM_ARGS() != 0) {
+ WRONG_PARAM_COUNT;
+ }
+
+ mh = ecalloc(1, sizeof(php_curlm));
+ mh->multi = curl_multi_init();
+
+ ZEND_REGISTER_RESOURCE(return_value, mh, le_curl_multi_handle);
+}
+/* }}} */
+
+/* {{{ int curl_multi_add_handle(resource multi, 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;
+
+ 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);
+
+ zval_add_ref(&z_ch);
+
+ _php_curl_cleanup_handle(ch);
+ ch->uses++;
+
+ RETURN_LONG((long) curl_multi_add_handle(mh->multi, ch->cp));
+}
+/* }}} */
+
+/* {{{ 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);
+
+ zval_ptr_dtor(&z_ch);
+
+ 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;
+}
+
+/* {{{ 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);
+ RETURN_LONG(select(maxfd + 1, &readfds, &writefds, &exceptfds, &to));
+}
+/* }}} */
+
+/* {{{ proto int curl_multi_exec(resource mh)
+ 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);
+
+ 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) {
+ if (ch->handlers->write->type == PHP_CURL_BINARY) {
+ smart_str_0(&ch->handlers->write->buf);
+ }
+
+ RETURN_STRINGL(ch->handlers->write->buf.c, ch->handlers->write->buf.len, 0);
+ }
+}
+
+
+/* {{{ proto array curl_multi_info_read(resource mh)
+ Get information about the current transfers */
+PHP_FUNCTION(curl_multi_info_read)
+{
+ zval *z_mh;
+ php_curlm *mh;
+ CURLMsg *tmp_msg;
+ int queued_msgs;
+
+ 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);
+
+ tmp_msg = curl_multi_info_read(mh->multi, &queued_msgs);
+ if (tmp_msg == NULL) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ add_assoc_long(return_value, "msg", tmp_msg->msg);
+ add_assoc_long(return_value, "result", tmp_msg->data.result);
+// add_assoc_resource(return_value, "handle", _find_handle(tmp_msg->easy_handle));
+ add_assoc_string(return_value, "whatever", (char *) tmp_msg->data.whatever, 1);
+}
+/* }}} */
+
+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)
+{
+ php_curlm *mh = (php_curlm *) rsrc->ptr;
+ curl_multi_cleanup(mh->multi);
+ // XXX: keep track of all curl handles and zval_ptr_dtor them here
+}
+
+#endif
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Sterling Hughes <sterling@php.net> |
- | Wez Furlong <wez@thebrainroom.com> |
+ | Wez Furlong <wez@thebrainroom.com> |
+----------------------------------------------------------------------+
*/
#if HAVE_CURL
-#include <curl/curl.h>
+#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
+
+int le_curl;
+#define le_curl_name "cURL handle"
+int le_curl_multi_handle;
+#define le_curl_multi_handle_name "cURL Multi Handle"
PHP_MINIT_FUNCTION(curl);
PHP_MSHUTDOWN_FUNCTION(curl);
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 *);
typedef struct {
zval *func;
};
typedef struct {
- CURL *cp;
- php_curl_handlers *handlers;
struct _php_curl_error err;
struct _php_curl_free to_free;
+ CURL *cp;
+ php_curl_handlers *handlers;
long id;
unsigned int uses;
} php_curl;
+typedef struct {
+ int still_running;
+ CURLM *multi;
+} php_curlm;
+
+void _php_curl_cleanup_handle(php_curl *);
+
/* streams support */
PHPAPI extern php_stream_ops php_curl_stream_ops;