X-Git-Url: https://git.cameronkatri.com/cgit.git/blobdiff_plain/c1572bb5ec4540b5008490cf471cc4a5e65ef728..0899eb644fab415e9a3b304f53da9da50aaf91aa:/ui-snapshot.c diff --git a/ui-snapshot.c b/ui-snapshot.c index b9e2a36..fa3ceaf 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c @@ -86,14 +86,40 @@ static int write_tar_xz_archive(const char *hex, const char *prefix) } const struct cgit_snapshot_format cgit_snapshot_formats[] = { - { ".zip", "application/x-zip", write_zip_archive, 0x01 }, - { ".tar.gz", "application/x-gzip", write_tar_gzip_archive, 0x02 }, - { ".tar.bz2", "application/x-bzip2", write_tar_bzip2_archive, 0x04 }, - { ".tar", "application/x-tar", write_tar_archive, 0x08 }, - { ".tar.xz", "application/x-xz", write_tar_xz_archive, 0x10 }, + /* .tar must remain the 0 index */ + { ".tar", "application/x-tar", write_tar_archive }, + { ".tar.gz", "application/x-gzip", write_tar_gzip_archive }, + { ".tar.bz2", "application/x-bzip2", write_tar_bzip2_archive }, + { ".tar.xz", "application/x-xz", write_tar_xz_archive }, + { ".zip", "application/x-zip", write_zip_archive }, { NULL } }; +static struct notes_tree snapshot_sig_notes[ARRAY_SIZE(cgit_snapshot_formats)]; + +const struct object_id *cgit_snapshot_get_sig(const char *ref, + const struct cgit_snapshot_format *f) +{ + struct notes_tree *tree; + struct object_id oid; + + if (get_oid(ref, &oid)) + return NULL; + + tree = &snapshot_sig_notes[f - &cgit_snapshot_formats[0]]; + if (!tree->initialized) { + struct strbuf notes_ref = STRBUF_INIT; + + strbuf_addf(¬es_ref, "refs/notes/signatures/%s", + f->suffix + 1); + + init_notes(tree, notes_ref.buf, combine_notes_ignore, 0); + strbuf_release(¬es_ref); + } + + return get_note(tree, &oid); +} + static const struct cgit_snapshot_format *get_format(const char *filename) { const struct cgit_snapshot_format *fmt; @@ -105,6 +131,11 @@ static const struct cgit_snapshot_format *get_format(const char *filename) return NULL; } +const unsigned cgit_snapshot_format_bit(const struct cgit_snapshot_format *f) +{ + return BIT(f - &cgit_snapshot_formats[0]); +} + static int make_snapshot(const struct cgit_snapshot_format *format, const char *hex, const char *prefix, const char *filename) @@ -129,6 +160,39 @@ static int make_snapshot(const struct cgit_snapshot_format *format, return 0; } +static int write_sig(const struct cgit_snapshot_format *format, + const char *hex, const char *archive, + const char *filename) +{ + const struct object_id *note = cgit_snapshot_get_sig(hex, format); + enum object_type type; + unsigned long size; + char *buf; + + if (!note) { + cgit_print_error_page(404, "Not found", + "No signature for %s", archive); + return 0; + } + + buf = read_object_file(note, &type, &size); + if (!buf) { + cgit_print_error_page(404, "Not found", "Not found"); + return 0; + } + + html("X-Content-Type-Options: nosniff\n"); + html("Content-Security-Policy: default-src 'none'\n"); + ctx.page.etag = oid_to_hex(note); + ctx.page.mimetype = xstrdup("application/pgp-signature"); + ctx.page.filename = xstrdup(filename); + cgit_print_http_headers(); + + html_raw(buf, size); + free(buf); + return 0; +} + /* Try to guess the requested revision from the requested snapshot name. * First the format extension is stripped, e.g. "cgit-0.7.2.tar.gz" become * "cgit-0.7.2". If this is a valid commit object name we've got a winner. @@ -185,6 +249,8 @@ void cgit_print_snapshot(const char *head, const char *hex, const char *filename, int dwim) { const struct cgit_snapshot_format* f; + const char *sig_filename = NULL; + char *adj_filename = NULL; char *prefix = NULL; if (!filename) { @@ -193,8 +259,17 @@ void cgit_print_snapshot(const char *head, const char *hex, return; } + if (ends_with(filename, ".asc")) { + sig_filename = filename; + + /* Strip ".asc" from filename for common format processing */ + adj_filename = xstrdup(filename); + adj_filename[strlen(adj_filename) - 4] = '\0'; + filename = adj_filename; + } + f = get_format(filename); - if (!f) { + 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; @@ -216,6 +291,11 @@ void cgit_print_snapshot(const char *head, const char *hex, if (!prefix) prefix = xstrdup(cgit_snapshot_prefix(ctx.repo)); - make_snapshot(f, hex, prefix, filename); + if (sig_filename) + write_sig(f, hex, filename, sig_filename); + else + make_snapshot(f, hex, prefix, filename); + free(prefix); + free(adj_filename); }