Diff options
Diffstat (limited to '')
| -rw-r--r-- | source/ui-plain.c | 92 |
1 file changed, 65 insertions, 27 deletions
diff --git a/source/ui-plain.c b/source/ui-plain.c index 57e4699..43bdb22 100644 --- a/source/ui-plain.c +++ b/source/ui-plain.c @@ -42,6 +42,55 @@ static int is_unsafe_type(const char *mimetype) strcmp(mimetype, "application/pdf"); } +static char *get_mimetype_for_filename(const char *filename) +{ + const char *ext; + char *type, line[1024]; + struct string_list fields = STRING_LIST_INIT_NODUP; + size_t i; + FILE *file; + struct string_list_item *entry; + + if (!filename) + return NULL; + + ext = strrchr(filename, '.'); + if (!ext) + return NULL; + ++ext; + if (!ext[0]) + return NULL; + entry = string_list_lookup(&ctx.cfg.mimetypes, ext); + if (entry) + return xstrdup(entry->util); + + if (!ctx.cfg.mimetype_file) + return NULL; + file = fopen(ctx.cfg.mimetype_file, "r"); + if (!file) + return NULL; + while (fgets(line, sizeof(line), file)) { + // A line of a mime.types file is one type followed by every + // extension that maps to it. + string_list_split_in_place(&fields, line, " \t\r\n", -1); + string_list_remove_empty_items(&fields, 0); + if (!fields.nr || fields.items[0].string[0] == '#') { + string_list_clear(&fields, 0); + continue; + } + type = fields.items[0].string; + for (i = 1; i < fields.nr; i++) { + if (!strcasecmp(ext, fields.items[i].string)) { + fclose(file); + return xstrdup(type); + } + } + string_list_clear(&fields, 0); + } + fclose(file); + return NULL; +} + /* * Writes the response for the object, error pages included, so the walk * does not go on to report the path as missing. @@ -69,7 +118,7 @@ static void print_object(const struct object_id *oid, const char *path) return; } - mimetype = cgit_get_mimetype_for_filename(path); + mimetype = get_mimetype_for_filename(path); ctx.page.mimetype = mimetype; if (!ctx.repo->enable_html_serving) { @@ -93,9 +142,9 @@ static void print_object(const struct object_id *oid, const char *path) static char *build_path(const char *base, int baselen, const char *path) { if (path[0]) - return cgit_fmtalloc("%.*s%s/", baselen, base, path); + return xstrfmt("%.*s%s/", baselen, base, path); else - return cgit_fmtalloc("%.*s/", baselen, base); + return xstrfmt("%.*s/", baselen, base); } static void print_dir(const char *base, int baselen, const char *path) @@ -159,20 +208,17 @@ static void print_dir_tail(void) html("</ul>\n</body>\n</html>\n"); } -/* - * read_tree reads the return value as a direction rather than a status, so - * READ_TREE_RECURSIVE means step into this entry and zero means step over it. - */ static int walk_tree(const struct object_id *oid, struct strbuf *base, const char *pathname, unsigned mode, void *context) { struct walk_tree_context *walk = context; - // A tree can hold two entries of one name, and only the first answers: - // a second response would follow the first in the same body. - if (walk->response != RESPONSE_NONE && walk->dir_len >= 0 && base->len == (size_t)walk->dir_len) - return 0; if (walk->dir_len >= 0 && base->len == (size_t)walk->dir_len) { + // A tree can hold two entries of one name, and only the first + // answers: a second response would follow the first in the same + // body. + if (walk->response != RESPONSE_NONE) + return 0; if (S_ISREG(mode) || S_ISLNK(mode)) { print_object(oid, pathname); walk->response = RESPONSE_BLOB; @@ -205,19 +251,8 @@ void cgit_print_plain(void) const char *rev = ctx.qry.oid; struct object_id oid; struct commit *commit; - int path_len = ctx.qry.path ? strlen(ctx.qry.path) : 0; - // nowildcard_len matches len so git treats the path as literal. As a - // glob, every entry a pattern like * matches would be answered with - // its own HTTP headers inside the body of the first. - struct pathspec_item path_items = { - .match = ctx.qry.path, - .len = path_len, - .nowildcard_len = path_len - }; - struct pathspec paths = { - .nr = 1, - .items = &path_items - }; + struct pathspec_item path_item; + struct pathspec paths = { 0 }; struct walk_tree_context walk = { .response = RESPONSE_NONE }; @@ -234,15 +269,18 @@ void cgit_print_plain(void) cgit_print_error_page(404, "Not Found", "Not found"); return; } - if (!path_items.match) { + // The path is taken literally, since as a glob every entry a pattern + // like * matches would be answered with its own HTTP headers inside + // the body of the first. + cgit_literal_pathspec(&paths, &path_item, ctx.qry.path); + if (!ctx.qry.path) { // The walk is never handed an entry for the top of the tree // itself, so the listing it would have opened is opened here. - paths.nr = 0; walk.dir_len = -1; print_dir("", 0, ""); walk.response = RESPONSE_LISTING; } else { - walk.dir_len = dir_prefix_len(path_items.match); + walk.dir_len = dir_prefix_len(ctx.qry.path); } read_tree(the_repository, repo_get_commit_tree(the_repository, commit), &paths, walk_tree, &walk); if (walk.response == RESPONSE_NONE) |
