summaryrefslogtreecommitdiffabout
authorLars Hjemli <hjemli@gmail.com>2009-02-13 19:43:30 (UTC)
committer Lars Hjemli <hjemli@gmail.com>2009-07-25 10:55:15 (UTC)
commitc4d46c7035d07070ac1ebf0c0b44df927358687f (patch) (side-by-side diff)
tree562cf4f01afe78b92b13ad5be5dc01e07db04a66
parent286a905842dc0bec6d21a614ec4a97c5f19d5bc4 (diff)
downloadcgit-c4d46c7035d07070ac1ebf0c0b44df927358687f.zip
cgit-c4d46c7035d07070ac1ebf0c0b44df927358687f.tar.gz
cgit-c4d46c7035d07070ac1ebf0c0b44df927358687f.tar.bz2
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>
Diffstat (more/less context) (ignore whitespace changes)
-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
@@ -8,24 +8,32 @@
#include "cgit.h"
#include "cache.h"
#include "cmd.h"
#include "configfile.h"
#include "html.h"
#include "ui-shared.h"
#include "ui-stats.h"
#include "scan-tree.h"
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"))
ctx.cfg.root_title = xstrdup(value);
else if (!strcmp(name, "root-desc"))
ctx.cfg.root_desc = xstrdup(value);
else if (!strcmp(name, "root-readme"))
ctx.cfg.root_readme = xstrdup(value);
else if (!strcmp(name, "css"))
ctx.cfg.css = xstrdup(value);
else if (!strcmp(name, "favicon"))
ctx.cfg.favicon = xstrdup(value);
@@ -92,24 +100,26 @@ void config_cb(const char *name, const char *value)
else if (!strcmp(name, "summary-tags"))
ctx.cfg.summary_tags = atoi(value);
else if (!strcmp(name, "agefile"))
ctx.cfg.agefile = xstrdup(value);
else if (!strcmp(name, "renamelimit"))
ctx.cfg.renamelimit = atoi(value);
else if (!strcmp(name, "robots"))
ctx.cfg.robots = xstrdup(value);
else if (!strcmp(name, "clone-prefix"))
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"))
ctx.repo = cgit_add_repo(value);
else if (!strcmp(name, "repo.name"))
ctx.repo->name = xstrdup(value);
else if (ctx.repo && !strcmp(name, "repo.path"))
ctx.repo->path = trim_end(value, '/');
else if (ctx.repo && !strcmp(name, "repo.clone-url"))
ctx.repo->clone_url = xstrdup(value);
else if (ctx.repo && !strcmp(name, "repo.desc"))
ctx.repo->desc = xstrdup(value);
@@ -204,24 +214,25 @@ static void prepare_context(struct cgit_context *ctx)
ctx->cfg.root_desc = "a fast webinterface for the git dscm";
ctx->cfg.script_name = CGIT_SCRIPT_NAME;
ctx->cfg.summary_branches = 10;
ctx->cfg.summary_log = 10;
ctx->cfg.summary_tags = 10;
ctx->page.mimetype = "text/html";
ctx->page.charset = PAGE_ENCODING;
ctx->page.filename = NULL;
ctx->page.size = 0;
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 {
char *req_ref;
char *first_ref;
int match;
};
int find_current_ref(const char *refname, const unsigned char *sha1,
int flags, void *cb_data)
{
struct refmatch *info;
diff --git a/cgit.h b/cgit.h
index 8c64efe..9259f33 100644
--- a/cgit.h
+++ b/cgit.h
@@ -6,24 +6,25 @@
#include <cache.h>
#include <grep.h>
#include <object.h>
#include <tree.h>
#include <commit.h>
#include <tag.h>
#include <diff.h>
#include <diffcore.h>
#include <refs.h>
#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>
/*
* Dateformats used on misc. pages
*/
#define FMT_LONGDATE "%Y-%m-%d %H:%M:%S (%Z)"
#define FMT_SHORTDATE "%Y-%m-%d"
#define FMT_ATOMDATE "%Y-%m-%dT%H:%M:%SZ"
@@ -165,24 +166,25 @@ struct cgit_config {
int max_commit_count;
int max_lock_attempts;
int max_msg_len;
int max_repodesc_len;
int max_stats;
int nocache;
int noheader;
int renamelimit;
int snapshots;
int summary_branches;
int summary_log;
int summary_tags;
+ struct string_list mimetypes;
};
struct cgit_page {
time_t modified;
time_t expires;
size_t size;
char *mimetype;
char *charset;
char *filename;
char *etag;
char *title;
int status;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index a207fe0..7256ec0 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -138,24 +138,28 @@ max-repo-count::
Specifies the number of entries to list per page on the repository
index page. Default value: "50".
max-repodesc-length::
Specifies the maximum number of repo description characters to display
on the repository index page. Default value: "80".
max-stats::
Set the default maximum statistics period. Valid values are "week",
"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
formatstring are the path and SHA1 of the submodule commit. Default
value: "./?repo=%s&page=commit&id=%s"
nocache::
If set to the value "1" caching will be disabled. This settings is
deprecated, and will not be honored starting with cgit-1.0. Default
value: "0".
noheader::
@@ -316,24 +320,37 @@ root-title=foobar.com git repositories
root-desc=tracking the foobar development
# Include some more info about foobar.com on the index page
root-readme=/var/www/htdocs/about.html
# Allow download of tar.gz, tar.bz2 and zip-files
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
## PPS: This list could be kept in a different file (e.g. '/etc/cgitrepos')
## and included like this:
## include=/etc/cgitrepos
##
repo.url=foo
repo.path=/pub/git/foo.git
repo.desc=the master foo repository
diff --git a/ui-plain.c b/ui-plain.c
index 93a3a05..27c6dae 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -8,42 +8,52 @@
#include "cgit.h"
#include "html.h"
#include "ui-shared.h"
char *curr_rev;
char *match_path;
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) {
html_status(404, "Not found", 0);
return;
}
buf = read_sha1_file(sha1, &type, &size);
if (!buf) {
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);
cgit_print_http_headers(&ctx);
html_raw(buf, size);
match = 1;
}
static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
const char *pathname, unsigned mode, int stage,
void *cbdata)
{