]> granicus.if.org Git - php/commitdiff
Allow NULL as value for CURLOPT_CUSTOMREQUEST option.
authordatibbaw <datibbaw@php.net>
Mon, 18 Nov 2013 04:06:27 +0000 (12:06 +0800)
committerTjerk Meesters <datibbaw@php.net>
Fri, 28 Feb 2014 10:27:22 +0000 (18:27 +0800)
Added test case.

Refactored the code to isolate the string handling. Fixed return values to use SUCCESS and FAILURE.

Removed unused error variable.

Indentation fix.
Removed the ugly goto.

ext/curl/interface.c
ext/curl/php_curl.h
ext/curl/tests/bug66109.phpt [new file with mode: 0644]
ext/curl/tests/responder/get.php

index 5f7783e669a78a5de8228e034318c3ea184ae481..0d96d1f026efd22eb36a517c3296be377117f62c 100644 (file)
@@ -165,50 +165,58 @@ static void _php_curl_close(zend_rsrc_list_entry *rsrc TSRMLS_DC);
 # 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) /* {{{ */
+static int php_curl_option_str(php_curl *ch, long option, const char *str, const int len, zend_bool make_copy TSRMLS_DC)
 {
        CURLcode error = CURLE_OK;
-#if LIBCURL_VERSION_NUM < 0x071100
-       char *copystr = NULL;
-#endif
+
+       if (make_copy || LIBCURL_VERSION_NUM < 0x071100) {
+               char *copystr;
+
+               /* Strings passed to libcurl as 'char *' arguments, are copied by the library since 7.17.0 */
+               copystr = estrndup(str, len);
+               error = curl_easy_setopt(ch->cp, option, copystr);
+               zend_llist_add_element(&ch->to_free->str, &copystr);
+       } else {
+               error = curl_easy_setopt(ch->cp, option, str);
+       }
+
+       SAVE_CURL_ERROR(ch, error)
+
+       return error == CURLE_OK ? SUCCESS : FAILURE;
+}
+
+static int php_curl_option_url(php_curl *ch, const char *url, const int len TSRMLS_DC) /* {{{ */
+{
        /* 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);
+               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;
+                       return FAILURE;
                }
 
                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;
+                       return FAILURE;
                }
                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);
+       return php_curl_option_str(ch, CURLOPT_URL, url, len, 0 TSRMLS_CC);
 }
 /* }}} */
 
-int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */
+void _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */
 {
        php_stream *stream;
        if (!ch || !ch->handlers) {
-               return 0;
+               return;
        }
 
        if (ch->handlers->std_err) {
@@ -265,7 +273,7 @@ int _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC) /* {{{ */
                        curl_easy_setopt(ch->cp, CURLOPT_FILE, (void *) ch);
                }
        }
-       return 1;
+       return ;
 }
 /* }}} */
 
@@ -1941,7 +1949,7 @@ PHP_FUNCTION(curl_init)
        _php_curl_set_default_options(ch);
 
        if (url) {
-               if (!php_curl_option_url(ch, url, url_len TSRMLS_CC)) {
+               if (php_curl_option_url(ch, url, url_len TSRMLS_CC) == FAILURE) {
                        _php_curl_close_ex(ch TSRMLS_CC);
                        RETURN_FALSE;
                }
@@ -2058,7 +2066,7 @@ PHP_FUNCTION(curl_copy_handle)
 }
 /* }}} */
 
-static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *return_value TSRMLS_DC) /* {{{ */
+static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue TSRMLS_DC) /* {{{ */
 {
        CURLcode     error=CURLE_OK;
 
@@ -2225,7 +2233,6 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
                        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
@@ -2240,14 +2247,10 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
                case CURLOPT_CAINFO:
                case CURLOPT_CAPATH:
                case CURLOPT_COOKIE:
-               case CURLOPT_CUSTOMREQUEST:
                case CURLOPT_EGDSOCKET:
-               case CURLOPT_FTPPORT:
                case CURLOPT_INTERFACE:
-               case CURLOPT_PRIVATE:
                case CURLOPT_PROXY:
                case CURLOPT_PROXYUSERPWD:
-               case CURLOPT_RANGE:
                case CURLOPT_REFERER:
                case CURLOPT_SSLCERTTYPE:
                case CURLOPT_SSLENGINE:
@@ -2256,23 +2259,14 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
                case CURLOPT_SSLKEYPASSWD:
                case CURLOPT_SSLKEYTYPE:
                case CURLOPT_SSL_CIPHER_LIST:
-               case CURLOPT_URL:
                case CURLOPT_USERAGENT:
                case CURLOPT_USERPWD:
-#if LIBCURL_VERSION_NUM >= 0x070d00 /* Available since 7.13.0 */
-               case CURLOPT_FTP_ACCOUNT:
-#endif
 #if LIBCURL_VERSION_NUM >= 0x070e01 /* Available since 7.14.1 */
                case CURLOPT_COOKIELIST:
 #endif
 #if LIBCURL_VERSION_NUM >= 0x070f05 /* Available since 7.15.5 */
                case CURLOPT_FTP_ALTERNATIVE_TO_USER:
 #endif
-#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
-               case CURLOPT_KRBLEVEL:
-#else
-               case CURLOPT_KRB4LEVEL:
-#endif
 #if LIBCURL_VERSION_NUM >= 0x071101 /* Available since 7.17.1 */
                case CURLOPT_SSH_HOST_PUBLIC_KEY_MD5:
 #endif
@@ -2287,7 +2281,6 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
 #endif
 #if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
                case CURLOPT_MAIL_FROM:
-               case CURLOPT_RTSP_SESSION_ID:
                case CURLOPT_RTSP_STREAM_URI:
                case CURLOPT_RTSP_TRANSPORT:
 #endif
@@ -2309,32 +2302,44 @@ static int _php_curl_setopt(php_curl *ch, long option, zval **zvalue, zval *retu
 #endif
                {
                        convert_to_string_ex(zvalue);
-                       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));
+                       return php_curl_option_str(ch, option, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 0 TSRMLS_CC);
+               }
+
+               /* Curl nullable string options */
+               case CURLOPT_CUSTOMREQUEST:
+               case CURLOPT_FTPPORT:
+               case CURLOPT_RANGE:
+#if LIBCURL_VERSION_NUM >= 0x070d00 /* Available since 7.13.0 */
+               case CURLOPT_FTP_ACCOUNT:
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071400 /* Available since 7.20.0 */
+               case CURLOPT_RTSP_SESSION_ID:
+#endif
+#if LIBCURL_VERSION_NUM >= 0x071004 /* Available since 7.16.4 */
+               case CURLOPT_KRBLEVEL:
 #else
-                                       goto string_copy;
+               case CURLOPT_KRB4LEVEL:
 #endif
-                               }
+               {
+                       if (Z_TYPE_PP(zvalue) == IS_NULL) {
+                               error = curl_easy_setopt(ch->cp, option, NULL);
+                       } else {
+                               convert_to_string_ex(zvalue);
+                               return php_curl_option_str(ch, option, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 0 TSRMLS_CC);
                        }
                        break;
                }
 
+               /* Curl private option */
+               case CURLOPT_PRIVATE:
+                       convert_to_string_ex(zvalue);
+                       return php_curl_option_str(ch, option, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 1 TSRMLS_CC);
+
+               /* Curl url option */
+               case CURLOPT_URL:
+                       convert_to_string_ex(zvalue);
+                       return php_curl_option_url(ch, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue) TSRMLS_CC);
+
                /* Curl file handle options */
                case CURLOPT_FILE:
                case CURLOPT_INFILE:
@@ -2346,18 +2351,15 @@ string_copy:
 
                        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;
+                               return FAILURE;
                        }
 
                        if (FAILURE == php_stream_cast((php_stream *) what, PHP_STREAM_AS_STDIO, (void *) &fp, REPORT_ERRORS)) {
-                               RETVAL_FALSE;
-                               return 1;
+                               return FAILURE;
                        }
 
                        if (!fp) {
-                               RETVAL_FALSE;
-                               return 1;
+                               return FAILURE;
                        }
 
                        error = CURLE_OK;
@@ -2373,8 +2375,7 @@ string_copy:
                                                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;
+                                               return FAILURE;
                                        }
                                        break;
                                case CURLOPT_WRITEHEADER:
@@ -2388,8 +2389,7 @@ string_copy:
                                                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;
+                                               return FAILURE;
                                        }
                                        break;
                                case CURLOPT_INFILE:
@@ -2410,8 +2410,7 @@ string_copy:
                                                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;
+                                               return FAILURE;
                                        }
                                        /* break omitted intentionally */
                                default:
@@ -2473,8 +2472,7 @@ string_copy:
 #endif
                                }
                                php_error_docref(NULL TSRMLS_CC, E_WARNING, "You must pass either an object or an array with the %s argument", name);
-                               RETVAL_FALSE;
-                               return 1;
+                               return FAILURE;
                        }
 
                        for (zend_hash_internal_pointer_reset(ph);
@@ -2487,7 +2485,6 @@ string_copy:
                                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;
                                }
                        }
@@ -2507,8 +2504,7 @@ string_copy:
                        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;
+                                       return FAILURE;
                                }
                        }
                        error = curl_easy_setopt(ch->cp, option, Z_LVAL_PP(zvalue));
@@ -2534,8 +2530,7 @@ string_copy:
                                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;
+                                       return FAILURE;
                                }
 
                                for (zend_hash_internal_pointer_reset(postfields);
@@ -2571,7 +2566,6 @@ string_copy:
                                                        postval = Z_STRVAL_P(prop);
 
                                                        if (php_check_open_basedir(postval TSRMLS_CC)) {
-                                                               RETVAL_FALSE;
                                                                return 1;
                                                        }
 
@@ -2620,8 +2614,7 @@ string_copy:
                                                }
                                                /* open_basedir check */
                                                if (php_check_open_basedir(postval TSRMLS_CC)) {
-                                                       RETVAL_FALSE;
-                                                       return 1;
+                                                       return FAILURE;
                                                }
                                                error = curl_formadd(&first, &last,
                                                                                CURLFORM_COPYNAME, string_key,
@@ -2652,8 +2645,7 @@ string_copy:
 
                                SAVE_CURL_ERROR(ch, error);
                                if (error != CURLE_OK) {
-                                       RETVAL_FALSE;
-                                       return 1;
+                                       return FAILURE;
                                }
 
                                if (Z_REFCOUNT_P(ch->clone) <= 1) {
@@ -2675,7 +2667,7 @@ string_copy:
                                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);
+                               curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, post);
                                error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, Z_STRLEN_PP(zvalue));
 #endif
                        }
@@ -2773,26 +2765,13 @@ string_copy:
                case CURLOPT_SSH_KNOWNHOSTS:
 #endif
                {
-#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;
+                               return FAILURE;
                        }
 
-#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;
+                       return php_curl_option_str(ch, option, Z_STRVAL_PP(zvalue), Z_STRLEN_PP(zvalue), 0 TSRMLS_CC);
                }
 
                case CURLINFO_HEADER_OUT:
@@ -2837,9 +2816,9 @@ string_copy:
 
        SAVE_CURL_ERROR(ch, error);
        if (error != CURLE_OK) {
-               return 1;
+               return FAILURE;
        } else {
-               return 0;
+               return SUCCESS;
        }
 }
 /* }}} */
@@ -2863,7 +2842,7 @@ PHP_FUNCTION(curl_setopt)
                RETURN_FALSE;
        }
 
-       if (!_php_curl_setopt(ch, options, zvalue, return_value TSRMLS_CC)) {
+       if (_php_curl_setopt(ch, options, zvalue TSRMLS_CC) == SUCCESS) {
                RETURN_TRUE;
        } else {
                RETURN_FALSE;
@@ -2894,7 +2873,7 @@ PHP_FUNCTION(curl_setopt_array)
                        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)) {
+               if (_php_curl_setopt(ch, (long) option, entry TSRMLS_CC) == FAILURE) {
                        RETURN_FALSE;
                }
                zend_hash_move_forward_ex(Z_ARRVAL_P(arr), &pos);
index e02a890b0bc2fae22b1ed571a15fdbebf6977e6a..96edb9ae03bb361c0b0f2f4417bac4d0948fd1ff 100644 (file)
@@ -198,7 +198,7 @@ typedef struct {
 
 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);
+void _php_curl_verify_handlers(php_curl *ch, int reporterror TSRMLS_DC);
 
 void curlfile_register_class(TSRMLS_D);
 PHP_CURL_API extern zend_class_entry *curl_CURLFile_class;
diff --git a/ext/curl/tests/bug66109.phpt b/ext/curl/tests/bug66109.phpt
new file mode 100644 (file)
index 0000000..aacfba4
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Bug #66109 (Option CURLOPT_CUSTOMREQUEST can't be reset to default.)
+--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=method");
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'DELETE');
+var_dump(curl_exec($ch));
+
+curl_setopt($ch, CURLOPT_CUSTOMREQUEST, NULL);
+var_dump(curl_exec($ch));
+
+curl_close($ch);
+
+?>
+--EXPECTF--
+string(6) "DELETE"
+string(3) "GET"
index 9e13d6a746dffc1f4670b5145b76a1c3aade58b7..60aafc03d41ddccaadc53428150be180cfe06639 100644 (file)
@@ -31,6 +31,9 @@
           echo $_FILES['file']['name'] . '|' . $_FILES['file']['type'];
       }
       break;
+    case 'method':
+      echo $_SERVER['REQUEST_METHOD'];
+      break;
     default:
       echo "Hello World!\n";
       echo "Hello World!";