* more intuitive support for headers and cookies (associative arrays)
authorMichael Wallner <mike@php.net>
Mon, 7 Feb 2005 17:13:56 +0000 (17:13 +0000)
committerMichael Wallner <mike@php.net>
Mon, 7 Feb 2005 17:13:56 +0000 (17:13 +0000)
* proto fixed
* include snprintf.h
* added info parameter to http_get/head/post functions
* include ctype.h - always
* fix curl config
* ditch http_accept_ranges() (sent automatically in http_send_data/resource)
* new HASH_ORNULL() macro

config.m4
http.c
http_api.c
php_http.h
php_http_api.h

index 26a5e918cd7c0e9e98abd753889f51b1e1afe9a5..f50162716ff0d6b79fe54857858f0260409e4cd6 100644 (file)
--- a/config.m4
+++ b/config.m4
@@ -8,13 +8,6 @@ PHP_ARG_WITH([curl], [for CURL support],
 
 if test "$PHP_HTTP" != "no"; then
 
-dnl -----
-dnl CTYPE
-dnl -----
-       if test -r /usr/include/ctype.h -o -r /usr/local/include/ctype.h ; then
-               AC_DEFINE([HAVE_CTYPE], [1], [Have ctype support])
-       fi
-
 dnl ----
 dnl CURL
 dnl ----
@@ -31,15 +24,15 @@ dnl ----
                        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"
-               
+
                if ${CURL_DIR}/bin/curl-config --libs print > /dev/null 2>&1; then
                        CURL_CONFIG=${CURL_DIR}/bin/curl-config
                else
@@ -47,26 +40,20 @@ dnl ----
                        CURL_CONFIG=${CURL_DIR}/curl-config
                        fi
                fi
-               
+
                PHP_ADD_INCLUDE($CURL_DIR/include)
                PHP_EVAL_LIBLINE($CURL_LIBS, CURL_SHARED_LIBADD)
                PHP_ADD_LIBRARY_WITH_PATH(curl, $CURL_DIR/lib, HTTP_SHARED_LIBADD)
-               
-               PHP_CHECK_LIBRARY(curl,curl_easy_init, 
-               [ 
+
+               PHP_CHECK_LIBRARY(curl,curl_easy_init,
+               [
                        AC_DEFINE(HAVE_CURL,1,[Have CURL easy support])
                ],[
                        AC_MSG_ERROR(There is something wrong with libcurl. Please check config.log for more information.)
                ],[
                        $CURL_LIBS -L$CURL_DIR/lib
                ])
-               
-               PHP_CHECK_LIBRARY(curl,curl_version_info,
-               [
-                       AC_DEFINE(HAVE_CURL_VERSION_INFO,1,[ ])
-               ],[],[
-                       $CURL_LIBS -L$CURL_DIR/lib
-               ])
+
        fi
 
 dnl ----
diff --git a/http.c b/http.c
index 41e463e0ec03f9928ae8df6af6841ae982f92362..9a3ed65c224e81ba4b5ee9981721e0517d6fee3d 100644 (file)
--- a/http.c
+++ b/http.c
@@ -20,9 +20,8 @@
 #endif
 
 #include "php.h"
-#include "main/snprintf.h"
+#include "snprintf.h"
 #include "ext/standard/info.h"
-#include "ext/standard/datetime.h"
 #include "ext/session/php_session.h"
 #include "ext/standard/php_string.h"
 #include "ext/standard/php_smart_str.h"
@@ -53,7 +52,6 @@ function_entry http_functions[] = {
        PHP_FE(http_match_etag, NULL)
        PHP_FE(http_cache_last_modified, NULL)
        PHP_FE(http_cache_etag, NULL)
-       PHP_FE(http_accept_ranges, NULL)
        PHP_FE(http_content_type, NULL)
        PHP_FE(http_content_disposition, NULL)
        PHP_FE(http_send_data, NULL)
@@ -93,6 +91,7 @@ zend_module_entry http_module_entry = {
 /* }}} */
 
 #define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
+#define HASH_ORNULL(z) ((z) ? Z_ARRVAL_P(z) : NULL)
 
 /* {{{ proto string http_date([int timestamp])
  *
@@ -242,10 +241,6 @@ PHP_FUNCTION(http_negotiate_charset)
 /* {{{ proto bool http_send_status(int status)
  *
  * Send HTTP status code.
- * This function sends the desired HTTP status code along with its corresponding
- * status message, e.g. calling http_send_status(304) will issue a
- * "Status: 304 Not Modified" with CGI-SAPIs and "HTTP/1.1 304 Not Modified"
- * when PHP is run as web server module.
  *
  */
 PHP_FUNCTION(http_send_status)
@@ -268,7 +263,7 @@ PHP_FUNCTION(http_send_status)
  *
  * This converts the given timestamp to a valid HTTP date and
  * sends it as "Last-Modified" HTTP header.  If timestamp is
- * omitted, current time is taken.
+ * omitted, current time is sent.
  *
  */
 PHP_FUNCTION(http_send_last_modified)
@@ -289,7 +284,7 @@ PHP_FUNCTION(http_send_last_modified)
 
 /* {{{ proto bool http_match_modified([int timestamp])
  *
- * Matches the given timestamp against the clients "If-Modified-Since" and
+ * Matches the given timestamp against the clients "If-Modified-Since" resp.
  * "If-Unmodified-Since" HTTP headers.
  *
  */
@@ -313,7 +308,7 @@ PHP_FUNCTION(http_match_modified)
 /* {{{ proto bool http_match_etag(string etag)
  *
  * This matches the given ETag against the clients
- * "If-Match" and "If-None-Match" HTTP headers.
+ * "If-Match" resp. "If-None-Match" HTTP headers.
  *
  */
 PHP_FUNCTION(http_match_etag)
@@ -334,7 +329,7 @@ PHP_FUNCTION(http_match_etag)
  * If timestamp_or_exires is greater than 0, it is handled as timestamp
  * and will be sent as date of last modification.  If it is 0 or omitted,
  * the current time will be sent as Last-Modified date.  If it's negative,
- * it is handled as expiration tim in seconds, which means that if the
+ * it is handled as expiration time in seconds, which means that if the
  * requested last modification date is not between the calculated timespan,
  * the Last-Modified header is updated and the actual body will be sent.
  *
@@ -502,7 +497,7 @@ PHP_FUNCTION(http_send_data)
        }
 
        convert_to_string_ex(&zdata);
-
+       http_send_header("Accept-Ranges: bytes");
        RETURN_SUCCESS(http_send_data(zdata));
 }
 /* }}} */
@@ -521,7 +516,7 @@ PHP_FUNCTION(http_send_file)
        }
 
        convert_to_string_ex(&zfile);
-
+       http_send_header("Accept-Ranges: bytes");
        RETURN_SUCCESS(http_send_file(zfile));
 }
 /* }}} */
@@ -541,36 +536,11 @@ PHP_FUNCTION(http_send_stream)
        }
 
        php_stream_from_zval(file, &zstream);
-
+       http_send_header("Accept-Ranges: bytes");
        RETURN_SUCCESS(http_send_stream(file));
 }
 /* }}} */
 
-/* {{{ proto bool http_accept_ranges(void)
- *
- * Issues a "Accept-Ranges: bytes" header.
- *
- * Example:
- * <pre>
- * <?php
- * http_content_type('application/x-zip');
- * http_content_disposition('latest.zip');
- * http_accept_ranges();
- * http_cache_etag();
- * http_send_file('../some/download.zip');
- * ?>
- * </pre>
- *
- */
-PHP_FUNCTION(http_accept_ranges)
-{
-       if (ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
-       RETURN_SUCCESS(http_send_header("Accept-Ranges: bytes"));
-}
-/* }}} */
-
 /* {{{ proto bool http_content_type([string content_type = 'application/x-octetstream'])
  *
  * Sets the content type.
@@ -696,16 +666,16 @@ PHP_FUNCTION(http_split_response)
 /* {{{ HAVE_CURL */
 #if defined(HAVE_CURL) && HAVE_CURL
 
-/* {{{ proto string http_get(string url[, array options])
+/* {{{ proto string http_get(string url[, array options[, array &info]])
  *
  * Performs an HTTP GET request on the supplied url.
  *
  * The second parameter is expected to be an associative
  * array where the following keys will be recognized:
  * <pre>
- *  - redirect:        int, whether and how many redirects to follow
+ *  - redirect:         int, whether and how many redirects to follow
  *  - unrestrictedauth: bool, whether to continue sending credentials on
- *                         redirects to a different host
+ *                      redirects to a different host
  *  - proxyhost:        string, proxy host in "host[:port]" format
  *  - proxyport:        int, use another proxy port as specified in proxyhost
  *  - proxyauth:        string, proxy credentials in "user:pass" format
@@ -713,26 +683,39 @@ PHP_FUNCTION(http_split_response)
  *  - httpauth:         string, http credentials in "user:pass" format
  *  - httpauthtype:     int, HTTP_AUTH_BASIC, DIGEST and/or NTLM
  *  - compress:         bool, whether to allow gzip/deflate content encoding
+ *                      (defaults to true)
  *  - port:             int, use another port as specified in the url
  *  - referer:          string, the referer to sends
  *  - useragent:        string, the user agent to send
- *  - headers:          array, list of custom headers in "header: value" format
- *  - cookies:          array, list of cookies in "name=value" format
+ *                      (defaults to PECL::HTTP/version (PHP/version)))
+ *  - headers:          array, list of custom headers as associative array
+ *                      like array("header" => "value")
+ *  - cookies:          array, list of cookies as associative array
+ *                      like array("cookie" => "value")
  *  - cookiestore:      string, path to a file where cookies are/will be stored
  * </pre>
+ *
+ * The optional third parameter will be filled with some additional information
+ * in form af an associative array, if supplied (don't forget to initialize it
+ * with NULL or array()).
  */
 PHP_FUNCTION(http_get)
 {
        char *URL, *data = NULL;
        size_t data_len = 0;
        int URL_len;
-       zval *options = NULL;
+       zval *options = NULL, *info = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &URL, &URL_len, &options) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
                RETURN_FALSE;
        }
 
-       if (SUCCESS == http_get(URL, options ? Z_ARRVAL_P(options) : NULL, &data, &data_len)) {
+       if (info) {
+               zval_dtor(info);
+               array_init(info);
+       }
+
+       if (SUCCESS == http_get(URL, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
                RETURN_STRINGL(data, data_len, 0);
        } else {
                RETURN_FALSE;
@@ -740,7 +723,7 @@ PHP_FUNCTION(http_get)
 }
 /* }}} */
 
-/* {{{ proto string http_head(string url[, array options])
+/* {{{ proto string http_head(string url[, array options[, array &info]])
  *
  * Performs an HTTP HEAD request on the suppied url.
  * Returns the HTTP response as string.
@@ -751,13 +734,18 @@ PHP_FUNCTION(http_head)
        char *URL, *data = NULL;
        size_t data_len = 0;
        int URL_len;
-       zval *options = NULL;
+       zval *options = NULL, *info = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &URL, &URL_len, &options) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
                RETURN_FALSE;
        }
 
-       if (SUCCESS == http_head(URL, options ? Z_ARRVAL_P(options) : NULL, &data, &data_len)) {
+       if (info) {
+               zval_dtor(info);
+               array_init(info);
+       }
+
+       if (SUCCESS == http_head(URL, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
                RETURN_STRINGL(data, data_len, 0);
        } else {
                RETURN_FALSE;
@@ -765,7 +753,7 @@ PHP_FUNCTION(http_head)
 }
 /* }}} */
 
-/* {{{ proto string http_post_data(string url, string data[, array options])
+/* {{{ proto string http_post_data(string url, string data[, array options[, &info]])
  *
  * Performs an HTTP POST request, posting data.
  * Returns the HTTP response as string.
@@ -776,13 +764,18 @@ PHP_FUNCTION(http_post_data)
        char *URL, *postdata, *data = NULL;
        size_t data_len = 0;
        int postdata_len, URL_len;
-       zval *options = NULL;
+       zval *options = NULL, *info = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a", &URL, &URL_len, &postdata, &postdata_len, &options) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
                RETURN_FALSE;
        }
 
-       if (SUCCESS == http_post_data(URL, postdata, (size_t) postdata_len, options ? Z_ARRVAL_P(options) : NULL, &data, &data_len)) {
+       if (info) {
+               zval_dtor(info);
+               array_init(info);
+       }
+
+       if (SUCCESS == http_post_data(URL, postdata, (size_t) postdata_len, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
                RETURN_STRINGL(data, data_len, 0);
        } else {
                RETURN_FALSE;
@@ -790,7 +783,7 @@ PHP_FUNCTION(http_post_data)
 }
 /* }}} */
 
-/* {{{ proto string http_post_data(string url, array data[, array options])
+/* {{{ proto string http_post_array(string url, array data[, array options[, array &info]])
  *
  * Performs an HTTP POST request, posting www-form-urlencoded array data.
  * Returns the HTTP response as string.
@@ -801,13 +794,18 @@ PHP_FUNCTION(http_post_array)
        char *URL, *data = NULL;
        size_t data_len = 0;
        int URL_len;
-       zval *options = NULL, *postdata;
+       zval *options = NULL, *info = NULL, *postdata;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a", &URL, &URL_len, &postdata, &options) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a/!z", &URL, &URL_len, &postdata, &options, &info) != SUCCESS) {
                RETURN_FALSE;
        }
 
-       if (SUCCESS == http_post_array(URL, Z_ARRVAL_P(postdata), options ? Z_ARRVAL_P(options) : NULL, &data, &data_len)) {
+       if (info) {
+               zval_dtor(info);
+               array_init(info);
+       }
+
+       if (SUCCESS == http_post_array(URL, Z_ARRVAL_P(postdata), HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
                RETURN_STRINGL(data, data_len, 0);
        } else {
                RETURN_FALSE;
index 91e8b37bbc2d10912ef67da5c70fdea3051d1cbe..32dc183077ac2639b83bcf2efbb24da08cca61d8 100644 (file)
 #include "php.h"
 #include "php_version.h"
 #include "php_streams.h"
-#include "main/snprintf.h"
+#include "snprintf.h"
 #include "ext/standard/md5.h"
 #include "ext/standard/url.h"
 #include "ext/standard/base64.h"
 #include "ext/standard/php_string.h"
+#include "ext/standard/php_smart_str.h"
 #include "ext/standard/php_lcg.h"
 
 #include "SAPI.h"
@@ -42,7 +43,6 @@
 #include "php_http_api.h"
 
 #include <ctype.h>
-
 #if defined(HAVE_CURL) && HAVE_CURL
 #include <curl/curl.h>
 #include <curl/easy.h>
@@ -58,7 +58,7 @@ static const char *wkdays[] = {
        "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"
 };
 static const char *weekdays[] = {
-       "Monday", "Tuesday", "Wednesday", 
+       "Monday", "Tuesday", "Wednesday",
        "Thursday", "Friday", "Saturday", "Sunday"
 };
 static const char *months[] = {
@@ -156,6 +156,14 @@ static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, i
 
 static size_t http_curl_body_callback(char *, size_t, size_t, void *);
 static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *);
+
+#define http_curl_getinfo(c, h) _http_curl_getinfo((c), (h) TSRMLS_CC)
+static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC);
+#define http_curl_getinfo_ex(c, i, a) _http_curl_getinfo_ex((c), (i), (a) TSRMLS_CC)
+static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC);
+#define http_curl_getinfoname(i) _http_curl_getinfoname((i) TSRMLS_CC)
+static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC);
+
 #endif
 /* }}} HAVE_CURL */
 
@@ -469,7 +477,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
                return;
        }
 
-       /* redirects */
+       /* redirects, defaults to 0 */
        if (zoption = http_curl_getopt1(options, "redirect", IS_LONG)) {
                curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1 : 0);
                curl_easy_setopt(ch, CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
@@ -505,9 +513,12 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
                curl_easy_setopt(ch, CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
        }
 
-       /* compress */
+       /* compress, enabled by default (empty string enables deflate and gzip) */
        if (zoption = http_curl_getopt2(options, "compress", IS_LONG, IS_BOOL)) {
-               /* empty string enables deflate and gzip */
+               if (Z_LVAL_P(zoption)) {
+                       curl_easy_setopt(ch, CURLOPT_ENCODING, "");
+               }
+       } else {
                curl_easy_setopt(ch, CURLOPT_ENCODING, "");
        }
 
@@ -521,18 +532,37 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
                curl_easy_setopt(ch, CURLOPT_REFERER, Z_STRVAL_P(zoption));
        }
 
-       /* useragent */
+       /* useragent, default "PECL::HTTP/version (PHP/version)" */
        if (zoption = http_curl_getopt1(options, "useragent", IS_STRING)) {
                curl_easy_setopt(ch, CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
+       } else {
+               curl_easy_setopt(ch, CURLOPT_USERAGENT,
+                       "PECL::HTTP/" PHP_EXT_HTTP_VERSION " (PHP/" PHP_VERSION ")");
        }
 
-       /* cookies */
+       /* cookies, array('name' => 'value') */
        if (zoption = http_curl_getopt1(options, "cookies", IS_ARRAY)) {
-               zval cookies, glue;
-               ZVAL_STRINGL(&glue, "; ", 2, 0);
-               php_implode(&glue, zoption, &cookies);
-               if (Z_STRVAL(cookies)) {
-                       curl_easy_setopt(ch, CURLOPT_COOKIE, Z_STRVAL(cookies));
+               char *cookie_key;
+               zval **cookie_val;
+               int key_type;
+               smart_str qstr = {0};
+
+               zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
+               while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
+                       if (key_type == HASH_KEY_IS_STRING) {
+                               zend_hash_get_current_key(Z_ARRVAL_P(zoption), &cookie_key, NULL, 0);
+                               zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &cookie_val);
+                               smart_str_appends(&qstr, cookie_key);
+                               smart_str_appendl(&qstr, "=", 1);
+                               smart_str_appendl(&qstr, Z_STRVAL_PP(cookie_val), Z_STRLEN_PP(cookie_val));
+                               smart_str_appendl(&qstr, "; ", 2);
+                               zend_hash_move_forward(Z_ARRVAL_P(zoption));
+                       }
+               }
+               smart_str_0(&qstr);
+               
+               if (qstr.c) {
+                       curl_easy_setopt(ch, CURLOPT_COOKIE, qstr.c);
                }
        }
 
@@ -542,14 +572,22 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
                curl_easy_setopt(ch, CURLOPT_COOKIEJAR, Z_STRVAL_P(zoption));
        }
 
-       /* additional headers */
+       /* additional headers, array('name' => 'value') */
        if (zoption = http_curl_getopt1(options, "headers", IS_ARRAY)) {
-               zval **header;
+               int key_type;
+               char *header_key, header[1024] = {0};
+               zval **header_val;
                struct curl_slist *headers = NULL;
+               
                zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
-               while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &header)) {
-                       headers = curl_slist_append(headers, Z_STRVAL_PP(header));
-                       zend_hash_move_forward(Z_ARRVAL_P(zoption));
+               while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
+                       if (key_type == HASH_KEY_IS_STRING) {
+                               zend_hash_get_current_key(Z_ARRVAL_P(zoption), &header_key, NULL, 0);
+                               zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &header_val);
+                               snprintf(header, 1024, "%s: %s", header_key, Z_STRVAL_PP(header_val));
+                               headers = curl_slist_append(headers, header);
+                               zend_hash_move_forward(Z_ARRVAL_P(zoption));
+                       }
                }
                if (headers) {
                        curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
@@ -558,9 +596,168 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
 }
 /* }}} */
 
-#endif
-/* }}} HAVE_CURL */
+/* {{{ static inline char *http_curl_getinfoname(CURLINFO) */
+static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC)
+{
+#define CASE(I) case CURLINFO_ ##I : return #I
+       switch (i)
+       {
+               /* CURLINFO_EFFECTIVE_URL                       =       CURLINFO_STRING +1, */
+               CASE(EFFECTIVE_URL);
+               /* CURLINFO_RESPONSE_CODE                       =       CURLINFO_LONG   +2, */
+               CASE(RESPONSE_CODE);
+               /* CURLINFO_TOTAL_TIME                          =       CURLINFO_DOUBLE +3, */
+               CASE(TOTAL_TIME);
+               /* CURLINFO_NAMELOOKUP_TIME                     =       CURLINFO_DOUBLE +4, */
+               CASE(NAMELOOKUP_TIME);
+               /* CURLINFO_CONNECT_TIME                        =       CURLINFO_DOUBLE +5, */
+               CASE(CONNECT_TIME);
+               /* CURLINFO_PRETRANSFER_TIME            =       CURLINFO_DOUBLE +6, */
+               CASE(PRETRANSFER_TIME);
+               /* CURLINFO_SIZE_UPLOAD                         =       CURLINFO_DOUBLE +7, */
+               CASE(SIZE_UPLOAD);
+               /* CURLINFO_SIZE_DOWNLOAD                       =       CURLINFO_DOUBLE +8, */
+               CASE(SIZE_DOWNLOAD);
+               /* CURLINFO_SPEED_DOWNLOAD                      =       CURLINFO_DOUBLE +9, */
+               CASE(SPEED_DOWNLOAD);
+               /* CURLINFO_SPEED_UPLOAD                        =       CURLINFO_DOUBLE +10, */
+               CASE(SPEED_UPLOAD);
+               /* CURLINFO_HEADER_SIZE                         =       CURLINFO_LONG   +11, */
+               CASE(HEADER_SIZE);
+               /* CURLINFO_REQUEST_SIZE                        =       CURLINFO_LONG   +12, */
+               CASE(REQUEST_SIZE);
+               /* CURLINFO_SSL_VERIFYRESULT            =       CURLINFO_LONG   +13, */
+               CASE(SSL_VERIFYRESULT);
+               /* CURLINFO_FILETIME                            =       CURLINFO_LONG   +14, */
+               CASE(FILETIME);
+               /* CURLINFO_CONTENT_LENGTH_DOWNLOAD     =       CURLINFO_DOUBLE +15, */
+               CASE(CONTENT_LENGTH_DOWNLOAD);
+               /* CURLINFO_CONTENT_LENGTH_UPLOAD       =       CURLINFO_DOUBLE +16, */
+               CASE(CONTENT_LENGTH_UPLOAD);
+               /* CURLINFO_STARTTRANSFER_TIME          =       CURLINFO_DOUBLE +17, */
+               CASE(STARTTRANSFER_TIME);
+               /* CURLINFO_CONTENT_TYPE                        =       CURLINFO_STRING +18, */
+               CASE(CONTENT_TYPE);
+               /* CURLINFO_REDIRECT_TIME                       =       CURLINFO_DOUBLE +19, */
+               CASE(REDIRECT_TIME);
+               /* CURLINFO_REDIRECT_COUNT                      =       CURLINFO_LONG   +20, */
+               CASE(REDIRECT_COUNT);
+               /* CURLINFO_PRIVATE                                     =       CURLINFO_STRING +21, */
+               CASE(PRIVATE);
+               /* CURLINFO_HTTP_CONNECTCODE            =       CURLINFO_LONG   +22, */
+               CASE(HTTP_CONNECTCODE);
+               /* CURLINFO_HTTPAUTH_AVAIL                      =       CURLINFO_LONG   +23, */
+               CASE(HTTPAUTH_AVAIL);
+               /* CURLINFO_PROXYAUTH_AVAIL                     =       CURLINFO_LONG   +24, */
+               CASE(PROXYAUTH_AVAIL);
+       }
+#undef CASE
+       return NULL;
+}
+/* }}} */
 
+/* {{{ static inline void http_curl_getinfo_ex(CURL, CURLINFO, zval *) */
+static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC)
+{
+       char *key;
+       if (key = http_curl_getinfoname(i)) {
+               switch (i & ~CURLINFO_MASK)
+               {
+                       case CURLINFO_STRING:
+                       {
+                               char *c;
+                               if (CURLE_OK == curl_easy_getinfo(ch, i, &c)) {
+                                       add_assoc_string(array, key, c ? c : "", 1);
+                               }
+                       }
+                       break;
+
+                       case CURLINFO_DOUBLE:
+                       {
+                               double d;
+                               if (CURLE_OK == curl_easy_getinfo(ch, i, &d)) {
+                                       add_assoc_double(array, key, (double) d);
+                               }
+                       }
+                       break;
+
+                       case CURLINFO_LONG:
+                       {
+                               long l;
+                               if (CURLE_OK == curl_easy_getinfo(ch, i, &l)) {
+                                       add_assoc_long(array, key, (long) l);
+                               }
+                       }
+                       break;
+               }
+       }
+}
+/* }}} */
+
+/* {{{ static inline http_curl_getinfo(CURL, HashTable *) */
+static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC)
+{
+       zval *array;
+
+       MAKE_STD_ZVAL(array);
+       Z_ARRVAL_P(array) = info;
+
+#define INFO(I) http_curl_getinfo_ex(ch, CURLINFO_ ##I , array)
+       /* CURLINFO_EFFECTIVE_URL                       =       CURLINFO_STRING +1, */
+       INFO(EFFECTIVE_URL);
+       /* CURLINFO_RESPONSE_CODE                       =       CURLINFO_LONG   +2, */
+       INFO(RESPONSE_CODE);
+       /* CURLINFO_TOTAL_TIME                          =       CURLINFO_DOUBLE +3, */
+       INFO(TOTAL_TIME);
+       /* CURLINFO_NAMELOOKUP_TIME                     =       CURLINFO_DOUBLE +4, */
+       INFO(NAMELOOKUP_TIME);
+       /* CURLINFO_CONNECT_TIME                        =       CURLINFO_DOUBLE +5, */
+       INFO(CONNECT_TIME);
+       /* CURLINFO_PRETRANSFER_TIME            =       CURLINFO_DOUBLE +6, */
+       INFO(PRETRANSFER_TIME);
+       /* CURLINFO_SIZE_UPLOAD                         =       CURLINFO_DOUBLE +7, */
+       INFO(SIZE_UPLOAD);
+       /* CURLINFO_SIZE_DOWNLOAD                       =       CURLINFO_DOUBLE +8, */
+       INFO(SIZE_DOWNLOAD);
+       /* CURLINFO_SPEED_DOWNLOAD                      =       CURLINFO_DOUBLE +9, */
+       INFO(SPEED_DOWNLOAD);
+       /* CURLINFO_SPEED_UPLOAD                        =       CURLINFO_DOUBLE +10, */
+       INFO(SPEED_UPLOAD);
+       /* CURLINFO_HEADER_SIZE                         =       CURLINFO_LONG   +11, */
+       INFO(HEADER_SIZE);
+       /* CURLINFO_REQUEST_SIZE                        =       CURLINFO_LONG   +12, */
+       INFO(REQUEST_SIZE);
+       /* CURLINFO_SSL_VERIFYRESULT            =       CURLINFO_LONG   +13, */
+       INFO(SSL_VERIFYRESULT);
+       /* CURLINFO_FILETIME                            =       CURLINFO_LONG   +14, */
+       INFO(FILETIME);
+       /* CURLINFO_CONTENT_LENGTH_DOWNLOAD     =       CURLINFO_DOUBLE +15, */
+       INFO(CONTENT_LENGTH_DOWNLOAD);
+       /* CURLINFO_CONTENT_LENGTH_UPLOAD       =       CURLINFO_DOUBLE +16, */
+       INFO(CONTENT_LENGTH_UPLOAD);
+       /* CURLINFO_STARTTRANSFER_TIME          =       CURLINFO_DOUBLE +17, */
+       INFO(STARTTRANSFER_TIME);
+       /* CURLINFO_CONTENT_TYPE                        =       CURLINFO_STRING +18, */
+       INFO(CONTENT_TYPE);
+       /* CURLINFO_REDIRECT_TIME                       =       CURLINFO_DOUBLE +19, */
+       INFO(REDIRECT_TIME);
+       /* CURLINFO_REDIRECT_COUNT                      =       CURLINFO_LONG   +20, */
+       INFO(REDIRECT_COUNT);
+       /* CURLINFO_PRIVATE                                     =       CURLINFO_STRING +21, */
+       INFO(PRIVATE);
+       /* CURLINFO_HTTP_CONNECTCODE            =       CURLINFO_LONG   +22, */
+       INFO(HTTP_CONNECTCODE);
+       /* CURLINFO_HTTPAUTH_AVAIL                      =       CURLINFO_LONG   +23, */
+       INFO(HTTPAUTH_AVAIL);
+       /* CURLINFO_PROXYAUTH_AVAIL                     =       CURLINFO_LONG   +24, */
+       INFO(PROXYAUTH_AVAIL);
+#undef INFO
+       efree(array);
+}
+/* }}} */
+
+/* {{{ Day/Month/TZ checks for http_parse_date()
+       Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
 static int check_day(char *day, size_t len)
 {
        int i;
@@ -602,6 +799,10 @@ static int check_tzone(char *tzone)
        }
        return -1;
 }
+/* }}} */
+
+#endif
+/* }}} HAVE_CURL */
 
 /* }}} internals */
 
@@ -624,12 +825,12 @@ PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC)
 }
 /* }}} */
 
-/* time_t http_parse_date(char *)
+/* {{{ time_t http_parse_date(char *)
        Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
-PHP_HTTP_API time_t http_parse_date(const char *date)
+PHP_HTTP_API time_t _http_parse_date(const char *date)
 {
        time_t t = 0;
-       int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1, 
+       int tz_offset = -1, year = -1, month = -1, monthday = -1, weekday = -1,
                hours = -1, minutes = -1, seconds = -1;
        struct tm tm;
        enum assume_next dignext = DATE_MDAY;
@@ -657,14 +858,14 @@ PHP_HTTP_API time_t http_parse_date(const char *date)
                                        found = 1;
                                }
                        }
-                       
+
                        if (!found && (month == -1)) {
                                month = check_month(buf);
                                if (month != -1) {
                                        found = 1;
                                }
                        }
-                       
+
                        if (!found && (tz_offset == -1)) {
                                /* this just must be a time zone string */
                                tz_offset = check_tzone(buf);
@@ -672,7 +873,7 @@ PHP_HTTP_API time_t http_parse_date(const char *date)
                                        found = 1;
                                }
                        }
-                       
+
                        if (!found) {
                                return -1; /* bad string */
                        }
@@ -786,7 +987,7 @@ PHP_HTTP_API time_t http_parse_date(const char *date)
                if((delta > 0) && (t + delta < t)) {
                        return -1; /* time_t overflow */
                }
-               
+
                t += delta;
        }
 
@@ -1499,9 +1700,9 @@ PHP_HTTP_API void _http_split_response(const zval *zresponse, zval *zheaders,
 /* {{{ HAVE_CURL */
 #if defined(HAVE_CURL) && HAVE_CURL
 
-/* {{{ STATUS http_get(char *, HashTable *, char **, size_t *) */
+/* {{{ STATUS http_get(char *, HashTable *, HashTable *, char **, size_t *) */
 PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
-       char **data, size_t *data_len TSRMLS_DC)
+       HashTable *info, char **data, size_t *data_len TSRMLS_DC)
 {
        CURL *ch = curl_easy_init();
 
@@ -1519,6 +1720,9 @@ PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
                return FAILURE;
        }
+       if (info) {
+               http_curl_getinfo(ch, info);
+       }
        curl_easy_cleanup(ch);
 
        http_curl_movebuf(CURLBUF_EVRY, data, data_len);
@@ -1527,9 +1731,9 @@ PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
 }
 /* }}} */
 
-/* {{{ STATUS http_head(char *, HashTable *, char **data, size_t *) */
+/* {{{ STATUS http_head(char *, HashTable *, HashTable *, char **data, size_t *) */
 PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
-       char **data, size_t *data_len TSRMLS_DC)
+       HashTable *info, char **data, size_t *data_len TSRMLS_DC)
 {
        CURL *ch = curl_easy_init();
 
@@ -1548,6 +1752,9 @@ PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
                return FAILURE;
        }
+       if (info) {
+               http_curl_getinfo(ch, info);
+       }
        curl_easy_cleanup(ch);
 
        http_curl_movebuf(CURLBUF_HDRS, data, data_len);
@@ -1556,9 +1763,9 @@ PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
 }
 /* }}} */
 
-/* {{{ STATUS http_post_data(char *, char *, size_t, HashTable *, char **, size_t *) */
+/* {{{ STATUS http_post_data(char *, char *, size_t, HashTable *, HashTable *, char **, size_t *) */
 PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata,
-       size_t postdata_len, HashTable *options, char **data,
+       size_t postdata_len, HashTable *options, HashTable *info, char **data,
        size_t *data_len TSRMLS_DC)
 {
        CURL *ch = curl_easy_init();
@@ -1580,6 +1787,9 @@ PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata,
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
                return FAILURE;
        }
+       if (info) {
+               http_curl_getinfo(ch, info);
+       }
        curl_easy_cleanup(ch);
 
        http_curl_movebuf(CURLBUF_EVRY, data, data_len);
@@ -1588,9 +1798,9 @@ PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata,
 }
 /* }}} */
 
-/* {{{ STATUS http_post_array(char *, HashTable *, HashTable *, char **, size_t *) */
+/* {{{ STATUS http_post_array(char *, HashTable *, HashTable *, HashTable *, char **, size_t *) */
 PHP_HTTP_API STATUS _http_post_array(const char *URL, HashTable *postarray,
-       HashTable *options, char **data, size_t *data_len TSRMLS_DC)
+       HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC)
 {
        smart_str qstr = {0};
        STATUS status;
@@ -1604,7 +1814,7 @@ PHP_HTTP_API STATUS _http_post_array(const char *URL, HashTable *postarray,
        }
        smart_str_0(&qstr);
 
-       status = http_post_data(URL, qstr.c, qstr.len, options, data, data_len);
+       status = http_post_data(URL, qstr.c, qstr.len, options, info, data, data_len);
        if (qstr.c) {
                efree(qstr.c);
        }
index 1012a12536b8197f305deb446b7a76ecf3dda18a..49804244b3048e2aed92a9436e1a6f4085c0f087 100644 (file)
@@ -45,7 +45,6 @@ PHP_FUNCTION(http_match_modified);
 PHP_FUNCTION(http_match_etag);
 PHP_FUNCTION(http_cache_last_modified);
 PHP_FUNCTION(http_cache_etag);
-PHP_FUNCTION(http_accept_ranges);
 PHP_FUNCTION(http_content_type);
 PHP_FUNCTION(http_content_disposition);
 PHP_FUNCTION(http_send_data);
index d3ef217c8007edd82b37d862639a5ddb5c3acab1..53198e1b53e4799d843a716acb9e04664df51149 100644 (file)
@@ -83,7 +83,8 @@ typedef enum {
 #define http_date(t) _http_date((t) TSRMLS_CC)
 PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC);
 
-PHP_HTTP_API time_t http_parse_date(const char *date);
+#define http_parse_date(d) _http_parse_date((d))
+PHP_HTTP_API time_t _http_parse_date(const char *date);
 
 #define http_send_status(s) _http_send_status((s) TSRMLS_CC)
 PHP_HTTP_API inline STATUS _http_send_status(const int status TSRMLS_DC);
@@ -147,17 +148,17 @@ PHP_HTTP_API void _http_split_response(const zval *zresponse, zval *zheaders, zv
 /* {{{ HAVE_CURL */
 #if defined(HAVE_CURL) && HAVE_CURL
 
-#define http_get(u, o, d, l) _http_get((u), (o), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options, char **data, size_t *data_len TSRMLS_DC);
+#define http_get(u, o, i, d, l) _http_get((u), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
 
-#define http_head(u, o, d, l) _http_head((u), (o), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options, char **data, size_t *data_len TSRMLS_DC);
+#define http_head(u, o, i, d, l) _http_head((u), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
 
-#define http_post_data(u, pd, pl, o, d, l) _http_post_data((u), (pd), (pl), (o), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata, size_t postdata_len, HashTable *options, char **data, size_t *data_len TSRMLS_DC);
+#define http_post_data(u, pd, pl, o, i, d, l) _http_post_data((u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata, size_t postdata_len, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
 
-#define http_post_array(u, p, o, d, l) _http_post_array((u), (p), (o), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_array(const char *URL, HashTable *postarray, HashTable *options, char **data, size_t *data_len TSRMLS_DC);
+#define http_post_array(u, p, o, i, d, l) _http_post_array((u), (p), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_array(const char *URL, HashTable *postarray, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
 
 #endif
 /* }}} HAVE_CURL */