1
/* ====================================================================
2
* Copyright (c) 1997,2006 Fons Rademakers.
3
* Author: Fons Rademakers 15/1/97
5
* Modified: Torre Wenaus, make it work for Apache 1.3.3 (Apache API
6
* prepends now ap_ to names).
8
* Rewrite: Fons Rademakers, port to Apache 2.0.
10
* To build and install this module in a running Apache 2.x server do:
12
* if this succeeds, become superuser and do:
13
* apxs -i -c mod_root2.c
14
* this will install the compiled module module in the Apache modules directory.
15
* Next add the file root2.conf to /etc/httpd/conf.d/, this file contains the
17
* LoadModule root_module modules/mod_root2.so
18
* AddHandler mod-root2 .root
19
* AddHandler mod-root2 .zip
20
* the last line is only needed if you want to support ZIP files containing
22
* Finally restart Apache using:
27
#include <apr_strings.h>
28
#include <ap_config.h>
30
#include <http_config.h>
31
#include <http_protocol.h>
33
#include <util_script.h>
34
#include <http_main.h>
35
#include <http_request.h>
37
static int root_handler(request_rec *r)
39
conn_rec *c = r->connection;
43
if (strcmp(r->handler, "mod-root2"))
46
r->allowed |= (AP_METHOD_BIT << M_GET);
47
if (r->method_number != M_GET)
49
if (r->finfo.filetype == 0) {
50
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
51
"File does not exist: %s", r->filename);
52
return HTTP_NOT_FOUND;
55
if ((rv = apr_file_open(&f, r->filename, APR_READ,
56
APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
57
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
58
"File permissions deny server access: %s", r->filename);
59
return HTTP_FORBIDDEN;
62
if (!r->args || strlen(r->args) == 0) {
63
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
64
"mod_root2: no argument specified for %s", r->filename);
66
return HTTP_INTERNAL_SERVER_ERROR;
69
if (!r->header_only) {
70
apr_bucket_brigade *bb;
77
bb = apr_brigade_create(r->pool, c->bucket_alloc);
79
if (strchr(r->args, ':') == 0) {
80
n = sscanf(r->args, "%ld", &length);
82
/* return file size */
84
rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, f);
85
if (rv != APR_SUCCESS) {
86
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
87
"mod_root2: cannot get size of file: %s", r->filename);
89
return HTTP_INTERNAL_SERVER_ERROR;
91
apr_brigade_printf(bb, NULL, NULL, "%ld", finfo.size);
92
b = apr_bucket_eos_create(c->bucket_alloc);
93
APR_BRIGADE_INSERT_TAIL(bb, b);
94
rv = ap_pass_brigade(r->output_filters, bb);
95
if (rv != APR_SUCCESS) {
96
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
97
"mod_root2: ap_pass_brigade failed for file %s of size %ld", r->filename, finfo.size);
99
return HTTP_INTERNAL_SERVER_ERROR;
104
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
105
"mod_root2: no valid argument specified for %s", r->filename);
107
return HTTP_INTERNAL_SERVER_ERROR;
110
for (s = apr_strtok(r->args, ",", &ctx); s; s = apr_strtok(NULL, ",", &ctx)) {
112
n = sscanf(s, "%ld:%ld", &offset, &length);
114
/* some sanity checks */
115
if (n != 2 || offset < 0 || length <= 0) {
116
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
117
"mod_root2: invalid offset or length specified for %s", r->filename);
119
return HTTP_INTERNAL_SERVER_ERROR;
123
b = apr_bucket_file_create(f, offset, length,
124
r->pool, c->bucket_alloc);
126
apr_bucket_copy(b, &b);
132
#if APR_HAS_LARGE_FILES
133
if (length > AP_MAX_SENDFILE) {
135
* APR_HAS_LARGE_FILES issue; must split into mutiple buckets,
136
* no greater than MAX(apr_size_t), and more granular than that
137
* in case the brigade code/filters attempt to read it directly.
139
apr_off_t fsize = length;
140
b->length = AP_MAX_SENDFILE;
141
while (fsize > AP_MAX_SENDFILE) {
142
APR_BRIGADE_INSERT_TAIL(bb, b);
143
apr_bucket_copy(b, &b);
144
b->start += AP_MAX_SENDFILE;
145
fsize -= AP_MAX_SENDFILE;
147
b->length = (apr_size_t)fsize; /* Resize just the last bucket */
151
APR_BRIGADE_INSERT_TAIL(bb, b);
153
b = apr_bucket_eos_create(c->bucket_alloc);
154
APR_BRIGADE_INSERT_TAIL(bb, b);
155
rv = ap_pass_brigade(r->output_filters, bb);
156
if (rv != APR_SUCCESS) {
157
ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
158
"mod_root2: ap_pass_brigade failed for file %s", r->filename);
160
return HTTP_INTERNAL_SERVER_ERROR;
168
static void register_hooks(apr_pool_t *p)
170
ap_hook_handler(root_handler, NULL, NULL, APR_HOOK_MIDDLE);
173
module AP_MODULE_DECLARE_DATA root_module =
175
STANDARD20_MODULE_STUFF,
176
NULL, /* create per-directory config structure */
177
NULL, /* merge per-directory config structures */
178
NULL, /* create per-server config structure */
179
NULL, /* merge per-server config structures */
180
NULL, /* command apr_table_t */
181
register_hooks /* register hooks */