summaryrefslogtreecommitdiff
path: root/ext/curl/streams.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/curl/streams.c')
-rw-r--r--ext/curl/streams.c171
1 files changed, 139 insertions, 32 deletions
diff --git a/ext/curl/streams.c b/ext/curl/streams.c
index a62aa1a39..1ff5a3d6d 100644
--- a/ext/curl/streams.c
+++ b/ext/curl/streams.c
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: streams.c,v 1.14.2.3 2006/08/10 17:16:35 iliaa Exp $ */
+/* $Id: streams.c,v 1.14.2.2.2.9 2006/09/15 15:42:53 tony2001 Exp $ */
/* This file implements cURL based wrappers.
* NOTE: If you are implementing your own streams that are intended to
@@ -87,31 +87,32 @@ static size_t on_header_available(char *data, size_t size, size_t nmemb, void *c
php_curl_stream *curlstream = (php_curl_stream *) stream->abstract;
TSRMLS_FETCH();
- 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';
+ 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);
}
}
- 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;
}
@@ -251,7 +252,7 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename,
{
php_stream *stream;
php_curl_stream *curlstream;
- zval *tmp;
+ zval *tmp, **ctx_opt = NULL;
curlstream = emalloc(sizeof(php_curl_stream));
memset(curlstream, 0, sizeof(php_curl_stream));
@@ -288,13 +289,6 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename,
curl_easy_setopt(curlstream->curl, CURLOPT_HEADERFUNCTION, on_header_available);
curl_easy_setopt(curlstream->curl, CURLOPT_WRITEHEADER, stream);
- /* currently buggy (bug is in curl) */
- if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) {
- curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 0);
- } else {
- curl_easy_setopt(curlstream->curl, CURLOPT_FOLLOWLOCATION, 1);
- }
-
curl_easy_setopt(curlstream->curl, CURLOPT_ERRORBUFFER, curlstream->errstr);
curl_easy_setopt(curlstream->curl, CURLOPT_VERBOSE, 0);
@@ -306,6 +300,93 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename,
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)) {
+ 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, 1);
+ } 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) && Z_TYPE_PP(ctx_opt) == IS_ARRAY) {
+ HashPosition pos;
+ zval **header = NULL;
+ struct curl_slist *hl = 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) {
+ hl = curl_slist_append(hl, Z_STRVAL_PP(header));
+ }
+ }
+ if (hl) {
+ curl_easy_setopt(curlstream->curl, CURLOPT_HTTPHEADER, hl);
+ }
+ }
+ 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)) || PG(safe_mode)) {
+ 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)) || PG(safe_mode)) {
+ 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, 1);
+ } 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);
@@ -345,15 +426,41 @@ php_stream *php_curl_stream_opener(php_stream_wrapper *wrapper, char *filename,
/* 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
+ php_stream_close(stream);
+ return NULL;
+ }
+
+ /* 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) {
+ php_stream_close(stream);
+ return NULL;
}
-
}
return stream;