diff options
author | Lennart Poettering <lennart@poettering.net> | 2004-03-24 21:15:21 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2004-03-24 21:15:21 +0000 |
commit | c174f20109543c0a0bc999369784a8ee52f7141c (patch) | |
tree | d8a892a1264831e9829f363c03bf3ae4bf7e5223 /src | |
parent | 85b5c5365026f6a49d441e11810e8e3fe1d57ea8 (diff) |
initial commit
git-svn-id: file:///home/lennart/svn/public/mod_mime_xattr/trunk@3 f01872de-66d6-0310-9185-fc3b30f50adc
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.in | 64 | ||||
-rw-r--r-- | src/mod_mime_xattr.c | 227 |
2 files changed, 291 insertions, 0 deletions
diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..0311c0d --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,64 @@ +# $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. + +DISTFILES=Makefile.in mod_mime_xattr.c +APXS=@APXS@ +APACHECTL=apachectl + +# additional user defines, includes and libraries +#DEF=-Dmy_define=my_value +#INC=-Imy/include/dir +#LIB=-Lmy/lib/dir -lc -lmylib +LIB=-lattr + +# the default target +all: mod_mime_xattr.so + +# compile the DSO file +mod_mime_xattr.so: mod_mime_xattr.c + $(APXS) -c $(DEF) $(INC) $(LIB) mod_mime_xattr.c + +# install the DSO file into the Apache installation +# and activate it in the Apache configuration +install: all + $(APXS) -i -a -n 'mime_xattr' mod_mime_xattr.so + +# cleanup +clean: + -rm -f mod_mime_xattr.o mod_mime_xattr.so + +# reload the module by installing and restarting Apache +reload: install restart + +# the general Apache start/restart/stop procedures +start: + $(APACHECTL) start +restart: + $(APACHECTL) restart +stop: + $(APACHECTL) stop + +distdir: + mkdir -p $(distdir) + cp -p $(DISTFILES) $(distdir) + +mostlyclean: clean +distclean: clean + +maintainer-clean: clean + rm -f Makefile + +.PHONY: all clean maintainer-clean mostlyclean distclean distdir install reload start stop restart 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 +}; |