P
past
Hi All,
I am using FTPSession.java which is based on the Internet Protocol
RFC959.
Through my client FTPSession.java, i am trying to download a file from
a ftp server which has a disclaimer on it.
This disclaimer is a multi line response.
The code of FTPSession, in its getResponse method is coded to handle
multi line responses, but when i connect to the server (it is a NT
server with Unix Style directory system) it gives me a null response
from the server.
It gives me a error in the method "getResponse", bad(short) response
from the server.
The server is not able to log me in as the response i get from the
server is null.
Is it a problem with the FTP server or do i need to handle it in the
FTPClient code.
The code of FTPSession which i am using is as below.
Can someboody please help me on this ASAP, as it is very urgent.
Thanks in advance
past
import java.io.*;
import java.net.*;
import java.util.*;
/**
* A java class used to transmit and receive files or text to a ftp
* server using File Transfer Protocol (FTP) by direct communications
* with the host machine using sockets on port 21.
*
* @param host - hostname running the ftp server to transmit the file
to.
* @param username - username used to log in to the ftp server.
* @param password - password used to log in to the ftp server.
* <p>
* <pre>
* FTPSession ftp = new FTPSession("computer.site.com", "anonymous",
"(e-mail address removed)");
* ftp.uploadFile("test.dat", (ftp.readFile("test.dat").toString());
* StringBuffer sb = ftp.downloadFile("test.dat");
* ftp.writeFile("new_"+ "test.dat",sb.toString());
* </pre>
*
*
*/
public class FTPSession
{
protected String username = null;
protected String password = null;
protected Socket sessionSocket = null;
protected Socket dataSocket = null;
protected String host = null;
protected String reply = null;
protected DataInputStream inStream = null;
protected DataOutputStream outStream = null;
protected PrintStream printStream = null;
protected boolean loggedIn = false;
protected static final String ASCII = "A";
protected static final String BINARY = "I";
protected static final int port = 21;
protected String transferType = BINARY;
/**
* A java class used to transmit and receive files or text to a ftp
* server using File Transfer Protocol (FTP) by direct communications
* with the host machine using sockets on port 21.
*
* @param host - hostname running the ftp server to transmit the file
to.
* @param username - username used to log in to the ftp server.
* @param password - password used to log in to the ftp server.
*/
public FTPSession(String _host, String _username, String _password)
{
this(_host,_username,_password,BINARY);
}
/**
* @param host - hostname running the ftp server to transmit the file
to.
* @param username - username used to log in to the ftp server.
* @param password - password used to log in to the ftp server.
* @param transferType - ASCII or BINARY transfer format (BINARY is
default).
*/
public FTPSession(String _host, String _username,
String _password, String _transferType)
{
host = _host;
username = _username;
password = _password;
if ( !(_transferType.equals(BINARY)) && !(_transferType.equals(ASCII))
)
throw new RuntimeException("Illegal parameter for transferType");
transferType = _transferType;
}
/**
* Used to download a file from the ftp server's machine.
* @param filename - filename to read from the ftp server.
* @return StringBuffer - contents of the file from the ftp server.
*/
public StringBuffer downloadFile(String filename) throws IOException
{
return(downloadFile("",filename));
}
/**
* Used to download a file from the ftp server's machine.
* @param directory - directory which the file resides on the ftp
server.
* @param filename - filename to read from the ftp server.
* @return StringBuffer - contents of the file from the ftp server.
*/
public StringBuffer downloadFile(String dir, String filename)
throws IOException
{
if (!loggedIn)
login();
// cd to the proper directory
changeDirectory(dir);
// set transfer mode to either BINARY or ASCII
reply = doCommand("TYPE " + transferType);
checkResponse(reply,'2');
// get socket which to transport data over.
dataSocket = getDataSocket();
InputStream inputStream = dataSocket.getInputStream();
// issue command to start transmission of file.
doCommand("RETR " + filename);
checkResponse(reply,'1');
// retrieve data from server.
String contents = retrieveData(inputStream);
// close connection for data transfer
dataSocket.close();
reply = getResponse();
checkResponse(reply,'2');
return (new StringBuffer(contents));
}
/**
* Used internally to read data from given input stream when
transferring
* data from the ftp server.
*
* @param inputStream - InputStream from socket used to transfer data.
* @return String - contents read from the InputStream given.
*/
protected String retrieveData(InputStream inputStream)
throws IOException
{
int c = 0;
char lineBuffer[] = new char[128];
char buffer[] = lineBuffer;
int room = buffer.length;
int offset = 0;
try {
loop: while (true)
{
// read characters into buffer
switch (c = inputStream.read())
{
case -1: break loop;
default: if (--room < 0)
{
buffer = new char[offset+128];
room = buffer.length - offset - 1;
System.arraycopy(lineBuffer,0,buffer,0,offset);
lineBuffer = buffer;
buffer[offset++] = (char) c;
break;
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
throw new IOException("Problems encountered while reading" +
" file from Server");
}
if ((c == -1) && (offset == 0))
return null;
return String.copyValueOf(buffer,0,offset);
}
/**
* Used to write a file to the client system. NOTE: this will not work
* if the client is running as an Applet.
*
* @param filename - filename to write the contents to on the client
system.
* @param contents - contents of the file to write to the client file
system.
*/
public void writeFile(String filename, String contents) throws
IOException
{
RandomAccessFile raf = new RandomAccessFile(filename,"rw");
raf.writeBytes(contents);
}
/**
* Used internally to create the socket connection to the host system
and
* setup the input, output and print streams.
*
* @param hostname - hostname of the host running the ftp server.
* @param port - port to connect to on the host system. (usually port
21)
*/
protected void connect(String host, int port) throws IOException
{
try {
// create connection to ftp server.
sessionSocket = new Socket(host, port);
} catch (Exception e) {
throw new IOException("Unable to connect to host:\n" + host);
}
inStream = new DataInputStream(sessionSocket.getInputStream());
outStream = new DataOutputStream(sessionSocket.getOutputStream());
printStream = new PrintStream(outStream);
// get reply to validate conection.
reply = getResponse();
checkResponse(reply,'2');
loggedIn = true;
}
/**
* Used internally to send the login sequence to the host system via
socket.
*
* @param username - username to login to the ftp server.
* @param password - password to login to the ftp server.
*/
public void login() throws IOException
{
login(username, password);
}
/**
* Used internally to send the login sequence to the host system via
socket.
*
* @param username - username to login to the ftp server.
* @param password - password to login to the ftp server.
*/
public void login(String username, String password) throws IOException
{
this.username = username;
this.password = password;
if (!loggedIn)
connect(host,port);
// send username to ftp server to login
reply = doCommand("USER " + username);
checkResponse(reply,'3');
// send password to ftp server to login
reply = doCommand("PASS " + password);
checkResponse(reply,'2');
}
/**
* Used internally to send the logout sequence to the host system via
socket.
*/
public void logout() throws IOException {
// no response comes from here
printStream.println("QUIT");
try {
printStream.flush();
printStream.close();
outStream.close();
inStream.close();
sessionSocket.close();
dataSocket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
loggedIn = false;
}
/**
* Used internally to validate a response by the host system.
*/
protected void checkResponse(String response, char digit) throws
IOException
{
if (response.charAt(0) != digit)
throw new IOException(response);
}
/**
* Used internally to validate a response by the host system.
*
* @param command - command sent to the ftp server on the host system.
* @return String - reply received from the host system.
*/
protected String doCommand(String command) throws IOException
{
//System.out.println("doCommand: " + command);
printStream.println(command);
return (getResponse());
}
/**
* Used internally to retrieve a response from the host system.
* Watches for responses that also include line continuation
characters.
*
* @param command - command sent to the ftp server on the host system.
* @return String - reply received from the host system.
*/
protected String getResponse() throws IOException
{
while (true)
{
reply = inStream.readLine();
if (reply == null)
throw new IOException("Bad (null) response from server");
if (reply.length() < 3)
throw new IOException("Bad (short) response from server");
// If there isn't a dash ('-') immediately after the number, then
// we've gotten the complete response. (The dash is the continu
// ation character)
if ((reply.length() == 3) || (reply.charAt(3) != '-'))
break;
}
//System.out.println("getResponse: " + reply);
return (reply);
}
/**
* Used internally to retrieve a data connection from the host system.
* host ip address and port number are parsed from the server's reply
to
* generate information for data connection.
*
* @return Socket - socket used to retrieve data from ftp server.
*/
protected Socket getDataSocket() throws IOException
{
int ctr = 0;
Socket dataSocket = null;
String[] parts = new String[6];
String part = null;
// Switch to PASV mode, capture server reply for socket information
reply = doCommand("PASV");
checkResponse(reply,'2');
// Our reply has data with the host ip and port for retrieving/sending
// data. It is in the form of:
// ### Text (###,###,###,###,##,###)[.]
// where,
// ### - reply code starts with '2' is good
// Text - general status message
// (..###..) - is the ip address and port which to connect
// to for data transfer. 1st four #'s are the ip
// address and the last two #'s are the port.
// [.] - possible period at the end of the line.
BreakString bs = new BreakString(reply,",");
Enumeration e = bs.result();
while (e.hasMoreElements())
{
part = (String) e.nextElement();
if (part.endsWith(")."))
{
parts[ctr++] = part.substring(0,part.length()-2);
}
else if (part.endsWith(")"))
{
parts[ctr++] = part.substring(0,part.length()-1);
}
else if (part.lastIndexOf("(") >= 0)
{
int begin = part.lastIndexOf("(");
parts[ctr++] = part.substring(begin+1,part.length());
}
else
{
parts[ctr++] = part;
}
}
// Piece together the IP address.
String ip = parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3];
// Determine port
int port = -1;
try {
int big = Integer.parseInt(parts[4]) << 8;
int small = Integer.parseInt(parts[5]);
port = big + small; // port number
} catch(NumberFormatException nfe) {
nfe.printStackTrace();
}
if ((ip != null) && (port != -1))
{
try {
dataSocket = new Socket(ip, port);
} catch (Exception se) {
se.printStackTrace();
throw new IOException("Unable to connect to address/port");
}
}
else
throw new IOException("Invalid IP address or port received");
return dataSocket;
}
/**
* Used to change directories on the server side for data retrieval or
* transmission.
*
* @param dir - directory to change to on the ftp server.
*/
public void changeDirectory(String dir) throws IOException
{
// some ftp servers do not understand CWD without a dirname
if ((dir != null) && !(dir.equals("")) && !(dir.equals(" ")))
{
reply = doCommand("CWD " + dir);
checkResponse(reply,'2');
}
}
/**
* Used to show current working directory on the server side.
*/
public String showDirectory() throws IOException
{
String path = null;
reply = doCommand("PWD");
checkResponse(reply,'2');
try {
// The message is in the format of:
// ### "directory information" response information
BreakString bs = new BreakString(reply, "\"");
Enumeration e = bs.result();
e.nextElement(); // throw away first part
path = (String) e.nextElement(); // dir info
} catch (Exception e) {
throw new IOException("Badly formed response from server: \n" +
reply);
}
return path;
}
public void finalize() { try { logout(); } catch (Exception ignore) {}
}
/**
* Main entry point to test the operation of the ftp server.
*
* @param server - host server to transfer file to.
* @param username - username to login to the ftp server.
* @param password - password to login to the ftp server.
* @param filename - name of file to transfer to the server
* and back to client's system.
*/
public static void main(String[] args)
{
String usage = "USAGE: FTPSession server username passwd filename";
if (args.length < 4)
{
System.out.println("\n" + usage + "\n\n");
System.exit(0);
}
try {
FTPSession ftp = new FTPSession(args[0], args[1], args[2]);
// retieve list of files on server
String path = ftp.showDirectory();
// change directories on server
ftp.changeDirectory("..");
// change directories on server
ftp.changeDirectory(path);
// download file
System.out.println("Downloading File: new_" + args[3] + " .......");
StringBuffer sb = ftp.downloadFile(args[3]);
ftp.writeFile("new_"+args[3],sb.toString());
ftp.logout();
} catch(java.io.IOException ioe) {
ioe.printStackTrace();
}
}
}
I am using FTPSession.java which is based on the Internet Protocol
RFC959.
Through my client FTPSession.java, i am trying to download a file from
a ftp server which has a disclaimer on it.
This disclaimer is a multi line response.
The code of FTPSession, in its getResponse method is coded to handle
multi line responses, but when i connect to the server (it is a NT
server with Unix Style directory system) it gives me a null response
from the server.
It gives me a error in the method "getResponse", bad(short) response
from the server.
The server is not able to log me in as the response i get from the
server is null.
Is it a problem with the FTP server or do i need to handle it in the
FTPClient code.
The code of FTPSession which i am using is as below.
Can someboody please help me on this ASAP, as it is very urgent.
Thanks in advance
past
import java.io.*;
import java.net.*;
import java.util.*;
/**
* A java class used to transmit and receive files or text to a ftp
* server using File Transfer Protocol (FTP) by direct communications
* with the host machine using sockets on port 21.
*
* @param host - hostname running the ftp server to transmit the file
to.
* @param username - username used to log in to the ftp server.
* @param password - password used to log in to the ftp server.
* <p>
* <pre>
* FTPSession ftp = new FTPSession("computer.site.com", "anonymous",
"(e-mail address removed)");
* ftp.uploadFile("test.dat", (ftp.readFile("test.dat").toString());
* StringBuffer sb = ftp.downloadFile("test.dat");
* ftp.writeFile("new_"+ "test.dat",sb.toString());
* </pre>
*
*
*/
public class FTPSession
{
protected String username = null;
protected String password = null;
protected Socket sessionSocket = null;
protected Socket dataSocket = null;
protected String host = null;
protected String reply = null;
protected DataInputStream inStream = null;
protected DataOutputStream outStream = null;
protected PrintStream printStream = null;
protected boolean loggedIn = false;
protected static final String ASCII = "A";
protected static final String BINARY = "I";
protected static final int port = 21;
protected String transferType = BINARY;
/**
* A java class used to transmit and receive files or text to a ftp
* server using File Transfer Protocol (FTP) by direct communications
* with the host machine using sockets on port 21.
*
* @param host - hostname running the ftp server to transmit the file
to.
* @param username - username used to log in to the ftp server.
* @param password - password used to log in to the ftp server.
*/
public FTPSession(String _host, String _username, String _password)
{
this(_host,_username,_password,BINARY);
}
/**
* @param host - hostname running the ftp server to transmit the file
to.
* @param username - username used to log in to the ftp server.
* @param password - password used to log in to the ftp server.
* @param transferType - ASCII or BINARY transfer format (BINARY is
default).
*/
public FTPSession(String _host, String _username,
String _password, String _transferType)
{
host = _host;
username = _username;
password = _password;
if ( !(_transferType.equals(BINARY)) && !(_transferType.equals(ASCII))
)
throw new RuntimeException("Illegal parameter for transferType");
transferType = _transferType;
}
/**
* Used to download a file from the ftp server's machine.
* @param filename - filename to read from the ftp server.
* @return StringBuffer - contents of the file from the ftp server.
*/
public StringBuffer downloadFile(String filename) throws IOException
{
return(downloadFile("",filename));
}
/**
* Used to download a file from the ftp server's machine.
* @param directory - directory which the file resides on the ftp
server.
* @param filename - filename to read from the ftp server.
* @return StringBuffer - contents of the file from the ftp server.
*/
public StringBuffer downloadFile(String dir, String filename)
throws IOException
{
if (!loggedIn)
login();
// cd to the proper directory
changeDirectory(dir);
// set transfer mode to either BINARY or ASCII
reply = doCommand("TYPE " + transferType);
checkResponse(reply,'2');
// get socket which to transport data over.
dataSocket = getDataSocket();
InputStream inputStream = dataSocket.getInputStream();
// issue command to start transmission of file.
doCommand("RETR " + filename);
checkResponse(reply,'1');
// retrieve data from server.
String contents = retrieveData(inputStream);
// close connection for data transfer
dataSocket.close();
reply = getResponse();
checkResponse(reply,'2');
return (new StringBuffer(contents));
}
/**
* Used internally to read data from given input stream when
transferring
* data from the ftp server.
*
* @param inputStream - InputStream from socket used to transfer data.
* @return String - contents read from the InputStream given.
*/
protected String retrieveData(InputStream inputStream)
throws IOException
{
int c = 0;
char lineBuffer[] = new char[128];
char buffer[] = lineBuffer;
int room = buffer.length;
int offset = 0;
try {
loop: while (true)
{
// read characters into buffer
switch (c = inputStream.read())
{
case -1: break loop;
default: if (--room < 0)
{
buffer = new char[offset+128];
room = buffer.length - offset - 1;
System.arraycopy(lineBuffer,0,buffer,0,offset);
lineBuffer = buffer;
buffer[offset++] = (char) c;
break;
}
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
throw new IOException("Problems encountered while reading" +
" file from Server");
}
if ((c == -1) && (offset == 0))
return null;
return String.copyValueOf(buffer,0,offset);
}
/**
* Used to write a file to the client system. NOTE: this will not work
* if the client is running as an Applet.
*
* @param filename - filename to write the contents to on the client
system.
* @param contents - contents of the file to write to the client file
system.
*/
public void writeFile(String filename, String contents) throws
IOException
{
RandomAccessFile raf = new RandomAccessFile(filename,"rw");
raf.writeBytes(contents);
}
/**
* Used internally to create the socket connection to the host system
and
* setup the input, output and print streams.
*
* @param hostname - hostname of the host running the ftp server.
* @param port - port to connect to on the host system. (usually port
21)
*/
protected void connect(String host, int port) throws IOException
{
try {
// create connection to ftp server.
sessionSocket = new Socket(host, port);
} catch (Exception e) {
throw new IOException("Unable to connect to host:\n" + host);
}
inStream = new DataInputStream(sessionSocket.getInputStream());
outStream = new DataOutputStream(sessionSocket.getOutputStream());
printStream = new PrintStream(outStream);
// get reply to validate conection.
reply = getResponse();
checkResponse(reply,'2');
loggedIn = true;
}
/**
* Used internally to send the login sequence to the host system via
socket.
*
* @param username - username to login to the ftp server.
* @param password - password to login to the ftp server.
*/
public void login() throws IOException
{
login(username, password);
}
/**
* Used internally to send the login sequence to the host system via
socket.
*
* @param username - username to login to the ftp server.
* @param password - password to login to the ftp server.
*/
public void login(String username, String password) throws IOException
{
this.username = username;
this.password = password;
if (!loggedIn)
connect(host,port);
// send username to ftp server to login
reply = doCommand("USER " + username);
checkResponse(reply,'3');
// send password to ftp server to login
reply = doCommand("PASS " + password);
checkResponse(reply,'2');
}
/**
* Used internally to send the logout sequence to the host system via
socket.
*/
public void logout() throws IOException {
// no response comes from here
printStream.println("QUIT");
try {
printStream.flush();
printStream.close();
outStream.close();
inStream.close();
sessionSocket.close();
dataSocket.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
loggedIn = false;
}
/**
* Used internally to validate a response by the host system.
*/
protected void checkResponse(String response, char digit) throws
IOException
{
if (response.charAt(0) != digit)
throw new IOException(response);
}
/**
* Used internally to validate a response by the host system.
*
* @param command - command sent to the ftp server on the host system.
* @return String - reply received from the host system.
*/
protected String doCommand(String command) throws IOException
{
//System.out.println("doCommand: " + command);
printStream.println(command);
return (getResponse());
}
/**
* Used internally to retrieve a response from the host system.
* Watches for responses that also include line continuation
characters.
*
* @param command - command sent to the ftp server on the host system.
* @return String - reply received from the host system.
*/
protected String getResponse() throws IOException
{
while (true)
{
reply = inStream.readLine();
if (reply == null)
throw new IOException("Bad (null) response from server");
if (reply.length() < 3)
throw new IOException("Bad (short) response from server");
// If there isn't a dash ('-') immediately after the number, then
// we've gotten the complete response. (The dash is the continu
// ation character)
if ((reply.length() == 3) || (reply.charAt(3) != '-'))
break;
}
//System.out.println("getResponse: " + reply);
return (reply);
}
/**
* Used internally to retrieve a data connection from the host system.
* host ip address and port number are parsed from the server's reply
to
* generate information for data connection.
*
* @return Socket - socket used to retrieve data from ftp server.
*/
protected Socket getDataSocket() throws IOException
{
int ctr = 0;
Socket dataSocket = null;
String[] parts = new String[6];
String part = null;
// Switch to PASV mode, capture server reply for socket information
reply = doCommand("PASV");
checkResponse(reply,'2');
// Our reply has data with the host ip and port for retrieving/sending
// data. It is in the form of:
// ### Text (###,###,###,###,##,###)[.]
// where,
// ### - reply code starts with '2' is good
// Text - general status message
// (..###..) - is the ip address and port which to connect
// to for data transfer. 1st four #'s are the ip
// address and the last two #'s are the port.
// [.] - possible period at the end of the line.
BreakString bs = new BreakString(reply,",");
Enumeration e = bs.result();
while (e.hasMoreElements())
{
part = (String) e.nextElement();
if (part.endsWith(")."))
{
parts[ctr++] = part.substring(0,part.length()-2);
}
else if (part.endsWith(")"))
{
parts[ctr++] = part.substring(0,part.length()-1);
}
else if (part.lastIndexOf("(") >= 0)
{
int begin = part.lastIndexOf("(");
parts[ctr++] = part.substring(begin+1,part.length());
}
else
{
parts[ctr++] = part;
}
}
// Piece together the IP address.
String ip = parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3];
// Determine port
int port = -1;
try {
int big = Integer.parseInt(parts[4]) << 8;
int small = Integer.parseInt(parts[5]);
port = big + small; // port number
} catch(NumberFormatException nfe) {
nfe.printStackTrace();
}
if ((ip != null) && (port != -1))
{
try {
dataSocket = new Socket(ip, port);
} catch (Exception se) {
se.printStackTrace();
throw new IOException("Unable to connect to address/port");
}
}
else
throw new IOException("Invalid IP address or port received");
return dataSocket;
}
/**
* Used to change directories on the server side for data retrieval or
* transmission.
*
* @param dir - directory to change to on the ftp server.
*/
public void changeDirectory(String dir) throws IOException
{
// some ftp servers do not understand CWD without a dirname
if ((dir != null) && !(dir.equals("")) && !(dir.equals(" ")))
{
reply = doCommand("CWD " + dir);
checkResponse(reply,'2');
}
}
/**
* Used to show current working directory on the server side.
*/
public String showDirectory() throws IOException
{
String path = null;
reply = doCommand("PWD");
checkResponse(reply,'2');
try {
// The message is in the format of:
// ### "directory information" response information
BreakString bs = new BreakString(reply, "\"");
Enumeration e = bs.result();
e.nextElement(); // throw away first part
path = (String) e.nextElement(); // dir info
} catch (Exception e) {
throw new IOException("Badly formed response from server: \n" +
reply);
}
return path;
}
public void finalize() { try { logout(); } catch (Exception ignore) {}
}
/**
* Main entry point to test the operation of the ftp server.
*
* @param server - host server to transfer file to.
* @param username - username to login to the ftp server.
* @param password - password to login to the ftp server.
* @param filename - name of file to transfer to the server
* and back to client's system.
*/
public static void main(String[] args)
{
String usage = "USAGE: FTPSession server username passwd filename";
if (args.length < 4)
{
System.out.println("\n" + usage + "\n\n");
System.exit(0);
}
try {
FTPSession ftp = new FTPSession(args[0], args[1], args[2]);
// retieve list of files on server
String path = ftp.showDirectory();
// change directories on server
ftp.changeDirectory("..");
// change directories on server
ftp.changeDirectory(path);
// download file
System.out.println("Downloading File: new_" + args[3] + " .......");
StringBuffer sb = ftp.downloadFile(args[3]);
ftp.writeFile("new_"+args[3],sb.toString());
ftp.logout();
} catch(java.io.IOException ioe) {
ioe.printStackTrace();
}
}
}