From 178f0fbc6e8522780c6ed73ec5e7edaa63d643a9 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sat, 31 Oct 2026 13:30:00 -0700 Subject: Strip a snapshot name's suffixes once --- source/ui-snapshot.c | 52 +++++++++++++++++++++------------------------------- 1 file changed, 21 insertions(+), 31 deletions(-) (limited to 'source') diff --git a/source/ui-snapshot.c b/source/ui-snapshot.c index 321bf61..04defa6 100644 --- a/source/ui-snapshot.c +++ b/source/ui-snapshot.c @@ -211,14 +211,11 @@ static int candidate_resolves(const struct cgit_repo *repo, const char *stem, * any is tried as a branch, which a branch spelled like a tag's stem would * otherwise win. */ -static const char *ref_from_filename(const struct cgit_repo *repo, const char *filename, - const struct cgit_snapshot_format *format) +static char *ref_from_filename(const struct cgit_repo *repo, const char *stem) { struct strbuf rev = STRBUF_INIT; - char *stem = xstrndup(filename, strlen(filename) - strlen(format->suffix)); int found = candidate_resolves(repo, stem, &rev, 1) || candidate_resolves(repo, stem, &rev, 0); - free(stem); if (!found) strbuf_release(&rev); return found ? strbuf_detach(&rev, NULL) : NULL; @@ -363,58 +360,51 @@ void cgit_print_snapshot(const char *head, const char *hex, const char *filename const char *sig_filename = NULL; char *archive_name = NULL; char *prefix = NULL; + char *ref = NULL; + size_t len; if (!filename) { cgit_print_error_page(400, "Bad Request", "No snapshot name specified"); return; } - if (ends_with(filename, SIG_SUFFIX)) { + if (strip_suffix(filename, SIG_SUFFIX, &len)) { sig_filename = filename; - archive_name = xstrdup(filename); - archive_name[strlen(archive_name) - strlen(SIG_SUFFIX)] = '\0'; - filename = archive_name; + filename = archive_name = xstrndup(filename, len); } f = find_format(filename); if (!f || (!sig_filename && !(ctx.repo->snapshots & cgit_snapshot_format_bit(f)))) { cgit_print_error_page(400, "Bad Request", "Unsupported snapshot format: %s", filename); - return; + goto done; } - // The name becomes the prefix of every member of the archive, and a - // revision expression such as :/pattern could carry a path in it. - if (!hex && dwim && strchr(filename, '/')) { - cgit_print_error_page(404, "Not Found", "Not found"); - return; - } - // A name that is all suffix names no revision, though the lookup below - // would settle on a ref called v. - if (!hex && dwim && strlen(filename) == strlen(f->suffix)) { - cgit_print_error_page(404, "Not Found", "Not found"); - return; - } if (!hex && dwim) { - hex = ref_from_filename(ctx.repo, filename, f); + strip_suffix(filename, f->suffix, &len); + prefix = xstrndup(filename, len); + // The stem becomes the prefix of every member of the archive, + // and a revision expression such as :/pattern could carry a path + // in it. An empty stem names no revision, though the lookup + // would settle on a ref called v. + if (len && !strchr(prefix, '/')) + hex = ref = ref_from_filename(ctx.repo, prefix); if (!hex) { cgit_print_error_page(404, "Not Found", "Not found"); - return; + goto done; } - prefix = xstrdup(filename); - prefix[strlen(filename) - strlen(f->suffix)] = '\0'; - } - - if (!hex) - hex = head; - - if (!prefix) + } else { prefix = xstrdup(cgit_snapshot_prefix(ctx.repo)); + if (!hex) + hex = head; + } if (sig_filename) send_sig(f, hex, filename, sig_filename); else send_snapshot(f, hex, prefix, filename); +done: free(prefix); + free(ref); free(archive_name); } -- cgit 2.11.1