/* $Id$ */
+#define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h>
-#if defined(HAVE_CURL) && HAVE_CURL
-# ifdef PHP_WIN32
-# include <winsock2.h>
-# include <sys/types.h>
-# endif
-#include <curl/curl.h>
-#include <curl/easy.h>
-#endif
-
#include "php.h"
#include "php_version.h"
#include "php_streams.h"
#include "SAPI.h"
-#if (PHP_MAJOR_VERSION >= 5)
+#ifdef ZEND_ENGINE_2
#include "ext/standard/php_http.h"
#else
-#include "php_http_build_query.h"
#include "http_build_query.c"
#endif
#include "php_http.h"
#include "php_http_api.h"
+#ifdef HTTP_HAVE_CURL
+
+#ifdef PHP_WIN32
+#include <winsock2.h>
+#include <sys/types.h>
+#endif
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+#endif
+
+
ZEND_DECLARE_MODULE_GLOBALS(http)
/* {{{ day/month names */
static int check_tzone(char *tzone);
/* {{{ HAVE_CURL */
-#if defined(HAVE_CURL) && HAVE_CURL
+#ifdef HTTP_HAVE_CURL
#define http_curl_initbuf(m) _http_curl_initbuf((m) TSRMLS_CC)
static inline void _http_curl_initbuf(http_curlbuf_member member TSRMLS_DC);
#define http_curl_freebuf(m) _http_curl_freebuf((m) TSRMLS_CC)
/* }}} */
/* {{{ HAVE_CURL */
-#if defined(HAVE_CURL) && HAVE_CURL
+#ifdef HTTP_HAVE_CURL
/* {{{ static inline void http_curl_initbuf(http_curlbuf_member) */
static inline void _http_curl_initbuf(http_curlbuf_member member TSRMLS_DC)
curl_easy_setopt(ch, CURLOPT_AUTOREFERER, 1);
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, http_curl_body_callback);
curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, http_curl_hdrs_callback);
-#if defined(ZTS)
+#ifdef ZTS
curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1);
#endif
-#if defined(PHP_DEBUG)
- curl_easy_setopt(ch, CURLOPT_VERBOSE, 1);
-#endif
if ((!options) || (1 > zend_hash_num_elements(options))) {
return;
chr_ptr = 0;
}
retval = (t <= http_parse_date(modified));
-#if defined(PHP_DEBUG)
- fprintf(stderr,
- "\nComparing Last-Modified %s(%s)==%d:\n\t%d\n\t%d\n\n",
- get_active_function_name(TSRMLS_C), entry, retval, t,
- http_parse_date(modified));
-#endif
efree(modified);
return retval;
}
} else {
result = (NULL != strstr(Z_STRVAL_P(zetag), quoted_etag));
}
-#if defined(PHP_DEBUG)
- fprintf(stderr,
- "\nComparing E-Tag %s(%s)==%d:\n\t<%s>\n\t<%s>\n\n",
- get_active_function_name(TSRMLS_C), entry, result,
- Z_STRVAL_P(zetag), quoted_etag);
-#endif
efree(quoted_etag);
return result;
}
}
/* write boundary once more */
- php_body_write("\r\n", 1 TSRMLS_CC);
+ php_body_write(HTTP_CRLF, 1 TSRMLS_CC);
php_body_write(bound, strlen(bound) TSRMLS_CC);
return SUCCESS;
char *d_ptr;
*decoded_len = 0;
- *decoded = (char *) ecalloc(1, encoded_len);
+ *decoded = (char *) ecalloc(encoded_len, 1);
d_ptr = *decoded;
e_ptr = encoded;
hex_len[i++] = *e_ptr++;
}
+ /* reached the end */
+ if (!strcmp(hex_len, "0")) {
+ break;
+ }
+
+ /* new line */
+ if (strncmp(e_ptr, HTTP_CRLF, 2)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Invalid character (expected 0x0D 0x0A; got: %x %x)",
+ *e_ptr, *(e_ptr + 1));
+ efree(*decoded);
+ return FAILURE;
+ }
+
/* hex to long */
- if (strcmp(hex_len, "0")) {
+ {
char *error = NULL;
chunk_len = strtol(hex_len, &error, 16);
if (error == hex_len) {
efree(*decoded);
return FAILURE;
}
- } else {
- break;
}
- /* new line */
- if (*e_ptr++ != '\r' || *e_ptr++ != '\n') {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Invalid character (expected 0x0A, 0x0D; got: %x)",
- *(e_ptr - 1));
- efree(*decoded);
- return FAILURE;
- }
-
- memcpy(d_ptr, e_ptr, chunk_len);
+ memcpy(d_ptr, e_ptr += 2, chunk_len);
d_ptr += chunk_len;
e_ptr += chunk_len + 2;
*decoded_len += chunk_len;
}
/* }}} */
-/* {{{ proto void http_split_response(zval *, zval *, zval *) */
-PHP_HTTP_API void _http_split_response(const zval *zresponse, zval *zheaders,
+/* {{{ proto STATUS http_split_response(zval *, zval *, zval *) */
+PHP_HTTP_API STATUS _http_split_response(const zval *zresponse, zval *zheaders,
zval *zbody TSRMLS_DC)
{
char *header, *response, *body = NULL;
Z_TYPE_P(zbody) = IS_NULL;
}
- /* check for HTTP status - FIXXME: strchr() */
+ return http_parse_headers(header, body - Z_STRVAL_P(zresponse), zheaders);
+}
+/* }}} */
+
+/* {{{ STATUS http_parse_headers(char *, long, zval *) */
+PHP_HTTP_API STATUS _http_parse_headers(char *header, int header_len, zval *array TSRMLS_DC)
+{
+ char *colon = NULL, *line = NULL, *begin = header;
+
+ if (header_len < 8) {
+ return FAILURE;
+ }
+
+ /* status code */
if (!strncmp(header, "HTTP/1.", 7)) {
- char *end = strchr(header, '\r');
- add_assoc_stringl(zheaders, "Status",
+ char *end = strstr(header, HTTP_CRLF);
+ add_assoc_stringl(array, "Status",
header + strlen("HTTP/1.x "),
end - (header + strlen("HTTP/1.x ")), 1);
header = end + 2;
}
- /* split headers */
- {
- char *colon = NULL, *line = header;
+
+ line = header;
- while ( (line - Z_STRVAL_P(zresponse) + 3) <
- (body - Z_STRVAL_P(zresponse))) {
- switch (*line++)
- {
- case '\r':
- if (colon && (*line == '\n')) {
- char *key = estrndup(header, colon - header);
- add_assoc_stringl(zheaders, key,
- colon + 2, line - colon - 3, 1);
- efree(key);
-
- colon = NULL;
- header += line - header + 1;
- }
- break;
+ while (header_len > (line - begin)) {
+ switch (*line++)
+ {
+ case 0:
+ case '\n':
+ if (colon && (*line != ' ') && (*line != '\t')) {
+ char *key = estrndup(header, colon - header);
+ add_assoc_stringl(array, key, colon + 2, line - colon - 4, 1);
+ efree(key);
+
+ colon = NULL;
+ header += line - header;
+ }
+ break;
- case ':':
- if (!colon) {
- colon = line - 1;
- }
- break;
- }
+ case ':':
+ if (!colon) {
+ colon = line - 1;
+ }
+ break;
}
}
+ return SUCCESS;
}
/* }}} */
/* {{{ HAVE_CURL */
-#if defined(HAVE_CURL) && HAVE_CURL
+#ifdef HTTP_HAVE_CURL
/* {{{ STATUS http_get(char *, HashTable *, HashTable *, char **, size_t *) */
PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options,