dnl ----
dnl DONE
dnl ----
- PHP_NEW_EXTENSION([http], [http.c http_api.c], [$ext_shared])
+ PHP_NEW_EXTENSION([http], [http.c http_api.c http_functions.c http_methods.c], [$ext_shared])
PHP_SUBST([HTTP_SHARED_LIBADD])
AC_DEFINE([HAVE_HTTP], [1], [Have extended HTTP support])
fi
ARG_ENABLE("http", "whether to enable extended HTTP support", "no");
if (PHP_HTTP != "no") {
- EXTENSION("http", "http.c http_api.c")
+ EXTENSION("http", "http.c http_functions.c http_methods.c http_api.c http_curl_api.c")
AC_DEFINE("HAVE_HTTP", 1, "Have extended HTTP support")
if (CHECK_LIB("libcurl.lib", "http", PHP_HTTP) &&
CHECK_HEADER_ADD_INCLUDE("curl/easy.h", "CFLAGS_HTTP") &&
#include "php_http.h"
#include "php_http_api.h"
+#include "php_http_curl_api.h"
#ifdef ZEND_ENGINE_2
# include "ext/standard/php_http.h"
};
/* }}} */
-#define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
-#define HASH_ORNULL(z) ((z) ? Z_ARRVAL_P(z) : NULL)
-#define NO_ARGS if (ZEND_NUM_ARGS()) WRONG_PARAM_COUNT
-
-#define array_copy(src, dst) zend_hash_copy(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
-#define array_merge(src, dst) zend_hash_merge(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1)
#ifdef ZEND_ENGINE_2
-# define HTTP_REGISTER_CLASS_EX(classname, name, parent, flags) \
- { \
- zend_class_entry ce; \
- INIT_CLASS_ENTRY(ce, #classname, name## _class_methods); \
- ce.create_object = name## _new_object; \
- name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
- name## _ce->ce_flags |= flags; \
- memcpy(& name## _object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
- name## _object_handlers.clone_obj = NULL; \
- name## _declare_default_properties(name## _ce); \
- }
-
-# define HTTP_REGISTER_CLASS(classname, name, parent, flags) \
- { \
- zend_class_entry ce; \
- INIT_CLASS_ENTRY(ce, #classname, name## _class_methods); \
- ce.create_object = NULL; \
- name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
- name## _ce->ce_flags |= flags; \
- }
-
-# define getObject(t, o) t * o = ((t *) zend_object_store_get_object(getThis() TSRMLS_CC))
-# define OBJ_PROP(o) o->zo.properties
-# define DCL_PROP(a, t, n, v) zend_declare_property_ ##t(ce, (#n), sizeof(#n), (v), (ZEND_ACC_ ##a) TSRMLS_CC)
-# define DCL_PROP_Z(a, n, v) zend_declare_property(ce, (#n), sizeof(#n), (v), (ZEND_ACC_ ##a) TSRMLS_CC)
-# define DCL_PROP_N(a, n) zend_declare_property_null(ce, (#n), sizeof(#n), (ZEND_ACC_ ##a) TSRMLS_CC)
-# define UPD_PROP(o, t, n, v) zend_update_property_ ##t(o->zo.ce, getThis(), (#n), sizeof(#n), (v) TSRMLS_CC)
-# define SET_PROP(o, n, z) zend_update_property(o->zo.ce, getThis(), (#n), sizeof(#n), (z) TSRMLS_CC)
-# define GET_PROP(o, n) zend_read_property(o->zo.ce, getThis(), (#n), sizeof(#n), 0 TSRMLS_CC)
-
-# define INIT_PARR(o, n) \
- { \
- zval *__tmp; \
- MAKE_STD_ZVAL(__tmp); \
- array_init(__tmp); \
- SET_PROP(o, n, __tmp); \
- }
-
-# define FREE_PARR(o, p) \
- { \
- zval *__tmp = NULL; \
- if (__tmp = GET_PROP(o, p)) { \
- zval_dtor(__tmp); \
- FREE_ZVAL(__tmp); \
- __tmp = NULL; \
- } \
- }
-
/* {{{ HTTPi */
zend_class_entry *httpi_ce;
zend_class_entry *httpi_response_ce;
static zend_object_handlers httpi_response_object_handlers;
-typedef struct {
- zend_object zo;
-} httpi_response_object;
-
#define httpi_response_declare_default_properties(ce) _httpi_response_declare_default_properties(ce TSRMLS_CC)
static inline void _httpi_response_declare_default_properties(zend_class_entry *ce TSRMLS_DC)
{
{NULL, NULL, NULL}
};
-
-/* {{{ proto void HTTPi_Response::__construct(bool cache, bool gzip)
- *
- */
-PHP_METHOD(HTTPi_Response, __construct)
-{
- zend_bool do_cache = 0, do_gzip = 0;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &do_cache, &do_gzip)) {
- // throw exception
- return;
- }
-
- UPD_PROP(obj, long, cache, do_cache);
- UPD_PROP(obj, long, gzip, do_gzip);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setCache(bool cache)
- *
- */
-PHP_METHOD(HTTPi_Response, setCache)
-{
- zend_bool do_cache = 0;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, long, cache, do_cache);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::getCache()
- *
- */
-PHP_METHOD(HTTPi_Response, getCache)
-{
- zval *do_cache = NULL;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- do_cache = GET_PROP(obj, cache);
- RETURN_BOOL(Z_LVAL_P(do_cache));
-}
-/* }}}*/
-
-/* {{{ proto bool HTTPi_Response::setGzip(bool gzip)
- *
- */
-PHP_METHOD(HTTPi_Response, setGzip)
-{
- zend_bool do_gzip = 0;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, long, gzip, do_gzip);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::getGzip()
- *
- */
-PHP_METHOD(HTTPi_Response, getGzip)
-{
- zval *do_gzip = NULL;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- do_gzip = GET_PROP(obj, gzip);
- RETURN_BOOL(Z_LVAL_P(do_gzip));
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setCacheControl(string control[, bool raw = false])
- *
- */
-PHP_METHOD(HTTPi_Response, setCacheControl)
-{
- char *ccontrol;
- int cc_len;
- zend_bool raw = 0;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &ccontrol, &cc_len, &raw)) {
- RETURN_FALSE;
- }
-
- if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, long, raw_cache_header, raw);
- UPD_PROP(obj, string, cacheControl, ccontrol);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Response::getCacheControl()
- *
- */
-PHP_METHOD(HTTPi_Response, getCacheControl)
-{
- zval *ccontrol;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- ccontrol = GET_PROP(obj, cacheControl);
- RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi::setContentType(string content_type)
- *
- */
-PHP_METHOD(HTTPi_Response, setContentType)
-{
- char *ctype;
- int ctype_len;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
- RETURN_FALSE;
- }
-
- if (!strchr(ctype, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, string, contentType, ctype);
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Response::getContentType()
- *
- */
-PHP_METHOD(HTTPi_Response, getContentType)
-{
- zval *ctype;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- ctype = GET_PROP(obj, contentType);
- RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setContentDisposition(string filename[, bool inline = false])
- *
- */
-PHP_METHOD(HTTPi_Response, setContentDisposition)
-{
- char *file;
- int file_len;
- zend_bool is_inline = 0;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &is_inline)) {
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, string, dispoFile, file);
- UPD_PROP(obj, long, dispoInline, is_inline);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto array HTTPi_Response::getContentDisposition()
- *
- */
-PHP_METHOD(HTTPi_Response, getContentDisposition)
-{
- zval *file;
- zval *is_inline;
- getObject(httpi_response_object, obj);
-
- if (ZEND_NUM_ARGS()) {
- WRONG_PARAM_COUNT;
- }
-
- file = GET_PROP(obj, dispoFile);
- is_inline = GET_PROP(obj, dispoInline);
-
- array_init(return_value);
- add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
- add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setETag(string etag)
- *
- */
-PHP_METHOD(HTTPi_Response, setETag)
-{
- char *etag;
- int etag_len;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, string, eTag, etag);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Response::getETag()
- *
- */
-PHP_METHOD(HTTPi_Response, getETag)
-{
- zval *etag;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- etag = GET_PROP(obj, eTag);
- RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setData(string data)
- *
- */
-PHP_METHOD(HTTPi_Response, setData)
-{
- zval *the_data;
- char *etag;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_data)) {
- RETURN_FALSE;
- }
-
- convert_to_string_ex(&the_data);
- SET_PROP(obj, data, the_data);
- UPD_PROP(obj, long, lastModified, http_lmod(the_data, SEND_DATA));
- UPD_PROP(obj, long, send_mode, SEND_DATA);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Response::getData()
- *
- */
-PHP_METHOD(HTTPi_Response, getData)
-{
- zval *the_data;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- the_data = GET_PROP(obj, data);
- RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setStream(resource stream)
- *
- */
-PHP_METHOD(HTTPi_Response, setStream)
-{
- zval *the_stream;
- php_stream *the_real_stream;
- char *etag;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
- RETURN_FALSE;
- }
-
- php_stream_from_zval(the_real_stream, &the_stream);
-
- SET_PROP(obj, stream, the_stream);
- UPD_PROP(obj, long, lastModified, http_lmod(the_real_stream, SEND_RSRC));
- UPD_PROP(obj, long, send_mode, SEND_RSRC);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto resource HTTPi_Response::getStream()
- *
- */
-PHP_METHOD(HTTPi_Response, getStream)
-{
- zval *the_stream;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- the_stream = GET_PROP(obj, stream);
- RETURN_RESOURCE(Z_LVAL_P(the_stream));
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Response::setFile(string file)
- *
- */
-PHP_METHOD(HTTPi_Response, setFile)
-{
- zval *the_file;
- getObject(httpi_response_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
- RETURN_FALSE;
- }
-
- convert_to_string_ex(&the_file);
-
- UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
- UPD_PROP(obj, long, lastModified, http_lmod(the_file, -1));
- UPD_PROP(obj, long, send_mode, -1);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Response::getFile()
- *
- */
-PHP_METHOD(HTTPi_Response, getFile)
-{
- zval *the_file;
- getObject(httpi_response_object, obj);
-
- NO_ARGS;
-
- the_file = GET_PROP(obj, file);
- RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
-}
-/* }}} */
-
-PHP_METHOD(HTTPi_Response, send)
-{
- zval *do_cache, *do_gzip;
- getObject(httpi_response_object, obj);
-
- do_cache = GET_PROP(obj, cache);
- do_gzip = GET_PROP(obj, gzip);
-
- /* caching */
- if (Z_LVAL_P(do_cache)) {
- zval *cctrl, *etag, *lmod, *ccraw;
-
- etag = GET_PROP(obj, eTag);
- lmod = GET_PROP(obj, lastModified);
- cctrl = GET_PROP(obj, cacheControl);
- ccraw = GET_PROP(obj, raw_cache_header);
-
- if (Z_LVAL_P(ccraw)) {
- http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
- http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
- } else {
- char cc_header[42] = {0};
- sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
- http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_header, strlen(cc_header));
- http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_header, strlen(cc_header));
- }
- }
-
- /* gzip */
- if (Z_LVAL_P(do_gzip)) {
- /* ... */
- }
-
- /* content type */
- {
- zval *ctype = GET_PROP(obj, contentType);
- if (Z_STRLEN_P(ctype)) {
- http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
- } else {
- http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
- }
- }
-
- /* content disposition */
- {
- zval *dispo_file = GET_PROP(obj, dispoFile);
- if (Z_STRLEN_P(dispo_file)) {
- zval *dispo_inline = GET_PROP(obj, dispoInline);
- http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), Z_LVAL_P(dispo_inline));
- }
- }
-
- /* send */
- {
- zval *send_mode = GET_PROP(obj, send_mode);
- switch (Z_LVAL_P(send_mode))
- {
- case SEND_DATA:
- {
- RETURN_SUCCESS(http_send_data(GET_PROP(obj, data)));
- }
-
- case SEND_RSRC:
- {
- php_stream *the_real_stream;
- zval *the_stream = GET_PROP(obj, stream);
- php_stream_from_zval(the_real_stream, &the_stream);
- RETURN_SUCCESS(http_send_stream(the_real_stream));
- }
-
- default:
- {
- RETURN_SUCCESS(http_send_file(GET_PROP(obj, file)));
- }
- }
- }
-}
/* }}} */
/* {{{ HTTPi_Request */
zend_class_entry *httpi_request_ce;
static zend_object_handlers httpi_request_object_handlers;
-typedef struct {
- zend_object zo;
- CURL *ch;
-
- struct curl_httppost *post_data[2];
-
-} httpi_request_object;
-
#define httpi_request_declare_default_properties(ce) _httpi_request_declare_default_properties(ce TSRMLS_CC)
static inline void _httpi_request_declare_default_properties(zend_class_entry *ce TSRMLS_DC)
{
o = ecalloc(1, sizeof(httpi_request_object));
o->zo.ce = ce;
o->ch = curl_easy_init();
- o->post_data[0] = NULL;
- o->post_data[1] = NULL;
ALLOC_HASHTABLE(OBJ_PROP(o));
zend_hash_init(OBJ_PROP(o), 0, NULL, ZVAL_PTR_DTOR, 0);
{NULL, NULL, NULL}
};
-/* {{{ proto void HTTPi_Request::__construct([string url[, long request_method = HTTP_GET]])
- *
- */
-PHP_METHOD(HTTPi_Request, __construct)
-{
- char *URL = NULL;
- int URL_len;
- long meth = -1;
- zval *info, *opts, *resp;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
- return;
- }
+#endif /* HTTP_HAVE_CURL */
+/* }}} */
- INIT_PARR(obj, options);
- INIT_PARR(obj, responseInfo);
- INIT_PARR(obj, responseData);
- INIT_PARR(obj, postData);
- INIT_PARR(obj, postFiles);
+#endif /* ZEND_ENGINE_2 */
- if (URL) {
- UPD_PROP(obj, string, url, URL);
- }
- if (meth > -1) {
- UPD_PROP(obj, long, method, meth);
- }
-}
+/* {{{ http_module_entry */
+zend_module_entry http_module_entry = {
+#if ZEND_MODULE_API_NO >= 20010901
+ STANDARD_MODULE_HEADER,
+#endif
+ "http",
+ http_functions,
+ PHP_MINIT(http),
+ PHP_MSHUTDOWN(http),
+ PHP_RINIT(http),
+ PHP_RSHUTDOWN(http),
+ PHP_MINFO(http),
+#if ZEND_MODULE_API_NO >= 20010901
+ PHP_EXT_HTTP_VERSION,
+#endif
+ STANDARD_MODULE_PROPERTIES
+};
/* }}} */
-/* {{{ proto void HTTPi_Request::__destruct()
- *
- */
-PHP_METHOD(HTTPi_Request, __destruct)
+/* {{{ php_http_init_globals(zend_http_globals *) */
+static void php_http_init_globals(zend_http_globals *http_globals)
{
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- FREE_PARR(obj, options);
- FREE_PARR(obj, responseInfo);
- FREE_PARR(obj, responseData);
- FREE_PARR(obj, postData);
- FREE_PARR(obj, postFiles);
+ http_globals->etag_started = 0;
+ http_globals->ctype = NULL;
+ http_globals->etag = NULL;
+ http_globals->lmod = 0;
+#ifdef HTTP_HAVE_CURL
+ http_globals->curlbuf.data = NULL;
+ http_globals->curlbuf.used = 0;
+ http_globals->curlbuf.free = 0;
+ http_globals->curlbuf.size = 0;
+#endif
+ http_globals->allowed_methods = NULL;
}
/* }}} */
-/* {{{ proto bool HTTPi_Request::setOptions(array options)
- *
- */
-PHP_METHOD(HTTPi_Request, setOptions)
+/* {{{ static inline STATUS http_check_allowed_methods(char *, int) */
+#define http_check_allowed_methods(m, l) _http_check_allowed_methods((m), (l) TSRMLS_CC)
+static inline void _http_check_allowed_methods(char *methods, int length TSRMLS_DC)
{
- zval *opts, *old_opts, **opt;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
- RETURN_FALSE;
- }
-
- old_opts = GET_PROP(obj, options);
-
- /* headers and cookies need extra attention -- thus cannot use zend_hash_merge() or php_array_merge() directly */
- for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(opts));
- zend_hash_get_current_data(Z_ARRVAL_P(opts), (void **) &opt) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(opts))) {
- char *key;
- long idx;
- if (HASH_KEY_IS_STRING == zend_hash_get_current_key(Z_ARRVAL_P(opts), &key, &idx, 0)) {
- if (!strcmp(key, "headers")) {
- zval **headers;
- if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
- array_merge(*opt, *headers);
- continue;
- }
- } else if (!strcmp(key, "cookies")) {
- zval **cookies;
- if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
- array_merge(*opt, *cookies);
- continue;
- }
- }
- zval_add_ref(opt);
- add_assoc_zval(old_opts, key, *opt);
- }
+ if (length && SG(request_info).request_method && (!strstr(methods, SG(request_info).request_method))) {
+ char *allow_header = emalloc(length + sizeof("Allow: "));
+ sprintf(allow_header, "Allow: %s", methods);
+ http_send_header(allow_header);
+ efree(allow_header);
+ http_send_status(405);
+ zend_bailout();
}
- RETURN_TRUE;
}
/* }}} */
-/* {{{ proto array HTTPi_Request::getOptions()
- *
- */
-PHP_METHOD(HTTPi_Request, getOptions)
+/* {{{ PHP_INI */
+PHP_INI_MH(update_allowed_methods)
{
- zval *opts;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- opts = GET_PROP(obj, options);
- array_init(return_value);
- array_copy(opts, return_value);
+ http_check_allowed_methods(new_value, new_value_length);
+ return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::setURL(string url)
- *
- */
-PHP_METHOD(HTTPi_Request, setURL)
-{
- char *URL = NULL;
- int URL_len;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
- RETURN_FALSE;
- }
- UPD_PROP(obj, string, url, URL);
- RETURN_TRUE;
-}
+PHP_INI_BEGIN()
+ STD_PHP_INI_ENTRY("http.allowed_methods", "OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT", PHP_INI_ALL, update_allowed_methods, allowed_methods, zend_http_globals, http_globals)
+PHP_INI_END()
/* }}} */
-/* {{{ proto string HTTPi_Request::getUrl()
- *
- */
-PHP_METHOD(HTTPi_Request, getURL)
+/* {{{ PHP_MINIT_FUNCTION */
+PHP_MINIT_FUNCTION(http)
{
- zval *URL;
- getObject(httpi_request_object, obj);
+ ZEND_INIT_MODULE_GLOBALS(http, php_http_init_globals, NULL);
+ REGISTER_INI_ENTRIES();
- NO_ARGS;
-
- URL = GET_PROP(obj, url);
- RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::setMethod(long request_method)
- *
- */
-PHP_METHOD(HTTPi_Request, setMethod)
-{
- long meth;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, long, method, meth);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto long HTTPi_Request::getMethod()
- *
- */
-PHP_METHOD(HTTPi_Request, getMethod)
-{
- zval *meth;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- meth = GET_PROP(obj, method);
- RETURN_LONG(Z_LVAL_P(meth));
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::setContentType(string content_type)
- *
- */
-PHP_METHOD(HTTPi_Request, setContentType)
-{
- char *ctype;
- int ct_len;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
- RETURN_FALSE;
- }
-
- if (!strchr(ctype, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
- "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
- ctype);
- RETURN_FALSE;
- }
-
- UPD_PROP(obj, string, contentType, ctype);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Request::getContentType()
- *
- */
-PHP_METHOD(HTTPi_Request, getContentType)
-{
- zval *ctype;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- ctype = GET_PROP(obj, contentType);
- RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::setQueryData(mixed query_data)
- *
- */
-PHP_METHOD(HTTPi_Request, setQueryData)
-{
- zval *qdata;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
- RETURN_FALSE;
- }
-
- if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
- smart_str qstr = {0};
- HTTP_URL_ARGSEP_OVERRIDE;
- if (SUCCESS != php_url_encode_hash_ex(HASH_OF(qdata), &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
- if (qstr.c) {
- efree(qstr.c);
- }
- HTTP_URL_ARGSEP_RESTORE;
- RETURN_FALSE;
- }
- HTTP_URL_ARGSEP_RESTORE;
- smart_str_0(&qstr);
- UPD_PROP(obj, string, queryData, qstr.c);
- efree(qstr.c);
- RETURN_TRUE;
- }
-
- convert_to_string(qdata);
- UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Request::getQueryData()
- *
- */
-PHP_METHOD(HTTPi_Request, getQueryData)
-{
- zval *qdata;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- qdata = GET_PROP(obj, queryData);
- RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::addQueryData(array query_params)
- *
- */
-PHP_METHOD(HTTPi_Request, addQueryData)
-{
- zval *qdata, *old_qdata;
- smart_str qstr = {0};
- char *separator;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
- RETURN_FALSE;
- }
-
- old_qdata = GET_PROP(obj, queryData);
- if (Z_STRLEN_P(old_qdata)) {
- smart_str_appendl(&qstr, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata));
- }
-
- HTTP_URL_ARGSEP_OVERRIDE;
- if (SUCCESS != php_url_encode_hash_ex(HASH_OF(qdata), &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
- if (qstr.c) {
- efree(qstr.c);
- }
- HTTP_URL_ARGSEP_RESTORE;
- RETURN_FALSE;
- }
- HTTP_URL_ARGSEP_RESTORE;
-
- smart_str_0(&qstr);
-
- UPD_PROP(obj, string, queryData, qstr.c);
- efree(qstr.c);
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto void HTTPi_Request::unsetQueryData()
- *
- */
-PHP_METHOD(HTTPi_Request, unsetQueryData)
-{
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- UPD_PROP(obj, string, queryData, "");
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::addPostData(array post_data)
- *
- */
-PHP_METHOD(HTTPi_Request, addPostData)
-{
- zval *post, *post_data;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
- RETURN_FALSE;
- }
-
- post = GET_PROP(obj, postData);
- array_merge(post_data, post);
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::setPostData(array post_data)
- *
- */
-PHP_METHOD(HTTPi_Request, setPostData)
-{
- zval *post, *post_data;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
- RETURN_FALSE;
- }
-
- post = GET_PROP(obj, postData);
- zend_hash_clean(Z_ARRVAL_P(post));
- array_copy(post_data, post);
-
- RETURN_TRUE;
-}
-/* }}}*/
-
-/* {{{ proto array HTTPi_Request::getPostData()
- *
- */
-PHP_METHOD(HTTPi_Request, getPostData)
-{
- zval *post_data;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- post_data = GET_PROP(obj, postData);
- array_init(return_value);
- array_copy(post_data, return_value);
-}
-/* }}} */
-
-/* {{{ proto void HTTPi_Request::unsetPostData()
- *
- */
-PHP_METHOD(HTTPi_Request, unsetPostData)
-{
- zval *post_data;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- post_data = GET_PROP(obj, postData);
- zend_hash_clean(Z_ARRVAL_P(post_data));
-}
-/* }}} */
-
-/* {{{ proto bool HTTPi_Request::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
- *
- */
-PHP_METHOD(HTTPi_Request, addPostFile)
-{
- zval *files, *entry;
- char *name, *file, *type = NULL;
- int name_len, file_len, type_len = 0;
- getObject(httpi_request_object, obj);
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
- RETURN_FALSE;
- }
-
- if (type_len) {
- if (!strchr(type, '/')) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
- RETURN_FALSE;
- }
- } else {
- type = "application/x-octetstream";
- type_len = sizeof("application/x-octetstream") - 1;
- }
-
- MAKE_STD_ZVAL(entry);
- array_init(entry);
-
- add_assoc_stringl(entry, "name", name, name_len, 1);
- add_assoc_stringl(entry, "type", type, type_len, 1);
- add_assoc_stringl(entry, "file", file, file_len, 1);
-
- files = GET_PROP(obj, postFiles);
- add_next_index_zval(files, entry);
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto array HTTPi_Request::getPostFiles()
- *
- */
-PHP_METHOD(HTTPi_Request, getPostFiles)
-{
- zval *files;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- files = GET_PROP(obj, postFiles);
-
- array_init(return_value);
- array_copy(files, return_value);
-}
-/* }}} */
-
-/* {{{ proto void HTTPi_Request::unsetPostFiles()
- *
- */
-PHP_METHOD(HTTPi_Request, unsetPostFiles)
-{
- zval *files;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- files = GET_PROP(obj, postFiles);
- zend_hash_clean(Z_ARRVAL_P(files));
-}
-/* }}} */
-
-/* {{{ proto array HTTPi_Request::getResponseData()
- *
- */
-PHP_METHOD(HTTPi_Request, getResponseData)
-{
- zval *data;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- data = GET_PROP(obj, responseData);
- array_init(return_value);
- array_copy(data, return_value);
-}
-/* }}} */
-
-/* {{{ proto array HTTPi_Request::getResponseHeaders()
- *
- */
-PHP_METHOD(HTTPi_Request, getResponseHeaders)
-{
- zval *data, **headers;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- array_init(return_value);
- data = GET_PROP(obj, responseData);
- if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
- array_copy(*headers, return_value);
- }
-}
-/* }}} */
-
-/* {{{ proto string HTTPi_Request::getResponseBody()
- *
- */
-PHP_METHOD(HTTPi_Request, getResponseBody)
-{
- zval *data, **body;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- data = GET_PROP(obj, responseData);
- if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
- RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
- } else {
- Z_TYPE_P(return_value) = IS_NULL;
- }
-}
-/* }}} */
-
-/* {{{ proto array HTTPi_Request::getResponseInfo()
- *
- */
-PHP_METHOD(HTTPi_Request, getResponseInfo)
-{
- zval *info;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- info = GET_PROP(obj, responseInfo);
- array_init(return_value);
- array_copy(info, return_value);
-}
-/* }}}*/
-
-/* {{{ proto bool HTTPi_Request::send()
- *
- */
-PHP_METHOD(HTTPi_Request, send)
-{
- STATUS status = FAILURE;
- zval *meth, *URL, *qdata, *opts, *info, *resp;
- char *response_data, *request_uri;
- size_t response_len;
- getObject(httpi_request_object, obj);
-
- NO_ARGS;
-
- if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initilaize cURL");
- RETURN_FALSE;
- }
-
- meth = GET_PROP(obj, method);
- URL = GET_PROP(obj, url);
- qdata = GET_PROP(obj, queryData);
- opts = GET_PROP(obj, options);
- info = GET_PROP(obj, responseInfo);
- resp = GET_PROP(obj, responseData);
-
- // HTTP_URI_MAXLEN+1 big char *
- request_uri = http_absolute_uri(Z_STRVAL_P(URL), NULL);
-
- if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
- if (!strchr(request_uri, '?')) {
- strcat(request_uri, "?");
- } else {
- strcat(request_uri, "&");
- }
- strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
- }
-
- switch (Z_LVAL_P(meth))
- {
- case HTTP_GET:
- status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
- break;
-
- case HTTP_HEAD:
- status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
- break;
-
- case HTTP_POST:
- {
- zval *post_files, *post_data, **data;
-
- post_files = GET_PROP(obj, postFiles);
- post_data = GET_PROP(obj, postData);
-
- if (!zend_hash_num_elements(Z_ARRVAL_P(post_files))) {
-
- /* urlencoded post */
- status = http_post_array_ex(obj->ch, request_uri, Z_ARRVAL_P(post_data), Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
-
- } else {
-
- /*
- * multipart post
- */
-
- /* normal data */
- for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(post_data));
- zend_hash_get_current_data(Z_ARRVAL_P(post_data), (void **) &data) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(post_data))) {
-
- char *key;
- long idx;
-
- if (HASH_KEY_IS_STRING == zend_hash_get_current_key(Z_ARRVAL_P(post_data), &key, &idx, 0)) {
- convert_to_string_ex(data);
- curl_formadd(&obj->post_data[0], &obj->post_data[1],
- CURLFORM_COPYNAME, key,
- CURLFORM_COPYCONTENTS, Z_STRVAL_PP(data),
- CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(data),
- CURLFORM_END
- );
- }
- }
-
- /* file data */
- for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(post_files));
- zend_hash_get_current_data(Z_ARRVAL_P(post_files), (void **) &data) == SUCCESS;
- zend_hash_move_forward(Z_ARRVAL_P(post_files))) {
-
- zval **file, **type, **name;
-
- if (
- SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "name", sizeof("name"), (void **) &name) &&
- SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &type) &&
- SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "file", sizeof("file"), (void **) &file)
- ) {
-
- curl_formadd(&obj->post_data[0], &obj->post_data[1],
- CURLFORM_COPYNAME, Z_STRVAL_PP(name),
- CURLFORM_FILENAME, Z_STRVAL_PP(name),
- CURLFORM_FILE, Z_STRVAL_PP(file),
- CURLFORM_CONTENTTYPE, Z_STRVAL_PP(type),
- CURLFORM_END
- );
- }
- }
-
- status = http_post_curldata_ex(obj->ch, request_uri, obj->post_data[0], Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
- curl_formfree(obj->post_data[0]);
- }
- }
- break;
-
- default:
- break;
- }
-
- efree(request_uri);
-
- /* final data handling */
- if (status != SUCCESS) {
- RETURN_FALSE;
- } else {
- zval *zheaders, *zbody;
-
- MAKE_STD_ZVAL(zbody);
- MAKE_STD_ZVAL(zheaders)
- array_init(zheaders);
-
- if (SUCCESS != http_split_response_ex(response_data, response_len, zheaders, zbody)) {
- zval_dtor(zheaders);
- efree(zheaders),
- efree(zbody);
- efree(response_data);
- RETURN_FALSE;
- }
-
- add_assoc_zval(resp, "headers", zheaders);
- add_assoc_zval(resp, "body", zbody);
-
- efree(response_data);
-
- RETURN_TRUE;
- }
- /* */
-}
-/* }}} */
-
-#endif /* HTTP_HAVE_CURL */
-/* }}} */
-
-#endif /* ZEND_ENGINE_2 */
-
-/* {{{ http_module_entry */
-zend_module_entry http_module_entry = {
-#if ZEND_MODULE_API_NO >= 20010901
- STANDARD_MODULE_HEADER,
-#endif
- "http",
- http_functions,
- PHP_MINIT(http),
- PHP_MSHUTDOWN(http),
- PHP_RINIT(http),
- PHP_RSHUTDOWN(http),
- PHP_MINFO(http),
-#if ZEND_MODULE_API_NO >= 20010901
- PHP_EXT_HTTP_VERSION,
-#endif
- STANDARD_MODULE_PROPERTIES
-};
-/* }}} */
-
-/* {{{ proto string http_date([int timestamp])
- *
- * This function returns a valid HTTP date regarding RFC 822/1123
- * looking like: "Wed, 22 Dec 2004 11:34:47 GMT"
- *
- */
-PHP_FUNCTION(http_date)
-{
- long t = -1;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (t == -1) {
- t = (long) time(NULL);
- }
-
- RETURN_STRING(http_date(t), 0);
-}
-/* }}} */
-
-/* {{{ proto string http_absolute_uri(string url[, string proto])
- *
- * This function returns an absolute URI constructed from url.
- * 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.
- *
- * Some examples:
- * <pre>
- * url = "page.php" => http://www.example.com/current/path/page.php
- * url = "/page.php" => http://www.example.com/page.php
- * url = "/page.php", proto = "https" => https://www.example.com/page.php
- * </pre>
- *
- */
-PHP_FUNCTION(http_absolute_uri)
-{
- char *url = NULL, *proto = NULL;
- int url_len = 0, proto_len = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &url, &url_len, &proto, &proto_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- RETURN_STRING(http_absolute_uri(url, proto), 0);
-}
-/* }}} */
-
-/* {{{ proto string http_negotiate_language(array supported[, string default = 'en-US'])
- *
- * This function negotiates the clients preferred language based on its
- * Accept-Language HTTP header. It returns the negotiated language or
- * the default language if none match.
- *
- * The qualifier is recognized and languages without qualifier are rated highest.
- *
- * The supported parameter is expected to be an array having
- * the supported languages as array values.
- *
- * Example:
- * <pre>
- * <?php
- * $langs = array(
- * 'en-US',// default
- * 'fr',
- * 'fr-FR',
- * 'de',
- * 'de-DE',
- * 'de-AT',
- * 'de-CH',
- * );
- * include './langs/'. http_negotiate_language($langs) .'.php';
- * ?>
- * </pre>
- *
- */
-PHP_FUNCTION(http_negotiate_language)
-{
- zval *supported;
- char *def = NULL;
- int def_len = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &supported, &def, &def_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (!def) {
- def = "en-US";
- }
-
- RETURN_STRING(http_negotiate_language(supported, def), 0);
-}
-/* }}} */
-
-/* {{{ proto string http_negotiate_charset(array supported[, string default = 'iso-8859-1'])
- *
- * This function negotiates the clients preferred charset based on its
- * Accept-Charset HTTP header. It returns the negotiated charset or
- * the default charset if none match.
- *
- * The qualifier is recognized and charset without qualifier are rated highest.
- *
- * The supported parameter is expected to be an array having
- * the supported charsets as array values.
- *
- * Example:
- * <pre>
- * <?php
- * $charsets = array(
- * 'iso-8859-1', // default
- * 'iso-8859-2',
- * 'iso-8859-15',
- * 'utf-8'
- * );
- * $pref = http_negotiate_charset($charsets);
- * if (!strcmp($pref, 'iso-8859-1')) {
- * iconv_set_encoding('internal_encoding', 'iso-8859-1');
- * iconv_set_encoding('output_encoding', $pref);
- * ob_start('ob_iconv_handler');
- * }
- * ?>
- * </pre>
- */
-PHP_FUNCTION(http_negotiate_charset)
-{
- zval *supported;
- char *def = NULL;
- int def_len = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &supported, &def, &def_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (!def) {
- def = "iso-8859-1";
- }
-
- RETURN_STRING(http_negotiate_charset(supported, def), 0);
-}
-/* }}} */
-
-/* {{{ proto bool http_send_status(int status)
- *
- * Send HTTP status code.
- *
- */
-PHP_FUNCTION(http_send_status)
-{
- int status = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
- RETURN_FALSE;
- }
- if (status < 100 || status > 510) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid HTTP status code (100-510): %d", status);
- RETURN_FALSE;
- }
-
- RETURN_SUCCESS(http_send_status(status));
-}
-/* }}} */
-
-/* {{{ proto bool http_send_last_modified([int timestamp])
- *
- * This converts the given timestamp to a valid HTTP date and
- * sends it as "Last-Modified" HTTP header. If timestamp is
- * omitted, current time is sent.
- *
- */
-PHP_FUNCTION(http_send_last_modified)
-{
- long t = -1;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (t == -1) {
- t = (long) time(NULL);
- }
-
- RETURN_SUCCESS(http_send_last_modified(t));
-}
-/* }}} */
-
-/* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
- *
- * Sets the content type.
- *
- */
-PHP_FUNCTION(http_send_content_type)
-{
- char *ct;
- int ct_len = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (!ct_len) {
- RETURN_SUCCESS(http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1));
- }
- RETURN_SUCCESS(http_send_content_type(ct, ct_len));
-}
-/* }}} */
-
-/* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
- *
- * Set the Content Disposition. The Content-Disposition header is very useful
- * if the data actually sent came from a file or something similar, that should
- * be "saved" by the client/user (i.e. by browsers "Save as..." popup window).
- *
- */
-PHP_FUNCTION(http_send_content_disposition)
-{
- char *filename;
- int f_len;
- zend_bool send_inline = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
- RETURN_FALSE;
- }
- RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
-}
-/* }}} */
-
-/* {{{ proto bool http_match_modified([int timestamp])
- *
- * Matches the given timestamp against the clients "If-Modified-Since" resp.
- * "If-Unmodified-Since" HTTP headers.
- *
- */
-PHP_FUNCTION(http_match_modified)
-{
- long t = -1;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
- RETURN_FALSE;
- }
-
- // current time if not supplied (senseless though)
- if (t == -1) {
- t = (long) time(NULL);
- }
-
- RETURN_BOOL(http_modified_match("HTTP_IF_MODIFIED_SINCE", t) || http_modified_match("HTTP_IF_UNMODIFIED_SINCE", t));
-}
-/* }}} */
-
-/* {{{ proto bool http_match_etag(string etag)
- *
- * This matches the given ETag against the clients
- * "If-Match" resp. "If-None-Match" HTTP headers.
- *
- */
-PHP_FUNCTION(http_match_etag)
-{
- int etag_len;
- char *etag;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- RETURN_BOOL(http_etag_match("HTTP_IF_NONE_MATCH", etag) || http_etag_match("HTTP_IF_MATCH", etag));
-}
-/* }}} */
-
-/* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
- *
- * If timestamp_or_exires is greater than 0, it is handled as timestamp
- * and will be sent as date of last modification. If it is 0 or omitted,
- * the current time will be sent as Last-Modified date. If it's negative,
- * it is handled as expiration time in seconds, which means that if the
- * requested last modification date is not between the calculated timespan,
- * the Last-Modified header is updated and the actual body will be sent.
- *
- */
-PHP_FUNCTION(http_cache_last_modified)
-{
- long last_modified = 0, send_modified = 0, t;
- zval *zlm;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
- RETURN_FALSE;
- }
-
- t = (long) time(NULL);
-
- /* 0 or omitted */
- if (!last_modified) {
- /* does the client have? (att: caching "forever") */
- if (zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE")) {
- last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
- /* send current time */
- } else {
- send_modified = t;
- }
- /* negative value is supposed to be expiration time */
- } else if (last_modified < 0) {
- last_modified += t;
- send_modified = t;
- /* send supplied time explicitly */
- } else {
- send_modified = last_modified;
- }
-
- RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, sizeof(HTTP_DEFAULT_CACHECONTROL) - 1));
-}
-/* }}} */
-
-/* {{{ proto bool http_cache_etag([string etag])
- *
- * This function attempts to cache the HTTP body based on an ETag,
- * either supplied or generated through calculation of the MD5
- * checksum of the output (uses output buffering).
- *
- * If clients "If-None-Match" header matches the supplied/calculated
- * ETag, the body is considered cached on the clients side and
- * a "304 Not Modified" status code is issued.
- *
- */
-PHP_FUNCTION(http_cache_etag)
-{
- char *etag;
- int etag_len = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, sizeof(HTTP_DEFAULT_CACHECONTROL) - 1));
-}
-/* }}} */
-
-/* {{{ proto string ob_httpetaghandler(string data, int mode)
- *
- * For use with ob_start().
- * Note that this has to be started as first output buffer.
- * WARNING: Don't use with http_send_*().
- */
-PHP_FUNCTION(ob_httpetaghandler)
-{
- char *data;
- int data_len;
- long mode;
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
- RETURN_FALSE;
- }
-
- if (mode & PHP_OUTPUT_HANDLER_START) {
- if (HTTP_G(etag_started)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_httpetaghandler can only be used once");
- RETURN_STRINGL(data, data_len, 1);
- }
- http_send_header("Cache-Control: " HTTP_DEFAULT_CACHECONTROL);
- HTTP_G(etag_started) = 1;
- }
-
- if (OG(ob_nesting_level) > 1) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_httpetaghandler must be started prior to other output buffers");
- RETURN_STRINGL(data, data_len, 1);
- }
-
- Z_TYPE_P(return_value) = IS_STRING;
- http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), mode);
-}
-/* }}} */
-
-/* {{{ proto void http_redirect([string url[, array params[, bool session,[ bool permanent]]]])
- *
- * Redirect to a given url.
- * The supplied url will be expanded with http_absolute_uri(), the params array will
- * be treated with http_build_query() and the session identification will be appended
- * if session is true.
- *
- * Depending on permanent the redirection will be issued with a permanent
- * ("301 Moved Permanently") or a temporary ("302 Found") redirection
- * status code.
- *
- * To be RFC compliant, "Redirecting to <a>URI</a>." will be displayed,
- * if the client doesn't redirect immediatly.
- */
-PHP_FUNCTION(http_redirect)
-{
- int url_len;
- zend_bool session = 0, permanent = 0;
- zval *params = NULL;
- smart_str qstr = {0};
- char *url, *URI, LOC[HTTP_URI_MAXLEN + 9], RED[HTTP_URI_MAXLEN * 2 + 34];
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bb", &url, &url_len, ¶ms, &session, &permanent) != SUCCESS) {
- RETURN_FALSE;
- }
-
- /* append session info */
- if (session && (PS(session_status) == php_session_active)) {
- if (!params) {
- MAKE_STD_ZVAL(params);
- array_init(params);
- }
- if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not append session information");
- }
- }
-
- /* treat params array with http_build_query() */
- if (params) {
- if (php_url_encode_hash_ex(Z_ARRVAL_P(params), &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) {
- if (qstr.c) {
- efree(qstr.c);
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode query parameters");
- RETURN_FALSE;
- }
- smart_str_0(&qstr);
- }
-
- URI = http_absolute_uri(url, NULL);
- if (qstr.c) {
- snprintf(LOC, HTTP_URI_MAXLEN + strlen("Location: "), "Location: %s?%s", URI, qstr.c);
- sprintf(RED, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, qstr.c, URI, qstr.c);
- efree(qstr.c);
- } else {
- snprintf(LOC, HTTP_URI_MAXLEN + strlen("Location: "), "Location: %s", URI);
- sprintf(RED, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
- }
- efree(URI);
-
- if ((SUCCESS == http_send_header(LOC)) && (SUCCESS == http_send_status((permanent ? 301 : 302)))) {
- php_body_write(RED, strlen(RED) TSRMLS_CC);
- RETURN_TRUE;
- }
- RETURN_FALSE;
-}
-/* }}} */
-
-/* {{{ proto bool http_send_data(string data)
- *
- * Sends raw data with support for (multiple) range requests.
- *
- */
-PHP_FUNCTION(http_send_data)
-{
- zval *zdata;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zdata) != SUCCESS) {
- RETURN_FALSE;
- }
-
- convert_to_string_ex(&zdata);
- http_send_header("Accept-Ranges: bytes");
- RETURN_SUCCESS(http_send_data(zdata));
-}
-/* }}} */
-
-/* {{{ proto bool http_send_file(string file)
- *
- * Sends a file with support for (multiple) range requests.
- *
- */
-PHP_FUNCTION(http_send_file)
-{
- zval *zfile;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zfile) != SUCCESS) {
- RETURN_FALSE;
- }
-
- convert_to_string_ex(&zfile);
- http_send_header("Accept-Ranges: bytes");
- RETURN_SUCCESS(http_send_file(zfile));
-}
-/* }}} */
-
-/* {{{ proto bool http_send_stream(resource stream)
- *
- * Sends an already opened stream with support for (multiple) range requests.
- *
- */
-PHP_FUNCTION(http_send_stream)
-{
- zval *zstream;
- php_stream *file;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
- RETURN_FALSE;
- }
-
- php_stream_from_zval(file, &zstream);
- http_send_header("Accept-Ranges: bytes");
- RETURN_SUCCESS(http_send_stream(file));
-}
-/* }}} */
-
-/* {{{ proto string http_chunked_decode(string encoded)
- *
- * This function decodes a string that was HTTP-chunked encoded.
- * Returns false on failure.
- */
-PHP_FUNCTION(http_chunked_decode)
-{
- char *encoded = NULL, *decoded = NULL;
- int encoded_len = 0, decoded_len = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (SUCCESS == http_chunked_decode(encoded, encoded_len, &decoded, &decoded_len)) {
- RETURN_STRINGL(decoded, decoded_len, 0);
- } else {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto array http_split_response(string http_response)
- *
- * This function splits an HTTP response into an array with headers and the
- * content body. The returned array may look simliar to the following example:
- *
- * <pre>
- * <?php
- * array(
- * 0 => array(
- * 'Status' => '200 Ok',
- * 'Content-Type' => 'text/plain',
- * 'Content-Language' => 'en-US'
- * ),
- * 1 => "Hello World!"
- * );
- * ?>
- * </pre>
- */
-PHP_FUNCTION(http_split_response)
-{
- zval *zresponse, *zbody, *zheaders;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zresponse) != SUCCESS) {
- RETURN_FALSE;
- }
-
- convert_to_string_ex(&zresponse);
-
- MAKE_STD_ZVAL(zbody);
- MAKE_STD_ZVAL(zheaders);
- array_init(zheaders);
-
- if (SUCCESS != http_split_response(zresponse, zheaders, zbody)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP response");
- RETURN_FALSE;
- }
-
- array_init(return_value);
- add_index_zval(return_value, 0, zheaders);
- add_index_zval(return_value, 1, zbody);
-}
-/* }}} */
-
-/* {{{ proto array http_parse_headers(string header)
- *
- */
-PHP_FUNCTION(http_parse_headers)
-{
- char *header, *rnrn;
- int header_len;
-
- if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
- RETURN_FALSE;
- }
-
- array_init(return_value);
-
- if (rnrn = strstr(header, HTTP_CRLF HTTP_CRLF)) {
- header_len = rnrn - header + 2;
- }
- if (SUCCESS != http_parse_headers(header, header_len, return_value)) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP header");
- zval_dtor(return_value);
- RETURN_FALSE;
- }
-}
-/* }}}*/
-
-/* {{{ proto array http_get_request_headers(void)
- *
- */
-PHP_FUNCTION(http_get_request_headers)
-{
- if (ZEND_NUM_ARGS()) {
- WRONG_PARAM_COUNT;
- }
-
- array_init(return_value);
- http_get_request_headers(return_value);
-}
-/* }}} */
-
-/* {{{ HAVE_CURL */
-#ifdef HTTP_HAVE_CURL
-
-/* {{{ proto string http_get(string url[, array options[, array &info]])
- *
- * Performs an HTTP GET request on the supplied url.
- *
- * The second parameter is expected to be an associative
- * array where the following keys will be recognized:
- * <pre>
- * - redirect: int, whether and how many redirects to follow
- * - unrestrictedauth: bool, whether to continue sending credentials on
- * redirects to a different host
- * - proxyhost: string, proxy host in "host[:port]" format
- * - proxyport: int, use another proxy port as specified in proxyhost
- * - proxyauth: string, proxy credentials in "user:pass" format
- * - proxyauthtype: int, HTTP_AUTH_BASIC and/or HTTP_AUTH_NTLM
- * - httpauth: string, http credentials in "user:pass" format
- * - httpauthtype: int, HTTP_AUTH_BASIC, DIGEST and/or NTLM
- * - compress: bool, whether to allow gzip/deflate content encoding
- * (defaults to true)
- * - port: int, use another port as specified in the url
- * - referer: string, the referer to sends
- * - useragent: string, the user agent to send
- * (defaults to PECL::HTTP/version (PHP/version)))
- * - headers: array, list of custom headers as associative array
- * like array("header" => "value")
- * - cookies: array, list of cookies as associative array
- * like array("cookie" => "value")
- * - cookiestore: string, path to a file where cookies are/will be stored
- * </pre>
- *
- * The optional third parameter will be filled with some additional information
- * in form af an associative array, if supplied, like the following example:
- * <pre>
- * <?php
- * array (
- * 'effective_url' => 'http://localhost',
- * 'response_code' => 403,
- * 'total_time' => 0.017,
- * 'namelookup_time' => 0.013,
- * 'connect_time' => 0.014,
- * 'pretransfer_time' => 0.014,
- * 'size_upload' => 0,
- * 'size_download' => 202,
- * 'speed_download' => 11882,
- * 'speed_upload' => 0,
- * 'header_size' => 145,
- * 'request_size' => 62,
- * 'ssl_verifyresult' => 0,
- * 'filetime' => -1,
- * 'content_length_download' => 202,
- * 'content_length_upload' => 0,
- * 'starttransfer_time' => 0.017,
- * 'content_type' => 'text/html; charset=iso-8859-1',
- * 'redirect_time' => 0,
- * 'redirect_count' => 0,
- * 'private' => '',
- * 'http_connectcode' => 0,
- * 'httpauth_avail' => 0,
- * 'proxyauth_avail' => 0,
- * )
- * ?>
- * </pre>
- */
-PHP_FUNCTION(http_get)
-{
- char *URL, *data = NULL;
- size_t data_len = 0;
- int URL_len;
- zval *options = NULL, *info = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (info) {
- zval_dtor(info);
- array_init(info);
- }
-
- if (SUCCESS == http_get(URL, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
- } else {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto string http_head(string url[, array options[, array &info]])
- *
- * Performs an HTTP HEAD request on the suppied url.
- * Returns the HTTP response as string.
- * See http_get() for a full list of available options.
- */
-PHP_FUNCTION(http_head)
-{
- char *URL, *data = NULL;
- size_t data_len = 0;
- int URL_len;
- zval *options = NULL, *info = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (info) {
- zval_dtor(info);
- array_init(info);
- }
-
- if (SUCCESS == http_head(URL, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
- } else {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto string http_post_data(string url, string data[, array options[, &info]])
- *
- * Performs an HTTP POST request, posting data.
- * Returns the HTTP response as string.
- * See http_get() for a full list of available options.
- */
-PHP_FUNCTION(http_post_data)
-{
- char *URL, *postdata, *data = NULL;
- size_t data_len = 0;
- int postdata_len, URL_len;
- zval *options = NULL, *info = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (info) {
- zval_dtor(info);
- array_init(info);
- }
-
- if (SUCCESS == http_post_data(URL, postdata, (size_t) postdata_len, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
- } else {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-/* {{{ proto string http_post_array(string url, array data[, array options[, array &info]])
- *
- * Performs an HTTP POST request, posting www-form-urlencoded array data.
- * Returns the HTTP response as string.
- * See http_get() for a full list of available options.
- */
-PHP_FUNCTION(http_post_array)
-{
- char *URL, *data = NULL;
- size_t data_len = 0;
- int URL_len;
- zval *options = NULL, *info = NULL, *postdata;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a/!z", &URL, &URL_len, &postdata, &options, &info) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (info) {
- zval_dtor(info);
- array_init(info);
- }
-
- if (SUCCESS == http_post_array(URL, Z_ARRVAL_P(postdata), HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
- RETURN_STRINGL(data, data_len, 0);
- } else {
- RETURN_FALSE;
- }
-}
-/* }}} */
-
-#endif
-/* }}} HAVE_CURL */
-
-
-/* {{{ proto bool http_auth_basic(string user, string pass[, string realm = "Restricted"])
- *
- * Example:
- * <pre>
- * <?php
- * if (!http_auth_basic('mike', 's3c|r3t')) {
- * die('<h1>Authorization failed!</h1>');
- * }
- * ?>
- * </pre>
- */
-PHP_FUNCTION(http_auth_basic)
-{
- char *realm = NULL, *user, *pass, *suser, *spass;
- int r_len, u_len, p_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &user, &u_len, &pass, &p_len, &realm, &r_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (!realm) {
- realm = "Restricted";
- }
-
- if (SUCCESS != http_auth_credentials(&suser, &spass)) {
- http_auth_header("Basic", realm);
- RETURN_FALSE;
- }
-
- if (strcasecmp(suser, user)) {
- http_auth_header("Basic", realm);
- RETURN_FALSE;
- }
-
- if (strcmp(spass, pass)) {
- http_auth_header("Basic", realm);
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool http_auth_basic_cb(mixed callback[, string realm = "Restricted"])
- *
- * Example:
- * <pre>
- * <?php
- * function auth_cb($user, $pass)
- * {
- * global $db;
- * $query = 'SELECT pass FROM users WHERE user='. $db->quoteSmart($user);
- * if (strlen($realpass = $db->getOne($query)) {
- * return $pass === $realpass;
- * }
- * return false;
- * }
- *
- * if (!http_auth_basic_cb('auth_cb')) {
- * die('<h1>Authorization failed</h1>');
- * }
- * ?>
- * </pre>
- */
-PHP_FUNCTION(http_auth_basic_cb)
-{
- zval *cb;
- char *realm = NULL, *user, *pass;
- int r_len;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &cb, &realm, &r_len) != SUCCESS) {
- RETURN_FALSE;
- }
-
- if (!realm) {
- realm = "Restricted";
- }
-
- if (SUCCESS != http_auth_credentials(&user, &pass)) {
- http_auth_header("Basic", realm);
- RETURN_FALSE;
- }
- {
- zval *zparams[2] = {NULL, NULL}, retval;
- int result = 0;
-
- MAKE_STD_ZVAL(zparams[0]);
- MAKE_STD_ZVAL(zparams[1]);
- ZVAL_STRING(zparams[0], user, 0);
- ZVAL_STRING(zparams[1], pass, 0);
-
- if (SUCCESS == call_user_function(EG(function_table), NULL, cb,
- &retval, 2, zparams TSRMLS_CC)) {
- result = Z_LVAL(retval);
- }
-
- efree(user);
- efree(pass);
- efree(zparams[0]);
- efree(zparams[1]);
-
- if (!result) {
- http_auth_header("Basic", realm);
- }
-
- RETURN_BOOL(result);
- }
-}
-/* }}}*/
-
-
-/* {{{ php_http_init_globals(zend_http_globals *) */
-static void php_http_init_globals(zend_http_globals *http_globals)
-{
- http_globals->etag_started = 0;
- http_globals->ctype = NULL;
- http_globals->etag = NULL;
- http_globals->lmod = 0;
-#ifdef HTTP_HAVE_CURL
- http_globals->curlbuf.body.data = NULL;
- http_globals->curlbuf.body.used = 0;
- http_globals->curlbuf.body.free = 0;
- http_globals->curlbuf.hdrs.data = NULL;
- http_globals->curlbuf.hdrs.used = 0;
- http_globals->curlbuf.hdrs.free = 0;
-#endif
- http_globals->allowed_methods = NULL;
-}
-/* }}} */
-
-/* {{{ static inline STATUS http_check_allowed_methods(char *, int) */
-#define http_check_allowed_methods(m, l) _http_check_allowed_methods((m), (l) TSRMLS_CC)
-static inline void _http_check_allowed_methods(char *methods, int length TSRMLS_DC)
-{
- if (length && SG(request_info).request_method && (!strstr(methods, SG(request_info).request_method))) {
- char *allow_header = emalloc(length + sizeof("Allow: "));
- sprintf(allow_header, "Allow: %s", methods);
- http_send_header(allow_header);
- efree(allow_header);
- http_send_status(405);
- zend_bailout();
- }
-}
-/* }}} */
-
-/* {{{ PHP_INI */
-PHP_INI_MH(update_allowed_methods)
-{
- http_check_allowed_methods(new_value, new_value_length);
- return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC);
-}
-
-PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("http.allowed_methods", "OPTIONS,GET,HEAD,POST,PUT,DELETE,TRACE,CONNECT", PHP_INI_ALL, update_allowed_methods, allowed_methods, zend_http_globals, http_globals)
-PHP_INI_END()
-/* }}} */
-
-/* {{{ PHP_MINIT_FUNCTION */
-PHP_MINIT_FUNCTION(http)
-{
- ZEND_INIT_MODULE_GLOBALS(http, php_http_init_globals, NULL);
- REGISTER_INI_ENTRIES();
-
-#if defined(HTTP_HAVE_CURL) && (LIBCURL_VERSION_NUM >= 0x070a05)
- REGISTER_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST, CONST_CS | CONST_PERSISTENT);
- REGISTER_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM, CONST_CS | CONST_PERSISTENT);
-#endif
+#if defined(HTTP_HAVE_CURL) && (LIBCURL_VERSION_NUM >= 0x070a05)
+ REGISTER_LONG_CONSTANT("HTTP_AUTH_BASIC", CURLAUTH_BASIC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("HTTP_AUTH_DIGEST", CURLAUTH_DIGEST, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("HTTP_AUTH_NTLM", CURLAUTH_NTLM, CONST_CS | CONST_PERSISTENT);
+#endif
#ifdef ZEND_ENGINE_2
HTTP_REGISTER_CLASS(HTTPi, httpi, NULL, ZEND_ACC_FINAL_CLASS);
HTTP_G(ctype) = NULL;
}
#ifdef HTTP_HAVE_CURL
- if (HTTP_G(curlbuf).body.data) {
- efree(HTTP_G(curlbuf).body.data);
- HTTP_G(curlbuf).body.data = NULL;
- }
- if (HTTP_G(curlbuf).hdrs.data) {
- efree(HTTP_G(curlbuf).hdrs.data);
- HTTP_G(curlbuf).hdrs.data = NULL;
+ if (HTTP_G(curlbuf).data) {
+ efree(HTTP_G(curlbuf).data);
+ HTTP_G(curlbuf).data = NULL;
+ HTTP_G(curlbuf).used = 0;
+ HTTP_G(curlbuf).free = 0;
}
#endif
return SUCCESS;
#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
-
-#if !defined(CURLINFO_RESONSE_CODE) && defined(CURLINFO_HTTP_CODE)
-#define CURLINFO_RESONSE_CODE CURLINFO_HTTP_CODE
-#endif
-
ZEND_DECLARE_MODULE_GLOBALS(http)
/* {{{ day/month names */
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);
static int http_ob_stack_get(php_ob_buffer *, php_ob_buffer **);
-/* {{{ 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)
-static inline void _http_curl_freebuf(http_curlbuf_member member TSRMLS_DC);
-#define http_curl_sizebuf(m, l) _http_curl_sizebuf((m), (l) TSRMLS_CC)
-static inline void _http_curl_sizebuf(http_curlbuf_member member, size_t len TSRMLS_DC);
-#define http_curl_movebuf(m, d, l) _http_curl_movebuf((m), (d), (l) TSRMLS_CC)
-static inline void _http_curl_movebuf(http_curlbuf_member member, char **data, size_t *data_len TSRMLS_DC);
-#define http_curl_copybuf(m, d, l) _http_curl_copybuf((m), (d), (l) TSRMLS_CC)
-static inline void _http_curl_copybuf(http_curlbuf_member member, char **data, size_t *data_len TSRMLS_DC);
-#define http_curl_setopts(c, u, o) _http_curl_setopts((c), (u), (o) TSRMLS_CC)
-static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC);
-
-#define http_curl_getopt(o, k) _http_curl_getopt((o), (k) TSRMLS_CC, 0)
-#define http_curl_getopt1(o, k, t1) _http_curl_getopt((o), (k) TSRMLS_CC, 1, (t1))
-#define http_curl_getopt2(o, k, t1, t2) _http_curl_getopt((o), (k) TSRMLS_CC, 2, (t1), (t2))
-static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...);
-
-static size_t http_curl_body_callback(char *, size_t, size_t, void *);
-static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *);
-
-#define http_curl_getinfo(c, h) _http_curl_getinfo((c), (h) TSRMLS_CC)
-static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC);
-#define http_curl_getinfo_ex(c, i, a) _http_curl_getinfo_ex((c), (i), (a) TSRMLS_CC)
-static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC);
-#define http_curl_getinfoname(i) _http_curl_getinfoname((i) TSRMLS_CC)
-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)
{
}
/* }}} */
-/* {{{ 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)
-{
- http_curl_freebuf(member);
-
- if (member & CURLBUF_HDRS) {
- HTTP_G(curlbuf).hdrs.data = emalloc(HTTP_CURLBUF_HDRSSIZE);
- HTTP_G(curlbuf).hdrs.free = HTTP_CURLBUF_HDRSSIZE;
- }
- if (member & CURLBUF_BODY) {
- HTTP_G(curlbuf).body.data = emalloc(HTTP_CURLBUF_BODYSIZE);
- HTTP_G(curlbuf).body.free = HTTP_CURLBUF_BODYSIZE;
- }
-}
-/* }}} */
-
-/* {{{ static inline void http_curl_freebuf(http_curlbuf_member) */
-static inline void _http_curl_freebuf(http_curlbuf_member member TSRMLS_DC)
-{
- if (member & CURLBUF_HDRS) {
- if (HTTP_G(curlbuf).hdrs.data) {
- efree(HTTP_G(curlbuf).hdrs.data);
- HTTP_G(curlbuf).hdrs.data = NULL;
- }
- HTTP_G(curlbuf).hdrs.used = 0;
- HTTP_G(curlbuf).hdrs.free = 0;
- }
- if (member & CURLBUF_BODY) {
- if (HTTP_G(curlbuf).body.data) {
- efree(HTTP_G(curlbuf).body.data);
- HTTP_G(curlbuf).body.data = NULL;
- }
- HTTP_G(curlbuf).body.used = 0;
- HTTP_G(curlbuf).body.free = 0;
- }
-}
-/* }}} */
-
-/* {{{ static inline void http_curl_copybuf(http_curlbuf_member, char **,
- size_t *) */
-static inline void _http_curl_copybuf(http_curlbuf_member member, char **data,
- size_t *data_len TSRMLS_DC)
-{
- *data = NULL;
- *data_len = 0;
-
- if ((member & CURLBUF_HDRS) && HTTP_G(curlbuf).hdrs.used) {
- if ((member & CURLBUF_BODY) && HTTP_G(curlbuf).body.used) {
- *data = emalloc(HTTP_G(curlbuf).hdrs.used + HTTP_G(curlbuf).body.used + 1);
- } else {
- *data = emalloc(HTTP_G(curlbuf).hdrs.used + 1);
- }
- memcpy(*data, HTTP_G(curlbuf).hdrs.data, HTTP_G(curlbuf).hdrs.used);
- *data_len = HTTP_G(curlbuf).hdrs.used;
- }
-
- if ((member & CURLBUF_BODY) && HTTP_G(curlbuf).body.used) {
- if (*data) {
- memcpy((*data) + HTTP_G(curlbuf).hdrs.used,
- HTTP_G(curlbuf).body.data, HTTP_G(curlbuf).body.used);
- *data_len = HTTP_G(curlbuf).hdrs.used + HTTP_G(curlbuf).body.used;
- } else {
- emalloc(HTTP_G(curlbuf).body.used + 1);
- memcpy(*data, HTTP_G(curlbuf).body.data, HTTP_G(curlbuf).body.used);
- *data_len = HTTP_G(curlbuf).body.used;
- }
- }
- if (*data) {
- (*data)[*data_len] = 0;
- } else {
- *data = "";
- }
-}
-/* }}} */
-
-/* {{{ static inline void http_curl_movebuf(http_curlbuf_member, char **,
- size_t *) */
-static inline void _http_curl_movebuf(http_curlbuf_member member, char **data,
- size_t *data_len TSRMLS_DC)
-{
- http_curl_copybuf(member, data, data_len);
- http_curl_freebuf(member);
-}
-/* }}} */
-
-/* {{{ static size_t http_curl_body_callback(char *, size_t, size_t, void *) */
-static size_t http_curl_body_callback(char *buf, size_t len, size_t n, void *s)
-{
- TSRMLS_FETCH();
-
- if ((len *= n) > HTTP_G(curlbuf).body.free) {
- size_t bsize = HTTP_CURLBUF_BODYSIZE;
- while (bsize < len) {
- bsize *= 2;
- }
- HTTP_G(curlbuf).body.data = erealloc(HTTP_G(curlbuf).body.data,
- HTTP_G(curlbuf).body.used + bsize);
- HTTP_G(curlbuf).body.free += bsize;
- }
-
- memcpy(HTTP_G(curlbuf).body.data + HTTP_G(curlbuf).body.used, buf, len);
- HTTP_G(curlbuf).body.free -= len;
- HTTP_G(curlbuf).body.used += len;
-
- return len;
-}
-/* }}} */
-
-/* {{{ static size_t http_curl_hdrs_callback(char*, size_t, size_t, void *) */
-static size_t http_curl_hdrs_callback(char *buf, size_t len, size_t n, void *s)
-{
- TSRMLS_FETCH();
-
- /* discard previous headers */
- if ((HTTP_G(curlbuf).hdrs.used) && (!strncmp(buf, "HTTP/1.", strlen("HTTP/1.")))) {
- http_curl_initbuf(CURLBUF_HDRS);
- }
-
- if ((len *= n) > HTTP_G(curlbuf).hdrs.free) {
- size_t bsize = HTTP_CURLBUF_HDRSSIZE;
- while (bsize < len) {
- bsize *= 2;
- }
- HTTP_G(curlbuf).hdrs.data = erealloc(HTTP_G(curlbuf).hdrs.data,
- HTTP_G(curlbuf).hdrs.used + bsize);
- HTTP_G(curlbuf).hdrs.free += bsize;
- }
-
- memcpy(HTTP_G(curlbuf).hdrs.data + HTTP_G(curlbuf).hdrs.used, buf, len);
- HTTP_G(curlbuf).hdrs.free -= len;
- HTTP_G(curlbuf).hdrs.used += len;
-
- return len;
-}
-/* }}} */
-
-/* {{{ static inline zval *http_curl_getopt(HashTable *, char *, int, ...) */
-static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...)
-{
- zval **zoption;
- va_list types;
- int i;
-
- if (SUCCESS != zend_hash_find(options, key, strlen(key) + 1, (void **) &zoption)) {
- return NULL;
- }
- if (checks < 1) {
- return *zoption;
- }
-
- va_start(types, checks);
- for (i = 0; i < checks; ++i) {
- if ((va_arg(types, int)) == (Z_TYPE_PP(zoption))) {
- va_end(types);
- return *zoption;
- }
- }
- va_end(types);
- return NULL;
-}
-/* }}} */
-
-/* {{{ static inline void http_curl_setopts(CURL *, char *, HashTable *) */
-static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC)
-{
- zval *zoption;
-
- /* standard options */
- curl_easy_setopt(ch, CURLOPT_URL, url);
- curl_easy_setopt(ch, CURLOPT_HEADER, 0);
- curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1);
- 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) && (LIBCURL_VERSION_NUM >= 0x070a00)
- curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1);
-#endif
-
- if ((!options) || (1 > zend_hash_num_elements(options))) {
- return;
- }
-
- /* redirects, defaults to 0 */
- if (zoption = http_curl_getopt1(options, "redirect", IS_LONG)) {
- curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1 : 0);
- curl_easy_setopt(ch, CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
- if (zoption = http_curl_getopt2(options, "unrestrictedauth", IS_LONG, IS_BOOL)) {
- curl_easy_setopt(ch, CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption));
- }
- } else {
- curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 0);
- }
-
- /* proxy */
- if (zoption = http_curl_getopt1(options, "proxyhost", IS_STRING)) {
- curl_easy_setopt(ch, CURLOPT_PROXY, Z_STRVAL_P(zoption));
- /* port */
- if (zoption = http_curl_getopt1(options, "proxyport", IS_LONG)) {
- curl_easy_setopt(ch, CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
- }
- /* user:pass */
- if (zoption = http_curl_getopt1(options, "proxyauth", IS_STRING)) {
- curl_easy_setopt(ch, CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
- }
-#if LIBCURL_VERSION_NUM > 0x070a06
- /* auth method */
- if (zoption = http_curl_getopt1(options, "proxyauthtype", IS_LONG)) {
- curl_easy_setopt(ch, CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
- }
-#endif
- }
-
- /* auth */
- if (zoption = http_curl_getopt1(options, "httpauth", IS_STRING)) {
- curl_easy_setopt(ch, CURLOPT_USERPWD, Z_STRVAL_P(zoption));
- }
-#if LIBCURL_VERSION_NUM > 0x070a05
- if (zoption = http_curl_getopt1(options, "httpauthtype", IS_LONG)) {
- curl_easy_setopt(ch, CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
- }
-#endif
-
- /* compress, enabled by default (empty string enables deflate and gzip) */
- if (zoption = http_curl_getopt2(options, "compress", IS_LONG, IS_BOOL)) {
- if (Z_LVAL_P(zoption)) {
- curl_easy_setopt(ch, CURLOPT_ENCODING, "");
- }
- } else {
- curl_easy_setopt(ch, CURLOPT_ENCODING, "");
- }
-
- /* another port */
- if (zoption = http_curl_getopt1(options, "port", IS_LONG)) {
- curl_easy_setopt(ch, CURLOPT_PORT, Z_LVAL_P(zoption));
- }
-
- /* referer */
- if (zoption = http_curl_getopt1(options, "referer", IS_STRING)) {
- curl_easy_setopt(ch, CURLOPT_REFERER, Z_STRVAL_P(zoption));
- }
-
- /* useragent, default "PECL::HTTP/version (PHP/version)" */
- if (zoption = http_curl_getopt1(options, "useragent", IS_STRING)) {
- curl_easy_setopt(ch, CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
- } else {
- curl_easy_setopt(ch, CURLOPT_USERAGENT,
- "PECL::HTTP/" PHP_EXT_HTTP_VERSION " (PHP/" PHP_VERSION ")");
- }
-
- /* cookies, array('name' => 'value') */
- if (zoption = http_curl_getopt1(options, "cookies", IS_ARRAY)) {
- char *cookie_key;
- zval **cookie_val;
- int key_type;
- smart_str qstr = {0};
-
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
- while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
- if (key_type == HASH_KEY_IS_STRING) {
- zend_hash_get_current_key(Z_ARRVAL_P(zoption), &cookie_key, NULL, 0);
- zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &cookie_val);
- smart_str_appends(&qstr, cookie_key);
- smart_str_appendl(&qstr, "=", 1);
- smart_str_appendl(&qstr, Z_STRVAL_PP(cookie_val), Z_STRLEN_PP(cookie_val));
- smart_str_appendl(&qstr, "; ", 2);
- zend_hash_move_forward(Z_ARRVAL_P(zoption));
- }
- }
- smart_str_0(&qstr);
-
- if (qstr.c) {
- curl_easy_setopt(ch, CURLOPT_COOKIE, qstr.c);
- /* FIXXXME: mem-leak */
- }
- }
-
- /* cookiestore */
- if (zoption = http_curl_getopt1(options, "cookiestore", IS_STRING)) {
- curl_easy_setopt(ch, CURLOPT_COOKIEFILE, Z_STRVAL_P(zoption));
- curl_easy_setopt(ch, CURLOPT_COOKIEJAR, Z_STRVAL_P(zoption));
- }
-
- /* additional headers, array('name' => 'value') */
- if (zoption = http_curl_getopt1(options, "headers", IS_ARRAY)) {
- int key_type;
- char *header_key, header[1024] = {0};
- zval **header_val;
- struct curl_slist *headers = NULL;
-
- zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
- while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
- 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, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val));
- headers = curl_slist_append(headers, header);
- zend_hash_move_forward(Z_ARRVAL_P(zoption));
- }
- }
- if (headers) {
- curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
- }
- }
-}
-/* }}} */
-
-/* {{{ static inline char *http_curl_getinfoname(CURLINFO) */
-static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC)
-{
-#define CASE(I) case CURLINFO_ ##I : { static char I[] = #I; return pretty_key(I, sizeof(#I)-1, 0, 0); }
- switch (i)
- {
- /* CURLINFO_EFFECTIVE_URL = CURLINFO_STRING +1, */
- CASE(EFFECTIVE_URL);
- /* CURLINFO_RESPONSE_CODE = CURLINFO_LONG +2, */
-#if LIBCURL_VERSION_NUM > 0x070a06
- CASE(RESPONSE_CODE);
-#else
- CASE(HTTP_CODE);
-#endif
- /* CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE +3, */
- CASE(TOTAL_TIME);
- /* CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE +4, */
- CASE(NAMELOOKUP_TIME);
- /* CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE +5, */
- CASE(CONNECT_TIME);
- /* CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE +6, */
- CASE(PRETRANSFER_TIME);
- /* CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE +7, */
- CASE(SIZE_UPLOAD);
- /* CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE +8, */
- CASE(SIZE_DOWNLOAD);
- /* CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE +9, */
- CASE(SPEED_DOWNLOAD);
- /* CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE +10, */
- CASE(SPEED_UPLOAD);
- /* CURLINFO_HEADER_SIZE = CURLINFO_LONG +11, */
- CASE(HEADER_SIZE);
- /* CURLINFO_REQUEST_SIZE = CURLINFO_LONG +12, */
- CASE(REQUEST_SIZE);
- /* CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG +13, */
- CASE(SSL_VERIFYRESULT);
- /* CURLINFO_FILETIME = CURLINFO_LONG +14, */
- CASE(FILETIME);
- /* CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE +15, */
- CASE(CONTENT_LENGTH_DOWNLOAD);
- /* CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE +16, */
- CASE(CONTENT_LENGTH_UPLOAD);
- /* CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE +17, */
- CASE(STARTTRANSFER_TIME);
- /* CURLINFO_CONTENT_TYPE = CURLINFO_STRING +18, */
- CASE(CONTENT_TYPE);
- /* CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE +19, */
- CASE(REDIRECT_TIME);
- /* CURLINFO_REDIRECT_COUNT = CURLINFO_LONG +20, */
- CASE(REDIRECT_COUNT);
- /* CURLINFO_PRIVATE = CURLINFO_STRING +21, * (mike) /
- CASE(PRIVATE);
- /* CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG +22, */
- CASE(HTTP_CONNECTCODE);
-#if LIBCURL_VERSION_NUM > 0x070a07
- /* CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG +23, */
- CASE(HTTPAUTH_AVAIL);
- /* CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG +24, */
- CASE(PROXYAUTH_AVAIL);
-#endif
- }
-#undef CASE
- return NULL;
-}
-/* }}} */
-
-/* {{{ static inline void http_curl_getinfo_ex(CURL, CURLINFO, zval *) */
-static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC)
-{
- char *key;
- if (key = http_curl_getinfoname(i)) {
- switch (i & ~CURLINFO_MASK)
- {
- case CURLINFO_STRING:
- {
- char *c;
- if (CURLE_OK == curl_easy_getinfo(ch, i, &c)) {
- add_assoc_string(array, key, c ? c : "", 1);
- }
- }
- break;
-
- case CURLINFO_DOUBLE:
- {
- double d;
- if (CURLE_OK == curl_easy_getinfo(ch, i, &d)) {
- add_assoc_double(array, key, d);
- }
- }
- break;
-
- case CURLINFO_LONG:
- {
- long l;
- if (CURLE_OK == curl_easy_getinfo(ch, i, &l)) {
- add_assoc_long(array, key, l);
- }
- }
- break;
- }
- }
-}
-/* }}} */
-
-/* {{{ static inline http_curl_getinfo(CURL, HashTable *) */
-static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC)
-{
- zval array;
- Z_ARRVAL(array) = info;
-
-#define INFO(I) http_curl_getinfo_ex(ch, CURLINFO_ ##I , &array)
- /* CURLINFO_EFFECTIVE_URL = CURLINFO_STRING +1, */
- INFO(EFFECTIVE_URL);
-#if LIBCURL_VERSION_NUM > 0x070a06
- /* CURLINFO_RESPONSE_CODE = CURLINFO_LONG +2, */
- INFO(RESPONSE_CODE);
-#else
- INFO(HTTP_CODE);
-#endif
- /* CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE +3, */
- INFO(TOTAL_TIME);
- /* CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE +4, */
- INFO(NAMELOOKUP_TIME);
- /* CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE +5, */
- INFO(CONNECT_TIME);
- /* CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE +6, */
- INFO(PRETRANSFER_TIME);
- /* CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE +7, */
- INFO(SIZE_UPLOAD);
- /* CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE +8, */
- INFO(SIZE_DOWNLOAD);
- /* CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE +9, */
- INFO(SPEED_DOWNLOAD);
- /* CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE +10, */
- INFO(SPEED_UPLOAD);
- /* CURLINFO_HEADER_SIZE = CURLINFO_LONG +11, */
- INFO(HEADER_SIZE);
- /* CURLINFO_REQUEST_SIZE = CURLINFO_LONG +12, */
- INFO(REQUEST_SIZE);
- /* CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG +13, */
- INFO(SSL_VERIFYRESULT);
- /* CURLINFO_FILETIME = CURLINFO_LONG +14, */
- INFO(FILETIME);
- /* CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE +15, */
- INFO(CONTENT_LENGTH_DOWNLOAD);
- /* CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE +16, */
- INFO(CONTENT_LENGTH_UPLOAD);
- /* CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE +17, */
- INFO(STARTTRANSFER_TIME);
- /* CURLINFO_CONTENT_TYPE = CURLINFO_STRING +18, */
- INFO(CONTENT_TYPE);
- /* CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE +19, */
- INFO(REDIRECT_TIME);
- /* CURLINFO_REDIRECT_COUNT = CURLINFO_LONG +20, */
- INFO(REDIRECT_COUNT);
- /* CURLINFO_PRIVATE = CURLINFO_STRING +21, */
- INFO(PRIVATE);
- /* CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG +22, */
- INFO(HTTP_CONNECTCODE);
-#if LIBCURL_VERSION_NUM > 0x070a07
- /* CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG +23, */
- INFO(HTTPAUTH_AVAIL);
- /* CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG +24, */
- INFO(PROXYAUTH_AVAIL);
-#endif
-#undef INFO
-}
-/* }}} */
-
-#endif
-/* }}} HAVE_CURL */
-
/* {{{ Day/Month/TZ checks for http_parse_date()
Originally by libcurl, Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al. */
static int check_day(char *day, size_t len)
}
/* }}} */
-/* static char *pretty_key(char *, int, int, int) */
-static char *pretty_key(char *key, int key_len, int uctitle, int xhyphen)
+/* char *pretty_key(char *, int, int, int) */
+char *pretty_key(char *key, int key_len, int uctitle, int xhyphen)
{
if (key && key_len) {
int i, wasalpha;
if ((PTR = strchr(URI, '\r')) || (PTR = strchr(URI, '\n'))) {
PTR = 0;
}
-
+
return URI;
}
/* }}} */
}
/* }}} */
-/* {{{ 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,
- 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_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)) {
- http_curl_freebuf(CURLBUF_EVRY);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
- return FAILURE;
- }
- if (info) {
- http_curl_getinfo(ch, info);
- }
- 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) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
- 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)) {
- http_curl_freebuf(CURLBUF_HDRS);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
- return FAILURE;
- }
- if (info) {
- http_curl_getinfo(ch, info);
- }
- 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);
- curl_easy_setopt(ch, CURLOPT_POSTFIELDS, postdata);
- curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, postdata_len);
-
- if (CURLE_OK != curl_easy_perform(ch)) {
- http_curl_freebuf(CURLBUF_EVRY);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
- return FAILURE;
- }
- if (info) {
- http_curl_getinfo(ch, info);
- }
- http_curl_movebuf(CURLBUF_EVRY, data, data_len);
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ STATUS http_post_array_ex(CURL *, char *, HashTable *, HashTable *, HashTable *, char **, size_t *) */
-PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray,
- HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC)
-{
- smart_str qstr = {0};
- STATUS status;
-
- HTTP_URL_ARGSEP_OVERRIDE;
- if (php_url_encode_hash_ex(postarray, &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) {
- if (qstr.c) {
- efree(qstr.c);
- }
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode post data");
- HTTP_URL_ARGSEP_RESTORE;
- return FAILURE;
- }
- smart_str_0(&qstr);
- HTTP_URL_ARGSEP_RESTORE;
-
- if (ch) {
- status = http_post_data_ex(ch, URL, qstr.c, qstr.len, options, info, data, data_len);
- } else {
- status = http_post_data(URL, qstr.c, qstr.len, options, info, data, data_len);
- }
-
- if (qstr.c) {
- efree(qstr.c);
- }
- return status;
-}
-/* }}} */
-
-/* {{{ STATUS http_post_curldata_ex(CURL *, char *, curl_httppost *, HashTable *, HashTable *, char **, size_t *) */
-PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL,
- struct curl_httppost *curldata, 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);
- curl_easy_setopt(ch, CURLOPT_HTTPPOST, curldata);
-
- if (CURLE_OK != curl_easy_perform(ch)) {
- http_curl_freebuf(CURLBUF_EVRY);
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
- return FAILURE;
- }
- if (info) {
- http_curl_getinfo(ch, info);
- }
- http_curl_movebuf(CURLBUF_EVRY, data, data_len);
- return SUCCESS;}
-/* }}} */
-
-#endif
-/* }}} HAVE_CURL */
-
/* {{{ STATUS http_auth_header(char *, char*) */
PHP_HTTP_API STATUS _http_auth_header(const char *type, const char *realm TSRMLS_DC)
{
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/
+
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PECL :: http |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, that |
+ | is bundled with this package in the file LICENSE, and is available |
+ | through the world-wide-web at http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#ifdef PHP_WIN32
+# define _WINSOCKAPI_
+# define ZEND_INCLUDE_FULL_WINDOWS_HEADERS
+# include <winsock2.h>
+# include <sys/types.h>
+#endif
+
+#include <curl/curl.h>
+#include <curl/easy.h>
+
+#include "php.h"
+#include "php_http.h"
+#include "php_http_api.h"
+#include "php_http_curl_api.h"
+
+#include "ext/standard/php_smart_str.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(http)
+
+#define http_curl_initbuf() _http_curl_initbuf_ex(0 TSRMLS_CC)
+#define http_curl_initbuf_ex(s) _http_curl_initbuf_ex((s) TSRMLS_CC)
+static inline void _http_curl_initbuf_ex(size_t chunk_size TSRMLS_DC);
+
+#define http_curl_freebuf() _http_curl_freebuf(TSRMLS_C)
+static inline void _http_curl_freebuf(TSRMLS_D);
+#define http_curl_sizebuf(l) _http_curl_sizebuf((l) TSRMLS_CC)
+static inline void _http_curl_sizebuf(size_t len TSRMLS_DC);
+#define http_curl_movebuf(d, l) _http_curl_movebuf((d), (l) TSRMLS_CC)
+static inline void _http_curl_movebuf(char **data, size_t *data_len TSRMLS_DC);
+#define http_curl_copybuf(d, l) _http_curl_copybuf((d), (l) TSRMLS_CC)
+static inline void _http_curl_copybuf(char **data, size_t *data_len TSRMLS_DC);
+#define http_curl_setopts(c, u, o) _http_curl_setopts((c), (u), (o) TSRMLS_CC)
+static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC);
+
+#define http_curl_getopt(o, k) _http_curl_getopt((o), (k) TSRMLS_CC, 0)
+#define http_curl_getopt1(o, k, t1) _http_curl_getopt((o), (k) TSRMLS_CC, 1, (t1))
+#define http_curl_getopt2(o, k, t1, t2) _http_curl_getopt((o), (k) TSRMLS_CC, 2, (t1), (t2))
+static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...);
+
+static size_t http_curl_body_callback(char *, size_t, size_t, void *);
+static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *);
+
+#define http_curl_getinfo(c, h) _http_curl_getinfo((c), (h) TSRMLS_CC)
+static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC);
+#define http_curl_getinfo_ex(c, i, a) _http_curl_getinfo_ex((c), (i), (a) TSRMLS_CC)
+static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC);
+#define http_curl_getinfoname(i) _http_curl_getinfoname((i) TSRMLS_CC)
+static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC);
+
+/* {{{ static inline void http_curl_initbuf(size_t chunk_size) */
+static inline void _http_curl_initbuf_ex(size_t chunk_size TSRMLS_DC)
+{
+ size_t size = (chunk_size > 0) ? chunk_size : HTTP_CURLBUF_SIZE;
+
+ http_curl_freebuf();
+
+ HTTP_G(curlbuf).data = emalloc(size);
+ HTTP_G(curlbuf).free = size;
+ HTTP_G(curlbuf).size = size;
+}
+/* }}} */
+
+/* {{{ static inline void http_curl_freebuf(void) */
+static inline void _http_curl_freebuf(TSRMLS_D)
+{
+ if (HTTP_G(curlbuf).data) {
+ efree(HTTP_G(curlbuf).data);
+ HTTP_G(curlbuf).data = NULL;
+ }
+ HTTP_G(curlbuf).used = 0;
+ HTTP_G(curlbuf).free = 0;
+ HTTP_G(curlbuf).size = 0;
+}
+/* }}} */
+
+/* {{{ static inline void http_curl_copybuf(char **, size_t *) */
+static inline void _http_curl_copybuf(char **data, size_t *data_len TSRMLS_DC)
+{
+ *data_len = HTTP_G(curlbuf).used;
+
+ *data = ecalloc(1, HTTP_G(curlbuf).used + 1);
+ memcpy(*data, HTTP_G(curlbuf).data, *data_len);
+}
+/* }}} */
+
+/* {{{ static inline void http_curl_movebuf(char **, size_t *) */
+static inline void _http_curl_movebuf(char **data, size_t *data_len TSRMLS_DC)
+{
+ http_curl_copybuf(data, data_len);
+ http_curl_freebuf();
+}
+/* }}} */
+
+/* {{{ static inline void http_curl_sizebuf(size_t len) */
+static inline void _http_curl_sizebuf(size_t len TSRMLS_DC)
+{
+ if (len > HTTP_G(curlbuf).free) {
+ size_t bsize = HTTP_G(curlbuf).size;
+ while (bsize < len) {
+ bsize *= 2;
+ }
+ HTTP_G(curlbuf).data = erealloc(HTTP_G(curlbuf).data, HTTP_G(curlbuf).used + bsize);
+ HTTP_G(curlbuf).free += bsize;
+ }
+}
+/* }}} */
+
+/* {{{ static size_t http_curl_body_callback(char *, size_t, size_t, void *) */
+static size_t http_curl_body_callback(char *buf, size_t len, size_t n, void *s)
+{
+ TSRMLS_FETCH();
+
+ http_curl_sizebuf(len *= n);
+
+ memcpy(HTTP_G(curlbuf).data + HTTP_G(curlbuf).used, buf, len);
+ HTTP_G(curlbuf).free -= len;
+ HTTP_G(curlbuf).used += len;
+ return len;
+}
+/* }}} */
+
+/* {{{ static size_t http_curl_hdrs_callback(char *, size_t, size_t, void *) */
+static size_t http_curl_hdrs_callback(char *buf, size_t len, size_t n, void *s)
+{
+ TSRMLS_FETCH();
+
+ /* discard previous headers */
+ if ((HTTP_G(curlbuf).used) && (!strncmp(buf, "HTTP/1.", sizeof("HTTP/1.") - 1))) {
+ http_curl_initbuf();
+ }
+ http_curl_sizebuf(len *= n);
+
+ memcpy(HTTP_G(curlbuf).data + HTTP_G(curlbuf).used, buf, len);
+ HTTP_G(curlbuf).free -= len;
+ HTTP_G(curlbuf).used += len;
+ return len;
+}
+/* }}} */
+
+/* {{{ static inline zval *http_curl_getopt(HashTable *, char *, int, ...) */
+static inline zval *_http_curl_getopt(HashTable *options, char *key TSRMLS_DC, int checks, ...)
+{
+ zval **zoption;
+ va_list types;
+ int i;
+
+ if (SUCCESS != zend_hash_find(options, key, strlen(key) + 1, (void **) &zoption)) {
+ return NULL;
+ }
+ if (checks < 1) {
+ return *zoption;
+ }
+
+ va_start(types, checks);
+ for (i = 0; i < checks; ++i) {
+ if ((va_arg(types, int)) == (Z_TYPE_PP(zoption))) {
+ va_end(types);
+ return *zoption;
+ }
+ }
+ va_end(types);
+ return NULL;
+}
+/* }}} */
+
+/* {{{ static inline void http_curl_setopts(CURL *, char *, HashTable *) */
+static inline void _http_curl_setopts(CURL *ch, const char *url, HashTable *options TSRMLS_DC)
+{
+ zval *zoption;
+
+ /* standard options */
+ curl_easy_setopt(ch, CURLOPT_URL, url);
+ curl_easy_setopt(ch, CURLOPT_HEADER, 0);
+ curl_easy_setopt(ch, CURLOPT_NOPROGRESS, 1);
+ 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) && (LIBCURL_VERSION_NUM >= 0x070a00)
+ curl_easy_setopt(ch, CURLOPT_NOSIGNAL, 1);
+#endif
+
+ if ((!options) || (1 > zend_hash_num_elements(options))) {
+ return;
+ }
+
+ /* redirects, defaults to 0 */
+ if (zoption = http_curl_getopt1(options, "redirect", IS_LONG)) {
+ curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, Z_LVAL_P(zoption) ? 1 : 0);
+ curl_easy_setopt(ch, CURLOPT_MAXREDIRS, Z_LVAL_P(zoption));
+ if (zoption = http_curl_getopt2(options, "unrestrictedauth", IS_LONG, IS_BOOL)) {
+ curl_easy_setopt(ch, CURLOPT_UNRESTRICTED_AUTH, Z_LVAL_P(zoption));
+ }
+ } else {
+ curl_easy_setopt(ch, CURLOPT_FOLLOWLOCATION, 0);
+ }
+
+ /* proxy */
+ if (zoption = http_curl_getopt1(options, "proxyhost", IS_STRING)) {
+ curl_easy_setopt(ch, CURLOPT_PROXY, Z_STRVAL_P(zoption));
+ /* port */
+ if (zoption = http_curl_getopt1(options, "proxyport", IS_LONG)) {
+ curl_easy_setopt(ch, CURLOPT_PROXYPORT, Z_LVAL_P(zoption));
+ }
+ /* user:pass */
+ if (zoption = http_curl_getopt1(options, "proxyauth", IS_STRING)) {
+ curl_easy_setopt(ch, CURLOPT_PROXYUSERPWD, Z_STRVAL_P(zoption));
+ }
+#if LIBCURL_VERSION_NUM > 0x070a06
+ /* auth method */
+ if (zoption = http_curl_getopt1(options, "proxyauthtype", IS_LONG)) {
+ curl_easy_setopt(ch, CURLOPT_PROXYAUTH, Z_LVAL_P(zoption));
+ }
+#endif
+ }
+
+ /* auth */
+ if (zoption = http_curl_getopt1(options, "httpauth", IS_STRING)) {
+ curl_easy_setopt(ch, CURLOPT_USERPWD, Z_STRVAL_P(zoption));
+ }
+#if LIBCURL_VERSION_NUM > 0x070a05
+ if (zoption = http_curl_getopt1(options, "httpauthtype", IS_LONG)) {
+ curl_easy_setopt(ch, CURLOPT_HTTPAUTH, Z_LVAL_P(zoption));
+ }
+#endif
+
+ /* compress, enabled by default (empty string enables deflate and gzip) */
+ if (zoption = http_curl_getopt2(options, "compress", IS_LONG, IS_BOOL)) {
+ if (Z_LVAL_P(zoption)) {
+ curl_easy_setopt(ch, CURLOPT_ENCODING, "");
+ }
+ } else {
+ curl_easy_setopt(ch, CURLOPT_ENCODING, "");
+ }
+
+ /* another port */
+ if (zoption = http_curl_getopt1(options, "port", IS_LONG)) {
+ curl_easy_setopt(ch, CURLOPT_PORT, Z_LVAL_P(zoption));
+ }
+
+ /* referer */
+ if (zoption = http_curl_getopt1(options, "referer", IS_STRING)) {
+ curl_easy_setopt(ch, CURLOPT_REFERER, Z_STRVAL_P(zoption));
+ }
+
+ /* useragent, default "PECL::HTTP/version (PHP/version)" */
+ if (zoption = http_curl_getopt1(options, "useragent", IS_STRING)) {
+ curl_easy_setopt(ch, CURLOPT_USERAGENT, Z_STRVAL_P(zoption));
+ } else {
+ curl_easy_setopt(ch, CURLOPT_USERAGENT,
+ "PECL::HTTP/" PHP_EXT_HTTP_VERSION " (PHP/" PHP_VERSION ")");
+ }
+
+ /* cookies, array('name' => 'value') */
+ if (zoption = http_curl_getopt1(options, "cookies", IS_ARRAY)) {
+ char *cookie_key;
+ zval **cookie_val;
+ int key_type;
+ smart_str qstr = {0};
+
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
+ while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
+ if (key_type == HASH_KEY_IS_STRING) {
+ zend_hash_get_current_key(Z_ARRVAL_P(zoption), &cookie_key, NULL, 0);
+ zend_hash_get_current_data(Z_ARRVAL_P(zoption), (void **) &cookie_val);
+ smart_str_appends(&qstr, cookie_key);
+ smart_str_appendl(&qstr, "=", 1);
+ smart_str_appendl(&qstr, Z_STRVAL_PP(cookie_val), Z_STRLEN_PP(cookie_val));
+ smart_str_appendl(&qstr, "; ", 2);
+ zend_hash_move_forward(Z_ARRVAL_P(zoption));
+ }
+ }
+ smart_str_0(&qstr);
+
+ if (qstr.c) {
+ curl_easy_setopt(ch, CURLOPT_COOKIE, qstr.c);
+ /* FIXXXME: mem-leak */
+ }
+ }
+
+ /* cookiestore */
+ if (zoption = http_curl_getopt1(options, "cookiestore", IS_STRING)) {
+ curl_easy_setopt(ch, CURLOPT_COOKIEFILE, Z_STRVAL_P(zoption));
+ curl_easy_setopt(ch, CURLOPT_COOKIEJAR, Z_STRVAL_P(zoption));
+ }
+
+ /* additional headers, array('name' => 'value') */
+ if (zoption = http_curl_getopt1(options, "headers", IS_ARRAY)) {
+ int key_type;
+ char *header_key, header[1024] = {0};
+ zval **header_val;
+ struct curl_slist *headers = NULL;
+
+ zend_hash_internal_pointer_reset(Z_ARRVAL_P(zoption));
+ while (HASH_KEY_NON_EXISTANT != (key_type = zend_hash_get_current_key_type(Z_ARRVAL_P(zoption)))) {
+ 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, 1023, "%s: %s", header_key, Z_STRVAL_PP(header_val));
+ headers = curl_slist_append(headers, header);
+ zend_hash_move_forward(Z_ARRVAL_P(zoption));
+ }
+ }
+ if (headers) {
+ curl_easy_setopt(ch, CURLOPT_HTTPHEADER, headers);
+ }
+ }
+}
+/* }}} */
+
+/* {{{ static inline char *http_curl_getinfoname(CURLINFO) */
+static inline char *_http_curl_getinfoname(CURLINFO i TSRMLS_DC)
+{
+#define CASE(I) case CURLINFO_ ##I : { static char I[] = #I; return pretty_key(I, sizeof(#I)-1, 0, 0); }
+ switch (i)
+ {
+ /* CURLINFO_EFFECTIVE_URL = CURLINFO_STRING +1, */
+ CASE(EFFECTIVE_URL);
+ /* CURLINFO_RESPONSE_CODE = CURLINFO_LONG +2, */
+#if LIBCURL_VERSION_NUM > 0x070a06
+ CASE(RESPONSE_CODE);
+#else
+ CASE(HTTP_CODE);
+#endif
+ /* CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE +3, */
+ CASE(TOTAL_TIME);
+ /* CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE +4, */
+ CASE(NAMELOOKUP_TIME);
+ /* CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE +5, */
+ CASE(CONNECT_TIME);
+ /* CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE +6, */
+ CASE(PRETRANSFER_TIME);
+ /* CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE +7, */
+ CASE(SIZE_UPLOAD);
+ /* CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE +8, */
+ CASE(SIZE_DOWNLOAD);
+ /* CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE +9, */
+ CASE(SPEED_DOWNLOAD);
+ /* CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE +10, */
+ CASE(SPEED_UPLOAD);
+ /* CURLINFO_HEADER_SIZE = CURLINFO_LONG +11, */
+ CASE(HEADER_SIZE);
+ /* CURLINFO_REQUEST_SIZE = CURLINFO_LONG +12, */
+ CASE(REQUEST_SIZE);
+ /* CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG +13, */
+ CASE(SSL_VERIFYRESULT);
+ /* CURLINFO_FILETIME = CURLINFO_LONG +14, */
+ CASE(FILETIME);
+ /* CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE +15, */
+ CASE(CONTENT_LENGTH_DOWNLOAD);
+ /* CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE +16, */
+ CASE(CONTENT_LENGTH_UPLOAD);
+ /* CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE +17, */
+ CASE(STARTTRANSFER_TIME);
+ /* CURLINFO_CONTENT_TYPE = CURLINFO_STRING +18, */
+ CASE(CONTENT_TYPE);
+ /* CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE +19, */
+ CASE(REDIRECT_TIME);
+ /* CURLINFO_REDIRECT_COUNT = CURLINFO_LONG +20, */
+ CASE(REDIRECT_COUNT);
+ /* CURLINFO_PRIVATE = CURLINFO_STRING +21, * (mike) /
+ CASE(PRIVATE);
+ /* CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG +22, */
+ CASE(HTTP_CONNECTCODE);
+#if LIBCURL_VERSION_NUM > 0x070a07
+ /* CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG +23, */
+ CASE(HTTPAUTH_AVAIL);
+ /* CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG +24, */
+ CASE(PROXYAUTH_AVAIL);
+#endif
+ }
+#undef CASE
+ return NULL;
+}
+/* }}} */
+
+/* {{{ static inline void http_curl_getinfo_ex(CURL, CURLINFO, zval *) */
+static inline void _http_curl_getinfo_ex(CURL *ch, CURLINFO i, zval *array TSRMLS_DC)
+{
+ char *key;
+ if (key = http_curl_getinfoname(i)) {
+ switch (i & ~CURLINFO_MASK)
+ {
+ case CURLINFO_STRING:
+ {
+ char *c;
+ if (CURLE_OK == curl_easy_getinfo(ch, i, &c)) {
+ add_assoc_string(array, key, c ? c : "", 1);
+ }
+ }
+ break;
+
+ case CURLINFO_DOUBLE:
+ {
+ double d;
+ if (CURLE_OK == curl_easy_getinfo(ch, i, &d)) {
+ add_assoc_double(array, key, d);
+ }
+ }
+ break;
+
+ case CURLINFO_LONG:
+ {
+ long l;
+ if (CURLE_OK == curl_easy_getinfo(ch, i, &l)) {
+ add_assoc_long(array, key, l);
+ }
+ }
+ break;
+ }
+ }
+}
+/* }}} */
+
+/* {{{ static inline http_curl_getinfo(CURL, HashTable *) */
+static inline void _http_curl_getinfo(CURL *ch, HashTable *info TSRMLS_DC)
+{
+ zval array;
+ Z_ARRVAL(array) = info;
+
+#define INFO(I) http_curl_getinfo_ex(ch, CURLINFO_ ##I , &array)
+ /* CURLINFO_EFFECTIVE_URL = CURLINFO_STRING +1, */
+ INFO(EFFECTIVE_URL);
+#if LIBCURL_VERSION_NUM > 0x070a06
+ /* CURLINFO_RESPONSE_CODE = CURLINFO_LONG +2, */
+ INFO(RESPONSE_CODE);
+#else
+ INFO(HTTP_CODE);
+#endif
+ /* CURLINFO_TOTAL_TIME = CURLINFO_DOUBLE +3, */
+ INFO(TOTAL_TIME);
+ /* CURLINFO_NAMELOOKUP_TIME = CURLINFO_DOUBLE +4, */
+ INFO(NAMELOOKUP_TIME);
+ /* CURLINFO_CONNECT_TIME = CURLINFO_DOUBLE +5, */
+ INFO(CONNECT_TIME);
+ /* CURLINFO_PRETRANSFER_TIME = CURLINFO_DOUBLE +6, */
+ INFO(PRETRANSFER_TIME);
+ /* CURLINFO_SIZE_UPLOAD = CURLINFO_DOUBLE +7, */
+ INFO(SIZE_UPLOAD);
+ /* CURLINFO_SIZE_DOWNLOAD = CURLINFO_DOUBLE +8, */
+ INFO(SIZE_DOWNLOAD);
+ /* CURLINFO_SPEED_DOWNLOAD = CURLINFO_DOUBLE +9, */
+ INFO(SPEED_DOWNLOAD);
+ /* CURLINFO_SPEED_UPLOAD = CURLINFO_DOUBLE +10, */
+ INFO(SPEED_UPLOAD);
+ /* CURLINFO_HEADER_SIZE = CURLINFO_LONG +11, */
+ INFO(HEADER_SIZE);
+ /* CURLINFO_REQUEST_SIZE = CURLINFO_LONG +12, */
+ INFO(REQUEST_SIZE);
+ /* CURLINFO_SSL_VERIFYRESULT = CURLINFO_LONG +13, */
+ INFO(SSL_VERIFYRESULT);
+ /* CURLINFO_FILETIME = CURLINFO_LONG +14, */
+ INFO(FILETIME);
+ /* CURLINFO_CONTENT_LENGTH_DOWNLOAD = CURLINFO_DOUBLE +15, */
+ INFO(CONTENT_LENGTH_DOWNLOAD);
+ /* CURLINFO_CONTENT_LENGTH_UPLOAD = CURLINFO_DOUBLE +16, */
+ INFO(CONTENT_LENGTH_UPLOAD);
+ /* CURLINFO_STARTTRANSFER_TIME = CURLINFO_DOUBLE +17, */
+ INFO(STARTTRANSFER_TIME);
+ /* CURLINFO_CONTENT_TYPE = CURLINFO_STRING +18, */
+ INFO(CONTENT_TYPE);
+ /* CURLINFO_REDIRECT_TIME = CURLINFO_DOUBLE +19, */
+ INFO(REDIRECT_TIME);
+ /* CURLINFO_REDIRECT_COUNT = CURLINFO_LONG +20, */
+ INFO(REDIRECT_COUNT);
+ /* CURLINFO_PRIVATE = CURLINFO_STRING +21, */
+ INFO(PRIVATE);
+ /* CURLINFO_HTTP_CONNECTCODE = CURLINFO_LONG +22, */
+ INFO(HTTP_CONNECTCODE);
+#if LIBCURL_VERSION_NUM > 0x070a07
+ /* CURLINFO_HTTPAUTH_AVAIL = CURLINFO_LONG +23, */
+ INFO(HTTPAUTH_AVAIL);
+ /* CURLINFO_PROXYAUTH_AVAIL = CURLINFO_LONG +24, */
+ INFO(PROXYAUTH_AVAIL);
+#endif
+#undef INFO
+}
+/* }}} */
+
+
+
+/* {{{ STATUS http_get(char *, HashTable *, HashTable *, char **, size_t *) */
+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) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
+ 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();
+ 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)) {
+ http_curl_freebuf();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
+ return FAILURE;
+ }
+ if (info) {
+ http_curl_getinfo(ch, info);
+ }
+ http_curl_movebuf(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) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initialize curl");
+ 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();
+ 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)) {
+ http_curl_freebuf();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
+ return FAILURE;
+ }
+ if (info) {
+ http_curl_getinfo(ch, info);
+ }
+ http_curl_movebuf(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();
+ http_curl_setopts(ch, URL, options);
+ curl_easy_setopt(ch, CURLOPT_POST, 1);
+ curl_easy_setopt(ch, CURLOPT_POSTFIELDS, postdata);
+ curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, postdata_len);
+
+ if (CURLE_OK != curl_easy_perform(ch)) {
+ http_curl_freebuf();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
+ return FAILURE;
+ }
+ if (info) {
+ http_curl_getinfo(ch, info);
+ }
+ http_curl_movebuf(data, data_len);
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ STATUS http_post_array_ex(CURL *, char *, HashTable *, HashTable *, HashTable *, char **, size_t *) */
+PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray,
+ HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC)
+{
+ smart_str qstr = {0};
+ STATUS status;
+
+ HTTP_URL_ARGSEP_OVERRIDE;
+ if (php_url_encode_hash_ex(postarray, &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) {
+ if (qstr.c) {
+ efree(qstr.c);
+ }
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode post data");
+ HTTP_URL_ARGSEP_RESTORE;
+ return FAILURE;
+ }
+ smart_str_0(&qstr);
+ HTTP_URL_ARGSEP_RESTORE;
+
+ if (ch) {
+ status = http_post_data_ex(ch, URL, qstr.c, qstr.len, options, info, data, data_len);
+ } else {
+ status = http_post_data(URL, qstr.c, qstr.len, options, info, data, data_len);
+ }
+
+ if (qstr.c) {
+ efree(qstr.c);
+ }
+ return status;
+}
+/* }}} */
+
+/* {{{ STATUS http_post_curldata_ex(CURL *, char *, curl_httppost *, HashTable *, HashTable *, char **, size_t *) */
+PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL,
+ struct curl_httppost *curldata, HashTable *options, HashTable *info,
+ char **data, size_t *data_len TSRMLS_DC)
+{
+ http_curl_initbuf();
+ http_curl_setopts(ch, URL, options);
+ curl_easy_setopt(ch, CURLOPT_POST, 1);
+ curl_easy_setopt(ch, CURLOPT_HTTPPOST, curldata);
+
+ if (CURLE_OK != curl_easy_perform(ch)) {
+ http_curl_freebuf();
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not perform request");
+ return FAILURE;
+ }
+ if (info) {
+ http_curl_getinfo(ch, info);
+ }
+ http_curl_movebuf(data, data_len);
+ return SUCCESS;}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PECL :: http |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, that |
+ | is bundled with this package in the file LICENSE, and is available |
+ | through the world-wide-web at http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "snprintf.h"
+#include "ext/standard/info.h"
+#include "ext/session/php_session.h"
+#include "ext/standard/php_string.h"
+#include "ext/standard/php_smart_str.h"
+
+#include "SAPI.h"
+
+#include "php_http.h"
+#include "php_http_api.h"
+#include "php_http_curl_api.h"
+
+ZEND_DECLARE_MODULE_GLOBALS(http)
+
+/* {{{ proto string http_date([int timestamp])
+ *
+ * This function returns a valid HTTP date regarding RFC 822/1123
+ * looking like: "Wed, 22 Dec 2004 11:34:47 GMT"
+ *
+ */
+PHP_FUNCTION(http_date)
+{
+ long t = -1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (t == -1) {
+ t = (long) time(NULL);
+ }
+
+ RETURN_STRING(http_date(t), 0);
+}
+/* }}} */
+
+/* {{{ proto string http_absolute_uri(string url[, string proto])
+ *
+ * This function returns an absolute URI constructed from url.
+ * 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.
+ *
+ * Some examples:
+ * <pre>
+ * url = "page.php" => http://www.example.com/current/path/page.php
+ * url = "/page.php" => http://www.example.com/page.php
+ * url = "/page.php", proto = "https" => https://www.example.com/page.php
+ * </pre>
+ *
+ */
+PHP_FUNCTION(http_absolute_uri)
+{
+ char *url = NULL, *proto = NULL;
+ int url_len = 0, proto_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &url, &url_len, &proto, &proto_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ RETURN_STRING(http_absolute_uri(url, proto), 0);
+}
+/* }}} */
+
+/* {{{ proto string http_negotiate_language(array supported[, string default = 'en-US'])
+ *
+ * This function negotiates the clients preferred language based on its
+ * Accept-Language HTTP header. It returns the negotiated language or
+ * the default language if none match.
+ *
+ * The qualifier is recognized and languages without qualifier are rated highest.
+ *
+ * The supported parameter is expected to be an array having
+ * the supported languages as array values.
+ *
+ * Example:
+ * <pre>
+ * <?php
+ * $langs = array(
+ * 'en-US',// default
+ * 'fr',
+ * 'fr-FR',
+ * 'de',
+ * 'de-DE',
+ * 'de-AT',
+ * 'de-CH',
+ * );
+ * include './langs/'. http_negotiate_language($langs) .'.php';
+ * ?>
+ * </pre>
+ *
+ */
+PHP_FUNCTION(http_negotiate_language)
+{
+ zval *supported;
+ char *def = NULL;
+ int def_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &supported, &def, &def_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (!def) {
+ def = "en-US";
+ }
+
+ RETURN_STRING(http_negotiate_language(supported, def), 0);
+}
+/* }}} */
+
+/* {{{ proto string http_negotiate_charset(array supported[, string default = 'iso-8859-1'])
+ *
+ * This function negotiates the clients preferred charset based on its
+ * Accept-Charset HTTP header. It returns the negotiated charset or
+ * the default charset if none match.
+ *
+ * The qualifier is recognized and charset without qualifier are rated highest.
+ *
+ * The supported parameter is expected to be an array having
+ * the supported charsets as array values.
+ *
+ * Example:
+ * <pre>
+ * <?php
+ * $charsets = array(
+ * 'iso-8859-1', // default
+ * 'iso-8859-2',
+ * 'iso-8859-15',
+ * 'utf-8'
+ * );
+ * $pref = http_negotiate_charset($charsets);
+ * if (!strcmp($pref, 'iso-8859-1')) {
+ * iconv_set_encoding('internal_encoding', 'iso-8859-1');
+ * iconv_set_encoding('output_encoding', $pref);
+ * ob_start('ob_iconv_handler');
+ * }
+ * ?>
+ * </pre>
+ */
+PHP_FUNCTION(http_negotiate_charset)
+{
+ zval *supported;
+ char *def = NULL;
+ int def_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|s", &supported, &def, &def_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (!def) {
+ def = "iso-8859-1";
+ }
+
+ RETURN_STRING(http_negotiate_charset(supported, def), 0);
+}
+/* }}} */
+
+/* {{{ proto bool http_send_status(int status)
+ *
+ * Send HTTP status code.
+ *
+ */
+PHP_FUNCTION(http_send_status)
+{
+ int status = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &status) != SUCCESS) {
+ RETURN_FALSE;
+ }
+ if (status < 100 || status > 510) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid HTTP status code (100-510): %d", status);
+ RETURN_FALSE;
+ }
+
+ RETURN_SUCCESS(http_send_status(status));
+}
+/* }}} */
+
+/* {{{ proto bool http_send_last_modified([int timestamp])
+ *
+ * This converts the given timestamp to a valid HTTP date and
+ * sends it as "Last-Modified" HTTP header. If timestamp is
+ * omitted, current time is sent.
+ *
+ */
+PHP_FUNCTION(http_send_last_modified)
+{
+ long t = -1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (t == -1) {
+ t = (long) time(NULL);
+ }
+
+ RETURN_SUCCESS(http_send_last_modified(t));
+}
+/* }}} */
+
+/* {{{ proto bool http_send_content_type([string content_type = 'application/x-octetstream'])
+ *
+ * Sets the content type.
+ *
+ */
+PHP_FUNCTION(http_send_content_type)
+{
+ char *ct;
+ int ct_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &ct, &ct_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (!ct_len) {
+ RETURN_SUCCESS(http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1));
+ }
+ RETURN_SUCCESS(http_send_content_type(ct, ct_len));
+}
+/* }}} */
+
+/* {{{ proto bool http_send_content_disposition(string filename[, bool inline = false])
+ *
+ * Set the Content Disposition. The Content-Disposition header is very useful
+ * if the data actually sent came from a file or something similar, that should
+ * be "saved" by the client/user (i.e. by browsers "Save as..." popup window).
+ *
+ */
+PHP_FUNCTION(http_send_content_disposition)
+{
+ char *filename;
+ int f_len;
+ zend_bool send_inline = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &filename, &f_len, &send_inline) != SUCCESS) {
+ RETURN_FALSE;
+ }
+ RETURN_SUCCESS(http_send_content_disposition(filename, f_len, send_inline));
+}
+/* }}} */
+
+/* {{{ proto bool http_match_modified([int timestamp])
+ *
+ * Matches the given timestamp against the clients "If-Modified-Since" resp.
+ * "If-Unmodified-Since" HTTP headers.
+ *
+ */
+PHP_FUNCTION(http_match_modified)
+{
+ long t = -1;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &t) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ // current time if not supplied (senseless though)
+ if (t == -1) {
+ t = (long) time(NULL);
+ }
+
+ RETURN_BOOL(http_modified_match("HTTP_IF_MODIFIED_SINCE", t) || http_modified_match("HTTP_IF_UNMODIFIED_SINCE", t));
+}
+/* }}} */
+
+/* {{{ proto bool http_match_etag(string etag)
+ *
+ * This matches the given ETag against the clients
+ * "If-Match" resp. "If-None-Match" HTTP headers.
+ *
+ */
+PHP_FUNCTION(http_match_etag)
+{
+ int etag_len;
+ char *etag;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ RETURN_BOOL(http_etag_match("HTTP_IF_NONE_MATCH", etag) || http_etag_match("HTTP_IF_MATCH", etag));
+}
+/* }}} */
+
+/* {{{ proto bool http_cache_last_modified([int timestamp_or_expires]])
+ *
+ * If timestamp_or_exires is greater than 0, it is handled as timestamp
+ * and will be sent as date of last modification. If it is 0 or omitted,
+ * the current time will be sent as Last-Modified date. If it's negative,
+ * it is handled as expiration time in seconds, which means that if the
+ * requested last modification date is not between the calculated timespan,
+ * the Last-Modified header is updated and the actual body will be sent.
+ *
+ */
+PHP_FUNCTION(http_cache_last_modified)
+{
+ long last_modified = 0, send_modified = 0, t;
+ zval *zlm;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &last_modified) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ t = (long) time(NULL);
+
+ /* 0 or omitted */
+ if (!last_modified) {
+ /* does the client have? (att: caching "forever") */
+ if (zlm = http_get_server_var("HTTP_IF_MODIFIED_SINCE")) {
+ last_modified = send_modified = http_parse_date(Z_STRVAL_P(zlm));
+ /* send current time */
+ } else {
+ send_modified = t;
+ }
+ /* negative value is supposed to be expiration time */
+ } else if (last_modified < 0) {
+ last_modified += t;
+ send_modified = t;
+ /* send supplied time explicitly */
+ } else {
+ send_modified = last_modified;
+ }
+
+ RETURN_SUCCESS(http_cache_last_modified(last_modified, send_modified, HTTP_DEFAULT_CACHECONTROL, sizeof(HTTP_DEFAULT_CACHECONTROL) - 1));
+}
+/* }}} */
+
+/* {{{ proto bool http_cache_etag([string etag])
+ *
+ * This function attempts to cache the HTTP body based on an ETag,
+ * either supplied or generated through calculation of the MD5
+ * checksum of the output (uses output buffering).
+ *
+ * If clients "If-None-Match" header matches the supplied/calculated
+ * ETag, the body is considered cached on the clients side and
+ * a "304 Not Modified" status code is issued.
+ *
+ */
+PHP_FUNCTION(http_cache_etag)
+{
+ char *etag;
+ int etag_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &etag, &etag_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ RETURN_SUCCESS(http_cache_etag(etag, etag_len, HTTP_DEFAULT_CACHECONTROL, sizeof(HTTP_DEFAULT_CACHECONTROL) - 1));
+}
+/* }}} */
+
+/* {{{ proto string ob_httpetaghandler(string data, int mode)
+ *
+ * For use with ob_start().
+ * Note that this has to be started as first output buffer.
+ * WARNING: Don't use with http_send_*().
+ */
+PHP_FUNCTION(ob_httpetaghandler)
+{
+ char *data;
+ int data_len;
+ long mode;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &data, &data_len, &mode)) {
+ RETURN_FALSE;
+ }
+
+ if (mode & PHP_OUTPUT_HANDLER_START) {
+ if (HTTP_G(etag_started)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_httpetaghandler can only be used once");
+ RETURN_STRINGL(data, data_len, 1);
+ }
+ http_send_header("Cache-Control: " HTTP_DEFAULT_CACHECONTROL);
+ HTTP_G(etag_started) = 1;
+ }
+
+ if (OG(ob_nesting_level) > 1) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "ob_httpetaghandler must be started prior to other output buffers");
+ RETURN_STRINGL(data, data_len, 1);
+ }
+
+ Z_TYPE_P(return_value) = IS_STRING;
+ http_ob_etaghandler(data, data_len, &Z_STRVAL_P(return_value), &Z_STRLEN_P(return_value), mode);
+}
+/* }}} */
+
+/* {{{ proto void http_redirect([string url[, array params[, bool session,[ bool permanent]]]])
+ *
+ * Redirect to a given url.
+ * The supplied url will be expanded with http_absolute_uri(), the params array will
+ * be treated with http_build_query() and the session identification will be appended
+ * if session is true.
+ *
+ * Depending on permanent the redirection will be issued with a permanent
+ * ("301 Moved Permanently") or a temporary ("302 Found") redirection
+ * status code.
+ *
+ * To be RFC compliant, "Redirecting to <a>URI</a>." will be displayed,
+ * if the client doesn't redirect immediatly.
+ */
+PHP_FUNCTION(http_redirect)
+{
+ int url_len;
+ zend_bool session = 0, permanent = 0;
+ zval *params = NULL;
+ smart_str qstr = {0};
+ char *url, *URI, LOC[HTTP_URI_MAXLEN + 9], RED[HTTP_URI_MAXLEN * 2 + 34];
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sa!/bb", &url, &url_len, ¶ms, &session, &permanent) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ /* append session info */
+ if (session && (PS(session_status) == php_session_active)) {
+ if (!params) {
+ MAKE_STD_ZVAL(params);
+ array_init(params);
+ }
+ if (add_assoc_string(params, PS(session_name), PS(id), 1) != SUCCESS) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not append session information");
+ }
+ }
+
+ /* treat params array with http_build_query() */
+ if (params) {
+ if (php_url_encode_hash_ex(Z_ARRVAL_P(params), &qstr, NULL,0,NULL,0,NULL,0,NULL TSRMLS_CC) != SUCCESS) {
+ if (qstr.c) {
+ efree(qstr.c);
+ }
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not encode query parameters");
+ RETURN_FALSE;
+ }
+ smart_str_0(&qstr);
+ }
+
+ URI = http_absolute_uri(url, NULL);
+ if (qstr.c) {
+ snprintf(LOC, HTTP_URI_MAXLEN + strlen("Location: "), "Location: %s?%s", URI, qstr.c);
+ sprintf(RED, "Redirecting to <a href=\"%s?%s\">%s?%s</a>.\n", URI, qstr.c, URI, qstr.c);
+ efree(qstr.c);
+ } else {
+ snprintf(LOC, HTTP_URI_MAXLEN + strlen("Location: "), "Location: %s", URI);
+ sprintf(RED, "Redirecting to <a href=\"%s\">%s</a>.\n", URI, URI);
+ }
+ efree(URI);
+
+ if ((SUCCESS == http_send_header(LOC)) && (SUCCESS == http_send_status((permanent ? 301 : 302)))) {
+ php_body_write(RED, strlen(RED) TSRMLS_CC);
+ RETURN_TRUE;
+ }
+ RETURN_FALSE;
+}
+/* }}} */
+
+/* {{{ proto bool http_send_data(string data)
+ *
+ * Sends raw data with support for (multiple) range requests.
+ *
+ */
+PHP_FUNCTION(http_send_data)
+{
+ zval *zdata;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zdata) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ convert_to_string_ex(&zdata);
+ http_send_header("Accept-Ranges: bytes");
+ RETURN_SUCCESS(http_send_data(zdata));
+}
+/* }}} */
+
+/* {{{ proto bool http_send_file(string file)
+ *
+ * Sends a file with support for (multiple) range requests.
+ *
+ */
+PHP_FUNCTION(http_send_file)
+{
+ zval *zfile;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zfile) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ convert_to_string_ex(&zfile);
+ http_send_header("Accept-Ranges: bytes");
+ RETURN_SUCCESS(http_send_file(zfile));
+}
+/* }}} */
+
+/* {{{ proto bool http_send_stream(resource stream)
+ *
+ * Sends an already opened stream with support for (multiple) range requests.
+ *
+ */
+PHP_FUNCTION(http_send_stream)
+{
+ zval *zstream;
+ php_stream *file;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zstream) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ php_stream_from_zval(file, &zstream);
+ http_send_header("Accept-Ranges: bytes");
+ RETURN_SUCCESS(http_send_stream(file));
+}
+/* }}} */
+
+/* {{{ proto string http_chunked_decode(string encoded)
+ *
+ * This function decodes a string that was HTTP-chunked encoded.
+ * Returns false on failure.
+ */
+PHP_FUNCTION(http_chunked_decode)
+{
+ char *encoded = NULL, *decoded = NULL;
+ int encoded_len = 0, decoded_len = 0;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &encoded, &encoded_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (SUCCESS == http_chunked_decode(encoded, encoded_len, &decoded, &decoded_len)) {
+ RETURN_STRINGL(decoded, decoded_len, 0);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto array http_split_response(string http_response)
+ *
+ * This function splits an HTTP response into an array with headers and the
+ * content body. The returned array may look simliar to the following example:
+ *
+ * <pre>
+ * <?php
+ * array(
+ * 0 => array(
+ * 'Status' => '200 Ok',
+ * 'Content-Type' => 'text/plain',
+ * 'Content-Language' => 'en-US'
+ * ),
+ * 1 => "Hello World!"
+ * );
+ * ?>
+ * </pre>
+ */
+PHP_FUNCTION(http_split_response)
+{
+ zval *zresponse, *zbody, *zheaders;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zresponse) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ convert_to_string_ex(&zresponse);
+
+ MAKE_STD_ZVAL(zbody);
+ MAKE_STD_ZVAL(zheaders);
+ array_init(zheaders);
+
+ if (SUCCESS != http_split_response(zresponse, zheaders, zbody)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP response");
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ add_index_zval(return_value, 0, zheaders);
+ add_index_zval(return_value, 1, zbody);
+}
+/* }}} */
+
+/* {{{ proto array http_parse_headers(string header)
+ *
+ */
+PHP_FUNCTION(http_parse_headers)
+{
+ char *header, *rnrn;
+ int header_len;
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &header, &header_len)) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+
+ if (rnrn = strstr(header, HTTP_CRLF HTTP_CRLF)) {
+ header_len = rnrn - header + 2;
+ }
+ if (SUCCESS != http_parse_headers(header, header_len, return_value)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not parse HTTP header");
+ zval_dtor(return_value);
+ RETURN_FALSE;
+ }
+}
+/* }}}*/
+
+/* {{{ proto array http_get_request_headers(void)
+ *
+ */
+PHP_FUNCTION(http_get_request_headers)
+{
+ if (ZEND_NUM_ARGS()) {
+ WRONG_PARAM_COUNT;
+ }
+
+ array_init(return_value);
+ http_get_request_headers(return_value);
+}
+/* }}} */
+
+/* {{{ HAVE_CURL */
+#ifdef HTTP_HAVE_CURL
+
+/* {{{ proto string http_get(string url[, array options[, array &info]])
+ *
+ * Performs an HTTP GET request on the supplied url.
+ *
+ * The second parameter is expected to be an associative
+ * array where the following keys will be recognized:
+ * <pre>
+ * - redirect: int, whether and how many redirects to follow
+ * - unrestrictedauth: bool, whether to continue sending credentials on
+ * redirects to a different host
+ * - proxyhost: string, proxy host in "host[:port]" format
+ * - proxyport: int, use another proxy port as specified in proxyhost
+ * - proxyauth: string, proxy credentials in "user:pass" format
+ * - proxyauthtype: int, HTTP_AUTH_BASIC and/or HTTP_AUTH_NTLM
+ * - httpauth: string, http credentials in "user:pass" format
+ * - httpauthtype: int, HTTP_AUTH_BASIC, DIGEST and/or NTLM
+ * - compress: bool, whether to allow gzip/deflate content encoding
+ * (defaults to true)
+ * - port: int, use another port as specified in the url
+ * - referer: string, the referer to sends
+ * - useragent: string, the user agent to send
+ * (defaults to PECL::HTTP/version (PHP/version)))
+ * - headers: array, list of custom headers as associative array
+ * like array("header" => "value")
+ * - cookies: array, list of cookies as associative array
+ * like array("cookie" => "value")
+ * - cookiestore: string, path to a file where cookies are/will be stored
+ * </pre>
+ *
+ * The optional third parameter will be filled with some additional information
+ * in form af an associative array, if supplied, like the following example:
+ * <pre>
+ * <?php
+ * array (
+ * 'effective_url' => 'http://localhost',
+ * 'response_code' => 403,
+ * 'total_time' => 0.017,
+ * 'namelookup_time' => 0.013,
+ * 'connect_time' => 0.014,
+ * 'pretransfer_time' => 0.014,
+ * 'size_upload' => 0,
+ * 'size_download' => 202,
+ * 'speed_download' => 11882,
+ * 'speed_upload' => 0,
+ * 'header_size' => 145,
+ * 'request_size' => 62,
+ * 'ssl_verifyresult' => 0,
+ * 'filetime' => -1,
+ * 'content_length_download' => 202,
+ * 'content_length_upload' => 0,
+ * 'starttransfer_time' => 0.017,
+ * 'content_type' => 'text/html; charset=iso-8859-1',
+ * 'redirect_time' => 0,
+ * 'redirect_count' => 0,
+ * 'private' => '',
+ * 'http_connectcode' => 0,
+ * 'httpauth_avail' => 0,
+ * 'proxyauth_avail' => 0,
+ * )
+ * ?>
+ * </pre>
+ */
+PHP_FUNCTION(http_get)
+{
+ char *URL, *data = NULL;
+ size_t data_len = 0;
+ int URL_len;
+ zval *options = NULL, *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (info) {
+ zval_dtor(info);
+ array_init(info);
+ }
+
+ if (SUCCESS == http_get(URL, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
+ RETURN_STRINGL(data, data_len, 0);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string http_head(string url[, array options[, array &info]])
+ *
+ * Performs an HTTP HEAD request on the suppied url.
+ * Returns the HTTP response as string.
+ * See http_get() for a full list of available options.
+ */
+PHP_FUNCTION(http_head)
+{
+ char *URL, *data = NULL;
+ size_t data_len = 0;
+ int URL_len;
+ zval *options = NULL, *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a/!z", &URL, &URL_len, &options, &info) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (info) {
+ zval_dtor(info);
+ array_init(info);
+ }
+
+ if (SUCCESS == http_head(URL, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
+ RETURN_STRINGL(data, data_len, 0);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string http_post_data(string url, string data[, array options[, &info]])
+ *
+ * Performs an HTTP POST request, posting data.
+ * Returns the HTTP response as string.
+ * See http_get() for a full list of available options.
+ */
+PHP_FUNCTION(http_post_data)
+{
+ char *URL, *postdata, *data = NULL;
+ size_t data_len = 0;
+ int postdata_len, URL_len;
+ zval *options = NULL, *info = NULL;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|a/!z", &URL, &URL_len, &postdata, &postdata_len, &options, &info) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (info) {
+ zval_dtor(info);
+ array_init(info);
+ }
+
+ if (SUCCESS == http_post_data(URL, postdata, (size_t) postdata_len, HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
+ RETURN_STRINGL(data, data_len, 0);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+/* {{{ proto string http_post_array(string url, array data[, array options[, array &info]])
+ *
+ * Performs an HTTP POST request, posting www-form-urlencoded array data.
+ * Returns the HTTP response as string.
+ * See http_get() for a full list of available options.
+ */
+PHP_FUNCTION(http_post_array)
+{
+ char *URL, *data = NULL;
+ size_t data_len = 0;
+ int URL_len;
+ zval *options = NULL, *info = NULL, *postdata;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|a/!z", &URL, &URL_len, &postdata, &options, &info) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (info) {
+ zval_dtor(info);
+ array_init(info);
+ }
+
+ if (SUCCESS == http_post_array(URL, Z_ARRVAL_P(postdata), HASH_ORNULL(options), HASH_ORNULL(info), &data, &data_len)) {
+ RETURN_STRINGL(data, data_len, 0);
+ } else {
+ RETURN_FALSE;
+ }
+}
+/* }}} */
+
+#endif
+/* }}} HAVE_CURL */
+
+
+/* {{{ proto bool http_auth_basic(string user, string pass[, string realm = "Restricted"])
+ *
+ * Example:
+ * <pre>
+ * <?php
+ * if (!http_auth_basic('mike', 's3c|r3t')) {
+ * die('<h1>Authorization failed!</h1>');
+ * }
+ * ?>
+ * </pre>
+ */
+PHP_FUNCTION(http_auth_basic)
+{
+ char *realm = NULL, *user, *pass, *suser, *spass;
+ int r_len, u_len, p_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &user, &u_len, &pass, &p_len, &realm, &r_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (!realm) {
+ realm = "Restricted";
+ }
+
+ if (SUCCESS != http_auth_credentials(&suser, &spass)) {
+ http_auth_header("Basic", realm);
+ RETURN_FALSE;
+ }
+
+ if (strcasecmp(suser, user)) {
+ http_auth_header("Basic", realm);
+ RETURN_FALSE;
+ }
+
+ if (strcmp(spass, pass)) {
+ http_auth_header("Basic", realm);
+ RETURN_FALSE;
+ }
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool http_auth_basic_cb(mixed callback[, string realm = "Restricted"])
+ *
+ * Example:
+ * <pre>
+ * <?php
+ * function auth_cb($user, $pass)
+ * {
+ * global $db;
+ * $query = 'SELECT pass FROM users WHERE user='. $db->quoteSmart($user);
+ * if (strlen($realpass = $db->getOne($query)) {
+ * return $pass === $realpass;
+ * }
+ * return false;
+ * }
+ *
+ * if (!http_auth_basic_cb('auth_cb')) {
+ * die('<h1>Authorization failed</h1>');
+ * }
+ * ?>
+ * </pre>
+ */
+PHP_FUNCTION(http_auth_basic_cb)
+{
+ zval *cb;
+ char *realm = NULL, *user, *pass;
+ int r_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &cb, &realm, &r_len) != SUCCESS) {
+ RETURN_FALSE;
+ }
+
+ if (!realm) {
+ realm = "Restricted";
+ }
+
+ if (SUCCESS != http_auth_credentials(&user, &pass)) {
+ http_auth_header("Basic", realm);
+ RETURN_FALSE;
+ }
+ {
+ zval *zparams[2] = {NULL, NULL}, retval;
+ int result = 0;
+
+ MAKE_STD_ZVAL(zparams[0]);
+ MAKE_STD_ZVAL(zparams[1]);
+ ZVAL_STRING(zparams[0], user, 0);
+ ZVAL_STRING(zparams[1], pass, 0);
+
+ if (SUCCESS == call_user_function(EG(function_table), NULL, cb,
+ &retval, 2, zparams TSRMLS_CC)) {
+ result = Z_LVAL(retval);
+ }
+
+ efree(user);
+ efree(pass);
+ efree(zparams[0]);
+ efree(zparams[1]);
+
+ if (!result) {
+ http_auth_header("Basic", realm);
+ }
+
+ RETURN_BOOL(result);
+ }
+}
+/* }}}*/
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PECL :: http |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, that |
+ | is bundled with this package in the file LICENSE, and is available |
+ | through the world-wide-web at http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "php.h"
+#include "php_http.h"
+#include "php_http_api.h"
+#include "php_http_curl_api.h"
+#include "ext/standard/php_smart_str.h"
+
+#ifdef ZEND_ENGINE_2
+
+/* {{{ HTTPi_Response */
+
+/* {{{ proto void HTTPi_Response::__construct(bool cache, bool gzip)
+ *
+ */
+PHP_METHOD(HTTPi_Response, __construct)
+{
+ zend_bool do_cache = 0, do_gzip = 0;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &do_cache, &do_gzip)) {
+ // throw exception
+ return;
+ }
+
+ UPD_PROP(obj, long, cache, do_cache);
+ UPD_PROP(obj, long, gzip, do_gzip);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setCache(bool cache)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setCache)
+{
+ zend_bool do_cache = 0;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_cache)) {
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, long, cache, do_cache);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::getCache()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getCache)
+{
+ zval *do_cache = NULL;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ do_cache = GET_PROP(obj, cache);
+ RETURN_BOOL(Z_LVAL_P(do_cache));
+}
+/* }}}*/
+
+/* {{{ proto bool HTTPi_Response::setGzip(bool gzip)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setGzip)
+{
+ zend_bool do_gzip = 0;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &do_gzip)) {
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, long, gzip, do_gzip);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::getGzip()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getGzip)
+{
+ zval *do_gzip = NULL;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ do_gzip = GET_PROP(obj, gzip);
+ RETURN_BOOL(Z_LVAL_P(do_gzip));
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setCacheControl(string control[, bool raw = false])
+ *
+ */
+PHP_METHOD(HTTPi_Response, setCacheControl)
+{
+ char *ccontrol;
+ int cc_len;
+ zend_bool raw = 0;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &ccontrol, &cc_len, &raw)) {
+ RETURN_FALSE;
+ }
+
+ if ((!raw) && (strcmp(ccontrol, "public") && strcmp(ccontrol, "private") && strcmp(ccontrol, "no-cache"))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cache-Control '%s' doesn't match public, private or no-cache", ccontrol);
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, long, raw_cache_header, raw);
+ UPD_PROP(obj, string, cacheControl, ccontrol);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Response::getCacheControl()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getCacheControl)
+{
+ zval *ccontrol;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ ccontrol = GET_PROP(obj, cacheControl);
+ RETURN_STRINGL(Z_STRVAL_P(ccontrol), Z_STRLEN_P(ccontrol), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi::setContentType(string content_type)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setContentType)
+{
+ char *ctype;
+ int ctype_len;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ctype_len)) {
+ RETURN_FALSE;
+ }
+
+ if (!strchr(ctype, '/')) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Content type '%s' doesn't seem to contain a primary and a secondary part", ctype);
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, string, contentType, ctype);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Response::getContentType()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getContentType)
+{
+ zval *ctype;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ ctype = GET_PROP(obj, contentType);
+ RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setContentDisposition(string filename[, bool inline = false])
+ *
+ */
+PHP_METHOD(HTTPi_Response, setContentDisposition)
+{
+ char *file;
+ int file_len;
+ zend_bool is_inline = 0;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &file, &file_len, &is_inline)) {
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, string, dispoFile, file);
+ UPD_PROP(obj, long, dispoInline, is_inline);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array HTTPi_Response::getContentDisposition()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getContentDisposition)
+{
+ zval *file;
+ zval *is_inline;
+ getObject(httpi_response_object, obj);
+
+ if (ZEND_NUM_ARGS()) {
+ WRONG_PARAM_COUNT;
+ }
+
+ file = GET_PROP(obj, dispoFile);
+ is_inline = GET_PROP(obj, dispoInline);
+
+ array_init(return_value);
+ add_assoc_stringl(return_value, "filename", Z_STRVAL_P(file), Z_STRLEN_P(file), 1);
+ add_assoc_bool(return_value, "inline", Z_LVAL_P(is_inline));
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setETag(string etag)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setETag)
+{
+ char *etag;
+ int etag_len;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &etag, &etag_len)) {
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, string, eTag, etag);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Response::getETag()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getETag)
+{
+ zval *etag;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ etag = GET_PROP(obj, eTag);
+ RETURN_STRINGL(Z_STRVAL_P(etag), Z_STRLEN_P(etag), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setData(string data)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setData)
+{
+ zval *the_data;
+ char *etag;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_data)) {
+ RETURN_FALSE;
+ }
+
+ convert_to_string_ex(&the_data);
+ SET_PROP(obj, data, the_data);
+ UPD_PROP(obj, long, lastModified, http_lmod(the_data, SEND_DATA));
+ UPD_PROP(obj, long, send_mode, SEND_DATA);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Response::getData()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getData)
+{
+ zval *the_data;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ the_data = GET_PROP(obj, data);
+ RETURN_STRINGL(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setStream(resource stream)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setStream)
+{
+ zval *the_stream;
+ php_stream *the_real_stream;
+ char *etag;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &the_stream)) {
+ RETURN_FALSE;
+ }
+
+ php_stream_from_zval(the_real_stream, &the_stream);
+
+ SET_PROP(obj, stream, the_stream);
+ UPD_PROP(obj, long, lastModified, http_lmod(the_real_stream, SEND_RSRC));
+ UPD_PROP(obj, long, send_mode, SEND_RSRC);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto resource HTTPi_Response::getStream()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getStream)
+{
+ zval *the_stream;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ the_stream = GET_PROP(obj, stream);
+ RETURN_RESOURCE(Z_LVAL_P(the_stream));
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Response::setFile(string file)
+ *
+ */
+PHP_METHOD(HTTPi_Response, setFile)
+{
+ zval *the_file;
+ getObject(httpi_response_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &the_file)) {
+ RETURN_FALSE;
+ }
+
+ convert_to_string_ex(&the_file);
+
+ UPD_PROP(obj, string, file, Z_STRVAL_P(the_file));
+ UPD_PROP(obj, long, lastModified, http_lmod(the_file, -1));
+ UPD_PROP(obj, long, send_mode, -1);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Response::getFile()
+ *
+ */
+PHP_METHOD(HTTPi_Response, getFile)
+{
+ zval *the_file;
+ getObject(httpi_response_object, obj);
+
+ NO_ARGS;
+
+ the_file = GET_PROP(obj, file);
+ RETURN_STRINGL(Z_STRVAL_P(the_file), Z_STRLEN_P(the_file), 1);
+}
+/* }}} */
+
+PHP_METHOD(HTTPi_Response, send)
+{
+ zval *do_cache, *do_gzip;
+ getObject(httpi_response_object, obj);
+
+ do_cache = GET_PROP(obj, cache);
+ do_gzip = GET_PROP(obj, gzip);
+
+ /* caching */
+ if (Z_LVAL_P(do_cache)) {
+ zval *cctrl, *etag, *lmod, *ccraw;
+
+ etag = GET_PROP(obj, eTag);
+ lmod = GET_PROP(obj, lastModified);
+ cctrl = GET_PROP(obj, cacheControl);
+ ccraw = GET_PROP(obj, raw_cache_header);
+
+ if (Z_LVAL_P(ccraw)) {
+ http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
+ http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), Z_STRVAL_P(cctrl), Z_STRLEN_P(cctrl));
+ } else {
+ char cc_header[42] = {0};
+ sprintf(cc_header, "%s, must-revalidate, max-age=0", Z_STRVAL_P(cctrl));
+ http_cache_etag(Z_STRVAL_P(etag), Z_STRLEN_P(etag), cc_header, strlen(cc_header));
+ http_cache_last_modified(Z_LVAL_P(lmod), Z_LVAL_P(lmod) ? Z_LVAL_P(lmod) : time(NULL), cc_header, strlen(cc_header));
+ }
+ }
+
+ /* gzip */
+ if (Z_LVAL_P(do_gzip)) {
+ /* ... */
+ }
+
+ /* content type */
+ {
+ zval *ctype = GET_PROP(obj, contentType);
+ if (Z_STRLEN_P(ctype)) {
+ http_send_content_type(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype));
+ } else {
+ http_send_content_type("application/x-octetstream", sizeof("application/x-octetstream") - 1);
+ }
+ }
+
+ /* content disposition */
+ {
+ zval *dispo_file = GET_PROP(obj, dispoFile);
+ if (Z_STRLEN_P(dispo_file)) {
+ zval *dispo_inline = GET_PROP(obj, dispoInline);
+ http_send_content_disposition(Z_STRVAL_P(dispo_file), Z_STRLEN_P(dispo_file), Z_LVAL_P(dispo_inline));
+ }
+ }
+
+ /* send */
+ {
+ zval *send_mode = GET_PROP(obj, send_mode);
+ switch (Z_LVAL_P(send_mode))
+ {
+ case SEND_DATA:
+ {
+ RETURN_SUCCESS(http_send_data(GET_PROP(obj, data)));
+ }
+
+ case SEND_RSRC:
+ {
+ php_stream *the_real_stream;
+ zval *the_stream = GET_PROP(obj, stream);
+ php_stream_from_zval(the_real_stream, &the_stream);
+ RETURN_SUCCESS(http_send_stream(the_real_stream));
+ }
+
+ default:
+ {
+ RETURN_SUCCESS(http_send_file(GET_PROP(obj, file)));
+ }
+ }
+ }
+}
+/* }}} */
+/* }}} */
+
+#ifdef HTTP_HAVE_CURL
+/* {{{ HTTPi_Request */
+
+/* {{{ proto void HTTPi_Request::__construct([string url[, long request_method = HTTP_GET]])
+ *
+ */
+PHP_METHOD(HTTPi_Request, __construct)
+{
+ char *URL = NULL;
+ int URL_len;
+ long meth = -1;
+ zval *info, *opts, *resp;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sl", &URL, &URL_len, &meth)) {
+ return;
+ }
+
+ INIT_PARR(obj, options);
+ INIT_PARR(obj, responseInfo);
+ INIT_PARR(obj, responseData);
+ INIT_PARR(obj, postData);
+ INIT_PARR(obj, postFiles);
+
+ if (URL) {
+ UPD_PROP(obj, string, url, URL);
+ }
+ if (meth > -1) {
+ UPD_PROP(obj, long, method, meth);
+ }
+}
+/* }}} */
+
+/* {{{ proto void HTTPi_Request::__destruct()
+ *
+ */
+PHP_METHOD(HTTPi_Request, __destruct)
+{
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ FREE_PARR(obj, options);
+ FREE_PARR(obj, responseInfo);
+ FREE_PARR(obj, responseData);
+ FREE_PARR(obj, postData);
+ FREE_PARR(obj, postFiles);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::setOptions(array options)
+ *
+ */
+PHP_METHOD(HTTPi_Request, setOptions)
+{
+ zval *opts, *old_opts, **opt;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/", &opts)) {
+ RETURN_FALSE;
+ }
+
+ old_opts = GET_PROP(obj, options);
+
+ /* headers and cookies need extra attention -- thus cannot use zend_hash_merge() or php_array_merge() directly */
+ for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(opts));
+ zend_hash_get_current_data(Z_ARRVAL_P(opts), (void **) &opt) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(opts))) {
+ char *key;
+ long idx;
+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key(Z_ARRVAL_P(opts), &key, &idx, 0)) {
+ if (!strcmp(key, "headers")) {
+ zval **headers;
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "headers", sizeof("headers"), (void **) &headers)) {
+ array_merge(*opt, *headers);
+ continue;
+ }
+ } else if (!strcmp(key, "cookies")) {
+ zval **cookies;
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(old_opts), "cookies", sizeof("cookies"), (void **) &cookies)) {
+ array_merge(*opt, *cookies);
+ continue;
+ }
+ }
+ zval_add_ref(opt);
+ add_assoc_zval(old_opts, key, *opt);
+ }
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array HTTPi_Request::getOptions()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getOptions)
+{
+ zval *opts;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ opts = GET_PROP(obj, options);
+ array_init(return_value);
+ array_copy(opts, return_value);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::setURL(string url)
+ *
+ */
+PHP_METHOD(HTTPi_Request, setURL)
+{
+ char *URL = NULL;
+ int URL_len;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &URL, &URL_len)) {
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, string, url, URL);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Request::getUrl()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getURL)
+{
+ zval *URL;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ URL = GET_PROP(obj, url);
+ RETURN_STRINGL(Z_STRVAL_P(URL), Z_STRLEN_P(URL), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::setMethod(long request_method)
+ *
+ */
+PHP_METHOD(HTTPi_Request, setMethod)
+{
+ long meth;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &meth)) {
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, long, method, meth);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto long HTTPi_Request::getMethod()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getMethod)
+{
+ zval *meth;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ meth = GET_PROP(obj, method);
+ RETURN_LONG(Z_LVAL_P(meth));
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::setContentType(string content_type)
+ *
+ */
+PHP_METHOD(HTTPi_Request, setContentType)
+{
+ char *ctype;
+ int ct_len;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &ctype, &ct_len)) {
+ RETURN_FALSE;
+ }
+
+ if (!strchr(ctype, '/')) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ "Content-Type '%s' doesn't seem to contain a primary and a secondary part",
+ ctype);
+ RETURN_FALSE;
+ }
+
+ UPD_PROP(obj, string, contentType, ctype);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Request::getContentType()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getContentType)
+{
+ zval *ctype;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ ctype = GET_PROP(obj, contentType);
+ RETURN_STRINGL(Z_STRVAL_P(ctype), Z_STRLEN_P(ctype), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::setQueryData(mixed query_data)
+ *
+ */
+PHP_METHOD(HTTPi_Request, setQueryData)
+{
+ zval *qdata;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &qdata)) {
+ RETURN_FALSE;
+ }
+
+ if ((Z_TYPE_P(qdata) == IS_ARRAY) || (Z_TYPE_P(qdata) == IS_OBJECT)) {
+ smart_str qstr = {0};
+ HTTP_URL_ARGSEP_OVERRIDE;
+ if (SUCCESS != php_url_encode_hash_ex(HASH_OF(qdata), &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
+ if (qstr.c) {
+ efree(qstr.c);
+ }
+ HTTP_URL_ARGSEP_RESTORE;
+ RETURN_FALSE;
+ }
+ HTTP_URL_ARGSEP_RESTORE;
+ smart_str_0(&qstr);
+ UPD_PROP(obj, string, queryData, qstr.c);
+ efree(qstr.c);
+ RETURN_TRUE;
+ }
+
+ convert_to_string(qdata);
+ UPD_PROP(obj, string, queryData, Z_STRVAL_P(qdata));
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Request::getQueryData()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getQueryData)
+{
+ zval *qdata;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ qdata = GET_PROP(obj, queryData);
+ RETURN_STRINGL(Z_STRVAL_P(qdata), Z_STRLEN_P(qdata), 1);
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::addQueryData(array query_params)
+ *
+ */
+PHP_METHOD(HTTPi_Request, addQueryData)
+{
+ zval *qdata, *old_qdata;
+ smart_str qstr = {0};
+ char *separator;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &qdata)) {
+ RETURN_FALSE;
+ }
+
+ old_qdata = GET_PROP(obj, queryData);
+ if (Z_STRLEN_P(old_qdata)) {
+ smart_str_appendl(&qstr, Z_STRVAL_P(old_qdata), Z_STRLEN_P(old_qdata));
+ }
+
+ HTTP_URL_ARGSEP_OVERRIDE;
+ if (SUCCESS != php_url_encode_hash_ex(HASH_OF(qdata), &qstr, NULL, 0, NULL, 0, NULL, 0, NULL TSRMLS_CC)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Couldn't encode query data");
+ if (qstr.c) {
+ efree(qstr.c);
+ }
+ HTTP_URL_ARGSEP_RESTORE;
+ RETURN_FALSE;
+ }
+ HTTP_URL_ARGSEP_RESTORE;
+
+ smart_str_0(&qstr);
+
+ UPD_PROP(obj, string, queryData, qstr.c);
+ efree(qstr.c);
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto void HTTPi_Request::unsetQueryData()
+ *
+ */
+PHP_METHOD(HTTPi_Request, unsetQueryData)
+{
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ UPD_PROP(obj, string, queryData, "");
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::addPostData(array post_data)
+ *
+ */
+PHP_METHOD(HTTPi_Request, addPostData)
+{
+ zval *post, *post_data;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
+ RETURN_FALSE;
+ }
+
+ post = GET_PROP(obj, postData);
+ array_merge(post_data, post);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::setPostData(array post_data)
+ *
+ */
+PHP_METHOD(HTTPi_Request, setPostData)
+{
+ zval *post, *post_data;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &post_data)) {
+ RETURN_FALSE;
+ }
+
+ post = GET_PROP(obj, postData);
+ zend_hash_clean(Z_ARRVAL_P(post));
+ array_copy(post_data, post);
+
+ RETURN_TRUE;
+}
+/* }}}*/
+
+/* {{{ proto array HTTPi_Request::getPostData()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getPostData)
+{
+ zval *post_data;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ post_data = GET_PROP(obj, postData);
+ array_init(return_value);
+ array_copy(post_data, return_value);
+}
+/* }}} */
+
+/* {{{ proto void HTTPi_Request::unsetPostData()
+ *
+ */
+PHP_METHOD(HTTPi_Request, unsetPostData)
+{
+ zval *post_data;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ post_data = GET_PROP(obj, postData);
+ zend_hash_clean(Z_ARRVAL_P(post_data));
+}
+/* }}} */
+
+/* {{{ proto bool HTTPi_Request::addPostFile(string name, string file[, string content_type = "application/x-octetstream"])
+ *
+ */
+PHP_METHOD(HTTPi_Request, addPostFile)
+{
+ zval *files, *entry;
+ char *name, *file, *type = NULL;
+ int name_len, file_len, type_len = 0;
+ getObject(httpi_request_object, obj);
+
+ if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|s", &name, &name_len, &file, &file_len, &type, &type_len)) {
+ RETURN_FALSE;
+ }
+
+ if (type_len) {
+ if (!strchr(type, '/')) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Content-Type '%s' doesn't seem to contain a primary and a secondary part", type);
+ RETURN_FALSE;
+ }
+ } else {
+ type = "application/x-octetstream";
+ type_len = sizeof("application/x-octetstream") - 1;
+ }
+
+ MAKE_STD_ZVAL(entry);
+ array_init(entry);
+
+ add_assoc_stringl(entry, "name", name, name_len, 1);
+ add_assoc_stringl(entry, "type", type, type_len, 1);
+ add_assoc_stringl(entry, "file", file, file_len, 1);
+
+ files = GET_PROP(obj, postFiles);
+ add_next_index_zval(files, entry);
+
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array HTTPi_Request::getPostFiles()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getPostFiles)
+{
+ zval *files;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ files = GET_PROP(obj, postFiles);
+
+ array_init(return_value);
+ array_copy(files, return_value);
+}
+/* }}} */
+
+/* {{{ proto void HTTPi_Request::unsetPostFiles()
+ *
+ */
+PHP_METHOD(HTTPi_Request, unsetPostFiles)
+{
+ zval *files;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ files = GET_PROP(obj, postFiles);
+ zend_hash_clean(Z_ARRVAL_P(files));
+}
+/* }}} */
+
+/* {{{ proto array HTTPi_Request::getResponseData()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getResponseData)
+{
+ zval *data;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ data = GET_PROP(obj, responseData);
+ array_init(return_value);
+ array_copy(data, return_value);
+}
+/* }}} */
+
+/* {{{ proto array HTTPi_Request::getResponseHeaders()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getResponseHeaders)
+{
+ zval *data, **headers;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ array_init(return_value);
+ data = GET_PROP(obj, responseData);
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "headers", sizeof("headers"), (void **) &headers)) {
+ array_copy(*headers, return_value);
+ }
+}
+/* }}} */
+
+/* {{{ proto string HTTPi_Request::getResponseBody()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getResponseBody)
+{
+ zval *data, **body;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ data = GET_PROP(obj, responseData);
+ if (SUCCESS == zend_hash_find(Z_ARRVAL_P(data), "body", sizeof("body"), (void **) &body)) {
+ RETURN_STRINGL(Z_STRVAL_PP(body), Z_STRLEN_PP(body), 1);
+ } else {
+ Z_TYPE_P(return_value) = IS_NULL;
+ }
+}
+/* }}} */
+
+/* {{{ proto array HTTPi_Request::getResponseInfo()
+ *
+ */
+PHP_METHOD(HTTPi_Request, getResponseInfo)
+{
+ zval *info;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ info = GET_PROP(obj, responseInfo);
+ array_init(return_value);
+ array_copy(info, return_value);
+}
+/* }}}*/
+
+/* {{{ proto bool HTTPi_Request::send()
+ *
+ */
+PHP_METHOD(HTTPi_Request, send)
+{
+ STATUS status = FAILURE;
+ zval *meth, *URL, *qdata, *opts, *info, *resp;
+ char *response_data, *request_uri;
+ size_t response_len;
+ getObject(httpi_request_object, obj);
+
+ NO_ARGS;
+
+ if ((!obj->ch) && (!(obj->ch = curl_easy_init()))) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not initilaize cURL");
+ RETURN_FALSE;
+ }
+
+ meth = GET_PROP(obj, method);
+ URL = GET_PROP(obj, url);
+ qdata = GET_PROP(obj, queryData);
+ opts = GET_PROP(obj, options);
+ info = GET_PROP(obj, responseInfo);
+ resp = GET_PROP(obj, responseData);
+
+ // HTTP_URI_MAXLEN+1 big char *
+ request_uri = http_absolute_uri(Z_STRVAL_P(URL), NULL);
+
+ if (Z_STRLEN_P(qdata) && (strlen(request_uri) < HTTP_URI_MAXLEN)) {
+ if (!strchr(request_uri, '?')) {
+ strcat(request_uri, "?");
+ } else {
+ strcat(request_uri, "&");
+ }
+ strncat(request_uri, Z_STRVAL_P(qdata), HTTP_URI_MAXLEN - strlen(request_uri));
+ }
+
+ switch (Z_LVAL_P(meth))
+ {
+ case HTTP_GET:
+ status = http_get_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ break;
+
+ case HTTP_HEAD:
+ status = http_head_ex(obj->ch, request_uri, Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ break;
+
+ case HTTP_POST:
+ {
+ zval *post_files, *post_data, **data;
+
+ post_files = GET_PROP(obj, postFiles);
+ post_data = GET_PROP(obj, postData);
+
+ if (!zend_hash_num_elements(Z_ARRVAL_P(post_files))) {
+
+ /* urlencoded post */
+ status = http_post_array_ex(obj->ch, request_uri, Z_ARRVAL_P(post_data), Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+
+ } else {
+
+ /*
+ * multipart post
+ */
+ struct curl_httppost *http_post_data[2] = {NULL, NULL};
+
+ /* normal data */
+ for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(post_data));
+ zend_hash_get_current_data(Z_ARRVAL_P(post_data), (void **) &data) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(post_data))) {
+
+ char *key;
+ long idx;
+
+ if (HASH_KEY_IS_STRING == zend_hash_get_current_key(Z_ARRVAL_P(post_data), &key, &idx, 0)) {
+ convert_to_string_ex(data);
+ curl_formadd(&http_post_data[0], &http_post_data[1],
+ CURLFORM_COPYNAME, key,
+ CURLFORM_COPYCONTENTS, Z_STRVAL_PP(data),
+ CURLFORM_CONTENTSLENGTH, Z_STRLEN_PP(data),
+ CURLFORM_END
+ );
+ }
+ }
+
+ /* file data */
+ for ( zend_hash_internal_pointer_reset(Z_ARRVAL_P(post_files));
+ zend_hash_get_current_data(Z_ARRVAL_P(post_files), (void **) &data) == SUCCESS;
+ zend_hash_move_forward(Z_ARRVAL_P(post_files))) {
+
+ zval **file, **type, **name;
+
+ if (
+ SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "name", sizeof("name"), (void **) &name) &&
+ SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "type", sizeof("type"), (void **) &type) &&
+ SUCCESS == zend_hash_find(Z_ARRVAL_PP(data), "file", sizeof("file"), (void **) &file)
+ ) {
+
+ curl_formadd(&http_post_data[0], &http_post_data[1],
+ CURLFORM_COPYNAME, Z_STRVAL_PP(name),
+ CURLFORM_FILENAME, Z_STRVAL_PP(name),
+ CURLFORM_FILE, Z_STRVAL_PP(file),
+ CURLFORM_CONTENTTYPE, Z_STRVAL_PP(type),
+ CURLFORM_END
+ );
+ }
+ }
+
+ status = http_post_curldata_ex(obj->ch, request_uri, http_post_data[0], Z_ARRVAL_P(opts), Z_ARRVAL_P(info), &response_data, &response_len);
+ curl_formfree(http_post_data[0]);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ efree(request_uri);
+
+ /* final data handling */
+ if (status != SUCCESS) {
+ RETURN_FALSE;
+ } else {
+ zval *zheaders, *zbody;
+
+ MAKE_STD_ZVAL(zbody);
+ MAKE_STD_ZVAL(zheaders)
+ array_init(zheaders);
+
+ if (SUCCESS != http_split_response_ex(response_data, response_len, zheaders, zbody)) {
+ zval_dtor(zheaders);
+ efree(zheaders),
+ efree(zbody);
+ efree(response_data);
+ RETURN_FALSE;
+ }
+
+ add_assoc_zval(resp, "headers", zheaders);
+ add_assoc_zval(resp, "body", zbody);
+
+ efree(response_data);
+
+ RETURN_TRUE;
+ }
+ /* */
+}
+/* }}} */
+/* }}} */
+#endif /* HTTP_HAVE_CURL */
+
+#endif /* ZEND_ENGINE_2 */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
<dir name="/">
<file role="doc">EXPERIMENTAL</file>
<file role="doc">docs/functions.html</file>
+
<file role="src" platform="windows">config.w32</file>
<file role="src">config.m4</file>
- <file role="src">http.c</file>
+
<file role="src">php_http.h</file>
- <file role="src">http_api.c</file>
<file role="src">php_http_api.h</file>
+ <file role="src">php_http_curl_api.h</file>
+
+ <file role="src">http.c</file>
+ <file role="src">http_functions.c</file>
+ <file role="src">http_methods.c</file>
+ <file role="src">http_api.c</file>
+ <file role="src">http_curl_api.c</file>
+
<file role="src">http_build_query.c</file>
<file role="src">php_http_build_query.h</file>
</dir>
# include "php_http_build_query.h"
#else
+typedef struct {
+ zend_object zo;
+} httpi_response_object;
+
#ifdef HTTP_HAVE_CURL
+
+#include <curl/curl.h>
+
+typedef struct {
+ zend_object zo;
+ CURL *ch;
+} httpi_request_object;
+
typedef enum {
HTTP_GET,
HTTP_HEAD,
HTTP_POST,
} http_request_method;
+
#endif
PHP_METHOD(HTTPi, date);
char *allowed_methods;
#ifdef HTTP_HAVE_CURL
struct {
- struct {
- char *data;
- size_t used;
- size_t free;
- } body;
- struct {
- char *data;
- size_t used;
- size_t free;
- } hdrs;
+ char *data;
+ size_t used;
+ size_t free;
+ size_t size;
} curlbuf;
#endif
ZEND_END_MODULE_GLOBALS(http)
# include "php_http_build_query.h"
#endif
+#define RETURN_SUCCESS(v) RETURN_BOOL(SUCCESS == (v))
+#define HASH_ORNULL(z) ((z) ? Z_ARRVAL_P(z) : NULL)
+#define NO_ARGS if (ZEND_NUM_ARGS()) WRONG_PARAM_COUNT
+
+#define array_copy(src, dst) zend_hash_copy(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *))
+#define array_merge(src, dst) zend_hash_merge(Z_ARRVAL_P(dst), Z_ARRVAL_P(src), (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *), 1)
+
+#ifdef ZEND_ENGINE_2
+
+# define HTTP_REGISTER_CLASS_EX(classname, name, parent, flags) \
+ { \
+ zend_class_entry ce; \
+ INIT_CLASS_ENTRY(ce, #classname, name## _class_methods); \
+ ce.create_object = name## _new_object; \
+ name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
+ name## _ce->ce_flags |= flags; \
+ memcpy(& name## _object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
+ name## _object_handlers.clone_obj = NULL; \
+ name## _declare_default_properties(name## _ce); \
+ }
+
+# define HTTP_REGISTER_CLASS(classname, name, parent, flags) \
+ { \
+ zend_class_entry ce; \
+ INIT_CLASS_ENTRY(ce, #classname, name## _class_methods); \
+ ce.create_object = NULL; \
+ name## _ce = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
+ name## _ce->ce_flags |= flags; \
+ }
+
+# define getObject(t, o) t * o = ((t *) zend_object_store_get_object(getThis() TSRMLS_CC))
+# define OBJ_PROP(o) o->zo.properties
+# define DCL_PROP(a, t, n, v) zend_declare_property_ ##t(ce, (#n), sizeof(#n), (v), (ZEND_ACC_ ##a) TSRMLS_CC)
+# define DCL_PROP_Z(a, n, v) zend_declare_property(ce, (#n), sizeof(#n), (v), (ZEND_ACC_ ##a) TSRMLS_CC)
+# define DCL_PROP_N(a, n) zend_declare_property_null(ce, (#n), sizeof(#n), (ZEND_ACC_ ##a) TSRMLS_CC)
+# define UPD_PROP(o, t, n, v) zend_update_property_ ##t(o->zo.ce, getThis(), (#n), sizeof(#n), (v) TSRMLS_CC)
+# define SET_PROP(o, n, z) zend_update_property(o->zo.ce, getThis(), (#n), sizeof(#n), (z) TSRMLS_CC)
+# define GET_PROP(o, n) zend_read_property(o->zo.ce, getThis(), (#n), sizeof(#n), 0 TSRMLS_CC)
+
+# define INIT_PARR(o, n) \
+ { \
+ zval *__tmp; \
+ MAKE_STD_ZVAL(__tmp); \
+ array_init(__tmp); \
+ SET_PROP(o, n, __tmp); \
+ }
+
+# define FREE_PARR(o, p) \
+ { \
+ zval *__tmp = NULL; \
+ if (__tmp = GET_PROP(o, p)) { \
+ zval_dtor(__tmp); \
+ FREE_ZVAL(__tmp); \
+ __tmp = NULL; \
+ } \
+ }
+
+#endif /* ZEND_ENGINE_2 */
+
/* make functions that return SUCCESS|FAILURE more obvious */
typedef int STATUS;
/* server vars shorthand */
#define HTTP_SERVER_VARS Z_ARRVAL_P(PG(http_globals)[TRACK_VARS_SERVER])
-/* override arg_separator.output to "&" for data used in outgoing requests */
-#include "zend_ini.h"
-#define HTTP_URL_ARGSEP_OVERRIDE zend_alter_ini_entry("arg_separator.output", sizeof("arg_separator.output") - 1, "&", 1, ZEND_INI_ALL, ZEND_INI_STAGE_RUNTIME)
-#define HTTP_URL_ARGSEP_RESTORE zend_restore_ini_entry("arg_separator.output", sizeof("arg_separator.output") - 1, ZEND_INI_STAGE_RUNTIME)
-
-/* {{{ HAVE_CURL */
-#ifdef HTTP_HAVE_CURL
-#include <curl/curl.h>
-
-/* CURL buffer size */
-#define HTTP_CURLBUF_BODYSIZE 16384
-#define HTTP_CURLBUF_HDRSSIZE 4096
-
-/* {{{ http_curlbuf_member */
-typedef enum {
- CURLBUF_BODY = 1,
- CURLBUF_HDRS = 2,
- CURLBUF_EVRY = 3
-} http_curlbuf_member;
-/* }}} */
-#endif
-/* }}} HAVE_CURL */
/* {{{ HTTP_GSC(var, name, ret) */
#define HTTP_GSC(var, name, ret) HTTP_GSP(var, name, return ret)
}
/* }}} */
+char *pretty_key(char *key, int key_len, int uctitle, int xhyphen);
+
/* {{{ public API */
#define http_date(t) _http_date((t) TSRMLS_CC)
PHP_HTTP_API char *_http_date(time_t t TSRMLS_DC);
#define http_get_request_headers(h) _http_get_request_headers((h) TSRMLS_CC)
PHP_HTTP_API void _http_get_request_headers(zval *array TSRMLS_DC);
-/* {{{ HAVE_CURL */
-#ifdef HTTP_HAVE_CURL
-
-#define http_get(u, o, i, d, l) _http_get((u), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
-#define http_get_ex(c, u, o, i, d, l) _http_get_ex((c), (u), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
-
-#define http_head(u, o, i, d, l) _http_head((u), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
-#define http_head_ex(c, u, o, i, d, l) _http_head_ex((c), (u), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
-
-#define http_post_data(u, pd, pl, o, i, d, l) _http_post_data((u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
-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);
-#define http_post_data_ex(c, u, pd, pl, o, i, d, l) _http_post_data_ex((c), (u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
-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);
-
-#define http_post_array(u, p, o, i, d, l) _http_post_array_ex(NULL, (u), (p), (o), (i), (d), (l) TSRMLS_CC)
-#define http_post_array_ex(c, u, p, o, i, d, l) _http_post_array_ex((c), (u), (p), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
-
-#define http_post_curldata_ex(c, u, h, o, i, d, l) _http_post_curldata_ex((c), (u), (h), (o), (i), (d), (l) TSRMLS_CC)
-PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, struct curl_httppost *curldata, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
-
-#endif
-/* }}} HAVE_CURL */
-
#define http_auth_credentials(u, p) _http_auth_credentials((u), (p) TSRMLS_CC)
PHP_HTTP_API STATUS _http_auth_credentials(char **user, char **pass TSRMLS_DC);
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | PECL :: http |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.0 of the PHP license, that |
+ | is bundled with this package in the file LICENSE, and is available |
+ | through the world-wide-web at http://www.php.net/license/3_0.txt. |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2004-2005 Michael Wallner <mike@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_HTTP_CURL_API_H
+#define PHP_HTTP_CURL_API_H
+
+#include <curl/curl.h>
+#include "zend_ini.h"
+
+/* override arg_separator.output to "&" for data used in outgoing requests */
+#define HTTP_URL_ARGSEP_OVERRIDE zend_alter_ini_entry("arg_separator.output", sizeof("arg_separator.output") - 1, "&", 1, ZEND_INI_ALL, ZEND_INI_STAGE_RUNTIME)
+#define HTTP_URL_ARGSEP_RESTORE zend_restore_ini_entry("arg_separator.output", sizeof("arg_separator.output") - 1, ZEND_INI_STAGE_RUNTIME)
+
+/* CURL buffer size */
+#define HTTP_CURLBUF_SIZE 16384
+
+#define http_get(u, o, i, d, l) _http_get((u), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_get(const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_get_ex(c, u, o, i, d, l) _http_get_ex((c), (u), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_get_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+
+#define http_head(u, o, i, d, l) _http_head((u), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_head(const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+#define http_head_ex(c, u, o, i, d, l) _http_head_ex((c), (u), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_head_ex(CURL *ch, const char *URL, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+
+#define http_post_data(u, pd, pl, o, i, d, l) _http_post_data((u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
+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);
+#define http_post_data_ex(c, u, pd, pl, o, i, d, l) _http_post_data_ex((c), (u), (pd), (pl), (o), (i), (d), (l) TSRMLS_CC)
+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);
+
+#define http_post_array(u, p, o, i, d, l) _http_post_array_ex(NULL, (u), (p), (o), (i), (d), (l) TSRMLS_CC)
+#define http_post_array_ex(c, u, p, o, i, d, l) _http_post_array_ex((c), (u), (p), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_array_ex(CURL *ch, const char *URL, HashTable *postarray, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+
+#define http_post_curldata_ex(c, u, h, o, i, d, l) _http_post_curldata_ex((c), (u), (h), (o), (i), (d), (l) TSRMLS_CC)
+PHP_HTTP_API STATUS _http_post_curldata_ex(CURL *ch, const char *URL, struct curl_httppost *curldata, HashTable *options, HashTable *info, char **data, size_t *data_len TSRMLS_DC);
+
+#endif
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */