summaryrefslogtreecommitdiff
path: root/NET/worlds/network/URL.java
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-02-12 22:33:32 -0800
committerFuwn <[email protected]>2026-02-12 22:33:32 -0800
commitc7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9 (patch)
treedf9f48bf128a6c0186a8e91857d6ff30fe0e9f18 /NET/worlds/network/URL.java
downloadworldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.tar.xz
worldsplayer-c7a9d4a6bd53ed7d61731770f2f10e8b9fd435f9.zip
Initial commit
Diffstat (limited to 'NET/worlds/network/URL.java')
-rw-r--r--NET/worlds/network/URL.java604
1 files changed, 604 insertions, 0 deletions
diff --git a/NET/worlds/network/URL.java b/NET/worlds/network/URL.java
new file mode 100644
index 0000000..eb45616
--- /dev/null
+++ b/NET/worlds/network/URL.java
@@ -0,0 +1,604 @@
+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<String, Object> psConversion = new Hashtable<String, Object>();
+ 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);
+ }
+}