* adding tests
[m6w6/ext-http] / http_api.c
index 0e73eb3682594c2533358181624c385726009f81..36211805e9781c3937997b0609301ce4c0cc1bcd 100644 (file)
@@ -144,6 +144,8 @@ static int check_day(char *day, size_t len);
 static int check_month(char *month);
 static int check_tzone(char *tzone);
 
+static char *pretty_key(char *key, int key_len, int uctitle, int xhyphen);
+
 /* {{{ HAVE_CURL */
 #ifdef HTTP_HAVE_CURL
 #define http_curl_initbuf(m) _http_curl_initbuf((m) TSRMLS_CC)
@@ -591,7 +593,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
                        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));
+                               snprintf(header, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val));
                                headers = curl_slist_append(headers, header);
                                zend_hash_move_forward(Z_ARRVAL_P(zoption));
                        }
@@ -606,7 +608,7 @@ static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *opti
 /* {{{ 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
+#define CASE(I) case CURLINFO_ ##I : return pretty_key(estrdup( #I ), strlen(#I), 0, 0)
        switch (i)
        {
                /* CURLINFO_EFFECTIVE_URL                       =       CURLINFO_STRING +1, */
@@ -683,7 +685,7 @@ static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRML
                        {
                                double d;
                                if (CURLE_OK == curl_easy_getinfo(ch, i, &d)) {
-                                       add_assoc_double(array, key, (double) d);
+                                       add_assoc_double(array, key, d);
                                }
                        }
                        break;
@@ -692,7 +694,7 @@ static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRML
                        {
                                long l;
                                if (CURLE_OK == curl_easy_getinfo(ch, i, &l)) {
-                                       add_assoc_long(array, key, (long) l);
+                                       add_assoc_long(array, key, l);
                                }
                        }
                        break;
@@ -704,12 +706,10 @@ static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRML
 /* {{{ 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;
+       zval array;
+       Z_ARRVAL(array) = info;
 
-#define INFO(I) http_curl_getinfo_ex(ch, CURLINFO_ ##I , array)
+#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, */
@@ -759,7 +759,6 @@ static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC)
        /* CURLINFO_PROXYAUTH_AVAIL                     =       CURLINFO_LONG   +24, */
        INFO(PROXYAUTH_AVAIL);
 #undef INFO
-       efree(array);
 }
 /* }}} */
 
@@ -811,6 +810,30 @@ static int check_tzone(char *tzone)
 }
 /* }}} */
 
+/* static char *pretty_key(char *, int, int, int) */
+static char *pretty_key(char *key, int key_len, int uctitle, int xhyphen)
+{
+       if (key && key_len) {
+               int i, wasalpha;
+               if (wasalpha = isalpha(key[0])) {
+                       key[0] = uctitle ? toupper(key[0]) : tolower(key[0]);
+               }
+               for (i = 1; i < key_len; i++) {
+                       if (isalpha(key[i])) {
+                               key[i] = ((!wasalpha) && uctitle) ? toupper(key[i]) : tolower(key[i]);
+                               wasalpha = 1;
+                       } else {
+                               if (xhyphen && (key[i] == '_')) {
+                                       key[i] = '-';
+                               }
+                               wasalpha = 0;
+                       }
+               }
+       }
+       return key;
+}
+/* }}} */
+
 /* }}} internals */
 
 /* {{{ public API */
@@ -819,7 +842,7 @@ static int check_tzone(char *tzone)
 PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC)
 {
        struct tm *gmtime, tmbuf;
-       char *date = ecalloc(1, 30);
+       char *date = ecalloc(31, 1);
 
        gmtime = php_gmtime_r(&t, &tmbuf);
        snprintf(date, 30,
@@ -1139,9 +1162,9 @@ PHP_HTTP_API STATUS _http_send_etag(const char *etag,
        int header_len;
        char *etag_header;
 
-       header_len = strlen("ETag: \"\"") + etag_len + 1;
-       etag_header = (char *) emalloc(header_len);
-       snprintf(etag_header, header_len, "ETag: \"%s\"", etag);
+       header_len = sizeof("ETag: \"\"") + etag_len + 1;
+       etag_header = ecalloc(header_len, 1);
+       sprintf(etag_header, "ETag: \"%s\"", etag);
        ret = http_send_header(etag_header);
        efree(etag_header);
 
@@ -1301,7 +1324,7 @@ PHP_HTTP_API http_range_status _http_get_request_ranges(zval *zranges,
 
        if (strncmp(range, "bytes=", strlen("bytes="))) {
                php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Range header misses bytes=");
-               return RANGE_ERR;
+               return RANGE_NO;
        }
 
        ptr = &begin;
@@ -1407,7 +1430,7 @@ PHP_HTTP_API http_range_status _http_get_request_ranges(zval *zranges,
                        break;
 
                        default:
-                               return RANGE_ERR;
+                               return RANGE_NO;
                        break;
                }
        } while (c != 0);
@@ -1722,7 +1745,7 @@ PHP_HTTP_API STATUS _http_parse_headers(char *header, int header_len, zval *arra
 {
        char *colon = NULL, *line = NULL, *begin = header;
 
-       if (header_len < 8) {
+       if (header_len < 2) {
                return FAILURE;
        }
 
@@ -1737,18 +1760,37 @@ PHP_HTTP_API STATUS _http_parse_headers(char *header, int header_len, zval *arra
 
        line = header;
 
-       while (header_len > (line - begin)) {
+       while (header_len >= (line - begin)) {
+               int value_len = 0;
+
                switch (*line++)
                {
                        case 0:
+                               --value_len; /* we don't have CR so value length is one char less */
                        case '\n':
-                               if (colon && (*line != ' ') && (*line != '\t')) {
-                                       char *key = estrndup(header, colon - header);
-                                       while (isspace(*(++colon)));
-                                       add_assoc_stringl(array, key, colon, line - colon - 2, 1);
-                                       efree(key);
+                               if (colon && ((!(*line - 1)) || ((*line != ' ') && (*line != '\t')))) {
+
+                                       /* skip empty key */
+                                       if (header != colon) {
+                                               char *key = estrndup(header, colon - header);
+                                               value_len += line - colon - 1;
+
+                                               /* skip leading ws */
+                                               while (isspace(*(++colon))) --value_len;
+                                               /* skip trailing ws */
+                                               while (isspace(colon[value_len - 1])) --value_len;
+
+                                               if (value_len < 1) {
+                                                       /* hm, empty header? */
+                                                       add_assoc_stringl(array, key, "", 0, 1);
+                                               } else {
+                                                       add_assoc_stringl(array, key, colon, value_len, 1);
+                                               }
+                                               efree(key);
+                                       }
 
                                        colon = NULL;
+                                       value_len = 0;
                                        header += line - header;
                                }
                        break;
@@ -1764,6 +1806,23 @@ PHP_HTTP_API STATUS _http_parse_headers(char *header, int header_len, zval *arra
 }
 /* }}} */
 
+/* {{{ void http_get_request_headers(zval *) */
+PHP_HTTP_API void _http_get_request_headers(zval *array TSRMLS_DC)
+{
+    char *key;
+
+    for (   zend_hash_internal_pointer_reset(HTTP_SERVER_VARS);
+            zend_hash_get_current_key(HTTP_SERVER_VARS, &key, NULL, 0) != HASH_KEY_NON_EXISTANT;
+            zend_hash_move_forward(HTTP_SERVER_VARS)) {
+        if (!strncmp(key, "HTTP_", 5)) {
+            zval **header;
+            zend_hash_get_current_data(HTTP_SERVER_VARS, (void **) &header);
+            add_assoc_stringl(array, pretty_key(key + 5, strlen(key) - 5, 1, 1), Z_STRVAL_PP(header), Z_STRLEN_PP(header), 1);
+        }
+    }
+}
+/* }}} */
+
 /* {{{ HAVE_CURL */
 #ifdef HTTP_HAVE_CURL