mirror of
https://github.com/xpipe-io/xpipe.git
synced 2026-05-29 16:11:03 +00:00
Rework http requests
This commit is contained in:
@@ -53,9 +53,6 @@ dependencies {
|
||||
api files("$rootDir/gradle/gradle_scripts/vernacular-1.16.jar")
|
||||
api 'org.bouncycastle:bcprov-jdk18on:1.80'
|
||||
api 'info.picocli:picocli:4.7.6'
|
||||
api ('org.kohsuke:github-api:1.326') {
|
||||
exclude group: 'org.apache.commons', module: 'commons-lang3'
|
||||
}
|
||||
api 'org.apache.commons:commons-lang3:3.17.0'
|
||||
api 'io.sentry:sentry:7.20.0'
|
||||
api 'commons-io:commons-io:2.18.0'
|
||||
|
||||
@@ -55,7 +55,8 @@ public class ConnectionFileSystem implements FileSystem {
|
||||
if (!shellControl.getTtyState().isPreservesOutput()
|
||||
|| !shellControl.getTtyState().isSupportsInput()) {
|
||||
throw ErrorEvent.expected(new UnsupportedOperationException(
|
||||
"Shell has a PTY allocated and as a result does not support file system operations. For more information see " + Hyperlinks.DOCS_TTY));
|
||||
"Shell has a PTY allocated and as a result does not support file system operations. For more information see "
|
||||
+ Hyperlinks.DOCS_TTY));
|
||||
}
|
||||
|
||||
shellControl.checkLicenseOrThrow();
|
||||
|
||||
@@ -132,6 +132,8 @@ public class AppPrefs {
|
||||
mapLocal(new SimpleBooleanProperty(false), "enforceWindowModality", Boolean.class, false);
|
||||
final BooleanProperty checkForSecurityUpdates =
|
||||
mapLocal(new SimpleBooleanProperty(true), "checkForSecurityUpdates", Boolean.class, false);
|
||||
final BooleanProperty disableApiHttpsTlsCheck =
|
||||
mapLocal(new SimpleBooleanProperty(false), "disableApiHttpsTlsCheck", Boolean.class, false);
|
||||
final BooleanProperty condenseConnectionDisplay =
|
||||
mapLocal(new SimpleBooleanProperty(false), "condenseConnectionDisplay", Boolean.class, false);
|
||||
final BooleanProperty showChildCategoriesInParentCategory =
|
||||
|
||||
@@ -3,10 +3,10 @@ package io.xpipe.app.prefs;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellDialects;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ExternalApplicationHelper {
|
||||
|
||||
@@ -21,17 +21,32 @@ public class ExternalApplicationHelper {
|
||||
}
|
||||
|
||||
public static void startAsync(String raw) throws Exception {
|
||||
try (var sc = LocalShell.getShell().start()) {
|
||||
if (ShellDialects.isPowershell(sc)) {
|
||||
// Do the best effort here
|
||||
// This does not respect quoting rules, but otherwise powershell wouldn't work at all
|
||||
var split = raw.split("\\s+");
|
||||
var splitBuilder = CommandBuilder.of().addAll(Arrays.asList(split));
|
||||
startAsync(splitBuilder);
|
||||
} else {
|
||||
startAsync(CommandBuilder.ofString(raw));
|
||||
}
|
||||
if (raw == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
raw = raw.trim();
|
||||
var split = Arrays.asList(raw.split("\\s+"));
|
||||
if (split.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
String exec;
|
||||
String args;
|
||||
if (raw.startsWith("\"")) {
|
||||
var end = raw.substring(1).indexOf("\"");
|
||||
if (end == -1) {
|
||||
return;
|
||||
}
|
||||
end++;
|
||||
exec = raw.substring(1, end);
|
||||
args = raw.substring(end + 1).trim();
|
||||
} else {
|
||||
exec = split.getFirst();
|
||||
args = split.stream().skip(1).collect(Collectors.joining(" "));
|
||||
}
|
||||
|
||||
startAsync(CommandBuilder.of().addFile(exec).add(args));
|
||||
}
|
||||
|
||||
public static void startAsync(CommandBuilder b) throws Exception {
|
||||
|
||||
@@ -30,7 +30,9 @@ public class SecurityCategory extends AppPrefsCategory {
|
||||
.pref(prefs.dontAutomaticallyStartVmSshServer)
|
||||
.addToggle(prefs.dontAutomaticallyStartVmSshServer)
|
||||
.pref(prefs.disableTerminalRemotePasswordPreparation)
|
||||
.addToggle(prefs.disableTerminalRemotePasswordPreparation));
|
||||
.addToggle(prefs.disableTerminalRemotePasswordPreparation)
|
||||
.pref(prefs.disableApiHttpsTlsCheck)
|
||||
.addToggle(prefs.disableApiHttpsTlsCheck));
|
||||
return builder.buildComp();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
package io.xpipe.app.terminal;
|
||||
|
||||
import io.xpipe.app.util.CommandSupport;
|
||||
import io.xpipe.app.util.LocalShell;
|
||||
import io.xpipe.core.process.CommandBuilder;
|
||||
import io.xpipe.core.process.ShellControl;
|
||||
|
||||
public class GnomeConsoleType extends ExternalTerminalType.SimplePathType implements TrackableTerminalType {
|
||||
|
||||
|
||||
@@ -56,7 +56,9 @@ public class MobaXTermTerminalType extends ExternalTerminalType.WindowsType {
|
||||
SshLocalBridge.init();
|
||||
var b = SshLocalBridge.get();
|
||||
var abs = b.getIdentityKey().toAbsolutePath();
|
||||
var drivePath = "/drives/" + abs.getRoot().toString().substring(0, 1).toLowerCase() + "/" + abs.getRoot().relativize(abs).toString().replaceAll("\\\\", "/");
|
||||
var drivePath =
|
||||
"/drives/" + abs.getRoot().toString().substring(0, 1).toLowerCase() + "/"
|
||||
+ abs.getRoot().relativize(abs).toString().replaceAll("\\\\", "/");
|
||||
var winPath = b.getIdentityKey().toString().replaceAll("\\\\", "\\\\\\\\");
|
||||
var command = CommandBuilder.of()
|
||||
.add("ssh")
|
||||
|
||||
@@ -4,140 +4,61 @@ import io.xpipe.app.core.AppDistributionType;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.issue.TrackEvent;
|
||||
import io.xpipe.app.util.HttpHelper;
|
||||
import io.xpipe.app.util.LicenseProvider;
|
||||
import io.xpipe.core.process.OsType;
|
||||
import io.xpipe.core.util.JacksonMapper;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import lombok.Value;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.kohsuke.github.GHRelease;
|
||||
import org.kohsuke.github.GHRepository;
|
||||
import org.kohsuke.github.GitHubBuilder;
|
||||
import org.kohsuke.github.RateLimitHandler;
|
||||
import org.kohsuke.github.authorization.AuthorizationProvider;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public class AppDownloads {
|
||||
|
||||
private static GHRepository repository;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private static GHRepository getRepository() throws IOException {
|
||||
if (repository != null) {
|
||||
return repository;
|
||||
public static Path downloadInstaller(String version) throws Exception {
|
||||
var release = Release.of(version);
|
||||
var builder = HttpRequest.newBuilder();
|
||||
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));
|
||||
}
|
||||
|
||||
var github = new GitHubBuilder()
|
||||
.withRateLimitHandler(RateLimitHandler.FAIL)
|
||||
.withAuthorizationProvider(AuthorizationProvider.ANONYMOUS)
|
||||
.build();
|
||||
repository = github.getRepository(AppProperties.get().isStaging() ? "xpipe-io/xpipe-ptb" : "xpipe-io/xpipe");
|
||||
return repository;
|
||||
var downloadFile = FileUtils.getTempDirectory().toPath().resolve(release.getFile());
|
||||
Files.write(downloadFile, response.body());
|
||||
TrackEvent.withInfo("Downloaded asset")
|
||||
.tag("version", version)
|
||||
.tag("url", release.getUrl())
|
||||
.tag("size", FileUtils.byteCountToDisplaySize(response.body().length))
|
||||
.tag("target", downloadFile)
|
||||
.handle();
|
||||
|
||||
return downloadFile;
|
||||
}
|
||||
|
||||
public static Optional<Path> downloadInstaller(
|
||||
AppInstaller.InstallerAssetType iAsset, String version, boolean omitErrors) {
|
||||
var release = AppDownloads.getRelease(version, omitErrors);
|
||||
if (release.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
var asset = release.orElseThrow().listAssets().toList().stream()
|
||||
.filter(ghAsset -> iAsset.isCorrectAsset(ghAsset.getName()))
|
||||
.findAny();
|
||||
if (asset.isEmpty()) {
|
||||
ErrorEvent.fromMessage("No matching asset found for " + iAsset.getExtension());
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
var builder = HttpRequest.newBuilder();
|
||||
var httpRequest = builder.uri(URI.create(asset.get().getBrowserDownloadUrl()))
|
||||
.GET()
|
||||
.build();
|
||||
var client = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.build();
|
||||
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofByteArray());
|
||||
if (response.statusCode() != 200) {
|
||||
throw new IOException(new String(response.body(), StandardCharsets.UTF_8));
|
||||
}
|
||||
var downloadFile =
|
||||
FileUtils.getTempDirectory().toPath().resolve(asset.get().getName());
|
||||
Files.write(downloadFile, response.body());
|
||||
TrackEvent.withInfo("Downloaded asset")
|
||||
.tag("version", version)
|
||||
.tag("url", asset.get().getBrowserDownloadUrl())
|
||||
.tag("size", FileUtils.byteCountToDisplaySize(response.body().length))
|
||||
.tag("target", downloadFile)
|
||||
.handle();
|
||||
|
||||
return Optional.of(downloadFile);
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t).omitted(omitErrors).expected().handle();
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<String> downloadChangelog(String version, boolean omitErrors) {
|
||||
var release = AppDownloads.getRelease(version, omitErrors);
|
||||
if (release.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
try {
|
||||
var uri = URI.create("https://api.xpipe.io/changelog?from="
|
||||
+ AppProperties.get().getVersion() + "&to=" + version + "&stage="
|
||||
+ AppProperties.get().isStaging());
|
||||
var builder = HttpRequest.newBuilder();
|
||||
var httpRequest = builder.uri(uri).GET().build();
|
||||
var client = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.build();
|
||||
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() != 200) {
|
||||
throw new IOException(response.body());
|
||||
}
|
||||
var json = JacksonMapper.getDefault().readTree(response.body());
|
||||
var changelog = json.required("changelog").asText();
|
||||
return Optional.of(changelog);
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t).omit().expected().handle();
|
||||
}
|
||||
|
||||
try {
|
||||
var asset = release.get().listAssets().toList().stream()
|
||||
.filter(ghAsset -> ghAsset.getName().equals("changelog.md"))
|
||||
.findAny();
|
||||
|
||||
if (asset.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
var uri = URI.create(asset.get().getBrowserDownloadUrl());
|
||||
var builder = HttpRequest.newBuilder();
|
||||
var httpRequest = builder.uri(uri).GET().build();
|
||||
var client = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.build();
|
||||
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() != 200) {
|
||||
throw new IOException(response.body());
|
||||
}
|
||||
return Optional.of(response.body());
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t).omitted(omitErrors).expected().handle();
|
||||
return Optional.empty();
|
||||
public static String downloadChangelog(String version) throws Exception {
|
||||
var uri = URI.create("https://api.xpipe.io/changelog?from="
|
||||
+ AppProperties.get().getVersion() + "&to=" + version + "&stage="
|
||||
+ AppProperties.get().isStaging());
|
||||
var builder = HttpRequest.newBuilder();
|
||||
var httpRequest = builder.uri(uri).GET().build();
|
||||
var client = HttpHelper.client();
|
||||
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() >= 400) {
|
||||
throw new IOException(response.body());
|
||||
}
|
||||
var json = JacksonMapper.getDefault().readTree(response.body());
|
||||
var changelog = json.required("changelog").asText();
|
||||
return changelog;
|
||||
}
|
||||
|
||||
private static String queryLatestVersion(boolean first, boolean securityOnly) throws Exception {
|
||||
@@ -158,11 +79,9 @@ public class AppDownloads {
|
||||
var httpRequest = builder.uri(url)
|
||||
.POST(HttpRequest.BodyPublishers.ofString(req.toPrettyString()))
|
||||
.build();
|
||||
var client = HttpClient.newBuilder()
|
||||
.followRedirects(HttpClient.Redirect.NORMAL)
|
||||
.build();
|
||||
var client = HttpHelper.client();
|
||||
var response = client.send(httpRequest, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() != 200) {
|
||||
if (response.statusCode() >= 400) {
|
||||
throw new IOException(response.body());
|
||||
}
|
||||
|
||||
@@ -176,24 +95,38 @@ public class AppDownloads {
|
||||
return ver;
|
||||
}
|
||||
|
||||
public static Optional<GHRelease> queryLatestRelease(boolean first, boolean securityOnly) throws Exception {
|
||||
public static Release queryLatestRelease(boolean first, boolean securityOnly) throws Exception {
|
||||
try {
|
||||
var ver = queryLatestVersion(first, securityOnly);
|
||||
var repo = getRepository();
|
||||
var rel = repo.getReleaseByTagName(ver);
|
||||
return Optional.ofNullable(rel);
|
||||
return Release.of(ver);
|
||||
} catch (Exception e) {
|
||||
throw ErrorEvent.expected(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Optional<GHRelease> getRelease(String version, boolean omitErrors) {
|
||||
try {
|
||||
var repo = getRepository();
|
||||
return Optional.ofNullable(repo.getReleaseByTagName(version));
|
||||
} catch (IOException e) {
|
||||
ErrorEvent.fromThrowable(e).omitted(omitErrors).expected().handle();
|
||||
return Optional.empty();
|
||||
@Value
|
||||
public static class Release {
|
||||
|
||||
public static Release of(String tag) {
|
||||
var type = AppInstaller.getSuitablePlatformAsset();
|
||||
var os =
|
||||
switch (OsType.getLocal()) {
|
||||
case OsType.Linux linux -> "linux";
|
||||
case OsType.MacOs macOs -> "macos";
|
||||
case OsType.Windows windows -> "windows";
|
||||
};
|
||||
var arch = AppProperties.get().getArch();
|
||||
var name = "xpipe-installer-%s-%s.%s".formatted(os, arch, type.getExtension());
|
||||
var url = "https://github.com/xpipe-io/%s/releases/download/%s/%s"
|
||||
.formatted(AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe", tag, name);
|
||||
var browser = "https://github.com/xpipe-io/%s/releases/%s"
|
||||
.formatted(AppProperties.get().isStaging() ? "xpipe-ptb" : "xpipe", tag);
|
||||
return new Release(tag, url, browser, name);
|
||||
}
|
||||
|
||||
String tag;
|
||||
String url;
|
||||
String browserUrl;
|
||||
String file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,21 +89,17 @@ public class AppInstaller {
|
||||
var logFile = FileNames.join(
|
||||
logsDir, "installer_" + file.getFileName().toString() + ".log");
|
||||
var systemWide = isSystemWide();
|
||||
var command = LocalShell.getShell().getShellDialect().equals(ShellDialects.CMD)
|
||||
? getCmdCommand(file.toString(), logFile, restartExec, systemWide)
|
||||
var command = LocalShell.getShell().getShellDialect().equals(ShellDialects.CMD) && !systemWide
|
||||
? getCmdCommand(file.toString(), logFile, restartExec)
|
||||
: getPowershellCommand(file.toString(), logFile, restartExec, systemWide);
|
||||
String toRun;
|
||||
if (ProcessControlProvider.get().getEffectiveLocalDialect() == ShellDialects.CMD) {
|
||||
toRun = systemWide
|
||||
? "powershell -Command Start-Process -Verb runAs -WindowStyle Minimized -FilePath cmd -ArgumentList \"/c\", '\""
|
||||
+ ScriptHelper.createLocalExecScript(command) + "\"'"
|
||||
: "start \"XPipe Updater\" /min cmd /c \"" + ScriptHelper.createLocalExecScript(command)
|
||||
+ "\"";
|
||||
if (ProcessControlProvider.get().getEffectiveLocalDialect() == ShellDialects.CMD && !systemWide) {
|
||||
toRun = "start \"XPipe Updater\" /min cmd /c \"" + ScriptHelper.createLocalExecScript(command)
|
||||
+ "\"";
|
||||
} else {
|
||||
toRun =
|
||||
"Start-Process -WindowStyle Minimized -FilePath powershell -ArgumentList \"-ExecutionPolicy\", \"Bypass\", \"-File\", \"`\""
|
||||
+ ScriptHelper.createLocalExecScript(command) + "`\"\""
|
||||
+ (systemWide ? " -Verb runAs" : "");
|
||||
+ ScriptHelper.createLocalExecScript(command) + "`\"\"";
|
||||
}
|
||||
runAndClose(() -> {
|
||||
LocalShell.getShell().executeSimpleCommand(toRun);
|
||||
@@ -112,7 +108,7 @@ public class AppInstaller {
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return ".msi";
|
||||
return "msi";
|
||||
}
|
||||
|
||||
private boolean isSystemWide() {
|
||||
@@ -120,8 +116,8 @@ public class AppInstaller {
|
||||
XPipeInstallation.getCurrentInstallationBasePath().resolve("system"));
|
||||
}
|
||||
|
||||
private String getCmdCommand(String file, String logFile, String exec, boolean systemWide) {
|
||||
var args = "MSIFASTINSTALL=7 DISABLEROLLBACK=1" + (systemWide ? " ALLUSERS=1" : "");
|
||||
private String getCmdCommand(String file, String logFile, String exec) {
|
||||
var args = "MSIFASTINSTALL=7 DISABLEROLLBACK=1";
|
||||
return String.format(
|
||||
"""
|
||||
echo Installing %s ...
|
||||
@@ -138,17 +134,18 @@ public class AppInstaller {
|
||||
private String getPowershellCommand(String file, String logFile, String exec, boolean systemWide) {
|
||||
var property = "MSIFASTINSTALL=7 DISABLEROLLBACK=1" + (systemWide ? " ALLUSERS=1" : "");
|
||||
var startProcessProperty = ", MSIFASTINSTALL=7, DISABLEROLLBACK=1" + (systemWide ? ", ALLUSERS=1" : "");
|
||||
var runas = systemWide ? "-Verb runAs" : "";
|
||||
return String.format(
|
||||
"""
|
||||
echo Installing %s ...
|
||||
cd "$env:HOMEDRIVE\\$env:HOMEPATH"
|
||||
echo '+ msiexec /i "%s" /lv "%s" /qb%s'
|
||||
Start-Process msiexec -Wait -ArgumentList "/i", "`"%s`"", "/lv", "`"%s`"", "/qb"%s
|
||||
Start-Process %s -FilePath msiexec -Wait -ArgumentList "/i", "`"%s`"", "/lv", "`"%s`"", "/qb"%s
|
||||
echo 'Starting XPipe ...'
|
||||
echo '+ "%s"'
|
||||
Start-Process -FilePath "%s"
|
||||
""",
|
||||
file, file, logFile, property, file, logFile, startProcessProperty, exec, exec);
|
||||
file, file, logFile, property, runas, file, logFile, startProcessProperty, exec, exec);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +186,7 @@ public class AppInstaller {
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return ".deb";
|
||||
return "deb";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +227,7 @@ public class AppInstaller {
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return ".rpm";
|
||||
return "rpm";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +268,7 @@ public class AppInstaller {
|
||||
|
||||
@Override
|
||||
public String getExtension() {
|
||||
return ".pkg";
|
||||
return "pkg";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.issue.ErrorEvent;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
import org.kohsuke.github.GHRelease;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
@@ -45,25 +43,18 @@ public class GitHubUpdater extends UpdateHandler {
|
||||
return list;
|
||||
}
|
||||
|
||||
public void prepareUpdateImpl() {
|
||||
var downloadFile = AppDownloads.downloadInstaller(
|
||||
lastUpdateCheckResult.getValue().getAssetType(),
|
||||
lastUpdateCheckResult.getValue().getVersion(),
|
||||
false);
|
||||
if (downloadFile.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void prepareUpdateImpl() throws Exception {
|
||||
var downloadFile =
|
||||
AppDownloads.downloadInstaller(lastUpdateCheckResult.getValue().getVersion());
|
||||
var changelogString =
|
||||
AppDownloads.downloadChangelog(lastUpdateCheckResult.getValue().getVersion(), false);
|
||||
var changelog = changelogString.orElse(null);
|
||||
AppDownloads.downloadChangelog(lastUpdateCheckResult.getValue().getVersion());
|
||||
var rel = new PreparedUpdate(
|
||||
AppProperties.get().getVersion(),
|
||||
AppDistributionType.get().getId(),
|
||||
lastUpdateCheckResult.getValue().getVersion(),
|
||||
lastUpdateCheckResult.getValue().getReleaseUrl(),
|
||||
downloadFile.get(),
|
||||
changelog,
|
||||
downloadFile,
|
||||
changelogString,
|
||||
lastUpdateCheckResult.getValue().getAssetType(),
|
||||
lastUpdateCheckResult.getValue().isSecurityOnly());
|
||||
preparedUpdate.setValue(rel);
|
||||
@@ -91,30 +82,16 @@ public class GitHubUpdater extends UpdateHandler {
|
||||
|
||||
public synchronized AvailableRelease refreshUpdateCheckImpl(boolean first, boolean securityOnly) throws Exception {
|
||||
var rel = AppDownloads.queryLatestRelease(first, securityOnly);
|
||||
event("Determined latest suitable release "
|
||||
+ rel.map(GHRelease::getName).orElse(null));
|
||||
|
||||
if (rel.isEmpty()) {
|
||||
lastUpdateCheckResult.setValue(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
var isUpdate = isUpdate(rel.get().getTagName());
|
||||
event("Determined latest suitable release " + rel.getTag());
|
||||
var isUpdate = isUpdate(rel.getTag());
|
||||
var assetType = AppInstaller.getSuitablePlatformAsset();
|
||||
var ghAsset = rel.orElseThrow().listAssets().toList().stream()
|
||||
.filter(g -> assetType.isCorrectAsset(g.getName()))
|
||||
.findAny();
|
||||
if (ghAsset.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
event("Selected asset " + ghAsset.get().getName());
|
||||
event("Selected asset " + rel.getFile());
|
||||
lastUpdateCheckResult.setValue(new AvailableRelease(
|
||||
AppProperties.get().getVersion(),
|
||||
AppDistributionType.get().getId(),
|
||||
rel.get().getTagName(),
|
||||
rel.get().getHtmlUrl().toString(),
|
||||
ghAsset.get().getBrowserDownloadUrl(),
|
||||
rel.getTag(),
|
||||
rel.getBrowserUrl(),
|
||||
rel.getUrl(),
|
||||
assetType,
|
||||
Instant.now(),
|
||||
isUpdate,
|
||||
|
||||
@@ -5,8 +5,6 @@ import io.xpipe.app.core.AppDistributionType;
|
||||
import io.xpipe.app.core.AppProperties;
|
||||
import io.xpipe.app.util.Hyperlinks;
|
||||
|
||||
import org.kohsuke.github.GHRelease;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -37,20 +35,13 @@ public class PortableUpdater extends UpdateHandler {
|
||||
|
||||
public synchronized AvailableRelease refreshUpdateCheckImpl(boolean first, boolean securityOnly) throws Exception {
|
||||
var rel = AppDownloads.queryLatestRelease(first, securityOnly);
|
||||
event("Determined latest suitable release "
|
||||
+ rel.map(GHRelease::getName).orElse(null));
|
||||
|
||||
if (rel.isEmpty()) {
|
||||
lastUpdateCheckResult.setValue(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
var isUpdate = isUpdate(rel.get().getTagName());
|
||||
event("Determined latest suitable release " + rel.getTag());
|
||||
var isUpdate = isUpdate(rel.getTag());
|
||||
lastUpdateCheckResult.setValue(new AvailableRelease(
|
||||
AppProperties.get().getVersion(),
|
||||
AppDistributionType.get().getId(),
|
||||
rel.get().getTagName(),
|
||||
rel.get().getHtmlUrl().toString(),
|
||||
rel.getTag(),
|
||||
rel.getBrowserUrl(),
|
||||
null,
|
||||
null,
|
||||
Instant.now(),
|
||||
|
||||
@@ -181,23 +181,23 @@ public abstract class UpdateHandler {
|
||||
if (AppProperties.get().isStaging() && preparedUpdate.getValue() != null) {
|
||||
UpdateAvailableDialog.showIfNeeded();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
ErrorEvent.fromThrowable(t).handle();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract List<ModalButton> createActions();
|
||||
|
||||
public void prepareUpdateImpl() {
|
||||
public void prepareUpdateImpl() throws Exception {
|
||||
var changelogString =
|
||||
AppDownloads.downloadChangelog(lastUpdateCheckResult.getValue().getVersion(), false);
|
||||
var changelog = changelogString.orElse(null);
|
||||
|
||||
AppDownloads.downloadChangelog(lastUpdateCheckResult.getValue().getVersion());
|
||||
var rel = new PreparedUpdate(
|
||||
AppProperties.get().getVersion(),
|
||||
AppDistributionType.get().getId(),
|
||||
lastUpdateCheckResult.getValue().getVersion(),
|
||||
lastUpdateCheckResult.getValue().getReleaseUrl(),
|
||||
null,
|
||||
changelog,
|
||||
changelogString,
|
||||
lastUpdateCheckResult.getValue().getAssetType(),
|
||||
lastUpdateCheckResult.getValue().isSecurityOnly());
|
||||
preparedUpdate.setValue(rel);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package io.xpipe.app.util;
|
||||
|
||||
import io.xpipe.app.prefs.AppPrefs;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
import java.net.http.HttpClient;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
public class HttpHelper {
|
||||
|
||||
@SneakyThrows
|
||||
public static HttpClient client() {
|
||||
var builder = HttpClient.newBuilder();
|
||||
builder.followRedirects(HttpClient.Redirect.NORMAL);
|
||||
if (AppPrefs.get() != null && AppPrefs.get().disableApiAuthentication().get()) {
|
||||
var sslContext = SSLContext.getInstance("TLS");
|
||||
var trustManager = new X509TrustManager() {
|
||||
@Override
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return new X509Certificate[] {};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
|
||||
};
|
||||
sslContext.init(null, new TrustManager[] {trustManager}, new SecureRandom());
|
||||
builder.sslContext(sslContext);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,6 @@ open module io.xpipe.app {
|
||||
requires org.kordamp.ikonli.material;
|
||||
requires io.sentry;
|
||||
requires io.xpipe.beacon;
|
||||
requires org.kohsuke.github;
|
||||
requires info.picocli;
|
||||
requires java.instrument;
|
||||
requires java.management;
|
||||
|
||||
Vendored
-22
@@ -1,22 +0,0 @@
|
||||
Copyright (c) 2011- Kohsuke Kawaguchi and other contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
-4
@@ -1,4 +0,0 @@
|
||||
name=Java API for GitHub
|
||||
version=1.326
|
||||
license=MIT License
|
||||
link=https://github.com/hub4j/github-api
|
||||
Generated
+2
-2
@@ -1332,5 +1332,5 @@ iconSourceDeletionContent=Do you want to delete this icon source and all associa
|
||||
refreshIcons=Refresh icons
|
||||
refreshIconsDescription=Retrieving, rendering, and caching all available 1000+ icons to .png files. This may take a while ...
|
||||
vaultUserLegacy=Vault user (Limited legacy compatibility mode)
|
||||
encryptVaultMultiUserTitle=Full old encryption for teams
|
||||
encryptVaultMultiUserContent=It is not possible to enable this option for team vaults, as it would render all data unusable for other users. If you want
|
||||
disableApiHttpsTlsCheck=Disable API HTTPS request certificate verification
|
||||
disableApiHttpsTlsCheckDescription=If your organization is decrypting your HTTPS traffic in firewalls using SSL interception, any update checks or license checks will fail due to the certificates not matching up. You can fix this by enabling this option and disabling TLS certificate validation.
|
||||
|
||||
Reference in New Issue
Block a user