home *** CD-ROM | disk | FTP | other *** search
/ Symantec Visual Cafe for Java 2.5 / symantec-visual-cafe-2.5-database-dev-edition.iso / VCafe / prosrc.bin / FtpClient.java < prev    next >
Encoding:
Java Source  |  1998-03-18  |  10.4 KB  |  496 lines

  1. /*
  2.  * @(#FtpClient.java
  3.  *
  4.  * Copyright (c) 1997 Symantec Corporation. All Rights Reserved.
  5.  *
  6.  */
  7.  
  8.  
  9. package symantec.itools.db.awt;
  10.  
  11. import java.net.*;
  12. import java.io.*;
  13. import java.awt.*;
  14. import java.util.*;
  15.  
  16. /**
  17.  * This class implements a subset of the FTP client-side protocol.
  18.  * It allows you to connect, login and retrieve files from a host system.
  19.  */
  20. public class FtpClient
  21. {
  22.     String host;
  23.     Socket s;
  24.     boolean Connected = false;
  25.     boolean LoggedIn = false;
  26.     PrintStream ftpout;
  27.     DataInputStream ftpin;
  28.     FtpErrors errs;
  29.     Vector v;
  30.     Vector files;
  31.     Vector dirs;
  32.     private boolean dataRead = false;
  33.     /**
  34.      * ASCII FTP transfer mode constant.
  35.      */
  36.     public static final int ASCII = 0;
  37.     /**
  38.      * Binary FTP transfer mode constant.
  39.      */
  40.     public static final int BINARY = 1;
  41.     private int xferMode = BINARY;
  42.     private boolean modeChange = true;
  43.  
  44.     /**
  45.      * Constructs a FtpClient connected to the host with the given name.
  46.      * The default transfer mode is binary.
  47.      *
  48.      * @param hostname the name of the host to connect to
  49.      * @exception IOException
  50.      * if failed to connect with the specified host
  51.      */
  52.     public FtpClient(String hostname) throws IOException
  53.     {
  54.         byte buf[] = new byte[3];
  55.         String str;
  56.         int ret;
  57.  
  58.         this.host = hostname;
  59.         Connected = true;
  60.  
  61.         errs = new FtpErrors();
  62.  
  63.         try {
  64.             s = new Socket(hostname, 21);
  65.         } catch (UnknownHostException e) {
  66.             Connected = false;
  67.         }
  68.  
  69.         ftpout = new PrintStream(s.getOutputStream());
  70.         ftpin = new DataInputStream(s.getInputStream());
  71.  
  72.         str = ftpin.readLine();
  73.  
  74.         try {
  75.             ret = Integer.parseInt(str.substring(0, 3));
  76.         } catch (NumberFormatException e) {
  77.             ret = -1;
  78.         } catch (StringIndexOutOfBoundsException e) {
  79.             ret = -1;
  80.         }
  81.  
  82.         if (ret == 220) {
  83.             //read the server info
  84.             str = ftpin.readLine();
  85.         } else {
  86.             throw new IOException("Connect");
  87.         }
  88.     }
  89.  
  90.     /**
  91.      * Sets FTP file transfer mode to either ASCII or binary.
  92.      *
  93.      * @param mode the new transfer mode, one of ASCII or BINARY
  94.      * @see #ASCII
  95.      * @see #BINARY
  96.      */
  97.     public void setXferMode(int mode)
  98.     {
  99.         if (mode != xferMode && (mode == ASCII || mode == BINARY)) {
  100.             xferMode = mode;
  101.             modeChange = true;
  102.         }
  103.  
  104.         return;
  105.     }
  106.  
  107.     /**
  108.      * Gets the current file transfer mode.
  109.      *
  110.      * @return the current transfer mode, either ASCII or BINARY
  111.      * @see #ASCII
  112.      * @see #BINARY
  113.      */
  114.     public int getXferMode()
  115.     {
  116.             return xferMode;
  117.     }
  118.  
  119.     /**
  120.      * Logs in to host with the given user name and password.
  121.      *
  122.      * @param user the user name
  123.      * @param passwd the user password
  124.      * @exception FtpLoginException
  125.      * if cannot log in
  126.      */
  127.     public void login(String user, String passwd)
  128.         throws FtpLoginException
  129.     {
  130.         int retCode;
  131.  
  132.         if (user == null) {
  133.             throw new FtpLoginException("Login cannot be null");
  134.         }
  135.  
  136.         try {
  137.             if ((retCode = doCmd("USER " + user + "\n")) != 331) {
  138.                 throw new FtpLoginException(getError(retCode));
  139.             }
  140.  
  141.             if ((retCode = doCmd("PASS " + passwd + "\n")) != 230) {
  142.                 throw new FtpLoginException(getError(retCode));
  143.             }
  144.  
  145.         } catch (IOException e) {
  146.             throw new FtpLoginException(e.getMessage());
  147.         }
  148.  
  149.         LoggedIn = true;
  150.     }
  151.  
  152.     /**
  153.      * Returns true if currently logged in, false otherwise.
  154.      */
  155.     public boolean loggedIn()
  156.     {
  157.         return LoggedIn;
  158.     }
  159.  
  160.     /**
  161.      * Implements the RETR (get file) command, returning a DataInputStream
  162.      * for the specified host file. The DataInputStream
  163.      * is used to transfer the file data from the host.
  164.      *
  165.      * @param name the name of the file to get
  166.      * @return the DataInputStream used to access that file
  167.      * @exception IOException
  168.      * if there is a problem accessing the file
  169.      */
  170.     public DataInputStream getFile(String name)
  171.         throws IOException
  172.     {
  173.         Socket fileStream;
  174.         int rval;
  175.         String buf;
  176.  
  177.         if (modeChange) {
  178.             if (xferMode == ASCII)
  179.                 rval = doCmd("TYPE A\n");
  180.             else
  181.                 rval = doCmd("TYPE I\n");
  182.  
  183.             if (rval != 200) {
  184.                 throw new IOException("Couldn't change xfer mode");
  185.             }
  186.  
  187.             modeChange = false;
  188.         }
  189.  
  190.         fileStream = doIOCmd("RETR " + name + "\n");
  191.  
  192.         buf = ftpin.readLine();
  193.  
  194.         return (new DataInputStream(fileStream.getInputStream()));
  195.     }
  196.  
  197.     /**
  198.      * Retrieves a list of files in the host's current directory.
  199.      *
  200.      * @return a Vector of filenames
  201.      * @exception IOException
  202.      * if there is a problem accessing the host
  203.      */
  204.     public Vector getFileList()
  205.         throws IOException
  206.     {
  207.         int retval;
  208.         Socket s;
  209.         DataInputStream dis;
  210.         String buf;
  211.         String retStr[];
  212.         boolean done = false;
  213.         String tmp;
  214.  
  215.         if (!dataRead) {
  216.             v = new Vector(100);
  217.             files = new Vector(100);
  218.             dirs = new Vector(100);
  219.  
  220.             s = doIOCmd("LIST -aF\n");
  221.             dis = new DataInputStream(s.getInputStream());
  222.  
  223.             done = false;
  224.  
  225.             if (s == null)
  226.                 throw new IOException("Socket creation failed");
  227.             while (!done) {
  228.                 buf = dis.readLine();
  229.                 if (buf == null) {
  230.                     done = true;
  231.                 } else {
  232.                     v.addElement(buf);
  233.                 }
  234.             }
  235.  
  236.             buf = ftpin.readLine();
  237.  
  238.             s.close();
  239.         }
  240.  
  241.         for (int i = 1; i < v.size(); i++) {
  242.             tmp = (String)(v.elementAt(i));
  243.             if (tmp.charAt(tmp.length() - 1) == '/')
  244.                 dirs.addElement(getDirName((String)(v.elementAt(i))));
  245.             else
  246.                 files.addElement(getFileName((String)(v.elementAt(i))));
  247.         }
  248.  
  249.         dataRead = true;
  250.  
  251.         return files;
  252.     }
  253.  
  254.  
  255.     /**
  256.      * Retrieves a list of directories in the host's current directory.
  257.      *
  258.      * @return a Vector of directory names
  259.      * @exception IOException
  260.      * if there is a problem accessing the host
  261.      */
  262.     public Vector getDirList()
  263.         throws IOException
  264.     {
  265.         Vector v;
  266.  
  267.         if (!dataRead)
  268.             v = getFileList();
  269.  
  270.         return dirs;
  271.     }
  272.  
  273.     /** Perform an IO Command which requires opening a passive socket
  274.      */
  275.  
  276.     private Socket doIOCmd(String cmd)
  277.         throws IOException
  278.     {
  279.         Socket s;
  280.         ServerSocket serv;
  281.            InetAddress hostAddr = InetAddress.getLocalHost();
  282.            byte addr[] = hostAddr.getAddress();
  283.         String newCmd = "PORT ";
  284.         int ret;
  285.  
  286.         serv = new ServerSocket(0);
  287.  
  288.         for (int i = 0; i < addr.length; i++) {
  289.             newCmd = newCmd + (addr[i] & 0xFF) + ",";
  290.         }
  291.  
  292.         newCmd = newCmd + ((serv.getLocalPort() >>> 8) & 0xff) + ","
  293.             + (serv.getLocalPort() & 0xff);
  294.  
  295.         ret = doCmd(newCmd + "\n");
  296.  
  297.         if ((ret != 200) && (ret != 226) && (ret !=230))
  298.             throw new IOException(getError(ret));
  299.  
  300.         ret = doCmd(cmd);
  301.  
  302.         if ((ret != 125) && (ret != 150) && (ret !=200))
  303.             throw new IOException(getError(ret));
  304.  
  305.         s = serv.accept();
  306.         serv.close();
  307.  
  308.         return s;
  309.     }
  310.  
  311.  
  312.     /**
  313.      * Changes to a different directory on the host.
  314.      *
  315.      * @param dir the new directory to change to
  316.      * @exception IOException
  317.      * if there is a problem accessing the host
  318.      */
  319.     public void chdir(String dir)
  320.         throws IOException
  321.     {
  322.         int retCode;
  323.  
  324.         dataRead = false;
  325.  
  326.         retCode = doCmd("CWD " + dir + "\n");
  327.  
  328.         if (retCode != 250 && retCode !=200) {
  329.             debug("Return code is: " + retCode);
  330.             throw new IOException("Couldn't cd to: " + dir);
  331.         }
  332.     }
  333.  
  334.     /** Issue a specific ftp command
  335.      */
  336.  
  337.     private int doCmd(String cmd)
  338.         throws IOException
  339.     {
  340.         byte buf[] = new byte[3];
  341.         int ret;
  342.         String str;
  343.  
  344.         ftpout.print(cmd);
  345.         ftpin.read(buf);
  346.         ftpin.readLine();
  347.  
  348.         str = new String(buf, 0);
  349.  
  350.         try {
  351.             ret = Integer.parseInt(str.substring(0, 3));
  352.         } catch (NumberFormatException e) {
  353.             ret = -1;
  354.         } catch (StringIndexOutOfBoundsException e) {
  355.             ret = -1;
  356.         }
  357.         return ret;
  358.     }
  359.  
  360.     /**
  361.      * Returns just the directory name of a host file list entry.
  362.      * The returned directory name has the trailing "/" stripped from it.
  363.      *
  364.      * @param s a host file list entry
  365.      * @return the directory name
  366.      */
  367.     public String getDirName(String s)
  368.     {
  369.         String tmp =null;
  370.         String ret;
  371.         StringTokenizer st1;
  372.  
  373.         st1 = new StringTokenizer(s);
  374.  
  375.         while (st1.hasMoreElements())
  376.         {
  377.             tmp = st1.nextToken();
  378.         }
  379.  
  380.         ret = tmp.substring(0, tmp.length() - 1);
  381.  
  382.         return ret;
  383.     }
  384.  
  385.     /**
  386.      * Returns just the file name of a host file list entry.
  387.      *
  388.      * @param s a host file list entry
  389.      * @the file name
  390.      */
  391.     public String getFileName(String s)
  392.     {
  393.         String tmp =null;
  394.         String ret;
  395.         StringTokenizer st1;
  396.         char ch;
  397.  
  398.         st1 = new StringTokenizer(s);
  399.  
  400.         while (st1.hasMoreElements())
  401.         {
  402.             tmp = st1.nextToken();
  403.         }
  404.  
  405.         ch = tmp.charAt(tmp.length() - 1);
  406.  
  407.         if (ch == '*' || ch == '@' || ch == '=')
  408.             return tmp.substring(0, tmp.length() - 1);
  409.         else
  410.             return tmp;
  411.     }
  412.  
  413.     /**
  414.      * Gets the error message corresponding to the given FTP error number.
  415.      *
  416.      * @param an FTP error number
  417.      * @return a description of that error
  418.      */
  419.     public String getError(int err)
  420.     {
  421.         return errs.getError(err);
  422.     }
  423.  
  424.     /**
  425.      * Closes the host connection.
  426.      */
  427.     public void closeHard()
  428.     {
  429.         try {
  430.             ftpin.close();
  431.             ftpout.close();
  432.         } catch (IOException e) {
  433.             // Ignore
  434.         }
  435.         LoggedIn = false;
  436.         dataRead = false;
  437.     }
  438.  
  439.     /**
  440.      * Performs an FTP QUIT command and then closes the host connection.
  441.      * @exception IOException
  442.      * if there is a problem accessing the host
  443.      */
  444.     public void quit()
  445.         throws IOException
  446.     {
  447.         doCmd("QUIT\n");
  448.  
  449.         ftpin.close();
  450.         ftpout.close();
  451.     }
  452.  
  453.     /** Debugging routine
  454.      */
  455.  
  456.     private void debug(String s)
  457.     {
  458.         //System.err.println(s);
  459.     }
  460. }
  461.  
  462. class FtpErrors
  463. {
  464.     Hashtable errTable;
  465.  
  466.     public static final int errs[] =
  467.         { 500, 501, 502, 503, 504, 530, 532, 550, 551, 552, 553 };
  468.  
  469.     public static final String errstr[] = {
  470.             "Syntax error, command unrecognized",
  471.             "Syntax error in parameters or arguments",
  472.             "Command not implemented",
  473.             "Bad sequence of commands",
  474.             "Command not implemented for that parameter",
  475.             "Not logged in",
  476.             "Need account for storing files",
  477.             "Requested action not taken",
  478.             "Requested action aborted: page type unknown",
  479.             "Requested file action aborted",
  480.             "Requested action not taken"
  481.     };
  482.  
  483.     public FtpErrors()
  484.     {
  485.         errTable = new Hashtable();
  486.  
  487.         for (int i = 0; i < errs.length; i++)
  488.             errTable.put(new Integer(errs[i]), errstr[i]);
  489.     }
  490.  
  491.     public String getError(int errorkey)
  492.     {
  493.         return (String)(errTable.get(new Integer(errorkey)));
  494.     }
  495. }
  496.