Merge branch 'vpn' into 23-release

This commit is contained in:
crschnick
2026-04-21 19:51:11 +00:00
parent 533236cb86
commit f87bfddb0a
26 changed files with 443 additions and 40 deletions

View File

@@ -10,6 +10,7 @@ import io.xpipe.app.platform.PlatformThread;
import io.xpipe.app.util.BooleanScope;
import io.xpipe.core.OsType;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.beans.property.Property;
@@ -70,6 +71,11 @@ public class ModalOverlayComp extends RegionBuilder<Region> {
}
});
}
@Override
protected Timeline createCloseBlockedAnimation() {
return new Timeline();
}
});
modal.setInTransitionFactory(
OsType.ofLocal() == OsType.LINUX ? null : node -> Animations.fadeIn(node, Duration.millis(150)));

View File

@@ -104,8 +104,7 @@ public class InPlaceKeyStrategy implements SshIdentityStrategy {
}),
key)
.nonNull()
.name("keyPassword")
.description("sshConfigHost.identityPassphraseDescription")
.nameAndDescription("keyPassphrase")
.sub(passwordChoice, keyPasswordProperty)
.nonNull()
.nameAndDescription("inPlacePublicKey")

View File

@@ -167,8 +167,7 @@ public class KeyFileStrategy implements SshIdentityStrategy {
false),
keyPath)
.nonNull()
.name("keyPassword")
.description("sshConfigHost.identityPassphraseDescription")
.nameAndDescription("keyPassphrase")
.sub(passwordChoice, keyPasswordProperty)
.nonNull()
.nameAndDescription("inPlacePublicKey")

View File

@@ -21,7 +21,8 @@ public enum DataStoreCreationCategory {
SERIAL(DataStorage.ALL_CONNECTIONS_CATEGORY_UUID),
MACRO(DataStorage.ALL_MACROS_CATEGORY_UUID),
FILE_SYSTEM(DataStorage.ALL_CONNECTIONS_CATEGORY_UUID),
IDENTITY(DataStorage.ALL_IDENTITIES_CATEGORY_UUID);
IDENTITY(DataStorage.ALL_IDENTITIES_CATEGORY_UUID),
NETWORK(DataStorage.ALL_CONNECTIONS_CATEGORY_UUID);
private final UUID category;
}

View File

@@ -9,8 +9,10 @@ import io.xpipe.app.process.CommandControl;
import io.xpipe.app.process.ShellControl;
import io.xpipe.app.process.ShellDialect;
import io.xpipe.app.secret.SecretRetrievalStrategy;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.RemoteDesktopDockContentEntry;
import io.xpipe.app.util.HttpProxy;
import io.xpipe.app.vnc.VncBaseStore;
import io.xpipe.core.SecretValue;
@@ -19,6 +21,7 @@ import javafx.beans.property.Property;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.ServiceLoader;
public abstract class ProcessControlProvider {
@@ -82,4 +85,6 @@ public abstract class ProcessControlProvider {
public abstract void cloneRepository(String url, Path target) throws Exception;
public abstract void pullRepository(Path target) throws Exception;
public abstract Optional<HttpProxy> getHttpProxy(DataStoreEntryRef<?> store) throws Exception;
}

View File

@@ -101,7 +101,7 @@ public class StoreCreationMenu {
menu.getItems()
.add(categoryMenu(
"addOther",
"mdi2f-folder-plus-outline", null, DataStoreCreationCategory.CLUSTER, DataStoreCreationCategory.FILE_SYSTEM, DataStoreCreationCategory.SERIAL));
"mdi2f-folder-plus-outline", null, DataStoreCreationCategory.NETWORK, DataStoreCreationCategory.CLUSTER, DataStoreCreationCategory.FILE_SYSTEM, DataStoreCreationCategory.SERIAL));
menu.getItems().add(new SeparatorMenuItem());

View File

@@ -24,6 +24,8 @@ import javafx.scene.layout.VBox;
import lombok.Getter;
import java.util.Objects;
import static atlantafx.base.theme.Styles.ACCENT;
import static atlantafx.base.theme.Styles.BUTTON_OUTLINED;
@@ -94,12 +96,16 @@ public class ErrorHandlerComp extends SimpleRegionBuilder {
private String getEventDescription() {
var desc = event.getDescription();
String lastLine = desc;
Throwable t = event.getThrowable();
while (t != null) {
var toAppend = t.getMessage() != null
? t.getMessage()
: AppI18n.get("errorTypeOccured", t.getClass().getSimpleName());
desc = desc != null ? desc + "\n\n" + toAppend : toAppend;
if (!Objects.equals(toAppend, lastLine)) {
desc = desc != null ? desc + "\n\n" + toAppend : toAppend;
lastLine = toAppend;
}
t = t.getCause() != t && !(t instanceof ProcessOutputException) ? t.getCause() : null;
}

View File

@@ -100,6 +100,12 @@ public final class AppPrefs {
.valueClass(Boolean.class)
.requiresRestart(false)
.build());
final BooleanProperty useExternalNetcatForProxies = map(Mapping.builder()
.property(new GlobalBooleanProperty(false))
.key("useExternalNetcatForProxies")
.valueClass(Boolean.class)
.requiresRestart(false)
.build());
final BooleanProperty pinLocalMachineOnStartup = map(Mapping.builder()
.property(new GlobalBooleanProperty(false))
.key("pinLocalMachineOnStartup")
@@ -275,6 +281,12 @@ public final class AppPrefs {
.valueClass(ShellScript.class)
.log(false)
.build());
final Property<UUID> httpProxy = map(Mapping.builder()
.property(new GlobalObjectProperty<>())
.key("httpProxy")
.valueClass(UUID.class)
.requiresRestart(false)
.build());
final Property<UUID> terminalProxy = map(Mapping.builder()
.property(new GlobalObjectProperty<>())
.key("terminalProxy")
@@ -443,6 +455,7 @@ public final class AppPrefs {
new ApiCategory(),
new McpCategory(),
new UpdatesCategory(),
new HttpProxyCategory(),
new SecurityCategory(),
new WorkspacesCategory(),
new DeveloperCategory(),
@@ -465,6 +478,10 @@ public final class AppPrefs {
return globalStorageHandler.isInitialized();
}
public ObservableBooleanValue useExternalNetcatForProxies() {
return useExternalNetcatForProxies;
}
public ObservableValue<Boolean> disableHttpsTlsCheck() {
return disableHttpsTlsCheck;
}
@@ -585,6 +602,10 @@ public final class AppPrefs {
return apiKey;
}
public ObservableValue<UUID> httpProxy() {
return httpProxy;
}
public ObservableBooleanValue disableApiAuthentication() {
return disableApiAuthentication;
}

View File

@@ -0,0 +1,110 @@
package io.xpipe.app.prefs;
import io.xpipe.app.comp.BaseRegionBuilder;
import io.xpipe.app.comp.RegionBuilder;
import io.xpipe.app.comp.base.*;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.ext.DataStore;
import io.xpipe.app.ext.DataStoreCreationCategory;
import io.xpipe.app.ext.DataStoreProviders;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.hub.comp.StoreChoiceComp;
import io.xpipe.app.hub.comp.StoreCreationDialog;
import io.xpipe.app.hub.comp.StoreCreationModel;
import io.xpipe.app.hub.comp.StoreViewState;
import io.xpipe.app.platform.LabelGraphic;
import io.xpipe.app.platform.OptionsBuilder;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntry;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.terminal.*;
import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.HttpProxy;
import io.xpipe.core.OsType;
import javafx.beans.property.SimpleObjectProperty;
public class HttpProxyCategory extends AppPrefsCategory {
@Override
protected String getId() {
return "httpProxy";
}
@Override
protected LabelGraphic getIcon() {
return new LabelGraphic.IconGraphic("mdi2s-server-network-outline");
}
@Override
protected BaseRegionBuilder<?, ?> create() {
var prefs = AppPrefs.get();
return new OptionsBuilder()
.title("httpProxyConfiguration")
.sub(proxy())
.sub(new OptionsBuilder()
.pref(prefs.disableHttpsTlsCheck)
.addToggle(prefs.disableHttpsTlsCheck)
)
.buildComp();
}
private OptionsBuilder proxy() {
var prefs = AppPrefs.get();
var initial = prefs.httpProxy.getValue();
var initialRef = initial != null ? DataStorage.get().getStoreEntryIfPresent(initial)
.map(e -> e.ref())
.filter(e -> HttpProxy.canUseAsProxy(e))
.orElse(null) : null;
var ref = new SimpleObjectProperty<>(initialRef);
ref.addListener((observable, oldValue, newValue) -> {
prefs.httpProxy.setValue(
newValue != null
? newValue.get().getUuid()
: null);
});
var proxyChoice = new DelayedInitComp(
RegionBuilder.of(() -> {
var comp = new StoreChoiceComp<>(
null,
ref,
DataStore.class,
r -> HttpProxy.canUseAsProxy(r),
StoreViewState.get().getAllConnectionsCategory()) {
@Override
protected String toName(DataStoreEntry entry) {
if (entry == null) {
return AppI18n.get("systemDefault");
}
return super.toName(entry);
}
@Override
protected String toGraphic(DataStoreEntry entry) {
if (entry == null) {
return "proc:networkProxy_icon.svg";
}
return super.toGraphic(entry);
}
};
return comp.build();
}),
() -> StoreViewState.get() != null && StoreViewState.get().isInitialized());
proxyChoice.maxWidth(getCompWidth());
var addButton = new ButtonComp(AppI18n.observable("addProxy"), () -> {
var selected = DataStoreProviders.byId("networkProxy").orElseThrow();
StoreCreationDialog.showCreation(
null, selected.defaultStore(DataStorage.get().getSelectedCategory()),
DataStoreCreationCategory.NETWORK,
ignored -> {},
false);
});
return new OptionsBuilder()
.nameAndDescription("httpProxy")
.addComp(proxyChoice, ref)
.addComp(addButton);
}
}

View File

@@ -138,7 +138,7 @@ public class McpCategory extends AppPrefsCategory {
.pref(prefs.enableMcpServer)
.addToggle(prefs.enableMcpServer)
.nameAndDescription("mcpClientConfigurationDetails")
.addComp(tabComp)
.addComp(tabComp.maxWidth(getCompWidth()))
.pref(prefs.enableMcpMutationTools)
.addToggle(prefs.enableMcpMutationTools)
.hide(prefs.enableMcpServer.not())
@@ -150,7 +150,7 @@ public class McpCategory extends AppPrefsCategory {
.getTextArea()
.promptTextProperty()
.bind(AppI18n.observable("mcpAdditionalContextSample"));
}))
}).maxWidth(getCompWidth()))
.hide(prefs.enableMcpServer.not()))
.buildComp();
}

View File

@@ -35,8 +35,7 @@ public class SecurityCategory extends AppPrefsCategory {
.addToggle(prefs.dontAutomaticallyStartVmSshServer)
.pref(prefs.disableTerminalRemotePasswordPreparation)
.addToggle(prefs.disableTerminalRemotePasswordPreparation)
.pref(prefs.disableHttpsTlsCheck)
.addToggle(prefs.disableHttpsTlsCheck));
);
return builder.buildComp();
}
}

View File

@@ -34,6 +34,11 @@ public class SshCategory extends AppPrefsCategory {
options.addComp(prefs.getCustomOptions("x11WslInstance").buildComp());
}
options.sub(new OptionsBuilder()
.pref(prefs.useExternalNetcatForProxies)
.addToggle(prefs.useExternalNetcatForProxies)
);
var agentTest = new SshAgentTestComp(
() -> {},
new SimpleObjectProperty<>(CustomAgentStrategy.builder().build()));

View File

@@ -190,9 +190,7 @@ public class HashicorpVaultPasswordManager implements PasswordManager {
}
var res = HttpHelper.client().send(req.build(), HttpResponse.BodyHandlers.ofString());
if (res.statusCode() >= 400) {
throw new IOException(res.body());
}
HttpHelper.checkOrThrow(res);
var resJson = JacksonMapper.getDefault().readTree(res.body());
if (!resJson.isObject()) {

View File

@@ -265,9 +265,7 @@ public interface DataStorageGroupStrategy {
.POST(java.net.http.HttpRequest.BodyPublishers.noBody())
.build();
var result = HttpHelper.client().send(request, HttpResponse.BodyHandlers.ofString());
if (result.statusCode() >= 400) {
throw ErrorEventFactory.expected(new IOException(result.body()));
}
HttpHelper.checkOrThrow(result);
var body = result.body();
if (body.length() == 0) {
throw ErrorEventFactory.expected(new IllegalArgumentException("Http response body is empty"));

View File

@@ -51,7 +51,7 @@ public class MobaXTermTerminalType implements ExternalApplicationType.WindowsTyp
var rawCommand = command.buildSimple();
var script = AppLocalTemp.getLocalTempDataDirectory().resolve("mobaxpipe.sh");
Files.writeString(Path.of(script.toString()), "#!/usr/bin/env bash\n" + rawCommand);
var fixedFile = script.toString().replaceAll("\\\\", "/").replaceAll("\\s", "\\$0");
var fixedFile = script.toString().replaceAll("\\\\", "/").replaceAll("\\s", "\\\\$0");
launch(CommandBuilder.of().add("-newtab").add(fixedFile));
}

View File

@@ -31,9 +31,7 @@ public class AppDownloads {
var httpRequest = builder.uri(URI.create(release.getUrl())).GET().build();
var client = HttpHelper.client();
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
if (response.statusCode() >= 400) {
throw new IOException(new String(response.body(), StandardCharsets.UTF_8));
}
HttpHelper.checkOrThrow(response);
var downloadFile = AppCache.getBasePath().resolve(release.getFile());
Files.write(downloadFile, response.body());
@@ -64,10 +62,7 @@ public class AppDownloads {
var httpRequest = builder.uri(uri).GET().build();
var client = HttpHelper.client();
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {
var s = response.body();
throw new IOException("Changelog not found" + (s != null && !s.isEmpty() ? ": " + s : ""));
}
HttpHelper.checkOrThrow(response);
var json = JacksonMapper.getDefault().readTree(response.body());
var changelog = json.required("changelog").asText();
return changelog;
@@ -104,9 +99,7 @@ public class AppDownloads {
.build();
var client = HttpHelper.client();
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {
throw new IOException(response.body());
}
HttpHelper.checkOrThrow(response);
var dateEntry = response.headers().firstValue("Date");
if (dateEntry.isPresent()) {

View File

@@ -28,9 +28,7 @@ public class GithubReleaseDownloader {
.uri(URI.create(getDownloadUrl(repository, filter)))
.build();
var r = HttpHelper.client().send(request, HttpResponse.BodyHandlers.ofByteArray());
if (r.statusCode() >= 400) {
throw new IOException(new String(r.body(), StandardCharsets.UTF_8));
}
HttpHelper.checkOrThrow(r);
Files.createDirectories(tempDir);
Files.write(temp, r.body());
@@ -55,9 +53,7 @@ public class GithubReleaseDownloader {
.uri(URI.create("https://api.github.com/repos/" + repository + "/releases"))
.build();
var r = HttpHelper.client().send(request, HttpResponse.BodyHandlers.ofString());
if (r.statusCode() >= 400) {
throw new IOException(r.body());
}
HttpHelper.checkOrThrow(r);
var json = JacksonMapper.getDefault().readTree(r.body());
var latest = json.get(0);

View File

@@ -1,10 +1,18 @@
package io.xpipe.app.util;
import io.xpipe.app.core.AppI18n;
import io.xpipe.app.issue.ErrorAction;
import io.xpipe.app.issue.ErrorEvent;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.prefs.AppPrefs;
import lombok.SneakyThrows;
import java.io.IOException;
import java.net.*;
import java.net.http.HttpClient;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
@@ -15,10 +23,17 @@ public class HttpHelper {
@SneakyThrows
public static HttpClient client() {
var proxy = HttpProxy.getActiveProxy();
return client(proxy.orElse(null), AppPrefs.get() != null && AppPrefs.get().disableHttpsTlsCheck().getValue());
}
@SneakyThrows
public static HttpClient client(HttpProxy proxy, boolean checkTls) {
var builder = HttpClient.newBuilder();
builder.version(HttpClient.Version.HTTP_1_1);
builder.followRedirects(HttpClient.Redirect.NORMAL);
if (AppPrefs.get() != null && AppPrefs.get().disableHttpsTlsCheck().getValue()) {
if (!checkTls) {
var sslContext = SSLContext.getInstance("TLS");
var trustManager = new X509TrustManager() {
@Override
@@ -35,6 +50,62 @@ public class HttpHelper {
sslContext.init(null, new TrustManager[] {trustManager}, new SecureRandom());
builder.sslContext(sslContext);
}
if (proxy != null) {
builder.proxy(ProxySelector.of(new InetSocketAddress(proxy.getHost(), proxy.getPort())));
builder.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
if (proxy.getUser() != null && proxy.getPassword() != null) {
return new PasswordAuthentication(proxy.getUser(), proxy.getPassword().getSecret());
} else {
return null;
}
}
});
}
return builder.build();
}
public static void checkOrThrow(HttpResponse<?> res) throws IOException {
if (res.statusCode() == 407) {
var ex = new IOException("HTTP proxy authentication required");
ErrorEventFactory.preconfigure(ErrorEventFactory.fromThrowable(ex)
.expected()
.customAction(new ErrorAction() {
@Override
public String getName() {
return AppI18n.get("httpProxyError");
}
@Override
public String getDescription() {
return AppI18n.get("httpProxyErrorDescription");
}
@Override
public boolean handle(ErrorEvent event) throws Exception {
AppPrefs.get().selectCategory("httpProxy");
return true;
}
}));
throw ex;
}
if (res.statusCode() >= 400) {
if (res.body() instanceof String s) {
var msg = !s.isEmpty() ?
s :
"Received HTTP " + res.statusCode() + " without further details";
throw new IOException(msg);
} else if (res.body() instanceof byte[] b) {
var msg = b.length > 0 ?
new String(b, StandardCharsets.UTF_8) :
"Received HTTP " + res.statusCode() + " without further details";
throw new IOException(msg);
}
}
}
}

View File

@@ -0,0 +1,59 @@
package io.xpipe.app.util;
import io.xpipe.app.ext.DataStore;
import io.xpipe.app.ext.ProcessControlProvider;
import io.xpipe.app.ext.ShellStore;
import io.xpipe.app.issue.ErrorEventFactory;
import io.xpipe.app.prefs.AppPrefs;
import io.xpipe.app.storage.DataStorage;
import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.core.SecretValue;
import lombok.Value;
import java.util.Optional;
@Value
public class HttpProxy {
public static Optional<HttpProxy> getActiveProxy() {
if (AppPrefs.get() == null) {
return Optional.empty();
}
var current = AppPrefs.get().httpProxy().getValue();
if (current == null) {
return Optional.empty();
}
var found = DataStorage.get().getStoreEntryIfPresent(current);
if (found.isEmpty()) {
return Optional.empty();
}
try {
var proxy = ProcessControlProvider.get().getHttpProxy(found.get().ref());
return proxy;
} catch (Exception e) {
ErrorEventFactory.fromThrowable(e).handle();
return Optional.empty();
}
}
public static boolean canUseAsProxy(DataStoreEntryRef<DataStore> ref) {
if (!ref.get().getValidity().isUsable()) {
return false;
}
try {
return ProcessControlProvider.get().getHttpProxy(ref).isPresent();
} catch (Exception e) {
ErrorEventFactory.fromThrowable(e).handle();
return false;
}
}
String host;
int port;
String user;
SecretValue password;
}

View File

@@ -168,8 +168,13 @@ def getJvmArgs() {
// Why is this not on by default? ...
// https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/net/doc-files/net-properties.html
// https://stackoverflow.com/questions/53333556/proxy-authentication-with-jdk-11-httpclient
// https://stackoverflow.com/questions/75150081/ioexception-too-many-authentication-attempts-limit-3-when-using-jdk-httpcli
jvmRunArgs += [
'-Djava.net.useSystemProxies=true'
'-Djava.net.useSystemProxies=true',
'-Djdk.http.auth.proxying.disabledSchemes=""',
'-Djdk.http.auth.tunneling.disabledSchemes=""',
'-Djdk.httpclient.auth.retrylimit=1'
]
// Fix platform theme detection on macOS

View File

@@ -177,9 +177,7 @@ public interface ScriptTextSource {
var req = HttpRequest.newBuilder().GET().uri(URI.create(url)).build();
var r = HttpHelper.client().send(req, HttpResponse.BodyHandlers.ofString());
if (r.statusCode() >= 400) {
throw ErrorEventFactory.expected(new IOException(r.body()));
}
HttpHelper.checkOrThrow(r);
Files.createDirectories(path.getParent());
Files.writeString(path, r.body());

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Layer_1"
data-name="Layer 1"
viewBox="0 0 204.59 204.59"
version="1.1"
sodipodi:docname="networkProxy_icon-dark.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.3945823"
inkscape:cx="136.24151"
inkscape:cy="99.312891"
inkscape:window-width="1920"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><defs
id="defs856"><style
id="style854">.cls-1{fill:#ac55ff;}</style><style
id="style2411">.cls-1{fill:#606161;}</style></defs><title
id="title858">identity</title><path
class="cls-1"
d="M332.32,153.7H179.68a26,26,0,0,0-26,26V332.32a26,26,0,0,0,26,26H332.32a26,26,0,0,0,26-26V179.68A26,26,0,0,0,332.32,153.7Zm14,178.62a14,14,0,0,1-14,14H179.68a14,14,0,0,1-14-14V179.68a14,14,0,0,1,14-14H332.32a14,14,0,0,1,14,14Z"
id="path860"
style="fill:#dfdfdf;fill-opacity:1"
transform="translate(-153.7 -153.7)" /><metadata
id="metadata932"><rdf:RDF><cc:Work
rdf:about=""><dc:title>identity</dc:title></cc:Work></rdf:RDF></metadata><path
d="M 50.618789,177.19298 H 154.7908 a 10.417202,10.417202 0 0 0 10.41722,-10.41719 V 135.52418 A 10.417202,10.417202 0 0 0 154.7908,125.10696 H 50.618789 a 10.417202,10.417202 0 0 0 -10.417198,10.41722 v 31.25161 a 10.417202,10.417202 0 0 0 10.417198,10.41719 z m 0,-41.6688 H 154.7908 v 31.25161 H 50.618789 Z"
id="path1"
style="stroke-width:5.2086;fill:#147dff;fill-opacity:1" /><path
d="m 154.7908,31.352142 -7.34411,7.344134 13.43818,13.490275 H 135.59711 A 36.374266,36.374266 0 0 0 66.661278,73.020945 H 44.524724 L 57.962907,59.53067 50.618789,52.186551 24.575781,78.229559 50.618789,104.27257 57.962907,96.928436 44.524724,83.438162 H 69.812481 A 36.374266,36.374266 0 0 0 138.74831,62.603748 h 22.13656 l -13.43818,13.490276 7.34411,7.344138 26.04301,-26.043012 z M 128.74781,67.812346 A 25.95446,25.95446 0 0 1 82.003214,83.438162 H 102.7048 V 73.020945 H 77.188388 A 25.96592,25.96592 0 0 1 123.40638,52.186551 H 102.7048 v 10.417197 h 25.51641 a 26.052903,26.052903 0 0 1 0.5266,5.208598 z"
id="path2"
style="stroke-width:5.2086;fill:#3cbb39;fill-opacity:1" /><circle
cx="68.352188"
cy="150.98668"
r="9.7888479"
id="circle1"
style="stroke-width:9.78885;fill:#f38523;fill-opacity:1" /></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
id="Layer_1"
data-name="Layer 1"
viewBox="0 0 204.59 204.59"
version="1.1"
sodipodi:docname="networkProxy_icon.svg"
inkscape:version="1.4 (86a8ad7, 2024-10-11)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="1.3945823"
inkscape:cx="136.24151"
inkscape:cy="99.312891"
inkscape:window-width="1920"
inkscape:window-height="1009"
inkscape:window-x="-8"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" /><defs
id="defs856"><style
id="style854">.cls-1{fill:#ac55ff;}</style><style
id="style2411">.cls-1{fill:#606161;}</style></defs><title
id="title858">identity</title><path
class="cls-1"
d="M332.32,153.7H179.68a26,26,0,0,0-26,26V332.32a26,26,0,0,0,26,26H332.32a26,26,0,0,0,26-26V179.68A26,26,0,0,0,332.32,153.7Zm14,178.62a14,14,0,0,1-14,14H179.68a14,14,0,0,1-14-14V179.68a14,14,0,0,1,14-14H332.32a14,14,0,0,1,14,14Z"
id="path860"
style="fill:#212121;fill-opacity:1"
transform="translate(-153.7 -153.7)" /><metadata
id="metadata932"><rdf:RDF><cc:Work
rdf:about=""><dc:title>identity</dc:title></cc:Work></rdf:RDF></metadata><path
d="M 50.618789,177.19298 H 154.7908 a 10.417202,10.417202 0 0 0 10.41722,-10.41719 V 135.52418 A 10.417202,10.417202 0 0 0 154.7908,125.10696 H 50.618789 a 10.417202,10.417202 0 0 0 -10.417198,10.41722 v 31.25161 a 10.417202,10.417202 0 0 0 10.417198,10.41719 z m 0,-41.6688 H 154.7908 v 31.25161 H 50.618789 Z"
id="path1"
style="stroke-width:5.2086;fill:#0066e3;fill-opacity:1" /><path
d="m 154.7908,31.352142 -7.34411,7.344134 13.43818,13.490275 H 135.59711 A 36.374266,36.374266 0 0 0 66.661278,73.020945 H 44.524724 L 57.962907,59.53067 50.618789,52.186551 24.575781,78.229559 50.618789,104.27257 57.962907,96.928436 44.524724,83.438162 H 69.812481 A 36.374266,36.374266 0 0 0 138.74831,62.603748 h 22.13656 l -13.43818,13.490276 7.34411,7.344138 26.04301,-26.043012 z M 128.74781,67.812346 A 25.95446,25.95446 0 0 1 82.003214,83.438162 H 102.7048 V 73.020945 H 77.188388 A 25.96592,25.96592 0 0 1 123.40638,52.186551 H 102.7048 v 10.417197 h 25.51641 a 26.052903,26.052903 0 0 1 0.5266,5.208598 z"
id="path2"
style="stroke-width:5.2086;fill:#30962e;fill-opacity:1" /><circle
cx="68.352188"
cy="150.98668"
r="9.7888479"
id="circle1"
style="stroke-width:9.78885;fill:#f27b10;fill-opacity:1" /></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -168,4 +168,5 @@ protonPassPasswordPlaceholder=Vault Name/Item name
protonPass=Proton Pass
passwork=Passwork
passworkPlaceholder=Item ID
socks5=SOCKS5

View File

@@ -1237,6 +1237,8 @@ customIpDescription=Override the default local VM IP detection if you use advanc
automaticallyDetect=Automatically detect
userAddDialogTitle=User creation
groupAddDialogTitle=Group creation
keyPassphrase=Key passphrase
keyPassphraseDescription=The optional passphrase for your key
passphrase=Passphrase
repeatPassphrase=Repeat passphrase
groupSecret=Group secret
@@ -2077,3 +2079,24 @@ rdpWindowsSecurityWarningDialogTitle=RDP security warnings
rdpWindowsSecurityWarningDialogContent=Since Windows build 26200, Windows will now always show of warning when an unsigned RDP file is launched, regardless of its contents.\n\nYou can disable this warning in the settings menu.
openSettings=Open settings
toggleSizeLock=Toggle size lock
useExternalNetcatForProxies=Use externally installed netcat executable for proxies
useExternalNetcatForProxiesDescription=Use locally installed netcat executable to proxy SSH connections instead of the built-in proxy functionality if possible. This requires ncat to be installed on Windows and nc on other operating systems.
networkProxy.displayName=Network proxy
networkProxy.displayDescription=Configure a proxy server to use as a gateway for connections
networkProxyType=Proxy type
networkProxyTypeDescription=The protocol of the proxy server
networkProxyHost=Host
networkProxyHostDescription=The host the proxy server is running on
networkProxyPort=Port
networkProxyPortDescription=The port the proxy server is listening on
networkProxyUsername=Username
networkProxyUsernameDescription=The username to log into the proxy if authentication is required
networkProxyPassword=Password
networkProxyPasswordDescription=The password to log into the proxy if authentication is required
httpProxy=HTTP proxy
httpProxyDescription=The proxy to use for any kind of HTTP requests sent by XPipe, e.g. update checks and license check requests.
httpProxyConfiguration=HTTP proxy configuration
addProxy=Add proxy ...
httpProxyError=Configure HTTP proxy settings
httpProxyErrorDescription=Add HTTP proxy authentication details in the settings menu
systemDefault=System default

View File

@@ -1 +1 @@
22.11-1
23.0-1