- export http_parse_cookie()
[m6w6/ext-http] / http_functions.c
index e731d9af041343c08112d467568f228d7d7a9f75..80030ce0469279b2ba76545b7c2471a5b5598aea 100644 (file)
 #ifdef HAVE_CONFIG_H
 #      include "config.h"
 #endif
-#include "php.h"
 
-#include "zend_operators.h"
+#define HTTP_WANT_CURL
+#include "php_http.h"
 
 #include "SAPI.h"
 #include "php_ini.h"
 #include "ext/standard/info.h"
 #include "ext/standard/php_string.h"
+#include "zend_operators.h"
+
 #if defined(HAVE_PHP_SESSION) && !defined(COMPILE_DL_SESSION)
 #      include "ext/session/php_session.h"
 #endif
 
-#include "php_http.h"
-#include "php_http_std_defs.h"
 #include "php_http_api.h"
-#include "php_http_request_api.h"
 #include "php_http_cache_api.h"
-#include "php_http_request_method_api.h"
-#include "php_http_request_api.h"
 #include "php_http_date_api.h"
+#include "php_http_encoding_api.h"
 #include "php_http_headers_api.h"
 #include "php_http_message_api.h"
+#include "php_http_request_api.h"
+#include "php_http_request_method_api.h"
 #include "php_http_send_api.h"
 #include "php_http_url_api.h"
-#include "php_http_encoding_api.h"
-
-#include "phpstr/phpstr.h"
 
 ZEND_EXTERN_MODULE_GLOBALS(http)
 
@@ -82,7 +79,7 @@ PHP_FUNCTION(http_date)
  * If a port is pecified in either the url or as sperate parameter,
  * it will be added if it differs from te default port for HTTP(S).
  * 
- * Returns the absolute URI as string.
+ * Returns the absolute URI as string on success or false on failure.
  * 
  * Examples:
  * <pre>
@@ -93,7 +90,7 @@ PHP_FUNCTION(http_date)
  */
 PHP_FUNCTION(http_build_uri)
 {
-       char *url = NULL, *proto = NULL, *host = NULL;
+       char *url = NULL, *proto = NULL, *host = NULL, *built = NULL;
        int url_len = 0, proto_len = 0, host_len = 0;
        long port = 0;
 
@@ -101,7 +98,10 @@ PHP_FUNCTION(http_build_uri)
                RETURN_FALSE;
        }
 
-       RETURN_STRING(http_absolute_uri_ex(url, url_len, proto, proto_len, host, host_len, port), 0);
+       if ((built = http_absolute_uri_ex(url, url_len, proto, proto_len, host, host_len, port))) {
+               RETURN_STRING(built, 0);
+       }
+       RETURN_FALSE;
 }
 /* }}} */
 
@@ -894,6 +894,7 @@ PHP_FUNCTION(http_parse_message)
  *         )
  *     [Folded] => works
  *         too 
+ * ) 
  * ?>
  * </pre>
  */
@@ -914,6 +915,44 @@ PHP_FUNCTION(http_parse_headers)
 }
 /* }}}*/
 
+/* {{{ proto object http_parse_cookie(string cookie)
+ *
+ * Parses HTTP cookies like sent in a response into a struct.
+ * 
+ * Expects a string as parameter containing the value of a Set-Cookie response header.
+ * 
+ * Returns an stdClass object with the cookie params as properties on success or FALSE on failure.
+ * 
+ * Example:
+ * <pre>
+ * <?php
+ * print_r(http_parse_cookie("foo=bar; path=/"));
+ * 
+ * stdClass Object
+ * (
+ *     [name] => foo
+ *     [value] => bar
+ *     [path] => /
+ * )
+ * ?>
+ * </pre> 
+ */
+PHP_FUNCTION(http_parse_cookie)
+{
+       char *cookie;
+       int cookie_len;
+       
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &cookie, &cookie_len)) {
+               RETURN_FALSE;
+       }
+       
+       object_init(return_value);
+       if (SUCCESS != http_parse_cookie(cookie, HASH_OF(return_value))) {
+               zval_dtor(return_value);
+               RETURN_FALSE;
+       }
+}
+
 /* {{{ proto array http_get_request_headers(void)
  *
  * Get a list of incoming HTTP headers.
@@ -977,6 +1016,23 @@ PHP_FUNCTION(http_match_request_header)
 /* {{{ HAVE_CURL */
 #ifdef HTTP_HAVE_CURL
 
+#define RETVAL_RESPONSE_OR_BODY(request) \
+       { \
+               zval **bodyonly; \
+                \
+               /* check if only the body should be returned */ \
+               if (options && (SUCCESS == zend_hash_find(Z_ARRVAL_P(options), "bodyonly", sizeof("bodyonly"), (void **) &bodyonly)) && zval_is_true(*bodyonly)) { \
+                       http_message *msg = http_message_parse(PHPSTR_VAL(&request.conv.response), PHPSTR_LEN(&request.conv.response)); \
+                        \
+                       if (msg) { \
+                               RETVAL_STRINGL(PHPSTR_VAL(&msg->body), PHPSTR_LEN(&msg->body), 1); \
+                               http_message_free(&msg); \
+                       } \
+               } else { \
+                       RETVAL_STRINGL(request.conv.response.data, request.conv.response.used, 1); \
+               } \
+       }
+
 /* {{{ proto string http_get(string url[, array options[, array &info]])
  *
  * Performs an HTTP GET request on the supplied url.
@@ -1053,7 +1109,7 @@ PHP_FUNCTION(http_get)
        zval *options = NULL, *info = NULL;
        char *URL;
        int URL_len;
-       phpstr response;
+       http_request request;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
                RETURN_FALSE;
@@ -1064,13 +1120,17 @@ PHP_FUNCTION(http_get)
                array_init(info);
        }
 
-       phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
-       if (SUCCESS == http_get(URL, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
-               RETURN_PHPSTR_VAL(&response);
-       } else {
-               phpstr_dtor(&response);
-               RETURN_FALSE;
+       RETVAL_FALSE;
+
+       http_request_init_ex(&request, NULL, HTTP_GET, URL);
+       if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+               http_request_exec(&request);
+               if (info) {
+                       http_request_info(&request, Z_ARRVAL_P(info));
+               }
+               RETVAL_RESPONSE_OR_BODY(request);
        }
+       http_request_dtor(&request);
 }
 /* }}} */
 
@@ -1087,7 +1147,7 @@ PHP_FUNCTION(http_head)
        zval *options = NULL, *info = NULL;
        char *URL;
        int URL_len;
-       phpstr response;
+       http_request request;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
                RETURN_FALSE;
@@ -1098,13 +1158,17 @@ PHP_FUNCTION(http_head)
                array_init(info);
        }
 
-       phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
-       if (SUCCESS == http_head(URL, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
-               RETURN_PHPSTR_VAL(&response);
-       } else {
-               phpstr_dtor(&response);
-               RETURN_FALSE;
+       RETVAL_FALSE;
+
+       http_request_init_ex(&request, NULL, HTTP_HEAD, URL);
+       if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+               http_request_exec(&request);
+               if (info) {
+                       http_request_info(&request, Z_ARRVAL_P(info));
+               }
+               RETVAL_RESPONSE_OR_BODY(request);
        }
+       http_request_dtor(&request);
 }
 /* }}} */
 
@@ -1122,8 +1186,8 @@ PHP_FUNCTION(http_post_data)
        zval *options = NULL, *info = NULL;
        char *URL, *postdata;
        int postdata_len, URL_len;
-       phpstr response;
        http_request_body body;
+       http_request request;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
                RETURN_FALSE;
@@ -1134,17 +1198,18 @@ PHP_FUNCTION(http_post_data)
                array_init(info);
        }
 
-       body.type = HTTP_REQUEST_BODY_CSTRING;
-       body.data = postdata;
-       body.size = postdata_len;
+       RETVAL_FALSE;
 
-       phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
-       if (SUCCESS == http_post(URL, &body, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
-               RETVAL_PHPSTR_VAL(&response);
-       } else {
-               phpstr_dtor(&response);
-               RETVAL_FALSE;
+       http_request_init_ex(&request, NULL, HTTP_POST, URL);
+       request.body = http_request_body_init_ex(&body, HTTP_REQUEST_BODY_CSTRING, postdata, postdata_len, 0);
+       if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+               http_request_exec(&request);
+               if (info) {
+                       http_request_info(&request, Z_ARRVAL_P(info));
+               }
+               RETVAL_RESPONSE_OR_BODY(request);
        }
+       http_request_dtor(&request);
 }
 /* }}} */
 
@@ -1162,14 +1227,14 @@ PHP_FUNCTION(http_post_fields)
        zval *options = NULL, *info = NULL, *fields, *files = NULL;
        char *URL;
        int URL_len;
-       phpstr response;
        http_request_body body;
+       http_request request;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|aa/!z", &URL, &URL_len, &fields, &files, &options, &info) != SUCCESS) {
                RETURN_FALSE;
        }
 
-       if (SUCCESS != http_request_body_fill(&body, Z_ARRVAL_P(fields), files ? Z_ARRVAL_P(files) : NULL)) {
+       if (!http_request_body_fill(&body, Z_ARRVAL_P(fields), files ? Z_ARRVAL_P(files) : NULL)) {
                RETURN_FALSE;
        }
 
@@ -1178,14 +1243,18 @@ PHP_FUNCTION(http_post_fields)
                array_init(info);
        }
 
-       phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
-       if (SUCCESS == http_post(URL, &body, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
-               RETVAL_PHPSTR_VAL(&response);
-       } else {
-               phpstr_dtor(&response);
-               RETVAL_FALSE;
+       RETVAL_FALSE;
+
+       http_request_init_ex(&request, NULL, HTTP_POST, URL);
+       request.body = &body;
+       if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+               http_request_exec(&request);
+               if (info) {
+                       http_request_info(&request, Z_ARRVAL_P(info));
+               }
+               RETVAL_RESPONSE_OR_BODY(request);
        }
-       http_request_body_dtor(&body);
+       http_request_dtor(&request);
 }
 /* }}} */
 
@@ -1203,10 +1272,10 @@ PHP_FUNCTION(http_put_file)
        char *URL, *file;
        int URL_len, f_len;
        zval *options = NULL, *info = NULL;
-       phpstr response;
        php_stream *stream;
        php_stream_statbuf ssb;
        http_request_body body;
+       http_request request;
 
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &file, &f_len, &options, &info)) {
                RETURN_FALSE;
@@ -1225,18 +1294,24 @@ PHP_FUNCTION(http_put_file)
                array_init(info);
        }
 
+       RETVAL_FALSE;
+
        body.type = HTTP_REQUEST_BODY_UPLOADFILE;
        body.data = stream;
        body.size = ssb.sb.st_size;
 
-       phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
-       if (SUCCESS == http_put(URL, &body, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
-               RETVAL_PHPSTR_VAL(&response);
-       } else {
-               phpstr_dtor(&response);
-               RETVAL_FALSE;
+       http_request_init_ex(&request, NULL, HTTP_PUT, URL);
+       request.body = &body;
+       if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+               http_request_exec(&request);
+               if (info) {
+                       http_request_info(&request, Z_ARRVAL_P(info));
+               }
+               RETVAL_RESPONSE_OR_BODY(request);
        }
        http_request_body_dtor(&body);
+       request.body = NULL;
+       http_request_dtor(&request);
 }
 /* }}} */
 
@@ -1255,10 +1330,10 @@ PHP_FUNCTION(http_put_stream)
        zval *resource, *options = NULL, *info = NULL;
        char *URL;
        int URL_len;
-       phpstr response;
        php_stream *stream;
        php_stream_statbuf ssb;
        http_request_body body;
+       http_request request;
 
        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr|a/!z", &URL, &URL_len, &resource, &options, &info)) {
                RETURN_FALSE;
@@ -1274,17 +1349,23 @@ PHP_FUNCTION(http_put_stream)
                array_init(info);
        }
 
+       RETVAL_FALSE;
+
        body.type = HTTP_REQUEST_BODY_UPLOADFILE;
        body.data = stream;
        body.size = ssb.sb.st_size;
 
-       phpstr_init_ex(&response, HTTP_CURLBUF_SIZE, 0);
-       if (SUCCESS == http_put(URL, &body, options ? Z_ARRVAL_P(options) : NULL, info ? Z_ARRVAL_P(info) : NULL, &response)) {
-               RETURN_PHPSTR_VAL(&response);
-       } else {
-               phpstr_dtor(&response);
-               RETURN_NULL();
+       http_request_init_ex(&request, NULL, HTTP_POST, URL);
+       request.body = &body;
+       if (SUCCESS == http_request_prepare(&request, options?Z_ARRVAL_P(options):NULL)) {
+               http_request_exec(&request);
+               if (info) {
+                       http_request_info(&request, Z_ARRVAL_P(info));
+               }
+               RETVAL_RESPONSE_OR_BODY(request);
        }
+       request.body = NULL;
+       http_request_dtor(&request);
 }
 /* }}} */
 #endif /* HTTP_HAVE_CURL */
@@ -1453,7 +1534,7 @@ PHP_FUNCTION(http_build_query)
 /* {{{ */
 #ifdef HTTP_HAVE_ZLIB
 
-/* {{{ proto string http_gzencode(string data[, int level = -1])
+/* {{{ proto string http_gzencode(string data[, int level = -1[, int mtime = 0]])
  *
  * Compress data with the HTTP compatible GZIP encoding.
  * 
@@ -1468,17 +1549,17 @@ PHP_FUNCTION(http_gzencode)
 {
        char *data;
        int data_len;
-       long level = -1;
+       long level = -1, mtime = 0;
 
        RETVAL_NULL();
        
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level)) {
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &data, &data_len, &level, &mtime)) {
                HTTP_CHECK_GZIP_LEVEL(level, return);
                {
                        char *encoded;
                        size_t encoded_len;
                        
-                       if (SUCCESS == http_encoding_gzencode(level, data, data_len, &encoded, &encoded_len)) {
+                       if (SUCCESS == http_encoding_gzencode(level, mtime, data, data_len, &encoded, &encoded_len)) {
                                RETURN_STRINGL(encoded, (int) encoded_len, 0);
                        }
                }
@@ -1512,7 +1593,7 @@ PHP_FUNCTION(http_gzdecode)
 }
 /* }}} */
 
-/* {{{  proto string http_deflate(string data[, int level = -1])
+/* {{{  proto string http_deflate(string data[, int level = -1[, bool zlib_header = false]])
  *
  * Compress data with the HTTP compatible DEFLATE encoding.
  * 
@@ -1528,16 +1609,17 @@ PHP_FUNCTION(http_deflate)
        char *data;
        int data_len;
        long level = -1;
+       zend_bool zhdr = 0;
        
        RETVAL_NULL();
        
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level)) {
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &data, &data_len, &level, &zhdr)) {
                HTTP_CHECK_GZIP_LEVEL(level, return);
                {
                        char *encoded;
                        size_t encoded_len;
                        
-                       if (SUCCESS == http_encoding_deflate(level, data, data_len, &encoded, &encoded_len)) {
+                       if (SUCCESS == http_encoding_deflate(level, zhdr, data, data_len, &encoded, &encoded_len)) {
                                RETURN_STRINGL(encoded, (int) encoded_len, 0);
                        }
                }
@@ -1571,64 +1653,6 @@ PHP_FUNCTION(http_inflate)
 }
 /* }}} */
 
-/* {{{ proto string http_compress(string data[, int level = -1])
- *
- * Compress data with the HTTP compatible COMPRESS encoding.
- * 
- * Expects the first parameter to be a string containing the data which should
- * be encoded.  Additionally accepts an optional int parameter specifying the
- * compression level, where -1 is default, 0 is no compression and 9 is best
- * compression ratio.
- * 
- * Returns the encoded string on success, or NULL on failure.
- */
-PHP_FUNCTION(http_compress)
-{
-       char *data;
-       int data_len;
-       long level = -1;
-       
-       RETVAL_NULL();
-       
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &level)) {
-               HTTP_CHECK_GZIP_LEVEL(level, return);
-               {
-                       char *encoded;
-                       size_t encoded_len;
-                       
-                       if (SUCCESS == http_encoding_compress(level, data, data_len, &encoded, &encoded_len)) {
-                               RETURN_STRINGL(encoded, (int) encoded_len, 0);
-                       }
-               }
-       }
-}
-/* }}} */
-
-/* {{{ proto string http_uncompress(string data)
- *
- * Uncompress data compressed with the HTTP compatible COMPRESS encoding.
- * 
- * Expects a string as parameter containing the compressed data.
- * 
- * Returns the decoded string on success, or NULL on failure.
- */
-PHP_FUNCTION(http_uncompress)
-{
-       char *data;
-       int data_len;
-       
-       RETVAL_NULL();
-       
-       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &data, &data_len)) {
-               char *decoded;
-               size_t decoded_len;
-               
-               if (SUCCESS == http_encoding_uncompress(data, data_len, &decoded, &decoded_len)) {
-                       RETURN_STRINGL(decoded, (int) decoded_len, 0);
-               }
-       }
-}
-/* }}} */
 #endif /* HTTP_HAVE_ZLIB */
 /* }}} */
 
@@ -1649,8 +1673,6 @@ PHP_FUNCTION(http_uncompress)
  *       and SSL requests can be issued 
  *  <li> HTTP_SUPPORT_ENCODINGS: whether ext/http was linked against zlib,
  *       and compressed HTTP responses can be decoded
- *  <li> HTTP_SUPPORT_MHASHETAGS: whether ext/http was linked against libmhash,
- *       and ETags can be generated with the available mhash algorithms
  *  <li> HTTP_SUPPORT_MAGICMIME: whether ext/http was linked against libmagic,
  *       and the HttpResponse::guessContentType() method is usable
  * </ul>