diff --git a/app/src/main/java/io/xpipe/app/core/AppLogs.java b/app/src/main/java/io/xpipe/app/core/AppLogs.java index f860fa6d8..2b01f8c20 100644 --- a/app/src/main/java/io/xpipe/app/core/AppLogs.java +++ b/app/src/main/java/io/xpipe/app/core/AppLogs.java @@ -18,6 +18,7 @@ import org.slf4j.spi.MDCAdapter; import org.slf4j.spi.SLF4JServiceProvider; import java.io.*; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.time.Instant; @@ -121,7 +122,7 @@ public class AppLogs { var file = usedLogsDir.resolve(AppNames.ofMain().getKebapName() + ".log"); var fos = new FileOutputStream(file.toFile(), true); var buf = new BufferedOutputStream(fos); - outFileStream = new PrintStream(buf, false); + outFileStream = new PrintStream(buf, false, StandardCharsets.UTF_8); } catch (Exception ex) { ErrorEventFactory.fromThrowable(ex).build().handle(); } @@ -175,7 +176,7 @@ public class AppLogs { @Override public void write(int b) { if (b == '\r' || b == '\n') { - String line = baos.toString(); + String line = baos.toString(StandardCharsets.UTF_8); if (line.length() == 0) { return; } @@ -186,7 +187,7 @@ public class AppLogs { baos.write(b); } } - })); + },true, StandardCharsets.UTF_8)); } private void hookUpSystemErr() { @@ -196,7 +197,7 @@ public class AppLogs { @Override public void write(int b) { if (b == '\r' || b == '\n') { - String line = baos.toString(); + String line = baos.toString(StandardCharsets.UTF_8); if (line.length() == 0) { return; } @@ -209,7 +210,7 @@ public class AppLogs { baos.write(b); } } - })); + },true, StandardCharsets.UTF_8)); } public void logException(String description, Throwable e) { diff --git a/app/src/main/java/io/xpipe/app/core/mode/AppOperationMode.java b/app/src/main/java/io/xpipe/app/core/mode/AppOperationMode.java index 519be2ac4..5c2f3b9d9 100644 --- a/app/src/main/java/io/xpipe/app/core/mode/AppOperationMode.java +++ b/app/src/main/java/io/xpipe/app/core/mode/AppOperationMode.java @@ -25,6 +25,8 @@ import lombok.Getter; import lombok.SneakyThrows; import java.awt.*; +import java.io.*; +import java.nio.charset.StandardCharsets; import java.time.Duration; import java.util.Arrays; import java.util.List; @@ -129,6 +131,43 @@ public abstract class AppOperationMode { }); } + // This is very important on Windows to not get into encoding issues + if (OsType.ofLocal() == OsType.WINDOWS) { + var con = System.console(); + // If a program does not have console attached, it can't determine the code page + // This happens if the program is run non-interactively, e.g. + // $Script="$(& 'C:\Program Files\XPipe\xpipe.exe' terminal-launch --port ? --request ?)" + // If the output of this command contains special characters, the stdout will print in the system default encoding + // However, all non-interactive usages like this are done in an environment + // where XPipe or another environment sets the code page to UTF8 + // Therefore, we have to override the stdout encoding if we don't have a console + if (con == null) { + var outField = FilterOutputStream.class.getDeclaredField("out"); + outField.setAccessible(true); + + // The original raw out stream is a private class + // designed to unblock carrier threads + // We want to keep this to retain all functionality + var printStreamOut = (BufferedOutputStream) outField.get(System.out); + var fdout = (FileOutputStream) outField.get(printStreamOut); + var newStdout = new PrintStream(new BufferedOutputStream(fdout, 128), true, StandardCharsets.UTF_8); + System.setProperty("stdout.encoding", "UTF-8"); + System.setOut(newStdout); + + // The original raw err stream is a private class + // designed to unblock carrier threads + // We want to keep this to retain all functionality + var printStreamErr = (BufferedOutputStream) outField.get(System.err); + var fderr = (FileOutputStream) outField.get(printStreamErr); + var newStderr = new PrintStream(new BufferedOutputStream(fderr, 128), true, StandardCharsets.UTF_8); + System.setProperty("stderr.encoding", "UTF-8"); + System.setErr(newStderr); + + // The stdin is a raw stream + System.setProperty("stdin.encoding", "UTF-8"); + } + } + AppProperties.init(args); if (AppProperties.get().isCli()) { diff --git a/build.gradle b/build.gradle index edfa5dbbe..5ff5805b9 100644 --- a/build.gradle +++ b/build.gradle @@ -144,6 +144,7 @@ def getBaseJvmArgs() { "--add-opens", "java.base/java.lang=$appPackage", "--add-opens", "java.base/java.net=$appPackage", "--add-opens", "java.base/java.nio.file=$appPackage", + "--add-opens", "java.base/java.io=$appPackage", "--add-opens", "jdk.zipfs/jdk.nio.zipfs=io.xpipe.modulefs", ] diff --git a/dist/changelog/24.2.1.md b/dist/changelog/24.2.1.md index f24b4a543..9a3516d03 100644 --- a/dist/changelog/24.2.1.md +++ b/dist/changelog/24.2.1.md @@ -1 +1,2 @@ -- Fix debug output not showing all data messages from terminal sessions \ No newline at end of file +- Fix encoding issue on some Windows systems causing connections launches to fail +- Fix debug output not showing all data messages from terminal sessions diff --git a/version b/version index ec0aaf9cc..8fadab056 100644 --- a/version +++ b/version @@ -1 +1 @@ -24.2.1-3 +24.2.1