diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7..35eb1dd 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/pom.xml b/pom.xml index dad740a..1f2d335 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.openautonomousconnection WebClient - 1.0-BETA.1.0 + 1.0.0-BETA.1.1 Open Autonomous Connection https://open-autonomous-connection.org/ @@ -45,48 +45,14 @@ Issue Tracker - https://repo.open-autonomous-connection.org/open-autonomous-connection/WebClient/issues + https://repo.open-autonomous-connection.org/open-autonomous-connection/DNSServer/issues - Open Autonomous Public License (OAPL) - https://open-autonomous-connection.org/license.html - - - GNU General Public License v3.0 - https://www.gnu.org/licenses/gpl-3.0.html - - Default license: Applies to all users and projects unless an explicit alternative license has been granted. - - - - LPGL 3 - https://www.gnu.org/licenses/lgpl-3.0.html#license-text - - - LPGL 2.1 - https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.en#SEC1 - - - WTPL License - https://github.com/ronmamo/reflections/tree/master?tab=WTFPL-1-ov-file - - - Apache License 2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt - - - MIT License - https://opensource.org/license/mit - - - javassist - https://github.com/jboss-javassist/javassist/blob/master/License.html - - - projectlombok - https://github.com/projectlombok/lombok?tab=License-1-ov-file + Open Autonomous Public License + https://repo.open-autonomous-connection.org/Open-Autonomous-Connection/OAPL/ + repo @@ -104,7 +70,7 @@ org.openautonomousconnection protocol - 1.0.0-BETA.5 + 1.0.0-BETA.5.2 org.projectlombok @@ -112,30 +78,21 @@ 1.18.38 provided + + org.jsoup + jsoup + 1.22.1 + compile + + + org.openautonomousconnection + luascript + 1.0-BETA.1.0 + + + org.openautonomousconnection.infonamelib + InfoNameLib + 1.0.0-BETA.1.0 + - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.0 - - - package - - shade - - - - - org.openautonomousconnection.webclient.Main - - - - - - - - \ No newline at end of file diff --git a/src/main/java/org/openautonomousconnection/webclient/Main.java b/src/main/java/org/openautonomousconnection/webclient/Main.java new file mode 100644 index 0000000..8a3f94f --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/Main.java @@ -0,0 +1,80 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient; + +import dev.unlegitdqrk.unlegitlibrary.event.EventManager; +import dev.unlegitdqrk.unlegitlibrary.network.system.packets.PacketHandler; +import org.openautonomousconnection.protocol.ProtocolBridge; +import org.openautonomousconnection.protocol.ProtocolSettings; +import org.openautonomousconnection.protocol.versions.ProtocolVersion; +import org.openautonomousconnection.webclient.network.WebClient; +import org.openautonomousconnection.webclient.network.handlers.ServerPacketHandler; +import org.openautonomousconnection.webclient.packetlistener.listeners.WebPacketListener; +import org.openautonomousconnection.webclient.ui.MainFrame; + +import java.beans.EventHandler; +import java.io.File; + +public class Main { + public static MainFrame mainFrame; + + public static final String DEFAULT_HOST = "ins.open-autonomous-connection.org"; + + public static final int DEFAULT_PORT = 1023; + + private static final ProtocolVersion PROTOCOL_VERSION = ProtocolVersion.PV_1_0_0_BETA; + + public static WebClient client; + + public static ProtocolBridge bridge; + + public static void main(String[] args) { + initProtocol(); + + try { + registerEventHandlers(); + } catch (Exception e) { + throw new RuntimeException(e); + } + registerPacketListeners(); + + mainFrame = new MainFrame(); + + mainFrame.setVisible(true); + } + + private static void initProtocol() { + client = new WebClient(); + + ProtocolSettings settings = new ProtocolSettings(); + + settings.packetHandler = new PacketHandler(); + settings.eventManager = new EventManager(); + + settings.host = DEFAULT_HOST; + settings.port = DEFAULT_PORT; + + try { + bridge = new ProtocolBridge( + client, + settings, + PROTOCOL_VERSION, + new File("logs") + ); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void registerEventHandlers() throws Exception { + EventManager eventManager = bridge.getProtocolSettings().eventManager; + + eventManager.registerListener(ServerPacketHandler.class); + } + + private static void registerPacketListeners() { + ServerPacketHandler.registerPacketListener(new WebPacketListener()); + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/Promise.java b/src/main/java/org/openautonomousconnection/webclient/network/Promise.java new file mode 100644 index 0000000..c09b387 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/Promise.java @@ -0,0 +1,59 @@ +package org.openautonomousconnection.webclient.network; + +import lombok.Getter; +import lombok.Setter; + +import java.util.concurrent.*; + +/** + * An object that is still waited for to be delivered by the server + * + * @param type of promised object + */ +public class Promise { + @Getter @Setter + private T object; + + public Promise() { + } + + public Promise(T object) { + this.object = object; + } + + public static Promise yieldPromise(int timeout, T reference) { + try (ExecutorService executorService = Executors.newSingleThreadExecutor()) { + Callable task = () -> { + for(int i = 0; i < timeout; i++) { + if(reference == null) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + if(reference == null) + throw new TimeoutException(); + + return reference; + }; + + Future future = executorService.submit(task); + + executorService.shutdown(); + + try { + return new Promise<>(future.get()); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + } + + private Class getType() { + return this.object.getClass(); + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/WebClient.java b/src/main/java/org/openautonomousconnection/webclient/network/WebClient.java new file mode 100644 index 0000000..4ad230c --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/WebClient.java @@ -0,0 +1,107 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.network; + +import lombok.Getter; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket; +import org.openautonomousconnection.protocol.side.client.ProtocolClient; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSRecord; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.WebRequestMethod; +import org.openautonomousconnection.webclient.network.type.NTFType; +import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; + +import javax.swing.text.Document; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Uses the OAC-Protocol networking client + * Suppressing "unchecked" warnings because of generic casts + */ +@SuppressWarnings("unchecked") +public class WebClient extends ProtocolClient { + /** + * Global protocol timeout = 30 seconds + */ + public static final int TIMEOUT = 30; + + public void fulfillPromise(NTFType type, T object) { + if(!this.outstandingPromises.containsKey(type)) + return; + + Object promisedValue = this.outstandingPromises.get(type); + + if(promisedValue != null) + return; + + this.outstandingPromises.replace(type, object); + } + + @Getter + private final Map outstandingPromises = new HashMap<>(); + + private Promise> promise(NTFType type) { + NetTransmitFile ntf = NetTransmitFile.of(type, null); + + this.outstandingPromises.put(type, ntf); + + return Promise.yieldPromise(TIMEOUT, ntf); + } + + @Override + public void onResponse(INSResponseStatus insResponseStatus, List list) { + } + + public Promise> get(NTFType type, String path, T test) { + try { + this.getClientWebConnection().sendPacket(new WebRequestPacket( + path, + WebRequestMethod.GET, + Map.of(), + null + )); + + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + + return this.promise(type); + } + + public void post(String path) { + try { + this.getClientWebConnection().sendPacket(new WebRequestPacket( + path, + WebRequestMethod.POST, + Map.of(), + null + )); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + public Promise> getIndex() { + try { + this.getClientWebConnection().sendPacket(new WebRequestPacket( + "index.html", + WebRequestMethod.GET, + Map.of(), + null + )); + } catch (IOException | ClassNotFoundException e) { + throw new RuntimeException(e); + } + + System.out.println(promise(NTFType.DOCUMENT).getClass().getSimpleName()); + + return null;//(Promise>) promise(NTFType.DOCUMENT); + } + +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/handlers/ClassicHandler.java b/src/main/java/org/openautonomousconnection/webclient/network/handlers/ClassicHandler.java new file mode 100644 index 0000000..c5e0796 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/handlers/ClassicHandler.java @@ -0,0 +1,43 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.network.handlers; + +import org.openautonomousconnection.protocol.side.client.ProtocolClient; +import org.openautonomousconnection.protocol.versions.v1_0_0.beta.INSResponseStatus; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.handlers.ClassicHandlerClient; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.objects.Classic_Domain; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.site.Classic_SiteType; +import org.openautonomousconnection.protocol.versions.v1_0_0.classic.utils.Classic_ProtocolVersion; + +/** + * Handle deprecated (classic) versions + */ + +@SuppressWarnings("deprecated") +public class ClassicHandler extends ClassicHandlerClient { + public ClassicHandler(ProtocolClient client) { + super(client); + } + + @Override + public void unsupportedClassicPacket(String className, Object[] objects) { + + } + + @Override + public void handleHTMLContent(Classic_SiteType classicSiteType, Classic_Domain classicDomain, String s) { + + } + + @Override + public void handleMessage(String message, Classic_ProtocolVersion classicProtocolVersion) { + + } + + @Override + public void validationCompleted(Classic_Domain classicDomain, INSResponseStatus insResponseStatus) { + + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/handlers/ServerPacketHandler.java b/src/main/java/org/openautonomousconnection/webclient/network/handlers/ServerPacketHandler.java new file mode 100644 index 0000000..6c38526 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/handlers/ServerPacketHandler.java @@ -0,0 +1,35 @@ +/* Author: Maple + * Jan. 16 2026 + * */ + +package org.openautonomousconnection.webclient.network.handlers; + +import dev.unlegitdqrk.unlegitlibrary.event.EventListener; +import dev.unlegitdqrk.unlegitlibrary.network.system.client.events.C_PacketReceivedEvent; +import dev.unlegitdqrk.unlegitlibrary.network.system.packets.Packet; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket; +import org.openautonomousconnection.webclient.packetlistener.PacketListener; + +import java.util.ArrayList; +import java.util.List; + +public class ServerPacketHandler extends EventListener { + + private static final List listeners = new ArrayList<>(); + + public static void registerPacketListener(PacketListener packetListener) { + listeners.add(packetListener); + } + + public void onPacketReceived(C_PacketReceivedEvent packetReceivedEvent) { + + Packet packet = packetReceivedEvent.getPacket(); + + switch (packet.getPacketID()) { + case 4 -> listeners + .forEach(l -> l.onAuthPacketReceived((AuthPacket) packet)); + case 9 -> listeners + .forEach(l -> l.onWebResponsePacketReceived((WebResponsePacket) packet));} + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/NTFType.java b/src/main/java/org/openautonomousconnection/webclient/network/type/NTFType.java new file mode 100644 index 0000000..78e0555 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/NTFType.java @@ -0,0 +1,13 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type; + +public enum NTFType { + UNKNOWN, + STYLESHEET, + DOCUMENT, + ICON, + FILE +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/NetTransmitFile.java b/src/main/java/org/openautonomousconnection/webclient/network/type/NetTransmitFile.java new file mode 100644 index 0000000..28c55da --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/NetTransmitFile.java @@ -0,0 +1,34 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type; + +import org.jsoup.nodes.Document; +import org.openautonomousconnection.webclient.network.type.application.NetAppstreamFile; +import org.openautonomousconnection.webclient.network.type.image.NetTransmitIcon; +import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument; +import org.openautonomousconnection.webclient.network.type.text.NetTransmitStylesheet; +import org.w3c.dom.css.CSSStyleSheet; + +import javax.swing.*; +import java.io.File; + +public interface NetTransmitFile { + T getNtf(); + void setNtf(T ntf); + + @SuppressWarnings("unchecked") + static NetTransmitFile of(NTFType type, T ntf) { + return (NetTransmitFile) switch (type) { + case FILE -> new NetAppstreamFile((File) ntf); + + case ICON -> new NetTransmitIcon((ImageIcon) ntf); + + case DOCUMENT -> new NetTransmitDocument((Document) ntf); + case STYLESHEET -> new NetTransmitStylesheet((CSSStyleSheet) ntf); + + case null, default -> new NetTransmitUnknown(ntf); + }; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/NetTransmitUnknown.java b/src/main/java/org/openautonomousconnection/webclient/network/type/NetTransmitUnknown.java new file mode 100644 index 0000000..e4f269a --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/NetTransmitUnknown.java @@ -0,0 +1,20 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type; + +import lombok.Getter; +import lombok.Setter; + +public class NetTransmitUnknown implements NetTransmitFile { + @Getter @Setter + private Object ntf; + + public NetTransmitUnknown() { + } + + public NetTransmitUnknown(Object ntf) { + this.ntf = ntf; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/application/NetAppstreamFile.java b/src/main/java/org/openautonomousconnection/webclient/network/type/application/NetAppstreamFile.java new file mode 100644 index 0000000..bca6d00 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/application/NetAppstreamFile.java @@ -0,0 +1,25 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type.application; + +import lombok.Getter; +import lombok.Setter; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; + +import java.io.File; + +public class NetAppstreamFile implements NetTransmitFile { + @Getter + @Setter + private File ntf; + + public NetAppstreamFile() { + + } + + public NetAppstreamFile(File ntf) { + this.ntf = ntf; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/image/NetTransmitIcon.java b/src/main/java/org/openautonomousconnection/webclient/network/type/image/NetTransmitIcon.java new file mode 100644 index 0000000..740d77d --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/image/NetTransmitIcon.java @@ -0,0 +1,25 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type.image; + +import lombok.Getter; +import lombok.Setter; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; + +import javax.swing.*; + +public class NetTransmitIcon implements NetTransmitFile { + @Getter + @Setter + private ImageIcon ntf; + + public NetTransmitIcon() { + + } + + public NetTransmitIcon(ImageIcon ntf) { + this.ntf = ntf; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/text/NetTransmitDocument.java b/src/main/java/org/openautonomousconnection/webclient/network/type/text/NetTransmitDocument.java new file mode 100644 index 0000000..8f55472 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/text/NetTransmitDocument.java @@ -0,0 +1,23 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type.text; + +import lombok.Getter; +import lombok.Setter; +import org.jsoup.nodes.Document; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; + +public class NetTransmitDocument implements NetTransmitFile { + @Getter @Setter + private Document ntf; + + public NetTransmitDocument() { + + } + + public NetTransmitDocument(Document ntf) { + this.ntf = ntf; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/type/text/NetTransmitStylesheet.java b/src/main/java/org/openautonomousconnection/webclient/network/type/text/NetTransmitStylesheet.java new file mode 100644 index 0000000..92fbfb7 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/type/text/NetTransmitStylesheet.java @@ -0,0 +1,25 @@ +/* Author: Maple + * Jan. 17 2026 + * */ + +package org.openautonomousconnection.webclient.network.type.text; + +import lombok.Getter; +import lombok.Setter; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; +import org.w3c.dom.css.CSSStyleSheet; + +public class NetTransmitStylesheet implements NetTransmitFile { + @Getter + @Setter + private CSSStyleSheet ntf; + + public NetTransmitStylesheet() { + + } + + public NetTransmitStylesheet(CSSStyleSheet ntf) { + this.ntf = ntf; + } + +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/website/WebSite.java b/src/main/java/org/openautonomousconnection/webclient/network/website/WebSite.java new file mode 100644 index 0000000..32cfc26 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/website/WebSite.java @@ -0,0 +1,104 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.network.website; + +import lombok.Getter; +import lombok.Setter; +import org.jsoup.nodes.Document; +import org.openautonomousconnection.webclient.Main; +import org.openautonomousconnection.webclient.network.Promise; +import org.openautonomousconnection.webclient.network.type.NTFType; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; + +import javax.annotation.Nullable; +import javax.swing.*; +import java.net.URL; +import java.util.Objects; + +/** + * Contains data about a site + * Suppressing "unchecked" warnings because of generic casts + */ +@SuppressWarnings("unchecked") +public final class WebSite { + @Getter + private final URL infoName; + + @Getter @Setter + private Document dom; + + /** + * + */ + public WebSite(URL infoName) { + this.infoName = infoName; + } + + /** + * Send new get request + */ + public Document requestNewDom() { + Document test = null; + + Promise> promise = (Promise>) + Main.client.get(NTFType.DOCUMENT, this.infoName.getPath().toString(), test); + return promise.getObject().getNtf(); + } + + /** + * Get favicon of site by attempting to retrieve the favicon.ico + * + * @return retrieved icon or null + */ + public Icon getFavIcon() { + return getFavIcon(this.infoName); + } + + /** + * Get favicon of site by attempting to retrieve the favicon.ico + * + * @param infoName info name that leads to the site with the favicon + * @return retrieved icon or null + */ + public static @Nullable Icon getFavIcon(URL infoName) { + ImageIcon test = null; + + Promise> promise = (Promise>) + Main.client.get(NTFType.ICON, infoName.getPath().toString(), test); + + return promise.getObject().getNtf(); + } + +// /** +// * Get HTML text (dom) of site +// * +// * @param infoName that leads to the target OAC page +// * @return html document +// */ +// public static Document getDom(InfoName infoName) { +// Main.client.getDocument(); +// } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (WebSite) obj; + return Objects.equals(this.infoName, that.infoName); + } + + @Override + public int hashCode() { + return Objects.hash(infoName); + } + + @Override + public String toString() { + return "WebSite{" + + "infoName=" + this.infoName + + ", dom=" + this.dom + + '}'; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/network/website/tab/Tab.java b/src/main/java/org/openautonomousconnection/webclient/network/website/tab/Tab.java new file mode 100644 index 0000000..28a75d1 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/network/website/tab/Tab.java @@ -0,0 +1,68 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.network.website.tab; + +import lombok.Getter; +import lombok.Setter; +import org.openautonomousconnection.webclient.network.website.WebSite; + +import javax.swing.*; +import java.net.URL; +import java.util.Objects; + +@Getter @Setter +public final class Tab { + private URL infoName; + private Icon favicon; + private WebSite webSite; + + public Tab(URL infoName, Icon favicon) { + this.infoName = infoName; + this.favicon = favicon; + this.webSite = new WebSite(infoName); + } + + public Tab(URL infoName) { + this.infoName = infoName; + this.favicon = WebSite.getFavIcon(infoName); + this.webSite = new WebSite(infoName); + } + + public Tab(WebSite webSite) { + this.infoName = webSite.getInfoName(); + this.favicon = webSite.getFavIcon(); + this.webSite = webSite; + } + + public void refresh() { + this.webSite.requestNewDom(); + this.favicon = this.webSite.getFavIcon(); + } + + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (obj == null || obj.getClass() != this.getClass()) return false; + var that = (Tab) obj; + return Objects.equals(this.infoName, that.infoName) && + Objects.equals(this.favicon, that.favicon) && + Objects.equals(this.webSite, that.webSite); + } + + @Override + public int hashCode() { + return Objects.hash(this.infoName, this.favicon, this.webSite); + } + + @Override + public String toString() { + return "Tab{" + + "infoName=" + this.infoName + + ", favicon=" + this.favicon + + ", webSite=" + this.webSite + + '}'; + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/packetlistener/PacketListener.java b/src/main/java/org/openautonomousconnection/webclient/packetlistener/PacketListener.java new file mode 100644 index 0000000..e799e04 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/packetlistener/PacketListener.java @@ -0,0 +1,24 @@ +/* Author: Maple + * Jan. 16 2026 + * */ + +package org.openautonomousconnection.webclient.packetlistener; + +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.AuthPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebRequestPacket; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket; + +public abstract class PacketListener { + + public void onAuthPacketReceived(AuthPacket authPacket) { + } + + public void onAuthPacketSent(AuthPacket authPacket) { + } + + public void onWebResponsePacketReceived(WebResponsePacket webResponsePacket) { + } + + public void onWebRequestPacketSent(WebRequestPacket webRequestPacket) { + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/packetlistener/listeners/WebPacketListener.java b/src/main/java/org/openautonomousconnection/webclient/packetlistener/listeners/WebPacketListener.java new file mode 100644 index 0000000..3255ca7 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/packetlistener/listeners/WebPacketListener.java @@ -0,0 +1,62 @@ +/* Author: Maple + * Jan. 16 2026 + * */ + +package org.openautonomousconnection.webclient.packetlistener.listeners; + +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.openautonomousconnection.protocol.packets.v1_0_0.beta.WebResponsePacket; +import org.openautonomousconnection.webclient.Main; +import org.openautonomousconnection.webclient.network.type.NTFType; +import org.openautonomousconnection.webclient.network.type.NetTransmitFile; +import org.openautonomousconnection.webclient.network.type.image.NetTransmitIcon; +import org.openautonomousconnection.webclient.network.type.text.NetTransmitDocument; +import org.openautonomousconnection.webclient.network.website.tab.Tab; +import org.openautonomousconnection.webclient.packetlistener.PacketListener; + +import javax.swing.*; + +public class WebPacketListener extends PacketListener { + @Override + public void onWebResponsePacketReceived(WebResponsePacket packet) { + NTFType type = NTFType.UNKNOWN; + + NetTransmitFile file = null; + + /* + full list of content types at https://repo.open-autonomous-connection.org/open-autonomous-connection/WebServer/src/branch/master/src/main/java/org/openautonomousconnection/webserver/ContentTypeResolver.java + */ + switch (packet.getContentType()) { + case "text/html": + type = NTFType.DOCUMENT; + + // body is sent as byte array (string) + + String htmlText = new String(packet.getBody()); + + Document dom = Jsoup.parse(htmlText); + + file = new NetTransmitDocument(); + break; + + case "image/png": // TODO: Implement + break; + + case "image/ico": // the server doesn't implement this yet, so favicons won't work at this moment + type = NTFType.ICON; + + ImageIcon icon = new ImageIcon(packet.getBody()); + + file = new NetTransmitIcon(icon); + break; + + // the same as application/octet-stream + default: + break; //TODO: stream files + + } + + Main.client.fulfillPromise(type, file); + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/ui/BrowserFrame.java b/src/main/java/org/openautonomousconnection/webclient/ui/BrowserFrame.java new file mode 100644 index 0000000..3a51994 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/ui/BrowserFrame.java @@ -0,0 +1,13 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.ui; + +import javax.swing.*; + +public abstract class BrowserFrame extends JFrame { + public BrowserFrame() { + this.setDefaultCloseOperation(EXIT_ON_CLOSE); + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/ui/DOMPanel.java b/src/main/java/org/openautonomousconnection/webclient/ui/DOMPanel.java new file mode 100644 index 0000000..9d93ca0 --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/ui/DOMPanel.java @@ -0,0 +1,10 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.ui; + +import javax.swing.*; + +public class DOMPanel extends JPanel { +} diff --git a/src/main/java/org/openautonomousconnection/webclient/ui/MainFrame.java b/src/main/java/org/openautonomousconnection/webclient/ui/MainFrame.java new file mode 100644 index 0000000..fb8b23d --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/ui/MainFrame.java @@ -0,0 +1,28 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.ui; + +import lombok.Getter; +import org.openautonomousconnection.webclient.network.website.tab.Tab; + +import java.net.MalformedURLException; +import java.net.URI; + +public final class MainFrame extends BrowserFrame{ + @Getter + private Tab openTab; + + public MainFrame() { + this.setSize(800, 600); + + try { + this.openTab = new Tab( + URI.create("web://open-autonomous-connection.org").toURL() + ); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/ui/tab/TabButton.java b/src/main/java/org/openautonomousconnection/webclient/ui/tab/TabButton.java new file mode 100644 index 0000000..d1fc5db --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/ui/tab/TabButton.java @@ -0,0 +1,31 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.ui.tab; + +import lombok.Getter; +import lombok.NonNull; +import lombok.Setter; +import org.openautonomousconnection.webclient.network.website.tab.Tab; + +import javax.swing.*; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; + +/** + * Button that contains Tab data + */ +@Getter @Setter +public class TabButton extends JButton { + private Tab tab; + + public TabButton(@NonNull String infoName) throws MalformedURLException { + this(URI.create(infoName).toURL()); + } + + public TabButton(@NonNull URL infoName) { + this.tab = new Tab(infoName); + } +} diff --git a/src/main/java/org/openautonomousconnection/webclient/ui/tab/TabButtonView.java b/src/main/java/org/openautonomousconnection/webclient/ui/tab/TabButtonView.java new file mode 100644 index 0000000..5ba930f --- /dev/null +++ b/src/main/java/org/openautonomousconnection/webclient/ui/tab/TabButtonView.java @@ -0,0 +1,49 @@ +/* Author: Maple + * Dec. 12 2025 + * */ + +package org.openautonomousconnection.webclient.ui.tab; + +import lombok.Getter; + +import javax.swing.*; +import java.awt.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * View at the top of the screen that contains the tabs + */ +public class TabButtonView extends JPanel { + @Getter + private final List tabButtons; + + public TabButtonView() { + this(Collections.emptyList()); + } + + /** + * Constructor with preset buttons + * @param tabButtons already created buttons + */ + public TabButtonView(Collection tabButtons) { + this.tabButtons = (List) tabButtons; + + FlowLayout layoutStyle = new FlowLayout(FlowLayout.LEFT, 0, 0); + + this.setLayout(layoutStyle); + + } + + public void addButton(TabButton tabButton) { + this.tabButtons.add(tabButton); + } + + public TabButton getButton(int index) { + return this.tabButtons.get(index); + } + + + +}