//#define QFTPPI_DEBUG
//#define QFTPDTP_DEBUG
#include "qftp.h"
#include "qabstractsocket.h"
#ifndef QT_NO_FTP
#include "qcoreapplication.h"
#include "qtcpsocket.h"
#include "qurlinfo.h"
#include "qstringlist.h"
#include "qregexp.h"
#include "qtimer.h"
#include "qfileinfo.h"
#include "qhash.h"
#include "qtcpserver.h"
#include "qlocale.h"
QT_BEGIN_NAMESPACE
class QFtpPI;
/*
The QFtpDTP (DTP = Data Transfer Process) controls all client side
data transfer between the client and server.
*/
class QFtpDTP : public QObject
{
Q_OBJECT
public:
enum ConnectState {
CsHostFound,
CsConnected,
CsClosed,
CsHostNotFound,
CsConnectionRefused
};
QFtpDTP(QFtpPI *p, QObject *parent = 0);
void setData(QByteArray *);
void setDevice(QIODevice *);
void writeData();
void setBytesTotal(qint64 bytes);
bool hasError() const;
QString errorMessage() const;
void clearError();
void connectToHost(const QString & host, quint16 port);
int setupListener(const QHostAddress &address);
void waitForConnection();
QTcpSocket::SocketState state() const;
qint64 bytesAvailable() const;
qint64 read(char *data, qint64 maxlen);
QByteArray readAll();
void abortConnection();
static bool parseDir(const QByteArray &buffer, const QString &userName, QUrlInfo *info);
signals:
void listInfo(const QUrlInfo&);
void readyRead();
void dataTransferProgress(qint64, qint64);
void connectState(int);
private slots:
void socketConnected();
void socketReadyRead();
void socketError(QAbstractSocket::SocketError);
void socketConnectionClosed();
void socketBytesWritten(qint64);
void setupSocket();
void dataReadyRead();
private:
void clearData();
QTcpSocket *socket;
QTcpServer listener;
QFtpPI *pi;
QString err;
qint64 bytesDone;
qint64 bytesTotal;
bool callWriteData;
// If is_ba is true, ba is used; ba is never 0.
// Otherwise dev is used; dev can be 0 or not.
union {
QByteArray *ba;
QIODevice *dev;
} data;
bool is_ba;
QByteArray bytesFromSocket;
};
/**********************************************************************
*
* QFtpPI - Protocol Interpreter
*
*********************************************************************/
class QFtpPI : public QObject
{
Q_OBJECT
public:
QFtpPI(QObject *parent = 0);
void connectToHost(const QString &host, quint16 port);
bool sendCommands(const QStringList &cmds);
bool sendCommand(const QString &cmd)
{ return sendCommands(QStringList(cmd)); }
void clearPendingCommands();
void abort();
QString currentCommand() const
{ return currentCmd; }
bool rawCommand;
bool transferConnectionExtended;
QFtpDTP dtp; // the PI has a DTP which is not the design of RFC 959, but it
// makes the design simpler this way
signals:
void connectState(int);
void finished(const QString&);
void error(int, const QString&);
void rawFtpReply(int, const QString&);
private slots:
void hostFound();
void connected();
void connectionClosed();
void delayedCloseFinished();
void readyRead();
void error(QAbstractSocket::SocketError);
void dtpConnectState(int);
private:
// the states are modelled after the generalized state diagram of RFC 959,
// page 58
enum State {
Begin,
Idle,
Waiting,
Success,
Failure
};
enum AbortState {
None,
AbortStarted,
WaitForAbortToFinish
};
bool processReply();
bool startNextCmd();
QTcpSocket commandSocket;
QString replyText;
char replyCode[3];
State state;
AbortState abortState;
QStringList pendingCommands;
QString currentCmd;
bool waitForDtpToConnect;
bool waitForDtpToClose;
QByteArray bytesFromSocket;
friend class QFtpDTP;
};
/**********************************************************************
*
* QFtpCommand implemenatation
*
*********************************************************************/
class QFtpCommand
{
public:
QFtpCommand(QFtp::Command cmd, QStringList raw, const QByteArray &ba);
QFtpCommand(QFtp::Command cmd, QStringList raw, QIODevice *dev = 0);
~QFtpCommand();
int id;
QFtp::Command command;
QStringList rawCmds;
// If is_ba is true, ba is used; ba is never 0.
// Otherwise dev is used; dev can be 0 or not.
union {
QByteArray *ba;
QIODevice *dev;
} data;
bool is_ba;
static QBasicAtomicInt idCounter;
};
QBasicAtomicInt QFtpCommand::idCounter = Q_BASIC_ATOMIC_INITIALIZER(1);
QFtpCommand::QFtpCommand(QFtp::Command cmd, QStringList raw, const QByteArray &ba)
: command(cmd), rawCmds(raw), is_ba(true)
{
id = idCounter.fetchAndAddRelaxed(1);
data.ba = new QByteArray(ba);
}
QFtpCommand::QFtpCommand(QFtp::Command cmd, QStringList raw, QIODevice *dev)
: command(cmd), rawCmds(raw), is_ba(false)
{
id = idCounter.fetchAndAddRelaxed(1);
data.dev = dev;
}
QFtpCommand::~QFtpCommand()
{
if (is_ba)
delete data.ba;
}
/**********************************************************************
*
* QFtpDTP implemenatation
*
*********************************************************************/
QFtpDTP::QFtpDTP(QFtpPI *p, QObject *parent) :
QObject(parent),
socket(0),
listener(this),
pi(p),
callWriteData(false)
{
clearData();
listener.setObjectName(QLatin1String("QFtpDTP active state server"));
connect(&listener, SIGNAL(newConnection()), SLOT(setupSocket()));
}
void QFtpDTP::setData(QByteArray *ba)
{
is_ba = true;
data.ba = ba;
}
void QFtpDTP::setDevice(QIODevice *dev)
{
is_ba = false;
data.dev = dev;
}
void QFtpDTP::setBytesTotal(qint64 bytes)
{
bytesTotal = bytes;
bytesDone = 0;
emit dataTransferProgress(bytesDone, bytesTotal);
}
void QFtpDTP::connectToHost(const QString & host, quint16 port)
{
bytesFromSocket.clear();
if (socket) {
delete socket;
socket = 0;
}
socket = new QTcpSocket(this);
socket->setObjectName(QLatin1String("QFtpDTP Passive state socket"));
connect(socket, SIGNAL(connected()), SLOT(socketConnected()));
connect(socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError)));
connect(socket, SIGNAL(disconnected()), SLOT(socketConnectionClosed()));
connect(socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
socket->connectToHost(host, port);
}
int QFtpDTP::setupListener(const QHostAddress &address)
{
if (!listener.isListening() && !listener.listen(address, 0))
return -1;
return listener.serverPort();
}
void QFtpDTP::waitForConnection()
{
// This function is only interesting in Active transfer mode; it works
// around a limitation in QFtp's design by blocking, waiting for an
// incoming connection. For the default Passive mode, it does nothing.
if (listener.isListening())
listener.waitForNewConnection();
}
QTcpSocket::SocketState QFtpDTP::state() const
{
return socket ? socket->state() : QTcpSocket::UnconnectedState;
}
qint64 QFtpDTP::bytesAvailable() const
{
if (!socket || socket->state() != QTcpSocket::ConnectedState)
return (qint64) bytesFromSocket.size();
return socket->bytesAvailable();
}
qint64 QFtpDTP::read(char *data, qint64 maxlen)
{
qint64 read;
if (socket && socket->state() == QTcpSocket::ConnectedState) {
read = socket->read(data, maxlen);
} else {
read = bytesFromSocket.size();
memcpy(data, bytesFromSocket.data(), read);
bytesFromSocket.clear();
}
bytesDone += read;
return read;
}
QByteArray QFtpDTP::readAll()
{
QByteArray tmp;
if (socket && socke
qftp.rar_The Client_qftp
版权申诉
136 浏览量
2022-09-19
20:40:00
上传
评论
收藏 16KB RAR 举报
邓凌佳
- 粉丝: 65
- 资源: 1万+
最新资源
- 下载安装这个软件.apk
- 【数据集详细解释及案例分析】数据集详细解释及案例分析
- 基于SHT71温湿度传感器、STM32F103C8T6、LCD1602温湿度采集显示系统proteus仿真设计
- 基于TH02温湿度传感器、STM32F103C8T6、LCD1602、FREERTOS的温湿度采集系统proteus仿真设计
- 【TCP-IP协议详细解释及案例分析】TCP-IP协议详细解释及案例分析
- 一文搞懂 LSTM(长短期记忆网络).rar
- 【autosar简介及基本案例解析】autosar简介及基本案例解析
- java模拟斗地主洗牌发牌
- springboot+vue登录系统 vue部分
- 常用常见 SQL语句语法
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈