package NET.worlds.network; import NET.worlds.console.Console; import NET.worlds.console.Gamma; import NET.worlds.console.InternetConnectionDialog; import NET.worlds.console.LoginWizard; import NET.worlds.console.Main; import NET.worlds.console.Window; import NET.worlds.console.WorldsMarkPart; import NET.worlds.core.IniFile; import NET.worlds.core.RegKey; import NET.worlds.core.RegKeyNotFoundException; import NET.worlds.core.ServerTableManager; import NET.worlds.core.Std; import NET.worlds.scape.SendURLAction; import NET.worlds.scape.World; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.text.MessageFormat; import java.util.Date; import java.util.StringTokenizer; import java.util.Vector; public class NetUpdate implements Runnable, RemoteFileConst { static final String VERSIONS = "upgrades.lst"; static final String WORLDVERSIONS = "upgrades.lst"; static final String SERVER = "upgradeServer"; static final String RESTARTCMD = "WorldsPlayer.exe"; static final String WORLDCURVER = "\\ver.txt"; static final String UPGRADER = ".\\bin\\gdkup.exe"; static final String SCRIPTFILE = "updates.lst"; static final String LANGUAGES = "languages.lst"; static final int UPGRADETIMEOUT = IniFile.gamma().getIniInt("upgradeTimeout", 7); static int TESTAUTOUPGRADE = IniFile.gamma().getIniInt("testautoupgrade", 0); static final int TESTWORLDAUTOUPGRADE = IniFile.gamma().getIniInt("testworldautoupgrade", 0); private static String uServer = getUpgradeServerIniEntry(IniFile.gamma()); private static String overrideServer; public static String overrideWorldServer = null; private static int _today; private static boolean beenCalled; static int gdkver; private boolean _force; private boolean forceWorldLoad; private String worldToUpdate; static int maxVers; private static final String INTERNAL = "internal"; private static final String EXTERNAL = "external"; private static int maxworld; private static Object updateLoadSyncer; static { IniFile oini = IniFile.override(); if (oini != null) { overrideWorldServer = oini.getIniString("WorldServer", ""); if (overrideWorldServer.equals("")) { if (Gamma.shaperEnabled()) { overrideWorldServer = "worldserver://test.3dcd.com"; } else { overrideWorldServer = null; } } } String s = getUpgradeServerIniEntry(oini); if (!s.equals("")) { overrideServer = s; uServer = s; } URL.setHttpServer(uServer.substring(0, uServer.lastIndexOf(47) + 1)); beenCalled = false; gdkver = 0; maxVers = IniFile.gamma().getIniInt("maxupgradeversion", 999999999); maxworld = -1; updateLoadSyncer = new Object(); } static String getUpgradeServerIniEntry(IniFile ini) { return ini == null ? "" : ini.getIniString("upgradeServer", ""); } public static void setUpgradeServerURL(String url) { if (overrideServer == null) { String upgradeDir = uServer; int start = upgradeDir.length() - 1; if (start != -1) { if (upgradeDir.charAt(start) == '/') { start--; } upgradeDir = upgradeDir.substring(upgradeDir.lastIndexOf(47, start)); uServer = url + upgradeDir; URL.setHttpServer(url + "/"); } } } public static boolean isInternalVersion() { String chatName = null; Console c = Console.getActive(); Galaxy g = null; if (c != null) { g = c.getGalaxy(); } if (g != null && g.getOnline()) { chatName = g.getChatname(); } else { String entry = IniFile.gamma().getIniString("lastchatname", "Fred"); if (entry.startsWith("VIP ") || entry.startsWith("vip ")) { chatName = entry.substring(4); } } if (chatName != null) { String[] employeeList = ServerTableManager.instance().getTable("employeeAccounts"); if (employeeList == null) { return false; } for (int i = 0; i < employeeList.length; i++) { if (employeeList[i].equals(chatName)) { return true; } } } return false; } public static String getInfoURL() { return getInfoURL(""); } public static String getInfoURL(String info) { String url = getUpgradeServerURL(); if (url == null) { return null; } else { String page = IniFile.override().getIniString("InfoPage", "index" + Console.message(".html")); if (Console.wasHttpNoSuchFile(url + info + page)) { page = IniFile.override().getIniString("InfoPage", "index.html"); } return url + info + page; } } public static String getUpgradeServerURL() { if (uServer.equals("")) { return null; } else { if (!uServer.endsWith("/")) { uServer = uServer + "/"; } return uServer; } } public static void showInfo() { showInfo(""); } public static void showInfo(String info) { new SendURLAction(getInfoURL(info)).startBrowser(); } private static boolean openPage(String browser, String destination) { DDEMLClass ddeml = new DDEMLClass(browser, "WWW_Activate"); boolean val = ddeml.Request("-1,0"); ddeml.destroy(); if (!val) { return false; } else { ddeml = new DDEMLClass(browser, "WWW_OpenURL"); val = ddeml.Request("\"" + destination + "\",,-1,0,,,"); ddeml.destroy(); return val; } } private NetUpdate(boolean force) { this._force = force; } private NetUpdate(String w) { this.worldToUpdate = w; } private NetUpdate(String w, boolean forceWorldLoad) { this.worldToUpdate = w; this.forceWorldLoad = forceWorldLoad; } static void notifyUser(String msg) { Console.println(msg); } static void warnUser(String msg) { IniFile.gamma().setIniString("RunUpgrade", ""); notifyUser(msg); } private static boolean timeToUpdate(boolean force) { while (Window.getMainWindow() == null || !LoginWizard.isFirstTimeDone() && !InternetConnectionDialog.isFirstTimeDone()) { try { Thread.sleep(1000L); } catch (InterruptedException var2) { } } if (!force) { if (IniFile.gamma().getIniInt("lastUpgradeCheck", 0) + UPGRADETIMEOUT > _today) { return false; } if (!LoginWizard.isFirstTimeDone() && InternetConnectionDialog.choseSingleUserMode()) { return false; } } if (getUpgradeServerURL() == null) { Object[] arguments = new Object[]{new String("upgradeServer")}; notifyUser(MessageFormat.format(Console.message("upgrade-check"), arguments)); return false; } else { return true; } } private static int getNextVers(String line, int vers, int testLevel, int[] retSize) { StringTokenizer st = null; try { st = new StringTokenizer(line); if (!st.hasMoreTokens()) { return -1; } else { int v = Integer.parseInt(st.nextToken()); if (st.hasMoreTokens() && (vers < 0 || v == vers) && (vers >= 0 || v <= 0 && v >= vers)) { int best = -1; while (st.hasMoreTokens()) { String s = st.nextToken(); int colon = s.indexOf(58); if (colon != -1) { int need = Integer.parseInt(s.substring(colon + 1)); if (need > 9999) { need /= 10; } int fixedGdkVer = gdkver <= 9999 ? gdkver : gdkver / 10; int curVer = Std.getVersion(); curVer = curVer <= 9999 ? curVer : curVer / 10; if (need > curVer || gdkver != 0 && need > fixedGdkVer) { continue; } s = s.substring(0, colon); } int size = 160000; int pound = s.indexOf(35); if (pound != -1) { size = Integer.parseInt(s.substring(pound + 1)); s = s.substring(0, pound); } int t = Integer.parseInt(s); int level = 0; if (t >= 999000000) { t -= 999000000; level = t / 100000 + 1; t %= 100000; if (level > testLevel) { continue; } } if (t <= maxVers && t > best) { best = t; retSize[0] = size; } } return best; } else { return -1; } } } catch (NumberFormatException var13) { return -1; } } private static String getVersions( URL remoteName, int vers, String patchRoot, Vector numbers, Vector patches, Vector sizes, String readableName, int test ) { CacheFile cf = Cache.getFile(remoteName, true); cf.waitUntilLoaded(); if (cf.error()) { return "Network error retrieving " + remoteName; } else { String localName = cf.getLocalName(); try { FileInputStream in = new FileInputStream(localName); DataInputStream dis = new DataInputStream(in); int[] size = new int[1]; String line; while ((line = dis.readLine()) != null) { int nextVersion = getNextVers(line, vers, test, size); if (nextVersion >= 0) { if (numbers != null) { numbers.addElement(new Integer(nextVersion)); } if (vers < 0) { patches.addElement(patchRoot + nextVersion + ".exe"); } else { patches.addElement(patchRoot + vers + "-" + nextVersion + ".exe"); } sizes.addElement(new Integer(size[0])); vers = nextVersion; } } dis.close(); in.close(); return null; } catch (FileNotFoundException var20) { return "system error re-opening " + localName + ": " + var20; } catch (IOException var21) { } finally { cf.close(); } return "System I/O error during upgrade processing"; } } public static String getLanguages(URL remoteName, Vector langIDs, Vector subLangIDs, int[] lSizes) { if (Gamma.loadProgress != null) { Gamma.loadProgress.setMessage("Downloading language support information..."); Gamma.loadProgress.advance(); } CacheFile cf = Cache.getFile(remoteName, true); cf.waitUntilLoaded(); if (cf.error()) { return "Network error retrieving " + remoteName; } else { String localName = cf.getLocalName(); try { FileInputStream in = new FileInputStream(localName); DataInputStream dis = new DataInputStream(in); String lang = null; String subLang = null; int sz = 0; int i = 0; String line; while ((line = dis.readLine()) != null) { if (line.charAt(2) != '_' && line.charAt(2) != ' ') { int lastSpace = line.lastIndexOf(32); lang = line.substring(0, lastSpace); subLang = null; int lng = line.length(); try { sz = Integer.parseInt(line.substring(lastSpace + 1, lng)); } catch (NumberFormatException var23) { System.out.println(line.substring(lastSpace, lng) + " is not quite a number"); } langIDs.addElement(lang); subLangIDs.addElement(subLang); lSizes[i++] = sz; } else { lang = line.substring(0, 2); subLang = line.substring(3, 5); int lng = line.length(); try { sz = Integer.parseInt(line.substring(6, lng)); } catch (NumberFormatException var24) { System.out.println(line.substring(6, lng) + " is not quite a number"); } langIDs.addElement(lang); subLangIDs.addElement(subLang); lSizes[i++] = sz; } } dis.close(); in.close(); return null; } catch (FileNotFoundException var25) { return "system error re-opening " + localName + ": " + var25; } catch (IOException var26) { } finally { cf.close(); } return "System I/O error during upgrade processing"; } } private static int wantUpdate(Vector numbers, Vector sizes, boolean first, String name, String info) { name = WorldsMarkPart.getExternalName(name); if (!Gamma.shaperEnabled()) { return numbers.size(); } else { Vector names = new Vector(); for (int i = 0; i < sizes.size(); i++) { names.addElement("Rev " + numbers.elementAt(i)); } return new UpgradeDialog(names, sizes, first, name, info, true).confirmUpgradeFromList(); } } private static Vector needUpdate(int gdkTo, Vector sizes, Vector names) { Vector versionList = new Vector(); Vector versionNumList = new Vector(); sizes.removeAllElements(); int curVersion = Std.getVersion(); String err = getVersions( URL.make(uServer + "upgrades.lst"), curVersion, "gdkup", versionNumList, versionList, sizes, Std.getProductName(), TESTAUTOUPGRADE ); if (err != null) { System.out.println(err); return versionList; } else { if (versionList.size() == 0 || gdkTo == 0 && (gdkTo = wantUpdate(versionNumList, sizes, false, Std.getProductName(), "")) <= 0) { gdkTo = 0; } versionList.setSize(gdkTo); sizes.setSize(gdkTo); for (int i = 0; i < gdkTo; i++) { names.addElement(i == gdkTo - 1 ? Std.getProductName() : null); } if (gdkTo > 0) { gdkver = versionNumList.elementAt(gdkTo - 1); } return versionList; } } public static int getCurrentVersionOfWorld(String worldDir, int curVersion) { if (worldDir.equals("")) { return curVersion; } else { try { DataInputStream dis = new DataInputStream(new FileInputStream(worldDir + "\\ver.txt")); String line = dis.readLine(); int lineStart = 0; if (line.charAt(0) == '+') { lineStart = line.indexOf(32) + 1; } if (line.regionMatches(true, lineStart, "internal", 0, "internal".length())) { line = line.substring(lineStart + "internal".length()); } else if (line.regionMatches(true, lineStart, "external", 0, "external".length())) { line = line.substring(lineStart + "external".length()); } curVersion = Integer.parseInt(line.trim()); } catch (FileNotFoundException var5) { } catch (IOException var6) { } catch (NumberFormatException var7) { System.out.println("Syntax error in " + worldDir + "\\ver.txt"); } return curVersion; } } private boolean listWorldUpgrades(String world, Vector versionList, Vector sizes, Vector names) { if (world.equals("")) { return true; } else { int curVersion = getCurrentVersionOfWorld(world, !this.forceWorldLoad && World.isCloistered() ? -1 : -2); Vector vnumlist = new Vector(); Vector exelist = new Vector(); Vector sizelist = new Vector(); String err = getVersions( URL.make(getUpgradeServerURL() + world + "/" + "upgrades.lst"), curVersion, world + "\\" + world, vnumlist, exelist, sizelist, world, TESTWORLDAUTOUPGRADE ); if (err != null) { System.out.println(err); } else { if (exelist.size() == 0) { return false; } String name = WorldsMarkPart.getExternalName(world) + " world"; int verto = wantUpdate(vnumlist, sizelist, curVersion < 0, "the " + name, world + "/"); if (verto > 0) { exelist.setSize(verto); sizelist.setSize(verto); for (int i = 0; i < verto; i++) { versionList.addElement(exelist.elementAt(i)); sizes.addElement(sizelist.elementAt(i)); names.addElement(i == verto - 1 ? name : null); } } } return true; } } public static int maxInstalledWorlds() { if (maxworld == -1) { IniFile ini = new IniFile("InstalledWorlds"); maxworld = ini.getIniInt("MaxInstalledWorlds", 0); ini.setIniInt("MaxInstalledWorlds", maxworld); } return maxworld + 50; } public static void maxInstalledWorld(int n) { if (maxworld == -1) { maxInstalledWorlds(); } if (n > maxworld) { maxworld = n; IniFile ini = new IniFile("InstalledWorlds"); ini.setIniInt("MaxInstalledWorlds", maxworld); } } public static Vector aboutWorlds() { Vector result = new Vector(); IniFile ini = new IniFile("InstalledWorlds"); for (int worldNum = 0; worldNum < maxInstalledWorlds(); worldNum++) { String name = ini.getIniString("InstalledWorld" + worldNum, "").trim(); int curVersion = getCurrentVersionOfWorld(name, -1); name = WorldsMarkPart.getExternalName(name); if (curVersion >= 0) { result.addElement(name + " version " + curVersion); maxInstalledWorld(worldNum); } } return result; } private static String getRestartCmd() { String restartCmd = "WorldsPlayer.exe"; return restartCmd + " world:restart"; } private static boolean hasString(Vector v, String s) { int j = v.size(); do { j--; } while (j >= 0 && !s.equals(v.elementAt(j))); return j >= 0; } private static Vector getLinesFromScriptFile(String restartCmd) { Vector lines = new Vector(); String scrFile = IniFile.gamma().getIniString("RunUpgrade", ""); if (!scrFile.equals("")) { DataInputStream dis = null; try { dis = new DataInputStream(new FileInputStream(scrFile)); String line; while ((line = dis.readLine()) != null) { if (restartCmd == null || !line.equals(restartCmd)) { lines.addElement(line.trim()); } } } catch (IOException var13) { } finally { if (dis != null) { try { dis.close(); } catch (IOException var12) { } } } } return lines; } private static void writeScriptFile(Vector lines, Vector patches, String restartCmd) { String scrFile = "updates.lst"; int count = patches.size(); for (int i = 0; i < count; i++) { String line = patches.elementAt(i); if (!hasString(lines, line)) { FileInputStream in = null; boolean needsPatch = false; try { in = new FileInputStream(line); byte[] bytes = new byte[4]; int bytesRead = in.read(bytes); assert bytesRead == bytes.length; needsPatch = bytes[0] == 37 && bytes[1] == 88 && bytes[2] == 68 && bytes[3] == 90; } catch (IOException var21) { } finally { if (in != null) { try { in.close(); } catch (IOException var19) { } } } if (needsPatch) { String tempName = line + "-xdelta"; new File(line).renameTo(new File(tempName)); lines.addElement("./bin/xdelta patch " + tempName + " bin/xup.template " + line); } lines.addElement(line); } } if (restartCmd != null) { lines.addElement(restartCmd); } IniFile.gamma().setIniString("RunUpgrade", ""); try { PrintStream ps = new PrintStream(new FileOutputStream(scrFile)); count = lines.size(); for (int ix = 0; ix < count; ix++) { ps.println(lines.elementAt(ix)); } ps.close(); IniFile.gamma().setIniString("RunUpgrade", "updates.lst"); } catch (IOException var20) { Console.println(Console.message("No-write-upgrade")); } } private static boolean loadPatchesAndUpdateScript(Vector patches, String restartCmd, Vector sizes, Vector names, String worldDir) { Vector alreadyListed = getLinesFromScriptFile(restartCmd); int i = patches.size(); while (--i >= 0) { String p = patches.elementAt(i); if (hasString(alreadyListed, p)) { patches.removeElementAt(i); sizes.removeElementAt(i); names.removeElementAt(i); } } Vector urls = new Vector(); Vector bytes = new Vector(); Vector condensedNames = new Vector(); int entrySize = 0; int totalSize = 0; boolean willNeedRegistry = false; for (int ix = 0; ix < sizes.size(); ix++) { String name = patches.elementAt(ix); String dnld = (uServer + name).replace('\\', '/'); urls.addElement(URL.make(dnld)); if (name.indexOf(45) < 0) { willNeedRegistry = true; } entrySize += sizes.elementAt(ix); if (names.elementAt(ix) != null) { totalSize += entrySize; bytes.addElement(new Integer(entrySize)); entrySize = 0; condensedNames.addElement(names.elementAt(ix)); } } assert entrySize == 0; if (totalSize == 0) { return true; } else { if (!Gamma.shaperEnabled()) { String prodName = worldDir != null ? "the " + worldDir + " world" : Std.getProductName(); Vector rjctdList = new UpgradeDialog(condensedNames, bytes, worldDir != null, prodName, "", false).rejectedList(); int ix = rjctdList.size(); while (--ix >= 0) { String s = rjctdList.elementAt(ix); int j = names.size(); while (--j >= 0) { String t = names.elementAt(j); if (t != null && s.equals(t)) { break; } } assert j >= 0; do { totalSize -= sizes.elementAt(j); patches.removeElementAt(j); urls.removeElementAt(j); sizes.removeElementAt(j); j--; } while (j >= 0 && names.elementAt(j) == null); } } if (totalSize == 0) { return false; } else { try { if (!new ProgressDialog(totalSize).loadFiles(patches, urls)) { return false; } } catch (IOException var19) { warnUser("Error creating upgrade script, upgrade failed"); System.out.println("error creating scriptfile " + var19); return false; } writeScriptFile(alreadyListed, patches, restartCmd); if (willNeedRegistry) { try { String intExt = isInternalVersion() ? "InternalGDK" : "3DCD"; RegKey root = RegKey.getRootKey(2); RegKey key = new RegKey(root, "SOFTWARE\\Worlds, Inc.\\" + intExt, 0); String here = URL.homeUnalias("x"); here = here.substring(0, here.length() - 2); key.setStringValue("InstallDir", here, false); key.close(); } catch (RegKeyNotFoundException var18) { } } return true; } } } private static boolean getUpdates(Vector patches, Vector sizes, Vector names, String wd) { String restartCmd = getRestartCmd(); if (restartCmd == null) { notifyUser(Console.message("Automatic-restart")); } synchronized (updateLoadSyncer) { if (!loadPatchesAndUpdateScript(patches, restartCmd, sizes, names, wd)) { return false; } } if (new NewVersionDialog().confirmRestart() && runUpdates("updates.lst")) { Main.end(); } return true; } private static native boolean CreateProcSpecial(String var0, String var1); private static boolean runUpdates(String upgradeScript) { IniFile.gamma().setIniString("RunUpgrade", ""); if (!CreateProcSpecial(".\\bin\\gdkup.exe", upgradeScript)) { System.out.println("error running .\\bin\\gdkup.exe"); return false; } else { return true; } } @Override public void run() { if (this.worldToUpdate != null) { this.asyncWorldCheck(this.worldToUpdate); } else { int gdkTo = 0; if (TESTAUTOUPGRADE != 0 || TESTWORLDAUTOUPGRADE != 0) { this._force = true; } if (timeToUpdate(this._force)) { notifyUser(Console.message("Checking-network")); Vector sizes = new Vector(); Vector names = new Vector(); Vector updateList = needUpdate(gdkTo, sizes, names); IniFile ini = new IniFile("InstalledWorlds"); for (int i = 0; i < maxInstalledWorlds(); i++) { String name = ini.getIniString("InstalledWorld" + i, "").trim(); if (name.length() > 0) { this.listWorldUpgrades(name, updateList, sizes, names); maxInstalledWorld(i); } } if (updateList.size() != 0 && getUpdates(updateList, sizes, names, null)) { notifyUser(Console.message("finished-checking")); } else { notifyUser(Console.message("no-updates")); } IniFile.gamma().setIniInt("LastUpgradeCheck", _today); } beenCalled = false; } } public static void loadWorld(String worldDir, boolean forceWorldLoad) { if (worldDir.equals("chaos")) { worldDir = "Chaos"; } NetUpdate nu = new NetUpdate(worldDir, forceWorldLoad); Thread t = new Thread(nu); t.setDaemon(true); t.start(); } public void asyncWorldCheck(String worldDir) { if (getCurrentVersionOfWorld(worldDir, -1) < 0) { Vector sizes = new Vector(); Vector updateList = new Vector(); Vector names = new Vector(); if (this.listWorldUpgrades(worldDir, updateList, sizes, names)) { if (updateList.size() != 0 && getUpdates(updateList, sizes, names, worldDir)) { notifyUser(worldDir + Console.message("download-finished")); } } else { notifyUser(worldDir + Console.message("custom-world")); } } } private static synchronized boolean busy() { if (beenCalled) { return true; } else { beenCalled = true; return false; } } public static boolean doUpdate(boolean force) { if (busy()) { if (force) { notifyUser(Console.message("Upgrade-progress")); } return false; } else { _today = (int)(new Date().getTime() / 86400000L); String upgradeScript = IniFile.gamma().getIniString("RunUpgrade", ""); if (!force && !upgradeScript.equals("")) { if (runUpdates(upgradeScript)) { return true; } beenCalled = false; } else { if (InternetConnectionDialog.choseSingleUserMode() && !force) { return false; } if (!force && IniFile.gamma().getIniInt("CheckUpgrades", 1) == 0) { notifyUser(Console.message("Check-for-up-opt")); beenCalled = false; } else { Thread t = new Thread(new NetUpdate(force)); t.setDaemon(true); t.start(); } } return false; } } }