#include "QFtpClient.h"
#include <QDir>
#include <QFileInfo>
#include <QObject>
#include <QEventLoop>
#include "log.h"
QDateTime start_t;
void set_start() { start_t = QDateTime::currentDateTime(); }
void time_span() { KOE_DEBUG(QObject::tr("spend time:%1ms").arg(start_t.msecsTo(QDateTime::currentDateTime()))); }
struct SingleCmd {
QFtp::Command cmd = QFtp::None;
int state = 0; // 0 - prepare, 1 - doing, 2 - done
QVariantList vParam;
SingleCmd(QFtp::Command c = QFtp::None) { cmd = c; }
bool is_valid()const { return cmd != QFtp::None; }
void reset() { cmd = QFtp::None; }
bool operator == (const SingleCmd& other) {
if (cmd == other.cmd) {
if (cmd == QFtp::List) { return true; }
else if (vParam.isEmpty() || other.vParam.isEmpty()) { return false; }
else { return vParam.front().toString() == other.vParam.front().toString(); }
}
else { return false; }
}
};
bool in_stringlist(const QString& sFind, const QStringList& v) {
for (auto s : v) { if (sFind.contains(s)) return true; }
return false;
}
QVariantList stringlist_varlist(const QStringList& vstring) {
QVariantList ret;
for (auto s : vstring) { ret.append(s); }
return ret;
}
QStringList varlist_stringlist(const QVariantList& varlist) {
QStringList ret;
for (auto var : varlist) { ret.append(var.toString()); }
return ret;
}
QFtpClient::QFtpClient(QString serverip, QString username, QString password, qint16 port, QObject* parent) : QFtp(parent) {
setIP(serverip, port); setUser(username, password); m_pConnect = new QTimer(this);
connect(this, SIGNAL(stateChanged(int)), this, SLOT(slot_state_changed(int)));
connect(m_pConnect, SIGNAL(timeout()), this, SLOT(slot_timer_connect()));
connect(this, SIGNAL(commandFinished(int, bool)), this, SLOT(slot_finish(int, bool)));
connect(this, SIGNAL(listInfo(const QUrlInfo&)), this, SLOT(slot_listinfo(const QUrlInfo&)));
connect(this, SIGNAL(signal_command_finish(int, QVariantList, QString)), this, SLOT(slot_inner_cmd(int, QVariantList, QString)));
}
QFtpClient::~QFtpClient() {
if (m_buffer) { m_buffer->deleteLater(); m_buffer = 0; } close_host();
if (m_pConnect) { m_pConnect->deleteLater(); m_pConnect = 0; }
}
void QFtpClient::setIP(const QString& ip, const qint16 port) { m_url.setHost(ip); m_url.setPort(port); }
void QFtpClient::setUser(const QString& username, const QString& password) { m_url.setUserName(username); m_url.setPassword(password); }
void QFtpClient::slot_finish(int id, bool berror) {
SingleCmd& smd = m_mapCmd[id]; smd.state = 2; QString errstr = berror ? errorString() : "";
switch (currentCommand()) {
case QFtp::ConnectToHost: connect_result(errstr); return;
case QFtp::Login: login_result(errstr); return;
case QFtp::Close: close_result(errstr); break;
case QFtp::List: { m_prevlistcmd = m_listcmd; list_result(smd); }break;
case QFtp::Get: get_result(smd, errstr); break;
case QFtp::Cd: cd_result(smd, errstr); break;
case QFtp::Put: put_result(smd, errstr); break;
case QFtp::Mkdir: mkd_result(smd, errstr); break;
case QFtp::Rmdir: rmd_result(smd, errstr); break;
case QFtp::Remove: rm_result(smd, errstr); break;
case QFtp::Rename: rename_result(smd, errstr); break;
default: break;
}
if (!m_lCmd.isEmpty() && smd == m_lCmd.front()) m_lCmd.pop_front();
if (m_lCmd.isEmpty() && !m_rmlist.isEmpty()) { m_lCmd.append(m_rmlist); m_rmlist.clear(); }
m_mapCmd.remove(id); next_cmd();
}
void QFtpClient::slot_listinfo(const QUrlInfo& url) {
if (m_mapCmd.isEmpty()) return;
switch (m_listcmd) {
case QFtp::Get: {
if (url.isFile()) {
if (!in_stringlist(url.name(), m_vExcept.toList())) {
SingleCmd smd; smd.cmd = QFtp::Get;
smd.vParam.append(m_CurrentPath.second + "/" + url.name());
smd.vParam.append(url.name());
// if get, append local file path
smd.vParam.append(m_CurrentPath.first + "/" + url.name());
m_lCmd.append(smd); inc_record(rt_total);
}
}
else if (url.isDir() && url.name() != "." && url.name() != "..") {
if(!in_stringlist(url.name(), m_vExcept.toList())){
m_PendingPath.append(qMakePair(m_CurrentPath.first + "/" + url.name(), m_CurrentPath.second + "/" + url.name()));
if (!m_CurrentPath.first.isEmpty()) QDir(m_CurrentPath.first).mkpath(url.name());
}
}
}break;
case QFtp::Rmdir: {
if (url.isFile()) {
build_cd_cmd(pwd());
SingleCmd smd; smd.cmd = QFtp::Remove;
smd.vParam.append(url.name());
smd.vParam.append(pwd() + "/" + url.name());
m_lCmd.append(smd); inc_record(rt_total);
}
else if (url.isDir() && url.name() != "." && url.name() != "..") {
build_cd_cmd(pwd() + '/' + url.name());
SingleCmd smd; smd.cmd = QFtp::List;
smd.vParam.append(pwd() + '/' + url.name());
m_lCmd.append(smd);
QList<SingleCmd> cdcmd; build_cd_cmd(pwd(), cdcmd);
smd.cmd = QFtp::Rmdir; smd.vParam.clear();
smd.vParam.append(pwd() + '/' + url.name());
smd.vParam.append(url.name());
cdcmd.append(smd); cdcmd.append(m_rmlist); m_rmlist = cdcmd;
}
}break;
case QFtp::List: { if (url.name() != "." && url.name() != "..") m_listresult.append(url); }break;
default: break;
}
}
void QFtpClient::slot_inner_cmd(int cmdid, QVariantList params, QString errorstring) {
switch (cmdid) {
case QFtp::ConnectToHost: {
if (errorstring.isEmpty()) emit signal_ftp_log("Success to connect ftp");
else emit signal_ftp_log(QString("Fail to connect ftp, reason:").append(errorstring), true);
} break;
case QFtp::Login: {
if (errorstring.isEmpty()) emit signal_ftp_log("Success to login ftp");
else emit signal_ftp_log(QString("Fail to login ftp, reason:").append(errorstring), true);
} break;
case QFtp::Close: {
if (errorstring.isEmpty()) emit signal_ftp_log("Success to close ftp");
else emit signal_ftp_log(QString("Fail to close ftp, reason:").append(errorstring), true);
} break;
case QFtp::Get: {
if (params.size() > 2) {
QString remotefilepath = params[0].toString(), remotefilename = params[1].toString(), localfilepath = params[2].toString();
if (errorstring.isEmpty()) emit signal_ftp_log(QString("Get file:%1 -> %2").append(remotefilepath).arg(localfilepath));
else emit signal_ftp_log(QString("Fail to get:%1 -> %2").append(remotefilepath).arg(localfilepath), true);
}
else if (!errorstring.isEmpty()) emit signal_ftp_log(errorstring, true);
} break;
case QFtp::Cd: {
if (!params.isEmpty()) { if (!errorstring.isEmpty()) emit signal_ftp_log(QString("Directory:%1 not exist").append(params.front().toString()), true); }
} break;
case QFtp::Put: {
if (params.size() > 2) {
QString localfile = params[0].toString(), remotefilename = params[1].toString(), remotefile = params[2].toString();
if (errorstring.isEmpty()) emit signal_ftp_log(QString("Put file:%1 -> %2").arg(localfile).arg(remotefile));
else emit signal_ftp_log(QString("Fail to put:%1 -> %2").append(localfile).arg(remotefile), true);
}
else if (!errorstring.isEmpty()) emit signal_ftp_log(errorstring, true);
} break;
case QFtp::Remove: {
if (params.size() > 1) {
QString remotefilepath = params[0].toString(), remotefilename = params[1].toString();
if (errorstring.isEmpty()) emit signal_ftp_log(QString("Remove file:%1").arg(remotefilepath));
else emit signal_ftp_log(QString("Fail to remove:%1").append(remotefilepath), true);
}
else if (!errorstring.isEmpty()) emit signal_ftp_log(errorstring, true);
} break;
case QFtp::Rmdir: {
if (params.size() > 1) {
QString remotepath = params[0].toString(), remotefoldername = params[1].toString();
if (errorstring.isEmpty()) emit signal_ftp_log(QString("rmdir:%1").arg(remotepath));
}
}break;
case QFtp::Rename: {
if (params.size() > 2) {
QString remotepath = params[0].toString(), remotetargetname = params[1].toString(), remotenewname = params[2].toString();
if (errorstring.isEmpty()) emit signal_ftp_log(QString("rename:%1 -> %2").arg(remotepath).arg(remotenewname));
}
}break;
default: break;
}
}
void QFtpClient::slot_state_changed(int value) { emit signal_state_changed(value); if (value != QFtp::LoggedIn) m_PathSection.clear(); }
void QFtpClient::slot_timer_connect() {
switch (state()) {
case QFtp::Unconnected: {
KOE_DEBUG(tr("try to connect ftp server"));
connectToHost(m_url.host(), m_url.port());
}break;
case QFtp::LoggedIn: {
if (m_pConnect) m_pConnect->stop();
}break;
case Connected: {
KOE_DEBUG(tr("try to login ftp server"));
login(m_url.userName(), m_url.password());
}break;
default: break;
}
}
void QFtpClient::connect_host() {
switch (state()) {
case QFtp::Connected: break;
case QFtp::Unconnected: {
if (m_pConnect) {
if (!m_pConnect->isActive()) {
connectToHost(m_url.host(), m_url.port());
m_pConnect->start(1000);
}
}
}break;
case HostLookup:
case Connecting: { KOE_DEBUG(tr("connecting to ftp server")); }break;
case LoggedIn: { KOE_DEBUG(tr("already connected to ftp server")); }break;
case Closing: { KOE_DEBUG(tr("ftp closing")); }break;
default: break;
}
}
bool QFtpClient::sync_connect(int msec) {
bool ok = false;
if (state() != QFtp::Unconnected) {
KOE_WARN(tr("Fail to connect to ftp for current state not unconnected"));
return false;
}
QEventLoop* e = new QEventLoop; QTimer* tOut = new QTimer; tOut->setInterval(msec);
QMetaObject::Connection ok_cnt = connect(this, &QFtp::stateChanged,
[&](int state) {
if (state == QFtp::LoggedIn) {
ok = true;
KOE_INFO(tr("Success to connect to ftp server and login"));
if (e && e->isRunning()) {
e->quit();
}
}
}
);
QMetaObject::Connection timer_cnt = connect(tOut, &QTimer::timeout,
[&] {
ok = false;
KOE_WARN(tr("Fail to connect to ftp server for timeout"));
if (e && e->isRunning()) {
e->quit();
}
}
);
tOut->start(); connect_host(); e->exec();
if (m_pConnect && m_pConnect->isActive()) m_pConnect->stop();
if (tOut) { if (tOut->isActive()) tOut->stop(); delete tOut; tOut = 0; }
if (e) { delete e; e = 0; } disconnect(ok_cnt); disconnect(timer_cnt);
return ok;
}
void QFtpClient::close_host() {
clear_cmd(); close();
if (m_pConnect) { if (m_pConnect->isActive()) m_pConnect->stop(); }
//if (state() == QFtp::Closing || state() == QFtp::Unconnected) return;
}
bool QFtpClient::get_buffer(const QString& remoteabsfile, int msec) {
const QString strcmd = tr("get buffer");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_get_buffer(remoteabsfile, msec);
}
bool QFtpClient::get_file(const QString& remoteabsfile, const QString& localabsfile, int msec) {
const QString strcmd = tr("get file");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_get_file(remoteabsfile, localabsfile, msec);
}
bool QFtpClient::get_files(const QList< QPair<QString, QString> >& vfiles, int msec) {
const QString strcmd = tr("get buffer");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
if (vfiles.isEmpty()) return false;
QVariantList varlist;
for (auto ppair : vfiles) varlist << ppair.first << ppair.second;
return inner_get_files(varlist, msec);
}
bool QFtpClient::get_tree(const QString& remoteabspath, const QString& localabspath, const QStringList& exceptabspath, int msec) {
const QString strcmd = tr("get tree");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_get_tree(remoteabspath, localabspath, exceptabspath, msec);
}
bool QFtpClient::put_files(const QList< QPair<QString, QString> >& vfiles, int msec) {
const QString strcmd = tr("get files");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
if (vfiles.isEmpty()) return false;
QVariantList varlist;
for (auto ppair : vfiles) varlist << ppair.first << ppair.second;
return inner_put_files(varlist, msec);
}
bool QFtpClient::put_file(const QString& localabsfile, const QString& remoteabsfile, int msec) {
const QString strcmd = tr("put file");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_put_file(localabsfile, remoteabsfile, msec);
}
bool QFtpClient::put_tree(const QString& localabspath, const QString& remoteabspath, const QStringList& exceptpath, int msec) {
const QString strcmd = tr("put tree");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_put_tree(localabspath, remoteabspath, exceptpath, msec);
}
bool QFtpClient::mk_dir(const QString& dir, int msec) {
const QString strcmd = tr("mk dir");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_mk_dir(dir, msec);
}
bool QFtpClient::mk_dir(const QStringList& dirlist, int msec) {
const QString strcmd = tr("mk multi dir");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_mk_dir(dirlist, msec);
}
bool QFtpClient::rm_tree(const QString& dir, int msec) {
const QString strcmd = tr("rm tree");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_rm_tree(dir, msec);
}
bool QFtpClient::rm_file(const QString& remotefile, int msec) {
const QString strcmd = tr("rm file");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_rm_file(remotefile, msec);
}
bool QFtpClient::_rename(const QString& remotefilepath, const QString& newname, int msec) {
const QString strcmd = tr("rename");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_rename(remotefilepath, newname, msec);
}
bool QFtpClient::_list(const QString& remotepath, int msec) {
const QString strcmd = tr("list");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_list(remotepath, msec);
}
bool QFtpClient::pwd_put_file(const QString& localabsfile, int msec) {
const QString strcmd = tr("put pwd file");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_put_file(localabsfile, "", msec);
}
bool QFtpClient::pwd_get_file(const QString& remotefile, const QUrl& localurl, int msec) {
const QString strcmd = tr("get pwd file");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
QString slocal = localurl.path();
if (slocal.startsWith('/')) slocal = slocal.mid(1);
if (!slocal.endsWith('/')) slocal += '/';
return inner_get_file(remotefile, slocal, msec);
}
bool QFtpClient::pwd_rm_file(const QString& remotefile, int msec) {
const QString strcmd = tr("remove pwd file");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_rm_file(remotefile, msec);
}
bool QFtpClient::pwd_rm_tree(const QString& dir, int msec) {
const QString strcmd = tr("remove pwd tree");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_rm_tree(dir, msec);
}
bool QFtpClient::pwd_mk_dir(const QString& remotedir, int msec) { return false; }
bool QFtpClient::pwd_rename(const QString& remotefile, const QString& newname, int msec) {
const QString strcmd = tr("rename");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_rename(remotefile, newname, msec);
}
bool QFtpClient::pwd_list(int msec) { return _list("", msec); }
bool QFtpClient::pwd_cd(const QString& dirname, bool done_list, int msec) {
const QString strcmd = tr("cd");
if (is_busy()) {
KOE_WARN(tr("fail to %1: busy").arg(strcmd));
return false;
}
bool isAlive = is_connect();
if (!isAlive) isAlive = sync_connect();
if (!isAlive) return false;
return inner_cd(dirname, done_list, msec);
}
bool QFtpClient::is_busy()const { return !m_lCmd.isEmpty(); }
bool QFtpClient::is_connect()const { return state() == QFtp::LoggedIn; }
QString QFtpClient::pwd() { return QString("/%1").arg(m_PathSection.join('/')); }
void QFtpClient::connect_result(QString errstr) {
if (errstr.isEmpty()) {
KOE_DEBUG(tr("Success to connect ftp"));
KOE_DEBUG(tr("try to login ftp server by user:%1").arg(m_url.userName()));
login(m_url.userName(), m_url.password());
}
else KOE_WARN(tr("Fail to connect ftp:%1").arg(errstr));
emit signal_command_finish(QFtp::ConnectToHost, {}, errstr);
}
void QFtpClient::login_result(QString errstr) {
if (errstr.isEmpty()) { KOE_DEBUG(tr("Success to login ftp")); }
else KOE_WARN(tr("Fail to login ftp:%1").arg(errstr));
emit signal_command_finish(QFtp::Login, {}, errstr);
}
void QFtpClient::close_result(QString errstr) {
if (errstr.isEmpty()) KOE_DEBUG(tr("Success to close ftp"));
else KOE_WARN(tr("Fail to close ftp:%1").arg(errstr));
emit signal_command_finish(QFtp::Close, {}, errstr);
}
void QFtpClient::list_result(const SingleCmd& ssmd) {
if (m_mapCmd.isEmpty()) return;
switch (m_prevlistcmd) {
case QFtp::Get: {
if (!m_PendingPath.isEmpty()) {
m_CurrentPath = m_PendingPath.takeLast();
build_cd_cmd(m_CurrentPath.second);
SingleCmd smd; smd.cmd = QFtp::List;
m_lCmd.append(smd); m_listcmd = m_prevlistcmd;
}
}break;
case QFtp::Rmdir: {
}break;
case QFtp::List: {
emit signal_list(m_listresult); /*m_listcmd = QFtp::None;*/ m_prevlistcmd = QFtp::None;
emit signal_command_finish(QFtp::List, QVariantList());
if (m_cmd == QC_LIST) inc_record(rt_success);
}break;
default: break;
}
}
bool QFtpClient::has_cmd() { return !m_lCmd.isEmpty(); }
bool QFtpClient::next_cmd() {
if (!is_connect()) return false;
if (m_lCmd.isEmpty()) { emit signal_done(m_cmd, success_count, execute_count, total_count); m_cmd = QC_NONE; reset_record(); }
else {
SingleCmd& smd = m_lCmd.front(); if (smd.state > 0) return false;
smd.state = 1;
switch (smd.cmd) {
case QFtp::Cd:
m_mapCmd.insert(cd(smd.vParam.front().toString()), smd);
if (m_cmd == QC_CD) { inc_record(rt_executing); }
break;
case QFtp::Mkdir:
m_mapCmd.insert(mkdir(smd.vParam.front().toString()), smd);
if (m_cmd == QC_MKD || m_cmd == QC_MKDS) { inc_record(rt_executing); }
break;
case QFtp::Put: {
if (smd.vParam.size() > 2) {
QFile qfile(smd.vParam.front().toString());
if (qfile.open(QIODevice::ReadOnly)) {
m_mapCmd.insert(put(qfile.readAll(), smd.vParam[1].toString()), smd); qfile.close();
if (m_cmd == QC_PUT_FILE || m_cmd == QC_PUT_FILES || m_cmd == QC_PUT_TREE) { inc_record(rt_executing); }
}
}
}break;
case QFtp::Get: {
if (smd.vParam.size() > 1) {
QString remotefilepath = smd.vParam[0].toString(), remotefilename = smd.vParam[1].toString();
if (smd.vParam.size() > 2) {
QString localfilepath = smd.vParam[2].toString(); int pathindex = localfilepath.lastIndexOf('/');
QDir dpath(localfilepath.mid(0, pathindex)); if (!dpath.exists()) dpath.mkpath(dpath.path());
QFile* pFile = new QFile(localfilepath);
//pFile->remove(); // if need rm ?
if (pFile->open(QIODevice::WriteOnly)) {
smd.vParam.append(QVariant::fromValue(pFile)); m_mapCmd.insert(get(remotefilename, pFile), smd);
if (m_cmd == QC_GET_FILE || m_cmd == QC_GET_FILES || m_cmd == QC_GET_TREE) { inc_record(rt_executing); }
}
else {
KOE_WARN(tr("fail to create file:%1").arg(localfilepath));
}
}
else {
if (!m_buffer) m_buffer = new QBuffer(this); m_mapCmd.insert(get(remotefilename, m_buffer, QFtp::Binary), smd);
if (m_cmd == QC_GET_FILE || m_cmd == QC_GET_FILES || m_cmd == QC_GET_TREE) { inc_record(rt_executing); }
}
}
}break;
case QFtp::List: m_mapCmd.insert(list(), smd); if (m_cmd == QC_LIST) inc_record(rt_executing); break;
case QFtp::Rmdir: { if (smd.vParam.size() > 0) m_mapCmd.insert(rmdir(smd.vParam.front().toString()), smd); }break;
case QFtp::Remove: {
if (smd.vParam.size() > 0) {
m_mapCmd.insert(remove(smd.vParam.front().toString()), smd);
if (m_cmd == QC_RM_FILE || m_cmd == QC_RM_TREE) { inc_record(rt_executing); }
}
}break;
case QFtp::Rename: {
if (smd.vParam.size() > 2) {
m_mapCmd.insert(rename(smd.vParam[1].toString(), smd.vParam[2].toString()), smd);
if (m_cmd == QC_RENAME) { inc_record(rt_executing); }
}
}break;
default: return false;
}
}
return true;
}
bool QFtpClient::next_cmd_util_done(int msec) {
bool ok = false; QEventLoop* e = new QEventLoop; QTimer* t = 0; QMetaObject::Connection timeoutCnt;
QMetaObject::Connection doneCnt = connect(this, &QFtpClient::signal_done,
[&](int cmdid, int ok_num, int exec_num, int total_num) {
ok = (cmdid == m_cmd) && (exec_num == 1 ? ok_num == exec_num : true);
if (e && e->isRunning()) e->quit();
}
);
if (msec > 0) {
t = new QTimer; t->setInterval(msec);
timeoutCnt = connect(t, &QTimer::timeout,
[&] {
ok = false;
if (!m_lCmd.isEmpty()) m_lCmd.clear();
if (e && e->isRunning()) e->quit();
}
);
}
if (next_cmd()) { if (t) t->start(); e->exec(); }
if (t) { delete t; t = 0; } if (e) { delete e; e = 0; }
disconnect(doneCnt); disconnect(timeoutCnt);
return ok;
}
void QFtpClient::cd_result(const SingleCmd& smd, QString errstr) {
if (m_mapCmd.isEmpty()) return;
if (smd.is_valid()) {
QString param = smd.vParam.isEmpty() ? "" : smd.vParam.front().toString();
if (!errstr.isEmpty()) {
KOE_WARN(tr("Fail to cd to:%1, for reason:%2").arg(param).arg(errstr));
emit signal_command_finish(QFtp::Cd, smd.vParam, errstr); return;
}
if (smd.vParam[0].toString() == "/") m_PathSection.clear();
else if (smd.vParam[0].toString() == "..") { if (!m_PathSection.isEmpty()) m_PathSection.pop_back(); }
else m_PathSection.append(smd.vParam[0].toString());
if (smd.vParam.size() > 1) {
if (smd.vParam[1].toInt() > 0) { QTimer::singleShot(100, [=] { pwd_list(); }); } // done_list
emit signal_command_finish(QFtp::Cd, smd.vParam); if (m_cmd == QC_CD) { inc_record(rt_success); }
}
}
}
void QFtpClient::put_result(const SingleCmd& smd, QString errstr) {
if (m_mapCmd.isEmpty()) return;
if (smd.is_valid()) {
if (smd.vParam.size() > 2) {
QString localfile = smd.vParam[0].toString(), remotefilename = smd.vParam[1].toString(), remotefile = smd.vParam[2].toString();
if (errstr.isEmpty()) {
KOE_DEBUG(tr("success put:%1 -> %2").arg(localfile).arg(remotefile));
if (m_cmd == QC_PUT_FILE || m_cmd == QC_PUT_FILES || m_cmd == QC_PUT_TREE) inc_record(rt_success);
}
else KOE_WARN(tr("Fail to put:%1 -> %2, for reason:%3").arg(localfile).arg(remotefile).arg(errorString()));
} else KOE_WARN(tr("param error"));
}
emit signal_command_finish(QFtp::Put, smd.vParam, errstr);
#ifdef _DEBUG
time_span();
#endif
}
void QFtpClient::mkd_result(const SingleCmd& smd, QString errstr) {
Q_UNUSED(smd); Q_UNUSED(errstr); if (m_mapCmd.isEmpty()) return;
emit signal_command_finish(QFtp::Mkdir, smd.vParam, errstr);
if (errstr.isEmpty()) { if (m_cmd == QC_MKD || m_cmd == QC_MKDS) inc_record(rt_success); }
}
void QFtpClient::rmd_result(const SingleCmd& smd, QString errstr) {
if (m_mapCmd.isEmpty()) return; const QString strcmd = tr("rm dir");
if (!errstr.isEmpty()) {
if (smd.vParam.size() > 0) {
KOE_WARN(tr("Fail to %1:%2, for reason:%3").arg(strcmd).arg(smd.vParam[0].toString()).arg(errstr));
}
}
else {
if (smd.vParam.size() > 0) {
KOE_DEBUG(QString("%1:%2").arg(strcmd).arg(smd.vParam[0].toString()));
}
}
emit signal_command_finish(QFtp::Rmdir, smd.vParam, errstr);
#ifdef _DEBUG
time_span();
#endif
}
void QFtpClient::rm_result(const SingleCmd& smd, QString errstr) {
if (m_mapCmd.isEmpty()) return; const QString strcmd = tr("rm file");
if (!errstr.isEmpty()) {
if (smd.vParam.size() > 0) {
KOE_WARN(tr("fail to %1:%2, for reason:%3").arg(strcmd).arg(smd.vParam[0].toString()).arg(errstr));
if (m_cmd == QC_RM_FILE || m_cmd == QC_RM_TREE) inc_record(rt_success);
}
}
else {
if (smd.vParam.size() > 0) {
KOE_DEBUG(QString("%1:%2").arg(strcmd).arg(smd.vParam[0].toString()));
}
}
emit signal_command_finish(QFtp::Remove, smd.vParam, errstr);
#ifdef _DEBUG
time_span();
#endif
}
void QFtpClient::rename_result(const SingleCmd& smd, QString errstr) {
if (m_mapCmd.isEmpty()) return; const QString strcmd = tr("rename");
if (!errstr.isEmpty()) {
if (smd.vParam.size() > 2) {
KOE_WARN(tr("fail to %1:%2 -> %3, for reason:%4").arg(strcmd).arg(smd.vParam[0].toString()).arg(smd.vParam[02].toString()).arg(errstr));
if (m_cmd == QC_RENAME) inc_record(rt_success);
}
}
emit signal_command_finish(QFtp::Rename, smd.vParam, errstr);
#ifdef _DEBUG
time_span();
#endif
}
void QFtpClient::build_pwd_cd_cmd(const QString& dirname, bool done_list) {
SingleCmd smd; smd.cmd = QFtp::Cd; smd.vParam.append(dirname); smd.vParam.append(done_list ? 1 : 0); m_lCmd.append(smd);
}
void QFtpClient::build_cd_cmd(const QString& remotepath) { build_cd_cmd(remotepath, m_lCmd); }
void QFtpClient::build_cd_cmd(const QString& remotepath, QList<SingleCmd>& l) {
QString sPath = remotepath; sPath = sPath.replace("\\", "/"); // "/" 替换 "\"
if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/"
QStringList v = sPath.split('/');
while (!v.isEmpty()) {
QString itemback = v.back();
if (itemback.contains('.')) {
v.pop_back(); // "/aa/bb/cc.py" -> "/aa/bb", 去除尾部含"."的文件名
if (itemback == "..") v.pop_back(); // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."的再进行一次上切
}
else break;
}
SingleCmd smd; smd.cmd = QFtp::Cd; smd.vParam.append("/"); l.append(smd);
for (const QString& s : v) {
if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./"
if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd"
if (!l.isEmpty()) l.pop_back(); continue;
}
smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); l.append(smd);
}
}
void QFtpClient::build_mkdir_cmd(const QString& remotepath) {
QString sPath = remotepath; sPath = sPath.replace("\\", "/");
if (remotepath.contains('/')) {
if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/"
QStringList v = sPath.split('/'); if (!v.isEmpty() && v.front().isEmpty()) v.pop_front();
while (v.contains("..")) { // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."的再进行一次上切
int index = v.indexOf("..");
if (index >= 0) { v.removeAt(index); if(index > 0) v.removeAt(index - 1); }
}
if (v.isEmpty()) return;
SingleCmd smd; smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd);
for (const QString& s : v) {
if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./"
if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd"
if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue;
}
smd.vParam.clear(); smd.cmd = QFtp::Mkdir; smd.vParam.append(s); m_lCmd.append(smd);
smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd);
}
}
else { SingleCmd smd; smd.cmd = QFtp::Mkdir; smd.vParam.append(sPath); m_lCmd.append(smd); }
}
void QFtpClient::build_rmdir_cmd(const QString& remotepath) {
QString sPath = remotepath; sPath = sPath.replace("\\", "/"); SingleCmd smd; QString targetdir = remotepath;
if (sPath.contains('/')) {
if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/"
QStringList v = sPath.split('/'); if (v.isEmpty()) { KOE_WARN(tr("giving param not directory:%1").arg(remotepath)); return; }
while (!v.isEmpty()) {
const QString& itemback = v.back();
if (itemback.contains('.')) {
v.pop_back(); // "/aa/bb/cc.py" -> "/aa/bb", 去除尾部含"."的文件名
if (itemback == "..") v.pop_back(); // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."的再进行一次上切
}
else break;
}
if (v.isEmpty()) return;
targetdir = v.last(); smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.push_back(smd);
for (const QString& s : v) {
if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./"
if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd"
if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue;
}
smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.push_back(smd);
}
}
else {
sPath = pwd() + '/' + targetdir; smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(targetdir); m_lCmd.push_back(smd);
}
smd.vParam.clear(); smd.cmd = QFtp::List; smd.vParam.append(sPath); m_lCmd.append(smd); m_listcmd = QFtp::Command::Rmdir;
QList<SingleCmd> cdcmd; build_cd_cmd(pwd(), cdcmd);
smd.cmd = QFtp::Rmdir; smd.vParam.clear(); smd.vParam.append(targetdir); smd.vParam.append(pwd() + '/' + targetdir);
cdcmd.append(smd); cdcmd.append(m_rmlist); m_rmlist = cdcmd;
}
void QFtpClient::build_rm_cmd(const QString& remotefile) {
QString sPath = remotefile; sPath = sPath.replace("\\", "/"); SingleCmd smd; QString targetfile = remotefile;
if (remotefile.contains('/')) {
if (sPath.endsWith('/')) sPath = sPath.mid(0, sPath.size() - 1); // 去除尾部"/"
QStringList v = sPath.split('/');
while (!v.isEmpty()) {
QString itemback = v.back();
if (itemback == "..") { // "/aa/bb/cc/.." -> "/aa/bb", 将尾部含".."进行两次上切
v.pop_back(); v.pop_back();
}
else break;
}
if (v.isEmpty()) return;
targetfile = v.takeLast(); if (!targetfile.contains('.')) { KOE_WARN(tr("giving param not file:%1").arg(remotefile)); return; }
smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd);
for (const QString& s : v) {
if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./"
if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd"
if (!m_lCmd.isEmpty()) m_lCmd.pop_back();
continue;
}
smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd);
}
}
else sPath = pwd();
smd.vParam.clear(); smd.cmd = QFtp::Remove; smd.vParam.append(targetfile); smd.vParam.append(sPath); m_lCmd.append(smd);
}
void QFtpClient::build_put_cmd(const QString& localfile, const QString& remotefile) {
QString sLocalPath = localfile; sLocalPath = sLocalPath.replace('\\', '/'); QFileInfo qinfo(sLocalPath);
if (!qinfo.exists()) { KOE_WARN(tr("local file not exist:%1").arg(localfile)); return; }
if (!qinfo.isFile()) { KOE_WARN(tr("local file is not file:%1").arg(localfile)); return; }
QString filename = sLocalPath.mid(sLocalPath.lastIndexOf('/') + 1), sRemotePath = remotefile.isEmpty() ? pwd() + '/' + filename : remotefile;
sRemotePath = sRemotePath.replace('\\', '/'); QStringList v = sRemotePath.split("/");
if (!remotefile.isEmpty()) {
// 上传文件名不可以是 "." 或 ".."
if (v.isEmpty() || v.back() == ".." || v.back() == ".") { KOE_WARN(tr("param error")); return; }
// remotefile以"/"结尾, 表示上传文件未指定文件名, 则使用本地文件名, example:
// localfile -> E:/dd/ee/ff.xx
// remotefile -> /aa/bb/cc/
// final remotefile -> /aa/bb/cc/ff.xx
filename = v.back().isEmpty() ? sLocalPath.mid(sLocalPath.lastIndexOf('/') + 1) : v.takeLast();
build_mkdir_cmd(v.join('/'));
}
SingleCmd smd; smd.cmd = QFtp::Put; smd.vParam.append(localfile);
smd.vParam.append(filename); smd.vParam.append(sRemotePath); m_lCmd.append(smd);
}
void QFtpClient::build_puts_cmd(const QVariantList& files) {
int file_size = files.size() / 2;
for (int i = 0; i < file_size; ++i) {
QString slocal = files[2 * i].toString(), sremote = files[2 * i + 1].toString();
sremote = sremote.replace('\\', '/'); QStringList v = sremote.split("/");
// 上传文件名不可以是 "." 或 ".."
if (v.isEmpty() || v.back() == ".." || v.back() == ".") { KOE_WARN(tr("param error")); continue; }
QString remotefilename = v.back().isEmpty() ? slocal.mid(slocal.lastIndexOf('/') + 1) : v.takeLast();
build_mkdir_cmd(v.join('/'));
SingleCmd smd; smd.cmd = QFtp::Put;
smd.vParam.append(slocal); smd.vParam.append(remotefilename); smd.vParam.append(sremote);
m_lCmd.append(smd);
}
}
void QFtpClient::build_putree_cmd(const QString& localpath, const QString& remotepath, const QStringList& vExcept) {
QString sRemotePath = remotepath; sRemotePath = sRemotePath.replace('\\', '/');
//rmdir(sRemotePath); // if need rm ?
QDir qLocalParentDir(localpath); if (!qLocalParentDir.exists()) { KOE_WARN(tr("local path not exist:%1").arg(qLocalParentDir.path())); return; }
QFileInfoList vFileInfo = qLocalParentDir.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot, QDir::DirsLast);
if (vFileInfo.isEmpty()) {
// there is no file in this dir, only mkdir
if (sRemotePath.split("/").isEmpty()) { KOE_WARN(tr("param error")); return; }
if (!in_stringlist(sRemotePath, vExcept)) build_mkdir_cmd(sRemotePath);
}
else {
for (const QFileInfo& FileInfo : vFileInfo) {
QString sFileName = FileInfo.fileName();
if (FileInfo.isDir()) {
// 子对象是目录, 则递归上传目录
qLocalParentDir.cd(sFileName);
if (!in_stringlist(qLocalParentDir.path(), vExcept))
build_putree_cmd(qLocalParentDir.path(), sRemotePath.endsWith("/") ? sRemotePath + sFileName : sRemotePath + "/" + sFileName, vExcept);
qLocalParentDir.cdUp();
}
else if (FileInfo.isFile()) {
// 子对象是文件, 则上传单个文件
if (!in_stringlist(qLocalParentDir.path() + "/" + sFileName, vExcept)) {
build_put_cmd(qLocalParentDir.path() + "/" + sFileName, sRemotePath.endsWith("/") ? sRemotePath + sFileName : sRemotePath + "/" + sFileName);
inc_record(rt_total);
}
}
}
}
}
void QFtpClient::build_get_buffer_cmd(const QString& remotefile) {
QString sRemotePath = remotefile; sRemotePath = sRemotePath.replace('\\', '/'); QStringList v = sRemotePath.split("/");
if (v.isEmpty()) { KOE_WARN(tr("param error")); return; }
build_cd_cmd(sRemotePath); QString remotefilename = v.takeLast();
SingleCmd smd; smd.cmd = QFtp::Get;
smd.vParam.append(sRemotePath); smd.vParam.append(remotefilename);
m_lCmd.append(smd);
}
void QFtpClient::build_get_cmd(const QString& remotefile, const QString& localfile) {
QString sRemotePath = remotefile; sRemotePath = sRemotePath.replace('\\', '/'); QString filename = sRemotePath;
if (remotefile.contains('/')) {
QStringList v = sRemotePath.split("/"); if (v.isEmpty()) { KOE_WARN(tr("param error")); return; }
build_cd_cmd(sRemotePath);
filename = v.takeLast(); SingleCmd smd; smd.cmd = QFtp::Get;
smd.vParam.append(sRemotePath); smd.vParam.append(filename);
smd.vParam.append(localfile); m_lCmd.append(smd);
}
else {
SingleCmd smd; smd.cmd = QFtp::Get; smd.vParam.append(pwd()); smd.vParam.append(filename);
smd.vParam.append(localfile.endsWith('/') ? localfile + filename : localfile); m_lCmd.append(smd);
}
}
void QFtpClient::build_gets_cmd(const QVariantList& files) {
int file_size = files.size() / 2;
for (int i = 0; i < file_size; ++i) {
QString sremote = files[2 * i].toString(), slocal = files[2 * i + 1].toString();
sremote = sremote.replace('\\', '/'); QStringList v = sremote.split("/");
if (v.isEmpty()) { KOE_WARN(tr("param error")); continue; }
build_cd_cmd(sremote); QString remotefilename = v.takeLast(); SingleCmd smd;
smd.cmd = QFtp::Get; smd.vParam.append(sremote); smd.vParam.append(remotefilename);
smd.vParam.append(slocal); m_lCmd.append(smd);
}
}
void QFtpClient::build_getree_cmd(const QString& remotepath, const QString& localpath, const QStringList& vExcept) {
m_CurrentPath = qMakePair(localpath, remotepath); build_cd_cmd(remotepath);
// 进入远程目录后 list 检索文件, list 后续操作中执行 get command
SingleCmd smd; smd.cmd = QFtp::List; m_lCmd.append(smd); m_listcmd = QFtp::Command::Get; m_vExcept.unite(vExcept.toSet());
}
void QFtpClient::build_rename_cmd(const QString& remotefilepath, const QString& newname) {
QString sPath = remotefilepath; sPath = sPath.replace('\\', '/'); SingleCmd smd; QString target = remotefilepath;
if (remotefilepath.contains('/')) {
QStringList v = sPath.split("/"); target = v.takeLast(); if (target.isEmpty()) return;
smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd);
for (const QString& s : v) {
if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./"
if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd"
if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue;
}
smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd);
}
}
else sPath = pwd();
smd.vParam.clear(); smd.cmd = QFtp::Rename;
smd.vParam.append(sPath); smd.vParam.append(target);
smd.vParam.append(newname); m_lCmd.append(smd);
}
void QFtpClient::build_list_cmd(const QString& remotepath) {
SingleCmd smd;
if (!remotepath.isEmpty()) {
QString sPath = remotepath; sPath = sPath.replace('\\', '/'); QStringList v = sPath.split("/");
smd.cmd = QFtp::Cd; smd.vParam.append("/"); m_lCmd.append(smd);
for (const QString& s : v) {
if (s.isEmpty() || s == ".") continue; // "/aa//xxx"跳过"//","/aa/./xxx"跳过"/./"
if (s == "..") { // "/aa/bb/../cc/dd" -> "/aa/cc/dd"
if (!m_lCmd.isEmpty()) m_lCmd.pop_back(); continue;
}
smd.vParam.clear(); smd.cmd = QFtp::Cd; smd.vParam.append(s); m_lCmd.append(smd);
}
}
smd.vParam.clear(); smd.cmd = QFtp::List; m_lCmd.append(smd); m_listcmd = QFtp::Command::List;
}
void QFtpClient::get_result(const SingleCmd& smd, QString errstr) {
if (m_mapCmd.isEmpty()) return;
QVariantList v = smd.vParam; if (v.size() < 2) return;
QString remotefilepath = v[0].toString(), remotefilename = v[1].toString();
if (v.size() > 2) {
QString localfilepath = v[2].toString(); QFile* pFile = v.size() == 4 ? v.takeLast().value<QFile*>() : 0;
// there is a question here: if command "get" not come back, memory will leak, maybe it can be controlled by timer
if (pFile) { if (pFile->isOpen()) pFile->close(); delete pFile; }
if (errstr.isEmpty()) {
KOE_DEBUG(tr("download file:%1 -> %2").arg(remotefilepath).arg(localfilepath));
if (m_cmd == QC_GET_BUFFER || m_cmd == QC_GET_FILE || m_cmd == QC_GET_FILES || m_cmd == QC_GET_TREE) inc_record(rt_success);
}
else {
KOE_WARN(tr("Fail to download:%1 -> %2, for reason:%3").arg(remotefilepath).arg(localfilepath).arg(errstr));
QDir().remove(localfilepath);
}
}
else if (m_buffer) emit signal_get_buffer(m_buffer->buffer());
emit signal_command_finish(QFtp::Get, v, errstr);
#ifdef _DEBUG
time_span();
#endif
}
void QFtpClient::clear_cmd() {
m_CurrentPath = qMakePair(QString(), QString());
m_PendingPath.clear(); m_lCmd.clear();
m_mapCmd.clear(); m_listcmd = QFtp::Command::None;
}
void QFtpClient::reset_record() { total_count = 0; execute_count = 0; success_count = 0; }
void QFtpClient::inc_record(record_type ty, int val) {
switch (ty) {
case rt_success: success_count += val; break;
case rt_executing: execute_count += val; break;
case rt_total: total_count += val; break;
default: break;
}
}
bool QFtpClient::inner_put_file(const QString& localabsfile, const QString& remoteabsfile, int msec) {
if (localabsfile.isEmpty() || remoteabsfile.isEmpty()) return false;
const QString strcmd = tr("put file");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Put, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
QFileInfo qlocalfile(localabsfile);
if (!qlocalfile.exists()) {
KOE_WARN(tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(localabsfile));
emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(localabsfile));
return false;
}
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_PUT_FILE; reset_record(); inc_record(rt_total);
build_put_cmd(localabsfile, remoteabsfile); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_put_files(QVariantList& files, int msec) {
if(files.isEmpty()) return false;
const QString strcmd = tr("put file");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Put, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
int file_size = files.size() / 2; if(file_size <= 0) return false;
for (int i = file_size - 1; i >= 0; --i) {
QFileInfo qlocalfile(files[2*i].toString());
if (!qlocalfile.exists()) {
KOE_WARN(tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(files[2 * i].toString()));
emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for local file not exist:%2").arg(strcmd).arg(files[2 * i].toString()));
files.removeAt(2 * i); files.removeAt(2 * i + 1); continue;
}
}
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_PUT_FILES; reset_record(); inc_record(rt_total, file_size);
build_puts_cmd(files); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_put_tree(const QString& localabspath, const QString& remoteabspath, const QStringList& vExcept, int msec) {
if (localabspath.isEmpty() || remoteabspath.isEmpty()) return false;
const QString strcmd = tr("put tree");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Put, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Put, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
QDir qLocalParentDir(localabspath);
if (!qLocalParentDir.exists()) {
KOE_WARN(tr("fail to %1, local path not exist:%2").arg(strcmd).arg(localabspath));
emit signal_command_finish(QFtp::Put, {}, tr("fail to %1, local path not exist:%2").arg(strcmd).arg(localabspath));
return false;
}
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_PUT_TREE; reset_record();
build_putree_cmd(localabspath, remoteabspath, vExcept);
return next_cmd_util_done(msec);
}
bool QFtpClient::inner_get_buffer(const QString& remoteabsfile, int msec) {
if (remoteabsfile.isEmpty()) return false;
const QString strcmd = tr("get file");
if (state() != QFtp::LoggedIn) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_GET_BUFFER; reset_record(); inc_record(rt_total);
build_get_buffer_cmd(remoteabsfile); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_get_file(const QString& remotefile, const QString& localfile, int msec){
if(remotefile.isEmpty() || localfile.isEmpty()) return false;
const QString strcmd = tr("get file");
if (state() != QFtp::LoggedIn) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
QDir qLocalDir(localfile.mid(0, localfile.lastIndexOf("/")));
if (!qLocalDir.exists()) QDir().mkpath(qLocalDir.path());
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_GET_FILE; reset_record(); inc_record(rt_total);
build_get_cmd(remotefile, localfile); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_get_files(QVariantList& files, int msec) {
if(files.isEmpty()) return false;
const QString strcmd = tr("get file");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
int file_size = files.size() / 2; if(file_size <= 0) return false;
clear_cmd();
for (int i = 0; i < file_size; ++i) {
QFileInfo qremotefile(files[2 * i].toString()), qlocalfile(files[2 * i + 1].toString());
QDir qLocalDir(qlocalfile.absolutePath().mid(0, qlocalfile.absolutePath().lastIndexOf("/")));
if (!qLocalDir.exists()) QDir().mkpath(qLocalDir.path());
}
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_GET_FILES; reset_record(); inc_record(rt_total, file_size);
build_gets_cmd(files); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_get_tree(const QString& remoteabspath, const QString& localabspath, const QStringList& vExcept, int msec){
if(remoteabspath.isEmpty() || localabspath.isEmpty()) return false;
const QString strcmd = tr("get tree");
if (state() != QFtp::LoggedIn) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Get, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_vExcept.clear(); m_cmd = QC_GET_TREE; reset_record();
build_getree_cmd(remoteabspath, localabspath, vExcept); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_rm_file(const QString& remotefile, int msec){
if(remotefile.isEmpty()) return false;
const QString strcmd = tr("rm file");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Remove, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Remove, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_RM_FILE; reset_record(); inc_record(rt_total);
build_rm_cmd(remotefile); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_rm_tree(const QString& dir, int msec){
if(dir.isEmpty()) return false;
const QString strcmd = tr("rm tree");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Rmdir, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Rmdir, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_RM_TREE; reset_record();
m_rmlist.clear(); build_rmdir_cmd(dir); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_mk_dir(const QString& dir, int msec){
if(dir.isEmpty()) return false;
const QString strcmd = tr("mk dir");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_MKD; reset_record(); inc_record(rt_total);
build_mkdir_cmd(dir.indexOf(".") >= 0 ? dir.left(dir.lastIndexOf("/")) : dir);
return next_cmd_util_done(msec);
}
bool QFtpClient::inner_mk_dir(const QStringList& dirlist, int msec){
if(dirlist.isEmpty()) return false;
const QString strcmd = tr("mk multi dir");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Mkdir, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_MKDS; reset_record(); inc_record(rt_total, dirlist.size());
for (const QString& remotedir : dirlist)
build_mkdir_cmd(remotedir.indexOf(".") >= 0 ? remotedir.left(remotedir.lastIndexOf("/")) : remotedir);
return next_cmd_util_done(msec);
}
bool QFtpClient::inner_rename(const QString& remotefilepath, const QString& newname, int msec){
if(remotefilepath.isEmpty() || newname.isEmpty()) return false;
const QString strcmd = tr("rename");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Rename, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Rename, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_RENAME; reset_record(); inc_record(rt_total);
build_rename_cmd(remotefilepath, newname); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_list(const QString& remotepath, int msec) {
if(remotepath.isEmpty()) return false;
const QString strcmd = tr("list");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::List, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::List, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_cmd = QC_LIST;
reset_record(); inc_record(rt_total);
m_listresult.clear(); build_list_cmd(remotepath); return next_cmd_util_done(msec);
}
bool QFtpClient::inner_cd(const QString& dirname, bool done_list, int msec) {
if(dirname.isEmpty()) return false;
const QString strcmd = tr("cd");
if (!is_connect()) {
KOE_WARN(tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
emit signal_command_finish(QFtp::Cd, {}, tr("fail to %1 for reason:ftp not loggedin").arg(strcmd));
return false;
}
if (has_cmd()) {
KOE_WARN(tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
emit signal_command_finish(QFtp::Cd, {}, tr("fail to exec command: %1, there are some other command executing, please try moment later").arg(strcmd));
return false;
}
else KOE_DEBUG(tr("command: %1").arg(strcmd));
clear_cmd();
#ifdef _DEBUG
set_start();
#endif
m_listresult.clear(); m_cmd = QC_CD; reset_record(); inc_record(rt_total);
build_pwd_cd_cmd(dirname, done_list); return next_cmd_util_done(msec);
}
这是QFtpclient.cpp