/* ui-tree.c: functions for tree output * * Copyright (C) 2006-2017 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include "cgit.h" #include "ui-tree.h" #include "html.h" #include "ui-shared.h" struct walk_tree_context { char *curr_rev; char *match_path; int state; }; static void print_text_buffer(const char *name, char *buf, unsigned long size) { unsigned long lineno, idx; const char *numberfmt = "%1$d\n"; html("\n"); if (ctx.cfg.enable_tree_linenumbers) { html("\n"); } else { html("\n"); } if (ctx.repo->source_filter) { char *filter_arg = xstrdup(name); html("
");
		idx = 0;
		lineno = 0;

		if (size) {
			htmlf(numberfmt, ++lineno);
			while (idx < size - 1) { // skip absolute last newline
				if (buf[idx] == '\n')
					htmlf(numberfmt, ++lineno);
				idx++;
			}
		}
		html("
");
		cgit_open_filter(ctx.repo->source_filter, filter_arg);
		html_raw(buf, size);
		cgit_close_filter(ctx.repo->source_filter);
		free(filter_arg);
		html("
\n"); return; } html("
");
	html_txt(buf);
	html("
\n"); } #define ROWLEN 32 static void print_binary_buffer(char *buf, unsigned long size) { unsigned long ofs, idx; static char ascii[ROWLEN + 1]; html("\n"); html(""); for (ofs = 0; ofs < size; ofs += ROWLEN, buf += ROWLEN) { htmlf("\n"); } html("
ofshex dumpascii
%04lx", ofs); for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) htmlf("%*s%02x", idx == 16 ? 4 : 1, "", buf[idx] & 0xff); html(" "); for (idx = 0; idx < ROWLEN && ofs + idx < size; idx++) ascii[idx] = isgraph(buf[idx]) ? buf[idx] : '.'; ascii[idx] = '\0'; html_txt(ascii); html("
\n"); } static void print_object(const unsigned char *sha1, char *path, const char *basename, const char *rev) { enum object_type type; char *buf; unsigned long size; type = sha1_object_info(sha1, &size); if (type == OBJ_BAD) { cgit_print_error_page(404, "Not found", "Bad object name: %s", sha1_to_hex(sha1)); return; } buf = read_sha1_file(sha1, &type, &size); if (!buf) { cgit_print_error_page(500, "Internal server error", "Error reading object %s", sha1_to_hex(sha1)); return; } cgit_set_title_from_path(path); cgit_print_layout_start(); htmlf("blob: %s (", sha1_to_hex(sha1)); cgit_plain_link("plain", NULL, NULL, ctx.qry.head, rev, path); if (ctx.cfg.enable_blame) { html(") ("); cgit_blame_link("blame", NULL, NULL, ctx.qry.head, rev, path); } html(")\n"); if (ctx.cfg.max_blob_size && size / 1024 > ctx.cfg.max_blob_size) { htmlf("
blob size (%ldKB) exceeds display size limit (%dKB).
", size / 1024, ctx.cfg.max_blob_size); return; } if (buffer_is_binary(buf, size)) print_binary_buffer(buf, size); else print_text_buffer(basename, buf, size); free(buf); } struct single_tree_ctx { struct strbuf *path; struct object_id oid; char *name; size_t count; }; static int single_tree_cb(const unsigned char *sha1, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *cbdata) { struct single_tree_ctx *ctx = cbdata; if (++ctx->count > 1) return -1; if (!S_ISDIR(mode)) { ctx->count = 2; return -1; } ctx->name = xstrdup(pathname); hashcpy(ctx->oid.hash, sha1); strbuf_addf(ctx->path, "/%s", pathname); return 0; } static void write_tree_link(const unsigned char *sha1, char *name, char *rev, struct strbuf *fullpath) { size_t initial_length = fullpath->len; struct tree *tree; struct single_tree_ctx tree_ctx = { .path = fullpath, .count = 1, }; struct pathspec paths = { .nr = 0 }; hashcpy(tree_ctx.oid.hash, sha1); while (tree_ctx.count == 1) { cgit_tree_link(name, NULL, "ls-dir", ctx.qry.head, rev, fullpath->buf); tree = lookup_tree(&tree_ctx.oid); if (!tree) return; free(tree_ctx.name); tree_ctx.name = NULL; tree_ctx.count = 0; read_tree_recursive(tree, "", 0, 1, &paths, single_tree_cb, &tree_ctx); if (tree_ctx.count != 1) break; html(" / "); name = tree_ctx.name; } strbuf_setlen(fullpath, initial_length); } static int ls_item(const unsigned char *sha1, struct strbuf *base, const char *pathname, unsigned mode, int stage, void *cbdata) { struct walk_tree_context *walk_tree_ctx = cbdata; char *name; struct strbuf fullpath = STRBUF_INIT; struct strbuf class = STRBUF_INIT; enum object_type type; unsigned long size = 0; name = xstrdup(pathname); strbuf_addf(&fullpath, "%s%s%s", ctx.qry.path ? ctx.qry.path : "", ctx.qry.path ? "/" : "", name); if (!S_ISGITLINK(mode)) { type = s