Package shared.ftp

Source Code of shared.ftp.JFtp

/*
* JFtp.java
*
* Created on 9. Dezember 2006, 09:20
*
*  Copyright (C) 9. Dezember 2006  <reiner>
*  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.
*P
*  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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/


package shared.ftp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.RandomAccessFile;
   
import java.net.BindException;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.net.NoRouteToHostException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.regex.Pattern;
import java.util.regex.Matcher;


import shared.proglistener.ProgListener;
import shared.proglistener.ProgNotify;
import shared.files.JPathHelper;
import shared.misc.JSleepHelper;

  //http://java.sun.com/j2se/javadoc/writingdoccomments/index.html#@see
/**
*
* main class for FTP
* @author reiner
* @see <a href="http://www.faqs.org/rfcs/rfc959.html">http://www.faqs.org/rfcs/rfc959.html</a><br>
* @see <a href="http://cr.yp.to/ftpparse/ftpparse.c">http://cr.yp.to/ftpparse/ftpparse.c</a> for passing the <code>LIST</code> results<br>
* @see <a href="http://www.ftp-sites.org">List with anonymous FTP sites</a><br>
* Tested with<br>
* <code>ftp.suse.com /</code><br>
* <code>ftp.openbsd.org /pub</code><br>
* <code>ftp.fastech.com</code> WarFTP server<br>
* <code>ftp.fica.com</code> Windows 5.0<br>
* <code>ftp.microsoft.com</code> Windows 5.0<br>
* <code>ftp.globalvillage.com</code> NcFTPd server<br>
* <code>ftp.genicom.com></code> WS_FTP Server<br>
* <code>ftp.lrz-muenchen.de</code><br>
* <code>ftp.adfa.edu.au</code> Icarus FTP server<br>
* <code>ftp.agso.gov.au</code> ProFTPD 1.2.6 Server<br>
* <code>ftp.kruemel.org</code> OS/2 system<br>
* <code>ftp.sun.com</code> Icarus FTP server<br>
* <code>ftp.linux-ipv6.org</code><br>
* <code>ftp.linuxfocus.org</code> freespirit FTP server<br>
* <code>ftp.mklinux.org</code> no password needed<br>
* <code>ftp.modulabbs.org</code><br>
* <code>ftp.mozilla.org</code><br>
* <code>ftp.apple.com</code><br>
* <code>ftp.april.se</code> MSDOS LIST mode<br>
* <code>ftp.cnam.fr</code><br>
*
*/

public class JFtp implements ProgListener
{
    public static final int REPLY_125 = 125; // Data connection already open; transfer starting.
    public static final int REPLY_150 = 150; // File status okay; about to open data connection.
    public static final int REPLY_200 = 200; // command ok
    public static final int REPLY_214 = 214; // Help message. On how to use the server or the meaning of a particular non-standard command. This reply is useful only to the human user.
    public static final int REPLY_215 = 215; //  215 NAME system type. Where NAME is an official system name from the list in the Assigned Numbers document.
    public static final int REPLY_220 = 220; // Service ready for new user
    public static final int REPLY_221 = 221; // Service closing control connection. Logged out if appropriate.
    public static final int REPLY_226 = 226; // Closing data connection.
    public static final int REPLY_227 = 227; // Entering Passive Mode (h1,h2,h3,h4,p1,p2).
    public static final int REPLY_230 = 230; // User logged in, proceed.
    public static final int REPLY_250 = 250; // Requested file action okay, completed
    public static final int REPLY_257 = 257; // "PATHNAME" created
    public static final int REPLY_331 = 331; // User name okay, need password
    public static final int REPLY_332 = 332; // Need account for login
    public static final int REPLY_350 = 350; // Requested file action pending further information.
   
    public static final char TYPE_ASCII  = 'A';
    public static final char TYPE_IMAGE  = 'I';
   
    public static final char MODE_STREAM  = 'S';
    public static final char MODE_BLOCK  = 'B';
    public static final char MODE_COMPRESSED  = 'C';
   
    protected static boolean m_isDebug = false;
    protected boolean m_bOpen = false;
   
    protected int m_dataPort = 0;
    protected boolean m_bPassive = true;

    protected Socket m_comSocket;
    protected int m_waitTimeout = 1000;
    protected int m_comConTimeOut = 30000;
    protected int m_comTimeOut = 10000;
    protected int m_dataConTimeout = 5000;
    protected int m_dataTimeout = 25000;
    protected int m_activeTimeOut = 5000;
//    protected int m_bufSize = 512;
    protected int m_bufSize = 1396;
   
    // Used for opening the data port in active mode
    protected int m_socketUsedReties = 10;
    protected int m_socketUsedWait = 1000;
   
    // true for command line programs, false for gui applications, which can use isReady()
    protected boolean m_bWaitForReady = true;

    protected BufferedReader m_comBufReader;
    protected BufferedWriter m_comBuffWriter;
   
    protected String[] m_tempFileNames = null;

    protected ArrayList<String> m_messages = new ArrayList<String>();
    protected ArrayList<String> m_lastListOutput = null;
    protected boolean m_bHasLastListOutputHardlinks;
    protected int m_lastReplyCode;
    protected Thread m_dataThread = null;

    protected final Object m_lock = new Object();
   
    /** Creates a new instance of JFtp */
    public JFtp()
    {
    }

    public void setDebug(boolean bDebug)
    {
        m_isDebug = bDebug;
    }

    public ArrayList<String> getLastListOutput()
    {
        return m_lastListOutput;
    }
   
    public boolean getHasLastListOutputHardlinks()
    {
        return m_bHasLastListOutputHardlinks;
    }
 
   
    public ArrayList<String> getMessages()
    {
        return m_messages;
    }
   
    public boolean getWaitForReady()
    {
        return m_bWaitForReady;
    }

    public void setWaitForReady(boolean bWaitForReady)
    {
        m_bWaitForReady = bWaitForReady;
    }
   
    public boolean isOpen()
    {
        return (m_bOpen && m_comSocket.isConnected());
    }

    /**
     * waits until the next command can be executed
     */
    public void waitForReady()
    {
        boolean flag = true;
        while(flag)
        {
            synchronized (m_lock)
            {
                if (m_dataThread == null)
                    flag = false;
                else
                {
                    if (m_isDebug)
                    System.err.println("Waiting ....");
                }
            }
            if (flag)
                JSleepHelper.sleep(300);
            else break;
        }
    }
   
    /**
     * checks if the next command can be executed
     * @return <code>true</code> if ready and <code>false</code> if not
     */

    public boolean isReady()
    {
        Thread.yield();
        boolean flag = false;
        if (isOpen())
        {
            Thread.yield();
            if (m_dataThread == null)
                flag = true;
        }
        return flag;
    }
   
    public void setActive(int dataPort)
    {
        m_dataPort = dataPort;
        m_bPassive = false;
    }

    public void setPassive()
    {
      m_bPassive = true;
    }

    // passive
    public boolean open(String server, String user, String pass)
    {
      return open(server, 21, user, pass, null, TYPE_IMAGE, true, 0);
    }

    public boolean open(String server, String user, String pass, String account)
    {
        return open(server, 21, user, pass, account, TYPE_IMAGE, true, 0);
    }

    public boolean open(String server, int port, String user, String pass)
    {
        return open(server, port, user, pass, null, TYPE_IMAGE, true, 0);
    }

    public boolean open(String server, int port, String user, String pass, String account)
    {
        return open(server, port, user, pass, account, TYPE_IMAGE, true, 0);
    }
   
    // active
    public boolean open(String server, String user, String pass, boolean bPassive)
    {
        return open(server, 21, user, pass, null, TYPE_IMAGE, bPassive, 0);
    }

    public boolean open(String server, String user, String pass, String account, boolean bPassive)
    {
        return open(server, 21, user, pass, account, TYPE_IMAGE, bPassive, 0);
    }

    public boolean open(String server, String user, String pass, boolean bPassive, int dataPort)
    {
        return open(server, 21, user, pass, null, TYPE_IMAGE, bPassive, dataPort);
    }

    public boolean open(String server, String user, String pass, String account, boolean bPassive, int dataPort)
    {
        return open(server, 21, user, pass, account, TYPE_IMAGE, bPassive, dataPort);
    }

    public boolean open(String server, int port, String user, String pass, boolean bPassive)
    {
        return open(server, port, user, pass, null, TYPE_IMAGE, bPassive, 0);
    }

    public boolean open(String server, int port, String user, String pass, String account, boolean bPassive)
    {
        return open(server, port, user, pass, account, TYPE_IMAGE, bPassive, 0);
    }

    public boolean open(String server, int port, String user, String pass, boolean bPassive, int dataPort)
    {
        return open(server, port, user, pass, null, TYPE_IMAGE, bPassive, dataPort);
    }

    public boolean open(String server, int port, String user, String pass, String account, boolean bPassive, int dataPort)
    {
        return open(server, port, user, pass, account, TYPE_IMAGE, bPassive, dataPort);
    }

    /**
     * full featured open function
     * @param server the server name or IP
     * @param port the port number for the communication, default is <code>21</code>
     * @param user the user name for login
     * @param pass the password for login
     * @param account the account name for login, if it is required
     * @param dataType the data type, default is binary<br>
   * <code><table>
   * <tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>TYPE_ASCII</td></tr>
   * <tr><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>TYPE_IMAGE</td></tr>
     * </table></code>
     * @param bPassive <code>true</code> for passive FTP else <code>false</code>
     * @param dataPort if bPassive is false port number for data channel, default is <code>20</code>
     */
    public boolean open(String server, int port, String user, String pass, String account, char dataType, boolean bPassive, int dataPort)
    {
        boolean flag = false;
        if (!isOpen())
        {
            try
            {
                m_comSocket = new Socket();
                m_comSocket.connect(new InetSocketAddress(server, port), m_comConTimeOut);
                m_comBufReader = new BufferedReader(new InputStreamReader(m_comSocket.getInputStream()));
                m_comBuffWriter = new BufferedWriter(new OutputStreamWriter(m_comSocket.getOutputStream()));
                getMessage(m_comTimeOut);
                if (m_lastReplyCode == REPLY_220 && doLogin(user, pass, account))
                {
                    m_bOpen = true;
                    flag = setDataType(dataType);
                    if (bPassive) setPassive();
                    else setActive(dataPort);
                }
            }
            catch (UnknownHostException ex)
            {
                if (m_isDebug)
                    System.err.println("Unable to connect to '" + server + "'");
            }
            catch (NoRouteToHostException ex)
            {
                if (m_isDebug)
                    System.err.println("Unable to connect to '" + server + "'; route error");
            }
            catch (ConnectException ex)
            {
                if (m_isDebug)
                    System.err.println("Unable to find '" + server + "'");
            }
            catch (SocketTimeoutException ex)
            {
                if (m_isDebug)
                    System.err.println("Timeout during connecting to '" + server + "'");
            }
            catch (IOException ex)
            {
                if (m_isDebug)
                    System.err.println("Error during connect to '" + server + "'");
            }
        }
        return flag;
    }
   
    /**
     * close the FTP connection, all data transfers must be completed or aborted before
     * @return <code>true</code> if successful or <code>false</code> if an error occured
     */
   
    public boolean close()
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("QUIT\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_221)
                    {
                        m_comSocket.close();
                        m_bOpen = false;
                        flag = true;
                    }
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean ping()
    {
      return noop();
    }
   
    public boolean noop()
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("NOOP\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_200)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }
   
    public String getCurrentDirectory()
    {
        String str = null;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    String hstr;
                    m_comBuffWriter.write("PWD\r\n");
                    m_comBuffWriter.flush();
                    hstr = getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_257 && hstr != null)
                    {
                        Pattern pat = Pattern.compile("^\\d{3}[ \t]+\"(.+)\".*");
                        Matcher m = pat.matcher(hstr);
                        if (m.find())
                        {
                            str = m.group(1);
                            if (m_isDebug)
                                System.err.println(str);
                        }
                    }
                }
                catch(IOException ex)
                {}
            }
        }
        return str;
    }

    /**
     * implements the <code>CWD</code> command
     * @param str the directory
     * @return true or false
     */
    public boolean setCurrentDirectory(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    String hstr;
                    m_comBuffWriter.write("CWD " + str + "\r\n");
                    m_comBuffWriter.flush();
                    hstr = getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_250)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean changeToParentDirectory()
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    String hstr;
                    m_comBuffWriter.write("CDUP\r\n");
                    m_comBuffWriter.flush();
                    hstr = getMessage(m_comTimeOut, 1);
                    if (m_lastReplyCode == REPLY_250)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean getStatus(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("STAT " + str + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_250)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean system()
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("SYST\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_215)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean site(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("SITE " + str + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_200)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean help(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("HELP " + str + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_214)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    protected boolean abortInternal()
    {
        boolean flag = false;
        try
        {
            m_comBuffWriter.write("ABOR\r\n");
            m_comBuffWriter.flush();
            getMessage(m_comTimeOut);
            if (m_lastReplyCode == REPLY_226)
                flag = true;
        }
        catch(IOException ex)
        {}
        return flag;
    }

    public boolean abort()
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
                flag = abortInternal();
        }
        return flag;
    }

    protected boolean renameInternal(String source, String target)
    {
        boolean flag = false;
        try
        {
            m_comBuffWriter.write("RNFR " + source + "\r\n");
            m_comBuffWriter.flush();
            getMessage(m_comTimeOut);
            if (m_lastReplyCode == REPLY_350)
            {
                m_comBuffWriter.write("RNTO " + target + "\r\n");
                m_comBuffWriter.flush();
                getMessage(m_comTimeOut);
                if (m_lastReplyCode == REPLY_250)
                    flag = true;
            }
        }
        catch(IOException ex)
        {}
        return flag;
    }

    public boolean rename(String source, String target)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
                flag = renameInternal(source, target);
        }
        return flag;
    }

    public boolean deleteFile(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("DELE " + str + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_250)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean makeDirectory(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("MKD " + str + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_257)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean deleteDirectory(String str)
    {
        boolean flag = false;
        synchronized (m_lock)
        {
            if (isReady())
            {
                try
                {
                    m_comBuffWriter.write("RMD " + str + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_250)
                        flag = true;
                }
                catch(IOException ex)
                {}
            }
        }
        return flag;
    }

    public boolean listDirectory(String str)
    {
        synchronized (m_lock)
        {}
        boolean flag = false;
        if (isReady())
        {
            Socket socket = null;
            ServerSocket serverSocket = null;
            if (m_bPassive)
                socket = doPassive();
            else serverSocket = doActive();

            if ((m_bPassive && socket != null) || (!m_bPassive && serverSocket != null))
            {
                final Socket _socket = socket;
                final ServerSocket _serverSocket = serverSocket;
                final JFtp ftp = this;
                final int waitTimeout = m_waitTimeout;
                final boolean [] bServerSocketWaits = new boolean[1];
                bServerSocketWaits[0] = false;
                m_dataThread = new Thread()
                {
                    public void run()
                    {
                        synchronized (ftp.m_lock)
                        {
                            ArrayList<String> results = new ArrayList<String>();
                            boolean bAbort = false;
                            Socket socket = _socket;
                            boolean flag = false;
                            try
                            {
                                if (_serverSocket != null)
                                {
                                    bServerSocketWaits[0] = true;
                                    socket = activeWaitForConnection(_serverSocket);
                                }

                                ftp.notify(new FtpNotify(FtpNotify.TYPE_LIST, ProgNotify.START));
                                BufferedReader bufReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                                String str;
                                while (!isInterrupted() && !bAbort && (str = bufReader.readLine()) != null)
                                {
                                    results.add(str);
                                    if (!ftp.notify(new FtpNotify<String>(FtpNotify.TYPE_LIST, ProgNotify.RUN, str)))
                                    {
                                        ftp.abort();
                                        bAbort = true;
                                    }
                                }
                                flag = true;
                            }
                            catch(IOException ex)
                            {}
                            closeSocket(socket);
                            if (flag)
                                ftp.notify(new FtpNotify<ArrayList<String> >(FtpNotify.TYPE_LIST, bAbort ? ProgNotify.ABORT : ProgNotify.END, results));
                            else
                                ftp.notify(new FtpNotify(FtpNotify.TYPE_LIST, ProgNotify.ERROR));
                        }
                    }
                };
                if (!m_bPassive)
                {
                    m_dataThread.start();
                    int count = 100;
                    while (!bServerSocketWaits[0] && count-- > 0)
                        JSleepHelper.sleep(50);
                    Thread.yield();
                }
                try
                {
                    flag = false;
                    m_comBuffWriter.write("LIST -al " + (str != null ? str : ".") + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_250 || m_lastReplyCode == REPLY_125 || m_lastReplyCode == REPLY_150)
                    {
                        if (m_bPassive)
                            m_dataThread.start();
                        flag = true;
                    }
                    if (!flag)
                    {
                        if (!m_bPassive)
                            m_dataThread.interrupt();
                        closeSocket(socket);
                        closeSocket(serverSocket);
                    }
                }
                catch(IOException ex)
                {
                    if (!m_bPassive)
                        m_dataThread.interrupt();
                    closeSocket(socket);
                    closeSocket(serverSocket);
                }
            }
        }
        if (!flag)
            m_dataThread = null;
        else if (m_bWaitForReady)
            waitForReady();
        return flag;
    }

    public boolean getFile(String source, String target)
    { 
        return getFile(source, target, false, 0);
    }

    public boolean getFile(String source, String target, boolean bTemp)
    { 
        return getFile(source, target, bTemp, 0);
    }

    public boolean getFile(String source, String target, long startPos)
    { 
        return getFile(source, target, false, startPos);
    }

    public boolean getFile(String source, final String target, final boolean bTemp, final long startPos)
    {
        synchronized (m_lock)
        {}
        boolean flag = false;
        if (isReady())
        {
            Socket socket = null;
            ServerSocket serverSocket = null;
            if (m_bPassive)
                socket = doPassive();
            else serverSocket = doActive();

            if ((m_bPassive && socket != null) || (!m_bPassive && serverSocket != null))
            {
                final Socket _socket = socket;
                final ServerSocket _serverSocket = serverSocket;
                final JFtp ftp = this;
                final int waitTimeout = m_waitTimeout;
                final boolean [] bServerSocketWaits = new boolean[1];
                bServerSocketWaits[0] = false;

                m_dataThread = new Thread()
                {
                    public void run()
                    {
                        synchronized (ftp.m_lock)
                        {
                            FileOutputStream fileOutput = null;
                            long size = 0;
                            boolean bAbort = false;
                            File tempFile = null;
                            Socket socket = _socket;
                            boolean flag = false;
                            try
                            {
                                if (_serverSocket != null)
                                {
                                    bServerSocketWaits[0] = true;
                                    socket = activeWaitForConnection(_serverSocket);
                                }

                                if (bTemp)
                                {
                                    tempFile = File.createTempFile("ftp", "", new File(JPathHelper.getFolder(target)));
                                    fileOutput = new FileOutputStream(tempFile);
                                }
                                else
                                {
                                    File file = new File(target);
                                    if (file.exists())
                                    {
                                        if (startPos > 0)
                                        {
                                            RandomAccessFile rf = new RandomAccessFile(file, "rw");
                                            if (rf.getFilePointer() > startPos)
                                                rf.setLength(startPos);
                                            rf.close();
                                            fileOutput = new FileOutputStream(target, true);
                                        }
                                    }
                                    if (fileOutput  == null)
                                        fileOutput = new FileOutputStream(target);
                                }
                                ftp.notify(new FtpNotify<String>(FtpNotify.TYPE_RETR, ProgNotify.START, bTemp ? tempFile.getPath() : target));
                                InputStream inputStream = socket.getInputStream();
                                int readed;
                                byte[] buf = new byte[m_bufSize];
                                while (!isInterrupted() && !bAbort && (readed = inputStream.read(buf)) > 0)
                                {
                                    fileOutput.write(buf, 0, readed);
                                    size += readed;
                                    if (!ftp.notify(new FtpNotify<Long>(FtpNotify.TYPE_RETR, ProgNotify.RUN, new Long(readed))))
                                    {
                                        ftp.abortInternal();
                                        bAbort = true;
                                    }
                                }
                                flag = true;
                            }
                            catch(IOException ex)
                            {}
                            closeSocket(socket);
                            if (fileOutput != null)
                            {
                                try
                                    {fileOutput.close();}
                                catch (IOException ex)
                                {}
                            }
                            if (flag && !bAbort && tempFile != null)
                                tempFile.renameTo(new File(target));
                            if (flag)
                                ftp.notify(new FtpNotify<Long>(FtpNotify.TYPE_RETR, bAbort ? ProgNotify.ABORT : ProgNotify.END, new Long(size)));
                            else
                                ftp.notify(new FtpNotify<String>(FtpNotify.TYPE_RETR, ProgNotify.ERROR, bTemp ? tempFile.getPath() : null));
                        }
                    }
                };
                try
                {
                    flag = false;
                    if (startPos > 0)
                    {
                        m_comBuffWriter.write("REST " + Long.toString(startPos) + "\r\n");
                        m_comBuffWriter.flush();
                        getMessage(m_comTimeOut);
                        if (m_lastReplyCode == REPLY_350)
                            flag = true;
                    }
                    else flag = true;
                    if (flag)
                    {
                        if (!m_bPassive)
                        {
                            m_dataThread.start();
                            // wait to ensure that the accept command from the server socket is called
                            int count = 100;
                            while (!bServerSocketWaits[0] && count-- > 0)
                                JSleepHelper.sleep(50);
                            Thread.yield();
                        }
                        flag = false;
                        m_comBuffWriter.write("RETR " + source + "\r\n");
                        m_comBuffWriter.flush();
                        getMessage(m_comTimeOut);
                        if (m_lastReplyCode == REPLY_150 || m_lastReplyCode == REPLY_125)
                        {
                            if (m_bPassive)
                                m_dataThread.start();
                            flag = true;
                        }
                    }
                    if (!flag)
                    {
                        if (!m_bPassive)
                            m_dataThread.interrupt();
                        closeSocket(socket);
                        closeSocket(serverSocket);
                    }
                }
                catch(IOException ex)
                {
                    if (!m_bPassive)
                        m_dataThread.interrupt();
                    closeSocket(socket);
                    closeSocket(serverSocket);
                }
            }
        }
        if (!flag)
            m_dataThread = null;
        else if (m_bWaitForReady)
            waitForReady();
        return flag;
    }

    public boolean sendFile(final String source, String target)
    {
      return sendFile(source, target, false, 0);
    }

    public boolean sendFile(final String source, String target, boolean bTemp)
    {
        return sendFile(source, target, bTemp, 0);
    }
   
    public boolean sendFile(final String source, String target, long startPos)
    {
      return sendFile(source, target, false, startPos);
    }

    public boolean sendFile(final String source, String target, final boolean bTemp, final long startPos)
    {
        synchronized (m_lock)
        {}
        m_tempFileNames = null;
        boolean flag = false;
        if (isReady())
        {
            Socket socket = null;
            ServerSocket serverSocket = null;
            if (m_bPassive)
                socket = doPassive();
            else serverSocket = doActive();

            final String[] tempFileNameArray = new String[1];
            if ((m_bPassive && socket != null) || (!m_bPassive && serverSocket != null))
            {
                final Socket _socket = socket;
                final ServerSocket _serverSocket = serverSocket;
                final JFtp ftp = this;
                final int waitTimeout = m_waitTimeout;
                final String _target = target;
                final boolean [] bServerSocketWaits = new boolean[1];
                bServerSocketWaits[0] = false;
                m_dataThread = new Thread()
                {
                    public void run()
                    {
                        synchronized (ftp.m_lock)
                        {
                            boolean flag = false;
                            long size = 0;
                            boolean bAbort = false;
                            FileInputStream fileInput = null;
                            Socket socket = _socket;
                            try
                            {
                                if (_serverSocket != null)
                                {
                                    bServerSocketWaits[0] = true;
                                    socket = activeWaitForConnection(_serverSocket);
                                }

                                fileInput = new FileInputStream(source);
                                if (startPos > 0)
                                    fileInput.skip(startPos);
                                ftp.notify(new FtpNotify<String>(FtpNotify.TYPE_STOR, ProgNotify.START, bTemp ? m_tempFileNames[0] : _target));
                                OutputStream outputStream = socket.getOutputStream();
                                int readed;
                                byte[] buf = new byte[m_bufSize];
                                while (!bAbort && (readed = fileInput.read(buf)) > 0)
                                {
                                    outputStream.write(buf, 0, readed);
                                    size += readed;
                                    if (!ftp.notify(new FtpNotify<Long>(FtpNotify.TYPE_STOR, ProgNotify.RUN, new Long(readed))))
                                    {
                                        ftp.abort();
                                        bAbort = true;
                                    }
                                }
                                flag = true;
                            }
                            catch(IOException ex)
                            {}
                            try
                                {fileInput.close();}
                            catch (IOException ex)
                            {}
                            closeSocket(socket);
                            if (flag)
                                ftp.notify(new FtpNotify<Long>(FtpNotify.TYPE_STOR, bAbort ? ProgNotify.ABORT : ProgNotify.END, new Long(size)));
                            else
                                ftp.notify(new FtpNotify<String>(FtpNotify.TYPE_STOR, ProgNotify.ERROR, bTemp ? m_tempFileNames[0] : null));
                        }
                    }
                };
                try
                {
                    if (startPos > 0)
                    {
                        m_comBuffWriter.write("REST " + Long.toString(startPos) + "\r\n");
                        m_comBuffWriter.flush();
                        getMessage(m_comTimeOut);
                        if (m_lastReplyCode == REPLY_350)
                            flag = true;
                    }
                    else flag = true;
                    if (flag)
                    {
                        flag = false;
                        if (!m_bPassive)
                        {
                             m_dataThread.start();
                            // wait to ensure that the accept command from the server socket is called
                            int count = 100;
                            while (!bServerSocketWaits[0] && count-- > 0)
                                JSleepHelper.sleep(50);
                            Thread.yield();
                        }
                        if (bTemp)
                            m_comBuffWriter.write("STOU \r\n");
                        else
                            m_comBuffWriter.write("STOR " + target + "\r\n");
                        m_comBuffWriter.flush();
                        String str = getMessage(m_comTimeOut);
                        if (m_lastReplyCode == REPLY_150)
                        {
                            if (bTemp)
                            {
                                Pattern pat = Pattern.compile("150[- ]FILE: (.+)");
                                Matcher m = pat.matcher(str);
                                if (m.find())
                                {
                                    m_tempFileNames = new String[2];
                                    m_tempFileNames[0] = m.group(1);
                                    m_tempFileNames[1] = target;
                                    flag = true;
                                }
                            }
                            else flag = true;
                            if (m_bPassive && flag)
                                m_dataThread.start();
                        }
                    }
                    if (!flag)
                    {
                        if (m_bPassive)
                            m_dataThread.interrupt();
                        closeSocket(socket);
                        closeSocket(serverSocket);
                    }
                }
                catch(IOException ex)
                {
                    if (m_bPassive)
                        m_dataThread.interrupt();
                    closeSocket(socket);
                    closeSocket(serverSocket);
                }
            }
        }
        if (!flag)
            m_dataThread = null;
        else if (m_bWaitForReady)
            waitForReady();
        return flag;
    }

    public boolean transferFile(final String source, String target, JFtp ftp2, final boolean bTemp)
    {
        boolean flag = false;
        if ((!m_bPassive && ftp2.m_bPassive) || (m_bPassive && !ftp2.m_bPassive))
        {
            synchronized (m_lock)
            {}
            synchronized (ftp2.m_lock)
            {}
            try
            {
                if (isReady() && ftp2.isReady())
                {
                    if (ftp2.m_bPassive)
                    {
                        InetSocketAddress addr = ftp2.doPassiveSimple();
                        flag = doActiveSimple(addr);
                    }
                    else
                    {
                        InetSocketAddress addr = doPassiveSimple();
                        flag = ftp2.doActiveSimple(addr);
                    }
                    if (flag)
                    {
                        flag = false;
                        if (bTemp)
                            ftp2.m_comBuffWriter.write("STOU \r\n");
                        else
                            ftp2.m_comBuffWriter.write("STOR " + target + "\r\n");
                        ftp2.m_comBuffWriter.flush();
                        String str = ftp2.getMessage(m_comTimeOut), str2;
                        if (ftp2.m_lastReplyCode == REPLY_150)
                        {
                            if (bTemp)
                            {
                                Pattern pat = Pattern.compile("150[- ]FILE: (.+)");
                                Matcher m = pat.matcher(str);
                                if (m.find())
                                    flag = true;
                            }
                            else flag = true;
                            if (flag)
                            {
                                flag = false;
                                m_comBuffWriter.write("RETR " + source + "\r\n");
                                m_comBuffWriter.flush();
                                getMessage(m_comTimeOut);
                                if (m_lastReplyCode == REPLY_150 || m_lastReplyCode == REPLY_125)
                                    flag = true;
                            }
                            if (flag)
                            {
                                flag = false;
                                notify(new FtpNotify<Long>(FtpNotify.TYPE_TRANSFER, ProgNotify.START));
                                str = getMessage(0, 1);
                                str2 = ftp2.getMessage(0, 1);
                                if ((m_lastReplyCode == REPLY_150 || m_lastReplyCode == REPLY_125) && ftp2.m_lastReplyCode == REPLY_150)
                                {
                                    if (bTemp)
                                    {
                                    }
                                    else flag = true;
                                }
                                notify(new FtpNotify<Long>(FtpNotify.TYPE_TRANSFER, flag ? ProgNotify.END : ProgNotify.ERROR));
                            }
                        }
                    }
                }
            }
            catch(IOException ex)
            {}
        }
        return flag;
    }

    protected Socket doPassive()
    {
        Socket socket = null;
        if (isReady())
        {
            try
            {
                InetSocketAddress addr = doPassiveSimple();
                if (addr != null)
                {
                    socket = new Socket();
                    socket.connect(addr, m_dataConTimeout);
                    socket.setSoTimeout(m_dataTimeout);
                }
            }
            catch(IOException ex)
            {}
        }
        return socket;
    }

    protected InetSocketAddress doPassiveSimple()
    {
        InetSocketAddress addr = null;
        if (isReady())
        {
            try
            {
                m_comBuffWriter.write("PASV\r\n");
                m_comBuffWriter.flush();
                String str = getMessage(m_comTimeOut);
                if (m_lastReplyCode == REPLY_227)
                {
                    Pattern pat = Pattern.compile("\\d{3}.*\\((\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)");
                    Matcher m = pat.matcher(str);
                    if (m.find())
                        addr = new InetSocketAddress(m.group(1) + "." + m.group(2) + "." + m.group(3) + "." + m.group(4), Integer.parseInt(m.group(5))*256 + Integer.parseInt(m.group(6)));
                }
            }
            catch(IOException ex)
            {}
        }
        return addr;
    }
   
    protected Socket activeWaitForConnection(ServerSocket serverSocket) throws IOException
    {
        Socket socket = null;
        if (serverSocket != null)
        {
            socket = serverSocket.accept();
            socket.setSoTimeout(m_dataTimeout);
            closeSocket(serverSocket);
        }
        return socket;
    }
   
    /**
     * prepare active FTP data transfer, so we listen on the data port and wait that the server connect to us
     */
    protected ServerSocket doActive()
    {
        ServerSocket socket = null;
        int count = 0;
        try
        {
            InetSocketAddress addr = new InetSocketAddress("0.0.0.0", m_dataPort);
            while(socket == null && count++ < m_socketUsedReties)
            {
                try
                {
                    socket = doInternalActive(addr);
                }
                catch(BindException ex)
                {
                    JSleepHelper.sleep(m_socketUsedWait);
                }
            }
        }
        catch(IOException ex)
        {}
      return socket;
    }

    protected ServerSocket doInternalActive(InetSocketAddress addr) throws IOException
    {
        ServerSocket socket = null;
        if (isReady())
        {
            String str = addr.getAddress().getHostAddress();
            int port = addr.getPort();
            if (str.equals("0.0.0.0"))
                str = m_comSocket.getLocalAddress().getHostAddress();

            socket = new ServerSocket();
            socket.setReuseAddress(true);
            if (port > 0)
                socket.bind(new InetSocketAddress("0.0.0.0", port));
            else
                socket.bind(null);
            socket.setSoTimeout(m_activeTimeOut);

            port = socket.getLocalPort();
            str = str.replace('.', ',');
            str += ',';
            str += Integer.toString(port/256);
            str += ',';
            str += Integer.toString(port%256);

            m_comBuffWriter.write("PORT " + str + "\r\n");
            m_comBuffWriter.flush();
            getMessage(m_comTimeOut);
            if (m_lastReplyCode != REPLY_200)
            {
                socket.close();
                socket = null;
            }
        }
        return socket;
    }


    protected boolean doActiveSimple(InetSocketAddress addr)
    {
        boolean flag = false;
        if (addr != null && isReady())
        {
            try
            {
                String str = addr.getAddress().getHostAddress();
                int port = addr.getPort();

                str = str.replace('.', ',');
                str += ',';
                str += Integer.toString(port/256);
                str += ',';
                str += Integer.toString(port%256);

                m_comBuffWriter.write("PORT " + str + "\r\n");
                m_comBuffWriter.flush();
                getMessage(m_comTimeOut);
                flag = true;
                if (m_lastReplyCode != REPLY_200)
                    flag = false;
            }
            catch(IOException ex)
            {}
        }
        return flag;
    }


    protected boolean doLogin(String user, String pass, String account)
    {
        boolean flag = false;
        try
        {
            m_comBuffWriter.write("USER "+ user + "\r\n");
            m_comBuffWriter.flush();
            getMessage(m_comTimeOut);
            if (m_lastReplyCode == REPLY_331)
            {
                m_comBuffWriter.write("PASS "+ pass + "\r\n");
                m_comBuffWriter.flush();
                getMessage(m_comTimeOut);
                if (m_lastReplyCode == REPLY_230)
                    flag = true;
                else if (m_lastReplyCode == REPLY_332)
                {
                    m_comBuffWriter.write("ACCT "+ account + "\r\n");
                    m_comBuffWriter.flush();
                    getMessage(m_comTimeOut);
                    if (m_lastReplyCode == REPLY_230)
                        flag = true;
                }
            }
            else if (m_lastReplyCode == REPLY_230)
                flag = true;
        }
        catch(IOException ex)
        {}
        return flag;
    }
   
    public boolean setDataType(char type)
    {
        boolean flag = false;
        try
        {
            m_comBuffWriter.write("TYPE "+ type + "\r\n");
            m_comBuffWriter.flush();
            getMessage(m_comTimeOut);
            if (m_lastReplyCode == REPLY_200)
                flag = true;
        }
        catch(IOException ex)
        {}
        return flag;
    }

    public boolean setTransferMode(char mode)
    {
        boolean flag = false;
        try
        {
            m_comBuffWriter.write("MODE "+ mode + "\r\n");
            m_comBuffWriter.flush();
            getMessage(m_comTimeOut);
            if (m_lastReplyCode == REPLY_200)
                flag = true;
        }
        catch(IOException ex)
        {}
        return flag;
    }

    protected String getMessage(int timeout)
    {
      return getMessage(timeout, 1);
    }
   
    protected String getMessage(int timeout, int lines)
    {
        String str = null;
        String hstr = null;
        try
        {
            m_comSocket.setSoTimeout(timeout);
            int count = lines > 0 ?  lines : -1;
            Boolean bMultiLine = false;
            while (bMultiLine || count < 0 || count-- > 0)
            {
                if ((hstr = m_comBufReader.readLine()) == null)
                    break;
                else
                {
                    if (str == null) str = hstr;
                    int status = getReplyCode(hstr, bMultiLine);
                    if (status > 0)
                    {
                        if (bMultiLine && status == m_lastReplyCode)
                        {
                            bMultiLine = false;
                            count = 0;
                        }
                        else m_lastReplyCode = status;
                    }
                    else if (status < 0)
                    {
                        m_lastReplyCode = -status;
                        bMultiLine = true;
                    }
                    synchronized(m_messages)
                    {
                        m_messages.add(hstr);
                        if (m_isDebug)
                            System.err.println(hstr);
                    }
                }
            }
        }
        catch (SocketException ex)
        {}
        catch (IOException ex)
        {}
        return str;
    }
   
    protected int getReplyCode(String str, Boolean bMultiline)
    {
        int status = 0;
        if (str != null)
        {
            Pattern pat = Pattern.compile("^(\\d{3})(-|\\s+).*");
            Matcher m = pat.matcher(str);
            if (m.find())
            {
                status = Integer.parseInt(m.group(1));
                if (m.group(2).equals("-"))
                    status = -status;
            }
        }
        return status;
    }
   
    @SuppressWarnings("unchecked")
    public boolean notify(ProgNotify progNotify)
    {
        boolean flag = true;
        boolean bTransferOk = false;
        FtpNotify ftpNotify = (FtpNotify)progNotify;
        if (ftpNotify.getReason() == ProgNotify.END)
        {
            getMessage(m_comTimeOut);
            if (m_lastReplyCode == REPLY_226)
                bTransferOk = true;
            m_dataThread = null;
        }
        else if (ftpNotify.getReason() == ProgNotify.ABORT || ftpNotify.getReason() == ProgNotify.ERROR)
        {
            m_dataThread = null;
        }
        if (ftpNotify.getType () == FtpNotify.TYPE_LIST)
        {
            if (ftpNotify.getReason() == ProgNotify.START)
            {
                if (m_isDebug)
                    System.err.println("List start");
            }
            else if (ftpNotify.getReason() == ProgNotify.RUN)
            {
                FtpNotify<String> ftpNotify2 = (FtpNotify<String>)ftpNotify;
                String fileName = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("List :" + fileName);
            }
            else if (ftpNotify.getReason() == ProgNotify.END)
            {
                FtpNotify<ArrayList<String> > ftpNotify2 = (FtpNotify<ArrayList<String> >)ftpNotify;
                ArrayList<String> list = ftpNotify2.getData();
                if (m_isDebug)
                {
                    System.err.println("List results:");
                    for (String str : list)
                    {
                        System.err.println(str);
                        parseListLine(str);
                    }
                }
                m_lastListOutput = list;
            }
            else if (ftpNotify.getReason() == ProgNotify.ERROR)
            {
                if (m_isDebug)
                    System.err.println("List error");
            }
            else if (ftpNotify.getReason() == ProgNotify.ABORT)
            {
                FtpNotify<ArrayList<String> > ftpNotify2 = (FtpNotify<ArrayList<String> >)ftpNotify;
                ArrayList<String> list = ftpNotify2.getData();
                if (m_isDebug)
                {
                    System.err.println("List abort");
                    for (String str : list)
                        System.err.println(str);
                }
            }
        }
        else if (ftpNotify.getType () == FtpNotify.TYPE_RETR)
        {
            if (ftpNotify.getReason() == ProgNotify.START)
            {
                FtpNotify<String> ftpNotify2 = (FtpNotify<String>)ftpNotify;
                String fileName = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("Retr start of '" + fileName + "'");
            }
            else if (ftpNotify.getReason() == ProgNotify.RUN)
            {
                if (m_isDebug)
                    System.err.println("Retr :" + ftpNotify.getData().toString());
            }
            else if (ftpNotify.getReason() == ProgNotify.END)
            {
                FtpNotify<Long> ftpNotify2 = (FtpNotify<Long>)ftpNotify;
                Long fileSize = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("Retr end fileSize = " + fileSize);
            }
            else if (ftpNotify.getReason() == ProgNotify.ERROR)
            {
                FtpNotify<String> ftpNotify2 = (FtpNotify<String>)ftpNotify;
                String tempFileName = ftpNotify2.getData();
                if (m_isDebug)
                {
                    if (tempFileName != null)
                        System.err.println("Retr error tempfile = '" + tempFileName + "'");
                    else
                        System.err.println("Retr error");
                }
            }
            else if (ftpNotify.getReason() == ProgNotify.ABORT)
            {
                FtpNotify<Long> ftpNotify2 = (FtpNotify<Long>)ftpNotify;
                Long fileSize = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("Retr abort fileSize = " + fileSize);
            }
        }
        else if (ftpNotify.getType () == FtpNotify.TYPE_STOR)
        {
            if (ftpNotify.getReason() == ProgNotify.START)
            {
                FtpNotify<String> ftpNotify2 = (FtpNotify<String>)ftpNotify;
                String fileName = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("Stor start of '" + fileName + "'");
            }
            else if (ftpNotify.getReason() == ProgNotify.RUN)
            {
                if (m_isDebug)
                    System.err.println("Stor :" + ftpNotify.getData().toString());
                // return false;
            }
            else if (ftpNotify.getReason() == ProgNotify.END)
            {
                if (m_tempFileNames != null)
                    renameInternal(m_tempFileNames[0], m_tempFileNames[1]);

                FtpNotify<Long> ftpNotify2 = (FtpNotify<Long>)ftpNotify;
                Long fileSize = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("Stor end fileSize = " + fileSize);
            }
            else if (ftpNotify.getReason() == ProgNotify.ERROR)
            {
                FtpNotify<String> ftpNotify2 = (FtpNotify<String>)ftpNotify;
                String tempFileName = ftpNotify2.getData();
                if (m_isDebug)
                {
                    if (tempFileName != null)
                        System.err.println("Stor error tempfile = '" + tempFileName + "'");
                    else
                        System.err.println("Stor error");
                }
            }
            else if (ftpNotify.getReason() == ProgNotify.ABORT)
            {
                FtpNotify<Long> ftpNotify2 = (FtpNotify<Long>)ftpNotify;
                Long fileSize = ftpNotify2.getData();
                if (m_isDebug)
                    System.err.println("Stor abort fileSize = " + fileSize);
            }
        }
        return flag;
    }
   
    /**
     * @param str line to parse
     * @return <code>JFtpFile</code> object if format was recognized, else <code>null</code>
     */
    public JFtpFile parseListLine(String str)
    {
        JFtpFile ftpFile = null;
        // Linux style
        /* ftp.suse.com
        drwxr-xr-x    2 root     root         4096 May 26  2004 bin
        drwxr-xr-x    2 root     root         4096 May 26  2004 dev
        drwxr-xr-x    2 root     root         4096 Sep 10  2004 etc
        drwxr-xr-x    2 root     root         4096 May 26  2004 lib
        drwxr-xr-x    2 root     root         4096 Feb 13  2006 msgs
        drwxr-xr-x    8 ftp      root         4096 Dec 18 00:13 pub
        drwxr-xr-x    3 root     root         4096 May 26  2004 usr
        */

        Calendar cal = Calendar.getInstance();
        Calendar now = Calendar.getInstance();
        cal.set(Calendar.MILLISECOND, 0);
        cal.set(Calendar.SECOND, 0);

        Pattern pat = Pattern.compile("([dl-])((?:[r-][w-][xst-]){3})\\s+(\\d+)\\s+([^\\s]+)\\s+([^\\s]+)\\s+(\\d+)\\s+([a-zA-Z]{3})\\s+(\\d{1,2})\\s+(\\d{4}|\\d{2}:\\d{2})\\s+(.+)");
        Matcher m = pat.matcher(str);
        if (m.matches())
        {
            ftpFile = new JFtpFile();
            if (m.group(1).equals("-"))
                ftpFile.setType(JFtpFile.TYPE_FILE);
            else if (m.group(1).equals("d"))
                ftpFile.setType(JFtpFile.TYPE_DIRECTORY);
            else if (m.group(1).equals("l"))
                ftpFile.setType(JFtpFile.TYPE_LINK);

            ftpFile.setRights(m.group(2));
            ftpFile.setNumberOfHardLinks(Integer.parseInt(m.group(3)));
            ftpFile.setUser(m.group(4));
            ftpFile.setGroup(m.group(5));
            ftpFile.setSize(Long.parseLong(m.group(6)));

            String month = m.group(7);
            if (month.equalsIgnoreCase("jan"))
                cal.set(Calendar.MONTH, Calendar.JANUARY);
            else if (month.equalsIgnoreCase("feb"))
                cal.set(Calendar.MONTH, Calendar.FEBRUARY);
            else if (month.equalsIgnoreCase("mar"))
                cal.set(Calendar.MONTH, Calendar.MARCH);
            else if (month.equalsIgnoreCase("apr"))
                cal.set(Calendar.MONTH, Calendar.APRIL);
            else if (month.equalsIgnoreCase("may"))
                cal.set(Calendar.MONTH, Calendar.MAY);
            else if (month.equalsIgnoreCase("jun"))
                cal.set(Calendar.MONTH, Calendar.JUNE);
            else if (month.equalsIgnoreCase("jul"))
                cal.set(Calendar.MONTH, Calendar.JULY);
            else if (month.equalsIgnoreCase("aug"))
                cal.set(Calendar.MONTH, Calendar.AUGUST);
            else if (month.equalsIgnoreCase("sep"))
                cal.set(Calendar.MONTH, Calendar.SEPTEMBER);
            else if (month.equalsIgnoreCase("oct"))
                cal.set(Calendar.MONTH, Calendar.OCTOBER);
            else if (month.equalsIgnoreCase("nov"))
                cal.set(Calendar.MONTH, Calendar.NOVEMBER);
            else if (month.equalsIgnoreCase("dec"))
                cal.set(Calendar.MONTH, Calendar.DECEMBER);

            cal.set(Calendar.DATE, Integer.parseInt(m.group(8)));
            ftpFile.setTimeStamp(cal);

            pat = Pattern.compile("(\\d{2}):(\\d{2})");
            Matcher m2 = pat.matcher(m.group(9));
            if (m2.matches())
            {
                cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m2.group(1)));
                cal.set(Calendar.MINUTE, Integer.parseInt(m2.group(2)));
                // guess the year
                if (cal.get(Calendar.MONTH) > now.get(Calendar.MONTH))
                    cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
            }
            else
            {
                cal.set(Calendar.HOUR_OF_DAY, 0);
                cal.set(Calendar.MINUTE, 0);
                cal.set(Calendar.YEAR, Integer.parseInt(m.group(9)));
            }
            ftpFile.setName(m.group(10));
            m_bHasLastListOutputHardlinks = true;
        }
        if (ftpFile == null)
        {
            // Linux style icarus FTP server (Version wu-2.6.2(3)
            /* ftp.adfa.edu.au, ftp.sun.com, ftp.cnam.fr
            drwxr-xr-x   8 12           512 Mar 27  2002 .
            drwxr-xr-x   8 12           512 Mar 27  2002 ..
            drwxr-xr-x   4 1            512 Sep 26  1995 EPub
            -rw-r--r--   1 1          57574 Apr  3  2002 Index
            drwxr-xr-x   2 1            512 Jul 14  2000 NSS
            lrwxrwxrwx   1 1              7 Apr  3  2002 bin -> usr/bin
            dr-xr-xr-x   2 1            512 Mar 27  2002 dev
            dr-xr-xr-x   2 1            512 Apr 18  2002 etc
            -rw-r--r--   1 1          14797 Apr  3  2002 ls-lRt.Z
            drwxrwxrwx   5 1            512 Sep 26  2003 pub
            drwxr-xr-x   5 1            512 Mar 27  2002 usr
            -rw-r--r--   1 1            750 Aug 30  1999 welcome.msg
            */
            pat = Pattern.compile("([dl-])((?:[r-][w-][xst-]){3})\\s+([^\\s]+)\\s+(\\d+)\\s+(\\d+)\\s+([a-zA-Z]{3})\\s+(\\d{1,2})\\s+(\\d{4}|\\d{2}:\\d{2})\\s+(.+)");
            m = pat.matcher(str);
            if (m.matches())
            {
                ftpFile = new JFtpFile();
                if (m.group(1).equals("-"))
                    ftpFile.setType(JFtpFile.TYPE_FILE);
                else if (m.group(1).equals("d"))
                    ftpFile.setType(JFtpFile.TYPE_DIRECTORY);
                else if (m.group(1).equals("l"))
                    ftpFile.setType(JFtpFile.TYPE_LINK);

                ftpFile.setRights(m.group(2));
                ftpFile.setNumberOfHardLinks(Integer.parseInt(m.group(3)));
                ftpFile.setUser(m.group(4));
                ftpFile.setSize(Long.parseLong(m.group(5)));

                String month = m.group(6);
                if (month.equalsIgnoreCase("jan"))
                    cal.set(Calendar.MONTH, Calendar.JANUARY);
                else if (month.equalsIgnoreCase("feb"))
                    cal.set(Calendar.MONTH, Calendar.FEBRUARY);
                else if (month.equalsIgnoreCase("mar"))
                    cal.set(Calendar.MONTH, Calendar.MARCH);
                else if (month.equalsIgnoreCase("apr"))
                    cal.set(Calendar.MONTH, Calendar.APRIL);
                else if (month.equalsIgnoreCase("may"))
                    cal.set(Calendar.MONTH, Calendar.MAY);
                else if (month.equalsIgnoreCase("jun"))
                    cal.set(Calendar.MONTH, Calendar.JUNE);
                else if (month.equalsIgnoreCase("jul"))
                    cal.set(Calendar.MONTH, Calendar.JULY);
                else if (month.equalsIgnoreCase("aug"))
                    cal.set(Calendar.MONTH, Calendar.AUGUST);
                else if (month.equalsIgnoreCase("sep"))
                    cal.set(Calendar.MONTH, Calendar.SEPTEMBER);
                else if (month.equalsIgnoreCase("oct"))
                    cal.set(Calendar.MONTH, Calendar.OCTOBER);
                else if (month.equalsIgnoreCase("nov"))
                    cal.set(Calendar.MONTH, Calendar.NOVEMBER);
                else if (month.equalsIgnoreCase("dec"))
                    cal.set(Calendar.MONTH, Calendar.DECEMBER);

                cal.set(Calendar.DATE, Integer.parseInt(m.group(7)));
                ftpFile.setTimeStamp(cal);

                pat = Pattern.compile("(\\d{2}):(\\d{2})");
                Matcher m2 = pat.matcher(m.group(8));
                if (m2.matches())
                {
                    cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m2.group(1)));
                    cal.set(Calendar.MINUTE, Integer.parseInt(m2.group(2)));
                    // guess the year
                    if (cal.get(Calendar.MONTH) > now.get(Calendar.MONTH))
                    cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
                }
                else
                {
                    cal.set(Calendar.HOUR_OF_DAY, 0);
                    cal.set(Calendar.MINUTE, 0);
                    cal.set(Calendar.YEAR, Integer.parseInt(m.group(8)));
                }
                ftpFile.setName(m.group(9));
                m_bHasLastListOutputHardlinks = true;
            }
        }
        if (ftpFile == null)
        {
            // Linux style yshome PROXY-FTP server (DeleGate/9.4.2-pre1)
            /* ftp.delegate.org,  ftp.sunfreeware.com
            drwxrwxr-x  3 delegate     4096 Jan 25  2004 .
            drwxrwxr-x  6 delegate     4096 Feb  2  2005 ..
            drwxrwxr-x 13 delegate     4096 Aug 12  2005 pub
            rw-rw-r--  1 delegate      272 Jan 25  2004 rsa-pubkey.pem
             */
            // I'am not sure if the first digit is the number of links!
            pat = Pattern.compile("([dl-])((?:[r-][w-][xst-]){3})\\s+(\\d+)\\s+([^\\s]+)\\s+(\\d+)\\s+([a-zA-Z]{3})\\s+(\\d{1,2})\\s+(\\d{4}|\\d{2}:\\d{2})\\s+(.+)");
            m = pat.matcher(str);
            if (m.matches())
            {
                ftpFile = new JFtpFile();
                if (m.group(1).equals("-"))
                    ftpFile.setType(JFtpFile.TYPE_FILE);
                else if (m.group(1).equals("d"))
                    ftpFile.setType(JFtpFile.TYPE_DIRECTORY);
                else if (m.group(1).equals("l"))
                    ftpFile.setType(JFtpFile.TYPE_LINK);

                ftpFile.setRights(m.group(2));
                ftpFile.setNumberOfHardLinks(Integer.parseInt(m.group(3)));
                ftpFile.setUser(m.group(4));
                ftpFile.setSize(Long.parseLong(m.group(5)));

                String month = m.group(6);
                if (month.equalsIgnoreCase("jan"))
                    cal.set(Calendar.MONTH, Calendar.JANUARY);
                else if (month.equalsIgnoreCase("feb"))
                    cal.set(Calendar.MONTH, Calendar.FEBRUARY);
                else if (month.equalsIgnoreCase("mar"))
                    cal.set(Calendar.MONTH, Calendar.MARCH);
                else if (month.equalsIgnoreCase("apr"))
                    cal.set(Calendar.MONTH, Calendar.APRIL);
                else if (month.equalsIgnoreCase("may"))
                    cal.set(Calendar.MONTH, Calendar.MAY);
                else if (month.equalsIgnoreCase("jun"))
                    cal.set(Calendar.MONTH, Calendar.JUNE);
                else if (month.equalsIgnoreCase("jul"))
                    cal.set(Calendar.MONTH, Calendar.JULY);
                else if (month.equalsIgnoreCase("aug"))
                    cal.set(Calendar.MONTH, Calendar.AUGUST);
                else if (month.equalsIgnoreCase("sep"))
                    cal.set(Calendar.MONTH, Calendar.SEPTEMBER);
                else if (month.equalsIgnoreCase("oct"))
                    cal.set(Calendar.MONTH, Calendar.OCTOBER);
                else if (month.equalsIgnoreCase("nov"))
                    cal.set(Calendar.MONTH, Calendar.NOVEMBER);
                else if (month.equalsIgnoreCase("dec"))
                    cal.set(Calendar.MONTH, Calendar.DECEMBER);

                cal.set(Calendar.DATE, Integer.parseInt(m.group(7)));
                ftpFile.setTimeStamp(cal);

                pat = Pattern.compile("(\\d{2}):(\\d{2})");
                Matcher m2 = pat.matcher(m.group(8));
                if (m2.matches())
                {
                    cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m2.group(1)));
                    cal.set(Calendar.MINUTE, Integer.parseInt(m2.group(2)));
                    // guess the year
                    if (cal.get(Calendar.MONTH) > now.get(Calendar.MONTH))
                    cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
                }
                else
                {
                    cal.set(Calendar.HOUR_OF_DAY, 0);
                    cal.set(Calendar.MINUTE, 0);
                    cal.set(Calendar.YEAR, Integer.parseInt(m.group(8)));
                }
                ftpFile.setName(m.group(9));
                m_bHasLastListOutputHardlinks = true;
            }
        }
        if (ftpFile == null)
        {
            // Linux style freespirit FTP server (Version wu-2.6.2-gus050408)
            /* ftp.linuxfocus.org
            drwxr-xr-x   6 root   @ root   @     4096 May  5  2003 .
            drwxr-xr-x   6 root   @ root   @     4096 May  5  2003 ..
            drwxr-x--x   2 root   @ root   @     4096 May  5  2003 bin
            drwxr-x--x   2 root   @ root   @     4096 May  5  2003 etc
            drwxr-x--x   2 root   @ root   @     4096 May  5  2003 lib
            drwxr-xr-x   4 root   @ 50     @     4096 May  5  2003 pub
            -rw-r--r--   1 root   @ root   @      313 Jul 11  2001 welcome.msg      */
            pat = Pattern.compile("([dl-])((?:[r-][w-][xst-]){3})\\s+(\\d+)\\s+([^\\s]+)\\s+@\\s+([^\\s]+)\\s+@\\s+(\\d+)\\s+([a-zA-Z]{3})\\s+(\\d{1,2})\\s+(\\d{4}|\\d{2}:\\d{2})\\s+(.+)");
            m = pat.matcher(str);
            if (m.matches())
            {
                ftpFile = new JFtpFile();
                if (m.group(1).equals("-"))
                    ftpFile.setType(JFtpFile.TYPE_FILE);
                else if (m.group(1).equals("d"))
                    ftpFile.setType(JFtpFile.TYPE_DIRECTORY);
                else if (m.group(1).equals("l"))
                    ftpFile.setType(JFtpFile.TYPE_LINK);

                ftpFile.setRights(m.group(2));
                ftpFile.setNumberOfHardLinks(Integer.parseInt(m.group(3)));
                ftpFile.setUser(m.group(4));
                ftpFile.setGroup(m.group(5));
                ftpFile.setSize(Long.parseLong(m.group(6)));

                String month = m.group(7);
                if (month.equalsIgnoreCase("jan"))
                    cal.set(Calendar.MONTH, Calendar.JANUARY);
                else if (month.equalsIgnoreCase("feb"))
                    cal.set(Calendar.MONTH, Calendar.FEBRUARY);
                else if (month.equalsIgnoreCase("mar"))
                    cal.set(Calendar.MONTH, Calendar.MARCH);
                else if (month.equalsIgnoreCase("apr"))
                    cal.set(Calendar.MONTH, Calendar.APRIL);
                else if (month.equalsIgnoreCase("may"))
                    cal.set(Calendar.MONTH, Calendar.MAY);
                else if (month.equalsIgnoreCase("jun"))
                    cal.set(Calendar.MONTH, Calendar.JUNE);
                else if (month.equalsIgnoreCase("jul"))
                    cal.set(Calendar.MONTH, Calendar.JULY);
                else if (month.equalsIgnoreCase("aug"))
                    cal.set(Calendar.MONTH, Calendar.AUGUST);
                else if (month.equalsIgnoreCase("sep"))
                    cal.set(Calendar.MONTH, Calendar.SEPTEMBER);
                else if (month.equalsIgnoreCase("oct"))
                    cal.set(Calendar.MONTH, Calendar.OCTOBER);
                else if (month.equalsIgnoreCase("nov"))
                    cal.set(Calendar.MONTH, Calendar.NOVEMBER);
                else if (month.equalsIgnoreCase("dec"))
                    cal.set(Calendar.MONTH, Calendar.DECEMBER);

                cal.set(Calendar.DATE, Integer.parseInt(m.group(8)));
                ftpFile.setTimeStamp(cal);

                pat = Pattern.compile("(\\d{2}):(\\d{2})");
                Matcher m2 = pat.matcher(m.group(9));
                if (m2.matches())
                {
                    cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(m2.group(1)));
                    cal.set(Calendar.MINUTE, Integer.parseInt(m2.group(2)));
                    // guess the year
                    if (cal.get(Calendar.MONTH) > now.get(Calendar.MONTH))
                    cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) - 1);
                }
                else
                {
                    cal.set(Calendar.HOUR_OF_DAY, 0);
                    cal.set(Calendar.MINUTE, 0);
                    cal.set(Calendar.YEAR, Integer.parseInt(m.group(9)));
                }
                ftpFile.setName(m.group(10));
                m_bHasLastListOutputHardlinks = true;
            }
        }
        if (ftpFile == null)
        {
            /*
            MSDOS style
            05-29-03  11:57AM       <DIR>          Control
            02-21-03  11:39AM       <DIR>          emergency
            05-13-03  02:20PM       <DIR>          MediaSync
            11-14-06  07:44PM       <DIR>          Reiner
            02-28-03  12:01PM       <DIR>          Router
            03-23-05  04:15PM       <DIR>          Sound
            11-12-04  08:58AM       <DIR>          tempStreams
            02-21-03  01:27PM       <DIR>          wma
            12-16-04  02:19PM       <DIR>          WUTemp
            11-18-03  02:48PM       <DIR>          wwwRoot
            */
            pat = Pattern.compile("(\\d{2})-(\\d{2})-(\\d{2})\\s+(\\d{2}):(\\d{2})([A|P]M)\\s+(<DIR>|\\d+)\\s+(.+)");
            m = pat.matcher(str);
            if (m.matches())
            {
                ftpFile = new JFtpFile();
                cal.set(Calendar.MONTH, Integer.parseInt(m.group(1)) - 1);
                cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(m.group(2)));
                cal.set(Calendar.YEAR, Integer.parseInt(m.group(3)));
                cal.set(Calendar.HOUR, Integer.parseInt(m.group(4)));
                cal.set(Calendar.MINUTE, Integer.parseInt(m.group(5)));
                cal.set(Calendar.AM_PM, m.group(6).equalsIgnoreCase("pm") ? Calendar.PM : Calendar.AM);
                ftpFile.setTimeStamp(cal);
                try
                {
                    ftpFile.setSize(Long.parseLong(m.group(7)));
                    ftpFile.setType(JFtpFile.TYPE_FILE);
                }
                catch(NumberFormatException ex)
                {
                    ftpFile.setType(JFtpFile.TYPE_DIRECTORY);
                }
                ftpFile.setName(m.group(8));
                m_bHasLastListOutputHardlinks = false;
            }
        }
        if (m_isDebug)
        {
            if (ftpFile == null)
            System.err.println("NO MATCH FOUND FOR '"+str + "'");
        }
        return ftpFile;
    }

    private void closeSocket(Socket socket)
    {
        if (socket != null)
        {
            try
                {socket.close();}
            catch(Exception ex)
            {}
        }
    }
    private void closeSocket(ServerSocket socket)
    {
        if (socket != null)
        {
            try
                {socket.close();}
            catch(Exception ex)
            {}
        }
    }
}
TOP

Related Classes of shared.ftp.JFtp

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.