* fixed some memleaks
[m6w6/ext-http] / http_api.c
index b099b5aca729397a7358155d84896e870ef836a8..6a62d92335b418da2375b77909f5a3581cb22271 100644 (file)
@@ -134,10 +134,6 @@ static const struct time_zone {
 /* {{{ internals */
 
 static int http_sort_q(const void *a, const void *b TSRMLS_DC);
-#define http_etag(e, p, l, m) _http_etag((e), (p), (l), (m) TSRMLS_CC)
-static inline char *_http_etag(char **new_etag, const void *data_ptr, const size_t data_len, const http_send_mode data_mode TSRMLS_DC);
-#define http_is_range_request() _http_is_range_request(TSRMLS_C)
-static inline int _http_is_range_request(TSRMLS_D);
 #define http_send_chunk(d, b, e, m) _http_send_chunk((d), (b), (e), (m) TSRMLS_CC)
 static STATUS _http_send_chunk(const void *data, const size_t begin, const size_t end, const http_send_mode mode TSRMLS_DC);
 
@@ -182,32 +178,14 @@ static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC);
 #endif
 /* }}} HAVE_CURL */
 
-/* {{{ static int http_sort_q(const void *, const void *) */
-static int http_sort_q(const void *a, const void *b TSRMLS_DC)
-{
-       Bucket *f, *s;
-       zval result, *first, *second;
-
-       f = *((Bucket **) a);
-       s = *((Bucket **) b);
-
-       first = *((zval **) f->pData);
-       second= *((zval **) s->pData);
-
-       if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
-               return 0;
-       }
-       return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
-}
-/* }}} */
-
-/* {{{ static inline char *http_etag(char **, void *, size_t, http_send_mode) */
-static inline char *_http_etag(char **new_etag, const void *data_ptr,
-       const size_t data_len, const http_send_mode data_mode TSRMLS_DC)
+/* {{{ inline char *http_etag(void *, size_t, http_send_mode) */
+inline char *_http_etag(const void *data_ptr, const size_t data_len, 
+       const http_send_mode data_mode TSRMLS_DC)
 {
-       char ssb_buf[127];
+       char ssb_buf[128] = {0};
        unsigned char digest[16];
        PHP_MD5_CTX ctx;
+       char *new_etag = ecalloc(33, 1);
 
        PHP_MD5Init(&ctx);
 
@@ -218,6 +196,11 @@ static inline char *_http_etag(char **new_etag, const void *data_ptr,
                break;
 
                case SEND_RSRC:
+                       if (!HTTP_G(ssb).sb.st_ino) {
+                               if (php_stream_stat((php_stream *) data_ptr, &HTTP_G(ssb))) {
+                                       return NULL;
+                               }
+                       }
                        snprintf(ssb_buf, 127, "%l=%l=%l",
                                HTTP_G(ssb).sb.st_mtime,
                                HTTP_G(ssb).sb.st_ino,
@@ -227,25 +210,45 @@ static inline char *_http_etag(char **new_etag, const void *data_ptr,
                break;
 
                default:
+                       efree(new_etag);
                        return NULL;
                break;
        }
 
        PHP_MD5Final(digest, &ctx);
-       make_digest(*new_etag, digest);
+       make_digest(new_etag, digest);
 
-       return *new_etag;
+       return new_etag;
 }
 /* }}} */
 
-/* {{{ static inline int http_is_range_request(void) */
-static inline int _http_is_range_request(TSRMLS_D)
+/* {{{inline int http_is_range_request(void) */
+inline int _http_is_range_request(TSRMLS_D)
 {
        return zend_hash_exists(Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER]),
                "HTTP_RANGE", strlen("HTTP_RANGE") + 1);
 }
 /* }}} */
 
+/* {{{ static int http_sort_q(const void *, const void *) */
+static int http_sort_q(const void *a, const void *b TSRMLS_DC)
+{
+       Bucket *f, *s;
+       zval result, *first, *second;
+
+       f = *((Bucket **) a);
+       s = *((Bucket **) b);
+
+       first = *((zval **) f->pData);
+       second= *((zval **) s->pData);
+
+       if (numeric_compare_function(&result, first, second TSRMLS_CC) != SUCCESS) {
+               return 0;
+       }
+       return (Z_LVAL(result) > 0 ? -1 : (Z_LVAL(result) < 0 ? 1 : 0));
+}
+/* }}} */
+
 /* {{{ static STATUS http_send_chunk(const void *, size_t, size_t,
        http_send_mode) */
 static STATUS _http_send_chunk(const void *data, const size_t begin,
@@ -844,6 +847,7 @@ static STATUS http_ob_stack_get(php_ob_buffer *o, php_ob_buffer **s)
        php_ob_buffer *b = emalloc(sizeof(php_ob_buffer));
        b->handler_name = estrdup(o->handler_name);
        b->buffer = estrndup(o->buffer, o->text_length);
+       b->text_length = o->text_length;
        b->chunk_size = o->chunk_size;
        b->erase = o->erase;
        s[i++] = b;
@@ -1119,7 +1123,7 @@ PHP_HTTP_API STATUS _http_start_ob_handler(php_output_handler_func_t handler_fun
        int count, i;
 
        if (count = OG(ob_nesting_level)) {
-               stack = ecalloc(sizeof(php_ob_buffer), count);
+               stack = ecalloc(sizeof(php_ob_buffer *), count);
 
                if (count > 1) {
                        zend_stack_apply_with_argument(&OG(ob_buffers), ZEND_STACK_APPLY_BOTTOMUP,
@@ -1134,13 +1138,21 @@ PHP_HTTP_API STATUS _http_start_ob_handler(php_output_handler_func_t handler_fun
                        php_end_ob_buffer(0, 0 TSRMLS_CC);
                }
        }
-       
+
        php_ob_set_internal_handler(handler_func, chunk_size, handler_name, erase TSRMLS_CC);
 
        for (i = 0; i < count; i++) {
                php_ob_buffer *s = stack[i];
-               php_start_ob_buffer_named(s->handler_name, s->chunk_size, s->erase TSRMLS_CC);
+               if (strcmp(s->handler_name, "default output handler")) {
+                       php_start_ob_buffer_named(s->handler_name, s->chunk_size, s->erase TSRMLS_CC);
+               }
                php_body_write(s->buffer, s->text_length TSRMLS_CC);
+               efree(s->handler_name);
+               efree(s->buffer);
+               efree(s);
+       }
+       if (count) {
+               efree(stack);
        }
 
        return SUCCESS;
@@ -1585,13 +1597,12 @@ PHP_HTTP_API STATUS _http_send(const void *data_ptr, const size_t data_size,
 
        /* etag handling */
        if (HTTP_G(etag_started)) {
-               char *etag = ecalloc(33, 1);
+               char *etag;
                /* interrupt */
                HTTP_G(etag_started) = 0;
                /* never ever use the output to compute the ETag if http_send() is used */
                php_end_ob_buffer(0, 0 TSRMLS_CC);
-               if (NULL == http_etag(&etag, data_ptr, data_size, data_mode)) {
-                       efree(etag);
+               if (!(etag = http_etag(data_ptr, data_size, data_mode))) {
                        return FAILURE;
                }
 
@@ -1887,6 +1898,7 @@ PHP_HTTP_API void _http_get_request_headers(zval *array TSRMLS_DC)
 PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
        HashTable *info, char **data, size_t *data_len TSRMLS_DC)
 {
+       STATUS rs;
        CURL *ch = curl_easy_init();
 
        if (!ch) {
@@ -1894,11 +1906,22 @@ PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
                return FAILURE;
        }
 
+       rs = http_get_ex(ch, URL, options, info, data, data_len);
+       curl_easy_cleanup(ch);
+       return rs;
+}
+/* }}} */
+
+/* {{{ STATUS http_get_ex(CURL *, char *, HashTable *, HashTable *, char **, size_t *) */
+PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options,
+       HashTable *info, char **data, size_t *data_len TSRMLS_DC)
+{
        http_curl_initbuf(CURLBUF_EVRY);
        http_curl_setopts(ch, URL, options);
+       curl_easy_setopt(ch, CURLOPT_NOBODY, 0);
+       curl_easy_setopt(ch, CURLOPT_POST, 0);
 
        if (CURLE_OK != curl_easy_perform(ch)) {
-               curl_easy_cleanup(ch);
                http_curl_freebuf(CURLBUF_EVRY);
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
                return FAILURE;
@@ -1906,18 +1929,15 @@ PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,
        if (info) {
                http_curl_getinfo(ch, info);
        }
-       curl_easy_cleanup(ch);
-
        http_curl_movebuf(CURLBUF_EVRY, data, data_len);
-
        return SUCCESS;
 }
-/* }}} */
 
 /* {{{ STATUS http_head(char *, HashTable *, HashTable *, char **data, size_t *) */
 PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
        HashTable *info, char **data, size_t *data_len TSRMLS_DC)
 {
+       STATUS rs;
        CURL *ch = curl_easy_init();
 
        if (!ch) {
@@ -1925,12 +1945,22 @@ PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
                return FAILURE;
        }
 
+       rs = http_head_ex(ch, URL, options, info, data, data_len);
+       curl_easy_cleanup(ch);
+       return rs;
+}
+/* }}} */
+
+/* {{{ STATUS http_head_ex(CURL *, char *, HashTable *, HashTable *, char **data, size_t *) */
+PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options,
+       HashTable *info, char **data, size_t *data_len TSRMLS_DC)
+{
        http_curl_initbuf(CURLBUF_HDRS);
        http_curl_setopts(ch, URL, options);
        curl_easy_setopt(ch, CURLOPT_NOBODY, 1);
+       curl_easy_setopt(ch, CURLOPT_POST, 0);
 
        if (CURLE_OK != curl_easy_perform(ch)) {
-               curl_easy_cleanup(ch);
                http_curl_freebuf(CURLBUF_HDRS);
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
                return FAILURE;
@@ -1938,26 +1968,33 @@ PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options,
        if (info) {
                http_curl_getinfo(ch, info);
        }
-       curl_easy_cleanup(ch);
-
        http_curl_movebuf(CURLBUF_HDRS, data, data_len);
-
        return SUCCESS;
 }
-/* }}} */
 
 /* {{{ 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, HashTable *info, char **data,
        size_t *data_len TSRMLS_DC)
 {
+       STATUS rs;
        CURL *ch = curl_easy_init();
 
        if (!ch) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
                return FAILURE;
        }
+       rs = http_post_data_ex(ch, URL, postdata, postdata_len, options, info, data, data_len);
+       curl_easy_cleanup(ch);
+       return rs;
+}
+/* }}} */
 
+/* {{{ STATUS http_post_data_ex(CURL *, char *, char *, size_t, HashTable *, HashTable *, char **, size_t *) */
+PHP_HTTP_API STATUS _http_post_data_ex(CURL *ch, const char *URL, char *postdata,
+       size_t postdata_len, HashTable *options, HashTable *info, char **data,
+       size_t *data_len TSRMLS_DC)
+{
        http_curl_initbuf(CURLBUF_EVRY);
        http_curl_setopts(ch, URL, options);
        curl_easy_setopt(ch, CURLOPT_POST, 1);
@@ -1965,7 +2002,6 @@ PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata,
        curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, postdata_len);
 
        if (CURLE_OK != curl_easy_perform(ch)) {
-               curl_easy_cleanup(ch);
                http_curl_freebuf(CURLBUF_EVRY);
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
                return FAILURE;
@@ -1973,10 +2009,7 @@ PHP_HTTP_API STATUS _http_post_data(const char *URL, char *postdata,
        if (info) {
                http_curl_getinfo(ch, info);
        }
-       curl_easy_cleanup(ch);
-
        http_curl_movebuf(CURLBUF_EVRY, data, data_len);
-
        return SUCCESS;
 }
 /* }}} */