* release 0.6.0
[m6w6/ext-http] / http_functions.c
index 8b79f42497beffd47140e6b272bbb9fb291c0169..2e72ab853dafcf82ebfab327ff56703b9f059adf 100644 (file)
@@ -15,6 +15,9 @@
 
 /* $Id$ */
 
+#define _WINSOCKAPI_
+#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
+
 #ifdef HAVE_CONFIG_H
 #      include "config.h"
 #endif
@@ -32,6 +35,7 @@
 #include "php_http.h"
 #include "php_http_api.h"
 #include "php_http_curl_api.h"
+#include "php_http_std_defs.h"
 
 ZEND_DECLARE_MODULE_GLOBALS(http)
 
@@ -265,7 +269,7 @@ PHP_FUNCTION(http_send_content_disposition)
 }
 /* }}} */
 
-/* {{{ proto bool http_match_modified([int timestamp])
+/* {{{ proto bool http_match_modified([int timestamp[, for_range = false]])
  *
  * Matches the given timestamp against the clients "If-Modified-Since" resp.
  * "If-Unmodified-Since" HTTP headers.
@@ -274,8 +278,9 @@ PHP_FUNCTION(http_send_content_disposition)
 PHP_FUNCTION(http_match_modified)
 {
        long t = -1;
+       zend_bool for_range = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &t, &for_range) != SUCCESS) {
                RETURN_FALSE;
        }
 
@@ -284,11 +289,14 @@ PHP_FUNCTION(http_match_modified)
                t = (long) time(NULL);
        }
 
-       RETURN_BOOL(http_modified_match("HTTP_IF_MODIFIED_SINCE", t) || http_modified_match("HTTP_IF_UNMODIFIED_SINCE", t));
+       if (for_range) {
+               RETURN_BOOL(http_modified_match("HTTP_IF_UNMODIFIED_SINCE", t));
+       }
+       RETURN_BOOL(http_modified_match("HTTP_IF_MODIFIED_SINCE", t));
 }
 /* }}} */
 
-/* {{{ proto bool http_match_etag(string etag)
+/* {{{ proto bool http_match_etag(string etag[, for_range = false])
  *
  * This matches the given ETag against the clients
  * "If-Match" resp. "If-None-Match" HTTP headers.
@@ -298,12 +306,16 @@ PHP_FUNCTION(http_match_etag)
 {
        int etag_len;
        char *etag;
+       zend_bool for_range = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &etag, &etag_len, &for_range) != SUCCESS) {
                RETURN_FALSE;
        }
 
-       RETURN_BOOL(http_etag_match("HTTP_IF_NONE_MATCH", etag) || http_etag_match("HTTP_IF_MATCH", etag));
+       if (for_range) {
+               RETURN_BOOL(http_etag_match("HTTP_IF_MATCH", etag));
+       }
+       RETURN_BOOL(http_etag_match("HTTP_IF_NONE_MATCH", etag));
 }
 /* }}} */
 
@@ -426,10 +438,12 @@ PHP_FUNCTION(ob_httpetaghandler)
 PHP_FUNCTION(http_redirect)
 {
        int url_len;
+       size_t query_len = 0;
        zend_bool session = 0, permanent = 0;
        zval *params = NULL;
-       smart_str qstr = {0};
-       char *url, *URI, LOC[HTTP_URI_MAXLEN + 9], RED[HTTP_URI_MAXLEN * 2 + 34];
+       char *query, *url, *URI,
+               LOC[HTTP_URI_MAXLEN + sizeof("Location: ")],
+               RED[HTTP_URI_MAXLEN * 2 + sizeof("Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n")];
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bb", &url, &url_len, &params, &session, &permanent) != SUCCESS) {
                RETURN_FALSE;
@@ -448,23 +462,18 @@ PHP_FUNCTION(http_redirect)
 
        /* treat params array with http_build_query() */
        if (params) {
-               if (php_url_encode_hash_ex(Z_ARRVAL_P(params), &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) {
-                       if (qstr.c) {
-                               efree(qstr.c);
-                       }
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode query parameters");
+               if (SUCCESS != http_urlencode_hash_ex(Z_ARRVAL_P(params), 0, NULL, 0, &query, &query_len)) {
                        RETURN_FALSE;
                }
-               smart_str_0(&qstr);
        }
 
        URI = http_absolute_uri(url, NULL);
-       if (qstr.c) {
-               snprintf(LOC, HTTP_URI_MAXLEN + strlen("Location: "), "Location: %s?%s", URI, qstr.c);
-               sprintf(RED, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, qstr.c, URI, qstr.c);
-               efree(qstr.c);
+       if (query_len) {
+               snprintf(LOC, HTTP_URI_MAXLEN + sizeof("Location: "), "Location: %s?%s", URI, query);
+               sprintf(RED, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, query, URI, query);
+               efree(query);
        } else {
-               snprintf(LOC, HTTP_URI_MAXLEN + strlen("Location: "), "Location: %s", URI);
+               snprintf(LOC, HTTP_URI_MAXLEN + sizeof("Location: "), "Location: %s", URI);
                sprintf(RED, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
        }
        efree(URI);
@@ -492,7 +501,7 @@ PHP_FUNCTION(http_send_data)
 
        convert_to_string_ex(&zdata);
        http_send_header("Accept-Ranges: bytes");
-       RETURN_SUCCESS(http_send_data(zdata));
+       RETURN_SUCCESS(http_send_data(Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)));
 }
 /* }}} */
 
@@ -503,15 +512,18 @@ PHP_FUNCTION(http_send_data)
  */
 PHP_FUNCTION(http_send_file)
 {
-       zval *zfile;
+       char *file;
+       int flen = 0;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zfile) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &file, &flen) != SUCCESS) {
+               RETURN_FALSE;
+       }
+       if (!flen) {
                RETURN_FALSE;
        }
 
-       convert_to_string_ex(&zfile);
        http_send_header("Accept-Ranges: bytes");
-       RETURN_SUCCESS(http_send_file(zfile));
+       RETURN_SUCCESS(http_send_file(file));
 }
 /* }}} */
 
@@ -568,6 +580,7 @@ PHP_FUNCTION(http_chunked_decode)
  *     0 => array(
  *         'Status' => '200 Ok',
  *         'Content-Type' => 'text/plain',
+
  *         'Content-Language' => 'en-US'
  *     ),
  *     1 => "Hello World!"
@@ -630,9 +643,7 @@ PHP_FUNCTION(http_parse_headers)
  */
 PHP_FUNCTION(http_get_request_headers)
 {
-       if (ZEND_NUM_ARGS()) {
-               WRONG_PARAM_COUNT;
-       }
+       NO_ARGS;
 
        array_init(return_value);
        http_get_request_headers(return_value);
@@ -669,6 +680,13 @@ PHP_FUNCTION(http_get_request_headers)
  *  - cookies:          array, list of cookies as associative array
  *                      like array("cookie" => "value")
  *  - cookiestore:      string, path to a file where cookies are/will be stored
+ *  - resume:           int, byte offset to start the download from;
+ *                      if the server supports ranges
+ *  - maxfilesize:      int, maximum file size that should be downloaded;
+ *                      has no effect, if the size of the requested entity is not known
+ *  - lastmodified:     int, timestamp for If-(Un)Modified-Since header
+ *  - timeout:          int, seconds the request may take
+ *  - connecttimeout:   int, seconds the connect may take
  * </pre>
  *
  * The optional third parameter will be filled with some additional information
@@ -879,7 +897,6 @@ PHP_FUNCTION(http_auth_basic)
  *     }
  *     return false;
  * }
- *
  * if (!http_auth_basic_cb('auth_cb')) {
  *     die('<h1>Authorization failed</h1>');
  * }
@@ -932,6 +949,45 @@ PHP_FUNCTION(http_auth_basic_cb)
 }
 /* }}}*/
 
+/* {{{ Sara Golemons http_build_query() */
+#ifndef ZEND_ENGINE_2
+
+/* {{{ proto string http_build_query(mixed formdata [, string prefix])
+   Generates a form-encoded query string from an associative array or object. */
+PHP_FUNCTION(http_build_query)
+{
+       zval *formdata;
+       char *prefix = NULL;
+       int prefix_len = 0;
+       smart_str formstr = {0};
+
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &formdata, &prefix, &prefix_len) != SUCCESS) {
+               RETURN_FALSE;
+       }
+
+       if (Z_TYPE_P(formdata) != IS_ARRAY && Z_TYPE_P(formdata) != IS_OBJECT) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter 1 expected to be Array or Object.  Incorrect value given.");
+               RETURN_FALSE;
+       }
+
+       if (php_url_encode_hash_ex(HASH_OF(formdata), &formstr, prefix, prefix_len, NULL, 0, NULL, 0, (Z_TYPE_P(formdata) == IS_OBJECT ? formdata : NULL) TSRMLS_CC) == FAILURE) {
+               if (formstr.c) {
+                       efree(formstr.c);
+               }
+               RETURN_FALSE;
+       }
+
+       if (!formstr.c) {
+               RETURN_NULL();
+       }
+
+       smart_str_0(&formstr);
+
+       RETURN_STRINGL(formstr.c, formstr.len, 0);
+}
+/* }}} */
+#endif /* !ZEND_ENGINE_2 */
+/* }}} */
 
 /*
  * Local variables:
@@ -941,3 +997,4 @@ PHP_FUNCTION(http_auth_basic_cb)
  * vim600: noet sw=4 ts=4 fdm=marker
  * vim<600: noet sw=4 ts=4
  */
+