All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.viaoa.util.OAFtpClient Maven / Gradle / Ivy

The newest version!
package com.viaoa.util;

import javax.swing.*;
import java.net.*;
import java.io.*;
import java.util.*;

/**
    connect()
    login(user, pw)
    setBinary()
    setAscii()
    
    get
    put
    append
*/
public class OAFtpClient {

    private Socket csock = null; // controll socket
    private Socket dsock = null; // data socket
    private BufferedReader reader; //qqqq dcis;
    private PrintWriter writer; //qqq  pos;

    public boolean connect(String server) throws IOException {
        csock = new Socket(server, 21);
        reader =  new BufferedReader(new InputStreamReader(csock.getInputStream()));
        writer = new PrintWriter(csock.getOutputStream(), true); // set auto flush true.
        return getResponse(null).substring(0,3).equals("220");
    }

    public void login(String user, String pass) throws IOException {
        ftpSendCmd("USER "+user);
        ftpSendCmd("PASS "+pass);
    }

    public void quit() { // logout, close streams
        try { 
            if (writer != null) {
                writer.print("BYE" + "\r\n" );
                writer.flush();
                writer.close();
            }
            if (reader != null)  reader.close();
            if (csock != null) csock.close();
        } 
        catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }

    public void setBinary() throws IOException {
        ftpSendCmd("TYPE I");
    }
    public void setAscii() throws IOException {
        ftpSendCmd("TYPE A");
    }

    public String getFileAsString(String dir, String file) throws IOException {
        ftpSetDir(dir);
        dsock = ftpGetDataSock();
        InputStream is = dsock.getInputStream();
        ftpSendCmd("RETR "+file);
        String contents = getAsString(is);
        is.close();
        dsock.close();
        return contents;
    }

    public String getDirectory(String dir) throws IOException {
        ftpSetDir(dir);
        dsock = ftpGetDataSock();
        InputStream is = dsock.getInputStream();
        ftpSendCmd("LIST");
        String contents = getAsString(is);
        is.close();
        dsock.close();
        return contents;
    }
    
    
    public void append(String dir, String file, String what) throws IOException {
        ftpSetDir(dir);
        dsock = ftpGetDataSock();
        OutputStream os = dsock.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        ftpSendCmd("APPE "+file); 
        dos.writeBytes(what);
        dos.flush();
        dos.close();
        dsock.close();
    }

    public void put(String dir, String fileName, File file) throws IOException {
        ftpSetDir(dir);
        dsock = ftpGetDataSock();
        OutputStream os = dsock.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        ftpSendCmd("STOR "+fileName);
    
        InputStream is = new FileInputStream(file);
        int bufferSize = 1024 * 2;
        byte[] bs = new byte[bufferSize];
        for (int i=0; ;i++) {
            int x = is.read(bs, 0, bufferSize);
            if (x < 0) break;
            dos.write(bs, 0, x);
        }
        is.close();
        
        dos.flush();
        dos.close();
        dsock.close();
    }

    public void put(String dir, String file, String what) throws IOException {
        ftpSetDir(dir);
        dsock = ftpGetDataSock();
        OutputStream os = dsock.getOutputStream();
        DataOutputStream dos = new DataOutputStream(os);
        ftpSendCmd("STOR "+file);
        dos.writeBytes(what);    
        dos.flush();
        dos.close();
        dsock.close();
    }


    
    ///////////////// private fields ////////////////////
    private boolean pauser = false;  // it's a hack. We're going to 
          // stall (refuse further requests) till we get a reply back 
          // from server for the current request.

    private String getAsString(InputStream is) {
        int c=0;
        char lineBuffer[]=new char[128], buf[]=lineBuffer;
        int room= buf.length, offset=0;
        try {
          loop: while (true) {
              // read chars into a buffer which grows as needed
                  switch (c = is.read() ) {
                      case -1: break loop;

                      default: if (--room < 0) {
                                   buf = new char[offset + 128];
                                   room = buf.length - offset - 1;
                                   System.arraycopy(lineBuffer, 0, 
                                            buf, 0, offset);
                                   lineBuffer = buf;
                               }
                               buf[offset++] = (char) c;
                               break;
                  }
          }
        } catch(IOException ioe) {ioe.printStackTrace();}
        if ((c == -1) && (offset == 0)) {
            return null;
        }
        return String.copyValueOf(buf, 0, offset);
    }


    private void ftpSetDir(String dir)
        throws IOException { 
        // cwd to dir
        ftpSendCmd("CWD "+dir);
    }


    private Socket ftpGetDataSock()
        throws IOException {
        // Go to PASV mode, capture server reply, parse for socket setup
        // V2.1: generalized port parsing, allows more server variations
        String reply = ftpSendCmd("PASV");

        // New technique: just find numbers before and after ","!
        StringTokenizer st = new StringTokenizer(reply, ",");
        String[] parts = new String[6]; // parts, incl. some garbage
        int i = 0; // put tokens into String array
        while(st.hasMoreElements()) {
            // stick pieces of host, port in String array
            try {
                parts[i] = st.nextToken();
                i++;
            } catch(NoSuchElementException nope){nope.printStackTrace();}
        } // end getting parts of host, port

        // Get rid of everything before first "," except digits
        String[] possNum = new String[3];
        for(int j = 0; j < 3; j++) {
            // Get 3 characters, inverse order, check if digit/character
            possNum[j] = parts[0].substring(parts[0].length() - (j + 1),
                parts[0].length() - j); // next: digit or character?
            if(!Character.isDigit(possNum[j].charAt(0)))
                possNum[j] = "";
        }
        parts[0] = possNum[2] + possNum[1] + possNum[0];
        // Get only the digits after the last ","
        String[] porties = new String[3];
        for(int k = 0; k < 3; k++) {
            // Get 3 characters, in order, check if digit/character
            // May be less than 3 characters
            if((k + 1) <= parts[5].length())
                porties[k] = parts[5].substring(k, k + 1);
            else porties[k] = "FOOBAR"; // definitely not a digit!
            // next: digit or character?
            if(!Character.isDigit(porties[k].charAt(0)))
                    porties[k] = "";
        } // Have to do this one in order, not inverse order
        parts[5] = porties[0] + porties[1] + porties[2];
        // Get dotted quad IP number first
        String ip = parts[0]+"."+parts[1]+"."+parts[2]+"."+parts[3];

        // Determine port
        int port = -1;
        try { // Get first part of port, shift by 8 bits.
            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))

            dsock = new Socket(ip, port);
        else throw new IOException();
        return dsock;
    }

    private String ftpSendCmd(String cmd)
        throws IOException
    { // This sends a dialog string to the server, returns reply
      // V2.0 Updated to parse multi-string responses a la RFC 959
      // Prints out only last response string of the lot.
        if (pauser) // i.e. we already issued a request, and are
                  // waiting for server to reply to it.  
            {
                if (reader != null)
                {
                    String discard = reader.readLine(); // will block here
                    // preventing this further client request until server
                    // responds to the already outstanding one.
                    pauser = false;
                }
            }
        writer.print(cmd + "\r\n" );
        writer.flush(); 
        String response = getResponse(cmd);
        return response;
    }

     // new method to read multi-line responses
     // responseHandler: takes a String command or null and returns
     // just the last line of a possibly multi-line response
     private String getResponse(String cmd) 
         throws IOException
     { // handle more than one line returned
        String reply = this.responseParser(reader.readLine());
        String numerals = reply.substring(0, 3);
        String hyph_test = reply.substring(3, 4);
        String next = null;
        if(hyph_test.equals("-")) {
            // Create "tester", marks end of multi-line output
            String tester = numerals + " ";
            boolean done = false;
            while(!done) { // read lines til finds last line
                next = reader.readLine();
                // Read "over" blank line responses
                while (next == null || next.equals("") || next.equals("  ")) {
                    next = reader.readLine();
                }

                // If next starts with "tester", we're done
               if(next != null && next.substring(0,4).equals(tester))
                   done = true;
            }
            return next;

        } else // "if (hyph_test.equals("-")) not true"
            return reply;
    }

    // responseParser: check first digit of first line of response
    // and take action based on it; set up to read an extra line
    // if the response starts with "1"
    private String responseParser(String resp)
        throws IOException
    { // Check first digit of resp, take appropriate action.
        String digit1 = resp.substring(0, 1);
        if(digit1.equals("1")) {
            // server to act, then give response
            // set pauser
            pauser = true;
            return resp;
        }
        else if(digit1.equals("2")) { // do usual handling
            // reset pauser
            pauser = false;
            return resp;
        }
        else if(digit1.equals("3") || digit1.equals("4")
            || digit1.equals("5")) { // do usual handling
            return resp;
        }
        else { // not covered, so return null
            return null;
        }
    }

/****

    public static void main(String[] args) {
        try {
            FTPClient ftp = new FTPClient();
            ftp.connect("ftp.vetplan.net");
            ftp.login("vince", "via83");
            // String s = ftp.get("", "test");
            // System.out.println("==> "+s);
            // ftp.put("", "xx", "Vince Via test");
            ftp.put("", "OAFtp.java", new File("util\\OAFtp.java"));
        }
        catch (Exception e) {
            e.printStackTrace();
            System.out.println("Error: "+e);
        }
    }
*****/
}


/**
Peter van der Linden's Linlyn applet
http://www.afu.com/t.java
*/

//////////////////////////////////////////
//  At last!  Java code to read/write files on the server from an applet!
//  This is the famous Linlyn code.
//
//  Use:  
//    compile this file, and have your applet call it as below.
//
//    to upload a file:  
//          Linlyn ftp = new Linlyn( , ,  );
//          ftp.upload( , ,  );
//
//    to download a file:  
//          Linlyn ftp = new Linlyn( , ,  );
//          String contents = ftp.download( ,  );
//
//          the default is ASCII transfer, an overloaded method does bin.
//
//    All parameters and return values are Strings. E.g.
//          Linlyn ftp = new Linlyn( "rtfm.mit.edu", "anonymous", "linden@" );
//          String contents = ftp.download( 
//                        "/pub/usenet-by-group/comp.lang.java.programmer"
//                        "Java_Programmers_FAQ" );
//
//          [the actual values above are not generally valid, substitute
//           your own server for your first attempt, see note 1.]
//
//    Notes:
//      1.  Usual applet security rules apply: you can only get a file
//          from the server that served the applet.
//      2.  The applet server must also be an FTP server.  This is NOT true
//          for some ISPs, such as best.com.  They have separate FTP and
//          http machines.  This code may work on such a setup if you put
//          the classfiles into the ftp area, and in the HTML file say:
//