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 f24159a328..2cced7b7ee 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 static long getContentLengthMirrored(int downloadClass, String urlInput) } } + /** + * 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 95074cc804..6c6670384e 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 @@ -395,6 +395,40 @@ private final class DownloaderTask implements Runnable, Tools.DownloaderFeedback 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(); + // The hash is a 40-byte download. + mInternetUsageCounter.getAndAdd(40); + }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; + } + } + @Override public void run() { try { @@ -405,6 +439,10 @@ public void run() { } 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 {