00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "apr_strings.h"
00018 #include "ap_config.h"
00019 #include "httpd.h"
00020 #include "http_config.h"
00021 #include "http_protocol.h"
00022 #include "http_log.h"
00023 #include "util_script.h"
00024 #include "http_main.h"
00025 #include "http_request.h"
00026
00027 #include "mod_core.h"
00028
00029 #define ASIS_MAGIC_TYPE "httpd/send-as-is"
00030
00031 static int asis_handler(request_rec *r)
00032 {
00033 conn_rec *c = r->connection;
00034 apr_file_t *f = NULL;
00035 apr_status_t rv;
00036 const char *location;
00037
00038 if(strcmp(r->handler,ASIS_MAGIC_TYPE) && strcmp(r->handler,"send-as-is"))
00039 return DECLINED;
00040
00041 r->allowed |= (AP_METHOD_BIT << M_GET);
00042 if (r->method_number != M_GET)
00043 return DECLINED;
00044 if (r->finfo.filetype == 0) {
00045 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
00046 "File does not exist: %s", r->filename);
00047 return HTTP_NOT_FOUND;
00048 }
00049
00050 if ((rv = apr_file_open(&f, r->filename, APR_READ,
00051 APR_OS_DEFAULT, r->pool)) != APR_SUCCESS) {
00052 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
00053 "file permissions deny server access: %s", r->filename);
00054 return HTTP_FORBIDDEN;
00055 }
00056
00057 ap_scan_script_header_err(r, f, NULL);
00058 location = apr_table_get(r->headers_out, "Location");
00059
00060 if (location && location[0] == '/' &&
00061 ((r->status == HTTP_OK) || ap_is_HTTP_REDIRECT(r->status))) {
00062
00063 apr_file_close(f);
00064
00065
00066 r->status = HTTP_OK;
00067
00068
00069
00070
00071 r->method = apr_pstrdup(r->pool, "GET");
00072 r->method_number = M_GET;
00073
00074 ap_internal_redirect_handler(location, r);
00075 return OK;
00076 }
00077
00078 if (!r->header_only) {
00079 apr_bucket_brigade *bb;
00080 apr_bucket *b;
00081 apr_off_t pos = 0;
00082
00083 rv = apr_file_seek(f, APR_CUR, &pos);
00084 if (rv != APR_SUCCESS) {
00085 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
00086 "mod_asis: failed to find end-of-headers position "
00087 "for %s", r->filename);
00088 apr_file_close(f);
00089 return HTTP_INTERNAL_SERVER_ERROR;
00090 }
00091
00092 bb = apr_brigade_create(r->pool, c->bucket_alloc);
00093 #if APR_HAS_LARGE_FILES
00094 if (r->finfo.size - pos > AP_MAX_SENDFILE) {
00095
00096
00097
00098
00099 apr_off_t fsize = r->finfo.size - pos;
00100 b = apr_bucket_file_create(f, pos, AP_MAX_SENDFILE,
00101 r->pool, c->bucket_alloc);
00102 while (fsize > AP_MAX_SENDFILE) {
00103 APR_BRIGADE_INSERT_TAIL(bb, b);
00104 apr_bucket_copy(b, &b);
00105 b->start += AP_MAX_SENDFILE;
00106 fsize -= AP_MAX_SENDFILE;
00107 }
00108 b->length = (apr_size_t)fsize;
00109 }
00110 else
00111 #endif
00112 b = apr_bucket_file_create(f, pos, (apr_size_t) (r->finfo.size - pos),
00113 r->pool, c->bucket_alloc);
00114 APR_BRIGADE_INSERT_TAIL(bb, b);
00115 b = apr_bucket_eos_create(c->bucket_alloc);
00116 APR_BRIGADE_INSERT_TAIL(bb, b);
00117 rv = ap_pass_brigade(r->output_filters, bb);
00118 if (rv != APR_SUCCESS) {
00119 ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
00120 "mod_asis: ap_pass_brigade failed for file %s", r->filename);
00121 return HTTP_INTERNAL_SERVER_ERROR;
00122 }
00123 }
00124 else {
00125 apr_file_close(f);
00126 }
00127
00128 return OK;
00129 }
00130
00131 static void register_hooks(apr_pool_t *p)
00132 {
00133 ap_hook_handler(asis_handler,NULL,NULL,APR_HOOK_MIDDLE);
00134 }
00135
00136 module AP_MODULE_DECLARE_DATA asis_module =
00137 {
00138 STANDARD20_MODULE_STUFF,
00139 NULL,
00140 NULL,
00141 NULL,
00142 NULL,
00143 NULL,
00144 register_hooks
00145 };