/* * mod_example_2.c: Example module for Apache HTTP Server 2.4 * This module calculates and displays MD5 or SHA1 digests of files. */ #include "httpd.h" #include "http_config.h" #include "http_protocol.h" #include "ap_config.h" #include "apr_md5.h" #include "apr_sha1.h" #include "apr_file_io.h" #include "apr_tables.h" static int example_handler(request_rec *r) { int rc, exists; apr_finfo_t finfo; apr_file_t *file; char *filename; char buffer[256]; apr_size_t readBytes; int n; apr_table_t *GET; apr_array_header_t *POST; const char *digestType; /* Check that the "example-handler" handler is being called. */ if (!r->handler || strcmp(r->handler, "example-handler")) return (DECLINED); /* Figure out which file is being requested by removing the .sum from it */ filename = apr_pstrdup(r->pool, r->filename); filename[strlen(filename)-4] = 0; /* Cut off the last 4 characters. */ /* Figure out if the file we request a sum on exists and isn't a directory */ rc = apr_stat(&finfo, filename, APR_FINFO_MIN, r->pool); if (rc == APR_SUCCESS) { exists = ( (finfo.filetype != APR_NOFILE) && !(finfo.filetype & APR_DIR) ); if (!exists) return HTTP_NOT_FOUND; /* Return a 404 if not found. */ } /* If apr_stat failed, we're probably not allowed to check this file. */ else return HTTP_FORBIDDEN; /* Parse the GET and, optionally, the POST data sent to us */ ap_args_to_table(r, &GET); ap_parse_form_data(r, NULL, &POST, -1, 8192); /* Set the appropriate content type */ ap_set_content_type(r, "text/html"); /* Print a title and some general information */ ap_rprintf(r, "

Information on %s:

", filename); ap_rprintf(r, "Size: %" APR_OFF_T_FMT " bytes
", finfo.size); /* Get the digest type the client wants to see */ digestType = apr_table_get(GET, "digest"); if (!digestType) digestType = "MD5"; rc = apr_file_open(&file, filename, APR_READ, APR_OS_DEFAULT, r->pool); if (rc == APR_SUCCESS) { /* Are we trying to calculate the MD5 or the SHA1 digest? */ if (!strcasecmp(digestType, "md5")) { /* Calculate the MD5 sum of the file */ union { char chr[16]; uint32_t num[4]; } digest; apr_md5_ctx_t md5; apr_md5_init(&md5); readBytes = 256; while ( apr_file_read(file, buffer, &readBytes) == APR_SUCCESS ) { apr_md5_update(&md5, buffer, readBytes); } apr_md5_final(digest.chr, &md5); /* Print out the MD5 digest */ ap_rputs("MD5: ", r); for (n = 0; n < APR_MD5_DIGESTSIZE/4; n++) { ap_rprintf(r, "%08x", digest.num[n]); } ap_rputs("", r); /* Print a link to the SHA1 version */ ap_rputs("
View the SHA1 hash instead", r); } else { /* Calculate the SHA1 sum of the file */ union { char chr[20]; uint32_t num[5]; } digest; apr_sha1_ctx_t sha1; apr_sha1_init(&sha1); readBytes = 256; while ( apr_file_read(file, buffer, &readBytes) == APR_SUCCESS ) { apr_sha1_update(&sha1, buffer, readBytes); } apr_sha1_final(digest.chr, &sha1); /* Print out the SHA1 digest */ ap_rputs("SHA1: ", r); for (n = 0; n < APR_SHA1_DIGESTSIZE/4; n++) { ap_rprintf(r, "%08x", digest.num[n]); } ap_rputs("", r); /* Print a link to the MD5 version */ ap_rputs("
View the MD5 hash instead", r); } apr_file_close(file); } /* Let the server know that we responded to this request. */ return OK; } static void register_hooks(apr_pool_t *pool) { /* Create a hook in the request handler, so we get called when a request arrives */ ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST); } AP_DECLARE_MODULE(example) = { STANDARD20_MODULE_STUFF, NULL, NULL, NULL, NULL, NULL, register_hooks /* Our hook registering function */ };