00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 #include "apr.h"
00111 #include "apr_strings.h"
00112
00113 #define APR_WANT_STRFUNC
00114 #include "apr_want.h"
00115
00116 #if APR_HAVE_SYS_TYPES_H
00117 #include <sys/types.h>
00118 #endif
00119
00120 #include "ap_config.h"
00121 #include "httpd.h"
00122 #include "http_config.h"
00123 #include "util_script.h"
00124 #include "http_log.h"
00125 #include "http_request.h"
00126 #include "http_protocol.h"
00127 #include "apr_lib.h"
00128
00129 #define DIR_CMD_PERMS OR_INDEXES
00130
00131 #define DEFAULT_METADIR ".web"
00132 #define DEFAULT_METASUFFIX ".meta"
00133 #define DEFAULT_METAFILES 0
00134
00135 module AP_MODULE_DECLARE_DATA cern_meta_module;
00136
00137 typedef struct {
00138 const char *metadir;
00139 const char *metasuffix;
00140 int metafiles;
00141 } cern_meta_dir_config;
00142
00143 static void *create_cern_meta_dir_config(apr_pool_t *p, char *dummy)
00144 {
00145 cern_meta_dir_config *new =
00146 (cern_meta_dir_config *) apr_palloc(p, sizeof(cern_meta_dir_config));
00147
00148 new->metadir = NULL;
00149 new->metasuffix = NULL;
00150 new->metafiles = DEFAULT_METAFILES;
00151
00152 return new;
00153 }
00154
00155 static void *merge_cern_meta_dir_configs(apr_pool_t *p, void *basev, void *addv)
00156 {
00157 cern_meta_dir_config *base = (cern_meta_dir_config *) basev;
00158 cern_meta_dir_config *add = (cern_meta_dir_config *) addv;
00159 cern_meta_dir_config *new =
00160 (cern_meta_dir_config *) apr_palloc(p, sizeof(cern_meta_dir_config));
00161
00162 new->metadir = add->metadir ? add->metadir : base->metadir;
00163 new->metasuffix = add->metasuffix ? add->metasuffix : base->metasuffix;
00164 new->metafiles = add->metafiles;
00165
00166 return new;
00167 }
00168
00169 static const char *set_metadir(cmd_parms *parms, void *in_dconf, const char *arg)
00170 {
00171 cern_meta_dir_config *dconf = in_dconf;
00172
00173 dconf->metadir = arg;
00174 return NULL;
00175 }
00176
00177 static const char *set_metasuffix(cmd_parms *parms, void *in_dconf, const char *arg)
00178 {
00179 cern_meta_dir_config *dconf = in_dconf;
00180
00181 dconf->metasuffix = arg;
00182 return NULL;
00183 }
00184
00185 static const char *set_metafiles(cmd_parms *parms, void *in_dconf, int arg)
00186 {
00187 cern_meta_dir_config *dconf = in_dconf;
00188
00189 dconf->metafiles = arg;
00190 return NULL;
00191 }
00192
00193
00194 static const command_rec cern_meta_cmds[] =
00195 {
00196 AP_INIT_FLAG("MetaFiles", set_metafiles, NULL, DIR_CMD_PERMS,
00197 "Limited to 'on' or 'off'"),
00198 AP_INIT_TAKE1("MetaDir", set_metadir, NULL, DIR_CMD_PERMS,
00199 "the name of the directory containing meta files"),
00200 AP_INIT_TAKE1("MetaSuffix", set_metasuffix, NULL, DIR_CMD_PERMS,
00201 "the filename suffix for meta files"),
00202 {NULL}
00203 };
00204
00205
00206
00207
00208 static int scan_meta_file(request_rec *r, apr_file_t *f)
00209 {
00210 char w[MAX_STRING_LEN];
00211 char *l;
00212 int p;
00213 apr_table_t *tmp_headers;
00214
00215 tmp_headers = apr_table_make(r->pool, 5);
00216 while (apr_file_gets(w, MAX_STRING_LEN - 1, f) == APR_SUCCESS) {
00217
00218
00219
00220 p = strlen(w);
00221 if (p > 0 && w[p - 1] == '\n') {
00222 if (p > 1 && w[p - 2] == '\015')
00223 w[p - 2] = '\0';
00224 else
00225 w[p - 1] = '\0';
00226 }
00227
00228 if (w[0] == '\0') {
00229 return OK;
00230 }
00231
00232
00233
00234 if (!(l = strchr(w, ':'))) {
00235 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
00236 "malformed header in meta file: %s", r->filename);
00237 return HTTP_INTERNAL_SERVER_ERROR;
00238 }
00239
00240 *l++ = '\0';
00241 while (*l && apr_isspace(*l))
00242 ++l;
00243
00244 if (!strcasecmp(w, "Content-type")) {
00245 char *tmp;
00246
00247
00248 char *endp = l + strlen(l) - 1;
00249 while (endp > l && apr_isspace(*endp))
00250 *endp-- = '\0';
00251
00252 tmp = apr_pstrdup(r->pool, l);
00253 ap_content_type_tolower(tmp);
00254 ap_set_content_type(r, tmp);
00255 }
00256 else if (!strcasecmp(w, "Status")) {
00257 sscanf(l, "%d", &r->status);
00258 r->status_line = apr_pstrdup(r->pool, l);
00259 }
00260 else {
00261 apr_table_set(tmp_headers, w, l);
00262 }
00263 }
00264 apr_table_overlap(r->headers_out, tmp_headers, APR_OVERLAP_TABLES_SET);
00265 return OK;
00266 }
00267
00268 static int add_cern_meta_data(request_rec *r)
00269 {
00270 char *metafilename;
00271 char *leading_slash;
00272 char *last_slash;
00273 char *real_file;
00274 char *scrap_book;
00275 apr_file_t *f = NULL;
00276 apr_status_t retcode;
00277 cern_meta_dir_config *dconf;
00278 int rv;
00279 request_rec *rr;
00280
00281 dconf = ap_get_module_config(r->per_dir_config, &cern_meta_module);
00282
00283 if (!dconf->metafiles) {
00284 return DECLINED;
00285 };
00286
00287
00288
00289 if (r->finfo.filetype == 0) {
00290 return DECLINED;
00291 };
00292
00293
00294 if (r->finfo.filetype == APR_DIR || r->uri[strlen(r->uri) - 1] == '/') {
00295 return DECLINED;
00296 };
00297
00298
00299 scrap_book = apr_pstrdup(r->pool, r->filename);
00300
00301 leading_slash = strchr(scrap_book, '/');
00302 last_slash = strrchr(scrap_book, '/');
00303 if ((last_slash != NULL) && (last_slash != leading_slash)) {
00304
00305 real_file = last_slash;
00306 real_file++;
00307 *last_slash = '\0';
00308 }
00309 else {
00310
00311 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
00312 "internal error in mod_cern_meta: %s", r->filename);
00313
00314 return DECLINED;
00315 };
00316
00317 metafilename = apr_pstrcat(r->pool, scrap_book, "/",
00318 dconf->metadir ? dconf->metadir : DEFAULT_METADIR,
00319 "/", real_file,
00320 dconf->metasuffix ? dconf->metasuffix : DEFAULT_METASUFFIX,
00321 NULL);
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 rr = ap_sub_req_lookup_file(metafilename, r, NULL);
00335 if (rr->status != HTTP_OK) {
00336 ap_destroy_sub_req(rr);
00337 return DECLINED;
00338 }
00339 ap_destroy_sub_req(rr);
00340
00341 retcode = apr_file_open(&f, metafilename, APR_READ, APR_OS_DEFAULT, r->pool);
00342 if (retcode != APR_SUCCESS) {
00343 if (APR_STATUS_IS_ENOENT(retcode)) {
00344 return DECLINED;
00345 }
00346 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
00347 "meta file permissions deny server access: %s", metafilename);
00348 return HTTP_FORBIDDEN;
00349 };
00350
00351
00352 rv = scan_meta_file(r, f);
00353 apr_file_close(f);
00354
00355 return rv;
00356 }
00357
00358 static void register_hooks(apr_pool_t *p)
00359 {
00360 ap_hook_fixups(add_cern_meta_data,NULL,NULL,APR_HOOK_MIDDLE);
00361 }
00362
00363 module AP_MODULE_DECLARE_DATA cern_meta_module =
00364 {
00365 STANDARD20_MODULE_STUFF,
00366 create_cern_meta_dir_config,
00367 merge_cern_meta_dir_configs,
00368 NULL,
00369 NULL,
00370 cern_meta_cmds,
00371 register_hooks
00372 };