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

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

/*  Copyright 1999-2015 Vince Via [email protected]
    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/
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:
//