home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-18 | 10.4 KB | 496 lines |
- /*
- * @(#FtpClient.java
- *
- * Copyright (c) 1997 Symantec Corporation. All Rights Reserved.
- *
- */
-
-
- package symantec.itools.db.awt;
-
- import java.net.*;
- import java.io.*;
- import java.awt.*;
- import java.util.*;
-
- /**
- * This class implements a subset of the FTP client-side protocol.
- * It allows you to connect, login and retrieve files from a host system.
- */
- public class FtpClient
- {
- String host;
- Socket s;
- boolean Connected = false;
- boolean LoggedIn = false;
- PrintStream ftpout;
- DataInputStream ftpin;
- FtpErrors errs;
- Vector v;
- Vector files;
- Vector dirs;
- private boolean dataRead = false;
- /**
- * ASCII FTP transfer mode constant.
- */
- public static final int ASCII = 0;
- /**
- * Binary FTP transfer mode constant.
- */
- public static final int BINARY = 1;
- private int xferMode = BINARY;
- private boolean modeChange = true;
-
- /**
- * Constructs a FtpClient connected to the host with the given name.
- * The default transfer mode is binary.
- *
- * @param hostname the name of the host to connect to
- * @exception IOException
- * if failed to connect with the specified host
- */
- public FtpClient(String hostname) throws IOException
- {
- byte buf[] = new byte[3];
- String str;
- int ret;
-
- this.host = hostname;
- Connected = true;
-
- errs = new FtpErrors();
-
- try {
- s = new Socket(hostname, 21);
- } catch (UnknownHostException e) {
- Connected = false;
- }
-
- ftpout = new PrintStream(s.getOutputStream());
- ftpin = new DataInputStream(s.getInputStream());
-
- str = ftpin.readLine();
-
- try {
- ret = Integer.parseInt(str.substring(0, 3));
- } catch (NumberFormatException e) {
- ret = -1;
- } catch (StringIndexOutOfBoundsException e) {
- ret = -1;
- }
-
- if (ret == 220) {
- //read the server info
- str = ftpin.readLine();
- } else {
- throw new IOException("Connect");
- }
- }
-
- /**
- * Sets FTP file transfer mode to either ASCII or binary.
- *
- * @param mode the new transfer mode, one of ASCII or BINARY
- * @see #ASCII
- * @see #BINARY
- */
- public void setXferMode(int mode)
- {
- if (mode != xferMode && (mode == ASCII || mode == BINARY)) {
- xferMode = mode;
- modeChange = true;
- }
-
- return;
- }
-
- /**
- * Gets the current file transfer mode.
- *
- * @return the current transfer mode, either ASCII or BINARY
- * @see #ASCII
- * @see #BINARY
- */
- public int getXferMode()
- {
- return xferMode;
- }
-
- /**
- * Logs in to host with the given user name and password.
- *
- * @param user the user name
- * @param passwd the user password
- * @exception FtpLoginException
- * if cannot log in
- */
- public void login(String user, String passwd)
- throws FtpLoginException
- {
- int retCode;
-
- if (user == null) {
- throw new FtpLoginException("Login cannot be null");
- }
-
- try {
- if ((retCode = doCmd("USER " + user + "\n")) != 331) {
- throw new FtpLoginException(getError(retCode));
- }
-
- if ((retCode = doCmd("PASS " + passwd + "\n")) != 230) {
- throw new FtpLoginException(getError(retCode));
- }
-
- } catch (IOException e) {
- throw new FtpLoginException(e.getMessage());
- }
-
- LoggedIn = true;
- }
-
- /**
- * Returns true if currently logged in, false otherwise.
- */
- public boolean loggedIn()
- {
- return LoggedIn;
- }
-
- /**
- * Implements the RETR (get file) command, returning a DataInputStream
- * for the specified host file. The DataInputStream
- * is used to transfer the file data from the host.
- *
- * @param name the name of the file to get
- * @return the DataInputStream used to access that file
- * @exception IOException
- * if there is a problem accessing the file
- */
- public DataInputStream getFile(String name)
- throws IOException
- {
- Socket fileStream;
- int rval;
- String buf;
-
- if (modeChange) {
- if (xferMode == ASCII)
- rval = doCmd("TYPE A\n");
- else
- rval = doCmd("TYPE I\n");
-
- if (rval != 200) {
- throw new IOException("Couldn't change xfer mode");
- }
-
- modeChange = false;
- }
-
- fileStream = doIOCmd("RETR " + name + "\n");
-
- buf = ftpin.readLine();
-
- return (new DataInputStream(fileStream.getInputStream()));
- }
-
- /**
- * Retrieves a list of files in the host's current directory.
- *
- * @return a Vector of filenames
- * @exception IOException
- * if there is a problem accessing the host
- */
- public Vector getFileList()
- throws IOException
- {
- int retval;
- Socket s;
- DataInputStream dis;
- String buf;
- String retStr[];
- boolean done = false;
- String tmp;
-
- if (!dataRead) {
- v = new Vector(100);
- files = new Vector(100);
- dirs = new Vector(100);
-
- s = doIOCmd("LIST -aF\n");
- dis = new DataInputStream(s.getInputStream());
-
- done = false;
-
- if (s == null)
- throw new IOException("Socket creation failed");
- while (!done) {
- buf = dis.readLine();
- if (buf == null) {
- done = true;
- } else {
- v.addElement(buf);
- }
- }
-
- buf = ftpin.readLine();
-
- s.close();
- }
-
- for (int i = 1; i < v.size(); i++) {
- tmp = (String)(v.elementAt(i));
- if (tmp.charAt(tmp.length() - 1) == '/')
- dirs.addElement(getDirName((String)(v.elementAt(i))));
- else
- files.addElement(getFileName((String)(v.elementAt(i))));
- }
-
- dataRead = true;
-
- return files;
- }
-
-
- /**
- * Retrieves a list of directories in the host's current directory.
- *
- * @return a Vector of directory names
- * @exception IOException
- * if there is a problem accessing the host
- */
- public Vector getDirList()
- throws IOException
- {
- Vector v;
-
- if (!dataRead)
- v = getFileList();
-
- return dirs;
- }
-
- /** Perform an IO Command which requires opening a passive socket
- */
-
- private Socket doIOCmd(String cmd)
- throws IOException
- {
- Socket s;
- ServerSocket serv;
- InetAddress hostAddr = InetAddress.getLocalHost();
- byte addr[] = hostAddr.getAddress();
- String newCmd = "PORT ";
- int ret;
-
- serv = new ServerSocket(0);
-
- for (int i = 0; i < addr.length; i++) {
- newCmd = newCmd + (addr[i] & 0xFF) + ",";
- }
-
- newCmd = newCmd + ((serv.getLocalPort() >>> 8) & 0xff) + ","
- + (serv.getLocalPort() & 0xff);
-
- ret = doCmd(newCmd + "\n");
-
- if ((ret != 200) && (ret != 226) && (ret !=230))
- throw new IOException(getError(ret));
-
- ret = doCmd(cmd);
-
- if ((ret != 125) && (ret != 150) && (ret !=200))
- throw new IOException(getError(ret));
-
- s = serv.accept();
- serv.close();
-
- return s;
- }
-
-
- /**
- * Changes to a different directory on the host.
- *
- * @param dir the new directory to change to
- * @exception IOException
- * if there is a problem accessing the host
- */
- public void chdir(String dir)
- throws IOException
- {
- int retCode;
-
- dataRead = false;
-
- retCode = doCmd("CWD " + dir + "\n");
-
- if (retCode != 250 && retCode !=200) {
- debug("Return code is: " + retCode);
- throw new IOException("Couldn't cd to: " + dir);
- }
- }
-
- /** Issue a specific ftp command
- */
-
- private int doCmd(String cmd)
- throws IOException
- {
- byte buf[] = new byte[3];
- int ret;
- String str;
-
- ftpout.print(cmd);
- ftpin.read(buf);
- ftpin.readLine();
-
- str = new String(buf, 0);
-
- try {
- ret = Integer.parseInt(str.substring(0, 3));
- } catch (NumberFormatException e) {
- ret = -1;
- } catch (StringIndexOutOfBoundsException e) {
- ret = -1;
- }
- return ret;
- }
-
- /**
- * Returns just the directory name of a host file list entry.
- * The returned directory name has the trailing "/" stripped from it.
- *
- * @param s a host file list entry
- * @return the directory name
- */
- public String getDirName(String s)
- {
- String tmp =null;
- String ret;
- StringTokenizer st1;
-
- st1 = new StringTokenizer(s);
-
- while (st1.hasMoreElements())
- {
- tmp = st1.nextToken();
- }
-
- ret = tmp.substring(0, tmp.length() - 1);
-
- return ret;
- }
-
- /**
- * Returns just the file name of a host file list entry.
- *
- * @param s a host file list entry
- * @the file name
- */
- public String getFileName(String s)
- {
- String tmp =null;
- String ret;
- StringTokenizer st1;
- char ch;
-
- st1 = new StringTokenizer(s);
-
- while (st1.hasMoreElements())
- {
- tmp = st1.nextToken();
- }
-
- ch = tmp.charAt(tmp.length() - 1);
-
- if (ch == '*' || ch == '@' || ch == '=')
- return tmp.substring(0, tmp.length() - 1);
- else
- return tmp;
- }
-
- /**
- * Gets the error message corresponding to the given FTP error number.
- *
- * @param an FTP error number
- * @return a description of that error
- */
- public String getError(int err)
- {
- return errs.getError(err);
- }
-
- /**
- * Closes the host connection.
- */
- public void closeHard()
- {
- try {
- ftpin.close();
- ftpout.close();
- } catch (IOException e) {
- // Ignore
- }
- LoggedIn = false;
- dataRead = false;
- }
-
- /**
- * Performs an FTP QUIT command and then closes the host connection.
- * @exception IOException
- * if there is a problem accessing the host
- */
- public void quit()
- throws IOException
- {
- doCmd("QUIT\n");
-
- ftpin.close();
- ftpout.close();
- }
-
- /** Debugging routine
- */
-
- private void debug(String s)
- {
- //System.err.println(s);
- }
- }
-
- class FtpErrors
- {
- Hashtable errTable;
-
- public static final int errs[] =
- { 500, 501, 502, 503, 504, 530, 532, 550, 551, 552, 553 };
-
- public static final String errstr[] = {
- "Syntax error, command unrecognized",
- "Syntax error in parameters or arguments",
- "Command not implemented",
- "Bad sequence of commands",
- "Command not implemented for that parameter",
- "Not logged in",
- "Need account for storing files",
- "Requested action not taken",
- "Requested action aborted: page type unknown",
- "Requested file action aborted",
- "Requested action not taken"
- };
-
- public FtpErrors()
- {
- errTable = new Hashtable();
-
- for (int i = 0; i < errs.length; i++)
- errTable.put(new Integer(errs[i]), errstr[i]);
- }
-
- public String getError(int errorkey)
- {
- return (String)(errTable.get(new Integer(errorkey)));
- }
- }
-