You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
599 lines
17 KiB
599 lines
17 KiB
15 years ago
|
// -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 2; -*-
|
||
|
/* This file is part of the KDE libraries
|
||
|
Copyright (C) 2000 David Faure <faure@kde.org>
|
||
|
|
||
|
This library is free software; you can redistribute it and/or
|
||
|
modify it under the terms of the GNU Library General Public
|
||
|
License as published by the Free Software Foundation; either
|
||
|
version 2 of the License, or (at your option) any later version.
|
||
|
|
||
|
This library 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
|
||
|
Library General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU Library General Public License
|
||
|
along with this library; see the file COPYING.LIB. If not, write to
|
||
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||
|
Boston, MA 02110-1301, USA.
|
||
|
*/
|
||
|
|
||
|
// $Id$
|
||
|
|
||
|
#ifndef __ftp_h__
|
||
|
#define __ftp_h__
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/socket.h>
|
||
|
|
||
|
#include <qcstring.h>
|
||
|
#include <qstring.h>
|
||
|
|
||
|
#include <kurl.h>
|
||
|
#include <kio/slavebase.h>
|
||
|
#include <kextsock.h>
|
||
|
#include <ksocks.h>
|
||
|
|
||
|
struct FtpEntry
|
||
|
{
|
||
|
QString name;
|
||
|
QString owner;
|
||
|
QString group;
|
||
|
QString link;
|
||
|
|
||
|
KIO::filesize_t size;
|
||
|
mode_t type;
|
||
|
mode_t access;
|
||
|
time_t date;
|
||
|
};
|
||
|
|
||
|
//===============================================================================
|
||
|
// FtpTextReader A helper class to read text lines from a socket
|
||
|
//===============================================================================
|
||
|
|
||
|
#ifdef KIO_FTP_PRIVATE_INCLUDE
|
||
|
class FtpSocket;
|
||
|
|
||
|
class FtpTextReader
|
||
|
{
|
||
|
public:
|
||
|
FtpTextReader() { textClear(); }
|
||
|
|
||
|
/**
|
||
|
* Resets the status of the object, also called from xtor
|
||
|
*/
|
||
|
void textClear();
|
||
|
|
||
|
/**
|
||
|
* Read a line from the socket into m_szText. Only the first RESP_READ_LIMIT
|
||
|
* characters are copied. If the server response is longer all extra data up to
|
||
|
* the new-line gets discarded. An ending CR gets stripped. The number of chars
|
||
|
* in the buffer is returned. Use textToLong() to check for truncation!
|
||
|
*/
|
||
|
int textRead(FtpSocket *pSock);
|
||
|
|
||
|
/**
|
||
|
* An accessor to the data read by textRead()
|
||
|
*/
|
||
|
const char* textLine() const { return m_szText; }
|
||
|
|
||
|
/**
|
||
|
* Returns true if the last textRead() resulted in a truncated line
|
||
|
*/
|
||
|
bool textTooLong() const { return m_bTextTruncated; }
|
||
|
|
||
|
/**
|
||
|
* Returns true if the last textRead() got an EOF or an error
|
||
|
*/
|
||
|
bool textEOF() const { return m_bTextEOF; }
|
||
|
|
||
|
enum {
|
||
|
|
||
|
/**
|
||
|
* This is the physical size of m_szText. Only up to textReadLimit
|
||
|
* characters are used to store a server reply. If the server reply
|
||
|
* is longer, the stored line gets truncated - see textTooLong()!
|
||
|
*/
|
||
|
textReadBuffer = 2048,
|
||
|
|
||
|
/**
|
||
|
* Max number of chars returned from textLine(). If the server
|
||
|
* sends more all chars until the next new-line are discarded.
|
||
|
*/
|
||
|
textReadLimit = 1024
|
||
|
};
|
||
|
|
||
|
private:
|
||
|
/**
|
||
|
* textRead() sets this true on trucation (e.g. line too long)
|
||
|
*/
|
||
|
bool m_bTextTruncated;
|
||
|
|
||
|
/**
|
||
|
* textRead() sets this true if the read returns 0 bytes or error
|
||
|
*/
|
||
|
bool m_bTextEOF;
|
||
|
|
||
|
/**
|
||
|
* textRead() fills this buffer with data
|
||
|
*/
|
||
|
char m_szText[textReadBuffer];
|
||
|
|
||
|
/**
|
||
|
* the number of bytes in the current response line
|
||
|
*/
|
||
|
int m_iTextLine;
|
||
|
|
||
|
/**
|
||
|
* the number of bytes in the response buffer (includes m_iRespLine)
|
||
|
*/
|
||
|
int m_iTextBuff;
|
||
|
};
|
||
|
#endif // KIO_FTP_PRIVATE_INCLUDE
|
||
|
|
||
|
//===============================================================================
|
||
|
// FtpSocket Helper Class for Data or Control Connections
|
||
|
//===============================================================================
|
||
|
#ifdef KIO_FTP_PRIVATE_INCLUDE
|
||
|
class FtpSocket : public FtpTextReader, public KExtendedSocket
|
||
|
{
|
||
|
private:
|
||
|
// hide the default xtor
|
||
|
FtpSocket() {}
|
||
|
public:
|
||
|
/**
|
||
|
* The one and only public xtor. The string data passed to the
|
||
|
* xtor must remain valid during the object's lifetime - it is
|
||
|
* used in debug messages to identify the socket instance.
|
||
|
*/
|
||
|
FtpSocket(const char* pszName)
|
||
|
{
|
||
|
m_pszName = pszName;
|
||
|
m_server = -1;
|
||
|
}
|
||
|
|
||
|
~FtpSocket() { closeSocket(); }
|
||
|
|
||
|
/**
|
||
|
* Resets the status of the object, also called from xtor
|
||
|
*/
|
||
|
void closeSocket();
|
||
|
|
||
|
/**
|
||
|
* We may have a server connection socket if not in passive mode. This
|
||
|
* routine returns the server socket set by setServer. The sock()
|
||
|
* function will return the server socket - if it is set.
|
||
|
*/
|
||
|
int server() const { return m_server; }
|
||
|
|
||
|
/**
|
||
|
* Set the server socket if arg >= 0, otherwise clear it.
|
||
|
*/
|
||
|
void setServer(int i) { m_server = (i >= 0) ? i : -1; }
|
||
|
|
||
|
/**
|
||
|
* returns the effective socket that user used for read/write. See server()
|
||
|
*/
|
||
|
int sock() const { return (m_server != -1) ? m_server : fd(); }
|
||
|
|
||
|
/**
|
||
|
* output an debug message via kdDebug
|
||
|
*/
|
||
|
void debugMessage(const char* pszMsg) const;
|
||
|
|
||
|
/**
|
||
|
* output an error message via kdError, returns iErrorCode
|
||
|
*/
|
||
|
int errorMessage(int iErrorCode, const char* pszMsg) const;
|
||
|
|
||
|
/**
|
||
|
* connect socket and set some options (reuse, keepalive, linger)
|
||
|
*/
|
||
|
int connectSocket(int iTimeOutSec, bool bControl);
|
||
|
|
||
|
/**
|
||
|
* utility to simplify calls to ::setsockopt(). Uses sock().
|
||
|
*/
|
||
|
bool setSocketOption(int opt, char*arg, socklen_t len) const;
|
||
|
|
||
|
/**
|
||
|
* utility to read data from the effective socket, see sock()
|
||
|
*/
|
||
|
long read(void* pData, long iMaxlen)
|
||
|
{
|
||
|
return KSocks::self()->read(sock(), pData, iMaxlen);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* utility to write data to the effective socket, see sock()
|
||
|
*/
|
||
|
long write(void* pData, long iMaxlen)
|
||
|
{
|
||
|
return KSocks::self()->write(sock(), pData, iMaxlen);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Use the inherited FtpTextReader to read a line from the socket
|
||
|
*/
|
||
|
int textRead()
|
||
|
{
|
||
|
return FtpTextReader::textRead(this);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
const char* m_pszName; // set by the xtor, used for debug output
|
||
|
int m_server; // socket override, see setSock()
|
||
|
};
|
||
|
#else
|
||
|
class FtpSocket;
|
||
|
#endif // KIO_FTP_PRIVATE_INCLUDE
|
||
|
|
||
|
//===============================================================================
|
||
|
// Ftp
|
||
|
//===============================================================================
|
||
|
class Ftp : public KIO::SlaveBase
|
||
|
{
|
||
|
// Ftp() {}
|
||
|
|
||
|
public:
|
||
|
Ftp( const QCString &pool, const QCString &app );
|
||
|
virtual ~Ftp();
|
||
|
|
||
|
virtual void setHost( const QString& host, int port, const QString& user, const QString& pass );
|
||
|
|
||
|
/**
|
||
|
* Connects to a ftp server and logs us in
|
||
|
* m_bLoggedOn is set to true if logging on was successful.
|
||
|
* It is set to false if the connection becomes closed.
|
||
|
*
|
||
|
*/
|
||
|
virtual void openConnection();
|
||
|
|
||
|
/**
|
||
|
* Closes the connection
|
||
|
*/
|
||
|
virtual void closeConnection();
|
||
|
|
||
|
virtual void stat( const KURL &url );
|
||
|
|
||
|
virtual void listDir( const KURL & url );
|
||
|
virtual void mkdir( const KURL & url, int permissions );
|
||
|
virtual void rename( const KURL & src, const KURL & dest, bool overwrite );
|
||
|
virtual void del( const KURL & url, bool isfile );
|
||
|
virtual void chmod( const KURL & url, int permissions );
|
||
|
|
||
|
virtual void get( const KURL& url );
|
||
|
virtual void put( const KURL& url, int permissions, bool overwrite, bool resume);
|
||
|
//virtual void mimetype( const KURL& url );
|
||
|
|
||
|
virtual void slave_status();
|
||
|
|
||
|
/**
|
||
|
* Handles the case that one side of the job is a local file
|
||
|
*/
|
||
|
virtual void copy( const KURL &src, const KURL &dest, int permissions, bool overwrite );
|
||
|
|
||
|
private:
|
||
|
// ------------------------------------------------------------------------
|
||
|
// All the methods named ftpXyz are lowlevel methods that are not exported.
|
||
|
// The implement functionality used by the public high-level methods. Some
|
||
|
// low-level methods still use error() to emit errors. This behaviour is not
|
||
|
// recommended - please return a boolean status or an error code instead!
|
||
|
// ------------------------------------------------------------------------
|
||
|
|
||
|
/**
|
||
|
* Status Code returned from ftpPut() and ftpGet(), used to select
|
||
|
* source or destination url for error messages
|
||
|
*/
|
||
|
typedef enum {
|
||
|
statusSuccess,
|
||
|
statusClientError,
|
||
|
statusServerError
|
||
|
} StatusCode;
|
||
|
|
||
|
/**
|
||
|
* Login Mode for ftpOpenConnection
|
||
|
*/
|
||
|
typedef enum {
|
||
|
loginDefered,
|
||
|
loginExplicit,
|
||
|
loginImplicit
|
||
|
} LoginMode;
|
||
|
|
||
|
/**
|
||
|
* Connect and login to the FTP server.
|
||
|
*
|
||
|
* @param loginMode controls if login info should be sent<br>
|
||
|
* loginDefered - must not be logged on, no login info is sent<br>
|
||
|
* loginExplicit - must not be logged on, login info is sent<br>
|
||
|
* loginImplicit - login info is sent if not logged on
|
||
|
*
|
||
|
* @return true on success (a login failure would return false).
|
||
|
*/
|
||
|
bool ftpOpenConnection (LoginMode loginMode);
|
||
|
|
||
|
/**
|
||
|
* Executes any auto login macro's as specified in a .netrc file.
|
||
|
*/
|
||
|
void ftpAutoLoginMacro ();
|
||
|
|
||
|
/**
|
||
|
* Called by openConnection. It logs us in.
|
||
|
* m_initialPath is set to the current working directory
|
||
|
* if logging on was successful.
|
||
|
*
|
||
|
* @return true on success.
|
||
|
*/
|
||
|
bool ftpLogin();
|
||
|
|
||
|
/**
|
||
|
* ftpSendCmd - send a command (@p cmd) and read response
|
||
|
*
|
||
|
* @param maxretries number of time it should retry. Since it recursively
|
||
|
* calls itself if it can't read the answer (this happens especially after
|
||
|
* timeouts), we need to limit the recursiveness ;-)
|
||
|
*
|
||
|
* return true if any response received, false on error
|
||
|
*/
|
||
|
bool ftpSendCmd( const QCString& cmd, int maxretries = 1 );
|
||
|
|
||
|
/**
|
||
|
* Use the SIZE command to get the file size.
|
||
|
* @param mode the size depends on the transfer mode, hence this arg.
|
||
|
* @return true on success
|
||
|
* Gets the size into m_size.
|
||
|
*/
|
||
|
bool ftpSize( const QString & path, char mode );
|
||
|
|
||
|
/**
|
||
|
* Set the current working directory, but only if not yet current
|
||
|
*/
|
||
|
bool ftpFolder(const QString& path, bool bReportError);
|
||
|
|
||
|
/**
|
||
|
* Runs a command on the ftp server like "list" or "retr". In contrast to
|
||
|
* ftpSendCmd a data connection is opened. The corresponding socket
|
||
|
* sData is available for reading/writing on success.
|
||
|
* The connection must be closed afterwards with ftpCloseCommand.
|
||
|
*
|
||
|
* @param mode is 'A' or 'I'. 'A' means ASCII transfer, 'I' means binary transfer.
|
||
|
* @param errorcode the command-dependent error code to emit on error
|
||
|
*
|
||
|
* @return true if the command was accepted by the server.
|
||
|
*/
|
||
|
bool ftpOpenCommand( const char *command, const QString & path, char mode,
|
||
|
int errorcode, KIO::fileoffset_t offset = 0 );
|
||
|
|
||
|
/**
|
||
|
* The counterpart to openCommand.
|
||
|
* Closes data sockets and then reads line sent by server at
|
||
|
* end of command.
|
||
|
* @return false on error (line doesn't start with '2')
|
||
|
*/
|
||
|
bool ftpCloseCommand();
|
||
|
|
||
|
/**
|
||
|
* Send "TYPE I" or "TYPE A" only if required, see m_cDataMode.
|
||
|
*
|
||
|
* Use 'A' to select ASCII and 'I' to select BINARY mode. If
|
||
|
* cMode is '?' the m_bTextMode flag is used to choose a mode.
|
||
|
*/
|
||
|
bool ftpDataMode(char cMode);
|
||
|
|
||
|
//void ftpAbortTransfer();
|
||
|
|
||
|
/**
|
||
|
* Used by ftpOpenCommand, return 0 on success or an error code
|
||
|
*/
|
||
|
int ftpOpenDataConnection();
|
||
|
|
||
|
/**
|
||
|
* closes a data connection, see ftpOpenDataConnection()
|
||
|
*/
|
||
|
void ftpCloseDataConnection();
|
||
|
|
||
|
/**
|
||
|
* Helper for ftpOpenDataConnection
|
||
|
*/
|
||
|
int ftpOpenPASVDataConnection();
|
||
|
/**
|
||
|
* Helper for ftpOpenDataConnection
|
||
|
*/
|
||
|
int ftpOpenEPSVDataConnection();
|
||
|
/**
|
||
|
* Helper for ftpOpenDataConnection
|
||
|
*/
|
||
|
int ftpOpenEPRTDataConnection();
|
||
|
/**
|
||
|
* Helper for ftpOpenDataConnection
|
||
|
*/
|
||
|
int ftpOpenPortDataConnection();
|
||
|
|
||
|
/**
|
||
|
* ftpAcceptConnect - wait for incoming connection
|
||
|
*
|
||
|
* return -2 on error or timeout
|
||
|
* otherwise returns socket descriptor
|
||
|
*/
|
||
|
int ftpAcceptConnect();
|
||
|
|
||
|
bool ftpChmod( const QString & path, int permissions );
|
||
|
|
||
|
// used by listDir
|
||
|
bool ftpOpenDir( const QString & path );
|
||
|
/**
|
||
|
* Called to parse directory listings, call this until it returns false
|
||
|
*/
|
||
|
bool ftpReadDir(FtpEntry& ftpEnt);
|
||
|
|
||
|
/**
|
||
|
* Helper to fill an UDSEntry
|
||
|
*/
|
||
|
void ftpCreateUDSEntry( const QString & filename, FtpEntry& ftpEnt, KIO::UDSEntry& entry, bool isDir );
|
||
|
|
||
|
void ftpShortStatAnswer( const QString& filename, bool isDir );
|
||
|
|
||
|
void ftpStatAnswerNotFound( const QString & path, const QString & filename );
|
||
|
|
||
|
/**
|
||
|
* This is the internal implementation of rename() - set put().
|
||
|
*
|
||
|
* @return true on success.
|
||
|
*/
|
||
|
bool ftpRename( const QString & src, const QString & dst, bool overwrite );
|
||
|
|
||
|
/**
|
||
|
* Called by openConnection. It opens the control connection to the ftp server.
|
||
|
*
|
||
|
* @return true on success.
|
||
|
*/
|
||
|
bool ftpOpenControlConnection( const QString & host, unsigned short int port );
|
||
|
|
||
|
/**
|
||
|
* closes the socket holding the control connection (see ftpOpenControlConnection)
|
||
|
*/
|
||
|
void ftpCloseControlConnection();
|
||
|
|
||
|
/**
|
||
|
* read a response from the server (a trailing CR gets stripped)
|
||
|
* @param iOffset -1 to read a new line from the server<br>
|
||
|
* 0 to return the whole response string
|
||
|
* >0 to return the response with iOffset chars skipped
|
||
|
* @return the reponse message with iOffset chars skipped (or "" if iOffset points
|
||
|
* behind the available data)
|
||
|
*/
|
||
|
const char* ftpResponse(int iOffset);
|
||
|
|
||
|
/**
|
||
|
* This is the internal implementation of get() - see copy().
|
||
|
*
|
||
|
* IMPORTANT: the caller should call ftpCloseCommand() on return.
|
||
|
* The function does not call error(), the caller should do this.
|
||
|
*
|
||
|
* @param iError set to an ERR_xxxx code on error
|
||
|
* @param iCopyFile -1 -or- handle of a local destination file
|
||
|
* @param hCopyOffset local file only: non-zero for resume
|
||
|
* @return 0 for success, -1 for server error, -2 for client error
|
||
|
*/
|
||
|
StatusCode ftpGet(int& iError, int iCopyFile, const KURL& url, KIO::fileoffset_t hCopyOffset);
|
||
|
|
||
|
/**
|
||
|
* This is the internal implementation of put() - see copy().
|
||
|
*
|
||
|
* IMPORTANT: the caller should call ftpCloseCommand() on return.
|
||
|
* The function does not call error(), the caller should do this.
|
||
|
*
|
||
|
* @param iError set to an ERR_xxxx code on error
|
||
|
* @param iCopyFile -1 -or- handle of a local source file
|
||
|
* @return 0 for success, -1 for server error, -2 for client error
|
||
|
*/
|
||
|
StatusCode ftpPut(int& iError, int iCopyFile, const KURL& url, int permissions, bool overwrite, bool resume);
|
||
|
|
||
|
/**
|
||
|
* helper called from copy() to implement FILE -> FTP transfers
|
||
|
*
|
||
|
* @param iError set to an ERR_xxxx code on error
|
||
|
* @param iCopyFile [out] handle of a local source file
|
||
|
* @param sCopyFile path of the local source file
|
||
|
* @return 0 for success, -1 for server error, -2 for client error
|
||
|
*/
|
||
|
StatusCode ftpCopyPut(int& iError, int& iCopyFile, QString sCopyFile, const KURL& url, int permissions, bool overwrite);
|
||
|
|
||
|
/**
|
||
|
* helper called from copy() to implement FTP -> FILE transfers
|
||
|
*
|
||
|
* @param iError set to an ERR_xxxx code on error
|
||
|
* @param iCopyFile [out] handle of a local source file
|
||
|
* @param sCopyFile path of the local destination file
|
||
|
* @return 0 for success, -1 for server error, -2 for client error
|
||
|
*/
|
||
|
StatusCode ftpCopyGet(int& iError, int& iCopyFile, QString sCopyFile, const KURL& url, int permissions, bool overwrite);
|
||
|
|
||
|
private: // data members
|
||
|
|
||
|
QString m_host;
|
||
|
unsigned short int m_port;
|
||
|
QString m_user;
|
||
|
QString m_pass;
|
||
|
/**
|
||
|
* Where we end up after connecting
|
||
|
*/
|
||
|
QString m_initialPath;
|
||
|
KURL m_proxyURL;
|
||
|
|
||
|
/**
|
||
|
* the current working directory - see ftpFolder
|
||
|
*/
|
||
|
QString m_currentPath;
|
||
|
|
||
|
/**
|
||
|
* the status returned by the FTP protocol, set in ftpResponse()
|
||
|
*/
|
||
|
int m_iRespCode;
|
||
|
|
||
|
/**
|
||
|
* the status/100 returned by the FTP protocol, set in ftpResponse()
|
||
|
*/
|
||
|
int m_iRespType;
|
||
|
|
||
|
/**
|
||
|
* This flag is maintained by ftpDataMode() and contains I or A after
|
||
|
* ftpDataMode() has successfully set the mode.
|
||
|
*/
|
||
|
char m_cDataMode;
|
||
|
|
||
|
/**
|
||
|
* true if logged on (m_control should also be non-NULL)
|
||
|
*/
|
||
|
bool m_bLoggedOn;
|
||
|
|
||
|
/**
|
||
|
* true if a "textmode" metadata key was found by ftpLogin(). This
|
||
|
* switches the ftp data transfer mode from binary to ASCII.
|
||
|
*/
|
||
|
bool m_bTextMode;
|
||
|
|
||
|
/**
|
||
|
* true if a data stream is open, used in closeConnection().
|
||
|
*
|
||
|
* When the user cancels a get or put command the Ftp dtor will be called,
|
||
|
* which in turn calls closeConnection(). The later would try to send QUIT
|
||
|
* which won't work until timeout. ftpOpenCommand sets the m_bBusy flag so
|
||
|
* that the sockets will be closed immedeately - the server should be
|
||
|
* capable of handling this and return an error code on thru the control
|
||
|
* connection. The m_bBusy gets cleared by the ftpCloseCommand() routine.
|
||
|
*/
|
||
|
bool m_bBusy;
|
||
|
|
||
|
bool m_bPasv;
|
||
|
bool m_bUseProxy;
|
||
|
|
||
|
KIO::filesize_t m_size;
|
||
|
static KIO::filesize_t UnknownSize;
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
epsvUnknown = 0x01,
|
||
|
epsvAllUnknown = 0x02,
|
||
|
eprtUnknown = 0x04,
|
||
|
epsvAllSent = 0x10,
|
||
|
pasvUnknown = 0x20,
|
||
|
chmodUnknown = 0x100
|
||
|
};
|
||
|
int m_extControl;
|
||
|
|
||
|
/**
|
||
|
* control connection socket, only set if openControl() succeeded
|
||
|
*/
|
||
|
FtpSocket *m_control;
|
||
|
|
||
|
/**
|
||
|
* data connection socket
|
||
|
*/
|
||
|
FtpSocket *m_data;
|
||
|
};
|
||
|
|
||
|
#endif
|