summary refs log tree commit diff
diff options
context:
space:
mode:
authorLars Hjemli <hjemli@gmail.com>2009-02-13 20:43:30 +0100
committerLars Hjemli <hjemli@gmail.com>2009-07-25 12:55:15 +0200
commitc4d46c7035d07070ac1ebf0c0b44df927358687f (patch)
tree562cf4f01afe78b92b13ad5be5dc01e07db04a66
parent286a905842dc0bec6d21a614ec4a97c5f19d5bc4 (diff)
Add support for mime type registration and lookup
This patch makes it possible to register mappings from filename
extension to mime type in cgitrc and use this mapping when returning
blob content in `plain` view.

The reason for adding this mapping to cgitrc (as opposed to parsing
something like /etc/mime.types) is to allow quick lookup of a limited
number of filename extensions (/etc/mime-types on my machine currently
contains over 700 entries).

NB: A nice addition to this patch would be to parse /etc/mime.types
when `plain` view is requested for a file with an extension for which
there is no mapping registered in cgitrc.

Signed-off-by: Lars Hjemli <hjemli@gmail.com>
-rw-r--r--cgit.c11
-rw-r--r--cgit.h2
-rw-r--r--cgitrc.5.txt17
-rw-r--r--ui-plain.c20
4 files changed, 45 insertions, 5 deletions
diff --git a/cgit.c b/cgit.c
index 2039ab1..4f414c3 100644
--- a/cgit.c
+++ b/cgit.c
@@ -17,6 +17,14 @@
 
 const char *cgit_version = CGIT_VERSION;
 
+void add_mimetype(const char *name, const char *value)
+{
+	struct string_list_item *item;
+
+	item = string_list_insert(xstrdup(name), &ctx.cfg.mimetypes);
+	item->util = xstrdup(value);
+}
+
 void config_cb(const char *name, const char *value)
 {
 	if (!strcmp(name, "root-title"))
@@ -101,6 +109,8 @@ void config_cb(const char *name, const char *value)
 		ctx.cfg.clone_prefix = xstrdup(value);
 	else if (!strcmp(name, "local-time"))
 		ctx.cfg.local_time = atoi(value);
+	else if (!prefixcmp(name, "mimetype."))
+		add_mimetype(name + 9, value);
 	else if (!strcmp(name, "repo.group"))
 		ctx.cfg.repo_group = xstrdup(value);
 	else if (!strcmp(name, "repo.url"))
@@ -213,6 +223,7 @@ static void prepare_context(struct cgit_context *ctx)
 	ctx->page.modified = time(NULL);
 	ctx->page.expires = ctx->page.modified;
 	ctx->page.etag = NULL;
+	memset(&ctx->cfg.mimetypes, 0, sizeof(struct string_list));
 }
 
 struct refmatch {
diff --git a/cgit.h b/cgit.h
index 8c64efe..9259f33 100644
--- a/cgit.h
+++ b/cgit.h
@@ -15,6 +15,7 @@
 #include <revision.h>
 #include <log-tree.h>
 #include <archive.h>
+#include <string-list.h>
 #include <xdiff-interface.h>
 #include <xdiff/xdiff.h>
 #include <utf8.h>
@@ -174,6 +175,7 @@ struct cgit_config {
 	int summary_branches;
 	int summary_log;
 	int summary_tags;
+	struct string_list mimetypes;
 };
 
 struct cgit_page {
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index a207fe0..7256ec0 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -147,6 +147,10 @@ max-stats::
 	"month", "quarter" and "year". If unspecified, statistics are
 	disabled. Default value: none. See also: "repo.max-stats".
 
+mimetype.<ext>::
+	Set the mimetype for the specified filename extension. This is used
+	by the `plain` command when returning blob content.
+
 module-link::
 	Text which will be used as the formatstring for a hyperlink when a
 	submodule is printed in a directory listing. The arguments for the
@@ -325,6 +329,19 @@ snapshots=tar.gz tar.bz2 zip
 
 
 ##
+## List of common mimetypes
+##
+
+mimetype.git=image/git
+mimetype.html=text/html
+mimetype.jpg=image/jpeg
+mimetype.jpeg=image/jpeg
+mimetype.pdf=application/pdf
+mimetype.png=image/png
+mimetype.svg=image/svg+xml
+
+
+##
 ## List of repositories.
 ## PS: Any repositories listed when repo.group is unset will not be
 ##     displayed under a group heading
diff --git a/ui-plain.c b/ui-plain.c
index 93a3a05..27c6dae 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -17,8 +17,9 @@ int match;
 static void print_object(const unsigned char *sha1, const char *path)
 {
 	enum object_type type;
-	char *buf;
+	char *buf, *ext;
 	unsigned long size;
+	struct string_list_item *mime;
 
 	type = sha1_object_info(sha1, &size);
 	if (type == OBJ_BAD) {
@@ -31,10 +32,19 @@ static void print_object(const unsigned char *sha1, const char *path)
 		html_status(404, "Not found", 0);
 		return;
 	}
-	if (buffer_is_binary(buf, size))
-		ctx.page.mimetype = "application/octet-stream";
-	else
-		ctx.page.mimetype = "text/plain";
+	ctx.page.mimetype = NULL;
+	ext = strrchr(path, '.');
+	if (ext && *(++ext)) {
+		mime = string_list_lookup(ext, &ctx.cfg.mimetypes);
+		if (mime)
+			ctx.page.mimetype = (char *)mime->util;
+	}
+	if (!ctx.page.mimetype) {
+		if (buffer_is_binary(buf, size))
+			ctx.page.mimetype = "application/octet-stream";
+		else
+			ctx.page.mimetype = "text/plain";
+	}
 	ctx.page.filename = fmt("%s", path);
 	ctx.page.size = size;
 	ctx.page.etag = sha1_to_hex(sha1);