Package de.kout.wlFxp.ftp

Source Code of de.kout.wlFxp.ftp.Ftp

/**
* Copyright (C) 2003 Alexander Kout
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

package de.kout.wlFxp.ftp;

import java.net.*;
import java.io.*;
import java.util.*;
// nio
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import de.kout.wlFxp.wlPanel;
import de.kout.wlFxp.*;

import java.util.zip.CRC32;
import java.util.regex.*;

import javax.net.ssl.*;
import java.util.concurrent.*;
import java.security.*;

/**
*  here are all the ftp things
*
*@author     Alexander Kout
*@created    30. M�rz 2002
*/

public class Ftp
     extends Thread {

  private boolean isPRETCapable = true;
  wlPanel panel;

  String host, user, pass;
  int port;
  // current Directory
  String pwd;

  String getReplyMsg, getReplyMultiLine;

  // MainSocket
  SSLSocketChannel sc = null;
//  Socket socket = null;
//  OutputStream out = null;

  getReplyThread gThread;

  InetAddress localAddress;

  Vector cmd;

  boolean connected;
  String transferMode = "";

  boolean quitting;
  boolean proxy;

  boolean abortConnect;

  // temporary
  long size;

  /**
   *  Description of the Field
   */
  public volatile long rest;

  int retrycount, retrydelay;

  long timeout;

  Hashtable cache;

  boolean aborted;

  // nio stuff
  // Charset and decoder
  private Charset charset;
  private CharsetDecoder decoder;
  private CharsetEncoder encoder;
  // Direct byte buffer for reading
  private ByteBuffer dbuf = ByteBuffer.allocateDirect(65536);
  private ByteBuffer ubuf = ByteBuffer.allocateDirect(8192);
 
//  private ByteBuffer clientIn, clientOut, cTOs, sTOc;
//  SSLEngineResult res;
//  SSLEngine sslEngine;
  int SSL;
  boolean PROT, PROTdata, PROTlist;

  private CharBuffer cbuf = CharBuffer.allocate(4096);
 
  private CRC32 crc;
  private byte[] crcbuffer = new byte[65536];
  public boolean computeCRC;
  private Hashtable crcCache;


  /**
   *  Constructor for the Ftp object
   *
   *@param  panel   the parent panel
   *@param  server  Description of the Parameter
   */
  public Ftp(wlPanel panel, FtpServer server) {
    super();
    crc = new CRC32();
    crcCache = new Hashtable();
    charset = Charset.forName(panel.getFrame().locale());
    decoder = charset.newDecoder();
    encoder = charset.newEncoder();

    this.host = server.getHost();
    if (server.getPort() == 0) {
      port = 21;
    } else {
      port = server.getPort();
    }
    this.user = server.getUser();
    this.pass = server.getPasswd();
    this.panel = panel;
    if (server.getRetryCount() != -1) {
      retrycount = server.getRetryCount();
    } else {
      retrycount = panel.getFrame().retrycount();
    }
    if (server.getRetryDelay() != -1) {
      retrydelay = server.getRetryDelay();
    } else {
      retrydelay = panel.getFrame().retrydelay();
    }
    SSL = server.getSSL();
    PROTdata = server.getPROTdata();
    PROTlist = server.getPROTlist();
    timeout = panel.getFrame().getTimeout() * 1000;
    cmd = new Vector();
    cache = new Hashtable();
  }


  /**
   *  Gets the connected attribute of the Ftp object
   *
   *@return    The connected value
   */
  public boolean isConnected() {
    if (!connected) {
      return false;
    }
    return sc.isConnected();
  }


  /**
   *  checks if the reply thread has some new lines
   *
   *@return                  The reply value
   *@exception  IOException  Description of Exception
   */
  public int getReply() throws IOException {
    gThread.start = System.currentTimeMillis();
    while (gThread.ret == 0) {
      try {
        sleep(50);
      } catch (InterruptedException e) {}
    }
    getReplyMsg = gThread.line;
    getReplyMultiLine = gThread.lines;
    int ret = gThread.ret;
    Utilities.print("ret = " + ret + "\n");
    gThread.ret = 0;
    gThread.start = 0;
    return ret;
  }


  /**
   *  gets the current directory
   *
   *@exception  IOException  Description of Exception
   */
  public void getPwd() throws IOException {
    try {
      doCmd("PWD");
      String output = getReplyMsg;
      while (output.length() < 6
           || output.substring(5, output.length()).indexOf("\"") == -1) {
        getReply();
        output = getReplyMsg;
      }
      // put it into the var pwd
      String tmppwd = output.substring(5, output.length());
      pwd = tmppwd.substring(0, tmppwd.indexOf("\""));
      // change vars in list and ftpSession
      panel.setFtpDir(pwd);
    } catch (CharacterCodingException e) {
      panel.getFrame().getStatusArea().append(e + "\n", panel.getColor());
    }
  }


  /**
   *  Gets the transferRate attribute of the Ftp object
   *
   *@param  time  Description of Parameter
   *@param  size  Description of Parameter
   */
  public void getTransferRate(long time, long size) {
    double secs = time / 1000.0;
    double rate = size / secs;
    StringBuffer t = new StringBuffer(100);
    t.append(Utilities.humanReadableTime(secs)).
        append(" size: ").
        append(Utilities.humanReadable(size)).
        append(" rate: ").
        append(Utilities.humanReadable(rate)).
        append("/s\n");
    panel.getFrame().getStatusArea().append(t.toString(), "darkred");
  }


  /**
   *  Main processing method for the Ftp object
   */
  public void run() {
    proxy = false;
    panel.getFrame().setAbort(false);
    for (int i = 0; !abortConnect && i < retrycount && !isConnected() && !(i == 1 && !panel.getFrame().autoreconnect()) && !quitting && panel.getFtpSession().ftp != null; i++) {
      try {
        connect();
      } catch (Exception e) {
        if (Utilities.debug) {
          e.printStackTrace(System.err);
        }
        Utilities.saveStackTrace(e);
        panel.getFrame().getStatusArea().append(e + "\n", "red");
        try {
          if (sc != null) {
            sc.close();
          }
        } catch (IOException ex) {
          System.err.println("sc close failed!");
        }
        if (panel.getFrame().autoreconnect() &&
            !panel.getFtpSession().connected() &&
            !quitting) {
          panel.getFrame().getStatusArea().append(host + " connection lost #" + (i + 1) + ".\nreconnecting in " + retrydelay + " secs.\n", "red");
          try {
            Thread.sleep(retrydelay * 1000);
          } catch (InterruptedException ie) {}
        }
      }
    }
    if (!isConnected()) {
      if (panel.getFrame().getTm() != null) {
        panel.getFrame().setAbort(true);
        synchronized (panel.getFrame().getTm().done) {
          panel.getFrame().getTm().done.notify();
        }
        synchronized (panel.getFrame().getTm().connect) {
          panel.getFrame().getTm().connect.notify();
        }
      }
      return;
    }
    try {
      if (!abortConnect) {
        doList(false);
      }
    } catch (IOException e) {
      e.printStackTrace(System.err);
      Utilities.saveStackTrace(e);
      panel.getFrame().getStatusArea().append(e + "\n", "red");
      try {
        sc.close();
        quit(false);
      } catch (IOException ex) {}
    }
    if (panel.getFrame().getTm() != null) {
      synchronized (panel.getFrame().getTm().done) {
        panel.getFrame().getTm().done.notify();
      }
      synchronized (panel.getFrame().getTm().connect) {
        panel.getFrame().getTm().connect.notify();
      }
    }
    // start
    String command;
    long noopTime;
    long frameNoopTime;
    while (connected) {
      if (panel.getFrame().isNOOP()) {
        noopTime = System.currentTimeMillis();
        frameNoopTime = panel.getFrame().getNoopTime() * 1000;
        while (cmd.isEmpty()) {
          try {
            Thread.sleep(50);
          } catch (InterruptedException e) {}
          if ((System.currentTimeMillis() - noopTime) > frameNoopTime) {
            if (panel.getFrame().getIdleAction().equals("NOOP")) {
              cmd.addElement("NOOP");
            } else if (panel.getFrame().getIdleAction().equals("PWD")) {
              cmd.addElement("PWD");
            } else if (panel.getFrame().getIdleAction().equals("LIST")) {
              cmd.addElement("list");
            } else if (panel.getFrame().getIdleAction().equals("CWD .")) {
              cmd.addElement("CWD .");
            }
          }
        }
        command = (String) cmd.firstElement();
        cmd.removeElementAt(0);
      } else {
        synchronized (cmd) {
          if (cmd.isEmpty()) {
            try {
              cmd.wait();
            } catch (InterruptedException e) {}
          }
          command = (String) cmd.firstElement();
          cmd.removeElementAt(0);
        }
      }
      aborted = false;
      panel.getFrame().setAbort(false);
      try {
        if (command.equals("quit")) {
          quit(true);
        } else if (command.equals("connect")) {
          proxy = false;
          connect();
        } else if (command.startsWith("changeDir")) {
          changeDir(command.substring(10, command.length()), true);
        } else if (command.equals("cdup")) {
          cdup();
        } else if (command.startsWith("cmd")) {
          doCmd(command.substring(4, command.length()));
        } else if (command.equals("list")) {
          doList(false);
        } else if (command.equals("download")) {
          Transfer transfer = (Transfer) cmd.firstElement();
          cmd.removeElementAt(0);
          FtpFile from = transfer.getSource();
          FtpFile to = transfer.getDest();
          if (from.isDirectory()) {
  //          new File(to.getAbsolutePath()).mkdir();
            panel.getFrame().getQueueList().removeFirst();
            panel.getFrame().getQueueList().updateView();
            //    panel.getOtherPanel().list.updateView();
            if(changeDir(from.getAbsolutePath(), true)) {
              Vector files = panel.getFiles();
              if (files.size() > 0 || !panel.getFrame().skiplist() || !panel.getFrame().skipEmptyDir())
                new File(to.getAbsolutePath()).mkdir();
              else
                panel.getFrame().getStatusArea().append("Skipped " + from.getName() + "\n", "red");
              for (int i = files.size() - 1; i >= 0; i--) {
                FtpFile tmp = new FtpFile(((FtpFile) files.elementAt(i)).getName());
                tmp.setFtpMode(false);
                tmp.setAbsolutePath(to.getAbsolutePath() + File.separator + ((FtpFile) files.elementAt(i)).getName());
                panel.getFrame().getQueueList().addAtBegin(new Transfer(((FtpFile) files.elementAt(i)), tmp, panel.getMode(), panel.getOtherPanel().getMode(), panel.getPosition(), panel.getFtpSession().currentServer, null));
              }
            }
            panel.getFrame().getQueueList().updateView();
          } else {
            if (!panel.getDir().equals(from.getParent())) {
              changeDir(from.getParent(), true);
            }
            if (!panel.getOtherPanel().getDir().equals(to.getParent())) {
              panel.getOtherPanel().setDir(to.getParent());
            }
            // temporary!
            this.size = from.getSize();

            if (new File(to.getAbsolutePath()).exists()) {
              to.setSize(new File(to.getAbsolutePath()).length());
              transfer = new Transfer(from, to, panel.getMode(), panel.getOtherPanel().getMode(), panel.getPosition(), panel.getFtpSession().currentServer, null);
            }
            // resume ?
            rest = 0;
            String[] fileExist = panel.getFrame().getFileExist();
            if (to.getSize() > 0 && to.getSize() == from.getSize()) {
              if (fileExist[3].equals("auto skip"))
                rest = -1;
              else if (fileExist[3].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[3].equals("ask"))
                panel.newResumeDialog(transfer);
            } else if (to.getSize() > 0 && to.getSize() > from.getSize()) {
              if (fileExist[6].equals("auto skip"))
                rest = -1;
              else if (fileExist[6].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[6].equals("ask"))
                panel.newResumeDialog(transfer);
            } else if (to.getSize() > 0) {
              if (fileExist[0].equals("auto skip"))
                rest = -1;
              else if (fileExist[0].equals("auto resume"))
                rest = to.getSize();
              else if (fileExist[0].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[0].equals("ask"))
                panel.newResumeDialog(transfer);
            }

            // download
            if (rest != -1) {
              if (!transferMode.equals("BINARY")) {
                doCmd("TYPE I");
                transferMode = "BINARY";
              }
              if (download("RETR ", from, to) && !panel.getFrame().abort()) {
                panel.getFrame().getQueueList().removeFirst();
                panel.getFrame().getQueueList().updateView();
                testSFV(to);
              }
            } else {
              panel.getFrame().getStatusArea().append("Skipped " + from.getName() + "\n", "red");
              panel.getFrame().getQueueList().removeFirst();
              panel.getFrame().getQueueList().updateView();
            }
          }
          rest = 0;
      //    panel.getOtherPanel().updateView();
      //    panel.getOtherPanel().addElement(to);
          while (!panel.getFrame().getTm().waiting) {
            Thread.sleep(10);
          }
          synchronized (panel.getFrame().getTm().done) {
            panel.getFrame().getTm().done.notify();
          }
          Utilities.print("tm notified\n");
        } else if (command.equals("upload")) {
          Transfer transfer = (Transfer) cmd.firstElement();
          cmd.removeElementAt(0);
          FtpFile from = transfer.getSource();
          FtpFile to = transfer.getDest();
          if (from.isDirectory()) {
  //          doCmd("MKD " + to.getAbsolutePath());
            panel.getFrame().getQueueList().removeFirst();
            panel.getFrame().getQueueList().updateView();
            cache.remove(panel.getDir());
            panel.getOtherPanel().setDir(from.getAbsolutePath());
            //
            FtpFile[] files = from.list();
            if (files.length > 0 || !panel.getFrame().skiplist() || !panel.getFrame().skipEmptyDir())
              doCmd("MKD " + to.getAbsolutePath());
            else
              panel.getFrame().getStatusArea().append("Skipped " + from.getName() + "\n", "red");
            for (int i = files.length - 1; i >= 0; i--) {
              FtpFile tmp = new FtpFile(files[i].getName());
              tmp.setAbsolutePath(to.getAbsolutePath() + "/" + files[i].getName());
              panel.getFrame().getQueueList().addAtBegin(new Transfer(files[i], tmp, panel.getOtherPanel().getMode(), panel.getMode(), panel.getOtherPanel().getPosition(), null, panel.getFtpSession().currentServer));
            }
            panel.getFrame().getQueueList().updateView();
          } else {
            if (!panel.getDir().equals(to.getParent())) {
              changeDir(to.getAbsolutePath().substring(0, to.getAbsolutePath().lastIndexOf("/")), false);
            }
            if (!panel.getOtherPanel().getDir().equals(from.getParent())) {
              panel.getOtherPanel().setDir(from.getParent());
            }
            // temporary!
            this.size = from.getSize();

            Vector files = panel.getFiles();
            for (int i = 0; i < files.size(); i++) {
              if (to.getName().equals(((FtpFile) files.elementAt(i)).getName())) {
                to.setSize(((FtpFile) files.elementAt(i)).getSize());
                transfer = new Transfer(from, to, panel.getOtherPanel().getMode(), panel.getMode(), panel.getOtherPanel().getPosition(), null, panel.getFtpSession().currentServer);
                break;
              }
            }
            // resume ?
            rest = 0;
            String[] fileExist = panel.getFrame().getFileExist();
            if (to.getSize() > 0 && to.getSize() == from.getSize()) {
              if (fileExist[4].equals("auto skip"))
                rest = -1;
              else if (fileExist[4].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[4].equals("ask"))
                panel.newResumeDialog(transfer);
            } else if (to.getSize() > 0 && to.getSize() > from.getSize()) {
              if (fileExist[7].equals("auto skip"))
                rest = -1;
              else if (fileExist[7].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[7].equals("ask"))
                panel.newResumeDialog(transfer);
            } else if (to.getSize() > 0) {
              if (fileExist[1].equals("auto skip"))
                rest = -1;
              else if (fileExist[1].equals("auto resume"))
                rest = to.getSize();
              else if (fileExist[1].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[1].equals("ask"))
                panel.newResumeDialog(transfer);
            }

            // upload
            if (rest != -1) {
              if (!transferMode.equals("BINARY")) {
                doCmd("TYPE I");
                transferMode = "BINARY";
              }
              if (upload("STOR ", from, to) && !panel.getFrame().abort()) {
                panel.getFrame().getQueueList().removeFirst();
                panel.getFrame().getQueueList().updateView();
                cache.remove(to.getParent());
              }
            } else {
              panel.getFrame().getStatusArea().append("Skipped " + from.getName() + "\n", "red");
              panel.getFrame().getQueueList().removeFirst();
              panel.getFrame().getQueueList().updateView();
            }
          }
          rest = 0;
          //    doList();
      //    panel.addElement(to);
          while (!panel.getFrame().getTm().waiting) {
            Thread.sleep(10);
          }
          synchronized (panel.getFrame().getTm().done) {
            panel.getFrame().getTm().done.notify();
          }
        } else if (command.startsWith("MKD")) {
          doCmd(command);
          doList(false);
        } else if (command.equals("fxp")) {
          Transfer transfer = (Transfer) cmd.firstElement();
          cmd.removeElementAt(0);
          FtpFile from = transfer.getSource();
          FtpFile to = transfer.getDest();
          if (from.isDirectory()) {
  //          panel.getOtherPanel().getFtpSession().ftp.doCmd("MKD " + to.getAbsolutePath());
            panel.getFrame().getQueueList().removeFirst();
            panel.getFrame().getQueueList().updateView();
            panel.getOtherPanel().getFtpSession().ftp.cache.remove(to.getParent());
            changeDir(from.getAbsolutePath(), true);
            Vector files = panel.getFiles();
            //
            if (files.size() > 0 || !panel.getFrame().skiplist() || !panel.getFrame().skipEmptyDir())
              panel.getOtherPanel().getFtpSession().ftp.doCmd("MKD " + to.getAbsolutePath());
            else
              panel.getFrame().getStatusArea().append("Skipped " + from.getName() + "\n", "red");
            for (int i = files.size() - 1; i >= 0; i--) {
              FtpFile tmp = new FtpFile(((FtpFile) files.elementAt(i)).getName());
              tmp.setAbsolutePath(to.getAbsolutePath() + "/" + ((FtpFile) files.elementAt(i)).getName());
              panel.getFrame().getQueueList().addAtBegin(new Transfer(((FtpFile) files.elementAt(i)), tmp, panel.getMode(), panel.getOtherPanel().getMode(), panel.getPosition(), panel.getFtpSession().currentServer, panel.getOtherPanel().getFtpSession().currentServer));
            }
            panel.getFrame().getQueueList().updateView();
          } else {
            if (!panel.getDir().equals(from.getParent())) {
              changeDir(from.getParent(), true);
            }
            if (!panel.getOtherPanel().getDir().equals(to.getParent())) {
              panel.getOtherPanel().getFtpSession().ftp.changeDir(to.getParent(), false);
            }
            panel.getOtherPanel().getFtpSession().ftp.size = from.getSize();

            Vector files = panel.getOtherPanel().getFiles();
            for (int i = 0; i < files.size(); i++) {
              if (to.getName().equals(((FtpFile) files.elementAt(i)).getName())) {
                to.setSize(((FtpFile) files.elementAt(i)).getSize());
                transfer = new Transfer(from, to, panel.getMode(), panel.getOtherPanel().getMode(), panel.getPosition(), panel.getFtpSession().currentServer, panel.getOtherPanel().getFtpSession().currentServer);
                break;
              }
            }
            // resume ?
            rest = 0;
            String[] fileExist = panel.getFrame().getFileExist();
            if (to.getSize() > 0 && to.getSize() == from.getSize()) {
              if (fileExist[5].equals("auto skip"))
                rest = -1;
              else if (fileExist[5].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[5].equals("ask"))
                panel.newResumeDialog(transfer);
            } else if (to.getSize() > 0 && to.getSize() > from.getSize()) {
              if (fileExist[8].equals("auto skip"))
                rest = -1;
              else if (fileExist[8].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[8].equals("ask"))
                panel.newResumeDialog(transfer);
            } else if (to.getSize() > 0) {
              if (fileExist[2].equals("auto skip"))
                rest = -1;
              else if (fileExist[2].equals("auto resume"))
                rest = to.getSize();
              else if (fileExist[2].equals("auto overwrite"))
                rest = 0;
              else if (fileExist[2].equals("ask"))
                panel.newResumeDialog(transfer);
            }

            if (rest != -1) {
              if (fxp(from, to, false) > 3) {
                if (panel.getOtherPanel().getFtpSession().ftp.fxp(from, to, true) > 3) {
                  panel.getFrame().getStatusArea().append("transfer failed\n", "red");
                }
              }
              panel.getFrame().getQueueList().removeFirst();
              panel.getFrame().getQueueList().updateView();
              panel.getOtherPanel().getFtpSession().ftp.cache.remove(to.getParent());
            } else {
              panel.getFrame().getStatusArea().append("Skipped " + from.getName() + "\n", "red");
              panel.getFrame().getQueueList().removeFirst();
              panel.getFrame().getQueueList().updateView();
            }
          }

      //    panel.getOtherPanel().addElement(to);
          while (!panel.getFrame().getTm().waiting) {
            Thread.sleep(10);
          }
          synchronized (panel.getFrame().getTm().done) {
            panel.getFrame().getTm().done.notify();
          }
        } else if (command.equals("delete")) {
          Vector v = (Vector) cmd.firstElement();
          cmd.removeElementAt(0);
          while (!v.isEmpty() && !panel.getFrame().abort()) {
            FtpFile f = (FtpFile) v.firstElement();
            v.removeElementAt(0);
            if (!f.isDirectory()) {
              if (!panel.getDir().equals(f.getParent())) {
                changeDir(f.getParent(), false);
              }
              if (doCmd("DELE " + f.getName()) < 4)
                panel.removeElement(f);
            } else if (f.isDirectory()) {
              if (recursiveDelete(f)) {
                panel.removeElement(f);
              }
            }
            cache.remove(f.getParent());
          }
        //  panel.updateView();
          panel.lightUpdateView();
        } else {
          doCmd(command);
        }
      } catch (Exception e) {
        e.printStackTrace(System.err);
        Utilities.saveStackTrace(e);
        synchronized (panel.getFrame().getTm().done) {
            panel.getFrame().getTm().done.notify();
        }
        panel.getFrame().getStatusArea().append(e + "\n", "red");
        try {
          sc.close();
          quit(false);
        } catch (IOException ex) {}
        //    sc = null;
        // if problem with sending data reconnect
        if (!quitting) {
          panel.getFtpSession().abortReconnect = false;
          if (panel.getFrame().autoreconnect() && !panel.getFtpSession().connected()) {
            panel.getFrame().getStatusArea().append("connection lost.\nreconnecting in " + retrydelay + " secs.\n", "red");
            try {
              Thread.sleep(retrydelay * 1000);
            } catch (InterruptedException ie) {}
            if (!panel.getFtpSession().connected() && !panel.getFtpSession().abortReconnect) {
              panel.getFtpSession().connect(panel.getFtpSession().currentServer);
            }
          }
        }
      }
      try {
        sleep(50);
      } catch (InterruptedException e) {}
    }
  }


  /**
   *  Adds a feature to the Command attribute of the Ftp object
   *
   *@param  command  The feature to be added to the Command attribute
   */
  public void addCommand(String command) {
    synchronized (cmd) {
      cmd.addElement(command);
      cmd.notify();
    }
  }


  /**
   *  Adds a feature to the Transfer attribute of the Ftp object
   *
   *@param  command  The feature to be added to the Transfer attribute
   *@param  t        The feature to be added to the Transfer attribute
   */
  public void addTransfer(String command, Transfer t) {
    synchronized (cmd) {
      cmd.addElement(command);
      cmd.addElement(t);
      cmd.notify();
    }
  }


  /**
   *  recursive delete a dir
   *
   *@param  dir              Description of the Parameter
   *@exception  IOException  Description of the Exception
   */
  protected boolean recursiveDelete(FtpFile dir) throws IOException {
    if (panel.getFrame().abort()) {
      return false;
    }
    changeDir(dir.getAbsolutePath(), true);
    Vector files = panel.getFiles();
    FtpFile ftpfile;
    while (!files.isEmpty() && !panel.getFrame().abort()) {
      ftpfile = (FtpFile) files.firstElement();
      files.removeElementAt(0);
      if (!ftpfile.isDirectory()) {
        doCmd("DELE " + ftpfile.getName());
      } else {
        recursiveDelete(ftpfile);
      }
    }
    if (panel.getFrame().abort()) {
      return false;
    }
    changeDir(dir.getParent(), true);
    cache.remove(dir.getAbsolutePath());
    if (doCmd("RMD " + dir.getName()) < 4)
      return true;
    return false;
  }


  /**
   *  Description of the Method
   *
   *@param  useCache         Description of the Parameter
   *@exception  IOException  Description of Exception
   */
  public void doList(boolean useCache) throws IOException {
    if (panel.getFrame().cache() && useCache && cache.containsKey(panel.getDir())) {
      panel.updateFtpView((String) cache.get(panel.getDir()));
    } else {
      if (!transferMode.equals("ASCII")) {
        doCmd("TYPE A");
        transferMode = "ASCII";
      }
      panel.updateFtpView(list("LIST -aL"));
    }
  }


  /**
   *  connects to host and makes login, pwd
   *
   *@exception  Exception    Description of the Exception
   */
  public void connect() throws Exception {
    panel.getFrame().getStatusArea().append("Connecting to: " + host + "\n", panel.getColor());
    connectToServer();
    if (!abortConnect && getReply() > 3) {
      quit(false);
      throw new Exception("Server REPLY");
    }
    if (!abortConnect && login() > 3) {
      quit(false);
      throw new Exception("LOGIN");
    }
    if (!abortConnect && SSL == 4) {
      doCmd("PBSZ 0");
      if (doCmd("PROT C") > 4) {
        PROT = true;
        PROTdata = true;
        PROTlist = true;
        doCmd("PROT P");
      }
    }
    if (!abortConnect) {
      getPwd();
    }
    if (!abortConnect) {
      if (!panel.getFtpSession().currentServer.getPath().equals("") && !panel.getDir().equals(panel.getFtpSession().currentServer.getPath())) {
        doCmd("CWD " + panel.getFtpSession().currentServer.getPath());
        getPwd();
      }
    }
//    panel.dirLabel.setText(panel.getDir());
  }


  /**
   *  is called by connect to make a new SocketChannel it also gets the
   *  localAddress for later
   *
   *@exception  IOException  Description of Exception
   */
  public void connectToServer() throws IOException {
    if (panel.getFrame().isProxy()) {
      sc = (SSLSocketChannel) panel.getFrame().proxyConnect(host, port, true);
      proxy = true;
    } else {
      InetSocketAddress isa = new InetSocketAddress(
          InetAddress.getByName(host), port);
      // Connect
    /*  socket = new Socket();
      socket.setSoTimeout((int) timeout);
      socket.connect((SocketAddress) isa, (int) timeout);
    */ 
      sc = new SSLSocketChannel();
      sc.configureBlocking(false);
      sc.connect(isa);
      long start = System.currentTimeMillis();
      while (!sc.finishConnect() && !abortConnect) {
        if ((System.currentTimeMillis() - start) > timeout)
          throw new IOException("connect timed out");
        try {
        Thread.sleep(20);
        } catch (InterruptedException e) {}
      }
    }
    if (!abortConnect) {
      localAddress = sc.socket().getLocalAddress();
      gThread = new getReplyThread(panel, sc);
    //  out = socket.getOutputStream();
      connected = true;
    } else if (sc != null) { // sc.socket() != null ?????
      quit(false);
    }
  }
 

  /**
   *  sends the USER PASS sequence
   *
   *@return                  Description of the Returned Value
   *@exception  IOException  Description of Exception
   */
  public int login() throws IOException {
    if (SSL > 0) {
      if (SSL == 3) {
        if (doCmd("AUTH TLS") > 3)
          SSL = 0;
      } else if (SSL == 1) {
        if (doCmd("AUTH SSL") > 3)
          SSL = 0;
      }
      gThread.wait = true;
      SSL = sc.tryTLS(SSL);
      gThread.wait = false;
    }
    String msg = "USER " + user;
    int ret;
    if ((ret = doCmd(msg)) > 3) {
      return ret;
    }
    if (ret == 2) {
      return 2;
    }
    String[] challenge = new String[2];
    int type;
    if ((type = testOTP(getReplyMultiLine, challenge)) > 0) {
      Utilities.print("Challenge is: "+challenge[0]+" "+challenge[1]+"\n");
      msg = "PASS " + jotp.computeOTP(challenge[0], challenge[1], pass, type);
    } else
      msg = "PASS " + pass;
    return doCmd(msg);
  }
 
  private int testOTP(String msg, String[] challenge) {
    String[] lines = Utilities.split(msg, "\r\n");
    for (int i = 0; i < lines.length; i++) {
      String[] t = Utilities.split(lines[i], " ");
      for (int k = 1; k < t.length; k++) {
        try {
        if (Pattern.matches("[0-9]+", t[k])) {
          challenge[0] = t[k];
          challenge[1] = t[k+1];
          if (lines[i].indexOf("md4") != -1)
            return 4;
          else
            return 5;
        }
        } catch (Exception e) {}
      }
    }
    return -1;
  }


  /**
   *  sends a command and calls getReply
   *
   *@param  cmd              the command without <CR>
   *@return                  Description of the Returned Value
   *@exception  IOException  Description of Exception
   */
  public int doCmd(String cmd) throws IOException {
    gThread.ret = 0;
    if (cmd.startsWith("PASS")) {
      panel.getFrame().getStatusArea().append("PASS\n", "black");
    } else {
      panel.getFrame().getStatusArea().append(cmd + "\n", "black");
    }
  //  out.write((cmd + "\r\n").getBytes());
    cbuf.clear();
    cbuf.put(cmd + "\r\n");
    cbuf.flip();
    sc.write(encoder.encode(cbuf));
    cbuf.clear();
    Utilities.print(cmd + "\r\n");
    return getReply();
  }


  /**
   *  sends the import IP Sync senquence
   *
   *@exception  IOException  Description of the Exception
   */
  private void ipSync() throws IOException {
    if (SSL == 0) {
      byte[] b = new byte[2];
      b[0] = -1;
      b[1] = -12;
      cbuf.clear();
      cbuf.put((char) 255);
      cbuf.put((char) 244);
      cbuf.flip();
      sc.write(encoder.encode(cbuf));
      cbuf.clear();
  //    sc.socket().sendUrgentData(255);
  //    sc.socket().sendUrgentData(242);
      // sync (DM)
    }
  }


  /**
   *  sends IpSync and ABOR
   *
   *@exception  IOException  Description of the Exception
   */
  public void abort() throws IOException {
//    gThread.ret = 0;
    panel.getFrame().setAbort(true);
    ipSync();
    send("ABOR");
    aborted = true;
  /*  panel.getFrame().getStatusArea().append("ABOR\n", "black");
    aborted = true;
    cbuf.clear();
    cbuf.put("ABOR\r\n");
    cbuf.flip();
    sc.write(encoder.encode(cbuf));
    cbuf.clear();
    Utilities.print("ABOR\n"); */
//    getReply();
  }


  /**
   *  Description of the Method
   *
   *@param  dir              Description of Parameter
   *@exception  IOException  Description of Exception
   */
  public boolean changeDir(String dir, boolean useCache) throws IOException {
    int ret = doCmd("CWD " + dir);
    getPwd();
    doList(useCache);
    return ret == 2;
  }


  /**
   *  Description of the Method
   *
   *@exception  IOException  Description of Exception
   */
  public void cdup() throws IOException {
    doCmd("CDUP");
    getPwd();
    doList(true);
  }


  /**
   *  does command "quit" and closes the SocketChannel
   *  if necessary it does a IpSync
   *
   *@exception  IOException  Description of Exception
   */
  public void quit(boolean block) throws IOException {
    quitting = true;
    Utilities.print("quitting...\n");
    connected = false;
    if (panel.getFtpSession().ftp == this) {
      // change vars in list and ftpSession
      panel.setFtpDir(" ");
      panel.updateFtpView("");
    }
    if (sc != null) {
      if (sc.isConnected()) {
        if (panel.getFrame().getTm() != null
            && panel.getFrame().getTm().waiting) {
          ipSync();
        }
        try {
          if (block)
            doCmd("QUIT");
          else
            send("QUIT");
        } catch (IOException e) {}
        if (gThread != null) {
          gThread.quit = true;
        }
        sc.close();
        Utilities.print("socket closed: " + host + "\n");
      }
    }
  }


  /**
   *  Description of the Method
   *
   *@param  v  Description of the Parameter
   */
  public void delete(Vector v) {
    synchronized (cmd) {
      cmd.addElement("delete");
      cmd.addElement(v);
      cmd.notify();
    }
  }
 
  private void configurePROT(boolean PROTx) throws IOException {
    if (PROTx && !PROT) {
      if (doCmd("PROT P") < 4)
        PROT = true;
      else {
        PROTdata = false;
        PROTlist = false;
      }
    } else if (!PROTx && PROT) {
      if (doCmd("PROT C") < 4)
        PROT = false;
      else {
        PROTdata = true;
        PROTlist = true;
      }
    }
  }


  /**
   *  lists the content of the current directory
   *
   *@param  command          Description of Parameter
   *@return                  Description of the Returned Value
   *@exception  IOException  Description of Exception
   */
  public String list(String command) throws IOException {
    configurePROT(PROTlist);
    SSLSocketChannel sc = null;
    if (panel.getFrame().passive()) {
      sc = doPASV(command);
    } else {
      sc = acceptConnection(command);
    }
    // i.e. connection not accepted
    if (sc == null) {
      return "";
    }
    if (PROTlist)
      sc.tryTLS(3);
    StringBuffer output = new StringBuffer(32000);
    int amount;
    dbuf.clear();
    long start = System.currentTimeMillis();
    CharBuffer cb;
    while ((amount = sc.read(dbuf)) != -1 && !aborted) {
      if (amount == 0) {
        if ((System.currentTimeMillis() - start) > timeout) {
          break;
        }
        try {
          Thread.sleep(5);
        } catch (InterruptedException e) {}
      } else {
        start = System.currentTimeMillis();
      }

      dbuf.flip();
      cb = decoder.decode(dbuf);
      output.append(cb);
      dbuf.clear();
    }
    if (aborted) {
      output.delete(0, output.length());
      aborted = false;
      for (int i = 0; i < 10 && gThread.ret == 0; i++) {
        try {
          sleep(50);
        } catch (InterruptedException e) {}
      }
    }
    //  Utilities.print(output);
    sc.close();
  //  getReply();
    gThread.ret = 0;
    cache.put(panel.getDir(), output.toString());
    if (Utilities.debug)
      Utilities.print(output.toString());
    return output.toString();
  }


  /**
   *  Description of the Method
   *
   *@param  command          Description of Parameter
   *@param  from             Description of the Parameter
   *@param  to               Description of the Parameter
   *@return                  Description of the Return Value
   *@exception  IOException  Description of Exception
   */
  public boolean download(String command, FtpFile from, FtpFile to) throws IOException {
    configurePROT(PROTdata);
    crc.reset();
    if (crcCache.containsKey(from.getName()))
      computeCRC = true;
    else
      computeCRC = false
    SSLSocketChannel sc = null;
    boolean append = false;
    if (panel.getFrame().passive()) {
      sc = doPASV(command + from.getName());
    } else {
      sc = acceptConnection(command + from.getName());
    }
    Date d1 = new Date();
    // i.e. connection not accepted
    if (sc == null) {
      return true;
    }
    if (PROTdata)
      sc.tryTLS(3);
    // Open the file and then get a channel from the stream
    if (rest > 0) {
      append = true;
    }
    /*
     *  FileOutputStream fos = new FileOutputStream(
     *  new File(
     *  panel.getOtherPanel().getDir() +
     *  File.separator +
     *  command.substring(5, command.length())), append);
     */
    FileOutputStream fos = new FileOutputStream(
        panel.getOtherPanel().getDir() +
        File.separator +
        to.getName(), append);
    FileChannel fc = fos.getChannel();
    int amount;
    dbuf.clear();
    long size = rest;
    Date d3 = new Date();
    long diffSize = 0;
    long diffTime = 0;
    boolean ret = true;
    long start = System.currentTimeMillis();
    long elapsedStart = start;
    try {
      while ((amount = sc.read(dbuf)) != -1 && !aborted) {
        if (amount == 0) {
          if ((System.currentTimeMillis() - start) > timeout) {
            break;
          }
          try {
            Thread.sleep(4);
          } catch (InterruptedException e) {}
        } else {
          start = System.currentTimeMillis();
        }
        size += amount;
        diffSize += amount;
        if ((diffTime = System.currentTimeMillis() - d3.getTime()) > 1000) {
          panel.getFrame().setStatusBar(from.getName(), from.getSize(), diffSize / (diffTime / 1000.0), size, (System.currentTimeMillis() - elapsedStart) / 1000);
        //  panel.getFrame().setPBar((int) (size * 100 / this.size));
          String perf = Utilities.humanReadable(size) + "@" + Utilities.humanReadable(diffSize / (diffTime / 1000.0)) + "/s";
        //  panel.getFrame().setStatusLabel(perf, (from.getSize()-size) / (diffSize/(diffTime / 1000.0)) );
       
          panel.getFrame().setTitle(perf);
          diffSize = 0;
          diffTime = 0;
          d3 = new Date();
        }
        if (dbuf.remaining() > 0) {
          continue;
        }
        dbuf.flip();
        // write into file
        fc.write(dbuf);
        crcUpdate();
        dbuf.clear();
      }
      dbuf.flip();
      // write rest into file
      fc.write(dbuf);
      crcUpdate();
      dbuf.clear();
    } catch (IOException e) {
      e.printStackTrace(System.err);
      Utilities.saveStackTrace(e);
      ret = false;
    }
    if (aborted) {
      ret = false;
      aborted = false;
      for (int i = 0; i < 10 && gThread.ret == 0; i++) {
        try {
          sleep(50);
        } catch (InterruptedException e) {}
      }
    }
    if (size < from.getSize()) {
      ret = false;
    }
    Date d2 = new Date();
    panel.getFrame().setStatusBar("", 0, 0.0, 0, 0);
    panel.getFrame().setTitle("wlFxp");
    fc.force(true);
    fos.close();
    sc.close();
    if (computeCRC) {
      panel.getFrame().getStatusArea().append(to.getName()+" crc32: "+hexformat(crc.getValue(), 8), panel.getColor());
      if (crcCache.get(from.getName()).equals(hexformat(crc.getValue(), 8)))
        panel.getFrame().getStatusArea().append("checksum correct", panel.getColor());
      else
        panel.getFrame().getStatusArea().append("checksum incorrect", "red");
    }
  //  getReply();
    gThread.ret = 0;
    getTransferRate(d2.getTime() - d1.getTime(), size - rest);
    return ret;
  }


  /**
   *  Description of the Method
   *
   *@param  command          Description of Parameter
   *@param  from             Description of the Parameter
   *@param  to               Description of the Parameter
   *@return                  Description of the Return Value
   *@exception  IOException  Description of Exception
   */
  public boolean upload(String command, FtpFile from, FtpFile to) throws IOException {
    SSLSocketChannel sc = null;
    configurePROT(PROTdata);
    if (panel.getFrame().passive()) {
      sc = doPASV(command + to.getName());
    } else {
      sc = acceptConnection(command + to.getName());
    }
    Date d1 = new Date();
    // i.e. connection not accepted
    if (sc == null) {
      return true;
    }
    if (PROTdata)
      sc.tryTLS(3);
    // Open the file and then get a channel from the stream
    FileInputStream fis = new FileInputStream(
        new File(
        panel.getOtherPanel().getDir() +
        File.separator +
        from.getName()));
    FileChannel fc = fis.getChannel();
    if (rest > 0) {
      fc.position(rest);
    }
    int amount;
    ubuf.clear();
    long size = rest;
    Date d3 = new Date();
    long diffSize = 0;
    long diffTime = 0;
    boolean ret = true;
    int s_amount = 0;
    long start = System.currentTimeMillis();
    long elapsedStart = start;
    int i;
    try {
      bigwhile :
      while ((amount = fc.read(ubuf)) != -1 && !aborted) {
        ubuf.flip();
        start = System.currentTimeMillis();

        i = 0;
        while ((i = sc.write(ubuf)) != -1 && !aborted) {
          s_amount += i;
          size += i;
          diffSize += i;

          if ((diffTime = System.currentTimeMillis() - d3.getTime()) > 1000) {
            panel.getFrame().setStatusBar(from.getName(), from.getSize(), diffSize / (diffTime / 1000.0), size, (System.currentTimeMillis() - elapsedStart) / 1000);
            //panel.getFrame().setPBar((int) (size * 100 / this.size));
            String perf = Utilities.humanReadable(size) + "@" + Utilities.humanReadable(diffSize / (diffTime / 1000.0)) + "/s";
            //panel.getFrame().setStatusLabel(perf, (from.getSize()-size) / (diffSize/(diffTime / 1000.0)));
            panel.getFrame().setTitle(perf);
            diffSize = 0;
            diffTime = 0;
            d3 = new Date();
          }
          if (amount <= s_amount) {
            break;
          }
          if (i == 0) {
            if ((System.currentTimeMillis() - start) > timeout) {
              break bigwhile;
            } else {
              try {
                Thread.sleep(4);
              } catch (InterruptedException e) {}
            }
          } else {
            start = System.currentTimeMillis();
          }
        }
        if (i == -1) {
          break;
        }

        s_amount = 0;
        ubuf.clear();
      }
    } catch (IOException e) {
      //  e.printStackTrace(System.err);
      Utilities.saveStackTrace(e);
      ret = false;
    }
    if (aborted) {
      ret = false;
      for (int j = 0; j < 10 && gThread.ret == 0; j++) {
        try {
          sleep(50);
        } catch (InterruptedException e) {}
      }
    }
    if (size < from.getSize()) {
      ret = false;
    }
    panel.getFrame().setStatusBar("", 0, 0.0, 0, 0);
    panel.getFrame().setTitle("wlFxp");
    fis.close();
    sc.close();
    while (!aborted && gThread.ret == 0) {
      try {
        sleep(50);
      } catch (InterruptedException e) {}
    }
    gThread.ret = 0;
    aborted = false;
    //
    Date d2 = new Date();
    getTransferRate(d2.getTime() - d1.getTime(), size - rest);
    return ret;
  }


  /**
   *  Description of the Method
   *
   *@param  s                Description of the Parameter
   *@exception  IOException  Description of the Exception
   */
  public void send(String s) throws IOException {
    try {
      gThread.ret = 0;
      panel.getFrame().getStatusArea().append(s + "\n", "black");
      cbuf.clear();
      cbuf.put(s + "\r\n");
      cbuf.flip();
      sc.write(encoder.encode(cbuf));
      cbuf.clear();
      Utilities.print(s + "\r\n");
    } catch (NullPointerException e) {}
  }


  /**
   *  Description of the Method
   *
   *@param  from             Description of the Parameter
   *@param  to               Description of the Parameter
   *@param  alternative      Description of the Parameter
   *@return                  Description of the Return Value
   *@exception  IOException  Description of Exception
   */
  public int fxp(FtpFile from, FtpFile to, boolean alternative) throws IOException {
    if (!transferMode.equals("BINARY")) {
      doCmd("TYPE I");
      transferMode = "BINARY";
    }
    if (sendPRET("RETR "+from.getName()) > 3)
      return 5;
    if (doCmd("PASV") > 3) {
      return 5;
    }
    String output = getReplyMsg;
    if (output.indexOf("(") == -1 || output.indexOf(")") == -1)
      return 5;
    output = output.substring(output.indexOf("(") + 1, output.indexOf(")"));
    return panel.getOtherPanel().getFtpSession().ftp.receivefxp(output, from, to, alternative);
  }


  /**
   *  Description of the Method
   *
   *@param  output           Description of Parameter
   *@param  from             Description of the Parameter
   *@param  to               Description of the Parameter
   *@param  alternative      Description of the Parameter
   *@return                  Description of the Return Value
   *@exception  IOException  Description of Exception
   */
  public int receivefxp(String output, FtpFile from, FtpFile to, boolean alternative)
       throws IOException {
    if (!transferMode.equals("BINARY")) {
      doCmd("TYPE I");
      transferMode = "BINARY";
    }
    if (doCmd("PORT " + output) > 3) {
      return 5;
    }
    if (panel.getOtherPanel().getFtpSession().ftp.rest > 0) {
      panel.getOtherPanel().getFtpSession().ftp.doCmd("REST " + panel.getOtherPanel().getFtpSession().ftp.rest);
      doCmd("REST " + panel.getOtherPanel().getFtpSession().ftp.rest);
    }
    if (alternative) {
      if (doCmd("RETR " + from.getName()) < 4) {
        if (panel.getOtherPanel().getFtpSession().ftp.doCmd("STOR " + to.getName()) < 4) {
          while (gThread.ret == 0 && !panel.getFrame().abort()) {
            try {
              Thread.sleep(200);
            } catch (InterruptedException e) {}
          }
          if (panel.getFrame().abort() && !aborted) {
            abort();
            //    panel.getOtherPanel().getFtpSession().ftp.abort();
          }
        }
        gThread.ret = 0;
      }
    } else {
      Date d1 = new Date();
      if (doCmd("STOR " + to.getName()) < 4) {
        if (panel.getOtherPanel().getFtpSession().ftp.doCmd("RETR " + from.getName()) < 4) {
          while (gThread.ret == 0 && !panel.getFrame().abort()) {
            try {
              Thread.sleep(200);
            } catch (InterruptedException e) {}
          }
          if (panel.getFrame().abort() && !aborted) {
            //    panel.getOtherPanel().getFtpSession().ftp.abort();
            abort();
          }

          Date d2 = new Date();
          getTransferRate(d2.getTime() - d1.getTime(), size - rest);
        } else {
          return 5;
        }
        gThread.ret = 0;
      } else {
        return 5;
      }
    }
    return 0;
  }


  /**
   *  gets a SocketChannel for a datatransfer after some command is send
   *
   *@param  cmd              the command that needs a dataport
   *@return                  Description of the Returned Value
   *@exception  IOException  Description of Exception
   */
  public SSLSocketChannel acceptConnection(String cmd) throws IOException {
    ServerSocketChannel ssc = ServerSocketChannel.open();
    InetSocketAddress isa = new InetSocketAddress(localAddress, 0);
    InetAddress i;
    int port;
    SSLSocketChannel sc = null;
    if (proxy) {
      sc = panel.getFrame().proxyBind(isa);
      i = panel.getFrame().getProxyInetAddress();
      port = panel.getFrame().getProxyBindPort();
    } else {
      ssc.socket().bind(isa);
      i = ssc.socket().getInetAddress();
      port = ssc.socket().getLocalPort();
    }
    port(i, port);
    if (rest > 0) {
      if (doCmd("REST " + rest) > 3) {
        rest = 0;
      }
    }
    if (doCmd(cmd) > 3) {
      return null;
    }
    if (!proxy) {
      sc = new SSLSocketChannel(ssc.accept());
      while (!sc.finishConnect() && !abortConnect) {
        try {
          Thread.sleep(20);
        } catch (InterruptedException e) {}
      }
    }
    sc.socket().setReceiveBufferSize(65536);
    sc.socket().setSendBufferSize(65536);

    return sc;
  }


  /**
   *  sends a port command
   *
   *@param  inetaddress      Description of the Parameter
   *@param  localport        Description of the Parameter
   *@exception  IOException  Description of Exception
   */
  public void port(InetAddress inetaddress, int localport) throws IOException {
    // get ip address in high byte order
    byte[] addrbytes = inetaddress.getAddress();
    // tell server what port we are listening on
    short addrshorts[] = new short[4];
    // problem:  bytes greater than 127 are printed as negative numbers
    for (int i = 0; i <= 3; i++) {
      addrshorts[i] = addrbytes[i];
      if (addrshorts[i] < 0) {
        addrshorts[i] += 256;
      }
    }
    doCmd("port " + addrshorts[0] + "," +
        addrshorts[1] + "," + addrshorts[2] + "," +
        addrshorts[3] + "," + ((localport & 0xff00) >>
        8) + "," + (localport & 0x00ff));
  }


  /**
   *  sends a PASV command and returns a InetSocketAddress that you can connect
   *  to
   *
   *@param  command          Description of Parameter
   *@return                  the InetSocketAddress which you can build a
   *      SocketChannel from.
   *@exception  IOException  Description of Exception
   */
  public SSLSocketChannel doPASV(String command) throws IOException {
    InetSocketAddress isa = null;
    SSLSocketChannel sc = null;
    dbuf.clear();
    try {
      sendPRET(command);
      doCmd("PASV");
      String output = getReplyMsg;
      while (output.indexOf(")") == -1) {
        getReply();
        output = getReplyMsg;
      }
      if (output.indexOf(",") == -1)
        return null;
      output = output.substring(output.indexOf("(") + 1,
          output.indexOf(")"));
      String[] parts = Utilities.split(output, ",");
      String ip = parts[0] + "." + parts[1] + "." +
          parts[2] + "." + parts[3];
      int port = Integer.parseInt(parts[4]) * 256 +
          Integer.parseInt(parts[5]);
      if (rest > 0) {
        if (doCmd("REST " + rest) > 3) {
          rest = 0;
        }
      }
      send(command);
      if (proxy) {
        sc = (SSLSocketChannel) panel.getFrame().proxyConnect(host, port, true);
      } else {
        isa = new InetSocketAddress(InetAddress.getByName(ip), port);
        sc = new SSLSocketChannel();
        sc.socket().setReceiveBufferSize(65536);
        sc.socket().setSendBufferSize(65536);
        sc.configureBlocking(false);
        sc.connect(isa);
        while (!sc.finishConnect() && !abortConnect) {
          try {
            Thread.sleep(20);
          } catch (InterruptedException e) {}
        }
      }
      if (getReply() > 3) {
        sc = null;
      }
      return sc;
    } catch (CharacterCodingException e) {
      panel.getFrame().getStatusArea().append(e + "\n", panel.getColor());
    }
    return sc;
  }

  private int sendPRET(String command) throws IOException {
    if(this.isPRETCapable) {
      int reply = doCmd("PRET "+command);
      if (command.startsWith("LIST") && reply > 3) {
        this.isPRETCapable = false;
      }
      return reply;
    }
    return 3;
  }
 
  private void updateChecksum(byte[] buffer, int off, int len) {
    crc.update(buffer, off, len);
  }
 
  public String hexformat(long value, int nibbles) {
    StringBuffer sb = new StringBuffer(Long.toHexString(value));
    while (sb.length() < nibbles)
      sb.insert(0,'0');
    return sb.toString();
  }
 
  private void crcUpdate() {
    if (computeCRC) {
      int crcLength = dbuf.position();
      dbuf.flip();
      dbuf.get(crcbuffer, 0, crcLength);
      updateChecksum(crcbuffer, 0, crcLength);
    }
  }
 
  private void testSFV(FtpFile f) {
    if (Pattern.matches(".*.sfv", f.getName().toLowerCase())) {
      try {
        BufferedReader reader = new BufferedReader(new FileReader(f.getAbsolutePath()));
        String line;
        while ((line = reader.readLine()) != null) {
          if (!line.startsWith(";")) {
            String[] t = Utilities.split(line, " ");
            if (t.length > 1) {
              crcCache.put(t[0], t[1].toLowerCase());
            }
          }
        }
      } catch (IOException e) {}
    }
  }
}
TOP

Related Classes of de.kout.wlFxp.ftp.Ftp

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.