- add ob_(deflate|inflate)handler
[m6w6/ext-http] / http_functions.c
index 279e4ea02e97777d76feb1a820944bd9b9dd0f11..41afd28e3733664ab0d7ad22e3f47fd2420002a1 100644 (file)
@@ -17,6 +17,7 @@
 #endif
 
 #define HTTP_WANT_CURL
 #endif
 
 #define HTTP_WANT_CURL
+#define HTTP_WANT_ZLIB
 #include "php_http.h"
 
 #include "SAPI.h"
 #include "php_http.h"
 
 #include "SAPI.h"
@@ -40,8 +41,6 @@
 #include "php_http_send_api.h"
 #include "php_http_url_api.h"
 
 #include "php_http_send_api.h"
 #include "php_http_url_api.h"
 
-ZEND_EXTERN_MODULE_GLOBALS(http)
-
 /* {{{ proto string http_date([int timestamp])
  *
  * Compose a valid HTTP date regarding RFC 822/1123
 /* {{{ proto string http_date([int timestamp])
  *
  * Compose a valid HTTP date regarding RFC 822/1123
@@ -67,41 +66,84 @@ PHP_FUNCTION(http_date)
 }
 /* }}} */
 
 }
 /* }}} */
 
-/* {{{ proto string http_build_uri(string url[, string proto[, string host[, int port]]])
+/* {{{ proto string http_build_url(mixed url[, mixed parts[, array new_url]])
  *
  *
- * Build a complete URI according to the supplied parameters.
- * 
- * If the url is already abolute but a different proto was supplied,
- * only the proto part of the URI will be updated.  If url has no
- * path specified, the path of the current REQUEST_URI will be taken.
- * The host will be taken either from the Host HTTP header of the client
- * the SERVER_NAME or just localhost if prior are not available.
- * 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 on success or false on failure.
- * 
- * Examples:
- * <pre>
- * <?php
- * $uri = http_build_uri("page.php", "https", NULL, 488);
- * ?>
- * </pre>
+ * Returns the new URL as string on success or FALSE on failure.
  */
  */
-PHP_FUNCTION(http_build_uri)
+PHP_FUNCTION(http_build_url)
 {
 {
-       char *url = NULL, *proto = NULL, *host = NULL, *built = NULL;
-       int url_len = 0, proto_len = 0, host_len = 0;
-       long port = 0;
+       char *url_str = NULL;
+       size_t url_len = 0;
+       zval *z_old_url = NULL, *z_new_url = NULL, *z_composed_url = NULL;
+       php_url *old_url = NULL, *new_url = NULL, *composed_url = NULL;
 
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssl", &url, &url_len, &proto, &proto_len, &host, &host_len, &port) != SUCCESS) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/|z/z", &z_old_url, &z_new_url, &z_composed_url) != SUCCESS) {
                RETURN_FALSE;
        }
                RETURN_FALSE;
        }
-
-       if ((built = http_absolute_uri_ex(url, url_len, proto, proto_len, host, host_len, port))) {
-               RETURN_STRING(built, 0);
+       
+       if (z_new_url) {
+               if (Z_TYPE_P(z_new_url) == IS_ARRAY || Z_TYPE_P(z_new_url) == IS_OBJECT) {
+                       new_url = array2url(HASH_OF(z_new_url));
+               } else {
+                       convert_to_string(z_new_url);
+                       if (!(new_url = php_url_parse_ex(Z_STRVAL_P(z_new_url), Z_STRLEN_P(z_new_url)))) {
+                               RETURN_FALSE;
+                       }
+               }
+       }
+       
+       if (Z_TYPE_P(z_old_url) == IS_ARRAY || Z_TYPE_P(z_old_url) == IS_OBJECT) {
+               old_url = array2url(HASH_OF(z_old_url));
+       } else {
+               convert_to_string(z_old_url);
+               if (!(old_url = php_url_parse_ex(Z_STRVAL_P(z_old_url), Z_STRLEN_P(z_old_url)))) {
+                       if (new_url) {
+                               php_url_free(new_url);
+                       }
+                       RETURN_FALSE;
+               }
+       }
+       
+       if (z_composed_url) {
+               http_build_url(old_url, new_url, &composed_url, &url_str, &url_len);
+               
+               zval_dtor(z_composed_url);
+               array_init(z_composed_url);
+               if (composed_url->scheme) {
+                       add_assoc_string(z_composed_url, "scheme", composed_url->scheme, 1);
+               }
+               if (composed_url->user) {
+                       add_assoc_string(z_composed_url, "user", composed_url->user, 1);
+               }
+               if (composed_url->pass) {
+                       add_assoc_string(z_composed_url, "pass", composed_url->pass, 1);
+               }
+               if (composed_url->host) {
+                       add_assoc_string(z_composed_url, "host", composed_url->host, 1);
+               }
+               if (composed_url->port) {
+                       add_assoc_long(z_composed_url, "port", composed_url->port);
+               }
+               if (composed_url->path) {
+                       add_assoc_string(z_composed_url, "path", composed_url->path, 1);
+               }
+               if (composed_url->query) {
+                       add_assoc_string(z_composed_url, "query", composed_url->query, 1);
+               }
+               if (composed_url->fragment) {
+                       add_assoc_string(z_composed_url, "fragment", composed_url->fragment, 1);
+               }
+               php_url_free(composed_url);
+       } else {
+               http_build_url(old_url, new_url, NULL, &url_str, &url_len);
+       }
+       
+       if (new_url) {
+               php_url_free(new_url);
        }
        }
-       RETURN_FALSE;
+       php_url_free(old_url);
+       
+       RETURN_STRINGL(url_str, url_len, 0);
 }
 /* }}} */
 
 }
 /* }}} */
 
@@ -685,7 +727,7 @@ PHP_FUNCTION(http_redirect)
                }
        }
 
                }
        }
 
-       URI = http_absolute_uri(url);
+       URI = http_absolute_url(url);
 
        if (query_len) {
                spprintf(&LOC, 0, "Location: %s?%s", URI, query);
 
        if (query_len) {
                spprintf(&LOC, 0, "Location: %s?%s", URI, query);
@@ -894,6 +936,7 @@ PHP_FUNCTION(http_parse_message)
  *         )
  *     [Folded] => works
  *         too 
  *         )
  *     [Folded] => works
  *         too 
+ * ) 
  * ?>
  * </pre>
  */
  * ?>
  * </pre>
  */
@@ -914,6 +957,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.
 /* {{{ proto array http_get_request_headers(void)
  *
  * Get a list of incoming HTTP headers.
@@ -1495,73 +1576,12 @@ PHP_FUNCTION(http_build_query)
 /* {{{ */
 #ifdef HTTP_HAVE_ZLIB
 
 /* {{{ */
 #ifdef HTTP_HAVE_ZLIB
 
-/* {{{ proto string http_gzencode(string data[, int level = -1])
- *
- * Compress data with the HTTP compatible GZIP encoding.
- * 
- * Expects the first parameter to be a string which contains the data that
- * should be encoded.  Additionally accepts an optional in paramter 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_gzencode)
-{
-       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_gzencode(level, data, data_len, &encoded, &encoded_len)) {
-                               RETURN_STRINGL(encoded, (int) encoded_len, 0);
-                       }
-               }
-       }
-}
-/* }}} */
-
-/* {{{ proto string http_gzdecode(string data)
- *
- * Uncompress data compressed with the HTTP compatible GZIP encoding.
- * 
- * Expects a string as parameter containing the compressed data.
- * 
- * Returns the decoded string on success, or NULL on failure.
- */
-PHP_FUNCTION(http_gzdecode)
-{
-       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_gzdecode(data, data_len, &decoded, &decoded_len)) {
-                       RETURN_STRINGL(decoded, (int) decoded_len, 0);
-               }
-       }
-}
-/* }}} */
-
-/* {{{  proto string http_deflate(string data[, int level = -1])
+/* {{{  proto string http_deflate(string data[, int flags = 0])
  *
  *
- * Compress data with the HTTP compatible DEFLATE encoding.
+ * Compress data with gzip, zlib AKA deflate or raw deflate encoding.
  * 
  * Expects the first parameter to be a string containing the data that should
  * 
  * Expects the first parameter to be a string containing the data that 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.
+ * be encoded.
  * 
  * Returns the encoded string on success, or NULL on failure.
  */
  * 
  * Returns the encoded string on success, or NULL on failure.
  */
@@ -1569,19 +1589,16 @@ PHP_FUNCTION(http_deflate)
 {
        char *data;
        int data_len;
 {
        char *data;
        int data_len;
-       long level = -1;
+       long flags = 0;
        
        RETVAL_NULL();
        
        
        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_deflate(level, data, data_len, &encoded, &encoded_len)) {
-                               RETURN_STRINGL(encoded, (int) encoded_len, 0);
-                       }
+       if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags)) {
+               char *encoded;
+               size_t encoded_len;
+               
+               if (SUCCESS == http_encoding_deflate(flags, data, data_len, &encoded, &encoded_len)) {
+                       RETURN_STRINGL(encoded, (int) encoded_len, 0);
                }
        }
 }
                }
        }
 }
@@ -1589,7 +1606,8 @@ PHP_FUNCTION(http_deflate)
 
 /* {{{ proto string http_inflate(string data)
  *
 
 /* {{{ proto string http_inflate(string data)
  *
- * Uncompress data compressed with the HTTP compatible DEFLATE encoding.
+ * Uncompress data compressed with either gzip, deflate AKA zlib or raw
+ * deflate encoding.
  * 
  * Expects a string as parameter containing the compressed data.
  * 
  * 
  * Expects a string as parameter containing the compressed data.
  * 
@@ -1613,64 +1631,47 @@ PHP_FUNCTION(http_inflate)
 }
 /* }}} */
 
 }
 /* }}} */
 
-/* {{{ proto string http_compress(string data[, int level = -1])
+/* {{{ proto string ob_deflatehandler(string data, int mode)
  *
  *
- * 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.
+ * For use with ob_start(). The deflate output buffer handler can only be used once.
+ * It conflicts with ob_gzhanlder and zlib.output_compression as well and should
+ * not be used after ext/mbstrings mb_output_handler and ext/sessions URL-Rewriter (AKA
+ * session.use_trans_sid).
  */
  */
-PHP_FUNCTION(http_compress)
+PHP_FUNCTION(ob_deflatehandler)
 {
        char *data;
        int data_len;
 {
        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);
-                       }
-               }
+       long mode;
+
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
+               RETURN_FALSE;
        }
        }
+
+       http_ob_deflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
+       Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
 }
 /* }}} */
 
 }
 /* }}} */
 
-/* {{{ proto string http_uncompress(string data)
+/* {{{ proto string ob_inflatehandler(string data, int mode)
  *
  *
- * 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.
+ * For use with ob_start().  Same restrictions as with ob_deflatehandler apply.
  */
  */
-PHP_FUNCTION(http_uncompress)
+PHP_FUNCTION(ob_inflatehandler)
 {
        char *data;
        int data_len;
 {
        char *data;
        int data_len;
+       long mode;
        
        
-       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);
-               }
+       if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
+               RETURN_FALSE;
        }
        }
+       
+       http_ob_inflatehandler(data, data_len, &Z_STRVAL_P(return_value), (uint *) &Z_STRLEN_P(return_value), mode);
+       Z_TYPE_P(return_value) = Z_STRVAL_P(return_value) ? IS_STRING : IS_NULL;
 }
 /* }}} */
 }
 /* }}} */
+
 #endif /* HTTP_HAVE_ZLIB */
 /* }}} */
 
 #endif /* HTTP_HAVE_ZLIB */
 /* }}} */