mirror of
https://github.com/HMCL-dev/HMCL.git
synced 2025-09-17 15:57:18 -04:00
parent
ba91c60e95
commit
e08ba4d421
@ -18,7 +18,6 @@
|
||||
package org.jackhuang.hmcl.download.game;
|
||||
|
||||
import org.jackhuang.hmcl.download.AbstractDependencyManager;
|
||||
import org.jackhuang.hmcl.download.ArtifactMalformedException;
|
||||
import org.jackhuang.hmcl.download.DefaultCacheRepository;
|
||||
import org.jackhuang.hmcl.game.Library;
|
||||
import org.jackhuang.hmcl.task.DownloadException;
|
||||
@ -26,13 +25,12 @@ import org.jackhuang.hmcl.task.FileDownloadTask;
|
||||
import org.jackhuang.hmcl.task.FileDownloadTask.IntegrityCheck;
|
||||
import org.jackhuang.hmcl.task.Task;
|
||||
import org.jackhuang.hmcl.util.DigestUtils;
|
||||
import org.jackhuang.hmcl.util.Pack200Utils;
|
||||
import org.jackhuang.hmcl.util.io.FileUtils;
|
||||
import org.jackhuang.hmcl.util.io.IOUtils;
|
||||
import org.jackhuang.hmcl.util.io.NetworkUtils;
|
||||
import org.tukaani.xz.XZInputStream;
|
||||
|
||||
import java.io.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@ -41,7 +39,6 @@ import java.util.*;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static org.jackhuang.hmcl.util.Logging.LOG;
|
||||
@ -51,10 +48,8 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
protected final File jar;
|
||||
protected final DefaultCacheRepository cacheRepository;
|
||||
protected final AbstractDependencyManager dependencyManager;
|
||||
private final File xzFile;
|
||||
protected final Library library;
|
||||
protected final String url;
|
||||
protected boolean xz;
|
||||
private final Library originalLibrary;
|
||||
private boolean cached = false;
|
||||
|
||||
@ -72,8 +67,6 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
|
||||
url = library.getDownload().getUrl();
|
||||
jar = file;
|
||||
|
||||
xzFile = new File(file.getAbsoluteFile().getParentFile(), file.getName() + ".pack.xz");
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -101,8 +94,6 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
throw new CancellationException();
|
||||
else
|
||||
throw new LibraryDownloadException(library, t);
|
||||
} else {
|
||||
if (xz) unpackLibrary(jar, Files.readAllBytes(xzFile.toPath()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,36 +117,13 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
}
|
||||
}
|
||||
|
||||
if (Pack200Utils.isSupported() && testURLExistence(url)) {
|
||||
List<URL> urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url + ".pack.xz");
|
||||
task = new FileDownloadTask(urls, xzFile, null);
|
||||
task.setCacheRepository(cacheRepository);
|
||||
task.setCaching(true);
|
||||
xz = true;
|
||||
} else {
|
||||
List<URL> urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url);
|
||||
task = new FileDownloadTask(urls, jar,
|
||||
library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null);
|
||||
task.setCacheRepository(cacheRepository);
|
||||
task.setCaching(true);
|
||||
task.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER);
|
||||
xz = false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean testURLExistence(String rawUrl) {
|
||||
List<URL> urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(rawUrl);
|
||||
for (URL url : urls) {
|
||||
URL xzURL = NetworkUtils.toURL(url.toString() + ".pack.xz");
|
||||
for (int retry = 0; retry < 3; retry++) {
|
||||
try {
|
||||
return NetworkUtils.urlExists(xzURL);
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.WARNING, "Failed to test for url existence: " + url + ".pack.xz", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false; // maybe some ugly implementation will give timeout for not existent url.
|
||||
List<URL> urls = dependencyManager.getDownloadProvider().injectURLWithCandidates(url);
|
||||
task = new FileDownloadTask(urls, jar,
|
||||
library.getDownload().getSha1() != null ? new IntegrityCheck("SHA-1", library.getDownload().getSha1()) : null);
|
||||
task.setCacheRepository(cacheRepository);
|
||||
task.setCaching(true);
|
||||
task.addIntegrityCheckHandler(FileDownloadTask.ZIP_INTEGRITY_CHECK_HANDLER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -167,7 +135,7 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
public void postExecute() throws Exception {
|
||||
if (!cached) {
|
||||
try {
|
||||
cacheRepository.cacheLibrary(library, jar.toPath(), xz);
|
||||
cacheRepository.cacheLibrary(library, jar.toPath(), false);
|
||||
} catch (IOException e) {
|
||||
LOG.log(Level.WARNING, "Failed to cache downloaded library " + library, e);
|
||||
}
|
||||
@ -232,44 +200,4 @@ public class LibraryDownloadTask extends Task<Void> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void unpackLibrary(File dest, byte[] src) throws IOException {
|
||||
if (dest.exists())
|
||||
if (!dest.delete())
|
||||
throw new IOException("Unable to delete file " + dest);
|
||||
|
||||
byte[] decompressed;
|
||||
try {
|
||||
decompressed = IOUtils.readFullyAsByteArray(new XZInputStream(new ByteArrayInputStream(src)));
|
||||
} catch (IOException e) {
|
||||
throw new ArtifactMalformedException("Library " + dest + " is malformed");
|
||||
}
|
||||
|
||||
String end = new String(decompressed, decompressed.length - 4, 4);
|
||||
if (!end.equals("SIGN"))
|
||||
throw new IOException("Unpacking failed, signature missing " + end);
|
||||
|
||||
int x = decompressed.length;
|
||||
int len = decompressed[(x - 8)] & 0xFF | (decompressed[(x - 7)] & 0xFF) << 8 | (decompressed[(x - 6)] & 0xFF) << 16 | (decompressed[(x - 5)] & 0xFF) << 24;
|
||||
|
||||
Path temp = Files.createTempFile("minecraft", ".pack");
|
||||
|
||||
byte[] checksums = Arrays.copyOfRange(decompressed, decompressed.length - len - 8, decompressed.length - 8);
|
||||
|
||||
try (OutputStream out = Files.newOutputStream(temp)) {
|
||||
out.write(decompressed, 0, decompressed.length - len - 8);
|
||||
}
|
||||
|
||||
try (FileOutputStream jarBytes = new FileOutputStream(dest); JarOutputStream jos = new JarOutputStream(jarBytes)) {
|
||||
Pack200Utils.unpack(temp.toFile(), jos);
|
||||
|
||||
JarEntry checksumsFile = new JarEntry("checksums.sha1");
|
||||
checksumsFile.setTime(0L);
|
||||
jos.putNextEntry(checksumsFile);
|
||||
jos.write(checksums);
|
||||
jos.closeEntry();
|
||||
}
|
||||
|
||||
Files.delete(temp);
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user