Return-Path:
-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
-
-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!
"
)
;
-
- /* 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;
-}
-
+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!"); + + /* 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.
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
-
-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;
-}
-
+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; +} +@@ -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 handle -
ap_rputs(
"
Hello, world!
"
,
r)
;
ap_rputs("Hello, world!", r);@@ -428,7 +429,7 @@ the next, without informing other handle -
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 handle -
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, h
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:
-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
)
;
-
- /* Create a copy of the 'original' variable that we can edit. */
- copy =
apr_pstrdup(
r-
>
pool,
original)
;
- return
OK;
-}
-
+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); + + /* 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 ne -
-/* 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;
-
-
- /* 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>
%u
bytes<br/>
"
,
finfo.
size)
;
-
- /* Get the digest type the client wants to see */
- digestType =
apr_table_get(
GET,
"
digest
"
)
;
- if
(
!
digestType)
digestType =
"
MD5
"
;
+
+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> %u 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)
{
+ 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 set -
-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 directive
-+
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 directiv
-+
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 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
;
-
- if
(
!
strcasecmp(
arg2,
"
deny
"
)
)
config.
typeOfAction +
=
0x10
;
- else
config.
typeOfAction +
=
0x20
;
- return
NULL
;
-}
-
+/* 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; +} +@@ -936,120 +933,120 @@ we can assemble our module into one big -
-/* 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 */
-}
;
-
+/* 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 */ +}; +@@ -1110,10 +1107,11 @@ directory or location in question? It do -
+
+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 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
)
;
[... 799 lines stripped ...]