diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/mirrors/DownloadMirror.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/mirrors/DownloadMirror.java index f24159a32..2cced7b7e 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/mirrors/DownloadMirror.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/mirrors/DownloadMirror.java @@ -87,6 +87,29 @@ public class DownloadMirror { } } + /** + * Download a file as a string from the current mirror. If the file does not exist on the mirror + * or the mirror returns an invalid string, request the file from the original source + * @param downloadClass Class of the download. Can either be DOWNLOAD_CLASS_LIBRARIES, + * DOWNLOAD_CLASS_METADATA or DOWNLOAD_CLASS_ASSETS + * @param urlInput The original (Mojang) URL for the download + * @return the contents of the downloaded file as a String. + */ + public static String downloadStringMirrored(int downloadClass, String urlInput) throws IOException{ + String resultString = null; + try { + resultString = DownloadUtils.downloadString(getMirrorMapping(downloadClass,urlInput)); + }catch (FileNotFoundException e) { + Log.w("DownloadMirror", "Failed to download string from mirror", e); + } + if(Tools.isValidString(resultString)) { + return resultString; + }else { + Log.w("DownloadMirror", "Downloaded string is invalid, falling back to default"); + } + return DownloadUtils.downloadString(urlInput); + } + /** * Check if the current download source is a mirror and not an official source. * @return true if the source is a mirror, false otherwise diff --git a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloader.java b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloader.java index 95074cc80..ade63b2b2 100644 --- a/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloader.java +++ b/app_pojavlauncher/src/main/java/net/kdt/pojavlaunch/tasks/MinecraftDownloader.java @@ -368,6 +368,8 @@ public class MinecraftDownloader { mSourceJarFile = clientJar; } + + private static byte[] getLocalBuffer() { byte[] tlb = sThreadLocalDownloadBuffer.get(); if(tlb != null) return tlb; @@ -395,6 +397,40 @@ public class MinecraftDownloader { this.mSkipIfFailed = skipIfFailed; } + private String downloadSha1() throws IOException { + String downloadedHash = DownloadMirror.downloadStringMirrored( + mDownloadClass, mTargetUrl + ".sha1" + ); + if(!Tools.isValidString(downloadedHash)) return null; + // Ensure that we don't have leading/trailing whitespaces before checking hash length + downloadedHash = downloadedHash.trim(); + // SHA1 is made up of 20 bytes, which means 40 hexadecimal digits, which means 40 chars + if(downloadedHash.length() != 40) return null; + return downloadedHash; + } + + /** + * Maven repositories usually have the hash of a library near it, like: + * .../libraryName-1.0.jar + * .../libraryName.1.0.jar.sha1 + * Since Minecraft libraries are stored in maven repositories, try to use + * this when downloading libraries without hashes in the json. + */ + private void tryGetLibrarySha1() { + String resultHash = null; + try { + resultHash = downloadSha1(); + }catch (IOException e) { + Log.i("MinecraftDownloader", "Failed to download hash", e); + } + if(resultHash != null) { + Log.i("MinecraftDownloader", "Got hash: "+resultHash+ " for "+FileUtils.getFileName(mTargetUrl)); + mTargetSha1 = resultHash; + } + // The hash is a 40-byte download. + mInternetUsageCounter.getAndAdd(40); + } + @Override public void run() { try { @@ -405,6 +441,10 @@ public class MinecraftDownloader { } private void runCatching() throws Exception { + if(mDownloadClass == DownloadMirror.DOWNLOAD_CLASS_LIBRARIES && !Tools.isValidString(mTargetSha1)) { + // If we're downloading a library, try to get sha1 since it might be available as a file + tryGetLibrarySha1(); + } if(Tools.isValidString(mTargetSha1)) { verifyFileSha1(); }else {