aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cgit.c2
-rw-r--r--cgit.h1
-rw-r--r--cgitrc.5.txt11
-rw-r--r--ui-plain.c52
4 files changed, 65 insertions, 1 deletions
diff --git a/cgit.c b/cgit.c
index 6a75f27..b9b3a66 100644
--- a/cgit.c
+++ b/cgit.c
@@ -241,6 +241,8 @@ void config_cb(const char *name, const char *value)
241 ctx.cfg.ssdiff = atoi(value); 241 ctx.cfg.ssdiff = atoi(value);
242 else if (!strcmp(name, "agefile")) 242 else if (!strcmp(name, "agefile"))
243 ctx.cfg.agefile = xstrdup(value); 243 ctx.cfg.agefile = xstrdup(value);
244 else if (!strcmp(name, "mimetype-file"))
245 ctx.cfg.mimetype_file = xstrdup(value);
244 else if (!strcmp(name, "renamelimit")) 246 else if (!strcmp(name, "renamelimit"))
245 ctx.cfg.renamelimit = atoi(value); 247 ctx.cfg.renamelimit = atoi(value);
246 else if (!strcmp(name, "remove-suffix")) 248 else if (!strcmp(name, "remove-suffix"))
diff --git a/cgit.h b/cgit.h
index b7c7ac9..6ee6769 100644
--- a/cgit.h
+++ b/cgit.h
@@ -177,6 +177,7 @@ struct cgit_config {
177 char *index_info; 177 char *index_info;
178 char *logo; 178 char *logo;
179 char *logo_link; 179 char *logo_link;
180 char *mimetype_file;
180 char *module_link; 181 char *module_link;
181 char *project_list; 182 char *project_list;
182 char *readme; 183 char *readme;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt
index fab0e0a..a72241f 100644
--- a/cgitrc.5.txt
+++ b/cgitrc.5.txt
@@ -226,6 +226,17 @@ mimetype.<ext>::
226 Set the mimetype for the specified filename extension. This is used 226 Set the mimetype for the specified filename extension. This is used
227 by the `plain` command when returning blob content. 227 by the `plain` command when returning blob content.
228 228
229mimetype-file::
230 Specifies the file to use for automatic mimetype lookup. If specified
231 then this field is used as a fallback when no "mimetype.<ext>" match is
232 found. If unspecified then no such lookup is performed. The typical file
233 to use on a Linux system is /etc/mime.types. Default value: none. See
234 also: "mimetype.<ext>". The format of the file must comply to:
235 - a comment line is an empty line or a line starting with a hash (#),
236 optionally preceded by whitespace
237 - a non-comment line starts with the mimetype (like image/png), followed
238 by one or more file extensions (like jpg), all separated by whitespace
239
229module-link:: 240module-link::
230 Text which will be used as the formatstring for a hyperlink when a 241 Text which will be used as the formatstring for a hyperlink when a
231 submodule is printed in a directory listing. The arguments for the 242 submodule is printed in a directory listing. The arguments for the
diff --git a/ui-plain.c b/ui-plain.c
index 2abd210..85877d7 100644
--- a/ui-plain.c
+++ b/ui-plain.c
@@ -6,6 +6,7 @@
6 * (see COPYING for full license text) 6 * (see COPYING for full license text)
7 */ 7 */
8 8
9#include <stdio.h>
9#include "cgit.h" 10#include "cgit.h"
10#include "html.h" 11#include "html.h"
11#include "ui-shared.h" 12#include "ui-shared.h"
@@ -13,12 +14,53 @@
13int match_baselen; 14int match_baselen;
14int match; 15int match;
15 16
17static char *get_mimetype_from_file(const char *filename, const char *ext)
18{
19 static const char *delimiters;
20 char *result;
21 FILE *fd;
22 char line[1024];
23 char *mimetype;
24 char *token;
25
26 if (!filename)
27 return NULL;
28
29 fd = fopen(filename, "r");
30 if (!fd)
31 return NULL;
32
33 delimiters = " \t\r\n";
34 result = NULL;
35
36 /* loop over all lines in the file */
37 while (!result && fgets(line, sizeof(line), fd)) {
38 mimetype = strtok(line, delimiters);
39
40 /* skip empty lines and comment lines */
41 if (!mimetype || (mimetype[0] == '#'))
42 continue;
43
44 /* loop over all extensions of mimetype */
45 while ((token = strtok(NULL, delimiters))) {
46 if (!strcasecmp(ext, token)) {
47 result = xstrdup(mimetype);
48 break;
49 }
50 }
51 }
52 fclose(fd);
53
54 return result;
55}
56
16static void print_object(const unsigned char *sha1, const char *path) 57static void print_object(const unsigned char *sha1, const char *path)
17{ 58{
18 enum object_type type; 59 enum object_type type;
19 char *buf, *ext; 60 char *buf, *ext;
20 unsigned long size; 61 unsigned long size;
21 struct string_list_item *mime; 62 struct string_list_item *mime;
63 int freemime;
22 64
23 type = sha1_object_info(sha1, &size); 65 type = sha1_object_info(sha1, &size);
24 if (type == OBJ_BAD) { 66 if (type == OBJ_BAD) {
@@ -33,10 +75,16 @@ static void print_object(const unsigned char *sha1, const char *path)
33 } 75 }
34 ctx.page.mimetype = NULL; 76 ctx.page.mimetype = NULL;
35 ext = strrchr(path, '.'); 77 ext = strrchr(path, '.');
78 freemime = 0;
36 if (ext && *(++ext)) { 79 if (ext && *(++ext)) {
37 mime = string_list_lookup(&ctx.cfg.mimetypes, ext); 80 mime = string_list_lookup(&ctx.cfg.mimetypes, ext);
38 if (mime) 81 if (mime) {
39 ctx.page.mimetype = (char *)mime->util; 82 ctx.page.mimetype = (char *)mime->util;
83 } else {
84 ctx.page.mimetype = get_mimetype_from_file(ctx.cfg.mimetype_file, ext);
85 if (ctx.page.mimetype)
86 freemime = 1;
87 }
40 } 88 }
41 if (!ctx.page.mimetype) { 89 if (!ctx.page.mimetype) {
42 if (buffer_is_binary(buf, size)) 90 if (buffer_is_binary(buf, size))
@@ -50,6 +98,8 @@ static void print_object(const unsigned char *sha1, const char *path)
50 cgit_print_http_headers(&ctx); 98 cgit_print_http_headers(&ctx);
51 html_raw(buf, size); 99 html_raw(buf, size);
52 match = 1; 100 match = 1;
101 if (freemime)
102 free(ctx.page.mimetype);
53} 103}
54 104
55static char *buildpath(const char *base, int baselen, const char *path) 105static char *buildpath(const char *base, int baselen, const char *path)