From c3f8ee64e905cdb103b5bfa07525fb4e85c31120 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 24 Jul 2013 11:49:27 -0500 Subject: Initial import of kasablanca 0.4.0.2 --- src/ftpthread.cpp | 1437 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1437 insertions(+) create mode 100644 src/ftpthread.cpp (limited to 'src/ftpthread.cpp') diff --git a/src/ftpthread.cpp b/src/ftpthread.cpp new file mode 100644 index 0000000..842fecc --- /dev/null +++ b/src/ftpthread.cpp @@ -0,0 +1,1437 @@ +/*************************************************************************** + * Copyright (C) 2004 by Magnus Kulke * + * mkulke@magnusmachine * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +// enable > 2gb support (LFS) + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE + +#include + +#include +#include +#include + +#include +#include + +#include "kbconfig.h" +#include "ftplib.h" +#include "kbdirinfo.h" +#include "eventhandler.h" +#include "kbfileinfo.h" +#include "ftpthread.h" + +using namespace std; + +/* +class description: + +the class accepts ftp operations by public methods. when such a method is called, +a certain type value is appended to a list. in the threads main loop (triggered when +start() is called) the list is processed by calling the ftplibpp functions. depending +on the result of an operation a certain event is posted to the eventreceiver. when +there is a value to be returned, it's named out_. +*/ + + +FtpThread::FtpThread() : QThread() +{ + mp_eventreceiver = NULL; + mp_ftp = new ftplib(); + + mp_ftp->SetCallbackArg(this); + mp_ftp->SetCallbackLogFunction(FtpThread::CallbackLog); + mp_ftp->SetCallbackBytes(1024); + mp_ftp->SetCallbackXferFunction(FtpThread::CallbackXfer); +} + +FtpThread::~FtpThread() +{ + delete mp_ftp; +} + +/* init the variables the ftp session needs */ + +void FtpThread::InitInternals() +{ + m_stringlist.clear(); + m_intlist.clear(); + m_ulonglist.clear(); + m_pwd = ""; + m_dataencrypted = false; + m_cache_vector.clear(); + m_cache_list.clear(); +} + +/* callback function for the transfer */ + +int FtpThread::CallbackXfer(off64_t xfered, void *arg) +{ + FtpThread* ftp = static_cast(arg); + + ftp->Event(EventHandler::xfered, new xferpair(xfered, ftp->m_dataencrypted)); + return 1; +} + +/* callback function for the logs */ + +void FtpThread::CallbackLog(char *log, void *arg, bool out) +{ + /* the incoming log message isn't formatted at all. data + can be "end.\r\n230 ne" for example. the log gets chopped + into lines and for every line an events is posted. for + in-logs there's no need for this procedure, as the logs + always arrive in line-format. */ + + FtpThread* ftp = static_cast(arg); + + if (out) + { + int pos; + QString buffer = ftp->m_linebuffer + log; + while ((pos = buffer.find('\n')) != -1) + { + ftp->Event(EventHandler::outlog, new QString(buffer.left(pos + 1))); + buffer.remove(0, pos + 1); + } + ftp->m_linebuffer = buffer; + } + else ftp->Event(EventHandler::inlog, new QString(log)); +} + +/* set the receiver for the events the thread posts when a certain ftp operation is done */ + +void FtpThread::SetEventReceiver(QObject* eventreceiver) +{ + mp_eventreceiver = eventreceiver; +} + +/* connect to host */ + +bool FtpThread::Connect(QString host) +{ + InitInternals(); + + if (running()) return false; + else + { + m_stringlist.append(host); + m_tasklist.append(FtpThread::connect); + return true; + } +} + +/* login with user and pass */ + +bool FtpThread::Login(QString user, QString pass) +{ + if (running()) return false; + else + { + m_stringlist.append(user); + m_stringlist.append(pass); + m_tasklist.append(FtpThread::login); + return true; + } +} + +/* quit the ftp session*/ + +bool FtpThread::Quit() +{ + if (running()) return false; + else + { + m_tasklist.append(FtpThread::quit); + return true; + } +} + +/* get file */ + +bool FtpThread::Transfer_Get(QString src, QString dst, int tls, off64_t resume) +{ + if (running()) return false; + else + { + m_stringlist.append(src); + m_stringlist.append(dst); + m_intlist.append(tls); + m_ulonglist.append(resume); + m_tasklist.append(FtpThread::transfer_get); + return true; + } +} + +/* fxp file */ + +bool FtpThread::Transfer_Fxp(QString src, QString dst, FtpThread *dstftp, int srctls, int dsttls, off64_t resume, int alt) +{ + if (running()) return false; + else + { + m_stringlist.append(src); + m_stringlist.append(dst); + m_ftplist.append(dstftp); + m_intlist.append(srctls); + m_intlist.append(dsttls); + m_ulonglist.append(resume); + m_intlist.append(alt); + m_tasklist.append(FtpThread::transfer_fxp); + return true; + } +} + +/* put file */ + +bool FtpThread::Transfer_Put(QString src, QString dst, int tls, off64_t resume) +{ + if (running()) return false; + else + { + m_stringlist.append(src); + m_stringlist.append(dst); + m_intlist.append(tls); + m_ulonglist.append(resume); + m_tasklist.append(FtpThread::transfer_put); + return true; + } +} + +/* transfer mkdir */ + +bool FtpThread::Transfer_Mkdir(QString dir) +{ + if (running()) return false; + else + { + m_stringlist.append(dir); + m_tasklist.append(FtpThread::transfer_mkdir); + return true; + } +} + +/* rename file */ + +bool FtpThread::Rename(QString src, QString dst) +{ + if (running()) return false; + else + { + m_stringlist.append(src); + m_stringlist.append(dst); + m_tasklist.append(FtpThread::rename); + return true; + } +} + +/* set wether the data channel is encrypted or not */ + +bool FtpThread::Pasv(bool flag) +{ + if (running()) return false; + else + { + if (flag) mp_ftp->SetConnmode(ftplib::pasv); + else mp_ftp->SetConnmode(ftplib::port); + return true; + } +} + +/* set wether the data channel is encrypted or not */ + +bool FtpThread::EncryptData(bool flag, bool force) +{ + if (running()) return false; + else + { + m_intlist.append(flag); + m_intlist.append(force); + m_tasklist.append(FtpThread::dataencryption); + return true; + } +} + +/* retrieve the current workind dir */ + +bool FtpThread::Pwd() +{ + if (running()) return false; + else + { + m_tasklist.append(FtpThread::pwd); + return true; + } +} + +/* change working dir to the given path */ + +bool FtpThread::Chdir(QString path) +{ + if (running()) return false; + else + { + m_stringlist.append(path); + m_tasklist.append(FtpThread::chdir); + return true; + } +} + +/* change working dir to the given path, used by transfers */ + +bool FtpThread::Transfer_Changedir(QString dir, int tls) +{ + if (running()) return false; + else + { + m_stringlist.append(dir); + m_intlist.append(tls); + m_tasklist.append(FtpThread::transfer_changedir); + return true; + } +} + +/* creates a directory */ + +bool FtpThread::Mkdir(QString path) +{ + if (running()) return false; + else + { + m_stringlist.append(path); + m_tasklist.append(FtpThread::mkdir); + return true; + } +} + +/* step above in the working dir */ + +bool FtpThread::Cdup() +{ + if (running()) return false; + else + { + m_tasklist.append(FtpThread::cdup); + return true; + } +} + +/* retrieve dir contents */ + +bool FtpThread::Dir(bool force) +{ + if (running()) return false; + else + { + m_intlist.append(force); + m_tasklist.append(FtpThread::dir); + return true; + } +} + +/* attempt negotiating an encrypted session */ + +bool FtpThread::Authtls() +{ + if (running()) return false; + else + { + m_tasklist.append(FtpThread::authtls); + return true; + } +} + +/* delete a file */ + +bool FtpThread::Rm(QString name) +{ + wait(KB_THREAD_TIMEOUT); + if (running()) return false; + else + { + m_stringlist.append(name); + m_tasklist.append(FtpThread::rm); + return true; + } +} + +/* delete a directory */ + +bool FtpThread::Rmdir(QString name) +{ + if (running()) return false; + else + { + m_stringlist.append(name); + m_tasklist.append(FtpThread::rmdir); + return true; + } +} + +/* issue raw command */ + +bool FtpThread::Raw(QString cmd) +{ + if (running()) return false; + else + { + m_stringlist.append(cmd); + m_tasklist.append(FtpThread::raw); + return true; + } +} + +/* scan the directory recursively */ + +bool FtpThread::Scandir(KbDirInfo* dir) +{ + if (running()) return false; + else + { + mp_scandir = dir; + m_tasklist.append(FtpThread::scandir); + return true; + } +} +/* the thread methods */ + +void FtpThread::Connect_thread() +{ + int result; + QString host = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Connect(host.latin1()); + + //unsigned long int xxx = mp_ftp->mp_netbuf->ipappr; + //qWarning("INFO %lu.%lu.%lu.%lu", xxx & 0xff, (xxx >> 8) & 0xff, (xxx >> 16) & 0xff, (xxx >> 24) & 0xff); + //qWarning("INFO: ip:%lu", mp_ftp->mp_netbuf->ipappr); + + if (result) Event(EventHandler::connect_success); + else + { + ClearQueue(); + Event(EventHandler::connect_failure); + } +} + +void FtpThread::Authtls_thread() +{ + int result; + + result = mp_ftp->NegotiateEncryption(); + + if (result) Event(EventHandler::authtls_success); + else + { + ClearQueue(); + Event(EventHandler::authtls_failure); + } +} + +void FtpThread::Login_thread() +{ + int result; + QString user = m_stringlist.front(); + m_stringlist.pop_front(); + QString pass = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Login(user.latin1(), pass.latin1()); + + if (result) Event(EventHandler::login_success); + else + { + ClearQueue(); + Event(EventHandler::login_failure); + } +} + +void FtpThread::Dataencryption_thread() +{ + int result, flag, force, cacheindex; + + flag = m_intlist.front(); + m_intlist.pop_front(); + force = m_intlist.front(); + m_intlist.pop_front(); + + cacheindex = -1; + + if (KbConfig::dirCachingIsEnabled()) + { + cacheindex = m_cache_list.findIndex(m_pwd); + + if ((cacheindex != -1) && (!force)) + { + Event(EventHandler::encryptdata_success); + return; + } + } + + if (flag) result = mp_ftp->SetDataEncryption(ftplib::secure); + else result = mp_ftp->SetDataEncryption(ftplib::unencrypted); + + if (result) + { + Event(EventHandler::encryptdata_success); + m_dataencrypted = flag; + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::encryptdata_failure); + } +} + +void FtpThread::Transfer_Changedir_thread() +{ + int result; + char buffer[1024]; + QString dirname; + + dirname = locateLocal("appdata", QString::number(rand()) + ".dir"); + + QString path = m_stringlist.front(); + m_stringlist.pop_front(); + int tls = m_intlist.front(); + m_intlist.pop_front(); + + if (path == m_pwd) + { + Event(EventHandler::transfer_success); + return; + } + + result = mp_ftp->Chdir(path.latin1()); + if (result) Event(EventHandler::chdir_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::chdir_failure); + Event(EventHandler::transfer_failure); + return; + } + + result = mp_ftp->Pwd(buffer, 1024); + if (result) + { + Event(EventHandler::pwd_success, new QString(buffer)); + m_pwd = buffer; + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::pwd_failure); + Event(EventHandler::transfer_failure); + return; + } + + if (tls) + { + result = mp_ftp->SetDataEncryption(ftplib::secure); + if (result) + { + Event(EventHandler::encryptdata_success); + m_dataencrypted = true; + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::encryptdata_failure); + Event(EventHandler::transfer_failure); + return; + } + } + + result = mp_ftp->Dir(dirname.latin1(), ""); + if (result) + { + m_dirlist.clear(); + m_filelist.clear(); + FormatFilelist(dirname.latin1(), m_pwd, &m_dirlist, &m_filelist); + m_dircontent.first = m_dirlist; + m_dircontent.second = m_filelist; + Event(EventHandler::dir_success, &m_dircontent); + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::dir_failure, &m_dircontent); + } + + if (!result) Event(EventHandler::transfer_failure); + else Event(EventHandler::transfer_success); + + QFile::remove(dirname); +} + +void FtpThread::Transfer_Mkdir_thread() +{ + int result; + QString dir = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Mkdir(dir.latin1()); + if (result) Event(EventHandler::mkdir_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::mkdir_failure); + Event(EventHandler::transfer_failure); + return; + } + + Event(EventHandler::transfer_success); +} + +void FtpThread::Transfer_Get_thread() +{ + int result; + + QString src = m_stringlist.front(); + m_stringlist.pop_front(); + QString dst = m_stringlist.front(); + m_stringlist.pop_front(); + int tls = m_intlist.front(); + m_intlist.pop_front(); + off64_t resume = m_ulonglist.front(); + m_ulonglist.pop_front(); + + if (tls > 1) + { + if (tls == 2) result = mp_ftp->SetDataEncryption(ftplib::unencrypted); + else result = mp_ftp->SetDataEncryption(ftplib::secure); + if (result) + { + Event(EventHandler::encryptdata_success); + m_dataencrypted = (tls > 2); + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::encryptdata_failure); + Event(EventHandler::transfer_failure); + return; + } + } + + if (resume == 0) result = mp_ftp->Get(dst.latin1(), src.latin1(), ftplib::image); + else result = mp_ftp->Get(dst.latin1(), src.latin1(), ftplib::image, resume); + + if (result) Event(EventHandler::get_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::get_failure); + Event(EventHandler::transfer_failure); + return; + } + + Event(EventHandler::transfer_success); +} + +void FtpThread::Transfer_Put_thread() +{ + int result; + + QString src = m_stringlist.front(); + m_stringlist.pop_front(); + QString dst = m_stringlist.front(); + m_stringlist.pop_front(); + int tls = m_intlist.front(); + m_intlist.pop_front(); + off64_t resume = m_ulonglist.front(); + m_ulonglist.pop_front(); + + if (tls > 1) + { + if (tls == 2) result = mp_ftp->SetDataEncryption(ftplib::unencrypted); + else result = mp_ftp->SetDataEncryption(ftplib::secure); + if (result) + { + Event(EventHandler::encryptdata_success); + m_dataencrypted = (tls > 2); + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::encryptdata_failure); + Event(EventHandler::transfer_failure); + return; + } + } + + if (resume == 0) result = mp_ftp->Put(src.latin1(), dst.latin1(), ftplib::image); + else result = mp_ftp->Put(src.latin1(), dst.latin1(), ftplib::image, resume); + + if (result) Event(EventHandler::put_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::put_failure); + Event(EventHandler::transfer_failure); + return; + } + + Event(EventHandler::transfer_success); +} + +void FtpThread::Quit_thread() +{ + int result; + + result = mp_ftp->Quit(); + + if (result) Event(EventHandler::quit_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::quit_failure); + } +} + +void FtpThread::Transfer_Fxp_thread() +{ + int result = 0; + ftplib::ftp method; + + QString src = m_stringlist.front(); + m_stringlist.pop_front(); + QString dst = m_stringlist.front(); + m_stringlist.pop_front(); + FtpThread* dstftp = m_ftplist.front(); + m_ftplist.pop_front(); + int srctls = m_intlist.front(); + m_intlist.pop_front(); + int dsttls = m_intlist.front(); + m_intlist.pop_front(); + off64_t resume = m_ulonglist.front(); + m_ulonglist.pop_front(); + int alt = m_intlist.front(); + m_intlist.pop_front(); + + if (srctls > 1) + { + if (!FxpDisableTls()) + { + Event(EventHandler::transfer_failure); + return; + } + } + + if (dsttls > 1) + { + if (!dstftp->FxpDisableTls()) + { + Event(EventHandler::transfer_failure); + return; + } + } + + if (alt) method = ftplib::alternativefxp; + else method = ftplib::defaultfxp; + + qWarning("bla_thread: %d", alt); + + if (resume) qWarning("WARNING: fxp resume isn't supported. overwriting file instead"); + result == ftplib::Fxp(mp_ftp, dstftp->Ftp(), src, dst, ftplib::image, method); + + FxpReportResult(result); + dstftp->FxpReportResult(result); + + if (result) Event(EventHandler::transfer_success); + else Event(EventHandler::transfer_failure); +} + +bool FtpThread::FxpDisableTls() +{ + bool result = mp_ftp->SetDataEncryption(ftplib::unencrypted); + if (result) + { + Event(EventHandler::encryptdata_success); + m_dataencrypted = false; + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::encryptdata_failure); + } + + return result; +} + +void FtpThread::FxpReportResult(bool result) +{ + if (result) Event(EventHandler::fxp_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::fxp_failure); + } +} + +void FtpThread::Pwd_thread() +{ + char buffer[1024]; + int result; + + result = mp_ftp->Pwd(buffer, 1024); + + if (result) + { + Event(EventHandler::pwd_success, new QString(buffer)); + m_pwd = buffer; + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::pwd_failure); + } +} + +void FtpThread::Chdir_thread() +{ + int result; + + QString path = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Chdir(path.latin1()); + + if (result) Event(EventHandler::chdir_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::chdir_failure); + } +} + +void FtpThread::Mkdir_thread() +{ + int result; + + QString path = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Mkdir(path.latin1()); + + if (result) Event(EventHandler::mkdir_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::mkdir_failure); + } +} + +void FtpThread::Cdup_thread() +{ + int result; + + result = mp_ftp->Cdup(); + + if (result) Event(EventHandler::chdir_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::chdir_failure); + } +} + +void FtpThread::Rm_thread() +{ + int result; + + QString name = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Delete(name.latin1()); + + if (result) Event(EventHandler::rm_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::rm_failure); + } +} + +void FtpThread::Rename_thread() +{ + int result; + + QString src = m_stringlist.front(); + m_stringlist.pop_front(); + QString dst = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Rename(src.latin1(),dst.latin1()); + + if (result) Event(EventHandler::rename_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::rename_failure); + } +} + +void FtpThread::Dir_thread() +{ + int result; + QString dirname; + int cacheindex = -1; + + int force = m_intlist.front(); + m_intlist.pop_front(); + + dirname = locateLocal("appdata", QString::number(rand()) + ".dir"); + + if (KbConfig::dirCachingIsEnabled()) + { + cacheindex = m_cache_list.findIndex(m_pwd); + + if ((cacheindex != -1) && (!force)) + { + m_dircontent = m_cache_vector.at(cacheindex); + Event(EventHandler::dir_success, &m_dircontent); + return; + } + } + + result = mp_ftp->Dir(dirname.latin1(), ""); + + if (result) + { + m_dirlist.clear(); + m_filelist.clear(); + FormatFilelist(dirname.latin1(), m_pwd, &m_dirlist, &m_filelist); + m_dircontent.first = m_dirlist; + m_dircontent.second = m_filelist; + m_cache_vector.push_back(m_dircontent); + m_cache_list.push_back(m_pwd); + + if (KbConfig::dirCachingIsEnabled()) + { + if (cacheindex == -1) + { + m_cache_vector.push_back(m_dircontent); + m_cache_list.push_back(m_pwd); + } + else m_cache_vector.at(cacheindex) = m_dircontent; + } + Event(EventHandler::dir_success, &m_dircontent); + } + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::dir_failure, &m_dircontent); + } + + QFile::remove(dirname); +} + +void FtpThread::Scandir_thread() +{ + bool result = true; + + list::iterator end_dir = mp_scandir->Dirlist()->end(); + for(list::iterator dirIterator = mp_scandir->Dirlist()->begin(); dirIterator != end_dir; dirIterator++) + { + result = Scandir_recurse(*dirIterator, (*dirIterator)->dirPath() + (*dirIterator)->fileName()); + } + + if (result) Event(EventHandler::scandir_success, mp_scandir); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::scandir_failure); + } +} + +void FtpThread::Rmdir_thread() +{ + bool result; + + QString name = m_stringlist.front(); + m_stringlist.pop_front(); + + result = Delete_recurse(name.latin1()); + + if (result) Event(EventHandler::rmdir_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::rmdir_failure); + } +} + +void FtpThread::Raw_thread() +{ + bool result; + + QString cmd = m_stringlist.front(); + m_stringlist.pop_front(); + + result = mp_ftp->Raw(cmd.latin1()); + + if (result) Event(EventHandler::raw_success); + else + { + if (ConnectionLost()) Event(EventHandler::connectionlost); + else Event(EventHandler::raw_failure); + } +} + +/* the thread's main loop */ + +void FtpThread::run() +{ + while (!m_tasklist.empty()) + { + task t = m_tasklist.front(); + m_tasklist.pop_front(); + + switch (t) + { + case FtpThread::connect: + Connect_thread(); + break; + case FtpThread::login: + Login_thread(); + break; + case FtpThread::quit: + Quit_thread(); + break; + case FtpThread::pwd: + Pwd_thread(); + break; + case FtpThread::chdir: + Chdir_thread(); + break; + case FtpThread::cdup: + Cdup_thread(); + break; + case FtpThread::dir: + Dir_thread(); + break; + case FtpThread::scandir: + Scandir_thread(); + break; + case FtpThread::rm: + Rm_thread(); + break; + case FtpThread::rmdir: + Rmdir_thread(); + break; + case FtpThread::authtls: + Authtls_thread(); + break; + case FtpThread::dataencryption: + Dataencryption_thread(); + break; + case FtpThread::transfer_get: + Transfer_Get_thread(); + break; + case transfer_put: + Transfer_Put_thread(); + break; + case FtpThread::mkdir: + Mkdir_thread(); + break; + case FtpThread::rename: + Rename_thread(); + break; + case FtpThread::raw: + Raw_thread(); + break; + case FtpThread::transfer_changedir: + Transfer_Changedir_thread(); + break; + case FtpThread::transfer_mkdir: + Transfer_Mkdir_thread(); + break; + case FtpThread::transfer_fxp: + Transfer_Fxp_thread(); + default: + Event(EventHandler::error); + break; + } + } + Event(EventHandler::finished); +} + +/* event is posted to the eventreceiver */ + +void FtpThread::Event(EventHandler::EventType type, void *data) +{ + if (mp_eventreceiver == NULL) qWarning("WARNING: mp_eventreceiver is NULL"); + else + { + QCustomEvent* e = new QCustomEvent(type); + if (data != NULL) e->setData(data); + qApp->postEvent(mp_eventreceiver, e); + } +} + +/* parses the dir file */ + +bool FtpThread::FormatFilelist(const char *filename, QString current, filist *dirtable, filist *filetable) +{ + int i, blocks, space, month_int = 1; + unsigned int loc, fileloc, datebegin, sizebegin = 0; + string buffer, filestring; + + FILE* dirfile; + + char file[1024]; + + char month[][5] = { + "... ", "Jan ", "Feb ", "Mar ", "Apr ", "May ", "Jun ", "Jul ", "Aug ", + "Sep ", "Oct ", "Nov ", "Dec " + }; + + dirfile = fopen(filename, "r"); + if (dirfile == NULL) + { + qWarning("ERROR: failed open dirfile"); + return false; + } + + while (fgets(file, 1024, dirfile) != NULL) + { + *(strchr(file,'\n')) = '\0'; + buffer = file; + + for (i = 1; i < 13; i++) + { + loc = buffer.find(month[i], 0); + if (loc != string::npos) + { + month_int = i; + break; + } + } + if( loc == string::npos ) + { + qWarning("INFO: no month entry found"); + loc = buffer.length(); + } + + datebegin = loc; + + space = 1; + blocks = 0; + fileloc = 0; + while (loc < buffer.length()) + { + if (space) + { + // look for a space + if (buffer[loc] == ' ') + { + blocks++; + space = !space; + } + } + else + { + // look for a non-space + if (buffer[loc] != ' ') + { + if (blocks > 2) + { + fileloc = loc; + break; + } + space = !space; + } + } + loc += 1; + } + if (blocks != 3) + { + qWarning("INFO: ignoring invalid line in dirlist"); + } + else + { + QString date(buffer.substr( datebegin, loc - datebegin - 1).c_str()); + + int day_int = date.section( ' ', 1, 1 ).toInt(); + int year_int = date.section( ' ', -1, -1 ).toInt(); + int hour_int = 0; + int minute_int = 0; + + if (day_int == 0) day_int = date.section( ' ', 1, 2 ).toInt(); + + if (year_int == 0) + { + year_int = QDate::currentDate().year(); + if (month_int > QDate::currentDate().month()) year_int--; + QTime mytime = QTime::fromString(date.section( ' ', -1, -1 )); + hour_int = mytime.hour(); + minute_int = mytime.minute(); + } + + unsigned int date_int = + (minute_int) | + (hour_int << 6 ) | + (day_int << 11) | + (month_int << 16) | + (year_int << 20); + + // 6 bits for minutes, 5 bits for hours, 5 bits for days, 4 bits for months, 11 bits for years -> 31 bits (should be sufficient) + + space = 0; + blocks = 0; + loc = datebegin; + while (loc > 0) + { + if (space) + { + if (buffer[loc] == ' ') + { + blocks++; + space = !space; + } + } + else + { + if (buffer[loc] != ' ') + { + if (blocks > 1) + { + sizebegin = loc + 1; + break; + } + space = !space; + } + } + loc--; + } + + off64_t size = atoll(buffer.substr( sizebegin, datebegin - sizebegin).c_str()); + + filestring.erase(); + filestring.append(buffer, fileloc, buffer.length() - fileloc); + if ((filestring.compare(".") != 0) && (filestring.compare("..") != 0)) + { + if ((*file == 'd') || (*file == 'D')) + { + KbFileInfo* di = new KbFileInfo(current, filestring.c_str(), size, date, date_int); + dirtable->push_back(di); + } + else if ((*file == 'l') || (*file == 'L')) + { + qWarning("INFO: links to files not supported yet"); + } + else + { + KbFileInfo* fi = new KbFileInfo(current, filestring.c_str(), size, date, date_int); + filetable->push_back(fi); + } + } + } + } + fclose(dirfile); + return true; +} + +/* recursive method to check content of a directory */ + +bool FtpThread::Scandir_recurse(KbDirInfo *dir, QString path) +{ + char currentpath[1024]; + int result; + filist dirlist; + filist filelist; + QString dirname; + + result = mp_ftp->Pwd(currentpath, 1024); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + result = mp_ftp->Chdir(dir->fileName().latin1()); + + if (!result) + { + Event(EventHandler::misc_failure); + return true; + } + else Event(EventHandler::misc_success); + + dirname = locateLocal("appdata", QString::number(rand()) + ".dir"); + + result = mp_ftp->Dir(dirname.latin1(), ""); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + if(!FormatFilelist(dirname.latin1(), path, &dirlist, &filelist)) return false; + + QFile::remove(dirname); + + filist::iterator end_file = filelist.end(); + for(filist::iterator fiIterator = filelist.begin(); fiIterator != end_file; fiIterator++) + { + dir->AddFile(*fiIterator); + } + + filist::iterator end_dir = dirlist.end(); + for(filist::iterator fiIterator = dirlist.begin(); fiIterator != end_dir; fiIterator++) + { + KbDirInfo* newdir = dir->AddDirectory(**fiIterator); + if (!Scandir_recurse(newdir, path + '/' + newdir->fileName())) return false; + } + + result = mp_ftp->Chdir(currentpath); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + return true; +} + +/* recursive method to delete directories */ + +bool FtpThread::Delete_recurse(QString name) +{ + char currentdir[1024]; + int result; + filist dirlist; + filist filelist; + QString dirname; + + result = mp_ftp->Pwd(currentdir, 1024); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + result = mp_ftp->Chdir(name.latin1()); + + if (!result) + { + Event(EventHandler::misc_failure); + return true; + } + else Event(EventHandler::misc_success); + + //dirname = QDir::homeDirPath() + + //"/.kasablanca/" + + //QString::number((int) time(NULL) & 0xffff) + + //".dir"; + dirname = locateLocal("appdata", QString::number(rand()) + ".dir"); + + result = mp_ftp->Dir(dirname.latin1(), ""); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + if(!FormatFilelist(dirname.latin1(), "", &dirlist, &filelist)) return false; + + QFile::remove(dirname); + + filist::iterator end_file = filelist.end(); + for(filist::iterator fiIterator = filelist.begin(); fiIterator != end_file; fiIterator++) + { + result = mp_ftp->Delete((*fiIterator)->fileName().latin1()); + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + } + + filist::iterator end_dir = dirlist.end(); + for(filist::iterator fiIterator = dirlist.begin(); fiIterator != end_dir; fiIterator++) + { + if (!Delete_recurse((*fiIterator)->fileName())) return false; + } + + result = mp_ftp->Chdir(currentdir); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + result = mp_ftp->Rmdir(name.latin1()); + + if (!result) + { + Event(EventHandler::misc_failure); + return false; + } + else Event(EventHandler::misc_success); + + return true; +} + +/* check if we lost the connection */ + +bool FtpThread::ConnectionLost() +{ + QString response; + + response = mp_ftp->LastResponse(); + + if (response.startsWith("421")) + { + ClearQueue(); + return true; + } + else return false; +} + +/* empty queue */ + +void FtpThread::ClearQueue() +{ + m_tasklist.clear(); + m_stringlist.clear(); + m_intlist.clear(); + m_ulonglist.clear(); + m_ftplist.clear(); + m_cache_vector.clear(); + m_cache_list.clear(); +} -- cgit v1.2.1