diff options
Diffstat (limited to 'src/net/minecraft/GameUpdater.java')
-rw-r--r-- | src/net/minecraft/GameUpdater.java | 205 |
1 files changed, 107 insertions, 98 deletions
diff --git a/src/net/minecraft/GameUpdater.java b/src/net/minecraft/GameUpdater.java index be2f532..9a79880 100644 --- a/src/net/minecraft/GameUpdater.java +++ b/src/net/minecraft/GameUpdater.java @@ -1,21 +1,42 @@ package net.minecraft; import java.applet.Applet; -import java.io.*; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FilePermission; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.net.*; -import java.security.*; -import java.security.cert.Certificate; +import java.net.HttpURLConnection; +import java.net.SocketPermission; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.AccessControlException; +import java.security.AccessController; +import java.security.CodeSource; +import java.security.PermissionCollection; +import java.security.PrivilegedExceptionAction; +import java.security.SecureClassLoader; import java.util.Enumeration; -import java.util.StringTokenizer; import java.util.Vector; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; import java.util.jar.JarOutputStream; import java.util.jar.Pack200; - +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; public class GameUpdater implements Runnable { public static final int STATE_INIT = 1; @@ -61,7 +82,7 @@ public class GameUpdater implements Runnable { } public void init() { - this.state = 1; + this.state = STATE_INIT; try { Class.forName("LZMA.LzmaInputStream"); @@ -88,25 +109,25 @@ public class GameUpdater implements Runnable { protected String getDescriptionForState() { switch (this.state) { - case 1: + case STATE_INIT: return "Initializing loader"; - case 2: + case STATE_DETERMINING_PACKAGES: return "Determining packages to load"; - case 3: + case STATE_CHECKING_CACHE: return "Checking cache for existing files"; - case 4: + case STATE_DOWNLOADING: return "Downloading packages"; - case 5: + case STATE_EXTRACTING_PACKAGES: return "Extracting downloaded packages"; - case 6: + case STATE_UPDATING_CLASSPATH: return "Updating classpath"; - case 7: + case STATE_SWITCHING_APPLET: return "Switching applet"; - case 8: + case STATE_INITIALIZE_REAL_APPLET: return "Initializing real applet"; - case 9: + case STATE_START_REAL_APPLET: return "Starting real applet"; - case 10: + case STATE_DONE: return "Done loading"; } return "unknown state"; @@ -125,49 +146,47 @@ public class GameUpdater implements Runnable { } protected void loadJarURLs() throws Exception { - this.state = 2; - String jarList = "lwjgl.jar, jinput.jar, lwjgl_util.jar, " + this.mainGameUrl; - jarList = trimExtensionByCapabilities(jarList); - - StringTokenizer jar = new StringTokenizer(jarList, ", "); - int jarCount = jar.countTokens() + 1; - - this.urlList = new URL[jarCount]; + this.state = STATE_DETERMINING_PACKAGES; - URL path = new URL("http://s3.amazonaws.com/MinecraftDownload/"); - - for (int i = 0; i < jarCount - 1; i++) { - this.urlList[i] = new URL(path, jar.nextToken()); - } + URL path = new URL("http://files.betacraft.uk/launcher/assets/"); + this.urlList = new URL[3]; String osName = System.getProperty("os.name"); - String nativeJar = null; + String librariesZip = "libs.zip"; + String nativesZip = null; if (osName.startsWith("Win")) { - nativeJar = "windows_natives.jar.lzma"; + librariesZip = "libs-windows.zip"; + nativesZip = "natives-windows.zip"; } else if (osName.startsWith("Linux")) { - nativeJar = "linux_natives.jar.lzma"; + librariesZip = "libs-linux.zip"; + nativesZip = "natives-linux.zip"; } else if (osName.startsWith("Mac")) { - nativeJar = "macosx_natives.jar.lzma"; - } else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) { - nativeJar = "solaris_natives.jar.lzma"; + librariesZip = "libs-osx.zip"; + nativesZip = "natives-osx.zip"; } else { fatalErrorOccured("OS (" + osName + ") not supported", null); + return; } - if (nativeJar == null) { + if (nativesZip == null) { fatalErrorOccured("no lwjgl natives files found", null); } else { - nativeJar = trimExtensionByCapabilities(nativeJar); - this.urlList[jarCount - 1] = new URL(path, nativeJar); + this.urlList[0] = new URL(path, nativesZip); } + + this.urlList[1] = new URL(path, librariesZip); + + // TODO: BetaCraft's server only has versions missing from mojang's download site. + // The launcher should use the info in "jsons.zip" to get the URL for the jar download. + this.urlList[2] = new URL(path, "versions/a1.0.13.jar"); } public void run() { init(); - this.state = 3; + this.state = STATE_CHECKING_CACHE; this.percentage = 5; try { @@ -209,7 +228,7 @@ public class GameUpdater implements Runnable { } updateClassPath(dir); - this.state = 10; + this.state = STATE_DONE; } catch (AccessControlException ace) { fatalErrorOccured(ace.getMessage(), ace); this.certificateRefused = true; @@ -235,13 +254,14 @@ public class GameUpdater implements Runnable { protected void updateClassPath(File dir) throws Exception { - this.state = 6; + this.state = STATE_UPDATING_CLASSPATH; this.percentage = 95; - URL[] urls = new URL[this.urlList.length]; - for (int i = 0; i < this.urlList.length; i++) { - urls[i] = (new File(dir, getJarName(this.urlList[i]))).toURI().toURL(); + File[] files = dir.listFiles((dir1, name) -> name.endsWith(".jar")); + URL[] urls = new URL[files.length]; + for (int i = 0; i < files.length; i++) { + urls[i] = files[i].toURI().toURL(); } if (classLoader == null) { @@ -318,8 +338,7 @@ public class GameUpdater implements Runnable { protected void downloadJars(String path) throws Exception { - this.state = 4; - + this.state = STATE_DOWNLOADING; int[] fileSizes = new int[this.urlList.length]; @@ -511,9 +530,28 @@ public class GameUpdater implements Runnable { f.delete(); } + protected void extractZIP(String in, String out) throws Exception { + File originalFile = new File(in); + Path targetDir = originalFile.toPath().getParent(); + ZipInputStream zipStream = new ZipInputStream(Files.newInputStream(originalFile.toPath())); + + ZipEntry entry; + while ((entry = zipStream.getNextEntry()) != null) { + Path resolvedPath = targetDir.resolve(entry.getName()).normalize(); + if (!resolvedPath.startsWith(targetDir)) { + throw new RuntimeException("Entry with illegal path: " + entry.getName()); + } + if (entry.isDirectory()) { + Files.createDirectories(resolvedPath); + } else { + Files.createDirectories(resolvedPath.getParent()); + Files.copy(zipStream, resolvedPath); + } + } + } protected void extractJars(String path) throws Exception { - this.state = 5; + this.state = STATE_EXTRACTING_PACKAGES; float increment = 10.0F / this.urlList.length; @@ -533,20 +571,23 @@ public class GameUpdater implements Runnable { } else if (filename.endsWith(".lzma")) { this.subtaskMessage = "Extracting: " + filename + " to " + filename.replace(".lzma", ""); extractLZMA(path + filename, path + filename.replace(".lzma", "")); + } else if (filename.endsWith(".zip")) { + this.subtaskMessage = "Extracting: " + filename + " to " + filename.replace(".zip", ""); + // TODO: This should only operate on the libraries zip + extractZIP(path + filename, path + filename.replace(".zip", "")); } } } protected void extractNatives(String path) throws Exception { - this.state = 5; - + this.state = STATE_EXTRACTING_PACKAGES; int initialPercentage = this.percentage; - String nativeJar = getJarName(this.urlList[this.urlList.length - 1]); + String nativeJar = getJarName(this.urlList[0]); + /* TODO: There should still be some kind of validation probably Certificate[] certificate = Launcher.class.getProtectionDomain().getCodeSource().getCertificates(); - if (certificate == null) { URL location = Launcher.class.getProtectionDomain().getCodeSource().getLocation(); @@ -557,50 +598,38 @@ public class GameUpdater implements Runnable { } catch (Exception exception) { } } - + */ File nativeFolder = new File(path + "natives"); if (!nativeFolder.exists()) { nativeFolder.mkdir(); } - JarFile jarFile = new JarFile(path + nativeJar, true); - Enumeration<JarEntry> entities = jarFile.entries(); + ZipFile zipFile = new ZipFile(path + nativeJar); + Enumeration<? extends ZipEntry> entities = zipFile.entries(); this.totalSizeExtract = 0; - - while (entities.hasMoreElements()) { - JarEntry entry = entities.nextElement(); - - - if (entry.isDirectory() || entry.getName().indexOf('/') != -1) { + ZipEntry entry = entities.nextElement(); + if (entry.isDirectory() || entry.getName().indexOf('/') != -1) continue; - } this.totalSizeExtract = (int) (this.totalSizeExtract + entry.getSize()); } this.currentSizeExtract = 0; - - entities = jarFile.entries(); - + entities = zipFile.entries(); while (entities.hasMoreElements()) { - JarEntry entry = entities.nextElement(); + ZipEntry entry = entities.nextElement(); - if (entry.isDirectory() || entry.getName().indexOf('/') != -1) { + if (entry.isDirectory() || entry.getName().indexOf('/') != -1) continue; - } File file = new File(path + "natives" + File.separator + entry.getName()); - if (file.exists() && - !file.delete()) { + if (file.exists() && !file.delete()) continue; - } - - - InputStream in = jarFile.getInputStream(jarFile.getEntry(entry.getName())); - OutputStream out = new FileOutputStream(path + "natives" + File.separator + entry.getName()); + InputStream in = zipFile.getInputStream(zipFile.getEntry(entry.getName())); + OutputStream out = Files.newOutputStream(Paths.get(nativeFolder.getPath(), entry.getName())); byte[] buffer = new byte[65536]; int bufferSize; @@ -612,36 +641,17 @@ public class GameUpdater implements Runnable { this.subtaskMessage = "Extracting: " + entry.getName() + " " + (this.currentSizeExtract * 100 / this.totalSizeExtract) + "%"; } - validateCertificateChain(certificate, entry.getCertificates()); - in.close(); out.close(); } this.subtaskMessage = ""; - jarFile.close(); + zipFile.close(); File f = new File(path + nativeJar); f.delete(); } - - protected static void validateCertificateChain(Certificate[] ownCerts, Certificate[] native_certs) throws Exception { - if (ownCerts == null) - return; - if (native_certs == null) - throw new Exception("Unable to validate certificate chain. Native entry did not have a certificate chain at all"); - - if (ownCerts.length != native_certs.length) - throw new Exception("Unable to validate certificate chain. Chain differs in length [" + ownCerts.length + " vs " + native_certs.length + "]"); - - for (int i = 0; i < ownCerts.length; i++) { - if (!ownCerts[i].equals(native_certs[i])) { - throw new Exception("Certificate mismatch: " + ownCerts[i] + " != " + native_certs[i]); - } - } - } - protected String getJarName(URL url) { String fileName = url.getFile(); @@ -677,7 +687,6 @@ public class GameUpdater implements Runnable { } } - public boolean canPlayOffline() { try { String path = AccessController.doPrivileged(new PrivilegedExceptionAction<String>() { |