about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJason A. Donenfeld2013-05-26 15:20:02 +0200
committerJason A. Donenfeld2013-05-26 16:30:03 +0200
commitdcbc0438b2543a733858d62170f3110a89edbed6 (patch)
treebdacfe4546c88bf6b03860ea69a0cad885fa6af4
parentui-summary: Disallow directory traversal (diff)
downloadcgit-dcbc0438b2543a733858d62170f3110a89edbed6.tar.gz
cgit-dcbc0438b2543a733858d62170f3110a89edbed6.zip
readme: use string_list instead of space deliminations
Now this is possible in cgitrc -

readme=:README.md
readme=:readme.md
readme=:README.mkd
readme=:readme.mkd
readme=:README.rst
readme=:readme.rst
readme=:README.html
readme=:readme.html
readme=:README.htm
readme=:readme.htm
readme=:README.txt
readme=:readme.txt
readme=:README
readme=:readme
readme=:INSTALL.txt
readme=:install.txt
readme=:INSTALL
readme=:install

Suggested-by: John Keeping <john@keeping.me.uk>
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--cgit.c92
-rw-r--r--cgit.h4
-rw-r--r--cgitrc.5.txt5
-rw-r--r--cmd.c3
-rw-r--r--scan-tree.c8
-rw-r--r--ui-blob.c61
-rw-r--r--ui-blob.h6
-rw-r--r--ui-shared.c2
-rw-r--r--ui-summary.c100
-rw-r--r--ui-summary.h1
10 files changed, 160 insertions, 122 deletions
diff --git a/cgit.c b/cgit.c index f738b83..f0a9acf 100644 --- a/cgit.c +++ b/cgit.c
@@ -1,7 +1,7 @@
1/* cgit.c: cgi for the git scm 1/* cgit.c: cgi for the git scm
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * Copyright (C) 2010, 2012 Jason A. Donenfeld <Jason@zx2c4.com> 4 * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com>
5 * 5 *
6 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text) 7 * (see COPYING for full license text)
@@ -101,13 +101,15 @@ static void repo_config(struct cgit_repo *repo, const char *name, const char *va
101 else if (!strcmp(name, "module-link")) 101 else if (!strcmp(name, "module-link"))
102 repo->module_link= xstrdup(value); 102 repo->module_link= xstrdup(value);
103 else if (!prefixcmp(name, "module-link.")) { 103 else if (!prefixcmp(name, "module-link.")) {
104 item = string_list_append(&repo->submodules, name + 12); 104 item = string_list_append(&repo->submodules, xstrdup(name + 12));
105 item->util = xstrdup(value); 105 item->util = xstrdup(value);
106 } else if (!strcmp(name, "section")) 106 } else if (!strcmp(name, "section"))
107 repo->section = xstrdup(value); 107 repo->section = xstrdup(value);
108 else if (!strcmp(name, "readme") && value != NULL) 108 else if (!strcmp(name, "readme") && value != NULL) {
109 repo->readme = xstrdup(value); 109 if (repo->readme.items == ctx.cfg.readme.items)
110 else if (!strcmp(name, "logo") && value != NULL) 110 memset(&repo->readme, 0, sizeof(repo->readme));
111 string_list_append(&repo->readme, xstrdup(value));
112 } else if (!strcmp(name, "logo") && value != NULL)
111 repo->logo = xstrdup(value); 113 repo->logo = xstrdup(value);
112 else if (!strcmp(name, "logo-link") && value != NULL) 114 else if (!strcmp(name, "logo-link") && value != NULL)
113 repo->logo_link = xstrdup(value); 115 repo->logo_link = xstrdup(value);
@@ -131,8 +133,8 @@ static void config_cb(const char *name, const char *value)
131 ctx.repo->path = trim_end(value, '/'); 133 ctx.repo->path = trim_end(value, '/');
132 else if (ctx.repo && !prefixcmp(name, "repo.")) 134 else if (ctx.repo && !prefixcmp(name, "repo."))
133 repo_config(ctx.repo, name + 5, value); 135 repo_config(ctx.repo, name + 5, value);
134 else if (!strcmp(name, "readme")) 136 else if (!strcmp(name, "readme") && value != NULL)
135 ctx.cfg.readme = xstrdup(value); 137 string_list_append(&ctx.cfg.readme, xstrdup(value));
136 else if (!strcmp(name, "root-title")) 138 else if (!strcmp(name, "root-title"))
137 ctx.cfg.root_title = xstrdup(value); 139 ctx.cfg.root_title = xstrdup(value);
138 else if (!strcmp(name, "root-desc")) 140 else if (!strcmp(name, "root-desc"))
@@ -470,37 +472,76 @@ static char *guess_defbranch(void)
470 return "master"; 472 return "master";
471 return xstrdup(ref + 11); 473 return xstrdup(ref + 11);
472} 474}
475/* The caller must free filename and ref after calling this. */
476static inline void parse_readme(const char *readme, char **filename, char **ref, struct cgit_repo *repo)
477{
478 const char *colon;
479
480 *filename = NULL;
481 *ref = NULL;
482
483 if (!readme || !readme[0])
484 return;
473 485
486 /* Check if the readme is tracked in the git repo. */
487 colon = strchr(readme, ':');
488 if (colon && strlen(colon) > 1) {
489 /* If it starts with a colon, we want to use
490 * the default branch */
491 if (colon == readme && repo->defbranch)
492 *ref = xstrdup(repo->defbranch);
493 else
494 *ref = xstrndup(readme, colon - readme);
495 readme = colon + 1;
496 }
497
498 /* Prepend repo path to relative readme path unless tracked. */
499 if (!(*ref) && readme[0] != '/')
500 *filename = fmtalloc("%s/%s", repo->path, readme);
501 else
502 *filename = xstrdup(readme);
503}
474static void choose_readme(struct cgit_repo *repo) 504static void choose_readme(struct cgit_repo *repo)
475{ 505{
476 char *entry, *filename, *ref; 506 int found;
507 char *filename, *ref;
508 struct string_list_item *entry;
477 509
478 /* If there's no space, we skip the possibly expensive 510 if (!repo->readme.nr)
479 * selection process. */
480 if (!repo->readme || !strchr(repo->readme, ' '))
481 return; 511 return;
482 512
483 for (entry = strtok(repo->readme, " "); entry; entry = strtok(NULL, " ")) { 513 found = 0;
484 cgit_parse_readme(entry, NULL, &filename, &ref, repo); 514 for_each_string_list_item(entry, &repo->readme) {
485 if (!(*filename)) { 515 parse_readme(entry->string, &filename, &ref, repo);
516 if (!filename) {
486 free(filename); 517 free(filename);
487 free(ref); 518 free(ref);
488 continue; 519 continue;
489 } 520 }
490 if (*ref && cgit_ref_path_exists(filename, ref)) { 521 /* If there's only one item, we skip the possibly expensive
491 free(filename); 522 * selection process. */
492 free(ref); 523 if (repo->readme.nr == 1) {
524 found = 1;
493 break; 525 break;
494 } 526 }
495 if (!access(filename, R_OK)) { 527 if (ref) {
496 free(filename); 528 if (cgit_ref_path_exists(filename, ref, 1)) {
497 free(ref); 529 found = 1;
530 break;
531 }
532 }
533 else if (!access(filename, R_OK)) {
534 found = 1;
498 break; 535 break;
499 } 536 }
500 free(filename); 537 free(filename);
501 free(ref); 538 free(ref);
502 } 539 }
503 repo->readme = entry; 540 repo->readme.strdup_strings = 1;
541 string_list_clear(&repo->readme, 0);
542 repo->readme.strdup_strings = 0;
543 if (found)
544 string_list_append(&repo->readme, filename)->util = ref;
504} 545}
505 546
506static int prepare_repo_cmd(struct cgit_context *ctx) 547static int prepare_repo_cmd(struct cgit_context *ctx)
@@ -660,6 +701,7 @@ static char *get_first_line(char *txt)
660 701
661static void print_repo(FILE *f, struct cgit_repo *repo) 702static void print_repo(FILE *f, struct cgit_repo *repo)
662{ 703{
704 struct string_list_item *item;
663 fprintf(f, "repo.url=%s\n", repo->url); 705 fprintf(f, "repo.url=%s\n", repo->url);
664 fprintf(f, "repo.name=%s\n", repo->name); 706 fprintf(f, "repo.name=%s\n", repo->name);
665 fprintf(f, "repo.path=%s\n", repo->path); 707 fprintf(f, "repo.path=%s\n", repo->path);
@@ -670,8 +712,12 @@ static void print_repo(FILE *f, struct cgit_repo *repo)
670 fprintf(f, "repo.desc=%s\n", tmp); 712 fprintf(f, "repo.desc=%s\n", tmp);
671 free(tmp); 713 free(tmp);
672 } 714 }
673 if (repo->readme) 715 for_each_string_list_item(item, &repo->readme) {
674 fprintf(f, "repo.readme=%s\n", repo->readme); 716 if (item->util)
717 fprintf(f, "repo.readme=%s:%s\n", (char *)item->util, item->string);
718 else
719 fprintf(f, "repo.readme=%s\n", item->string);
720 }
675 if (repo->defbranch) 721 if (repo->defbranch)
676 fprintf(f, "repo.defbranch=%s\n", repo->defbranch); 722 fprintf(f, "repo.defbranch=%s\n", repo->defbranch);
677 if (repo->module_link) 723 if (repo->module_link)
diff --git a/cgit.h b/cgit.h index 850b792..f28cf30 100644 --- a/cgit.h +++ b/cgit.h
@@ -73,7 +73,7 @@ struct cgit_repo {
73 char *owner; 73 char *owner;
74 char *defbranch; 74 char *defbranch;
75 char *module_link; 75 char *module_link;
76 char *readme; 76 struct string_list readme;
77 char *section; 77 char *section;
78 char *clone_url; 78 char *clone_url;
79 char *logo; 79 char *logo;
@@ -183,7 +183,7 @@ struct cgit_config {
183 char *mimetype_file; 183 char *mimetype_file;
184 char *module_link; 184 char *module_link;
185 char *project_list; 185 char *project_list;
186 char *readme; 186 struct string_list readme;
187 char *robots; 187 char *robots;
188 char *root_title; 188 char *root_title;
189 char *root_desc; 189 char *root_desc;
diff --git a/cgitrc.5.txt b/cgitrc.5.txt index 12a843b..6437ef4 100644 --- a/cgitrc.5.txt +++ b/cgitrc.5.txt
@@ -290,8 +290,9 @@ project-list::
290 290
291readme:: 291readme::
292 Text which will be used as default value for "repo.readme". Multiple 292 Text which will be used as default value for "repo.readme". Multiple
293 files may be specified, separated by a space, and cgit will use the 293 config keys may be specified, and cgit will use the first found file
294 first found file in this list. Default value: none. 294 in this list. This is useful in conjunction with scan-path. Default
295 value: none. See also: scan-path, repo.readme.
295 296
296remove-suffix:: 297remove-suffix::
297 If set to "1" and scan-path is enabled, if any repositories are found 298 If set to "1" and scan-path is enabled, if any repositories are found
diff --git a/cmd.c b/cmd.c index 198bf2f..abe8e46 100644 --- a/cmd.c +++ b/cmd.c
@@ -1,6 +1,7 @@
1/* cmd.c: the cgit command dispatcher 1/* cmd.c: the cgit command dispatcher
2 * 2 *
3 * Copyright (C) 2008 Lars Hjemli 3 * Copyright (C) 2008 Lars Hjemli
4 * Copyright (C) 2013 Jason A. Donenfeld <Jason@zx2c4.com>.
4 * 5 *
5 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
6 * (see COPYING for full license text) 7 * (see COPYING for full license text)
@@ -46,7 +47,7 @@ static void about_fn(struct cgit_context *ctx)
46 47
47static void blob_fn(struct cgit_context *ctx) 48static void blob_fn(struct cgit_context *ctx)
48{ 49{
49 cgit_print_blob(ctx->qry.sha1, ctx->qry.path, ctx->qry.head); 50 cgit_print_blob(ctx->qry.sha1, ctx->qry.path, ctx->qry.head, 0);
50} 51}
51 52
52static void commit_fn(struct cgit_context *ctx) 53static void commit_fn(struct cgit_context *ctx)
diff --git a/scan-tree.c b/scan-tree.c index a1ec8fb..2684b44 100644 --- a/scan-tree.c +++ b/scan-tree.c
@@ -1,7 +1,7 @@
1/* scan-tree.c 1/* scan-tree.c
2 * 2 *
3 * Copyright (C) 2008-2009 Lars Hjemli 3 * Copyright (C) 2008-2009 Lars Hjemli
4 * Copyright (C) 2010, 2012 Jason A. Donenfeld <Jason@zx2c4.com> 4 * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com>
5 * 5 *
6 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text) 7 * (see COPYING for full license text)
@@ -147,12 +147,6 @@ static void add_repo(const char *base, struct strbuf *path, repo_config_fn fn)
147 strbuf_setlen(path, pathlen); 147 strbuf_setlen(path, pathlen);
148 } 148 }
149 149
150 if (!repo->readme) {
151 strbuf_addstr(path, "README.html");
152 if (!stat(path->buf, &st))
153 repo->readme = "README.html";
154 strbuf_setlen(path, pathlen);
155 }
156 if (ctx.cfg.section_from_path) { 150 if (ctx.cfg.section_from_path) {
157 n = ctx.cfg.section_from_path; 151 n = ctx.cfg.section_from_path;
158 if (n > 0) { 152 if (n > 0) {
diff --git a/ui-blob.c b/ui-blob.c index b4be139..eb14a75 100644 --- a/ui-blob.c +++ b/ui-blob.c
@@ -1,7 +1,7 @@
1/* ui-blob.c: show blob content 1/* ui-blob.c: show blob content
2 * 2 *
3 * Copyright (C) 2008 Lars Hjemli 3 * Copyright (C) 2008 Lars Hjemli
4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com> 4 * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com>
5 * 5 *
6 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text) 7 * (see COPYING for full license text)
@@ -15,7 +15,8 @@
15struct walk_tree_context { 15struct walk_tree_context {
16 const char *match_path; 16 const char *match_path;
17 unsigned char *matched_sha1; 17 unsigned char *matched_sha1;
18 int found_path; 18 int found_path:1;
19 int file_only:1;
19}; 20};
20 21
21static int walk_tree(const unsigned char *sha1, const char *base, int baselen, 22static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
@@ -23,6 +24,8 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
23{ 24{
24 struct walk_tree_context *walk_tree_ctx = cbdata; 25 struct walk_tree_context *walk_tree_ctx = cbdata;
25 26
27 if (walk_tree_ctx->file_only && !S_ISREG(mode))
28 return READ_TREE_RECURSIVE;
26 if (strncmp(base, walk_tree_ctx->match_path, baselen) 29 if (strncmp(base, walk_tree_ctx->match_path, baselen)
27 || strcmp(walk_tree_ctx->match_path + baselen, pathname)) 30 || strcmp(walk_tree_ctx->match_path + baselen, pathname))
28 return READ_TREE_RECURSIVE; 31 return READ_TREE_RECURSIVE;
@@ -31,33 +34,34 @@ static int walk_tree(const unsigned char *sha1, const char *base, int baselen,
31 return 0; 34 return 0;
32} 35}
33 36
34int cgit_ref_path_exists(const char *path, const char *ref) 37int cgit_ref_path_exists(const char *path, const char *ref, int file_only)
35{ 38{
36 unsigned char sha1[20]; 39 unsigned char sha1[20];
37 unsigned long size; 40 unsigned long size;
38 struct pathspec_item path_items = { 41 struct pathspec_item path_items = {
39 .match = path, 42 .match = path,
40 .len = strlen(path) 43 .len = strlen(path)
41 }; 44 };
42 struct pathspec paths = { 45 struct pathspec paths = {
43 .nr = 1, 46 .nr = 1,
44 .items = &path_items 47 .items = &path_items
45 }; 48 };
46 struct walk_tree_context walk_tree_ctx = { 49 struct walk_tree_context walk_tree_ctx = {
47 .match_path = path, 50 .match_path = path,
48 .matched_sha1 = sha1, 51 .matched_sha1 = sha1,
49 .found_path = 0 52 .found_path = 0,
50 }; 53 .file_only = file_only
54 };
51 55
52 if (get_sha1(ref, sha1)) 56 if (get_sha1(ref, sha1))
53 return 0; 57 return 0;
54 if (sha1_object_info(sha1, &size) != OBJ_COMMIT) 58 if (sha1_object_info(sha1, &size) != OBJ_COMMIT)
55 return 0; 59 return 0;
56 read_tree_recursive(lookup_commit_reference(sha1)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx); 60 read_tree_recursive(lookup_commit_reference(sha1)->tree, "", 0, 0, &paths, walk_tree, &walk_tree_ctx);
57 return walk_tree_ctx.found_path; 61 return walk_tree_ctx.found_path;
58} 62}
59 63
60int cgit_print_file(char *path, const char *head) 64int cgit_print_file(char *path, const char *head, int file_only)
61{ 65{
62 unsigned char sha1[20]; 66 unsigned char sha1[20];
63 enum object_type type; 67 enum object_type type;
@@ -75,7 +79,8 @@ int cgit_print_file(char *path, const char *head)
75 struct walk_tree_context walk_tree_ctx = { 79 struct walk_tree_context walk_tree_ctx = {
76 .match_path = path, 80 .match_path = path,
77 .matched_sha1 = sha1, 81 .matched_sha1 = sha1,
78 .found_path = 0 82 .found_path = 0,
83 .file_only = file_only
79 }; 84 };
80 85
81 if (get_sha1(head, sha1)) 86 if (get_sha1(head, sha1))
@@ -98,7 +103,7 @@ int cgit_print_file(char *path, const char *head)
98 return 0; 103 return 0;
99} 104}
100 105
101void cgit_print_blob(const char *hex, char *path, const char *head) 106void cgit_print_blob(const char *hex, char *path, const char *head, int file_only)
102{ 107{
103 unsigned char sha1[20]; 108 unsigned char sha1[20];
104 enum object_type type; 109 enum object_type type;
@@ -116,6 +121,8 @@ void cgit_print_blob(const char *hex, char *path, const char *head)
116 struct walk_tree_context walk_tree_ctx = { 121 struct walk_tree_context walk_tree_ctx = {
117 .match_path = path, 122 .match_path = path,
118 .matched_sha1 = sha1, 123 .matched_sha1 = sha1,
124 .found_path = 0,
125 .file_only = file_only
119 }; 126 };
120 127
121 if (hex) { 128 if (hex) {
diff --git a/ui-blob.h b/ui-blob.h index ce3649f..16847b2 100644 --- a/ui-blob.h +++ b/ui-blob.h
@@ -1,8 +1,8 @@
1#ifndef UI_BLOB_H 1#ifndef UI_BLOB_H
2#define UI_BLOB_H 2#define UI_BLOB_H
3 3
4extern int cgit_ref_path_exists(const char *path, const char *ref); 4extern int cgit_ref_path_exists(const char *path, const char *ref, int file_only);
5extern int cgit_print_file(char *path, const char *head); 5extern int cgit_print_file(char *path, const char *head, int file_only);
6extern void cgit_print_blob(const char *hex, char *path, const char *head); 6extern void cgit_print_blob(const char *hex, char *path, const char *head, int file_only);
7 7
8#endif /* UI_BLOB_H */ 8#endif /* UI_BLOB_H */
diff --git a/ui-shared.c b/ui-shared.c index 519eef7..7ab2ab1 100644 --- a/ui-shared.c +++ b/ui-shared.c
@@ -864,7 +864,7 @@ void cgit_print_pageheader(struct cgit_context *ctx)
864 if (ctx->repo->max_stats) 864 if (ctx->repo->max_stats)
865 cgit_stats_link("stats", NULL, hc(ctx, "stats"), 865 cgit_stats_link("stats", NULL, hc(ctx, "stats"),
866 ctx->qry.head, ctx->qry.vpath); 866 ctx->qry.head, ctx->qry.vpath);
867 if (ctx->repo->readme) 867 if (ctx->repo->readme.nr)
868 reporevlink("about", "about", NULL, 868 reporevlink("about", "about", NULL,
869 hc(ctx, "about"), ctx->qry.head, NULL, 869 hc(ctx, "about"), ctx->qry.head, NULL,
870 NULL); 870 NULL);
diff --git a/ui-summary.c b/ui-summary.c index 57206dd..d8500d6 100644 --- a/ui-summary.c +++ b/ui-summary.c
@@ -1,7 +1,7 @@
1/* ui-summary.c: functions for generating repo summary page 1/* ui-summary.c: functions for generating repo summary page
2 * 2 *
3 * Copyright (C) 2006 Lars Hjemli 3 * Copyright (C) 2006 Lars Hjemli
4 * Copyright (C) 2010 Jason A. Donenfeld <Jason@zx2c4.com> 4 * Copyright (C) 2010-2013 Jason A. Donenfeld <Jason@zx2c4.com>
5 * 5 *
6 * Licensed under GNU General Public License v2 6 * Licensed under GNU General Public License v2
7 * (see COPYING for full license text) 7 * (see COPYING for full license text)
@@ -13,6 +13,7 @@
13#include "ui-log.h" 13#include "ui-log.h"
14#include "ui-refs.h" 14#include "ui-refs.h"
15#include "ui-blob.h" 15#include "ui-blob.h"
16#include <libgen.h>
16 17
17static void print_url(char *base, char *suffix) 18static void print_url(char *base, char *suffix)
18{ 19{
@@ -95,69 +96,57 @@ void cgit_print_summary()
95 html("</table>"); 96 html("</table>");
96} 97}
97 98
98/* The caller must free filename and ref after calling this. */ 99/* The caller must free the return value. */
99void cgit_parse_readme(const char *readme, const char *path, char **filename, char **ref, struct cgit_repo *repo) 100static char* append_readme_path(const char *filename, const char *ref, const char *path)
100{ 101{
101 const char *slash, *colon; 102 char *file, *base_dir, *full_path, *resolved_base = NULL, *resolved_full = NULL;
102 char *resolved_base, *resolved_full;
103
104 *filename = NULL;
105 *ref = NULL;
106
107 if (!readme || !(*readme))
108 return;
109
110 /* Check if the readme is tracked in the git repo. */
111 colon = strchr(readme, ':');
112 if (colon && strlen(colon) > 1) {
113 /* If it starts with a colon, we want to use
114 * the default branch */
115 if (colon == readme && repo->defbranch)
116 *ref = xstrdup(repo->defbranch);
117 else
118 *ref = xstrndup(readme, colon - readme);
119 readme = colon + 1;
120 }
121
122 /* Prepend repo path to relative readme path unless tracked. */
123 if (!(*ref) && *readme != '/')
124 readme = fmtalloc("%s/%s", repo->path, readme);
125
126 /* If a subpath is specified for the about page, make it relative 103 /* If a subpath is specified for the about page, make it relative
127 * to the directory containing the configured readme. */ 104 * to the directory containing the configured readme. */
128 if (path) { 105
129 slash = strrchr(readme, '/'); 106 file = xstrdup(filename);
130 if (!slash) { 107 base_dir = dirname(file);
131 if (!colon) 108 if (!strcmp(base_dir, ".") || !strcmp(base_dir, "..")) {
132 return; 109 if (!ref) {
133 slash = colon; 110 free(file);
134 } 111 return NULL;
135 *filename = xmalloc(slash - readme + 1 + strlen(path) + 1);
136 strncpy(*filename, readme, slash - readme + 1);
137 if (!(*ref))
138 resolved_base = realpath(*filename, NULL);
139 strcpy(*filename + (slash - readme + 1), path);
140 if (!(*ref))
141 resolved_full = realpath(*filename, NULL);
142 if (!(*ref) && (!resolved_base || !resolved_full || strstr(resolved_full, resolved_base) != resolved_full)) {
143 free(*filename);
144 *filename = NULL;
145 }
146 if (!(*ref)) {
147 free(resolved_base);
148 free(resolved_full);
149 } 112 }
113 full_path = xstrdup(path);
150 } else 114 } else
151 *filename = xstrdup(readme); 115 full_path = fmtalloc("%s/%s", base_dir, path);
116
117 if (!ref) {
118 resolved_base = realpath(base_dir, NULL);
119 resolved_full = realpath(full_path, NULL);
120 if (!resolved_base || !resolved_full || strncmp(resolved_base, resolved_full, strlen(resolved_base))) {
121 free(full_path);
122 full_path = NULL;
123 }
124 }
125
126 free(file);
127 free(resolved_base);
128 free(resolved_full);
129
130 return full_path;
152} 131}
153 132
154void cgit_print_repo_readme(char *path) 133void cgit_print_repo_readme(char *path)
155{ 134{
156 char *filename, *ref; 135 char *filename, *ref;
157 cgit_parse_readme(ctx.repo->readme, path, &filename, &ref, ctx.repo); 136 int free_filename = 0;
158 137
159 if (!filename) 138 if (ctx.repo->readme.nr == 0)
160 return; 139 return;
140
141 filename = ctx.repo->readme.items[0].string;
142 ref = ctx.repo->readme.items[0].util;
143
144 if (path) {
145 free_filename = 1;
146 filename = append_readme_path(filename, ref, path);
147 if (!filename)
148 return;
149 }
161 150
162 /* Print the calculated readme, either from the git repo or from the 151 /* Print the calculated readme, either from the git repo or from the
163 * filesystem, while applying the about-filter. 152 * filesystem, while applying the about-filter.
@@ -168,14 +157,15 @@ void cgit_print_repo_readme(char *path)
168 cgit_open_filter(ctx.repo->about_filter); 157 cgit_open_filter(ctx.repo->about_filter);
169 } 158 }
170 if (ref) 159 if (ref)
171 cgit_print_file(filename, ref); 160 cgit_print_file(filename, ref, 1);
172 else 161 else
173 html_include(filename); 162 html_include(filename);
174 if (ctx.repo->about_filter) { 163 if (ctx.repo->about_filter) {
175 cgit_close_filter(ctx.repo->about_filter); 164 cgit_close_filter(ctx.repo->about_filter);
176 ctx.repo->about_filter->argv[1] = NULL; 165 ctx.repo->about_filter->argv[1] = NULL;
166 free(ref);
177 } 167 }
178 html("</div>"); 168 html("</div>");
179 free(filename); 169 if (free_filename)
180 free(ref); 170 free(filename);
181} 171}
diff --git a/ui-summary.h b/ui-summary.h index d6dc5ba..c01f560 100644 --- a/ui-summary.h +++ b/ui-summary.h
@@ -1,7 +1,6 @@
1#ifndef UI_SUMMARY_H 1#ifndef UI_SUMMARY_H
2#define UI_SUMMARY_H 2#define UI_SUMMARY_H
3 3
4extern void cgit_parse_readme(const char *readme, const char *path, char **filename, char **ref, struct cgit_repo *repo);
5extern void cgit_print_summary(); 4extern void cgit_print_summary();
6extern void cgit_print_repo_readme(char *path); 5extern void cgit_print_repo_readme(char *path);
7 6