============
$Id$
-HttpResponse class is infunctional with current ZendEngine2,
+HttpResponse class may be infunctional with current ZendEngine2,
a fix is pending.
-http_chunked_decode() still depends on CRLF.
[ --enable-http Enable extended HTTP support])
PHP_ARG_WITH([curl], [for CURL support],
[ --with-curl[=DIR] Include CURL support])
+PHP_ARG_WITH([mhash], [for mhash support],
+[ --with-mhash[=DIR] Include mhash support])
if test "$PHP_HTTP" != "no"; then
fi
+dnl ----
+dnl MHASH
+dnl ----
+
+ if test "$PHP_MHASH" != "no"; then
+ for i in $PHP_MHASH /usr/local /usr /opt/mhash; do
+ test -f $i/include/mhash.h && MHASH_DIR=$i && break
+ done
+
+ if test -z "$MHASH_DIR"; then
+ AC_MSG_ERROR(Please reinstall libmhash - cannot find mhash.h)
+ fi
+
+ PHP_ADD_INCLUDE($MHASH_DIR/include)
+ PHP_ADD_LIBRARY_WITH_PATH(mhash, $MHASH_DIR/lib, MHASH_SHARED_LIBADD)
+ AC_DEFINE(HAVE_LIBMHASH,1,[HAve mhash support])
+ fi
+
dnl ----
dnl DONE
dnl ----
// $Id$
ARG_ENABLE("http", "whether to enable extended HTTP support", "no");
+ARG_WITH("mhash", "mhash support", "no");
if (PHP_HTTP != "no") {
+
+ if (PHP_MHASH != "no") {
+ if (CHECK_HEADER_ADD_INCLUDE('mhash.h', 'CFLAGS_HTTP') &&
+ CHECK_LIB('libmhash.lib', 'mhash')) {
+ AC_DEFINE('HAVE_LIBMHASH', 1 , "Have mhash library");
+ } else {
+ WARNING("mhash not enabled; libraries and headers not found");
+ }
+ }
+
EXTENSION("http",
"missing.c http.c http_functions.c http_exception_object.c "+
"http_util_object.c http_message_object.c http_requestpool_object.c "+
#include "php_http_std_defs.h"
#include "php_http_api.h"
#include "php_http_send_api.h"
+#include "php_http_cache_api.h"
#ifdef HTTP_HAVE_CURL
# include "php_http_request_api.h"
#endif
#ifdef ZEND_ENGINE_2
HTTP_PHP_INI_ENTRY("http.only_exceptions", "0", PHP_INI_ALL, OnUpdateBool, only_exceptions)
#endif
+ HTTP_PHP_INI_ENTRY("http.etag_mode", "-2", PHP_INI_ALL, OnUpdateLong, etag.mode)
PHP_INI_END()
/* }}} */
#endif
REGISTER_INI_ENTRIES();
+
+ HTTP_LONG_CONSTANT("HTTP_ETAG_MD5", HTTP_ETAG_MD5);
+ HTTP_LONG_CONSTANT("HTTP_ETAG_SHA1", HTTP_ETAG_SHA1);
+ HTTP_LONG_CONSTANT("HTTP_ETAG_MHASH", HTTP_ETAG_MHASH);
#ifdef HTTP_HAVE_CURL
if (CURLE_OK != curl_global_init(CURL_GLOBAL_ALL)) {
#include "php_streams.h"
#include "php_output.h"
#include "ext/standard/md5.h"
+#include "ext/standard/sha1.h"
#include "php_http.h"
#include "php_http_std_defs.h"
{
php_stream_statbuf ssb;
char ssb_buf[128] = {0};
- unsigned char digest[16];
- PHP_MD5_CTX ctx;
- char *new_etag = ecalloc(1, 33);
-
- PHP_MD5Init(&ctx);
-
+ size_t ssb_len;
+ void *ctx = http_etag_init();
+
switch (data_mode)
{
case SEND_DATA:
- PHP_MD5Update(&ctx, data_ptr, data_len);
+ http_etag_update(ctx, data_ptr, data_len);
break;
case SEND_RSRC:
{
if (php_stream_stat((php_stream *) data_ptr, &ssb)) {
- efree(new_etag);
+ efree(ctx);
return NULL;
}
-
- snprintf(ssb_buf, 127, "%ld=%ld=%ld", ssb.sb.st_mtime, ssb.sb.st_ino, ssb.sb.st_size);
- PHP_MD5Update(&ctx, ssb_buf, strlen(ssb_buf));
+ ssb_len = snprintf(ssb_buf, 127, "%ld=%ld=%ld", ssb.sb.st_mtime, ssb.sb.st_ino, ssb.sb.st_size);
+ http_etag_update(ctx, ssb_buf, ssb_len);
}
break;
default:
{
if (php_stream_stat_path((char *) data_ptr, &ssb)) {
- efree(new_etag);
+ efree(ctx);
return NULL;
}
-
- snprintf(ssb_buf, 127, "%ld=%ld=%ld", ssb.sb.st_mtime, ssb.sb.st_ino, ssb.sb.st_size);
- PHP_MD5Update(&ctx, ssb_buf, strlen(ssb_buf));
+ ssb_len = snprintf(ssb_buf, 127, "%ld=%ld=%ld", ssb.sb.st_mtime, ssb.sb.st_ino, ssb.sb.st_size);
+ http_etag_update(ctx, ssb_buf, ssb_len);
}
break;
}
- PHP_MD5Final(digest, &ctx);
- make_digest(new_etag, digest);
-
- return new_etag;
+ return http_etag_finish(ctx);
}
/* }}} */
PHP_HTTP_API void _http_ob_etaghandler(char *output, uint output_len,
char **handled_output, uint *handled_output_len, int mode TSRMLS_DC)
{
- char etag[33] = { 0 };
- unsigned char digest[16];
+ char etag[41] = { 0 };
+ unsigned char digest[20];
if (mode & PHP_OUTPUT_HANDLER_START) {
+ if (HTTP_G(etag).started) {
+ http_error(HE_WARNING, HTTP_E_RUNTIME, "ob_etaghandler can only be used once");
+ return;
+ }
HTTP_G(etag).started = 1;
- PHP_MD5Init(&HTTP_G(etag).md5ctx);
+ HTTP_G(etag).ctx = http_etag_init();
}
- PHP_MD5Update(&HTTP_G(etag).md5ctx, output, output_len);
+ http_etag_update(HTTP_G(etag).ctx, output, output_len);
if (mode & PHP_OUTPUT_HANDLER_END) {
- PHP_MD5Final(digest, &HTTP_G(etag).md5ctx);
-
+ char *etag = http_etag_finish(HTTP_G(etag).ctx);
+
/* just do that if desired */
if (HTTP_G(etag).started) {
char *sent_header = NULL;
- make_digest(etag, digest);
http_send_cache_control(HTTP_DEFAULT_CACHECONTROL, lenof(HTTP_DEFAULT_CACHECONTROL));
- http_send_etag_ex(etag, 32, &sent_header);
-
+ http_send_etag_ex(etag, strlen(etag), &sent_header);
+
if (http_match_etag("HTTP_IF_NONE_MATCH", etag)) {
+ efree(etag);
http_exit_ex(304, sent_header, NULL, 0);
} else {
STR_FREE(sent_header);
}
}
+ efree(etag);
}
*handled_output_len = output_len;
/* capture mode */
if (Z_BVAL_P(GET_STATIC_PROP(catch))) {
- zval *the_data;
+ zval the_data;
- MAKE_STD_ZVAL(the_data);
- php_ob_get_buffer(the_data TSRMLS_CC);
-
- SET_STATIC_PROP(data, the_data);
+ INIT_PZVAL(&the_data);
+ php_ob_get_buffer(&the_data TSRMLS_CC);
+ SET_STATIC_PROP(data, &the_data);
ZVAL_LONG(GET_STATIC_PROP(mode), SEND_DATA);
if (!Z_STRLEN_P(GET_STATIC_PROP(eTag))) {
- char *etag = http_etag(Z_STRVAL_P(the_data), Z_STRLEN_P(the_data), SEND_DATA);
+ char *etag = http_etag(Z_STRVAL(the_data), Z_STRLEN(the_data), SEND_DATA);
UPD_STATIC_PROP(string, eTag, etag);
efree(etag);
}
+ zval_dtor(&the_data);
clean_ob = 1;
}
*/
PHP_METHOD(HttpResponse, capture)
{
- zval *do_catch;
+ zval do_catch;
NO_ARGS;
- MAKE_STD_ZVAL(do_catch);
- ZVAL_LONG(do_catch, 1);
+ INIT_PZVAL(&do_catch);
+ ZVAL_LONG(&do_catch, 1);
- SET_STATIC_PROP(catch, do_catch);
+ SET_STATIC_PROP(catch, &do_catch);
php_end_ob_buffers(0 TSRMLS_CC);
php_start_ob_buffer(NULL, 0, 0 TSRMLS_CC);
static void dup_zval(zval **z)
{
+ zval *o = *z;
zval_add_ref(z);
SEPARATE_ZVAL(z);
}
}
retval = SUCCESS;
}
-
+ zval_ptr_dtor(&value);
EG(scope) = old_scope;
return retval;
{
zend_hash_copy(static_members, ce->static_members, (copy_ctor_func_t) zval_add_ref, NULL, sizeof(zval *));
zend_hash_destroy(ce->static_members);
- zend_hash_init_ex(ce->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
+ zend_hash_init_ex(ce->static_members, static_members->nNumOfElements, NULL, ZVAL_PTR_DTOR, 1, 0);
}
void zend_init_static_properties(zend_class_entry *ce, HashTable *static_members TSRMLS_DC)
# include <curl/curl.h>
#endif
#include "ext/standard/md5.h"
+#include "ext/standard/sha1.h"
#include "phpstr/phpstr.h"
extern zend_module_entry http_module_entry;
zend_bool only_exceptions;
#endif
struct _http_globals_etag {
+ long mode;
+ void *ctx;
zend_bool started;
- PHP_MD5_CTX md5ctx;
} etag;
struct _http_globals_log {
#define PHP_HTTP_CACHE_API_H
#include "php_http_std_defs.h"
+#include "php_http.h"
#include "php_http_api.h"
#include "php_http_send_api.h"
+#include "zend_ini.h"
+
+#ifdef HAVE_LIBMHASH
+# include <mhash.h>
+#endif
+
+ZEND_EXTERN_MODULE_GLOBALS(http);
+
+typedef enum {
+ HTTP_ETAG_MD5 = -2,
+ HTTP_ETAG_SHA1 = -1,
+ HTTP_ETAG_MHASH = 0,
+} http_etag_mode;
+
+#ifdef HAVE_LIBMHASH
+static void *http_etag_alloc_mhash_digest(size_t size)
+{
+ return emalloc(size);
+}
+#endif
+
+#define http_etag_digest(d, l) _http_etag_digest((d), (l) TSRMLS_CC)
+static inline char *_http_etag_digest(const unsigned char *digest, int len TSRMLS_DC)
+{
+ int i;
+ char *hex = emalloc(len * 2 + 1);
+ char *ptr = hex;
+
+ /* optimize this --
+ look at apache's make_etag */
+ for (i = 0; i < len; ++i) {
+ sprintf(ptr, "%02x", digest[i]);
+ ptr += 2;
+ }
+ *ptr = '\0';
+
+ return hex;
+}
+
+#define http_etag_init() _http_etag_init(TSRMLS_C)
+static inline void *_http_etag_init(TSRMLS_D)
+{
+ void *ctx;
+ long mode = INI_INT("http.etag_mode");
+
+ switch (mode)
+ {
+ case HTTP_ETAG_SHA1:
+ PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX)));
+ break;
+
+ case HTTP_ETAG_MD5:
+invalid_flag:
+ PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX)));
+ break;
+
+ default:
+ {
+#ifdef HAVE_LIBMHASH
+ if ((mode >= 0) && (mode <= mhash_count())) {
+ ctx = mhash_init(mode);
+ }
+ if ((!ctx) || (ctx == MHASH_FAILED))
+#endif
+ {
+ HTTP_G(etag).mode = HTTP_ETAG_MD5;
+ goto invalid_flag;
+ }
+ }
+ break;
+ }
+
+ return ctx;
+}
+
+#define http_etag_finish(c) _http_etag_finish((c) TSRMLS_CC)
+static inline char *_http_etag_finish(void *ctx TSRMLS_DC)
+{
+ char *etag = NULL;
+ unsigned char digest[20];
+ long mode = INI_INT("http.etag_mode");
+
+ switch (mode)
+ {
+ case HTTP_ETAG_SHA1:
+ PHP_SHA1Final(digest, ctx);
+ etag = http_etag_digest(digest, 20);
+ efree(ctx);
+ break;
+
+ case HTTP_ETAG_MD5:
+ PHP_MD5Final(digest, ctx);
+ etag = http_etag_digest(digest, 16);
+ efree(ctx);
+ break;
+
+ default:
+ {
+#ifdef HAVE_LIBMHASH
+ unsigned char *mhash_digest = mhash_end_m(ctx, http_etag_alloc_mhash_digest);
+ etag = http_etag_digest(mhash_digest, mhash_get_block_size(mode));
+ efree(mhash_digest);
+#endif
+ }
+ break;
+ }
+
+ return etag;
+}
+
+#define http_etag_update(c, d, l) _http_etag_update((c), (d), (l) TSRMLS_CC)
+static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC)
+{
+ switch (INI_INT("http.etag_mode"))
+ {
+ case HTTP_ETAG_SHA1:
+ PHP_SHA1Update(ctx, data_ptr, data_len);
+ break;
+
+ case HTTP_ETAG_MD5:
+ PHP_MD5Update(ctx, data_ptr, data_len);
+ break;
+
+ default:
+#ifdef HAVE_LIBMHASH
+ mhash(ctx, data_ptr, data_len);
+#endif
+ break;
+ }
+}
+
#define http_etag(p, l, m) _http_etag((p), (l), (m) TSRMLS_CC)
PHP_HTTP_API char *_http_etag(const void *data_ptr, size_t data_len, http_send_mode data_mode TSRMLS_DC);