From 30888cbd1d7896066bf090cac80b8c05e0ea327d Mon Sep 17 00:00:00 2001
From: Daniel Gruno
-module AP_MODULE_DECLARE_DATA example_module
@@ -184,18 +185,18 @@ definition will look like this:
+=
-{
- STANDARD20_MODULE_STUFF,
- create_dir_conf, /* Per-directory configuration handler */
- merge_dir_conf, /* Merge handler for per-directory configurations */
- create_svr_conf, /* Per-server configuration handler */
- merge_svr_conf, /* Merge handler for per-server configurations */
- directives, /* Any directives we may have for httpd */
- register_hooks /* Our hook registering function */
-};
-
+module AP_MODULE_DECLARE_DATA example_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_dir_conf, /* Per-directory configuration handler */
+ merge_dir_conf, /* Merge handler for per-directory configurations */
+ create_svr_conf, /* Per-server configuration handler */
+ merge_svr_conf, /* Merge handler for per-server configurations */
+ directives, /* Any directives we may have for httpd */
+ register_hooks /* Our hook registering function */
+};
+
module AP_MODULE_DECLARE_DATA example_module =
{
STANDARD20_MODULE_STUFF,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- register_hooks
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ register_hooks /* Our hook registering function */
};
-/* Our hook registering function */
-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);
-}
-
+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);
+}
+
@@ -264,27 +265,27 @@ In C code, our example handler will now look like this:
-
-static int example_handler(request_rec *r)
-{
- /* First off, we need to check if this is a call for the "example-handler" handler.
- * If it is, we accept it and do our things, if not, we simply return DECLINED,
- * and the server will try somewhere else.
- */
- if (!r->handler || strcmp(r->handler, "example-handler")) return (DECLINED);
+
+static int example_handler(request_rec *r)
+{
+ /* First off, we need to check if this is a call for the "example-handler" handler.
+ * If it is, we accept it and do our things, if not, we simply return DECLINED,
+ * and the server will try somewhere else.
+ */
+ if (!r->handler || strcmp(r->handler, "example-handler")) return (DECLINED);
- /* Now that we are handling this request, we'll write out "Hello, world!" to the client.
- * To do so, we must first set the appropriate content type, followed by our output.
- */
- ap_set_content_type(r, "text/html");
- ap_rprintf(r, "Hello, world!");
+ /* Now that we are handling this request, we'll write out "Hello, world!" to the client.
+ * To do so, we must first set the appropriate content type, followed by our output.
+ */
+ ap_set_content_type(r, "text/html");
+ ap_rprintf(r, "Hello, world!");
- /* Lastly, we must tell the server that we took care of this request and everything went fine.
- * We do so by simply returning the value OK to the server.
- */
- return OK;
-}
-
+ /* Lastly, we must tell the server that we took care of this request and everything went fine.
+ * We do so by simply returning the value OK to the server.
+ */
+ return OK;
+}
+
@@ -305,14 +306,14 @@ HTTP request and respond accordingly.
Some key elements of the
request_req structure are:
r->handler (char*): Contains the name of the handler the server is currently asking to do the handling of this requestr->method (char*): Contains the HTTP method being used, f.x. GET or POSTr->filename (char*): Contains the translated filename the client is requestingr->args (char*): Contains the query string of the request, if anyr->headers_in (apr_table_t*): Contains all the headers sent by the clientr->connection (conn_rec*): A record containing information about the current connectionr->useragent_ip (char*): The IP address of the client connecting to usr->pool (apr_pool_t*): The memory pool of this request. We'll discuss this in the "
+r->handler (char*): Contains the name of the handler the server is currently asking to do the handling of this requestr->method (char*): Contains the HTTP method being used, f.x. GET or POSTr->filename (char*): Contains the translated filename the client is requestingr->args (char*): Contains the query string of the request, if anyr->headers_in (apr_table_t*): Contains all the headers sent by the clientr->connection (conn_rec*): A record containing information about the current connectionr->useragent_ip (char*): The IP address of the client connecting to usr->pool (apr_pool_t*): The memory pool of this request. We'll discuss this in the "
Memory management" chapter.
@@ -327,30 +328,30 @@ Let's try out some of these variables in another example handler:
-static int example_handler(request_rec *r)
-{
- /* Set the appropriate content type */
- ap_set_content_type(r, "text/html");
-
- /* Print out the IP address of the client connecting to us: */
- ap_rprintf(r, "<h2>Hello, %s!</h2>", r->useragent_ip);
+
+static int example_handler(request_rec *r)
+{
+ /* Set the appropriate content type */
+ ap_set_content_type(r, "text/html");
+
+ /* Print out the IP address of the client connecting to us: */
+ ap_rprintf(r, "<h2>Hello, %s!</h2>", r->useragent_ip);
- /* If we were reached through a GET or a POST request, be happy, else sad. */
- if ( !strcmp(r->method, "POST") || !strcmp(r->method, "GET") ) {
- ap_rputs("You used a GET or a POST method, that makes us happy!<br>", r);
- }
- else {
- ap_rputs("You did not use POST or GET, that makes us sad :(<br>", r);
- }
-
- /* Lastly, if there was a query string, let's print that too! */
- if (r->args) {
- ap_rprintf(r, "Your query string was: %s", r->args);
- }
- return OK;
-}
-
+ /* If we were reached through a GET or a POST request, be happy, else sad. */
+ if ( !strcmp(r->method, "POST") || !strcmp(r->method, "GET") ) {
+ ap_rputs("You used a GET or a POST method, that makes us happy!<br/>", r);
+ }
+ else {
+ ap_rputs("You did not use POST or GET, that makes us sad :(<br/>", r);
+ }
+
+ /* Lastly, if there was a query string, let's print that too! */
+ if (r->args) {
+ ap_rprintf(r, "Your query string was: %s", r->args);
+ }
+ return OK;
+}
+
@@ -366,13 +367,13 @@ status code, for example:
-
-static int example_handler(request_rec *r)
-{
- /* Return 404: Not found */
- return HTTP_NOT_FOUND;
-}
-
+static int example_handler(request_rec *r)
+{
+ /* Return 404: Not found */
+ return HTTP_NOT_FOUND;
+}
+
@@ -416,7 +417,7 @@ the next, without informing other handlers. -
ap_rputs("Hello, world!", r);
ap_rputs("Hello, world!", r);
@@ -428,7 +429,7 @@ the next, without informing other handlers.
-ap_rprintf(r, "Hello, %s!", r->useragent_ip);
ap_rprintf(r, "Hello, %s!", r->useragent_ip);@@ -439,7 +440,7 @@ the next, without informing other handlers. -
ap_set_content_type(r, "text/plain"); /* force a raw text output */
ap_set_content_type(r, "text/plain"); /* force a raw text output */@@ -460,7 +461,7 @@ clean up after yourself - pretty neat, huh?
In our module, we will primarily be allocating memory for each request, so
-it's appropriate to use the r->pool
+it's appropriate to use the r->pool
reference when creating new objects. A few of the functions for allocating
memory within a pool are:
sprintf, ex
-
-static int example_handler(request_rec *r)
-{
- const char* original = "You can't edit this!";
- char* copy;
- int* integers;
+
+static int example_handler(request_rec *r)
+{
+ const char* original = "You can't edit this!";
+ char* copy;
+ int* integers;
- /* Allocate space for 10 integer values and set them all to zero. */
- integers = apr_pcalloc(r->pool, sizeof(int)*10);
+ /* Allocate space for 10 integer values and set them all to zero. */
+ integers = apr_pcalloc(r->pool, sizeof(int)*10);
- /* Create a copy of the 'original' variable that we can edit. */
- copy = apr_pstrdup(r->pool, original);
- return OK;
-}
-
+ /* Create a copy of the 'original' variable that we can edit. */
+ copy = apr_pstrdup(r->pool, original);
+ return OK;
+}
+
@@ -505,15 +506,15 @@ function to sort it out:
-
-static void register_hooks(apr_pool_t *pool)
-{
- /* Call a function that initializes some stuff */
- example_init_function(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);
-}
-
+static void register_hooks(apr_pool_t *pool)
+{
+ /* Call a function that initializes some stuff */
+ example_init_function(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);
+}
+
@@ -544,13 +545,13 @@ POST data is four simple lines: -
+
apr_table_t *GET;
apr_array_header_t *POST;
ap_args_to_table(r, &GET);
-ap_parse_form_data(r, NULL, &POST, -1, 8192);
-
+ap_parse_form_data(r, NULL, &POST, -1, 8192);
+
@@ -561,14 +562,13 @@ GET. To extract this value, we need only perform a simple operation: -
-/* Get the "digest" key from the query string, if any. */
-const char *digestType = apr_table_get(GET, "digest");
-
-/* If no key was returned, we will set a default value instead. */
-if (!digestType) digestType = "sha1";
+
+/* Get the "digest" key from the query string, if any. */ +const char *digestType = apr_table_get(GET, "digest"); - +/* If no key was returned, we will set a default value instead. */ +if (!digestType) digestType = "sha1"; +
@@ -588,119 +588,116 @@ out the MD5 or SHA1 digest of files: -
-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;
+
+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);
+ /* 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 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;
+ /* 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 */
+ /* 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);
+ 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");
+ /* 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> %u bytes<br/>", finfo.size);
+ /* Print a title and some general information */
+ ap_rprintf(r, "<h2>Information on %s:</h2>", filename);
+ ap_rprintf(r, "<b>Size:</b> %u bytes<br/>", finfo.size);
- /* Get the digest type the client wants to see */
- digestType = apr_table_get(GET, "digest");
- if (!digestType) digestType = "MD5";
+ /* 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) {
+ 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);
+ /* 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 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 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);
+ /* 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;
-}
-
+ }
+ /* Let the server know that we responded to this request. */
+ return OK;
+}
+
@@ -743,13 +740,13 @@ that parses the parameters given and sets up a configuration accordingly. -
-typedef struct {
- int enabled; /* Enable or disable our module */
- const char *path; /* Some path to...something */
- int typeOfAction; /* 1 means action A, 2 means action B and so on */
-} example_config;
-
+typedef struct {
+ int enabled; /* Enable or disable our module */
+ const char *path; /* Some path to...something */
+ int typeOfAction; /* 1 means action A, 2 means action B and so on */
+} example_config;
+
@@ -760,46 +757,46 @@ values to their defaults:
-
-typedef struct {
- int enabled; /* Enable or disable our module */
- const char *path; /* Some path to...something */
- int typeOfAction; /* 1 means action A, 2 means action B and so on */
-} example_config;
-
-static example_config config;
-
-static int example_handler(request_rec *r)
-{
- if (!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
- ap_set_content_type(r, "text/plain");
- ap_rprintf(r, "Enabled: %u\n", config.enabled);
- ap_rprintf(r, "Path: %s\n", config.path);
- ap_rprintf(r, "TypeOfAction: %x\n", config.typeOfAction);
- return OK;
-}
-
-static void register_hooks(apr_pool_t *pool)
-{
- config.enabled = 1;
- config.path = "/foo/bar";
- config.typeOfAction = 0x00;
- ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
-}
-
-/* Define our module as an entity and assign a function for registering hooks */
-
-module AP_MODULE_DECLARE_DATA example_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* Per-directory configuration handler */
- NULL, /* Merge handler for per-directory configurations */
- NULL, /* Per-server configuration handler */
- NULL, /* Merge handler for per-server configurations */
- NULL, /* Any directives we may have for httpd */
- register_hooks /* Our hook registering function */
-};
-
+typedef struct {
+ int enabled; /* Enable or disable our module */
+ const char *path; /* Some path to...something */
+ int typeOfAction; /* 1 means action A, 2 means action B and so on */
+} example_config;
+
+static example_config config;
+
+static int example_handler(request_rec *r)
+{
+ if (!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
+ ap_set_content_type(r, "text/plain");
+ ap_rprintf(r, "Enabled: %u\n", config.enabled);
+ ap_rprintf(r, "Path: %s\n", config.path);
+ ap_rprintf(r, "TypeOfAction: %x\n", config.typeOfAction);
+ return OK;
+}
+
+static void register_hooks(apr_pool_t *pool)
+{
+ config.enabled = 1;
+ config.path = "/foo/bar";
+ config.typeOfAction = 0x00;
+ ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
+}
+
+/* Define our module as an entity and assign a function for registering hooks */
+
+module AP_MODULE_DECLARE_DATA example_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* Per-directory configuration handler */
+ NULL, /* Merge handler for per-directory configurations */
+ NULL, /* Per-server configuration handler */
+ NULL, /* Merge handler for per-server configurations */
+ NULL, /* Any directives we may have for httpd */
+ register_hooks /* Our hook registering function */
+};
+
@@ -827,18 +824,18 @@ reference to the configuration directives we want to register with the server:
-+
module AP_MODULE_DECLARE_DATA example_module =
{
STANDARD20_MODULE_STUFF,
- NULL, /* Per-directory configuration handler */
- NULL, /* Merge handler for per-directory configurations */
- NULL, /* Per-server configuration handler */
- NULL, /* Merge handler for per-server configurations */
- example_directives, /* Any directives we may have for httpd */
- register_hooks /* Our hook registering function */
+ NULL, /* Per-directory configuration handler */
+ NULL, /* Merge handler for per-directory configurations */
+ NULL, /* Per-server configuration handler */
+ NULL, /* Merge handler for per-server configurations */
+ example_directives, /* Any directives we may have for httpd */
+ register_hooks /* Our hook registering function */
};
-
+
@@ -850,15 +847,15 @@ will add a structure with three directives and a NULL at the end:
-+
static const command_rec example_directives[] =
{
- AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
- AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
- AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
- { NULL }
+ AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
+ AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
+ AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
+ { NULL }
};
-
+
@@ -896,35 +893,35 @@ exampleAction directive to accept two arguments, its C function also has an additional parameter defined:
-
-/* Handler for the "exambleEnabled" directive */
-const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
-{
- if(!strcasecmp(arg, "on")) config.enabled = 1;
- else config.enabled = 0;
- return NULL;
-}
-
-/* Handler for the "examplePath" directive */
-const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
-{
- config.path = arg;
- return NULL;
-}
-
-/* Handler for the "exampleAction" directive */
-/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
-/* and we store it in a bit-wise manner. */
-const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
-{
- if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
- else config.typeOfAction = 0x02;
+
+/* Handler for the "exambleEnabled" directive */
+const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
+{
+ if(!strcasecmp(arg, "on")) config.enabled = 1;
+ else config.enabled = 0;
+ return NULL;
+}
+
+/* Handler for the "examplePath" directive */
+const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
+{
+ config.path = arg;
+ return NULL;
+}
+
+/* Handler for the "exampleAction" directive */
+/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
+/* and we store it in a bit-wise manner. */
+const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
+{
+ if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
+ else config.typeOfAction = 0x02;
- if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
- else config.typeOfAction += 0x20;
- return NULL;
-}
-
+ if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
+ else config.typeOfAction += 0x20;
+ return NULL;
+}
+
@@ -936,120 +933,120 @@ we can assemble our module into one big file:
-
-/* mod_example_config_simple.c: */
-#include <stdio.h>
-#include "apr_hash.h"
-#include "ap_config.h"
-#include "ap_provider.h"
-#include "httpd.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_request.h"
-
-/*
- ==============================================================================
- Our configuration prototype and declaration:
- ==============================================================================
- */
-typedef struct {
- int enabled; /* Enable or disable our module */
- const char *path; /* Some path to...something */
- int typeOfAction; /* 1 means action A, 2 means action B and so on */
-} example_config;
-
-static example_config config;
-
-/*
- ==============================================================================
- Our directive handlers:
- ==============================================================================
- */
-/* Handler for the "exambleEnabled" directive */
-const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
-{
- if(!strcasecmp(arg, "on")) config.enabled = 1;
- else config.enabled = 0;
- return NULL;
-}
-
-/* Handler for the "examplePath" directive */
-const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
-{
- config.path = arg;
- return NULL;
-}
-
-/* Handler for the "exampleAction" directive */
-/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
-/* and we store it in a bit-wise manner. */
-const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
-{
- if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
- else config.typeOfAction = 0x02;
+
+/* mod_example_config_simple.c: */
+#include <stdio.h>
+#include "apr_hash.h"
+#include "ap_config.h"
+#include "ap_provider.h"
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+
+/*
+ ==============================================================================
+ Our configuration prototype and declaration:
+ ==============================================================================
+ */
+typedef struct {
+ int enabled; /* Enable or disable our module */
+ const char *path; /* Some path to...something */
+ int typeOfAction; /* 1 means action A, 2 means action B and so on */
+} example_config;
+
+static example_config config;
+
+/*
+ ==============================================================================
+ Our directive handlers:
+ ==============================================================================
+ */
+/* Handler for the "exambleEnabled" directive */
+const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
+{
+ if(!strcasecmp(arg, "on")) config.enabled = 1;
+ else config.enabled = 0;
+ return NULL;
+}
+
+/* Handler for the "examplePath" directive */
+const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
+{
+ config.path = arg;
+ return NULL;
+}
+
+/* Handler for the "exampleAction" directive */
+/* Let's pretend this one takes one argument (file or db), and a second (deny or allow), */
+/* and we store it in a bit-wise manner. */
+const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char* arg2)
+{
+ if(!strcasecmp(arg1, "file")) config.typeOfAction = 0x01;
+ else config.typeOfAction = 0x02;
- if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
- else config.typeOfAction += 0x20;
- return NULL;
-}
-
-/*
- ==============================================================================
- The directive structure for our name tag:
- ==============================================================================
- */
-static const command_rec example_directives[] =
-{
- AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
- AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
- AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
- { NULL }
-};
-/*
- ==============================================================================
- Our module handler:
- ==============================================================================
- */
-static int example_handler(request_rec *r)
-{
- if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
- ap_set_content_type(r, "text/plain");
- ap_rprintf(r, "Enabled: %u\n", config.enabled);
- ap_rprintf(r, "Path: %s\n", config.path);
- ap_rprintf(r, "TypeOfAction: %x\n", config.typeOfAction);
- return OK;
-}
-
-/*
- ==============================================================================
- The hook registration function (also initializes the default config values):
- ==============================================================================
- */
-static void register_hooks(apr_pool_t *pool)
-{
- config.enabled = 1;
- config.path = "/foo/bar";
- config.typeOfAction = 3;
- ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
-}
-/*
- ==============================================================================
- Our module name tag:
- ==============================================================================
- */
-module AP_MODULE_DECLARE_DATA example_module =
-{
- STANDARD20_MODULE_STUFF,
- NULL, /* Per-directory configuration handler */
- NULL, /* Merge handler for per-directory configurations */
- NULL, /* Per-server configuration handler */
- NULL, /* Merge handler for per-server configurations */
- example_directives, /* Any directives we may have for httpd */
- register_hooks /* Our hook registering function */
-};
-
+ if(!strcasecmp(arg2, "deny")) config.typeOfAction += 0x10;
+ else config.typeOfAction += 0x20;
+ return NULL;
+}
+
+/*
+ ==============================================================================
+ The directive structure for our name tag:
+ ==============================================================================
+ */
+static const command_rec example_directives[] =
+{
+ AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
+ AP_INIT_TAKE1("examplePath", example_set_path, NULL, RSRC_CONF, "The path to whatever"),
+ AP_INIT_TAKE2("exampleAction", example_set_action, NULL, RSRC_CONF, "Special action value!"),
+ { NULL }
+};
+/*
+ ==============================================================================
+ Our module handler:
+ ==============================================================================
+ */
+static int example_handler(request_rec *r)
+{
+ if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
+ ap_set_content_type(r, "text/plain");
+ ap_rprintf(r, "Enabled: %u\n", config.enabled);
+ ap_rprintf(r, "Path: %s\n", config.path);
+ ap_rprintf(r, "TypeOfAction: %x\n", config.typeOfAction);
+ return OK;
+}
+
+/*
+ ==============================================================================
+ The hook registration function (also initializes the default config values):
+ ==============================================================================
+ */
+static void register_hooks(apr_pool_t *pool)
+{
+ config.enabled = 1;
+ config.path = "/foo/bar";
+ config.typeOfAction = 3;
+ ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
+}
+/*
+ ==============================================================================
+ Our module name tag:
+ ==============================================================================
+ */
+module AP_MODULE_DECLARE_DATA example_module =
+{
+ STANDARD20_MODULE_STUFF,
+ NULL, /* Per-directory configuration handler */
+ NULL, /* Merge handler for per-directory configurations */
+ NULL, /* Per-server configuration handler */
+ NULL, /* Merge handler for per-server configurations */
+ example_directives, /* Any directives we may have for httpd */
+ register_hooks /* Our hook registering function */
+};
+
@@ -1110,10 +1107,11 @@ directory or location in question? It does so by making one simple call:
-+
+example_config *config = (example_config*) ap_get_module_config(r->per_dir_config, &example_module); +-example_config *config = (example_config*) ap_get_module_config(
r->per_dir_config, &example_module);
-
+
That's it! Of course, a whole lot goes on behind the scenes, which we will discuss in this chapter, starting with how the server came to know what our @@ -1129,33 +1127,33 @@ variable that we can use to track which context configuration is being used by the server in various places:
-
-typedef struct {
- char context[256];
- char path[256];
- int typeOfAction;
- int enabled;
-} example_config;
-
+typedef struct {
+ char context[256];
+ char path[256];
+ int typeOfAction;
+ int enabled;
+} example_config;
+
Our handler for requests will also be modified, yet still very simple:
-
-static int example_handler(request_rec *r)
-{
- if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
- example_config *config = (example_config*) ap_get_module_config(r->per_dir_config, &example_module);
- ap_set_content_type(r, "text/plain");
- ap_rprintf("Enabled: %u\n", config->enabled);
- ap_rprintf("Path: %s\n", config->path);
- ap_rprintf("TypeOfAction: %x\n", config->typeOfAction);
- ap_rprintf("Context: %s\n", config->context);
- return OK;
-}
-
+static int example_handler(request_rec *r)
+{
+ if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
+ example_config *config = (example_config*) ap_get_module_config(r->per_dir_config, &example_module);
+ ap_set_content_type(r, "text/plain");
+ ap_rprintf("Enabled: %u\n", config->enabled);
+ ap_rprintf("Path: %s\n", config->path);
+ ap_rprintf("TypeOfAction: %x\n", config->typeOfAction);
+ ap_rprintf("Context: %s\n", config->context);
+ return OK;
+}
+
@@ -1168,9 +1166,9 @@ a directive required five elements be set:
-
-AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
-
+AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, RSRC_CONF, "Enable or disable mod_example"),
+
@@ -1191,18 +1189,18 @@ and managing our configurations. Since we have chosen the per-directory
per-directory creator and merger function reference in our tag:
-
-module AP_MODULE_DECLARE_DATA example_module =
-{
- STANDARD20_MODULE_STUFF,
- create_dir_conf, /* Per-directory configuration handler */
- merge_dir_conf, /* Merge handler for per-directory configurations */
- NULL, /* Per-server configuration handler */
- NULL, /* Merge handler for per-server configurations */
- directives, /* Any directives we may have for httpd */
- register_hooks /* Our hook registering function */
-};
-
+module AP_MODULE_DECLARE_DATA example_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_dir_conf, /* Per-directory configuration handler */
+ merge_dir_conf, /* Merge handler for per-directory configurations */
+ NULL, /* Per-server configuration handler */
+ NULL, /* Merge handler for per-server configurations */
+ directives, /* Any directives we may have for httpd */
+ register_hooks /* Our hook registering function */
+};
+
@@ -1216,20 +1214,20 @@ our first step is to make a function for creating new, blank
configurations. We do so by creating the function we just referenced in
our name tag as the Per-directory configuration handler:
-
-void* example_create_dir_conf(apr_pool_t* pool, char* context) {
- context = context ? context : "(undefined context)";
- example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
- if(cfg) {
- /* Set some default values */
- strcpy(cfg->context, x);
- cfg->enabled = 0;
- cfg->path = "/foo/bar";
- cfg->typeOfAction = 0x11;
- }
- return cfg;
-}
-
+void* example_create_dir_conf(apr_pool_t* pool, char* context) {
+ context = context ? context : "(undefined context)";
+ example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
+ if(cfg) {
+ /* Set some default values */
+ strcpy(cfg->context, x);
+ cfg->enabled = 0;
+ cfg->path = "/foo/bar";
+ cfg->typeOfAction = 0x11;
+ }
+ return cfg;
+}
+
@@ -1272,19 +1270,19 @@ two configurations and decide how they are to be merged:
-
-void* merge_dir_conf(apr_pool_t* pool, void* BASE, void* ADD) {
- example_config* base = (example_config *) BASE ;
- example_config* add = (example_config *) ADD ;
- example_config* conf = (example_config *) create_dir_conf(pool, "Merged configuration");
+
+void* merge_dir_conf(apr_pool_t* pool, void* BASE, void* ADD) {
+ example_config* base = (example_config *) BASE ;
+ example_config* add = (example_config *) ADD ;
+ example_config* conf = (example_config *) create_dir_conf(pool, "Merged configuration");
- conf->enabled = ( add->enabled == 0 ) ? base->enabled : add->enabled ;
- conf->typeOfAction = add->typeOfAction ? add->typeOfAction : base->typeOfAction;
- strcpy(conf->path, strlen(add->path) ? add->path : base->path);
+ conf->enabled = ( add->enabled == 0 ) ? base->enabled : add->enabled ;
+ conf->typeOfAction = add->typeOfAction ? add->typeOfAction : base->typeOfAction;
+ strcpy(conf->path, strlen(add->path) ? add->path : base->path);
- return conf ;
-}
-
+ return conf ;
+}
+
@@ -1322,232 +1320,232 @@ added some prototypes to keep the compiler happy:
-
-/*$6
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- * mod_example_config.c
- +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- */
-
-
-#include <stdio.h>
-#include "apr_hash.h"
-#include "ap_config.h"
-#include "ap_provider.h"
-#include "httpd.h"
-#include "http_core.h"
-#include "http_config.h"
-#include "http_log.h"
-#include "http_protocol.h"
-#include "http_request.h"
-
-/*$1
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Configuration structure
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-typedef struct
-{
- char context[256];
- char path[256];
- int typeOfAction;
- int enabled;
-} example_config;
-
-/*$1
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Prototypes
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-static int example_handler(request_rec *r);
-const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg);
-const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg);
-const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2);
-void *create_dir_conf(apr_pool_t *pool, char *context);
-void *merge_dir_conf(apr_pool_t *pool, void *BASE, void *ADD);
-static void register_hooks(apr_pool_t *pool);
-
-/*$1
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Configuration directives
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-static const command_rec directives[] =
-{
- AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, ACCESS_CONF, "Enable or disable mod_example"),
- AP_INIT_TAKE1("examplePath", example_set_path, NULL, ACCESS_CONF, "The path to whatever"),
- AP_INIT_TAKE2("exampleAction", example_set_action, NULL, ACCESS_CONF, "Special action value!"),
- { NULL }
-};
-
-/*$1
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Our name tag
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- */
-
-module AP_MODULE_DECLARE_DATA example_module =
-{
- STANDARD20_MODULE_STUFF,
- create_dir_conf, /* Per-directory configuration handler */
- merge_dir_conf, /* Merge handler for per-directory configurations */
- NULL, /* Per-server configuration handler */
- NULL, /* Merge handler for per-server configurations */
- directives, /* Any directives we may have for httpd */
- register_hooks /* Our hook registering function */
-};
-
-/*
- =======================================================================================================================
- Hook registration function
- =======================================================================================================================
- */
-static void register_hooks(apr_pool_t *pool)
-{
- ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
-}
-
-/*
- =======================================================================================================================
- Our example web service handler
- =======================================================================================================================
- */
-static int example_handler(request_rec *r)
-{
- if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- example_config *config = (example_config *) ap_get_module_config(r->per_dir_config, &example_module);
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- ap_set_content_type(r, "text/plain");
- ap_rprintf(r, "Enabled: %u\n", config->enabled);
- ap_rprintf(r, "Path: %s\n", config->path);
- ap_rprintf(r, "TypeOfAction: %x\n", config->typeOfAction);
- ap_rprintf(r, "Context: %s\n", config->context);
- return OK;
-}
-
-/*
- =======================================================================================================================
- Handler for the "exambleEnabled" directive
- =======================================================================================================================
- */
-const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- example_config *conf = (example_config *) cfg;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- if(conf)
- {
- if(!strcasecmp(arg, "on"))
- conf->enabled = 1;
- else
- conf->enabled = 0;
- }
-
- return NULL;
-}
-
-/*
- =======================================================================================================================
- Handler for the "examplePath" directive
- =======================================================================================================================
- */
-const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- example_config *conf = (example_config *) cfg;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- if(conf)
- {
- strcpy(conf->path, arg);
- }
-
- return NULL;
-}
-
-/*
- =======================================================================================================================
- Handler for the "exampleAction" directive ;
- Let's pretend this one takes one argument (file or db), and a second (deny or allow), ;
- and we store it in a bit-wise manner.
- =======================================================================================================================
- */
-const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- example_config *conf = (example_config *) cfg;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- if(conf)
- {
- {
- if(!strcasecmp(arg1, "file"))
- conf->typeOfAction = 0x01;
- else
- conf->typeOfAction = 0x02;
- if(!strcasecmp(arg2, "deny"))
- conf->typeOfAction += 0x10;
- else
- conf->typeOfAction += 0x20;
- }
- }
-
- return NULL;
-}
-
-/*
- =======================================================================================================================
- Function for creating new configurations for per-directory contexts
- =======================================================================================================================
- */
-void *create_dir_conf(apr_pool_t *pool, char *context)
-{
- context = context ? context : "Newly created configuration";
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- if(cfg)
- {
- {
- /* Set some default values */
- strcpy(cfg->context, context);
- cfg->enabled = 0;
- memset(cfg->path, 0, 256);
- cfg->typeOfAction = 0x00;
- }
- }
-
- return cfg;
-}
-
-/*
- =======================================================================================================================
- Merging function for configurations
- =======================================================================================================================
- */
-void *merge_dir_conf(apr_pool_t *pool, void *BASE, void *ADD)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- example_config *base = (example_config *) BASE;
- example_config *add = (example_config *) ADD;
- example_config *conf = (example_config *) create_dir_conf(pool, "Merged configuration");
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- conf->enabled = (add->enabled == 0) ? base->enabled : add->enabled;
- conf->typeOfAction = add->typeOfAction ? add->typeOfAction : base->typeOfAction;
- strcpy(conf->path, strlen(add->path) ? add->path : base->path);
- return conf;
-}
-
+/*$6
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ * mod_example_config.c
+ +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ */
+
+
+#include <stdio.h>
+#include "apr_hash.h"
+#include "ap_config.h"
+#include "ap_provider.h"
+#include "httpd.h"
+#include "http_core.h"
+#include "http_config.h"
+#include "http_log.h"
+#include "http_protocol.h"
+#include "http_request.h"
+
+/*$1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Configuration structure
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+typedef struct
+{
+ char context[256];
+ char path[256];
+ int typeOfAction;
+ int enabled;
+} example_config;
+
+/*$1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Prototypes
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+static int example_handler(request_rec *r);
+const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg);
+const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg);
+const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2);
+void *create_dir_conf(apr_pool_t *pool, char *context);
+void *merge_dir_conf(apr_pool_t *pool, void *BASE, void *ADD);
+static void register_hooks(apr_pool_t *pool);
+
+/*$1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Configuration directives
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+static const command_rec directives[] =
+{
+ AP_INIT_TAKE1("exampleEnabled", example_set_enabled, NULL, ACCESS_CONF, "Enable or disable mod_example"),
+ AP_INIT_TAKE1("examplePath", example_set_path, NULL, ACCESS_CONF, "The path to whatever"),
+ AP_INIT_TAKE2("exampleAction", example_set_action, NULL, ACCESS_CONF, "Special action value!"),
+ { NULL }
+};
+
+/*$1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Our name tag
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+module AP_MODULE_DECLARE_DATA example_module =
+{
+ STANDARD20_MODULE_STUFF,
+ create_dir_conf, /* Per-directory configuration handler */
+ merge_dir_conf, /* Merge handler for per-directory configurations */
+ NULL, /* Per-server configuration handler */
+ NULL, /* Merge handler for per-server configurations */
+ directives, /* Any directives we may have for httpd */
+ register_hooks /* Our hook registering function */
+};
+
+/*
+ =======================================================================================================================
+ Hook registration function
+ =======================================================================================================================
+ */
+static void register_hooks(apr_pool_t *pool)
+{
+ ap_hook_handler(example_handler, NULL, NULL, APR_HOOK_LAST);
+}
+
+/*
+ =======================================================================================================================
+ Our example web service handler
+ =======================================================================================================================
+ */
+static int example_handler(request_rec *r)
+{
+ if(!r->handler || strcmp(r->handler, "example-handler")) return(DECLINED);
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ example_config *config = (example_config *) ap_get_module_config(r->per_dir_config, &example_module);
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ ap_set_content_type(r, "text/plain");
+ ap_rprintf(r, "Enabled: %u\n", config->enabled);
+ ap_rprintf(r, "Path: %s\n", config->path);
+ ap_rprintf(r, "TypeOfAction: %x\n", config->typeOfAction);
+ ap_rprintf(r, "Context: %s\n", config->context);
+ return OK;
+}
+
+/*
+ =======================================================================================================================
+ Handler for the "exambleEnabled" directive
+ =======================================================================================================================
+ */
+const char *example_set_enabled(cmd_parms *cmd, void *cfg, const char *arg)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ example_config *conf = (example_config *) cfg;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ if(conf)
+ {
+ if(!strcasecmp(arg, "on"))
+ conf->enabled = 1;
+ else
+ conf->enabled = 0;
+ }
+
+ return NULL;
+}
+
+/*
+ =======================================================================================================================
+ Handler for the "examplePath" directive
+ =======================================================================================================================
+ */
+const char *example_set_path(cmd_parms *cmd, void *cfg, const char *arg)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ example_config *conf = (example_config *) cfg;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ if(conf)
+ {
+ strcpy(conf->path, arg);
+ }
+
+ return NULL;
+}
+
+/*
+ =======================================================================================================================
+ Handler for the "exampleAction" directive ;
+ Let's pretend this one takes one argument (file or db), and a second (deny or allow), ;
+ and we store it in a bit-wise manner.
+ =======================================================================================================================
+ */
+const char *example_set_action(cmd_parms *cmd, void *cfg, const char *arg1, const char *arg2)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ example_config *conf = (example_config *) cfg;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ if(conf)
+ {
+ {
+ if(!strcasecmp(arg1, "file"))
+ conf->typeOfAction = 0x01;
+ else
+ conf->typeOfAction = 0x02;
+ if(!strcasecmp(arg2, "deny"))
+ conf->typeOfAction += 0x10;
+ else
+ conf->typeOfAction += 0x20;
+ }
+ }
+
+ return NULL;
+}
+
+/*
+ =======================================================================================================================
+ Function for creating new configurations for per-directory contexts
+ =======================================================================================================================
+ */
+void *create_dir_conf(apr_pool_t *pool, char *context)
+{
+ context = context ? context : "Newly created configuration";
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ example_config *cfg = apr_pcalloc(pool, sizeof(example_config));
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ if(cfg)
+ {
+ {
+ /* Set some default values */
+ strcpy(cfg->context, context);
+ cfg->enabled = 0;
+ memset(cfg->path, 0, 256);
+ cfg->typeOfAction = 0x00;
+ }
+ }
+
+ return cfg;
+}
+
+/*
+ =======================================================================================================================
+ Merging function for configurations
+ =======================================================================================================================
+ */
+void *merge_dir_conf(apr_pool_t *pool, void *BASE, void *ADD)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ example_config *base = (example_config *) BASE;
+ example_config *add = (example_config *) ADD;
+ example_config *conf = (example_config *) create_dir_conf(pool, "Merged configuration");
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ conf->enabled = (add->enabled == 0) ? base->enabled : add->enabled;
+ conf->typeOfAction = add->typeOfAction ? add->typeOfAction : base->typeOfAction;
+ strcpy(conf->path, strlen(add->path) ? add->path : base->path);
+ return conf;
+}
+
@@ -1573,33 +1571,33 @@ or check out the rest of our documentation for further tips.
-
-const char *read_post_value(const apr_array_header_t *fields, const char *key)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- int i;
- apr_table_entry_t *e = 0;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- e = (apr_table_entry_t *) fields->elts;
- for(i = 0; i < fields->nelts; i++) {
- if(!strcmp(e[i].key, key)) return e[i].val;
- }
- return 0;
-}
-static int example_handler(request_req *r)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~*/
- apr_array_header_t *POST;
- const char *value;
- /*~~~~~~~~~~~~~~~~~~~~~~*/
- ap_parse_form_data(r, NULL, &POST, -1, 8192);
+
+const char *read_post_value(const apr_array_header_t *fields, const char *key)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ int i;
+ apr_table_entry_t *e = 0;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ e = (apr_table_entry_t *) fields->elts;
+ for(i = 0; i < fields->nelts; i++) {
+ if(!strcmp(e[i].key, key)) return e[i].val;
+ }
+ return 0;
+}
+static int example_handler(request_req *r)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~*/
+ apr_array_header_t *POST;
+ const char *value;
+ /*~~~~~~~~~~~~~~~~~~~~~~*/
+ ap_parse_form_data(r, NULL, &POST, -1, 8192);
- value = read_post_value(POST, "valueA");
- if (!value) value = "(undefined)";
- ap_rprintf(r, "The value of valueA is: %s", value);
- return OK;
-}
-
+ value = read_post_value(POST, "valueA");
+ if (!value) value = "(undefined)";
+ ap_rprintf(r, "The value of valueA is: %s", value);
+ return OK;
+}
+
@@ -1609,23 +1607,22 @@ or check out the rest of our documentation for further tips.
-
-static int example_handler(request_req *r)
-{
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- const apr_array_header_t *fields;
- int i;
- apr_table_entry_t *e = 0;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- fields = apr_table_elts(r->headers_in);
- e = (apr_table_entry_t *) fields->elts;
- for(i = 0; i < fields->nelts; i++) {
- ap_rprintf(r, "<b>%s</b>: %s<br/>", e[i].key, e[i].val);
- }
- return OK;
-}
-
+static int example_handler(request_req *r)
+{
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ const apr_array_header_t *fields;
+ int i;
+ apr_table_entry_t *e = 0;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ fields = apr_table_elts(r->headers_in);
+ e = (apr_table_entry_t *) fields->elts;
+ for(i = 0; i < fields->nelts; i++) {
+ ap_rprintf(r, "<b>%s</b>: %s<br/>", e[i].key, e[i].val);
+ }
+ return OK;
+}
@@ -1635,55 +1632,55 @@ or check out the rest of our documentation for further tips.
-
-static int util_read(request_rec *r, const char **rbuf, apr_off_t *size)
-{
- /*~~~~~~~~*/
- int rc = OK;
- /*~~~~~~~~*/
-
- if((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
- return(rc);
- }
-
- if(ap_should_client_block(r)) {
-
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- char argsbuffer[HUGE_STRING_LEN];
- apr_off_t rsize, len_read, rpos = 0;
- apr_off_t length = r->remaining;
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- *rbuf = (const char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1));
- *size = length;
- while((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0) {
- if((rpos + len_read) > length) {
- rsize = length - rpos;
- }
- else {
- rsize = len_read;
- }
-
- memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize);
- rpos += rsize;
- }
- }
- return(rc);
-}
-
-static int example_handler(request_req* r)
-{
- /*~~~~~~~~~~~~~~~~*/
- apr_off_t size;
- const char *buffer;
- /*~~~~~~~~~~~~~~~~*/
-
- if(util_read(r, &data, &size) == OK) {
- ap_rprintf("We read a request body that was %u bytes long", size);
- }
- return OK;
-}
-
+static int util_read(request_rec *r, const char **rbuf, apr_off_t *size)
+{
+ /*~~~~~~~~*/
+ int rc = OK;
+ /*~~~~~~~~*/
+
+ if((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR))) {
+ return(rc);
+ }
+
+ if(ap_should_client_block(r)) {
+
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ char argsbuffer[HUGE_STRING_LEN];
+ apr_off_t rsize, len_read, rpos = 0;
+ apr_off_t length = r->remaining;
+ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+
+ *rbuf = (const char *) apr_pcalloc(r->pool, (apr_size_t) (length + 1));
+ *size = length;
+ while((len_read = ap_get_client_block(r, argsbuffer, sizeof(argsbuffer))) > 0) {
+ if((rpos + len_read) > length) {
+ rsize = length - rpos;
+ }
+ else {
+ rsize = len_read;
+ }
+
+ memcpy((char *) *rbuf + rpos, argsbuffer, (size_t) rsize);
+ rpos += rsize;
+ }
+ }
+ return(rc);
+}
+
+static int example_handler(request_req* r)
+{
+ /*~~~~~~~~~~~~~~~~*/
+ apr_off_t size;
+ const char *buffer;
+ /*~~~~~~~~~~~~~~~~*/
+
+ if(util_read(r, &data, &size) == OK) {
+ ap_rprintf("We read a request body that was %u bytes long", size);
+ }
+ return OK;
+}
+
--
2.47.3