Improve minecraft-client.jar download to use a temporary file before verification

This commit is contained in:
Lukas Rieger (Blue) 2024-12-10 23:52:53 +01:00
parent 7200e94262
commit 51f12741c9
No known key found for this signature in database
GPG Key ID: AA33883B1BBA03E6

View File

@ -134,32 +134,41 @@ public static MinecraftVersion load(@Nullable String id, Path dataRoot, boolean
} }
private static void download(VersionManifest.Version version, Path file) throws IOException { private static void download(VersionManifest.Version version, Path file) throws IOException {
boolean downloadCompletedAndVerified = false;
VersionManifest.Download download = version.fetchDetail().getDownloads().getClient(); VersionManifest.Download download = version.fetchDetail().getDownloads().getClient();
Logger.global.logInfo("Downloading '" + download.getUrl() + "' to '" + file + "'..."); Logger.global.logInfo("Downloading '" + download.getUrl() + "' to '" + file + "'...");
FileHelper.createDirectories(file.toAbsolutePath().normalize().getParent()); FileHelper.createDirectories(file.toAbsolutePath().normalize().getParent());
Path unverifiedFile = file.getParent().resolve(file.getFileName().toString() + ".unverified");
try ( try {
DigestInputStream in = new DigestInputStream(new URI(download.getUrl()).toURL().openStream(), MessageDigest.getInstance("SHA-1")); try (
OutputStream out = Files.newOutputStream(file, StandardOpenOption.WRITE, StandardOpenOption.CREATE_NEW, StandardOpenOption.TRUNCATE_EXISTING) DigestInputStream in = new DigestInputStream(
) { new URI(download.getUrl()).toURL().openStream(),
in.transferTo(out); MessageDigest.getInstance("SHA-1")
);
OutputStream out = Files.newOutputStream(unverifiedFile)
) {
// download
in.transferTo(out);
// verify sha-1
if (!Arrays.equals(
in.getMessageDigest().digest(),
hexStringToByteArray(download.getSha1())
)) {
throw new IOException("SHA-1 of the downloaded file does not match!");
}
// verify sha-1
if (!Arrays.equals(
in.getMessageDigest().digest(),
hexStringToByteArray(download.getSha1())
)) {
throw new IOException("SHA-1 of the downloaded file does not match!");
} }
downloadCompletedAndVerified = true; // rename once verified
FileHelper.atomicMove(unverifiedFile, file);
} catch (NoSuchAlgorithmException | IOException | URISyntaxException ex) { } catch (NoSuchAlgorithmException | IOException | URISyntaxException ex) {
Logger.global.logWarning("Failed to download '" + download.getUrl() + "': " + ex); Logger.global.logWarning("Failed to download '" + download.getUrl() + "': " + ex);
} finally { } finally {
if (!downloadCompletedAndVerified) Files.deleteIfExists(unverifiedFile);
Files.deleteIfExists(file);
} }
} }