diff options
| -rw-r--r-- | cgit.h | 2 | ||||
| -rw-r--r-- | ui-shared.c | 7 | ||||
| -rw-r--r-- | ui-snapshot.c | 76 |
3 files changed, 84 insertions, 1 deletions
| @@ -374,6 +374,8 @@ extern void cgit_parse_url(const char *url); | |||
| 374 | extern const char *cgit_repobasename(const char *reponame); | 374 | extern const char *cgit_repobasename(const char *reponame); |
| 375 | 375 | ||
| 376 | extern int cgit_parse_snapshots_mask(const char *str); | 376 | extern int cgit_parse_snapshots_mask(const char *str); |
| 377 | extern const struct object_id *cgit_snapshot_get_sig(const char *ref, | ||
| 378 | const struct cgit_snapshot_format *f); | ||
| 377 | 379 | ||
| 378 | extern int cgit_open_filter(struct cgit_filter *filter, ...); | 380 | extern int cgit_open_filter(struct cgit_filter *filter, ...); |
| 379 | extern int cgit_close_filter(struct cgit_filter *filter); | 381 | extern int cgit_close_filter(struct cgit_filter *filter); |
diff --git a/ui-shared.c b/ui-shared.c index 9d7ee3d..8a786e0 100644 --- a/ui-shared.c +++ b/ui-shared.c | |||
| @@ -1133,6 +1133,13 @@ void cgit_print_snapshot_links(const struct cgit_repo *repo, const char *ref, | |||
| 1133 | strbuf_addstr(&filename, f->suffix); | 1133 | strbuf_addstr(&filename, f->suffix); |
| 1134 | cgit_snapshot_link(filename.buf, NULL, NULL, NULL, NULL, | 1134 | cgit_snapshot_link(filename.buf, NULL, NULL, NULL, NULL, |
| 1135 | filename.buf); | 1135 | filename.buf); |
| 1136 | if (cgit_snapshot_get_sig(ref, f)) { | ||
| 1137 | strbuf_addstr(&filename, ".asc"); | ||
| 1138 | html(" ("); | ||
| 1139 | cgit_snapshot_link("sig", NULL, NULL, NULL, NULL, | ||
| 1140 | filename.buf); | ||
| 1141 | html(")"); | ||
| 1142 | } | ||
| 1136 | html(separator); | 1143 | html(separator); |
| 1137 | } | 1144 | } |
| 1138 | strbuf_release(&filename); | 1145 | strbuf_release(&filename); |
diff --git a/ui-snapshot.c b/ui-snapshot.c index abf8399..c7611e8 100644 --- a/ui-snapshot.c +++ b/ui-snapshot.c | |||
| @@ -94,6 +94,31 @@ const struct cgit_snapshot_format cgit_snapshot_formats[] = { | |||
| 94 | { NULL } | 94 | { NULL } |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | static struct notes_tree snapshot_sig_notes[ARRAY_SIZE(cgit_snapshot_formats)]; | ||
| 98 | |||
| 99 | const struct object_id *cgit_snapshot_get_sig(const char *ref, | ||
| 100 | const struct cgit_snapshot_format *f) | ||
| 101 | { | ||
| 102 | struct notes_tree *tree; | ||
| 103 | struct object_id oid; | ||
| 104 | |||
| 105 | if (get_oid(ref, &oid)) | ||
| 106 | return NULL; | ||
| 107 | |||
| 108 | tree = &snapshot_sig_notes[f - &cgit_snapshot_formats[0]]; | ||
| 109 | if (!tree->initialized) { | ||
| 110 | struct strbuf notes_ref = STRBUF_INIT; | ||
| 111 | |||
| 112 | strbuf_addf(¬es_ref, "refs/notes/signatures/%s", | ||
| 113 | f->suffix + 1); | ||
| 114 | |||
| 115 | init_notes(tree, notes_ref.buf, combine_notes_ignore, 0); | ||
| 116 | strbuf_release(¬es_ref); | ||
| 117 | } | ||
| 118 | |||
| 119 | return get_note(tree, &oid); | ||
| 120 | } | ||
| 121 | |||
| 97 | static const struct cgit_snapshot_format *get_format(const char *filename) | 122 | static const struct cgit_snapshot_format *get_format(const char *filename) |
| 98 | { | 123 | { |
| 99 | const struct cgit_snapshot_format *fmt; | 124 | const struct cgit_snapshot_format *fmt; |
| @@ -129,6 +154,39 @@ static int make_snapshot(const struct cgit_snapshot_format *format, | |||
| 129 | return 0; | 154 | return 0; |
| 130 | } | 155 | } |
| 131 | 156 | ||
| 157 | static int write_sig(const struct cgit_snapshot_format *format, | ||
| 158 | const char *hex, const char *archive, | ||
| 159 | const char *filename) | ||
| 160 | { | ||
| 161 | const struct object_id *note = cgit_snapshot_get_sig(hex, format); | ||
| 162 | enum object_type type; | ||
| 163 | unsigned long size; | ||
| 164 | char *buf; | ||
| 165 | |||
| 166 | if (!note) { | ||
| 167 | cgit_print_error_page(404, "Not found", | ||
| 168 | "No signature for %s", archive); | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | buf = read_sha1_file(note->hash, &type, &size); | ||
| 173 | if (!buf) { | ||
| 174 | cgit_print_error_page(404, "Not found", "Not found"); | ||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | html("X-Content-Type-Options: nosniff\n"); | ||
| 179 | html("Content-Security-Policy: default-src 'none'\n"); | ||
| 180 | ctx.page.etag = oid_to_hex(note); | ||
| 181 | ctx.page.mimetype = xstrdup("application/pgp-signature"); | ||
| 182 | ctx.page.filename = xstrdup(filename); | ||
| 183 | cgit_print_http_headers(); | ||
| 184 | |||
| 185 | html_raw(buf, size); | ||
| 186 | free(buf); | ||
| 187 | return 0; | ||
| 188 | } | ||
| 189 | |||
| 132 | /* Try to guess the requested revision from the requested snapshot name. | 190 | /* Try to guess the requested revision from the requested snapshot name. |
| 133 | * First the format extension is stripped, e.g. "cgit-0.7.2.tar.gz" become | 191 | * First the format extension is stripped, e.g. "cgit-0.7.2.tar.gz" become |
| 134 | * "cgit-0.7.2". If this is a valid commit object name we've got a winner. | 192 | * "cgit-0.7.2". If this is a valid commit object name we've got a winner. |
| @@ -185,6 +243,8 @@ void cgit_print_snapshot(const char *head, const char *hex, | |||
| 185 | const char *filename, int dwim) | 243 | const char *filename, int dwim) |
| 186 | { | 244 | { |
| 187 | const struct cgit_snapshot_format* f; | 245 | const struct cgit_snapshot_format* f; |
| 246 | const char *sig_filename = NULL; | ||
| 247 | char *adj_filename = NULL; | ||
| 188 | char *prefix = NULL; | 248 | char *prefix = NULL; |
| 189 | 249 | ||
| 190 | if (!filename) { | 250 | if (!filename) { |
| @@ -193,6 +253,15 @@ void cgit_print_snapshot(const char *head, const char *hex, | |||
| 193 | return; | 253 | return; |
| 194 | } | 254 | } |
| 195 | 255 | ||
| 256 | if (ends_with(filename, ".asc")) { | ||
| 257 | sig_filename = filename; | ||
| 258 | |||
| 259 | /* Strip ".asc" from filename for common format processing */ | ||
| 260 | adj_filename = xstrdup(filename); | ||
| 261 | adj_filename[strlen(adj_filename) - 4] = '\0'; | ||
| 262 | filename = adj_filename; | ||
| 263 | } | ||
| 264 | |||
| 196 | f = get_format(filename); | 265 | f = get_format(filename); |
| 197 | if (!f || !(ctx.repo->snapshots & f->bit)) { | 266 | if (!f || !(ctx.repo->snapshots & f->bit)) { |
| 198 | cgit_print_error_page(400, "Bad request", | 267 | cgit_print_error_page(400, "Bad request", |
| @@ -216,6 +285,11 @@ void cgit_print_snapshot(const char *head, const char *hex, | |||
| 216 | if (!prefix) | 285 | if (!prefix) |
| 217 | prefix = xstrdup(cgit_snapshot_prefix(ctx.repo)); | 286 | prefix = xstrdup(cgit_snapshot_prefix(ctx.repo)); |
| 218 | 287 | ||
| 219 | make_snapshot(f, hex, prefix, filename); | 288 | if (sig_filename) |
| 289 | write_sig(f, hex, filename, sig_filename); | ||
| 290 | else | ||
| 291 | make_snapshot(f, hex, prefix, filename); | ||
| 292 | |||
| 220 | free(prefix); | 293 | free(prefix); |
| 294 | free(adj_filename); | ||
| 221 | } | 295 | } |
