blob: eaf6424dd23135b0439c8158183b5c9a7572d307 [file] [log] [blame]
/*
* 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, "<h2>Information on %s:</h2>", filename);
ap_rprintf(r, "<b>Size:</b> %" APR_OFF_T_FMT " bytes<br/>", 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("<b>MD5: </b><code>", r);
for (n = 0; n < APR_MD5_DIGESTSIZE/4; n++) {
ap_rprintf(r, "%08x", digest.num[n]);
}
ap_rputs("</code>", r);
/* Print a link to the SHA1 version */
ap_rputs("<br/><a href='?digest=sha1'>View the SHA1 hash instead</a>", 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("<b>SHA1: </b><code>", r);
for (n = 0; n < APR_SHA1_DIGESTSIZE/4; n++) {
ap_rprintf(r, "%08x", digest.num[n]);
}
ap_rputs("</code>", r);
/* Print a link to the MD5 version */
ap_rputs("<br/><a href='?digest=md5'>View the MD5 hash instead</a>", 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 */
};