fix problem when finishing a chunked encoding stream
[m6w6/ext-http] / php_http_etag.c
1 #include "php_http.h"
2
3 #include <ext/standard/crc32.h>
4 #include <ext/standard/sha1.h>
5 #include <ext/standard/md5.h>
6
7 PHP_HTTP_API void *php_http_etag_init(TSRMLS_D)
8 {
9 void *ctx = NULL;
10 char *mode = PHP_HTTP_G->env.etag_mode;
11
12 #ifdef PHP_HTTP_HAVE_HASH
13 const php_hash_ops *eho = NULL;
14
15 if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
16 ctx = emalloc(eho->context_size);
17 eho->hash_init(ctx);
18 } else
19 #endif
20 if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
21 ctx = emalloc(sizeof(uint));
22 *((uint *) ctx) = ~0;
23 } else if (mode && !strcasecmp(mode, "sha1")) {
24 PHP_SHA1Init(ctx = emalloc(sizeof(PHP_SHA1_CTX)));
25 } else {
26 PHP_MD5Init(ctx = emalloc(sizeof(PHP_MD5_CTX)));
27 }
28
29 return ctx;
30 }
31
32 PHP_HTTP_API char *php_http_etag_finish(void *ctx TSRMLS_DC)
33 {
34 unsigned char digest[128] = {0};
35 char *etag = NULL, *mode = PHP_HTTP_G->env.etag_mode;
36
37 #ifdef PHP_HTTP_HAVE_HASH
38 const php_hash_ops *eho = NULL;
39
40 if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
41 eho->hash_final(digest, ctx);
42 etag = php_http_etag_digest(digest, eho->digest_size);
43 } else
44 #endif
45 if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
46 *((uint *) ctx) = ~*((uint *) ctx);
47 etag = php_http_etag_digest((const unsigned char *) ctx, sizeof(uint));
48 } else if (mode && (!strcasecmp(mode, "sha1"))) {
49 PHP_SHA1Final(digest, ctx);
50 etag = php_http_etag_digest(digest, 20);
51 } else {
52 PHP_MD5Final(digest, ctx);
53 etag = php_http_etag_digest(digest, 16);
54 }
55 efree(ctx);
56
57 return etag;
58 }
59
60 PHP_HTTP_API size_t php_http_etag_update(void *ctx, const char *data_ptr, size_t data_len TSRMLS_DC)
61 {
62 char *mode = PHP_HTTP_G->env.etag_mode;
63 #ifdef PHP_HTTP_HAVE_HASH
64 const php_hash_ops *eho = NULL;
65
66 if (mode && (eho = php_hash_fetch_ops(mode, strlen(mode)))) {
67 eho->hash_update(ctx, (const unsigned char *) data_ptr, data_len);
68 } else
69 #endif
70 if (mode && ((!strcasecmp(mode, "crc32")) || (!strcasecmp(mode, "crc32b")))) {
71 uint i, c = *((uint *) ctx);
72 for (i = 0; i < data_len; ++i) {
73 CRC32(c, data_ptr[i]);
74 }
75 *((uint *)ctx) = c;
76 } else if (mode && (!strcasecmp(mode, "sha1"))) {
77 PHP_SHA1Update(ctx, (const unsigned char *) data_ptr, data_len);
78 } else {
79 PHP_MD5Update(ctx, (const unsigned char *) data_ptr, data_len);
80 }
81
82 return data_len;
83 }
84