Skip to content

Commit

Permalink
Fix possible encoding issues in the new AnsiNoSyncOutputStream
Browse files Browse the repository at this point in the history
  • Loading branch information
gnodet committed Oct 23, 2020
1 parent 182b884 commit 8283aaf
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 7 deletions.
8 changes: 4 additions & 4 deletions jansi/src/main/java/org/fusesource/jansi/AnsiConsole.java
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ private static PrintStream ansiSystem(boolean stdout) {
// the ansi escapes.
if (getBoolean(JANSI_STRIP)) {
jansiOutputType = JansiOutputType.STRIP_ANSI;
return new PrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out)), true);
return new PrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out), enc), true);
}

if (IS_WINDOWS) {
Expand All @@ -146,15 +146,15 @@ && SetConsoleMode(console, mode[0] | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0) {
// codes but we can use jansi-native Kernel32 API for console
try {
jansiOutputType = JansiOutputType.WINDOWS;
return newPrintStream(new AnsiNoSyncOutputStream(out, new WindowsAnsiProcessor(out, stdout)), enc);
return newPrintStream(new AnsiNoSyncOutputStream(out, new WindowsAnsiProcessor(out, stdout), enc), enc);
} catch (Throwable ignore) {
// this happens when JNA is not in the path.. or
// this happens when the stdout is being redirected to a file.
}

// Use the ANSIOutputStream to strip out the ANSI escape sequences.
jansiOutputType = JansiOutputType.STRIP_ANSI;
return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out)), enc);
return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out), enc), enc);
}

// We must be on some Unix variant or ANSI-enabled ConEmu, Cygwin or MSYS(2) on Windows...
Expand All @@ -166,7 +166,7 @@ && SetConsoleMode(console, mode[0] | ENABLE_VIRTUAL_TERMINAL_PROCESSING) != 0) {
// to strip the ANSI sequences..
if (!forceColored && isatty(stdout ? 1 : 2) == 0) {
jansiOutputType = JansiOutputType.STRIP_ANSI;
return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out)), enc);
return newPrintStream(new AnsiNoSyncOutputStream(out, new AnsiProcessor(out), enc), enc);
}
} catch (Throwable ignore) {
// These errors happen if the JNI lib is not available for your platform.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;

/**
Expand Down Expand Up @@ -62,10 +63,22 @@ public class AnsiNoSyncOutputStream extends FilterOutputStream {
private int startOfValue;
private final ArrayList<Object> options = new ArrayList<Object>();
private int state = LOOKING_FOR_FIRST_ESC_CHAR;
private final Charset cs;

public AnsiNoSyncOutputStream(OutputStream os, AnsiProcessor ap) {
this(os, ap, Charset.defaultCharset());
}

public AnsiNoSyncOutputStream(OutputStream os, AnsiProcessor ap, Charset cs) {
super(os);
this.ap = ap;
this.cs = cs;
}

public AnsiNoSyncOutputStream(OutputStream os, AnsiProcessor ap, String encoding) {
super(os);
this.ap = ap;
this.cs = encoding != null ? Charset.forName(encoding) : Charset.defaultCharset();
}

/**
Expand Down Expand Up @@ -138,7 +151,7 @@ public void write(int data) throws IOException {
case LOOKING_FOR_STR_ARG_END:
buffer[pos++] = (byte) data;
if ('"' != data) {
String value = new String(buffer, startOfValue, (pos - 1) - startOfValue);
String value = new String(buffer, startOfValue, (pos - 1) - startOfValue, cs);
options.add(value);
if (data == ';') {
state = LOOKING_FOR_NEXT_ARG;
Expand Down Expand Up @@ -177,7 +190,7 @@ public void write(int data) throws IOException {
case LOOKING_FOR_OSC_PARAM:
buffer[pos++] = (byte) data;
if (BEL == data) {
String value = new String(buffer, startOfValue, (pos - 1) - startOfValue);
String value = new String(buffer, startOfValue, (pos - 1) - startOfValue, cs);
options.add(value);
reset(ap.processOperatingSystemCommand(options));
} else if (FIRST_ESC_CHAR == data) {
Expand All @@ -190,7 +203,7 @@ public void write(int data) throws IOException {
case LOOKING_FOR_ST:
buffer[pos++] = (byte) data;
if (SECOND_ST_CHAR == data) {
String value = new String(buffer, startOfValue, (pos - 2) - startOfValue);
String value = new String(buffer, startOfValue, (pos - 2) - startOfValue, cs);
options.add(value);
reset(ap.processOperatingSystemCommand(options));
} else {
Expand Down
60 changes: 60 additions & 0 deletions jansi/src/test/java/org/fusesource/jansi/EncodingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2009-2020 the original author(s).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/package org.fusesource.jansi;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class EncodingTest {

@Test
public void testEncoding8859() throws UnsupportedEncodingException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final AtomicReference<String> newLabel = new AtomicReference<String>();
PrintStream ansi = new PrintStream(new AnsiNoSyncOutputStream(baos, new AnsiProcessor(baos) {
@Override
protected void processChangeWindowTitle(String label) {
newLabel.set(label);
}
}, "ISO-8859-1"), true, "ISO-8859-1");

ansi.print("\033]0;un bon café\007");
ansi.flush();
assertEquals("un bon café", newLabel.get());
}

@Test
public void testEncodingUtf8() throws UnsupportedEncodingException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final AtomicReference<String> newLabel = new AtomicReference<String>();
PrintStream ansi = new PrintStream(new AnsiNoSyncOutputStream(baos, new AnsiProcessor(baos) {
@Override
protected void processChangeWindowTitle(String label) {
newLabel.set(label);
}
}, "UTF-8"), true, "UTF-8");

ansi.print("\033]0;ひらがな\007");
ansi.flush();
assertEquals("ひらがな", newLabel.get());
}

}

0 comments on commit 8283aaf

Please sign in to comment.