+
+/* The caller must free the return value. */
+static char* append_readme_path(const char *filename, const char *ref, const char *path)
+{
+ char *file, *base_dir, *full_path, *resolved_base = NULL, *resolved_full = NULL;
+ /* If a subpath is specified for the about page, make it relative
+ * to the directory containing the configured readme. */
+
+ file = xstrdup(filename);
+ base_dir = dirname(file);
+ if (!strcmp(base_dir, ".") || !strcmp(base_dir, "..")) {
+ if (!ref) {
+ free(file);
+ return NULL;
+ }
+ full_path = xstrdup(path);
+ } else
+ full_path = fmtalloc("%s/%s", base_dir, path);
+
+ if (!ref) {
+ resolved_base = realpath(base_dir, NULL);
+ resolved_full = realpath(full_path, NULL);
+ if (!resolved_base || !resolved_full || prefixcmp(resolved_full, resolved_base)) {
+ free(full_path);
+ full_path = NULL;
+ }
+ }
+
+ free(file);
+ free(resolved_base);
+ free(resolved_full);
+
+ return full_path;
+}
+
+void cgit_print_repo_readme(char *path)
+{
+ char *filename, *ref;
+ int free_filename = 0;
+
+ if (ctx.repo->readme.nr == 0)
+ return;
+
+ filename = ctx.repo->readme.items[0].string;
+ ref = ctx.repo->readme.items[0].util;
+
+ if (path) {
+ free_filename = 1;
+ filename = append_readme_path(filename, ref, path);
+ if (!filename)
+ return;
+ }
+
+ /* Print the calculated readme, either from the git repo or from the
+ * filesystem, while applying the about-filter.
+ */
+ html("<div id='summary'>");
+ cgit_open_filter(ctx.repo->about_filter, filename);
+ if (ref)
+ cgit_print_file(filename, ref, 1);
+ else
+ html_include(filename);
+ cgit_close_filter(ctx.repo->about_filter);
+
+ html("</div>");
+ if (free_filename)
+ free(filename);
+}