Is BufferedReader ignoring the first line? - java

I am currently writing a service that should take cleartext commands and then return something according to thoose commands, which is also in cleartext.
I have this odd problem with BufferedReader, or, it might be telnet that is odd, for some reason the BufferedReader reads the first command, however that command is ignored no matter what i do, which i can get around by sending the first command twice, but that is just stretching it a bit, in my oppinion.
The code below is in a run() method.
Then i set out as a PrintWriter and in as a BufferedReader.
The runs variable is by default true.
out = new PrintWriter(handle.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(handle.getInputStream()));
while (runs) {
String msg;
msg = in.readLine();
String[] command;
command = msg.split(" ", 3);
/* do something with the command */
}
So my question is if BufferedReader is ignoring the first line or is it telnet that is not coorperating with me?
If it is something else, then please enlighten me.
EDIT
I got this debug message:
Debug: ���� ����'������/nick halmark
so i suppose that it is about all the questionmarks.

I am actually using the latest Putty since i am developing on a windows box... and as far as i recall... then it does not exist by default
If you are using PuTTY, you need to choose the "Raw" Connection Type.
Microsoft telnet servers like to have some content/protocol negotiation at the beginning, so PuTTY will do this by default as per the RFC 854 spec. That's the garbage that you are reading.

Related

Is BufferedReader blocking the standard console input?

I'm writing a simple chat application in Java and everything works fine except the following strange bug:
When you type something in the terminal, for example you press "a" and the console writes "a", then you press "i", it writes "i", "r" -> "r"... and you get the word (e.g. "air") written in console.
In my case I press "e", the console writes "(nothing)", "i" ->"(noting)", "r" -> (nothing) and only after I pressed "enter" console suddenly displays the whole word "air", works in the same way with more than one words. In reality the user can write whatever he/she wants but the typed down text will appear only after Enter has been pressed.
In my program I use a BufferedReader object to read from the socket:
try( ....some socket stuff....
PrintWriter out = new PrintWriter(clientSocket.getOutputStream(),true);//out is the socket output
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); //in is the socket input
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in)); //that's the standard input, the one from keyboard
while(true){
if (stdIn.ready()){
userInput=stdIn.readLine();
out.println(userInput);
if(userInput.equals("Bye.")) break;
System.out.println("Me: "+userInput);
}
if(in.ready()){
if((serverInput= in.readLine())!=null){
System.out.println("Stranger: "+serverInput);
}
}
In my opinion that methods - ready and readline() - probably bug the console. It seems a little bit weird for me but it's Java and I'm not very skilled.
Apart from that the chat works like charm - it sends and receives properly. The read-receive-input script is exactly the same and on the client side. When you're typing a message nothing will show up in console but it actually is there and on Enter it displays, it's not a delay, it's influenced by Enter.
This is not possible to do in java.
At least not with platform independent way.
What you are trying to do is, read character by character, without pressing enter key.
But the console on os itself by default is in buffered line mode.
So, only solution is to put your console on raw mode (line editing bypassed and no enter key required), making it platform dependent.
Edit : Your description says character reading, and your code is doing something else by the way.

Java encoding from OS X to Windows

I have made a primitive multi-client chat with swing GUI. Everything works fine as long as both people write from the same OS. If one of them writes from Windows and the other from OS X, the encoding of some special characters goes nuts. ( I am from CZE, we use characters as š,ě,č,ř,ž...). I have searched for a long time but didn't find anything that would help.
I have input and output defined as:
in = new BufferedReader(new InputStreamReader(soc.getInputStream()));
out = new PrintWriter(new OutputStreamWriter(soc.getOutputStream()));
where soc is the socket used for connecting to the server side.
The sending process is as simple as:
out.println(message);
where message is a String, which I got from JTextArea by calling method .getText()
I know why this problem occurs, but I was unable to find any reasonable solution.
Any help will be appreciated.
Thanks
When reading character data from Input/OutputStreams, it's a good practice to always specify the character encoding. Otherwise the platform default encoding is used (which might not be the same on all systems).
in = new BufferedReader(new InputStreamReader(soc.getInputStream(), StandardCharsets.UTF_8));
out = new PrintWriter(new OutputStreamWriter(soc.getOutputStream(), StandardCharsets.UTF_8));

How to pass argument to Java Process?

I have a Java application that creates and runs a process (x.exe). When process x is executed, it prompts the user to enter a password. How to pass this password to the user?
I tried to use the OutputStream of the process and wrote the password to the stream but still the process didn't run.
Runtime r=Runtime.getRuntime();
Process p=r.exec("x.exe");
p.getOutputStream()//.use to pass the arguments
You need to flush the stream, and also, it maybe expects a CR at the end of the password to simulate the ENTER key the user types at the end of the password. This works for me in Linux:
Runtime r = Runtime.getRuntime();
Process p = r.exec("myTestingExe");
p.getOutputStream().write("myPassword\n".getBytes()); // notice the `\n`
p.getOutputStream().flush();
Some caveats:
This works in Linux with '\n' at the end, maybe in Windows you would need \r instead (honestly I'm not sure of how Windows handles the "ENTER" key in the input)
I'm using "myPassword\n".getBytes() but a more complete value would be new String("myPassword".getBytes(), Charset.forName("MyCharsetName")); (where "MyCharsetName" is a supported encoding) if you are using an encoding like "UTF-8".
As already was pointed out you can consider to use an Expect-like library for interacting between your Java program and a spawn OS process. Basically, you would need to wait until the password prompt gets available in the process input stream and then write the password terminated by the end-of-line to the process output stream.
If you decide to go with a third party library approach I'd recommend you to give a try my own modern alternative to expect4j and others. It is called ExpectIt has no dependencies and is Apache licensed.
Here is a possible example with the use of the expect library:
Process process = Runtime.getRuntime().exec("...");
Expect expect = new ExpectBuilder()
.withInputs(process.getInputStream())
.withOutput(process.getOutputStream())
.withErrorOnTimeout(true)
.build();
expect.expect(contains("Password:"));
expect.sendLine("secret");
expect.close();
Note: the contains method is statically imported.
You can try library like expect4j to interact with the external process

Remove special characters while using "more" command from Java using JSCH?

I have a log file on a UNIX server which is dynamically changing.
I want to build an application to view that file on a Java GUI using Swings in multiple pages using SSH.
I am using JSCH Library to execute the "more" command for that log file. But in the output, some special characters like '[24;1H[K[7m' are printed. How to remove these special characters.
I am using the following code
session.setConfig("StrictHostKeyChecking", "no");
session.connect(30000);
Channel channel=session.openChannel("shell");
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect();
Thread.sleep(3000);
PrintStream ps = new PrintStream(channel.getOutputStream(), true);
ps.println("more " + fileName);
The output is :
[?7h[?1l(B=[24;1H[K************ Start Display Current Environment ************
[24;1H[K[7mSystemOut.log (0%)[m[24;1H[24;1H[KID: soacore.FP6123 BuildVrsn: null Desc: WebSphere Process Server 6.1.2.3
[24;1H[K[7mSystemOut.log (0%)[m
As you can see, some special characters are printed. How to remove those special characters?
I found out the answer. Just one line of code does the trick.
((ChannelShell) channel).setPtyType("dumb");
Adding the above line before the connect() removes all the non printable characters.
If you are developing a terminal emulator you can consider using a third-party library that could help you to manage the input data flow, specially dealing with the ANSI terminal control characters you are encountering. Tools like Expect are traditionally used to automate interacting between a program and text based terminal systems.
There are several exiting Expect for Java implementations you can use. Here I'd like to promote my own open source tool called ExpectIt. It supports filtering the input data to remove unwanted characters like terminal control that you may find very useful for your use case. It has other advantages stated on the project page.
Here is an example of using ExpectIt to iterate through the results of the more command. Note registering the removeColors filter which filters out the terminal characters.
session.setConfig(config);
session.connect();
Channel channel = session.openChannel("shell");
Expect expect = new ExpectBuilder()
.withOutput(channel.getOutputStream())
.withInputs(channel.getInputStream(), channel.getExtInputStream())
// register filters to remove ANSI color characters
.withInputFilters(removeColors())
.build();
try {
channel.connect();
// define the command line prompt
final String PROMPT = "...";
expect.expect(contains(PROMPT));
expect.sendLine("more <file>");
while (true) {
// expect either the end of the page or the end of the command
MultiResult result = expect.expect(anyOf(contains("--More--"), contains(PROMPT)));
// print the result
System.out.println(result.getBefore());
// exit if reach the end
if (result.getResults().get(1).isSuccessful()) {
break;
}
// scroll to the next page
expect.send(" ");
}
The code below works assuming that the corresponding methods are imported statically.

Client-side string encoding java

My team and I have this nasty problem with parsing a string received from our server. The server is pretty simple socket stuff done in qt here is the sendData function:
void sendData(QTcpSocket *client,QString response){
QString text = response.toUtf8();
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out << (quint32)0;
out << text;
out.device()->seek(0);
out << (quint32)(block.size() - sizeof(quint32));
try{
client->write(block);
}
catch(...){...
The client is in Java and is also pretty standard socket stuff, here is where we are at now after trying many many different ways of decoding the response from the server:
Socket s;
try {
s = new Socket(URL, 1987);
PrintWriter output = new PrintWriter(s.getOutputStream(), true);
InputStreamReader inp = new InputStreamReader(s.getInputStream(), Charset.forName("UTF-8"));
BufferedReader rd = new BufferedReader( inp );
String st;
while ((st = rd.readLine()) != null){
System.out.println(st);
}...
If a connection is made with the server it sends a string "Send Handshake" with the size of the string in bytes sent before it as seen in the first block of code. This notifies the client that it should send authentication to the server. As of now the string we get from the server looks like this:
������ ��������S��e��n��d�� ��H��a��n��d��s��h��a��k��e
We have used tools such as string encode/decode tool to try and assess how the string is encoded but it fails on every configuration.
We are out of ideas as to what encoding this is, if any, or how to fix it.
Any help would be much appreciated.
At a glance, the line where you convert the QString parameter to a Utf8 QByteArray and then back to a QString seems odd:
QString text = response.toUtf8();
When the QByteArray returned by toUtf8() is assigned to text, I think it is assumed that the QByteArray contains an Ascii (char*) buffer.
I'm pretty sure that QDataStream is intended to be used only within Qt. It provides a platform-independent way of serializing data that is then intended to be deserialized with another QDataStream somewhere else. As you noticed, it's including a lot of extra stuff besides your raw data, and that extra stuff is subject to change at the next Qt version. (This is why the documentation suggests including in your stream the version of QDataStream being used ... so it can use the correct deserialization logic.)
In other words, the extra stuff you are seeing is probably meta-data included by Qt and it is not guaranteed to be the same with the next Qt version. From the docs:
QDataStream's binary format has evolved since Qt 1.0, and is likely to
continue evolving to reflect changes done in Qt. When inputting or
outputting complex types, it's very important to make sure that the
same version of the stream (version()) is used for reading and
writing.
If you are going to another language, this isn't practical to use. If it is just text you are passing, use a well-known transport mechanism (JSON, XML, ASCII text, UTF-8, etc.) and bypass the QDataStream altogether.

Categories