diff --git a/app/src/main/java/io/xpipe/app/storage/DataStorage.java b/app/src/main/java/io/xpipe/app/storage/DataStorage.java index 81ff0f43a..8edfdb3d9 100644 --- a/app/src/main/java/io/xpipe/app/storage/DataStorage.java +++ b/app/src/main/java/io/xpipe/app/storage/DataStorage.java @@ -452,6 +452,10 @@ public abstract class DataStorage { } public Set> getDependencies(DataStoreEntry entry) { + return getDependencies(entry, new HashSet<>()); + } + + private Set> getDependencies(DataStoreEntry entry, Set> visited) { var l = new HashSet>(); var store = entry.getStore(); @@ -460,12 +464,17 @@ public abstract class DataStorage { } var deps = store.getDependencies(); + visited.add(entry.ref()); l.addAll(deps); for (DataStoreEntryRef dep : deps) { - if (!l.contains(dep)) { - l.addAll(getDependencies(dep.get())); + if (!visited.contains(dep)) { + visited.add(dep); + l.addAll(getDependencies(dep.get(), visited)); } } + + l.remove(entry.ref()); + return l; } diff --git a/app/src/main/java/io/xpipe/app/terminal/WindowsTerminalType.java b/app/src/main/java/io/xpipe/app/terminal/WindowsTerminalType.java index 30d79b0c5..3046925fe 100644 --- a/app/src/main/java/io/xpipe/app/terminal/WindowsTerminalType.java +++ b/app/src/main/java/io/xpipe/app/terminal/WindowsTerminalType.java @@ -49,6 +49,10 @@ public interface WindowsTerminalType extends ExternalTerminalType, TrackableTerm cmd.add("--pos").addQuoted(bounds.getX() + "," + (bounds.getY() + 20)); } + // Start from high window index to guarantee that xpipe uses its own window + cmd.addIf(configuration.isPreferTabs(), "-w", "100", "nt") + .addIf(!configuration.isPreferTabs(), "-w", "" + windowCounter.getAndIncrement()); + if (configuration.getColor() != null) { cmd.add("--tabColor").addQuoted(configuration.getColor().toHexString()); } diff --git a/dist/changelog/23.5.1.md b/dist/changelog/23.5.1.md new file mode 100644 index 000000000..4d800dfa7 --- /dev/null +++ b/dist/changelog/23.5.1.md @@ -0,0 +1 @@ +- Fix NullPointer introduced in v23.5 for some SSH connections diff --git a/dist/changelog/23.5.2.md b/dist/changelog/23.5.2.md new file mode 100644 index 000000000..e385e2857 --- /dev/null +++ b/dist/changelog/23.5.2.md @@ -0,0 +1 @@ +- Fix services with undefined type throwing errors about illegal URL formatting diff --git a/dist/changelog/23.5.md b/dist/changelog/23.5.md index 1c2d5fe46..5902df8d2 100644 --- a/dist/changelog/23.5.md +++ b/dist/changelog/23.5.md @@ -3,4 +3,5 @@ - Add ability to customize mount point for Hashicorp vault and OpenBao SSH secrets engine for certificate renewal - Add support for the new Windows Intelligent Terminal - Add delay to terminal pause prompt to prevent accidental triggers -- Attempt to fix KeePassXC concurrency issues +- Implement fix for KeePassXC concurrency issues +- Fix various issues and update docs for the /connection/add API endpoint diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java index f361e82f7..ed393ac8f 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStore.java @@ -48,18 +48,24 @@ public abstract class AbstractServiceStore @Override public void checkComplete() throws Throwable { + // We do not require the host to be complete + if (getHost() != null) { + Validators.isType(getHost(), HostAddressStore.class); + } Validators.nonNull(remotePort); Validators.nonNull(serviceProtocolType); if (getHost() == null) { Validators.nonNull(getAddress()); } - var addr = serviceProtocolType.formatAddress(getOpenTargetUrl()); - if (addr != null) { - try { - URI.create(addr); - } catch (IllegalArgumentException e) { - throw new ValidationException(e.getMessage()); + if (serviceProtocolType.hasScheme()) { + var addr = serviceProtocolType.formatAddress(getOpenTargetUrl()); + if (addr != null) { + try { + URI.create(addr); + } catch (IllegalArgumentException e) { + throw new ValidationException(e.getMessage()); + } } } } @@ -104,6 +110,10 @@ public abstract class AbstractServiceStore return false; } + if (!getHost().getStore().isComplete()) { + return false; + } + if (getHost().getStore() instanceof HostAddressGatewayStore g && !(getHost().getStore() instanceof NetworkTunnelStore)) { var gw = g.getTunnelGateway(); @@ -136,6 +146,10 @@ public abstract class AbstractServiceStore } if (getHost() != null) { + if (!getHost().getStore().isComplete()) { + return null; + } + if (!(getHost().getStore() instanceof NetworkTunnelStore) && getHost().getStore() instanceof HostAddressGatewayStore g) { if (g.getTunnelGateway() == null diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java index a5504400e..c5a8ff800 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/service/AbstractServiceStoreProvider.java @@ -39,6 +39,10 @@ public abstract class AbstractServiceStoreProvider implements SingletonSessionSt } if (abs.getHost() != null) { + if (!abs.getHost().getStore().isComplete()) { + return false; + } + if (abs.getHost().getStore() instanceof HostAddressGatewayStore a) { if (a.getTunnelGateway() != null && a.getTunnelGateway().getStore().requiresTunnel() diff --git a/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceProtocolType.java b/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceProtocolType.java index 4935f0ed4..e9f9e8d95 100644 --- a/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceProtocolType.java +++ b/ext/base/src/main/java/io/xpipe/ext/base/service/ServiceProtocolType.java @@ -21,6 +21,8 @@ import java.util.Locale; }) public interface ServiceProtocolType { + boolean hasScheme(); + String formatAddress(String base); void open(String url) throws Exception; @@ -33,6 +35,11 @@ public interface ServiceProtocolType { @Builder class Undefined implements ServiceProtocolType { + @Override + public boolean hasScheme() { + return false; + } + @Override public String formatAddress(String base) { return base; @@ -55,6 +62,11 @@ public interface ServiceProtocolType { String path; + @Override + public boolean hasScheme() { + return true; + } + @Override public String formatAddress(String base) { var url = "http://" + base; @@ -83,6 +95,11 @@ public interface ServiceProtocolType { String path; + @Override + public boolean hasScheme() { + return true; + } + @Override public String formatAddress(String base) { var url = "https://" + base; @@ -111,6 +128,11 @@ public interface ServiceProtocolType { String commandTemplate; + @Override + public boolean hasScheme() { + return false; + } + @Override public String formatAddress(String base) { return base; diff --git a/ext/system/src/main/java/io/xpipe/ext/system/podman/PodmanContainerStoreProvider.java b/ext/system/src/main/java/io/xpipe/ext/system/podman/PodmanContainerStoreProvider.java index 63dd13c34..a2ae6ce49 100644 --- a/ext/system/src/main/java/io/xpipe/ext/system/podman/PodmanContainerStoreProvider.java +++ b/ext/system/src/main/java/io/xpipe/ext/system/podman/PodmanContainerStoreProvider.java @@ -48,7 +48,7 @@ public class PodmanContainerStoreProvider implements ShellStoreProvider { @Override public DataStoreEntry getDisplayParent(DataStoreEntry store) { PodmanContainerStore s = store.getStore().asNeeded(); - return s.getCmd().get(); + return s.getCmd() != null ? s.getCmd().get() : null; } @Override