/dev/trunk

To get this branch, use:
bzr branch http://darksoft.org/webbzr/dev/trunk

« back to all changes in this revision

Viewing changes to apps/mod_root2/mod_root2.c

  • Committer: Suren A. Chilingaryan
  • Date: 2008-04-02 10:23:22 UTC
  • Revision ID: csa@dside.dyndns.org-20080402102322-okib92sicg2dx3o3
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ====================================================================
 
2
 * Copyright (c) 1997,2006 Fons Rademakers.
 
3
 * Author: Fons Rademakers  15/1/97
 
4
 *
 
5
 * Modified: Torre Wenaus, make it work for Apache 1.3.3 (Apache API
 
6
 *           prepends now ap_ to names).
 
7
 *
 
8
 * Rewrite: Fons Rademakers, port to Apache 2.0.
 
9
 *
 
10
 * To build and install this module in a running Apache 2.x server do:
 
11
 *    apxs -c mod_root2.c
 
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
 
16
 * three lines:
 
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
 
21
 * ROOT files.
 
22
 * Finally restart Apache using:
 
23
 *    apachectl restart
 
24
 */
 
25
 
 
26
 
 
27
#include <apr_strings.h>
 
28
#include <ap_config.h>
 
29
#include <httpd.h>
 
30
#include <http_config.h>
 
31
#include <http_protocol.h>
 
32
#include <http_log.h>
 
33
#include <util_script.h>
 
34
#include <http_main.h>
 
35
#include <http_request.h>
 
36
 
 
37
static int root_handler(request_rec *r)
 
38
{
 
39
   conn_rec *c = r->connection;
 
40
   apr_file_t *f = NULL;
 
41
   apr_status_t rv;
 
42
 
 
43
   if (strcmp(r->handler, "mod-root2"))
 
44
      return DECLINED;
 
45
 
 
46
   r->allowed |= (AP_METHOD_BIT << M_GET);
 
47
   if (r->method_number != M_GET)
 
48
      return DECLINED;
 
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;
 
53
   }
 
54
 
 
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;
 
60
   }
 
61
 
 
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);
 
65
      apr_file_close(f);
 
66
      return HTTP_INTERNAL_SERVER_ERROR;
 
67
   }
 
68
 
 
69
   if (!r->header_only) {
 
70
      apr_bucket_brigade *bb;
 
71
      apr_bucket *b;
 
72
      apr_off_t offset;
 
73
      apr_size_t length;
 
74
      int n, i = 0;
 
75
      char *ctx, *s;
 
76
 
 
77
      bb = apr_brigade_create(r->pool, c->bucket_alloc);
 
78
 
 
79
      if (strchr(r->args, ':') == 0) {
 
80
         n = sscanf(r->args, "%ld", &length);
 
81
         if (length == -1) {
 
82
            /* return file size */
 
83
            apr_finfo_t finfo;
 
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);
 
88
               apr_file_close(f);
 
89
               return HTTP_INTERNAL_SERVER_ERROR;
 
90
            }
 
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);
 
98
               apr_file_close(f);
 
99
               return HTTP_INTERNAL_SERVER_ERROR;
 
100
            }
 
101
            apr_file_close(f);
 
102
            return OK;
 
103
         }
 
104
         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
 
105
                       "mod_root2: no valid argument specified for %s", r->filename);
 
106
         apr_file_close(f);
 
107
         return HTTP_INTERNAL_SERVER_ERROR;
 
108
      }
 
109
 
 
110
      for (s = apr_strtok(r->args, ",", &ctx); s; s = apr_strtok(NULL, ",", &ctx)) {
 
111
 
 
112
         n = sscanf(s, "%ld:%ld", &offset, &length);
 
113
 
 
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);
 
118
            apr_file_close(f);
 
119
            return HTTP_INTERNAL_SERVER_ERROR;
 
120
         }
 
121
 
 
122
         if (i == 0) {
 
123
            b = apr_bucket_file_create(f, offset, length,
 
124
                                       r->pool, c->bucket_alloc);
 
125
         } else {
 
126
            apr_bucket_copy(b, &b);
 
127
            b->start = offset;
 
128
            b->length = length;
 
129
         }
 
130
         i++;
 
131
 
 
132
#if APR_HAS_LARGE_FILES
 
133
         if (length > AP_MAX_SENDFILE) {
 
134
            /*
 
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.
 
138
             */
 
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;
 
146
            }
 
147
            b->length = (apr_size_t)fsize; /* Resize just the last bucket */
 
148
         }
 
149
#endif
 
150
 
 
151
         APR_BRIGADE_INSERT_TAIL(bb, b);
 
152
      }
 
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);
 
159
         apr_file_close(f);
 
160
         return HTTP_INTERNAL_SERVER_ERROR;
 
161
      }
 
162
   }
 
163
   apr_file_close(f);
 
164
 
 
165
   return OK;
 
166
}
 
167
 
 
168
static void register_hooks(apr_pool_t *p)
 
169
{
 
170
   ap_hook_handler(root_handler, NULL, NULL, APR_HOOK_MIDDLE);
 
171
}
 
172
 
 
173
module AP_MODULE_DECLARE_DATA root_module =
 
174
{
 
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 */
 
182
};
 
183