upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / generators / mod_asis.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "apr_strings.h"
18 #include "ap_config.h"
19 #include "httpd.h"
20 #include "http_config.h"
21 #include "http_protocol.h"
22 #include "http_log.h"
23 #include "util_script.h"
24 #include "http_main.h"
25 #include "http_request.h"
26
27 #include "mod_core.h"
28
29 #define ASIS_MAGIC_TYPE "httpd/send-as-is"
30
31 static int asis_handler(request_rec *r)
32 {
33     conn_rec *c = r->connection;
34     apr_file_t *f = NULL;
35     apr_status_t rv;
36     const char *location;
37
38     if(strcmp(r->handler,ASIS_MAGIC_TYPE) && strcmp(r->handler,"send-as-is"))
39         return DECLINED;
40
41     r->allowed |= (AP_METHOD_BIT << M_GET);
42     if (r->method_number != M_GET)
43         return DECLINED;
44     if (r->finfo.filetype == 0) {
45         ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
46                     "File does not exist: %s", r->filename);
47         return HTTP_NOT_FOUND;
48     }
49
50     if ((rv = apr_file_open(&f, r->filename, APR_READ, 
51                 APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
52         ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
53                     "file permissions deny server access: %s", r->filename);
54         return HTTP_FORBIDDEN;
55     }
56
57     ap_scan_script_header_err(r, f, NULL);
58     location = apr_table_get(r->headers_out, "Location");
59
60     if (location && location[0] == '/' &&
61         ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
62
63         apr_file_close(f);
64
65         /* Internal redirect -- fake-up a pseudo-request */
66         r->status = HTTP_OK;
67
68         /* This redirect needs to be a GET no matter what the original
69          * method was.
70          */
71         r->method = apr_pstrdup(r->pool, "GET");
72         r->method_number = M_GET;
73
74         ap_internal_redirect_handler(location, r);
75         return OK;
76     }
77
78     if (!r->header_only) {
79         apr_bucket_brigade *bb;
80         apr_bucket *b;
81         apr_off_t pos = 0;
82
83         rv = apr_file_seek(f, APR_CUR, &pos);
84         if (rv != APR_SUCCESS) {
85             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
86                           "mod_asis: failed to find end-of-headers position "
87                           "for %s", r->filename);
88             apr_file_close(f);
89             return HTTP_INTERNAL_SERVER_ERROR;
90         }
91
92         bb = apr_brigade_create(r->pool, c->bucket_alloc);
93 #if APR_HAS_LARGE_FILES
94         if (r->finfo.size - pos > AP_MAX_SENDFILE) {
95             /* APR_HAS_LARGE_FILES issue; must split into mutiple buckets, 
96              * no greater than MAX(apr_size_t), and more granular than that
97              * in case the brigade code/filters attempt to read it directly.
98              */
99             apr_off_t fsize = r->finfo.size - pos;
100             b = apr_bucket_file_create(f, pos, AP_MAX_SENDFILE,
101                                        r->pool, c->bucket_alloc);
102             while (fsize > AP_MAX_SENDFILE) {
103                 APR_BRIGADE_INSERT_TAIL(bb, b);
104                 apr_bucket_copy(b, &b);
105                 b->start += AP_MAX_SENDFILE;
106                 fsize -= AP_MAX_SENDFILE;
107             }
108             b->length = (apr_size_t)fsize; /* Resize just the last bucket */
109         }
110         else
111 #endif
112         b = apr_bucket_file_create(f, pos, (apr_size_t) (r->finfo.size - pos),
113                                    r->pool, c->bucket_alloc);
114         APR_BRIGADE_INSERT_TAIL(bb, b);
115         b = apr_bucket_eos_create(c->bucket_alloc);
116         APR_BRIGADE_INSERT_TAIL(bb, b);
117         rv = ap_pass_brigade(r->output_filters, bb);
118         if (rv != APR_SUCCESS) {
119             ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
120                           "mod_asis: ap_pass_brigade failed for file %s", r->filename);
121             return HTTP_INTERNAL_SERVER_ERROR;
122         }
123     }
124     else {
125         apr_file_close(f);
126     }
127
128     return OK;
129 }
130
131 static void register_hooks(apr_pool_t *p)
132 {
133     ap_hook_handler(asis_handler,NULL,NULL,APR_HOOK_MIDDLE);
134 }
135
136 module AP_MODULE_DECLARE_DATA asis_module =
137 {
138     STANDARD20_MODULE_STUFF,
139     NULL,                       /* create per-directory config structure */
140     NULL,                       /* merge per-directory config structures */
141     NULL,                       /* create per-server config structure */
142     NULL,                       /* merge per-server config structures */
143     NULL,                       /* command apr_table_t */
144     register_hooks              /* register hooks */
145 };