From 92f5e5a5df0bff3d8076c1f5ed73590b40849501 Mon Sep 17 00:00:00 2001 From: Michael Wallner Date: Sat, 19 Nov 2005 09:26:18 +0000 Subject: [PATCH] - add preliminary ext/hash support (currently only for Win32) --- config.w32 | 7 +++ http.c | 32 ++++++---- http_cache_api.c | 8 +++ http_response_object.c | 8 +++ php_http_cache_api.h | 131 +++++++++++++++++++++++++-------------- tests/etag_mode_005.phpt | 24 +++++++ tests/etag_mode_015.phpt | 22 +++++++ tests/etag_mode_035.phpt | 24 +++++++ tests/etag_mode_045.phpt | 22 +++++++ 9 files changed, 218 insertions(+), 60 deletions(-) create mode 100644 tests/etag_mode_005.phpt create mode 100644 tests/etag_mode_015.phpt create mode 100644 tests/etag_mode_035.phpt create mode 100644 tests/etag_mode_045.phpt diff --git a/config.w32 b/config.w32 index 8120ff2..af89ae7 100644 --- a/config.w32 +++ b/config.w32 @@ -29,6 +29,13 @@ if (PHP_HTTP != "no") { } else { WARNING("zlib encoding functions not enabled; libraries and headers not found"); } + + if (PHP_HASH != "no") { + if (glob(configure_module_dirname +"\\..\\hash\\php_hash_sha.h").length) { + ADD_FLAG("CFLAGS_HTTP", "/I"+ configure_module_dirname +"\\..\\hash"); + AC_DEFINE("HTTP_HAVE_HASH_EXT_INCLUDES", 1, ""); + } + } MHASH_LIB = PHP_DEBUG != "no" ? "libmhash-staticd.lib":"libmhash-static.lib"; if (CHECK_HEADER_ADD_INCLUDE('mhash.h', 'CFLAGS_HTTP') && diff --git a/http.c b/http.c index 6695ff9..4a7ccd9 100644 --- a/http.c +++ b/http.c @@ -217,6 +217,11 @@ PHP_INI_MH(http_update_allowed_methods) return OnUpdateString(entry, new_value, new_value_length, mh_arg1, mh_arg2, mh_arg3, stage TSRMLS_CC); } +#undef CASE_HTTP_ETAG_HASH +#define CASE_HTTP_ETAG_HASH(HASH) \ + case HTTP_ETAG_##HASH: \ + ZEND_WRITE(#HASH, lenof(#HASH)); \ + break; PHP_INI_DISP(http_etag_mode_displayer) { long value; @@ -231,20 +236,19 @@ PHP_INI_DISP(http_etag_mode_displayer) switch (value) { - case HTTP_ETAG_CRC32: - ZEND_WRITE("HTTP_ETAG_CRC32", lenof("HTTP_ETAG_CRC32")); - break; - - case HTTP_ETAG_SHA1: - ZEND_WRITE("HTTP_ETAG_SHA1", lenof("HTTP_ETAG_SHA1")); - break; - - case HTTP_ETAG_MD5: +#ifdef HTTP_HAVE_HASH_EXT + CASE_HTTP_ETAG_HASH(RIPEMD160); + CASE_HTTP_ETAG_HASH(RIPEMD128); + CASE_HTTP_ETAG_HASH(SHA512); + CASE_HTTP_ETAG_HASH(SHA384); + CASE_HTTP_ETAG_HASH(SHA256); +#endif + CASE_HTTP_ETAG_HASH(CRC32); + CASE_HTTP_ETAG_HASH(SHA1); #ifndef HTTP_HAVE_MHASH default: #endif - ZEND_WRITE("HTTP_ETAG_MD5", lenof("HTTP_ETAG_MD5")); - break; + CASE_HTTP_ETAG_HASH(MD5); #ifdef HTTP_HAVE_MHASH default: @@ -418,7 +422,11 @@ PHP_MINFO_FUNCTION(http) php_info_print_table_colspan_header(2, "Supported ETag Hash Algorithms"); { - php_info_print_table_row(2, "PHP", "CRC32, MD5, SHA1"); + php_info_print_table_row(2, "PHP", "CRC32, MD5, SHA1" +#ifdef HTTP_HAVE_HASH_EXT + ", SHA256, SHA384, SHA512, RIPEMD128, RIPEMD160" +#endif + ); #ifdef HTTP_HAVE_MHASH { phpstr *algos = phpstr_new(); diff --git a/http_cache_api.c b/http_cache_api.c index eb68044..963bb7e 100644 --- a/http_cache_api.c +++ b/http_cache_api.c @@ -42,6 +42,14 @@ PHP_MINIT_FUNCTION(http_cache) HTTP_LONG_CONSTANT("HTTP_ETAG_SHA1", HTTP_ETAG_SHA1); HTTP_LONG_CONSTANT("HTTP_ETAG_CRC32", HTTP_ETAG_CRC32); +#ifdef HTTP_HAVE_HASH_EXT + HTTP_LONG_CONSTANT("HTTP_ETAG_SHA256", HTTP_ETAG_SHA256); + HTTP_LONG_CONSTANT("HTTP_ETAG_SHA384", HTTP_ETAG_SHA384); + HTTP_LONG_CONSTANT("HTTP_ETAG_SHA512", HTTP_ETAG_SHA512); + HTTP_LONG_CONSTANT("HTTP_ETAG_RIPEMD128", HTTP_ETAG_RIPEMD128); + HTTP_LONG_CONSTANT("HTTP_ETAG_RIPEMD160", HTTP_ETAG_RIPEMD160); +#endif + #ifdef HTTP_HAVE_MHASH { int l, i, c = mhash_count(); diff --git a/http_response_object.c b/http_response_object.c index e5b0d00..544b603 100644 --- a/http_response_object.c +++ b/http_response_object.c @@ -248,6 +248,14 @@ static inline void _http_response_object_declare_default_properties(TSRMLS_D) DCL_CONST(long, "ETAG_SHA1", HTTP_ETAG_SHA1); DCL_CONST(long, "ETAG_CRC32", HTTP_ETAG_CRC32); +# ifdef HTTP_HAVE_HASH_EXT + DCL_CONST(long, "ETAG_SHA256", HTTP_ETAG_SHA256); + DCL_CONST(long, "ETAG_SHA384", HTTP_ETAG_SHA384); + DCL_CONST(long, "ETAG_SHA512", HTTP_ETAG_SHA512); + DCL_CONST(long, "ETAG_RIPEMD128", HTTP_ETAG_RIPEMD128); + DCL_CONST(long, "ETAG_RIPEMD160", HTTP_ETAG_RIPEMD160); +# endif + # ifdef HTTP_HAVE_MHASH { int l, i, c = mhash_count(); diff --git a/php_http_cache_api.h b/php_http_cache_api.h index e6c0838..7017dfd 100644 --- a/php_http_cache_api.h +++ b/php_http_cache_api.h @@ -26,6 +26,13 @@ #include "php_http_api.h" #include "php_http_send_api.h" +#if defined(HAVE_HASH_EXT) && !defined(COMPILE_DL_HASH) && defined(HTTP_HAVE_HASH_EXT_INCLUDES) +# define HTTP_HAVE_HASH_EXT +# include "php_hash.h" +# include "php_hash_sha.h" +# include "php_hash_ripemd.h" +#endif + #ifdef HTTP_HAVE_MHASH # include #endif @@ -33,6 +40,13 @@ ZEND_EXTERN_MODULE_GLOBALS(http); typedef enum { +#ifdef HTTP_HAVE_HASH_EXT + HTTP_ETAG_RIPEMD160 = -8, + HTTP_ETAG_RIPEMD128 = -7, + HTTP_ETAG_SHA512 = -6, + HTTP_ETAG_SHA384 = -5, + HTTP_ETAG_SHA256 = -4, +#endif HTTP_ETAG_CRC32 = -3, HTTP_ETAG_MD5 = -2, HTTP_ETAG_SHA1 = -1, @@ -50,27 +64,31 @@ static void *http_etag_alloc_mhash_digest(size_t size) #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) { + static const char hexdigits[16] = "0123456789abcdef"; 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++ = hexdigits[digest[i] >> 4]; + *ptr++ = hexdigits[digest[i] & 0xF]; } *ptr = '\0'; return hex; } +#undef CASE_HTTP_ETAG_HASH +#define CASE_HTTP_ETAG_HASH(HASH) \ + case HTTP_ETAG_##HASH: \ + PHP_##HASH##Init(ctx = emalloc(sizeof(PHP_##HASH##_CTX))); \ + break; #define http_etag_init() _http_etag_init(TSRMLS_C) static inline void *_http_etag_init(TSRMLS_D) { void *ctx = NULL; long mode = HTTP_G(etag).mode; - + switch (mode) { case HTTP_ETAG_CRC32: @@ -78,16 +96,18 @@ static inline void *_http_etag_init(TSRMLS_D) *((uint *) ctx) = ~0; break; - case HTTP_ETAG_SHA1: - PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX))); - break; - - case HTTP_ETAG_MD5: +#ifdef HTTP_HAVE_HASH_EXT + CASE_HTTP_ETAG_HASH(RIPEMD160); + CASE_HTTP_ETAG_HASH(RIPEMD128); + CASE_HTTP_ETAG_HASH(SHA512); + CASE_HTTP_ETAG_HASH(SHA384); + CASE_HTTP_ETAG_HASH(SHA256); +#endif + CASE_HTTP_ETAG_HASH(SHA1); #ifndef HTTP_HAVE_MHASH default: #endif - PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX))); - break; + CASE_HTTP_ETAG_HASH(MD5); #ifdef HTTP_HAVE_MHASH default: @@ -101,12 +121,18 @@ static inline void *_http_etag_init(TSRMLS_D) return ctx; } +#undef CASE_HTTP_ETAG_HASH +#define CASE_HTTP_ETAG_HASH(HASH) \ + case HTTP_ETAG_##HASH: \ + if (*((PHP_##HASH##_CTX **) ctx_ptr)) { \ + efree(*((PHP_##HASH##_CTX **) ctx_ptr)); \ + *((PHP_##HASH##_CTX **) ctx_ptr) = NULL; \ + } \ + break; #define http_etag_free(cp) _http_etag_free((cp) TSRMLS_CC) static inline void _http_etag_free(void **ctx_ptr TSRMLS_DC) { - long mode = HTTP_G(etag).mode; - - switch (mode) + switch (HTTP_G(etag).mode) { case HTTP_ETAG_CRC32: if (*((uint **) ctx_ptr)) { @@ -114,23 +140,19 @@ static inline void _http_etag_free(void **ctx_ptr TSRMLS_DC) *((uint **) ctx_ptr) = NULL; } break; - - case HTTP_ETAG_SHA1: - if (*((PHP_SHA1_CTX **) ctx_ptr)) { - efree(*((PHP_SHA1_CTX **) ctx_ptr)); - *((PHP_SHA1_CTX **) ctx_ptr) = NULL; - } - break; - - case HTTP_ETAG_MD5: + +#ifdef HTTP_HAVE_HASH_EXT + CASE_HTTP_ETAG_HASH(RIPEMD160); + CASE_HTTP_ETAG_HASH(RIPEMD128); + CASE_HTTP_ETAG_HASH(SHA512); + CASE_HTTP_ETAG_HASH(SHA384); + CASE_HTTP_ETAG_HASH(SHA256); +#endif + CASE_HTTP_ETAG_HASH(SHA1); #ifndef HTTP_HAVE_MHASH default: #endif - if (*((PHP_MD5_CTX **) ctx_ptr)) { - efree(*((PHP_MD5_CTX **) ctx_ptr)); - *((PHP_MD5_CTX **) ctx_ptr) = NULL; - } - break; + CASE_HTTP_ETAG_HASH(MD5); #ifdef HTTP_HAVE_MHASH default: @@ -144,11 +166,17 @@ static inline void _http_etag_free(void **ctx_ptr TSRMLS_DC) } } +#undef CASE_HTTP_ETAG_HASH +#define CASE_HTTP_ETAG_HASH(HASH, len) \ + case HTTP_ETAG_##HASH##: \ + PHP_##HASH##Final(digest, *((PHP_##HASH##_CTX **) ctx_ptr)); \ + etag = http_etag_digest(digest, len); \ + break; #define http_etag_finish(c) _http_etag_finish((c) TSRMLS_CC) static inline char *_http_etag_finish(void **ctx_ptr TSRMLS_DC) { char *etag = NULL; - unsigned char digest[20]; + unsigned char digest[128]; long mode = HTTP_G(etag).mode; switch (mode) @@ -157,19 +185,19 @@ static inline char *_http_etag_finish(void **ctx_ptr TSRMLS_DC) **((uint **) ctx_ptr) = ~**((uint **) ctx_ptr); etag = http_etag_digest(*((const unsigned char **) ctx_ptr), sizeof(uint)); break; - - case HTTP_ETAG_SHA1: - PHP_SHA1Final(digest, *((PHP_SHA1_CTX **) ctx_ptr)); - etag = http_etag_digest(digest, 20); - break; - - case HTTP_ETAG_MD5: + +#ifdef HTTP_HAVE_HASH_EXT + CASE_HTTP_ETAG_HASH(RIPEMD160, 20); + CASE_HTTP_ETAG_HASH(RIPEMD128, 16); + CASE_HTTP_ETAG_HASH(SHA512, 64); + CASE_HTTP_ETAG_HASH(SHA384, 48); + CASE_HTTP_ETAG_HASH(SHA256, 32); +#endif + CASE_HTTP_ETAG_HASH(SHA1, 20); #ifndef HTTP_HAVE_MHASH default: #endif - PHP_MD5Final(digest, *((PHP_MD5_CTX **) ctx_ptr)); - etag = http_etag_digest(digest, 16); - break; + CASE_HTTP_ETAG_HASH(MD5, 16); #ifdef HTTP_HAVE_MHASH default: @@ -189,10 +217,15 @@ static inline char *_http_etag_finish(void **ctx_ptr TSRMLS_DC) return etag; } +#undef CASE_HTTP_ETAG_HASH +#define CASE_HTTP_ETAG_HASH(HASH) \ + case HTTP_ETAG_##HASH: \ + PHP_##HASH##Update(ctx, (const unsigned char *) data_ptr, data_len); \ + break; #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")) + switch (HTTP_G(etag).mode) { case HTTP_ETAG_CRC32: { @@ -205,16 +238,18 @@ static inline void _http_etag_update(void *ctx, const char *data_ptr, size_t dat } break; - case HTTP_ETAG_SHA1: - PHP_SHA1Update(ctx, (const unsigned char *) data_ptr, data_len); - break; - - case HTTP_ETAG_MD5: +#ifdef HTTP_HAVE_HASH_EXT + CASE_HTTP_ETAG_HASH(RIPEMD160); + CASE_HTTP_ETAG_HASH(RIPEMD128); + CASE_HTTP_ETAG_HASH(SHA512); + CASE_HTTP_ETAG_HASH(SHA384); + CASE_HTTP_ETAG_HASH(SHA256); +#endif + CASE_HTTP_ETAG_HASH(SHA1); #ifndef HTTP_HAVE_MHASH default: #endif - PHP_MD5Update(ctx, (const unsigned char *) data_ptr, data_len); - break; + CASE_HTTP_ETAG_HASH(MD5); #ifdef HTTP_HAVE_MHASH default: diff --git a/tests/etag_mode_005.phpt b/tests/etag_mode_005.phpt new file mode 100644 index 0000000..cb15962 --- /dev/null +++ b/tests/etag_mode_005.phpt @@ -0,0 +1,24 @@ +--TEST-- +ext/hash etag +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Content-type: %s +X-Powered-By: PHP/%s +Cache-Control: private, must-revalidate, max-age=0 +Accept-Ranges: bytes +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb" +Content-Length: 4 + +abc diff --git a/tests/etag_mode_015.phpt b/tests/etag_mode_015.phpt new file mode 100644 index 0000000..d156bb9 --- /dev/null +++ b/tests/etag_mode_015.phpt @@ -0,0 +1,22 @@ +--TEST-- +ob ext/hash etag +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Content-type: %s +X-Powered-By: PHP/%s +Cache-Control: private, must-revalidate, max-age=0 +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb" + +abc diff --git a/tests/etag_mode_035.phpt b/tests/etag_mode_035.phpt new file mode 100644 index 0000000..1cd9430 --- /dev/null +++ b/tests/etag_mode_035.phpt @@ -0,0 +1,24 @@ +--TEST-- +ext/hash etag +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +X-Powered-By: PHP/%s +Cache-Control: private, must-revalidate, max-age=0 +Accept-Ranges: bytes +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb" +Content-Length: 4 +Content-type: %s + +abc diff --git a/tests/etag_mode_045.phpt b/tests/etag_mode_045.phpt new file mode 100644 index 0000000..b4c5dd6 --- /dev/null +++ b/tests/etag_mode_045.phpt @@ -0,0 +1,22 @@ +--TEST-- +ob ext/hash etag +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +X-Powered-By: PHP/%s +Cache-Control: private, must-revalidate, max-age=0 +ETag: "edeaaff3f1774ad2888673770c6d64097e391bc362d7d6fb34982ddf0efd18cb" +Content-type: %s + +abc -- 2.30.2