summaryrefslogtreecommitdiffstats
path: root/src/mod_mime_xattr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mod_mime_xattr.c')
-rw-r--r--src/mod_mime_xattr.c227
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
+};