Diff options
| -rw-r--r-- | MANUAL.txt | 6 | |
| -rw-r--r-- | source/ui-tree.c | 22 | |
| -rwxr-xr-x | tests/t0104-tree.sh | 19 |
3 files changed, 38 insertions, 9 deletions
@@ -344,8 +344,10 @@ max-blob-size:: memory to serve. The tree page's file view, the blame page, a tracked readme, a snapshot signature and the raw "plain" and "blob" output all refuse a larger object rather than load it whole, and the diff and patch - pages show it as binary. Set to "0" to disable the limit. Default value: - "10240" (10 MB). + pages show it as binary. Whatever this is set to, the tree page shows no + more than the first 64 KB of a binary file as a hex dump, and links a + larger one to its "plain" output. Set to "0" to disable the limit. + Default value: "10240" (10 MB). max-commit-count:: Specifies the number of entries to list per page in "log" page. Default diff --git a/source/ui-tree.c b/source/ui-tree.c index aff4f0f..8e17cc4 100644 --- a/source/ui-tree.c +++ b/source/ui-tree.c @@ -21,6 +21,10 @@ #define HEXDUMP_ROW_HALF (HEXDUMP_ROW_BYTES / 2) #define HEXDUMP_GAP_WIDTH 4 +// Every byte dumped costs about seven bytes of markup, so a blob near +// max-blob-size would make a page several times its own size. +#define HEXDUMP_MAX_BYTES (64 * 1024) + // How many single-child directories a listing row follows into one path. #define MAX_DIR_CHAIN_LEVELS 15 @@ -101,9 +105,9 @@ static int is_graphic(unsigned char ch) return isprint(ch) && !isspace(ch); } -static void print_binary_buffer(char *buf, size_t size) +static void print_binary_buffer(char *buf, size_t size, const char *path, const char *rev) { - size_t offset, idx; + size_t offset, idx, shown = size < HEXDUMP_MAX_BYTES ? size : HEXDUMP_MAX_BYTES; char ascii[HEXDUMP_ROW_BYTES + 1]; struct strbuf row = STRBUF_INIT; @@ -111,10 +115,10 @@ static void print_binary_buffer(char *buf, size_t size) html("<tr><th>ofs</th><th>hex dump</th><th>ascii</th></tr>\n"); // A row goes out in one write rather than a write per byte. - for (offset = 0; offset < size; offset += HEXDUMP_ROW_BYTES, buf += HEXDUMP_ROW_BYTES) { + for (offset = 0; offset < shown; offset += HEXDUMP_ROW_BYTES, buf += HEXDUMP_ROW_BYTES) { strbuf_reset(&row); strbuf_addf(&row, "<tr><td class='right'>%04zx</td><td class='hex'>", offset); - for (idx = 0; idx < HEXDUMP_ROW_BYTES && offset + idx < size; idx++) { + for (idx = 0; idx < HEXDUMP_ROW_BYTES && offset + idx < shown; idx++) { int gap = idx == HEXDUMP_ROW_HALF ? HEXDUMP_GAP_WIDTH : 1; strbuf_addf(&row, "%*s%02x", gap, "", (unsigned char)buf[idx]); @@ -122,7 +126,7 @@ static void print_binary_buffer(char *buf, size_t size) strbuf_addstr(&row, " </td><td class='hex'>"); html_raw(row.buf, row.len); - for (idx = 0; idx < HEXDUMP_ROW_BYTES && offset + idx < size; idx++) + for (idx = 0; idx < HEXDUMP_ROW_BYTES && offset + idx < shown; idx++) ascii[idx] = is_graphic(buf[idx]) ? buf[idx] : '.'; ascii[idx] = '\0'; html_txt(ascii); @@ -130,6 +134,12 @@ static void print_binary_buffer(char *buf, size_t size) } strbuf_release(&row); html("</table>\n"); + if (shown < size) { + htmlf("<div class='truncated'>Only the first %d KB of this file are shown. ", + HEXDUMP_MAX_BYTES / 1024); + cgit_plain_link("View the whole file", NULL, NULL, ctx.qry.head, rev, path); + html(".</div>\n"); + } } /* @@ -179,7 +189,7 @@ static bool print_object(const struct object_id *oid, const char *path, html(")</div>\n"); if (is_binary) - print_binary_buffer(buf, size); + print_binary_buffer(buf, size, path, rev); else print_text_buffer(filename, buf, size); diff --git a/tests/t0104-tree.sh b/tests/t0104-tree.sh index 9d6e542..490abb3 100755 --- a/tests/t0104-tree.sh +++ b/tests/t0104-tree.sh @@ -245,7 +245,24 @@ test_expect_success 'a binary file in the tree shows as a hex dump' ' cgitrc_repo binrc bin && cgit_rc binrc "url=bin/tree/blob.bin" >tmp && grep "<table class=.bin-blob.>" tmp && - grep "<td class=.right.>0000</td><td class=.hex.> 00 01 02 62 69 6e" tmp + grep "<td class=.right.>0000</td><td class=.hex.> 00 01 02 62 69 6e" tmp && + ! grep "class=.truncated." tmp +' + +# Each byte of the dump costs several bytes of markup, so a large binary is +# dumped up to its first 64 KB and links to the whole file. +test_expect_success 'a large binary is dumped only in part' ' + ( + cd repos/bin && + printf "\\000" >big.bin && + test_seq 1 20000 >>big.bin && + git add big.bin && + git commit -m "large binary" + ) && + cgit_rc binrc "url=bin/tree/big.bin" >tmp && + grep "<td class=.right.>ffe0</td>" tmp && + ! grep "<td class=.right.>10000</td>" tmp && + grep "<div class=.truncated.>Only the first 64 KB of this file are shown. <a href=./bin/plain/big.bin.>View the whole file</a>.</div>" tmp ' test_done |
