[PATCH] Passthrough MD5/SHA1 calculation of uploaded files
| From: | David Santinoli | Date: | Mon, 07 Jul 2003 16:21:23 +0000 |
| Subject: | [PATCH] Passthrough MD5/SHA1 calculation of uploaded files | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-3289@lists.php.net to get a copy of this message | ||
Hi,
I'm submitting a patch (previously sent to php-dev as suggested in
the [obsolete?] README.SUBMITTING_PATCH) to perform "on the fly"
MD5/SHA1 digest calculation of a file uploaded via the HTTP POST method.
Since it is not uncommon for applications to require some digest of a
freshly uploaded file, doing the math directly in the buffer where the
file is being read can save some time.
Digest calculation is triggered by setting the special input fields
COMPUTE_MD5 and/or COMPUTE_SHA1 to a non-zero value:
<input type="hidden" name="COMPUTE_SHA1" value="1">
(note that these assignments must precede the
<input type="file" name=...> field, as in the MAX_FILE_SIZE case.)
The result is found in the special variables
$_FILES[userfile]["md5"] and $_FILES[userfile]["sha1"].
These variables are defined only upon request of the corresponding
digest.
The patch was produced against rfc1867.c v1.137, but applies to the
current CVS file (v1.141) as well.
Cheers,
David
--
David Santinoli, Milano + <david@santinoli.com>
Independent Linux/Unix consultant + http://www.santinoli.com
--- rfc1867.c.cvs 2003-06-25 16:54:28.000000000 +0200 +++ rfc1867.c 2003-06-25 16:58:40.000000000 +0200 @@ -32,6 +32,8 @@ #include "php_globals.h" #include "php_variables.h" #include "rfc1867.h" +#include "ext/standard/md5.h" +#include "ext/standard/sha1.h" #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) #include "ext/mbstring/mbstring.h" @@ -697,6 +699,13 @@ zval *array_ptr = (zval *) arg; FILE *fp; zend_llist header; + int compute_md5=0, compute_sha1=0; + PHP_MD5_CTX md5_context; + unsigned char md5_digest[16]; + char md5_string[33]; + PHP_SHA1_CTX sha1_context; + unsigned char sha1_digest[20]; + char sha1_string[41]; if (SG(request_info).content_length > SG(post_max_size)) { sapi_module.sapi_error(E_WARNING, "POST Content-Length of %d bytes exceeds the limit of %d bytes", SG(request_info).content_length, SG(post_max_size)); @@ -809,6 +818,10 @@ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); if (!strcasecmp(param, "MAX_FILE_SIZE")) { max_file_size = atol(value); + } else if (!strcasecmp(param, "COMPUTE_MD5")) { + compute_md5 = atol(value); + } else if (!strcasecmp(param, "COMPUTE_SHA1")) { + compute_sha1 = atol(value); } efree(param); @@ -859,6 +872,14 @@ cancel_upload = UPLOAD_ERROR_D; } + if (compute_md5) { + PHP_MD5Init(&md5_context); + } + + if (compute_sha1) { + PHP_SHA1Init(&sha1_context); + } + while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC))) { if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) { @@ -869,6 +890,13 @@ cancel_upload = UPLOAD_ERROR_B; } else if (blen > 0) { wlen = fwrite(buff, 1, blen, fp); + + if (compute_md5) { + PHP_MD5Update(&md5_context, buff, blen); + } + if (compute_sha1) { + PHP_SHA1Update(&sha1_context, buff, blen); + } if (wlen < blen) { sapi_module.sapi_error(E_WARNING, "Only %d bytes were written, expected to write %ld", wlen, blen); @@ -880,6 +908,15 @@ } fclose(fp); + if (compute_md5) { + PHP_MD5Final(md5_digest, &md5_context); + make_digest(md5_string, md5_digest); + } + if (compute_sha1) { + PHP_SHA1Final(sha1_digest, &sha1_context); + make_digest(sha1_string, sha1_digest); + } + #ifdef DEBUG_FILE_UPLOAD if(strlen(filename) > 0 && total_bytes == 0) { sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename); @@ -1014,6 +1051,26 @@ add_protected_variable(lbuf TSRMLS_CC); register_http_post_files_variable(lbuf, temp_filename, http_post_files, 1 TSRMLS_CC); + /* Add $foo[md5] */ + if (!cancel_upload && compute_md5) { + if (is_arr_upload) { + sprintf(lbuf, "%s[md5][%s]", abuf, array_index); + } else { + sprintf(lbuf, "%s[md5]", param); + } + register_http_post_files_variable(lbuf, md5_string, http_post_files, 0 TSRMLS_CC); + } + + /* Add $foo[sha1] */ + if (!cancel_upload && compute_sha1) { + if (is_arr_upload) { + sprintf(lbuf, "%s[sha1][%s]", abuf, array_index); + } else { + sprintf(lbuf, "%s[sha1]", param); + } + register_http_post_files_variable(lbuf, sha1_string, http_post_files, 0 TSRMLS_CC); + } + PG(magic_quotes_gpc) = magic_quotes_gpc; {
--- rfc1867.c.cvs 2003-06-25 16:54:28.000000000 +0200 +++ rfc1867.c 2003-06-25 16:58:40.000000000 +0200 @@ -32,6 +32,8 @@ #include "php_globals.h" #include "php_variables.h" #include "rfc1867.h" +#include "ext/standard/md5.h" +#include "ext/standard/sha1.h" #if HAVE_MBSTRING && !defined(COMPILE_DL_MBSTRING) #include "ext/mbstring/mbstring.h" @@ -697,6 +699,13 @@ zval *array_ptr = (zval *) arg; FILE *fp; zend_llist header; + int compute_md5=0, compute_sha1=0; + PHP_MD5_CTX md5_context; + unsigned char md5_digest[16]; + char md5_string[33]; + PHP_SHA1_CTX sha1_context; + unsigned char sha1_digest[20]; + char sha1_string[41]; if (SG(request_info).content_length > SG(post_max_size)) { sapi_module.sapi_error(E_WARNING, "POST Content-Length of %d bytes exceeds the limit of %d bytes", SG(request_info).content_length, SG(post_max_size)); @@ -809,6 +818,10 @@ safe_php_register_variable(param, value, array_ptr, 0 TSRMLS_CC); if (!strcasecmp(param, "MAX_FILE_SIZE")) { max_file_size = atol(value); + } else if (!strcasecmp(param, "COMPUTE_MD5")) { + compute_md5 = atol(value); + } else if (!strcasecmp(param, "COMPUTE_SHA1")) { + compute_sha1 = atol(value); } efree(param); @@ -859,6 +872,14 @@ cancel_upload = UPLOAD_ERROR_D; } + if (compute_md5) { + PHP_MD5Init(&md5_context); + } + + if (compute_sha1) { + PHP_SHA1Init(&sha1_context); + } + while (!cancel_upload && (blen = multipart_buffer_read(mbuff, buff, sizeof(buff) TSRMLS_CC))) { if (PG(upload_max_filesize) > 0 && total_bytes > PG(upload_max_filesize)) { @@ -869,6 +890,13 @@ cancel_upload = UPLOAD_ERROR_B; } else if (blen > 0) { wlen = fwrite(buff, 1, blen, fp); + + if (compute_md5) { + PHP_MD5Update(&md5_context, buff, blen); + } + if (compute_sha1) { + PHP_SHA1Update(&sha1_context, buff, blen); + } if (wlen < blen) { sapi_module.sapi_error(E_WARNING, "Only %d bytes were written, expected to write %ld", wlen, blen); @@ -880,6 +908,15 @@ } fclose(fp); + if (compute_md5) { + PHP_MD5Final(md5_digest, &md5_context); + make_digest(md5_string, md5_digest); + } + if (compute_sha1) { + PHP_SHA1Final(sha1_digest, &sha1_context); + make_digest(sha1_string, sha1_digest); + } + #ifdef DEBUG_FILE_UPLOAD if(strlen(filename) > 0 && total_bytes == 0) { sapi_module.sapi_error(E_WARNING, "Uploaded file size 0 - file [%s=%s] not saved", param, filename); @@ -1014,6 +1051,26 @@ add_protected_variable(lbuf TSRMLS_CC); register_http_post_files_variable(lbuf, temp_filename, http_post_files, 1 TSRMLS_CC); + /* Add $foo[md5] */ + if (!cancel_upload && compute_md5) { + if (is_arr_upload) { + sprintf(lbuf, "%s[md5][%s]", abuf, array_index); + } else { + sprintf(lbuf, "%s[md5]", param); + } + register_http_post_files_variable(lbuf, md5_string, http_post_files, 0 TSRMLS_CC); + } + + /* Add $foo[sha1] */ + if (!cancel_upload && compute_sha1) { + if (is_arr_upload) { + sprintf(lbuf, "%s[sha1][%s]", abuf, array_index); + } else { + sprintf(lbuf, "%s[sha1]", param); + } + register_http_post_files_variable(lbuf, sha1_string, http_post_files, 0 TSRMLS_CC); + } + PG(magic_quotes_gpc) = magic_quotes_gpc; {