66import org .slf4j .Logger ;
77import org .slf4j .LoggerFactory ;
88
9- import java .io .FileNotFoundException ;
109import java .io .IOException ;
11- import java .io .RandomAccessFile ;
10+ import java .nio .ByteBuffer ;
11+ import java .nio .CharBuffer ;
12+ import java .nio .channels .AsynchronousFileChannel ;
13+ import java .nio .charset .Charset ;
14+ import java .nio .charset .CharsetDecoder ;
1215import java .nio .charset .StandardCharsets ;
16+ import java .nio .file .Path ;
17+ import java .nio .file .Paths ;
18+ import java .nio .file .StandardOpenOption ;
19+ import java .util .concurrent .Future ;
1320
1421public class WindowsConnection extends Connection {
1522
1623 private static final Logger log = LoggerFactory .getLogger (WindowsConnection .class );
1724
18- private RandomAccessFile pipe ;
25+ private final int BUFFER_SIZE = 8192 ;
26+ private AsynchronousFileChannel pipe ;
27+ private final ByteBuffer buffer = ByteBuffer .allocate (BUFFER_SIZE );
28+ private final Charset charset = StandardCharsets .UTF_8 ;
29+ private final CharsetDecoder charsetDecoder = charset .newDecoder ();
30+ private final CharBuffer charBuffer = CharBuffer .allocate (BUFFER_SIZE );
1931
2032 /**
2133 * Connect to the KeePassXC proxy via a Windows named pipe the proxy has opened.
@@ -25,9 +37,9 @@ public class WindowsConnection extends Connection {
2537 @ Override
2638 public void connect () throws IOException {
2739 try {
28- pipe = new RandomAccessFile ("\\ \\ .\\ pipe\\ " + PROXY_NAME + "_" + System .getenv ("USERNAME" ),
29- "rw" );
30- } catch (FileNotFoundException e ) {
40+ Path path = Paths . get ("\\ \\ .\\ pipe\\ " + PROXY_NAME + "_" + System .getenv ("USERNAME" ));
41+ pipe = AsynchronousFileChannel . open ( path , StandardOpenOption . READ , StandardOpenOption . WRITE );
42+ } catch (IOException e ) {
3143 log .error ("Cannot connect to proxy. Is KeepassXC started?" );
3244 throw e ;
3345 }
@@ -42,25 +54,27 @@ public void connect() throws IOException {
4254 @ Override
4355 protected void sendCleartextMessage (String msg ) throws IOException {
4456 log .trace ("Sending message: {}" , msg );
45- pipe .write (msg .getBytes (StandardCharsets .UTF_8 ));
57+ pipe .write (ByteBuffer . wrap ( msg .getBytes (StandardCharsets .UTF_8 )), 0 );
4658 }
4759
4860 @ Override
4961 protected JSONObject getCleartextResponse () {
50- int c ;
51- var raw = "" ;
52- do {
53- try {
54- c = pipe .read ();
55- raw += (char ) c ;
56- } catch (IOException e ) {
57- log .error (e .toString (), e .getCause ());
58- return new JSONObject ();
59- }
60- } while (c != 125 ); // end of transmission
62+ var raw = new StringBuilder ();
63+ long position = 0 ;
64+ Future <Integer > operation = pipe .read (buffer , position );
65+ while (!operation .isDone ());
66+ buffer .flip ();
67+ charsetDecoder .decode (buffer , charBuffer , true );
68+ charBuffer .flip ();
69+ raw .append (charBuffer );
70+ buffer .compact ();
71+ charBuffer .clear ();
6172 log .trace ("Reading message: {}" , raw );
6273 try {
63- return new JSONObject (raw );
74+ var s = raw .toString ();
75+ // Test, if we received more than one message with the last read
76+ if (s .length () - s .replace ("}" , "" ).length () > 1 ) throw new JSONException ("" );
77+ return new JSONObject (raw .toString ());
6478 } catch (JSONException e ) {
6579 log .error ("Message corrupted. Received: {}" , raw );
6680 return new JSONObject ();
0 commit comments