JSch shell returns into StringArray - java

I am trying to relearn Java after 10 years of not touching it. I want to create a library using JSch from some other apps I am looking to write. I have the connections ironed out but I am using stdin and stdout right now.
I am looking to have a method that accepts a single command in a String and returns an ArrayList with the results.
Any assistance would be great!
//This vars are in the class.
private JSch _jsch;
private Session _session;
private Channel _channel;
Here is my connection method
public boolean Connect () throws JSchException
{
try {
_jsch = new JSch();
_session = _jsch.getSession(_user, _hostname, _port);
_session.setPassword(_password);
_session.setConfig("StrictHostKeyChecking", "no");
_channel = _session.openChannel("shell");
//((ChannelShell)_channel).setPtyType("vt100");
_channel.setInputStream(bais);
_channel.setOutputStream(baos);
_channel.connect(3000);
}//try to connect
catch (JSchException ex)
{
throw ex;
}
return true;
}
The goal is once I open the connection I can send this method a command and return the results in an array. Act based on the results and send more commands. I don't want to close the connection each time as they will build on the commands that come before it. I am not sure how to work with the Inputs and Output Streams enough to get the results I am looking for. If you can assist with filling out the following method, I would be grateful.
public List<String> ExecuteCommand (String command) {
//run command to existing connection
//Get returned lines to Array List and return the list
}
Thanks

Here's an example of running a local process and creating a return ArrayList filled line by line with the output from the process. Whilst it's not exactly what you want, it should give you an idea.
public List<String> ExecuteCommand (String command) {
Runtime r = Runtime.getRuntime();
Process p = r.exec(command);
p.waitFor();
BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = "";
ArrayList<String> output = new ArrayList<String>();
while ((line = b.readLine()) != null) {
output.add(line);
}
return output;
}

I've created an open source project (click to see) to implements remote file system. Here is the most important code snippet, which also supports sudo. In the example, I redirect error output to standard output. If you do not want the error output, you can remove it. In the example, I use StringWriter instead of List<String>. I encourage you to use it.
/**
* Executes commands at target host.
* #throws IOException Failed to capture a return code
*/
public int exec(boolean sudo, String command, StringWriter output) throws IOException {
ChannelExec channel = null;
try {
channel = (ChannelExec) session.openChannel("exec");
sudo = sudo && !username.equals("root");
if (sudo) {
command = "sudo -S -p '' " + command;
channel.setPty(true);
}
channel.setCommand(command);
InputStream stdout = channel.getInputStream(); // The stream will be recycled automatically
InputStream stderr = channel.getErrStream(); // The stream will be recycled automatically
channel.connect();
boolean passwordEntered = false;
if (sudo && !StringUtils.isEmpty(password)) {
OutputStream stdin = channel.getOutputStream();
stdin.write(password.getBytes());
stdin.write("\n".getBytes());
IOUtils.closeQuietly(stdin);
passwordEntered = true;
}
String contents = readFully(stdout);
if (passwordEntered) {
contents = contents.substring(password.length());
}
output.write(contents.trim());
contents = readFully(stderr);
int retval = channel.getExitStatus();
if (retval != 0) {
output.append(contents.trim());
}
return retval;
}
catch (JSchException ex) {
throw new IOException(ex);
}
finally {
output.flush();
if (channel != null) {
channel.disconnect();
}
}
}
private static String readFully(InputStream input) throws IOException {
StringBuilder output = new StringBuilder();
int bytesRead = input.read();
while (bytesRead != -1) {
output.append((char) bytesRead);
bytesRead = input.read();
}
return output.toString();
}

Here is the solution I have currently. It could use some stream lining and clean up but it is getting me what I am looking for.
I didn't want to mark this as an answer but I haven't posted to this site before so excuse me if I did that wrong. Here is the new connect method
public boolean Connect () throws JSchException
{
try {
_jsch = new JSch();
_session = _jsch.getSession(_user, _hostname, _port);
_session.setPassword(_password);
_session.setConfig("StrictHostKeyChecking", "no");
_session.connect();
_channel = _session.openChannel("shell");
_channel.setInputStream(null);
_isInput = _channel.getInputStream();
_isOutput = _channel.getOutputStream();
_reader = new BufferedReader (new InputStreamReader(_isInput));
_writer = new BufferedWriter (new OutputStreamWriter (_isOutput));
_channel.connect(3000);
LastLogin = _reader.readLine(); //get last login message
}//try to connect
catch (JSchException ex)
{
throw ex;
}
catch (UnsupportedEncodingException uee)
{
return false;
}
catch (IOException ioe)
{
return false;
}
return true;
}
Here is my execute method. I know there is a better way to get from the char[] to an ArrayList but I haven't ironed that out just yet.
public List<String> ExecuteCommand (String command)
{
List<String> returns = new ArrayList();
try {
_writer.write(command);
if ( !command.endsWith("\n") )
_writer.write("\n");
_writer.flush();
Thread.sleep(2000); //allow time to exec
int c;
StringBuilder response= new StringBuilder();
while (_reader.ready()) {
c = _reader.read();
if (c == -1)
break;
response.append( (char)c ) ;
}//while
String[] lines = response.toString().split("\n");
for (String line: lines)
{
if (line.trim().length()!=0)
returns.add(line);
}
}//try
catch (IOException e)
{
//handle this later
}//catch
catch (InterruptedException ie)
{
//handle this later
}
return returns;
}//ExecuteCommand
I know it isn't great but it works.

Related

wkhtmltopdf called from java getting hanged

We are the using the following code to generate PDFs using wkhtmltopdf
public class SystemUtils{
public String executeCommand(String... command) {
Process process = null;
try {
// Using redirectErrorStream as true. Otherwise we have to read both process.getInputStream() and
// process.getErrorStream() in order to not exhaust the stream buffer.
process = new ProcessBuilder(command).redirectErrorStream(true).start();
process.waitFor();
StringBuilder outputBuilder = new StringBuilder();
try(BufferedReader stdError = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = stdError.readLine()) != null) {
outputBuilder.append(line).append(StringConstants.CARRIAGE_RETURN);
}
}
return outputBuilder.toString();
} catch (IOException | InterruptedException e) {
String exceptionMsg = "Error while executing command '"+command+"' : ";
LOGGER.error(exceptionMsg, e);
throw new AppException(exceptionMsg, e);
} finally {
if(process != null){
process.destroy();
}
}
}
public static void main(String[] args){
SystemUtils systemUtils = new SystemUtils();
String[] array = {"wkhtmltopdf", "/home/pgullapalli/Desktop/testsimilar1.html", "/home/pgullapalli/Desktop/test.pdf"};
systemUtils.executeCommand(array);
}
}
This works absolutely fine for smaller size files. But when we try to process a larger file, it is indefinitely waiting without any response. I am not sure what is going wrong? Can someone please suggest?
I moved process.waitFor() before the return statement and it started working. This probably could be happening as the output buffer has filled and we are not reading from it. After moving the process.waitFor after the stream reading, things are working fine.

Reading output from command line

I'm really stuck here, I've read number of articles and answers on stackoverflow, but nothing solved my problem.
I've got the method which runs Selenium Server Hub from cmd.exe using batch file:
public static boolean startGrid() throws IOException {
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "start", START_GRID_BAT_PATH);
builder.redirectErrorStream(true);
Process process = builder.start();
String out = getCmdOutput(process);
return out.contains("Selenium Grid hub is up and running");
}
The server is started successfully and is running in open cmd.
To make sure that server is up I use the following method to get the output from the cmd:
protected static String getCmdOutput(Process proc) throws java.io.IOException {
String res = "";
BufferedReader stdInput = new BufferedReader(new
InputStreamReader(proc.getInputStream()));
String s = "";
while ((s = stdInput.readLine()) != null) {
res += s;
}
return res;
}
And here is where the problem starts - method hangs at the the line s = stdInput.readLine()) != null
It seems that it can't read any line from the cmd, although I can see that there is number of lines in the output produced by running server.
Any ideas what is wrong?
Maybe the output produced by the server doesn't contain any \r or \n characters but is simply line-wrapped.
Anyhow, you shouldn't rely on the line feed characters when reading the output.
The following example shows how to read binary data from the InputStream of the process non-blocking with java.nio, convert the bytes to chars and write the result to a StringWriter - which is preferrable to using string concatenation.
protected static String getCmdOutput(Process proc, Consumer<String> consumer)
final InputStream source = proc.getInputStream();
final StringWriter sink = new StringWriter();
final ByteBuffer buf = ByteBuffer.allocate(1024);
final CharBuffer chars = CharBuffer.allocate(1024);
final CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
try(final ReadableByteChannel from = Channels.newChannel(source)) {
while (from.read(buf) != -1) {
buf.flip();
decoder.decode(buf, chars, false);
chars.flip();
sink.write(chars.array(), chars.position(), chars.remaining());
buf.compact();
chars.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
return sink.toString();
}
Edit:
As you are starting a process that is continuously producing output, the loop won't finish as long as the process is running. So to continue your parent process, you have to start a thread that is capturing and processing the output of the process continuously
For example
Consumer<String> consumer = ...;
Thread t = new Thread(() -> {
final InputStream source = proc.getInputStream();
final StringWriter sink = new StringWriter();
final ByteBuffer buf = ByteBuffer.allocate(1024);
final CharBuffer chars = CharBuffer.allocate(1024);
final CharsetDecoder decoder = Charset.defaultCharset().newDecoder();
try(final ReadableByteChannel from = Channels.newChannel(source)) {
while (from.read(buf) != -1) {
buf.flip();
decoder.decode(buf, chars, false);
chars.flip();
sink.write(chars.array(), chars.position(), chars.remaining());
forward(sink, consumer); //forward the captured content to a consumer
buf.compact();
chars.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
});
t.start();
private void forward(StringWriter sink, Consumer<String> consumer) {
StringBuffer buf = sink.getBuffer();
int pos = buf.lastIndexOf("\n");
//you may use other options for triggering the process here,
//i.e. on every invocation, on fixed length, etc
if(pos != -1){
consumer.accept(buf.substring(0, pos + 1));
buf.delete(0, pos + 1);
}
//or to send the entire buffer
/*
consumer.accept(sink.toString());
sink.getBuffer().delete(0, sink.getBuffer().length());
*/
}
Depending on your use case, you may not necessarily need a separate thread. It might be ok to process the child-process' output in the main thread and do what you want with the output in the consumer.
It doesn't hang, it just blocks waiting for a line to be read. And after the line has been read, it waits for the next. And so on.
Getting the output stream of a child process should be made in a separate thread, because the child process could in fact hang, than your main thread will hang, too.
An example:
given the instance methods
private static final long WAITTIME_FOR_CHILD = Duration.ofMinutes(5).toNanos();
private static final String START_SEQUENCE = "whatever";
private final Lock lock = new ReentrantLock();
private final Condition waitForStart = lock.newCondition();
private boolean started;
the code that starts the child process
// prepare child process
lock.lock();
try {
Process process = processBuilder.start();
// both standard and error output streams get redirected
pipe(process.getInputStream(), System.out, START_SEQUENCE);
pipe(process.getErrorStream(), System.err, START_SEQUENCE);
// loop because of 'spurious wakeups' - should happen only on Linux,
// but better take care of it
// wait until WAITTIME_FOR_CHILD (default 5 minutes, see above)
long waitTime = WAITTIME_FOR_CHILD;
while (!started) {
// we wait hier until the child process starts or timeout happens
// value <= 0 means timeout
waitTime = waitForStart.awaitNanos(waitTime);
if (waitTime <= 0) {
process.destroyForcibly();
throw new IOException("Prozess xxx couldn't be started");
}
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException("Error during start of xxx", e);
} finally {
lock.unlock();
}
private void getCmdOutput(InputStream in, PrintStream out, final String startSeq) {
startDaemon(() -> {
try (Scanner sc = new Scanner(in)) {
while (sc.hasNextLine()) {
String line = sc.nextLine();
// check your know output sequence
if (line.contains(startSeq)) {
lock.lock();
try {
if (!started) {
started = true;
// waiting for process start finished
waitForStart.signal();
}
} finally {
lock.unlock();
}
}
out.println(line);
}
}
});
}
private void startDaemon(Runnable task) {
Thread thread = new Thread(task);
thread.setDaemon(true);
thread.start();
}
Try replacing while condition like this:
while ((s = stdInput.readLine()) != null && !s.equals("")) {
ProcessBuilder pb =
new ProcessBuilder("myCommand", "myArg1", "myArg2");
Map<String, String> env = pb.environment();
env.put("VAR1", "myValue");
env.remove("OTHERVAR");
env.put("VAR2", env.get("VAR1") + "suffix");
pb.directory(new File("myDir"));
File log = new File("log");
pb.redirectErrorStream(true);
pb.redirectOutput(Redirect.appendTo(log));
Process p = pb.start();
assert pb.redirectInput() == Redirect.PIPE;
assert pb.redirectOutput().file() == log;
assert p.getInputStream().read() == -1;
You can redirect output to a file as oracle documentation offers in basic example:
https://docs.oracle.com/javase/7/docs/api/java/lang/ProcessBuilder.html

Send a string command to a socket

I am not very familiar with telnet so I would appreciate the help from any willing.
I have smart plugs which can be switch on or off through a telnet interface.
I always use telnet via command prompt to connect to the server Digi X4 connect port (via >telnet ). If I want to switch the socket on/off, I have to now type: "12 set pow=on/off" and press enter.
I would like to implement this through java using the telnet client. I am now able to connect to the port (thanks to the answers posted on this platform), but to send the command to switch devices on/off is proving difficult for me. I still have to type "12 set pow=on/off" and press enter. I would like Java to send this command.
Below is my java code. I would appreciate your assistance. Bab
public class TelnetConnection {
static TelnetClient tc = null;
public static void main(String[] a) throws Exception
{
String[] args = {"122.1222.181.45","8085"};
System.out.println("arg value: "+args);
if(args.length < 1)
{
System.err.println("Usage: Error <remote-ip> [<remote-port>]");
System.exit(1);
}
String remoteip = args[0];
int remoteport;
if (args.length > 1)
{
remoteport = (new Integer(args[1])).intValue();
}
else
{
remoteport = 7000;
}
tc = new TelnetClient();
while (true)
{
boolean end_loop = false;
try
{
tc.connect(remoteip, remoteport);
Thread reader = new Thread (new TelnetClientExample());
tc.registerNotifHandler(new TelnetClientExample());
System.out.println("TelnetClientExample");
reader.start();
OutputStream outstr = tc.getOutputStream();
PrintWriter out = new PrintWriter(outstr);
String buff = "11 set pow=on";
//int ret_read = 0;
do
{
try
{
out.print(buff);
outstr.flush();
}
catch (IOException e)
{
System.err.println("Error");
end_loop = true;
}
}
while((true) && (end_loop == false));
try
{
tc.disconnect();
}
catch (IOException e)
{
System.err.println("Error");
}
}
catch (IOException e)
{
System.err.println("Exception while connecting:" + e.getMessage());
System.exit(1);
}
}
}
}
Try tring buff = "11 set pow=on\n"; the server may need the newline to detect end-of-command.
By the way, the loop that infinitely sends that to the server looks worrisome.
You need to send a line terminator corresponding to 'and press Enter'.
The line terminator in Telnet is defined as \r\n.

How do I execute a sequence of related console commands?

I'm currently working on a project where a client receives shell/console commands from a server, and must execute them.
How do I get Java to run these commands from within either a shell or a command prompt? I'm hoping to be able to disregard the platform type - and not have to specify shell or command prompt - but if I can't, then that's okay.
I must be able to send a sequence of related commands, not just one command. This means that the shell/prompt cannot exit or close between commands.
My current code, as follows, allows for the execution of a sequence of programs, but these commands must somehow be piped into a shell/command prompt, from which the output must be read.
ArrayList<String> comDat = new ArrayList<>();
while(true) {
String input = con.recv();
System.out.println("> " + input);
if(!input.equals("EOF")) comDat.add(input); else {
String[] s = new String[comDat.size()];
for(int i = 0; i < comDat.size(); i++) s[i] = comDat.get(i);
System.out.println("---Command sequence executing---");
Process p = Runtime.getRuntime().exec(s);
p.waitFor();
System.out.println("---ErrorStream output---"); String line = "";
BufferedReader errStream = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while((line = errStream.readLine()) != null) System.out.println("< " + line);
System.out.println("\n---OutputStream output---"); line = "";
BufferedReader outStream = new BufferedReader(new InputStreamReader(p.getInputStream()));
while((line = errStream.readLine()) != null) System.out.println("< " + line);
}
Thread.sleep(200);
}
Thanks for the help!
The basic premise revoles around the fact the dir isn't an external command but is function of cmd.
I would avoid BufferedReaders when reading the output of a process as not all processes use new lines when sending output (such as progress indicators), instead you should read char for char (IMHO).
You should us ProcessBuilder instead of Runtime#exec. It provides better management and allows you to redirect the error stream into the input stream, making it easier to read the input.
import java.io.IOException;
import java.io.InputStream;
public class TestProcessBuilder {
public static void main(String[] args) {
try {
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "dir");
pb.redirectError();
Process p = pb.start();
InputStreamConsumer isc = new InputStreamConsumer(p.getInputStream());
isc.start();
int exitCode = p.waitFor();
isc.join();
System.out.println("Process terminated with " + exitCode);
} catch (IOException | InterruptedException exp) {
exp.printStackTrace();
}
}
public static class InputStreamConsumer extends Thread {
private InputStream is;
public InputStreamConsumer(InputStream is) {
this.is = is;
}
#Override
public void run() {
try {
int value = -1;
while ((value = is.read()) != -1) {
System.out.print((char)value);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
}
}

java.lang.Exception: Error while transmitting data how to solve this error

I am trying to send a file from server side to client side upon request. The file that is sent is encrypted and the client shpuld decrypt it. the encryption process works fine but while decrypting i need to have the DerIOBuffer objetc which I have using serializing. what should i do..please help
server:
import java.net.*;
import java.io.*;
import java.math.BigInteger;
import com.dragongate_technologies.borZoi.*;
public class FileServer {
static final int LISTENING_PORT = 3210;
public static void main(String[] args) {
File directory; // The directory from which the gets the files that it serves.
ServerSocket listener; // Listens for connection requests.
Socket connection; // A socket for communicating with a client.
/* Check that there is a command-line argument.
If not, print a usage message and end. */
if (args.length == 0) {
System.out.println("Usage: java FileServer <directory>");
return;
}
/* Get the directory name from the command line, and make
it into a file object. Check that the file exists and
is in fact a directory. */
directory = new File(args[0]);
if ( ! directory.exists() ) {
System.out.println("Specified directory does not exist.");
return;
}
if (! directory.isDirectory() ) {
System.out.println("The specified file is not a directory.");
return;
}
/* Listen for connection requests from clients. For
each connection, create a separate Thread of type
ConnectionHandler to process it. The ConnectionHandler
class is defined below. The server runs until the
program is terminated, for example by a CONTROL-C. */
try {
listener = new ServerSocket(LISTENING_PORT);
System.out.println("Listening on port " + LISTENING_PORT);
while (true) {
connection = listener.accept();
new ConnectionHandler(directory,connection);
}
}
catch (Exception e) {
System.out.println("Server shut down unexpectedly.");
System.out.println("Error: " + e);
return;
}
} // end main()
static class ConnectionHandler extends Thread {
// An object of this class is a thread that will
// process the connection with one client. The
// thread starts itself in the constructor.
File directory; // The directory from which files are served
Socket connection; // A connection to the client.
TextReader incoming; // For reading data from the client.
PrintWriter outgoing; // For transmitting data to the client.
ConnectionHandler(File dir, Socket conn) {
// Constructor. Record the connection and
// the directory and start the thread running.
directory = dir;
connection = conn;
start();
}
void sendIndex() throws Exception {
// This is called by the run() method in response
// to an "index" command. Send the list of files
// in the directory.
String[] fileList = directory.list();
for (int i = 0; i < fileList.length; i++)
outgoing.println(fileList[i]);
outgoing.flush();
outgoing.close();
if (outgoing.checkError())
throw new Exception("Error while transmitting data.");
}
void ecies_ex(String fileName) throws Exception {
// This function encrypts the file that has been requested
// by the client.
String at1,dc1,der1;
OutputStream os = connection.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(os);
ECDomainParameters dp = ECDomainParameters.NIST_B_163();
ECPrivKey skA = new ECPrivKey(dp, BigInteger.valueOf(123));
ECPubKey pkA = new ECPubKey(skA);
ECPrivKey skB = new ECPrivKey(dp, BigInteger.valueOf(230));
ECPubKey pkB = new ECPubKey(skB);
File file = new File(directory,fileName);
if ( (! file.exists()) || file.isDirectory()) {
// (Note: Don't try to send a directory, which
// shouldn't be there anyway.)
outgoing.println("error");
}
else {
outgoing.println("ok");
String pt1 = new String();
BufferedReader br = null;
try {
String sCurrentLine;
br = new BufferedReader(new FileReader(fileName));
while ((sCurrentLine = br.readLine()) != null) {
pt1=pt1+"\n"+sCurrentLine;
}
} catch (IOException e) {
e.printStackTrace();
}
ECIES crypt = new ECIES(skA, pkB, pt1.getBytes()); // encrypt the data
try {
DerIOBuffer der = new DerIOBuffer(crypt);
oos.writeObject(der);
ECIES decrypt = der.toECIES();
dc1=decrypt.toString2(); //cipher text
//at1=decrypt.toString3(); //authentication tag
FileWriter fstream = new FileWriter("encrypted.txt");
BufferedWriter out = new BufferedWriter(fstream);
out.write(dc1);
//Close the output stream
out.close();
} catch (Exception e) {
System.out.println(e.toString());
}
TextReader fileIn = new TextReader( new FileReader("encrypted.txt") );
while (fileIn.peek() != '\0') {
// Read and send lines from the file until
// an end-of-file is encountered.
String line = fileIn.getln();
outgoing.println(line);
}
}
outgoing.flush();
// oos.close();
// os.close();
outgoing.close();
if (outgoing.checkError())
throw new Exception("Error while transmitting data.");
}
public void run() {
// This is the method that is executed by the thread.
// It creates streams for communicating with the client,
// reads a command from the client, and carries out that
// command. The connection is logged to standard output.
// An output beginning with ERROR indicates that a network
// error occurred. A line beginning with OK means that
// there was no network error, but does not imply that the
// command from the client was a legal command.
String command = "Command not read";
try {
incoming = new TextReader( connection.getInputStream() );
outgoing = new PrintWriter( connection.getOutputStream() );
command = incoming.getln();
if (command.equals("index")) {
sendIndex();
}
else if (command.startsWith("get")){
String fileName = command.substring(3).trim();
ecies_ex(fileName);
//sendFile(fileName);
}
else {
outgoing.println("unknown command");
outgoing.flush();
}
System.out.println("OK " + connection.getInetAddress()
+ " " + command);
}
catch (Exception e) {
System.out.println("ERROR " + connection.getInetAddress()
+ " " + command + " " + e);
}
finally {
try {
connection.close();
}
catch (IOException e) {
}
}
}
} // end nested class ConnectionHandler
} //end class FileServer
client :
import java.net.*;
import java.io.*;
import java.math.BigInteger;
import com.dragongate_technologies.borZoi.*;
public class FileClient {
static final int LISTENING_PORT = 3210;
public static void main(String[] args) {
String computer; // Name or IP address of server.
Socket connection; // A socket for communicating with that computer.
PrintWriter outgoing; // Stream for sending a command to the server.
TextReader incoming; // Stream for reading data from the connection.
String command; // Command to send to the server.
String pt3;
ECDomainParameters dp = ECDomainParameters.NIST_B_163();
ECPrivKey skB = new ECPrivKey(dp, BigInteger.valueOf(230));
//ECPrivKey skB = new ECPrivKey (dp);
ECPubKey pkB = new ECPubKey(skB);
/* Check that the number of command-line arguments is legal.
If not, print a usage message and end. */
if (args.length == 0 || args.length > 3) {
System.out.println("Usage: java FileClient <server>");
System.out.println(" or java FileClient <server> <file>");
System.out.println(" or java FileClient <server> <file> <local-file>");
return;
}
/* Get the server name and the message to send to the server. */
computer = args[0];
if (args.length == 1)
command = "index";
else
command = "get " + args[1];
/* Make the connection and open streams for communication.
Send the command to the server. If something fails
during this process, print an error message and end. */
try {
connection = new Socket( computer, LISTENING_PORT );
incoming = new TextReader( connection.getInputStream() );
outgoing = new PrintWriter( connection.getOutputStream() );
outgoing.println(command);
outgoing.flush();
}
catch (Exception e) {
System.out.println(
"Can't make connection to server at \"" + args[0] + "\".");
System.out.println("Error: " + e);
return;
}
/* Read and process the server's response to the command. */
try {
if (args.length == 1) {
// The command was "index". Read and display lines
// from the server until the end-of-stream is reached.
System.out.println("File list from server:");
while (incoming.eof() == false) {
String line = incoming.getln();
System.out.println(" " + line);
}
}
else {
// The command was "get <file-name>". Read the server's
// response message. If the message is "ok", get the file.
String message = incoming.getln();
if (! message.equals("ok")) {
System.out.println("File not found on server.");
return;
}
PrintWriter fileOut; // For writing the received data to a file.
if (args.length == 3) {
// Use the third parameter as a file name.
fileOut = new PrintWriter( new FileWriter(args[2]) );
}
else {
// Use the second parameter as a file name,
// but don't replace an existing file.
File file = new File(args[1]);
if (file.exists()) {
System.out.println("A file with that name already exists.");
System.out.println("To replace it, use the three-argument");
System.out.println("version of the command.");
return;
}
fileOut = new PrintWriter( new FileWriter(args[1]) );
}
while (incoming.peek() != '\0') {
// Copy lines from incoming to the file until
// the end of the incoming stream is encountered.
String line = incoming.getln();
fileOut.println(line);
}
InputStream is = connection.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
DerIOBuffer der = (DerIOBuffer)ois.readObject();
ECIES decrypt = der.toECIES();
byte[] pt2 = decrypt.decrypt(skB); // decrypt the data
pt3=new String(pt2);
if (fileOut.checkError()) {
System.out.println("Some error occurred while writing the file.");
System.out.println("Output file might be empty or incomplete.");
}
}
}
catch (Exception e) {
System.out.println("Sorry, an error occurred while reading data from the server.");
System.out.println("Error: " + e);
}
} // end main()
} //end class FileClient
If you care about errors, you should not use PrintWriter. Why? Because if an error does occur on output via a PrintWriter, you have no way to find out what it was. This is what makes it difficult to figure out what the real problem is in this case. I recommend that you fix this so that you can get to the real cause of the problem.
The real problem could be related to to the following issues:
If the stuff you are trying to write could be binary, you shouldn't use PrintWriter ... or Readers / Writers at all.
You seem to be using Object serialization unnecessarily ... and on a class that looks like it may not be serializable.
Based on the difficulty I had in finding documentation for the "borZoi" library ... and other things ... I think you may have made a poor choice of library for doing crypto work.

Categories