package NET.worlds.network; import NET.worlds.console.Console; import NET.worlds.console.Gamma; import NET.worlds.core.IniFile; import NET.worlds.scape.Restorer; import NET.worlds.scape.Saver; import NET.worlds.scape.SuperRoot; import java.io.File; import java.io.IOException; import java.io.Serializable; import java.net.MalformedURLException; import java.util.Hashtable; import java.util.StringTokenizer; public class URL implements Serializable { static final long serialVersionUID = 1L; private String _url; private static Hashtable psConversion = new Hashtable(); private static IniFile protocols = new IniFile("Protocol"); private static String currentDir = System.getProperty("user.dir").replace('\\', '/'); private static URL home; private static URL file; private static boolean useCachedFiles; private static URL avatar; static { assert currentDir.charAt(1) == ':' || currentDir.startsWith("//"); try { currentDir = validateFile(currentDir); } catch (MalformedURLException var2) { var2.printStackTrace(System.out); assert false; } if (!currentDir.endsWith("/")) { currentDir = currentDir + "/"; } home = make(Gamma.getHome()); file = make("file:"); psConversion.put("home", home); useCachedFiles = true; useCachedFiles = IniFile.gamma().getIniInt("useNetworkAvatars", 1) == 1; int override = IniFile.override().getIniInt("useNetworkAvatars", -1); if (override != -1) { useCachedFiles = override == 1; } String avatarDir = IniFile.gamma().getIniString("avatarDir", "avatar/"); if (!avatarDir.endsWith("/")) { avatarDir = avatarDir + "/"; } if (useCachedFiles) { setAvatarServer(NetUpdate.getUpgradeServerURL() + avatarDir); } else { setAvatarServer("home:avatars/"); } avatar = make("avatar:"); } public URL(SuperRoot reference, String urlstr) throws MalformedURLException { this(getBestContainer(reference), urlstr); } public URL(URL reference, String urlstr) throws MalformedURLException { if (isAbsolute(urlstr)) { this._url = normalize(urlstr); } else { this._url = "rel:" + reference.getAbsolute(urlstr); } } public URL(String urlstr) throws MalformedURLException { this(null, urlstr); } public static URL make(String s) { return make(getCurDir(), s); } public static URL make(URL url, String s) { try { return new URL(url, s); } catch (MalformedURLException var3) { var3.printStackTrace(System.out); throw new Error("Can't make URL"); } } private String getAbsolute(String urlstr) throws MalformedURLException { if (!isAbsolute(urlstr)) { urlstr = this._url.substring(0, this.getBaseIndex()) + urlstr; } if (urlstr.startsWith("rel:")) { urlstr = urlstr.substring(4); } return normalize(urlstr); } private int getBaseIndex() { int i = this.getPackageIndex(); if (this._url.endsWith(".class")) { int lastDot = this._url.lastIndexOf(46, this._url.length() - 7) + 1; if (lastDot > i) { i = lastDot; } } return i; } public String getAbsolute() { return this._url.startsWith("rel:") ? this._url.substring(4) : this._url; } @Override public String toString() { return this.getInternal(); } public String getInternal() { return this._url; } public String getBase() { return this._url.substring(this.getBaseIndex()); } public String getBaseWithoutExt() { int start = this.getBaseIndex(); int end = this._url.lastIndexOf(46); if (end < start) { end = this._url.length(); } return this._url.substring(start, end); } private static boolean isAbsolute(String urlstr) { return urlstr != null && (urlstr.indexOf(58) >= 0 || urlstr.replace('\\', '/').startsWith("//")); } private static int getRelpathIndex(String s) { int i = s.indexOf(58) + 1; if (s.regionMatches(i, "//", 0, 2)) { i = s.indexOf(47, i + 2) + 1; } else if (s.startsWith("file:") && s.regionMatches(i + 1, ":/", 0, 2)) { i += 3; } return i; } private static String normalize(String url) throws MalformedURLException { if (url == null) { throw new MalformedURLException("null URL string"); } else { url = url.replace('\\', '/').trim(); int pathi = url.indexOf(58) + 1; if (pathi == 1) { throw new MalformedURLException("Missing protocol specifier"); } else { boolean hasHost = url.regionMatches(pathi, "//", 0, 2); if (pathi <= 2) { if (pathi == 0 && !hasHost) { throw new MalformedURLException("Missing protocol specifier"); } url = "file:" + url; pathi = 5; } if (url.lastIndexOf(47, pathi - 1) >= 0) { throw new MalformedURLException("/ in protocol specifier of " + url); } else { url = url.substring(0, pathi).toLowerCase() + url.substring(pathi); if (hasHost) { pathi = url.indexOf(47, pathi + 2) + 1; if (pathi == 0) { url = url + '/'; pathi = url.length(); } } if (url.startsWith("rel:")) { url = normalize(url.substring(4)); return url.startsWith("rel:") ? url : "rel:" + url; } else { if (url.startsWith("file:")) { url = "file:" + validateFile(url.substring(5)); if (!hasHost) { assert url.indexOf(58, 5) == 6; assert url.charAt(7) == '/'; pathi += 3; } } else if (url.startsWith("http") && !hasHost) { throw new MalformedURLException("http must have //host/"); } return url.substring(0, pathi) + removeDots(url.substring(pathi)); } } } } } private static String validateFile(String p) throws MalformedURLException { if (p.startsWith("//")) { int slash = p.indexOf(47, 2); if (slash < 0) { p = p + "/"; } return p; } else { p = p.toLowerCase(); int colon = p.indexOf(58); if (colon != 1) { return p.indexOf(47) == 0 ? currentDir.substring(0, 2) + p : currentDir + p; } else if (p.indexOf(47) != 2) { throw new MalformedURLException("Slash must follow colon"); } else { char drive = Character.toLowerCase(p.charAt(0)); if (!Character.isLowerCase(drive)) { throw new MalformedURLException("Invalid drive letter"); } else { return drive + p.substring(1); } } } } public String getRelativeTo(URL reference) { if (reference != null && this._url.startsWith("rel:")) { String url = this.unalias(); String ref = reference.unalias(); int pathStart = ref.indexOf(58) + 1; boolean isLocal = pathStart == 2; if (!isLocal) { String hasHost = null; if (ref.regionMatches(pathStart, "//", 0, 2)) { hasHost = ref; } else if (url.regionMatches(pathStart, "//", 0, 2)) { hasHost = url; } if (hasHost != null) { pathStart = hasHost.indexOf(47, pathStart + 2) + 1; if (pathStart == 0) { return this._url; } } } if (!ref.regionMatches(isLocal, 0, url, 0, pathStart)) { return this._url; } else { int noncommonStart = pathStart; int len = Math.min(url.length(), ref.length()); for (int common = pathStart; common < len; common++) { char c = url.charAt(common); char d = ref.charAt(common); if (c != d && (!isLocal || Character.toLowerCase(c) != Character.toLowerCase(d))) { break; } if (c == '/') { noncommonStart = common + 1; } } url = url.substring(noncommonStart); int pos = noncommonStart; while ((pos = ref.indexOf(47, pos) + 1) != 0) { url = "../" + url; if (this._url.startsWith("rel:home:")) { return this._url; } } return url; } } else { return this._url; } } public String getRelativeTo(SuperRoot r) { return this.getRelativeTo(getBestContainer(r)); } public static URL getBestContainer(SuperRoot sr) { URL url = null; if (sr != null) { url = sr.getContainingSourceURL(); } return url == null ? getCurDir() : url; } public static String getRelativeTo(URL u, SuperRoot r) { return u == null ? null : u.getRelativeTo(r); } public static URL getHome() { return home; } public static String homeUnalias(String s) { return make("home:" + s).unalias(); } public static URL getContainingOrCurDir(SuperRoot t) { URL dir = t.getContainingSourceURL(); return dir == null ? getCurDir() : make(dir._url.substring(0, dir.getBaseIndex())); } private static void setAvatarServer(String url) { String avURL = protocols.getIniString("avatar", url); try { psConversion.put("avatar", new URL(new URL(avURL).unalias())); } catch (MalformedURLException var3) { System.out.println("Avatar protocol is invalid."); assert false; } } public static boolean usingCachedAvatars() { return useCachedFiles; } public static void setHttpServer(String url) { psConversion.put("worldshttp", make(url)); } public static URL getCurDir() { return file; } public static URL getAvatar() { return avatar; } private int getPackageIndex() { int i = this._url.lastIndexOf(47) + 1; if (i == 0) { i = this._url.indexOf(58) + 1; if (i == 4 && this._url.startsWith("rel:")) { i = this._url.indexOf(58, 4) + 1; } } return i; } public String unalias() { String url = this.getAbsolute(); if (url.endsWith(".class")) { int base = this.getPackageIndex(); int len = url.length(); url = url.substring(0, base) + url.substring(base, len - 6).replace('.', '/') + ".class"; } int protLen = url.indexOf(58); String prot = url.substring(0, protLen); Object alias = psConversion.get(prot); if (alias == null) { psConversion.put(prot, psConversion); String s = protocols.getIniString(prot, ""); if (s != null && !s.equals("")) { try { alias = new URL(new URL(s).unalias()); psConversion.put(prot, alias); } catch (MalformedURLException var8) { System.out.println("Invalid inifile entry for " + prot); } } } else if (prot.equals("avatar") && url.endsWith(".rwg")) { alias = null; } if (alias instanceof URL) { URL u = (URL)alias; assert !u._url.startsWith("rel:"); if (u._url.startsWith("file:") && url.length() > protLen + 1 && url.charAt(protLen + 1) == '/') { protLen++; } url = u._url.substring(0, u.getBaseIndex()) + url.substring(protLen + 1); } if (!url.startsWith("file:")) { return url; } else { url = url.substring(5); try { url = normalize(validateFile(url)); } catch (MalformedURLException var7) { return url; } assert url.startsWith("file:"); return url.substring(5); } } public static String searchPath(String name, String path) { StringTokenizer e = new StringTokenizer(path, File.pathSeparator); while (e.hasMoreTokens()) { String dir = e.nextToken(); String expandedName = name; if (!dir.equals(".")) { expandedName = dir + File.separator + name; } File f = new File(expandedName); if (f.exists()) { return expandedName; } } return null; } public String getClassName() { if (!this._url.endsWith(".class")) { return null; } else { int base = this.getPackageIndex(); int len = this._url.length(); return this._url.substring(base, len - 6); } } public URL getClassDir() { return !this._url.endsWith(".class") ? null : make(this._url.substring(0, this.getPackageIndex())); } public boolean endsWith(String ext) { return this._url.endsWith(ext); } public String getExt() { int i = this._url.lastIndexOf(46); return i != -1 && this._url.indexOf(47, i) < 0 && this._url.indexOf(58, i) < 0 ? this._url.substring(i) : ""; } public static String maybeAddExt(String url, String ext) { int dot = url.lastIndexOf(46); return dot >= 0 && url.indexOf(47, dot) < 0 && url.indexOf(92, dot) < 0 ? url : url + ext; } public static URL restore(Restorer r, String defaultExt) throws IOException { return restore(r, r.restoreString(), defaultExt); } public static URL restore(Restorer r, String url, String defaultExt) throws IOException { if (url == null) { return null; } else { if (defaultExt != null) { url = maybeAddExt(url, defaultExt); } if (isAbsolute(url)) { return new URL(url); } else { URL ref = r.getReferenceURL(); if (r.version() >= 6) { if (ref == null) { throw new IOException("No absolute base for relative URL " + url); } else { return new URL(ref, url); } } else if (url.endsWith(".class")) { return make((url.indexOf(47) < 0 ? "system:" : "file:") + url); } else { String s = searchPath(url, ".;.."); if (s != null) { if (ref == null) { return new URL("file:" + s); } else { URL unaliasedRef = make(ref.unalias()); String rel = new URL("rel:file:" + s).getRelativeTo(unaliasedRef); return new URL(ref, rel); } } else { System.out.println(url + " doesn't exist in RWSHAPEPATH"); return make(ref, url); } } } } } public static URL restore(Restorer r) throws IOException { return restore(r, null); } public void save(Saver s) throws IOException { String r = this.getRelativeTo(s.getReferenceURL()); if (r.startsWith("../") || r.startsWith("rel:file:") || r.startsWith("file:")) { Console.println(Console.message("path-to-outside") + r); } s.saveString(r); } public static void save(Saver s, URL url) throws IOException { if (url == null) { s.saveString(null); } else { url.save(s); } } @Override public boolean equals(Object o) { if (o instanceof URL) { URL other = (URL)o; return this._url.equals(other.getInternal()) ? true : this.unalias().equals(other.unalias()); } else { return false; } } @Override public int hashCode() { return this.unalias().hashCode(); } public boolean isRemote() { String s = this.unalias(); return s.startsWith("//") || s.indexOf(58) < 2 ? false : !s.startsWith("system:") && !s.startsWith("session:"); } public static String removeDots(String url) { url = "/" + url; int firstSubdir = 1; int nextSearch = firstSubdir - 1; int firstDot; while ((firstDot = url.indexOf("/.", nextSearch) + 1) > 0) { int endSlash = url.indexOf(47, firstDot); if (endSlash < 0) { break; } int numDots = endSlash - firstDot; int i = firstDot; while (i < endSlash && url.charAt(i) == '.') { i++; } if (i != endSlash) { nextSearch = endSlash; } else { while (true) { if (numDots == 1) { endSlash++; } else { if (firstDot != firstSubdir) { firstDot = url.lastIndexOf(47, firstDot - 2) + 1; if (firstDot <= firstSubdir) { firstDot = firstSubdir; } numDots--; continue; } endSlash -= numDots; firstSubdir += numDots + 1; } url = url.substring(0, firstDot) + url.substring(endSlash); nextSearch = firstSubdir - 1; break; } } } return url.substring(1); } }