diff options
Diffstat (limited to 'src/mod_mime_xattr.c')
-rw-r--r-- | src/mod_mime_xattr.c | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/src/mod_mime_xattr.c b/src/mod_mime_xattr.c new file mode 100644 index 0000000..434de4a --- /dev/null +++ b/src/mod_mime_xattr.c @@ -0,0 +1,227 @@ +/* $Id$ */ + +/*** + + Copyright 2004 Lennart Poettering + + Licensed under the Apache License, Version 2.0 (the "License"); you + may not use this file except in compliance with the License. You + may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied. See the License for the specific language governing + permissions and limitations under the License. + +***/ + +#include <sys/types.h> +#include <attr/xattr.h> +#include <ctype.h> + +#include "httpd.h" +#include "http_config.h" +#include "http_core.h" +#include "http_log.h" +#include "http_main.h" +#include "http_protocol.h" +#include "http_request.h" +#include "ap_config.h" + +#define XATTR_NAME_MIMETYPE "user.mime-type" +#define XATTR_NAME_ENCODING "user.mime-encoding" +#define XATTR_NAME_CHARSET "user.charset" +#define XATTR_NAME_HANDLER "user.apache-handler" + +module MODULE_VAR_EXPORT mime_xattr_module; + +struct mime_xattr_dir_config { + int enable_mime_type; + int enable_handler; +}; + +static void* create_mime_xattr_dir_config(pool *p, char*dummy) { + struct mime_xattr_dir_config *c = (struct mime_xattr_dir_config*) ap_palloc(p, sizeof(struct mime_xattr_dir_config)); + c->enable_mime_type = 0; + c->enable_handler = 0; + return c; +} + +static const char *enable_xattr_mime_type(cmd_parms *parms, void *mconfig, int flag) { + struct mime_xattr_dir_config *c = (struct mime_xattr_dir_config*) mconfig; + c->enable_mime_type = flag; + return NULL; +} + +static const char *enable_xattr_handler(cmd_parms *parms, void *mconfig, int flag) { + struct mime_xattr_dir_config *c = (struct mime_xattr_dir_config*) mconfig; + c->enable_handler = flag; + return NULL; +} + +static const command_rec mime_xattr_cmds[] = { + {"XAttrMimeType", + enable_xattr_mime_type, + NULL, + OR_FILEINFO, + FLAG, + "Requires 'On' or 'Off' for enabling resp. disabling usage of file system extended attribute data for MIME type detection." }, + + {"XAttrHandler", + enable_xattr_handler, + NULL, + OR_FILEINFO, + FLAG, + "Requires 'On' or 'Off' for enabling resp. disabling usage of file system extended attribute data for handler detection." }, + + { NULL } +}; + +static char* get_xattr(pool *p, const char *fn, const char *attr) { + char v[256]; + ssize_t l; + + if ((l = lgetxattr(fn, attr, v, sizeof(v)-1)) < 0) + if ((l = getxattr(fn, attr, v, sizeof(v)-1)) < 0) + return NULL; + + v[l] = 0; + + return ap_pstrdup(p, v); +} + +static char* validate_charset(char *f) { + char *c; + + for (c = f; *c; c++) { + *c = tolower(*c); + if (!(*c >= 'a' && *c <= 'z') && !(*c >= '0' && *c <= '9') && *c != '-') + return NULL; + } + + return c > f ? f : NULL; +} + +#define validate_encoding(f) validate_charset(f) +#define validate_handler(f) validate_charset(f) + +static char* validate_mime_type(char *f) { + char *c, *slash = NULL; + + for (c = f; *c; c++) { + *c = tolower(*c); + + if (*c == '/') { + if (!slash && c > f) { + slash = c; + continue; + } else + return NULL; + } + + if (!(*c >= 'a' && *c <= 'z') && !(*c >= '0' && *c <= '9') && *c != '-') + return NULL; + } + + return c > f && slash && slash < c-1 ? f : NULL; +} + +static int find_ct(request_rec *r) { + int result = DECLINED; + struct mime_xattr_dir_config* c; + + if (r->finfo.st_mode == 0 || !r->filename || !S_ISREG(r->finfo.st_mode)) + return DECLINED; + + c = (struct mime_xattr_dir_config*) ap_get_module_config(r->per_dir_config, &mime_xattr_module); + + if (c->enable_mime_type) { + char *mime_type, *charset, *encoding; + + if ((charset = get_xattr(r->pool, r->filename, XATTR_NAME_CHARSET))) + if (!(charset = validate_charset(charset))) + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_mime_xattr: bad charset specification on file <%s>", r->filename); + + if ((mime_type = get_xattr(r->pool, r->filename, XATTR_NAME_MIMETYPE))) { + if (!(mime_type = validate_mime_type(mime_type))) + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_mime_xattr: bad mime type specification on file <%s>", r->filename); + else { + if (charset) + mime_type = ap_psprintf(r->pool, "%s; charset=%s", mime_type, charset); + + r->content_type = mime_type; + result = OK; + } + } + + if (charset && !mime_type && r->content_type) { + char *a, *ct = ap_pstrdup(r->pool, r->content_type); + static const char spec[] = "; charset="; + + if ((a = strstr(ct, spec))) { + char *e; + e = a+strlen(spec); + e += strcspn(e, "; "); + + *a = 0; + + r->content_type = ap_psprintf(r->pool, "%s; charset=%s%s", ct, charset, e); + } else + r->content_type = ap_psprintf(r->pool, "%s; charset=%s", ct, charset); + } + + if ((encoding = get_xattr(r->pool, r->filename, XATTR_NAME_ENCODING))) { + if (!(encoding = validate_encoding(encoding))) + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_mime_xattr: bad encoding specification on file <%s>", r->filename); + else + r->content_encoding = encoding; + } + } + + if (c->enable_handler) { + char *handler; + + if ((handler = get_xattr(r->pool, r->filename, XATTR_NAME_HANDLER))) { + if (!(handler = validate_handler(handler))) + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, "mod_mime_xattr: bad apache handler specification on file <%s>", r->filename); + else { + r->handler = handler; + result = OK; + } + } + } + + return result; +} + +/* Dispatch list for API hooks */ +module MODULE_VAR_EXPORT mime_xattr_module = { + STANDARD_MODULE_STUFF, + NULL, /* module initializer */ + create_mime_xattr_dir_config, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + NULL, /* create per-server config structures */ + NULL, /* merge per-server config structures */ + mime_xattr_cmds, /* table of config file commands */ + NULL, /* [#8] MIME-typed-dispatched handlers */ + NULL, /* [#1] URI to filename translation */ + NULL, /* [#4] validate user id from request */ + NULL, /* [#5] check if the user is ok _here_ */ + NULL, /* [#3] check access by host address */ + find_ct, /* [#6] determine MIME type */ + NULL, /* [#7] pre-run fixups */ + NULL, /* [#9] log a transaction */ + NULL, /* [#2] header parser */ + NULL, /* child_init */ + NULL, /* child_exit */ + NULL /* [#0] post read-request */ +#ifdef EAPI + ,NULL, /* EAPI: add_module */ + NULL, /* EAPI: remove_module */ + NULL, /* EAPI: rewrite_command */ + NULL /* EAPI: new_connection */ +#endif +}; |