| ... | ... | @@ -526,9 +526,7 @@ fn fetchAndUnpack( |
| 526 | 526 | // whose content-disposition header is: 'attachment; filename="<project>-<sha>.tar.gz"' |
| 527 | 527 | const content_disposition = req.response.headers.getFirstValue("Content-Disposition") orelse |
| 528 | 528 | return report.fail(dep.url_tok, "Missing 'Content-Disposition' header for Content-Type=application/octet-stream", .{}); |
| 529 | | if (mem.startsWith(u8, content_disposition, "attachment;") and |
| 530 | | mem.endsWith(u8, content_disposition, ".tar.gz\"")) |
| 531 | | { |
| 529 | if (isTarAttachment(content_disposition)) { |
| 532 | 530 | try unpackTarball(gpa, &req, tmp_directory.handle, std.compress.gzip); |
| 533 | 531 | } else return report.fail(dep.url_tok, "Unsupported 'Content-Disposition' header value: '{s}' for Content-Type=application/octet-stream", .{content_disposition}); |
| 534 | 532 | } else { |
| ... | ... | @@ -766,3 +764,37 @@ fn renameTmpIntoCache( |
| 766 | 764 | break; |
| 767 | 765 | } |
| 768 | 766 | } |
| 767 | |
| 768 | fn isTarAttachment(content_disposition: []const u8) bool { |
| 769 | const disposition_type_end = ascii.indexOfIgnoreCase(content_disposition, "attachment;") orelse return false; |
| 770 | |
| 771 | var value_start = ascii.indexOfIgnoreCasePos(content_disposition, disposition_type_end + 1, "filename") orelse return false; |
| 772 | value_start += "filename".len; |
| 773 | if (content_disposition[value_start] == '*') { |
| 774 | value_start += 1; |
| 775 | } |
| 776 | if (content_disposition[value_start] != '=') return false; |
| 777 | value_start += 1; |
| 778 | |
| 779 | var value_end = mem.indexOfPos(u8, content_disposition, value_start, ";") orelse content_disposition.len; |
| 780 | if (content_disposition[value_end - 1] == '\"') { |
| 781 | value_end -= 1; |
| 782 | } |
| 783 | return ascii.endsWithIgnoreCase(content_disposition[value_start..value_end], ".tar.gz"); |
| 784 | } |
| 785 | |
| 786 | test "isTarAttachment" { |
| 787 | try std.testing.expect(isTarAttachment("attaChment; FILENAME=\"stuff.tar.gz\"; size=42")); |
| 788 | try std.testing.expect(isTarAttachment("attachment; filename*=\"stuff.tar.gz\"")); |
| 789 | try std.testing.expect(isTarAttachment("ATTACHMENT; filename=\"stuff.tar.gz\"")); |
| 790 | try std.testing.expect(isTarAttachment("attachment; FileName=\"stuff.tar.gz\"")); |
| 791 | try std.testing.expect(isTarAttachment("attachment; FileName*=UTF-8\'\'xyz%2Fstuff.tar.gz")); |
| 792 | |
| 793 | try std.testing.expect(!isTarAttachment("attachment FileName=\"stuff.tar.gz\"")); |
| 794 | try std.testing.expect(!isTarAttachment("attachment; FileName=\"stuff.tar\"")); |
| 795 | try std.testing.expect(!isTarAttachment("attachment; FileName\"stuff.gz\"")); |
| 796 | try std.testing.expect(!isTarAttachment("attachment; size=42")); |
| 797 | try std.testing.expect(!isTarAttachment("inline; size=42")); |
| 798 | try std.testing.expect(!isTarAttachment("FileName=\"stuff.tar.gz\"; attachment;")); |
| 799 | try std.testing.expect(!isTarAttachment("FileName=\"stuff.tar.gz\";")); |
| 800 | } |