diff --git a/krusader/VFS/abstractthreadedjob.cpp b/krusader/VFS/abstractthreadedjob.cpp index 57c1da4a..fc8ddc60 100644 --- a/krusader/VFS/abstractthreadedjob.cpp +++ b/krusader/VFS/abstractthreadedjob.cpp @@ -1,651 +1,653 @@ /*************************************************************************** packjob.cpp - description ------------------- copyright : (C) 2009 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "abstractthreadedjob.h" -#include -#include -#include -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include +#include +#include +// QtWidgets +#include #include #include #include #include "krvfshandler.h" #include "krarchandler.h" #include "vfs.h" #include "preservingcopyjob.h" #include "../krglobal.h" #include "../krservices.h" extern KRarcHandler arcHandler; AbstractThreadedJob::AbstractThreadedJob() : KIO::Job(), _locker(), _waiter(), _stack(), _maxProgressValue(0), _currentProgress(0), _exiting(false), _jobThread(0) { } void AbstractThreadedJob::startAbstractJobThread(AbstractJobThread * jobThread) { _jobThread = jobThread; _jobThread->setJob(this); _jobThread->moveToThread(_jobThread); _jobThread->start(); } AbstractThreadedJob::~AbstractThreadedJob() { _exiting = true; if (_jobThread) { _jobThread->abort(); _locker.lock(); _waiter.wakeAll(); _locker.unlock(); _jobThread->wait(); delete _jobThread; } } bool AbstractThreadedJob::event(QEvent *e) { if (e->type() == QEvent::User) { UserEvent *event = (UserEvent*) e; switch (event->command()) { case CMD_SUCCESS: { emitResult(); } break; case CMD_ERROR: { int error = event->args()[ 0 ].value(); QString errorText = event->args()[ 1 ].value(); setError(error); setErrorText(errorText); emitResult(); } break; case CMD_INFO: { QString info = event->args()[ 0 ].value(); QString arg1 = event->args()[ 1 ].value(); QString arg2 = event->args()[ 2 ].value(); QString arg3 = event->args()[ 3 ].value(); QString arg4 = event->args()[ 4 ].value(); _title = info; emit description(this, info, qMakePair(arg1, arg2), qMakePair(arg3, arg4)); } break; case CMD_RESET: { QString info = event->args()[ 0 ].value(); QString arg1 = event->args()[ 1 ].value(); QString arg2 = event->args()[ 2 ].value(); QString arg3 = event->args()[ 3 ].value(); QString arg4 = event->args()[ 4 ].value(); _title = info; setProcessedAmount(KJob::Bytes, 0); setTotalAmount(KJob::Bytes, 0); emitSpeed(0); emit description(this, info, qMakePair(arg1, arg2), qMakePair(arg3, arg4)); } break; case CMD_UPLOAD_FILES: case CMD_DOWNLOAD_FILES: { QList sources = KrServices::toUrlList(event->args()[ 0 ].value()); QUrl dest = event->args()[ 1 ].value(); KIO::Job *job = PreservingCopyJob::createCopyJob(PM_PRESERVE_ATTR, sources, dest, KIO::CopyJob::Copy, false, false); addSubjob(job); job->setUiDelegate(new KIO::JobUiDelegate()); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotDownloadResult(KJob*))); connect(job, SIGNAL(processedAmount(KJob *, KJob::Unit, qulonglong)), this, SLOT(slotProcessedAmount(KJob *, KJob::Unit, qulonglong))); connect(job, SIGNAL(totalAmount(KJob *, KJob::Unit, qulonglong)), this, SLOT(slotTotalAmount(KJob *, KJob::Unit, qulonglong))); connect(job, SIGNAL(speed(KJob *, unsigned long)), this, SLOT(slotSpeed(KJob *, unsigned long))); connect(job, SIGNAL(description(KJob *, const QString &, const QPair &, const QPair &)), this, SLOT(slotDescription(KJob *, const QString &, const QPair &, const QPair &))); } break; case CMD_MAXPROGRESSVALUE: { qulonglong maxValue = event->args()[ 0 ].value(); _maxProgressValue = maxValue; _currentProgress = 0; } break; case CMD_ADD_PROGRESS: { qulonglong progress = event->args()[ 0 ].value(); _currentProgress += progress; if (_maxProgressValue != 0) { setPercent(100 * _currentProgress / _maxProgressValue); int elapsed = _time.isNull() ? 1 : _time.secsTo(QTime::currentTime()); if (elapsed != 0 && event->args().count() > 1) { _time = QTime::currentTime(); QString progressString = (event->args()[ 1 ].value()); emit description(this, _title, qMakePair(progressString, QString("%1/%2").arg(_currentProgress).arg(_maxProgressValue)), qMakePair(QString(), QString()) ); } } } break; case CMD_GET_PASSWORD: { QString path = event->args()[ 0 ].value(); QString password = KRarcHandler::getPassword(path); QList *resultResp = new QList (); (*resultResp) << password; addEventResponse(resultResp); } break; case CMD_MESSAGE: { QString message = event->args()[ 0 ].value(); KIO::JobUiDelegate *ui = static_cast(uiDelegate()); KMessageBox::information(ui ? ui->window() : 0, message); QList *resultResp = new QList (); addEventResponse(resultResp); } break; } return true; } else { return KIO::Job::event(e); } } void AbstractThreadedJob::addEventResponse(QList * obj) { _locker.lock(); _stack.push(obj); _waiter.wakeOne(); _locker.unlock(); } QList * AbstractThreadedJob::getEventResponse(UserEvent * event) { _locker.lock(); QApplication::postEvent(this, event); _waiter.wait(&_locker); if (_exiting) return 0; QList *resp = _stack.pop(); _locker.unlock(); return resp; } void AbstractThreadedJob::sendEvent(UserEvent * event) { QApplication::postEvent(this, event); } void AbstractThreadedJob::slotDownloadResult(KJob* job) { QList *resultResp = new QList (); if (job) { (*resultResp) << QVariant(job->error()); (*resultResp) << QVariant(job->errorText()); } else { (*resultResp) << QVariant(KJob::UserDefinedError); (*resultResp) << QVariant(QString(i18n("Internal error, undefined in result signal"))); } addEventResponse(resultResp); } void AbstractThreadedJob::slotProcessedAmount(KJob *, KJob::Unit unit, qulonglong xu) { setProcessedAmount(unit, xu); } void AbstractThreadedJob::slotTotalAmount(KJob *, KJob::Unit unit, qulonglong xu) { setTotalAmount(unit, xu); } void AbstractThreadedJob::slotSpeed(KJob *, unsigned long spd) { emitSpeed(spd); } void AbstractThreadedJob::slotDescription(KJob *, const QString &title, const QPair &field1, const QPair &field2) { QString mytitle = title; if (!_title.isNull()) mytitle = _title; emit description(this, mytitle, field1, field2); } class AbstractJobObserver : public KRarcObserver { protected: AbstractJobThread * _jobThread; public: AbstractJobObserver(AbstractJobThread * thread): _jobThread(thread) {} virtual ~AbstractJobObserver() {} virtual void processEvents() Q_DECL_OVERRIDE { usleep(1000); qApp->processEvents(); } virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { _jobThread->sendReset(jobTitle); _jobThread->sendMaxProgressValue(count); } virtual void subJobStopped() Q_DECL_OVERRIDE { } virtual bool wasCancelled() Q_DECL_OVERRIDE { return _jobThread->_exited; } virtual void error(const QString & error) Q_DECL_OVERRIDE { _jobThread->sendError(KIO::ERR_NO_CONTENT, error); } virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { _jobThread->sendError(KIO::ERR_NO_CONTENT, error + '\n' + details); } virtual void incrementProgress(int c) Q_DECL_OVERRIDE { _jobThread->sendAddProgress(c, _jobThread->_progressTitle); } }; AbstractJobThread::AbstractJobThread() : _job(0), _downloadTempDir(0), _observer(0), _tempFile(0), _tempDir(0), _exited(false) { } AbstractJobThread::~AbstractJobThread() { if (_downloadTempDir) { delete _downloadTempDir; _downloadTempDir = 0; } if (_observer) { delete _observer; _observer = 0; } if (_tempFile) { delete _tempFile; _tempFile = 0; } } void AbstractJobThread::run() { QTimer::singleShot(0, this, SLOT(slotStart())); QPointer threadLoop = new QEventLoop(this); _loop = threadLoop; threadLoop->exec(); _loop = 0; delete threadLoop; } void AbstractJobThread::terminate() { if (_loop && !_exited) { _loop->quit(); _exited = true; } } void AbstractJobThread::abort() { terminate(); } QList AbstractJobThread::remoteUrls(const QUrl &baseUrl, const QStringList & files) { QList urlList; foreach(const QString &name, files) { QUrl url = baseUrl; url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (name)); urlList << url; } return urlList; } QUrl AbstractJobThread::downloadIfRemote(const QUrl &baseUrl, const QStringList & files) { // download remote URL-s if necessary if (!baseUrl.isLocalFile()) { sendInfo(i18n("Downloading remote files")); _downloadTempDir = new QTemporaryDir(); QList urlList = remoteUrls(baseUrl, files); QUrl dest(_downloadTempDir->path()); QList args; args << KrServices::toStringList(urlList); args << dest; UserEvent * downloadEvent = new UserEvent(CMD_DOWNLOAD_FILES, args); QList * result = _job->getEventResponse(downloadEvent); if (result == 0) return QUrl(); int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return QUrl(); } else { return dest; } } else { return baseUrl; } } QString AbstractJobThread::tempFileIfRemote(const QUrl &kurl, const QString &type) { if (kurl.isLocalFile()) { return kurl.path(); } _tempFile = new QTemporaryFile(QDir::tempPath() + QLatin1String("/krusader_XXXXXX.") + type); _tempFile->open(); _tempFileName = _tempFile->fileName(); _tempFile->close(); // necessary to create the filename QFile::remove(_tempFileName); _tempFileTarget = kurl; return _tempFileName; } QString AbstractJobThread::tempDirIfRemote(const QUrl &kurl) { if (kurl.isLocalFile()) { return kurl.adjusted(QUrl::StripTrailingSlash).path(); } _tempDir = new QTemporaryDir(); _tempDirTarget = kurl; return _tempDirName = _tempDir->path(); } void AbstractJobThread::sendSuccess() { terminate(); QList args; UserEvent * errorEvent = new UserEvent(CMD_SUCCESS, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendError(int errorCode, QString message) { terminate(); QList args; args << errorCode; args << message; UserEvent * errorEvent = new UserEvent(CMD_ERROR, args); _job->sendEvent(errorEvent); } void AbstractJobThread::sendInfo(QString message, QString a1, QString a2, QString a3, QString a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; UserEvent * infoEvent = new UserEvent(CMD_INFO, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendReset(QString message, QString a1, QString a2, QString a3, QString a4) { QList args; args << message; args << a1; args << a2; args << a3; args << a4; UserEvent * infoEvent = new UserEvent(CMD_RESET, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendMaxProgressValue(qulonglong value) { QList args; args << value; UserEvent * infoEvent = new UserEvent(CMD_MAXPROGRESSVALUE, args); _job->sendEvent(infoEvent); } void AbstractJobThread::sendAddProgress(qulonglong value, const QString &progress) { QList args; args << value; if (!progress.isNull()) args << progress; UserEvent * infoEvent = new UserEvent(CMD_ADD_PROGRESS, args); _job->sendEvent(infoEvent); } void AbstractJobThread::calcSpaceLocal(const QUrl &baseUrl, const QStringList & files, KIO::filesize_t &totalSize, unsigned long &totalDirs, unsigned long &totalFiles) { sendReset(i18n("Calculating space")); vfs *calcSpaceVfs = KrVfsHandler::getVfs(baseUrl); KIO::JobUiDelegate *ui = static_cast(_job->uiDelegate()); if(ui) calcSpaceVfs->setParentWindow(ui->window()); calcSpaceVfs->vfs_refresh(baseUrl); for (int i = 0; i != files.count(); i++) { calcSpaceVfs->vfs_calcSpaceLocal(files[ i ], &totalSize, &totalFiles, &totalDirs, &_exited); } delete calcSpaceVfs; } KRarcObserver * AbstractJobThread::observer() { if (_observer) return _observer; _observer = new AbstractJobObserver(this); return _observer; } bool AbstractJobThread::uploadTempFiles() { if (_tempFile != 0 || _tempDir != 0) { sendInfo(i18n("Uploading to remote destination")); if (_tempFile) { QList urlList; urlList << QUrl::fromLocalFile(_tempFileName); QList args; args << KrServices::toStringList(urlList); args << _tempFileTarget; UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == 0) return false; int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return false; } } if (_tempDir) { QList urlList; QDir tempDir(_tempDirName); QStringList list = tempDir.entryList(); foreach(const QString &name, list) { if (name == "." || name == "..") continue; QUrl url = QUrl::fromLocalFile(_tempDirName).adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + (name)); urlList << url; } QList args; args << KrServices::toStringList(urlList); args << _tempDirTarget; UserEvent * uploadEvent = new UserEvent(CMD_UPLOAD_FILES, args); QList * result = _job->getEventResponse(uploadEvent); if (result == 0) return false; int errorCode = (*result)[ 0 ].value(); QString errorText = (*result)[ 1 ].value(); delete result; if (errorCode) { sendError(errorCode, errorText); return false; } } } return true; } QString AbstractJobThread::getPassword(const QString &path) { QList args; args << path; UserEvent * getPasswdEvent = new UserEvent(CMD_GET_PASSWORD, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == 0) return QString(); QString password = (*result)[ 0 ].value(); if (password.isNull()) password = QString(""); delete result; return password; } void AbstractJobThread::sendMessage(const QString &message) { QList args; args << message; UserEvent * getPasswdEvent = new UserEvent(CMD_MESSAGE, args); QList * result = _job->getEventResponse(getPasswdEvent); if (result == 0) return; delete result; } //! Gets some archive information that is needed in several cases. /*! \param path A path to the archive. \param type The type of the archive. \param password The password of the archive. \param arcName The name of the archive. \param sourceFolder A QUrl, which may be remote, of the folder where the archive is. \return If the archive information has been obtained. */ bool AbstractJobThread::getArchiveInformation(QString &path, QString &type, QString &password, QString &arcName, const QUrl &sourceFolder) { // Safety checks (though the user shouldn't have been able to select something named "" or "..") if (arcName.isEmpty()) return false; if (arcName == "..") return false; QUrl url = sourceFolder.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + arcName); path = url.adjusted(QUrl::StripTrailingSlash).path(); QMimeDatabase db; QMimeType mt = db.mimeTypeForUrl(url); QString mime = mt.isValid() ? mt.name() : QString(); bool encrypted = false; type = arcHandler.getType(encrypted, path, mime); // Check that the archive is supported if (!KRarcHandler::arcSupported(type)) { sendError(KIO::ERR_NO_CONTENT, i18nc("%1=archive filename", "%1, unsupported archive type.", arcName)); return false; } password = encrypted ? getPassword(path) : QString(); return true; } diff --git a/krusader/VFS/abstractthreadedjob.h b/krusader/VFS/abstractthreadedjob.h index 7185a717..33374fb0 100644 --- a/krusader/VFS/abstractthreadedjob.h +++ b/krusader/VFS/abstractthreadedjob.h @@ -1,198 +1,199 @@ /*************************************************************************** threadedjob.h - description ------------------- copyright : (C) 2009 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef ABSTRACTTHREADEDJOB_H #define ABSTRACTTHREADEDJOB_H -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include class AbstractJobThread; class QTemporaryDir; class UserEvent; class KRarcObserver; class QTemporaryFile; class AbstractThreadedJob : public KIO::Job { friend class AbstractJobThread; Q_OBJECT protected: AbstractThreadedJob(); void addEventResponse(QList * obj); QList * getEventResponse(UserEvent * event); void sendEvent(UserEvent * event); virtual ~AbstractThreadedJob(); virtual bool event(QEvent *) Q_DECL_OVERRIDE; virtual void startAbstractJobThread(AbstractJobThread*); virtual bool doSuspend() Q_DECL_OVERRIDE { return false; } protected slots: void slotDownloadResult(KJob*); void slotProcessedAmount(KJob *, KJob::Unit, qulonglong); void slotTotalAmount(KJob *, KJob::Unit, qulonglong); void slotSpeed(KJob *, unsigned long); void slotDescription(KJob *job, const QString &title, const QPair &field1, const QPair &field2); public: QMutex _locker; QWaitCondition _waiter; QStack *> _stack; QString _title; qulonglong _maxProgressValue; qulonglong _currentProgress; QTime _time; bool _exiting; private: AbstractJobThread * _jobThread; }; class AbstractJobThread : public QThread { friend class AbstractThreadedJob; friend class AbstractJobObserver; Q_OBJECT public: AbstractJobThread(); virtual ~AbstractJobThread(); void abort(); KRarcObserver * observer(); protected slots: virtual void slotStart() = 0; protected: virtual void run() Q_DECL_OVERRIDE; void setJob(AbstractThreadedJob * job) { _job = job; } QList remoteUrls(const QUrl &baseUrl, const QStringList & files); QUrl downloadIfRemote(const QUrl &baseUrl, const QStringList & files); void calcSpaceLocal(const QUrl &baseUrl, const QStringList & files, KIO::filesize_t &totalSize, unsigned long &totalDirs, unsigned long &totalFiles); void sendError(int errorCode, QString message); void sendInfo(QString message, QString a1 = QString(), QString a2 = QString(), QString a3 = QString(), QString a4 = QString()); void sendReset(QString message, QString a1 = QString(""), QString a2 = QString(""), QString a3 = QString(""), QString a4 = QString("")); void sendSuccess(); void sendMessage(const QString &message); void sendMaxProgressValue(qulonglong value); void sendAddProgress(qulonglong value, const QString &progress = QString()); void setProgressTitle(const QString &title) { _progressTitle = title; } QString tempFileIfRemote(const QUrl &kurl, const QString &type); QString tempDirIfRemote(const QUrl &kurl); bool uploadTempFiles(); bool isExited() { return _exited; } void terminate(); QString getPassword(const QString &path); bool getArchiveInformation(QString &, QString &, QString &, QString &, const QUrl &); AbstractThreadedJob *_job; QEventLoop *_loop; QTemporaryDir *_downloadTempDir; KRarcObserver *_observer; QTemporaryFile *_tempFile; QString _tempFileName; QUrl _tempFileTarget; QTemporaryDir *_tempDir; QString _tempDirName; QUrl _tempDirTarget; bool _exited; QString _progressTitle; }; enum PossibleCommands { CMD_ERROR = 1, CMD_INFO = 2, CMD_RESET = 3, CMD_DOWNLOAD_FILES = 4, CMD_UPLOAD_FILES = 5, CMD_SUCCESS = 6, CMD_MAXPROGRESSVALUE = 7, CMD_ADD_PROGRESS = 8, CMD_GET_PASSWORD = 9, CMD_MESSAGE = 10 }; class UserEvent : public QEvent { public: UserEvent(int command, const QList &args) : QEvent(QEvent::User), _command(command), _args(args) {} inline int command() { return _command; } inline const QList & args() { return _args; } protected: int _command; QList _args; }; #endif // __ABSTRACTTHREADED_JOB_H__ diff --git a/krusader/VFS/ftp_vfs.cpp b/krusader/VFS/ftp_vfs.cpp index 3df9fbd6..57418c42 100644 --- a/krusader/VFS/ftp_vfs.cpp +++ b/krusader/VFS/ftp_vfs.cpp @@ -1,292 +1,293 @@ /*************************************************************************** ftp_vfs.cpp ------------------- copyright : (C) 2000 by Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "ftp_vfs.h" -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include #include #include #include #include #include #include #include "krpermhandler.h" #include "../krglobal.h" #include "../defaults.h" ftp_vfs::ftp_vfs(QObject* panel) : vfs(panel), busy(false) { // set the writable attribute isWritable = true; vfs_type = VFS_FTP; } ftp_vfs::~ftp_vfs() { busy = false; } void ftp_vfs::slotAddFiles(KIO::Job *, const KIO::UDSEntryList& entries) { int rwx = -1; QString prot = vfs_origin.scheme(); if (prot == "krarc" || prot == "tar" || prot == "zip") rwx = PERM_ALL; KIO::UDSEntryList::const_iterator it = entries.begin(); KIO::UDSEntryList::const_iterator end = entries.end(); // as long as u can find files - add them to the vfs for (; it != end; ++it) { KFileItem kfi(*it, vfs_origin, true, true); vfile *temp; // get file statistics QString name = kfi.text(); // ignore un-needed entries if (name.isEmpty() || name == "." || name == "..") continue; KIO::filesize_t size = kfi.size(); time_t mtime = kfi.time(KFileItem::ModificationTime).toTime_t(); bool symLink = kfi.isLink(); mode_t mode = kfi.mode() | kfi.permissions(); QString perm = KRpermHandler::mode2QString(mode); // set the mimetype QString mime = kfi.mimetype(); QString symDest = ""; if (symLink) { symDest = kfi.linkDest(); if (kfi.isDir()) perm[ 0 ] = 'd'; } // create a new virtual file object if (kfi.user().isEmpty()) temp = new vfile(name, size, perm, mtime, symLink, false, getuid(), getgid(), mime, symDest, mode, rwx); else { QString currentUser = vfs_origin.userName(); if (currentUser.contains("@")) /* remove the FTP proxy tags from the username */ currentUser.truncate(currentUser.indexOf('@')); if (currentUser.isEmpty()) { if (vfs_origin.host().isEmpty()) currentUser = KRpermHandler::uid2user(getuid()); else { currentUser = ""; // empty, but not QString() } } temp = new vfile(name, size, perm, mtime, symLink, false, kfi.user(), kfi.group(), currentUser, mime, symDest, mode, rwx, kfi.ACL().asString(), kfi.defaultACL().asString()); } if (!kfi.localPath().isEmpty()) { temp->vfile_setUrl(QUrl::fromLocalFile(kfi.localPath())); } else { temp->vfile_setUrl(kfi.url()); } temp->vfile_setIcon(kfi.iconName()); foundVfile(temp); } } void ftp_vfs::slotPermanentRedirection(KIO::Job*, const QUrl &, const QUrl& newUrl) { vfs_origin = newUrl.adjusted(QUrl::StripTrailingSlash); } void ftp_vfs::slotRedirection(KIO::Job *, const QUrl &url) { // update the origin vfs_origin = url.adjusted(QUrl::StripTrailingSlash); } void ftp_vfs::slotListResult(KJob *job) { if (job && job->error()) { // we failed to refresh listError = true; // display error message if (!quietMode) // job->uiDelegate()->showErrorMessage(); emit error(job->errorString()); } busy = false; } bool ftp_vfs::populateVfsList(const QUrl &origin, bool showHidden) { QString errorMsg; if (!origin.isValid()) errorMsg = i18n("Malformed URL:\n%1", origin.url()); if (!KProtocolManager::supportsListing(origin)) { if (origin.scheme() == "ftp" && KProtocolManager::supportsReading(origin)) errorMsg = i18n("Krusader does not support FTP access via HTTP.\nIf it is not the case, please check and change the proxy settings in the System Settings."); else errorMsg = i18n("Protocol not supported by Krusader:\n%1", origin.url()); } if (!errorMsg.isEmpty()) { printf("error\n"); if (!quietMode) emit error(errorMsg); return false; } busy = true; vfs_origin = origin.adjusted(QUrl::StripTrailingSlash); //QTimer::singleShot( 0,this,SLOT(startLister()) ); listError = false; // Open the directory marked by origin KIO::Job *job = KIO::listDir(vfs_origin, KIO::HideProgressInfo, showHidden); connect(job, SIGNAL(entries(KIO::Job*, const KIO::UDSEntryList&)), this, SLOT(slotAddFiles(KIO::Job*, const KIO::UDSEntryList&))); connect(job, SIGNAL(redirection(KIO::Job*, const QUrl&)), this, SLOT(slotRedirection(KIO::Job*, const QUrl&))); connect(job, SIGNAL(permanentRedirection(KIO::Job*, const QUrl&, const QUrl&)), this, SLOT(slotPermanentRedirection(KIO::Job*, const QUrl&, const QUrl&))); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotListResult(KJob*))); if(!parentWindow.isNull()) { KIO::JobUiDelegate *ui = static_cast(job->uiDelegate()); ui->setWindow(parentWindow); } if (!quietMode) { emit startJob(job); } while (busy && vfs_processEvents()); if (listError) return false; return true; } // copy a file to the vfs (physical) void ftp_vfs::vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir, PreserveMode /*pmode*/) { QUrl destUrl = vfs_origin; if (!dir.isEmpty()) { destUrl.setPath(QDir::cleanPath(destUrl.path() + '/' + dir)); if (destUrl.scheme() == "tar" || destUrl.scheme() == "zip" || destUrl.scheme() == "krarc") { if (QDir(destUrl.adjusted(QUrl::StripTrailingSlash).path()).exists()) destUrl.setScheme("file"); // if we get out from the archive change the protocol } } KIO::Job* job = 0; switch (mode) { case KIO::CopyJob::Copy: job = KIO::copy(fileUrls, destUrl); break; case KIO::CopyJob::Move: job = KIO::move(fileUrls, destUrl); break; case KIO::CopyJob::Link: job = KIO::link(fileUrls, destUrl); break; } connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); if (mode == KIO::CopyJob::Move) // notify the other panel connect(job, SIGNAL(result(KJob*)), toNotify, SLOT(vfs_refresh(KJob*))); } // remove a file from the vfs (physical) void ftp_vfs::vfs_delFiles(const QStringList &fileNames, bool /* reallyDelete */) { QList filesUrls = vfs_getFiles(fileNames); KIO::Job *job = KIO::del(filesUrls); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } QList ftp_vfs::vfs_getFiles(const QStringList &names) { QList urls; foreach (const QString &name, names) { urls.append(vfs_getFile(name)); } return urls; } // return a path to the file QUrl ftp_vfs::vfs_getFile(const QString& name) { vfile * vf = vfs_search(name); if (!vf) return QUrl(); // empty return vf->vfile_getUrl(); } void ftp_vfs::vfs_mkdir(const QString& name) { QUrl url = vfs_origin; url = url.adjusted(QUrl::StripTrailingSlash); url.setPath(url.path() + '/' + name); KIO::SimpleJob* job = KIO::mkdir(url); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } void ftp_vfs::vfs_rename(const QString& fileName, const QString& newName) { QUrl oldUrl = vfs_origin; oldUrl = oldUrl.adjusted(QUrl::StripTrailingSlash); oldUrl.setPath(oldUrl.path() + '/' + fileName); QUrl newUrl = vfs_origin; newUrl = newUrl.adjusted(QUrl::StripTrailingSlash); newUrl.setPath(newUrl.path() + '/' + newName); KIO::Job *job = KIO::moveAs(oldUrl, newUrl, KIO::HideProgressInfo); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } QString ftp_vfs::vfs_workingDir() { return vfs_origin.adjusted(QUrl::StripTrailingSlash).url(); } diff --git a/krusader/VFS/kiojobwrapper.cpp b/krusader/VFS/kiojobwrapper.cpp index 82cb4216..449860ba 100644 --- a/krusader/VFS/kiojobwrapper.cpp +++ b/krusader/VFS/kiojobwrapper.cpp @@ -1,295 +1,298 @@ /*************************************************************************** kiojobwrapper.cpp ------------------- copyright : (C) 2008+ by Csaba Karai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "kiojobwrapper.h" #include #include -#include -#include -#include +// QtCore +#include +// QtGui +#include +// QtWidgets +#include #include #include #include #include #include #include "virtualcopyjob.h" #include "packjob.h" class JobStartEvent : public QEvent { public: JobStartEvent(KIOJobWrapper * wrapperIn) : QEvent(QEvent::User), m_wrapper(wrapperIn) {} virtual ~JobStartEvent() {} KIOJobWrapper * wrapper() { return m_wrapper; } private: QPointer m_wrapper; }; KrJobStarter * KrJobStarter::m_self = 0; bool KrJobStarter::event(QEvent * e) { if (e->type() == QEvent::User) { JobStartEvent *je = (JobStartEvent *)e; je->wrapper()->createJob(); return true; } return QObject::event(e); } KIOJobWrapper::KIOJobWrapper(KIOJobWrapperType type, const QUrl &url) : QObject(0), m_autoErrorHandling(false), m_started(false), m_suspended(false) { moveToThread(QApplication::instance()->thread()); m_type = type; m_url = url; } KIOJobWrapper::KIOJobWrapper(KIOJobWrapperType type, const QUrl &url, void * userData) : QObject(0), m_autoErrorHandling(false), m_started(false), m_suspended(false) { moveToThread(QApplication::instance()->thread()); m_type = type; m_url = url; m_userData = userData; } KIOJobWrapper::KIOJobWrapper(KIOJobWrapperType type, const QUrl &url, const QList &list, int pmode, bool showp) : QObject(0), m_autoErrorHandling(false), m_started(false), m_suspended(false) { moveToThread(QApplication::instance()->thread()); m_type = type; m_url = url; m_urlList = list; m_pmode = pmode; m_showProgress = showp; } KIOJobWrapper::KIOJobWrapper(KIOJobWrapperType type, const QUrl &url, const QUrl &dest, const QStringList &names, bool showp, const QString &atype, const QMap &packProps) : QObject(0), m_urlList(), m_autoErrorHandling(false), m_started(false), m_suspended(false) { m_type = type; m_url = dest; m_archiveSourceBase = url; foreach(const QString &name , names) { QUrl srcUrl = url; srcUrl = srcUrl.adjusted(QUrl::StripTrailingSlash); srcUrl.setPath(srcUrl.path() + '/' + (name)); m_urlList << srcUrl; } m_archiveFileNames = names; m_showProgress = showp; m_archiveType = atype; m_archiveProperties = packProps; } KIOJobWrapper::~KIOJobWrapper() { } void KIOJobWrapper::createJob() { KIO::Job * job = 0; switch (m_type) { case Stat: job = KIO::stat(m_url); break; case DirectorySize: job = KIO::directorySize(m_url); break; case VirtualMove: case VirtualCopy: { VirtualCopyJob * vcj = (VirtualCopyJob *)m_userData; vcj->slotStart(); job = vcj; } break; case Copy: job = PreservingCopyJob::createCopyJob((PreserveMode)m_pmode, m_urlList, m_url, KIO::CopyJob::Copy, false, m_showProgress); break; case Move: job = PreservingCopyJob::createCopyJob((PreserveMode)m_pmode, m_urlList, m_url, KIO::CopyJob::Move, false, m_showProgress); break; case Pack: job = PackJob::createPacker(m_archiveSourceBase, m_url, m_archiveFileNames, m_archiveType, m_archiveProperties); break; case Unpack: job = UnpackJob::createUnpacker(m_archiveSourceBase, m_url, m_archiveFileNames); break; default: fprintf(stderr, "Internal error: invalid job!\n"); break; } if (job) { m_job = job; connect(job, SIGNAL(destroyed()), this, SLOT(deleteLater())); for (int i = 0; i != m_signals.count(); i++) if (!m_receivers[ i ].isNull()) connect(job, m_signals[ i ], m_receivers[ i ], m_methods[ i ]); if (m_autoErrorHandling && job->ui()) job->ui()->setAutoErrorHandlingEnabled(true); if (m_suspended) job->suspend(); } else deleteLater(); } KIOJobWrapper * KIOJobWrapper::stat(QUrl &url) { return new KIOJobWrapper(Stat, url); } KIOJobWrapper * KIOJobWrapper::directorySize(QUrl &url) { return new KIOJobWrapper(DirectorySize, url); } KIOJobWrapper * KIOJobWrapper::copy(int pmode, QList &list, QUrl &url, bool showProgress) { return new KIOJobWrapper(Copy, url, list, pmode, showProgress); } KIOJobWrapper * KIOJobWrapper::move(int pmode, QList &list, QUrl &url, bool showProgress) { return new KIOJobWrapper(Move, url, list, pmode, showProgress); } KIOJobWrapper * KIOJobWrapper::virtualCopy(const QStringList *names, vfs * vfs, QUrl& dest, const QUrl &baseURL, int pmode, bool showProgressInfo) { return new KIOJobWrapper(VirtualCopy, dest, new VirtualCopyJob(names, vfs, dest, baseURL, (PreserveMode)pmode, KIO::CopyJob::Copy, showProgressInfo, false)); } KIOJobWrapper * KIOJobWrapper::virtualMove(const QStringList *names, vfs * vfs, QUrl& dest, const QUrl &baseURL, int pmode, bool showProgressInfo) { return new KIOJobWrapper(VirtualMove, dest, new VirtualCopyJob(names, vfs, dest, baseURL, (PreserveMode)pmode, KIO::CopyJob::Move, showProgressInfo, false)); } KIOJobWrapper * KIOJobWrapper::pack(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps, bool showProgressInfo) { return new KIOJobWrapper(Pack, srcUrl, destUrl, fileNames, showProgressInfo, type, packProps); } KIOJobWrapper * KIOJobWrapper::unpack(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, bool showProgressInfo) { return new KIOJobWrapper(Unpack, srcUrl, destUrl, fileNames, showProgressInfo, QString(), QMap ()); } void KIOJobWrapper::start() { m_started = true; KrJobStarter *self = KrJobStarter::self(); QApplication::postEvent(self, new JobStartEvent(this)); } void KIOJobWrapper::connectTo(const char * signal, const QObject * receiver, const char * method) { m_signals.append(signal); m_receivers.append((QObject *)receiver); m_methods.append(method); } QString KIOJobWrapper::typeStr() { switch (m_type) { case Stat: return i18nc("Job type", "Status"); case DirectorySize: return i18nc("Job type", "Folder Size"); case Copy: case VirtualCopy: return i18nc("Job type", "Copy"); case Move: case VirtualMove: return i18nc("Job type", "Move"); case Pack: return i18nc("Job type", "Pack"); case Unpack: return i18nc("Job type", "Unpack"); default: return i18nc("Job type", "Unknown"); } } void KIOJobWrapper::suspend() { m_suspended = true; if (m_job) m_job->suspend(); } void KIOJobWrapper::resume() { m_suspended = false; if (m_job) m_job->resume(); } void KIOJobWrapper::abort() { if (m_job) m_job->kill(); } QString KIOJobWrapper::toolTip() { QString tip = "
"; tip += "

" + typeStr().toHtmlEscaped() + "

"; tip += ""; tip += ""; tip += ""; tip += "
" + i18n("Target").toHtmlEscaped() + "" + url().toDisplayString().toHtmlEscaped() + "
" + i18n("Source").toHtmlEscaped() + ""; foreach(const QUrl &urlIn, urlList()) { tip += "
  • " + urlIn.toDisplayString().toHtmlEscaped() + "
  • "; } tip += "
    "; tip += "
    "; return tip; } diff --git a/krusader/VFS/kiojobwrapper.h b/krusader/VFS/kiojobwrapper.h index 93340da0..254775ee 100644 --- a/krusader/VFS/kiojobwrapper.h +++ b/krusader/VFS/kiojobwrapper.h @@ -1,157 +1,158 @@ /*************************************************************************** kiojobwrapper.h ------------------- copyright : (C) 2008+ by Csaba Karai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KIOJOBWRAPPER_H #define KIOJOBWRAPPER_H -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include #include class QEvent; class vfs; enum KIOJobWrapperType { Stat = 1, DirectorySize = 2, Copy = 3, Move = 4, VirtualCopy = 5, VirtualMove = 6, Pack = 7, Unpack = 8 }; class KIOJobWrapper : public QObject { Q_OBJECT friend class KrJobStarter; friend class JobStartEvent; private: KIOJobWrapperType m_type; QUrl m_url; QList m_urlList; bool m_showProgress; int m_pmode; void * m_userData; bool m_autoErrorHandling; QMap m_archiveProperties; QStringList m_archiveFileNames; QString m_archiveType; QUrl m_archiveSourceBase; QList m_signals; QList > m_receivers; QList m_methods; QPointer m_job; bool m_started; bool m_suspended; KIOJobWrapper(KIOJobWrapperType type, const QUrl &url); KIOJobWrapper(KIOJobWrapperType type, const QUrl &url, void * userData); KIOJobWrapper(KIOJobWrapperType type, const QUrl &url, const QList &list, int pmode, bool showp); KIOJobWrapper(KIOJobWrapperType type, const QUrl &url, const QUrl &dest, const QStringList &names, bool showp, const QString &atype, const QMap &packProps); void createJob(); public: virtual ~KIOJobWrapper(); void start(); void suspend(); void resume(); void abort(); void connectTo(const char * signal, const QObject * receiver, const char * method); void setAutoErrorHandlingEnabled(bool err) { m_autoErrorHandling = err; } bool isStarted() { return m_started; } bool isSuspended() { return m_suspended; } KIO::Job * job() { return m_job; } KIOJobWrapperType type() { return m_type; } QString typeStr(); QUrl url() { return m_url; } QList urlList() { return m_urlList; } QString toolTip(); static KIOJobWrapper * stat(QUrl &url); static KIOJobWrapper * directorySize(QUrl &url); static KIOJobWrapper * copy(int pmode, QList &list, QUrl &url, bool showProgress); static KIOJobWrapper * move(int pmode, QList &list, QUrl &url, bool showProgress); static KIOJobWrapper * virtualCopy(const QStringList *names, vfs * vfs, QUrl& dest, const QUrl &baseURL, int pmode, bool showProgressInfo); static KIOJobWrapper * virtualMove(const QStringList *names, vfs * vfs, QUrl& dest, const QUrl &baseURL, int pmode, bool showProgressInfo); static KIOJobWrapper * pack(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps, bool showProgressInfo); static KIOJobWrapper * unpack(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, bool showProgressInfo); }; class KrJobStarter : public QObject { Q_OBJECT friend class KIOJobWrapper; public: KrJobStarter() { m_self = this; } protected: bool event(QEvent * e); static KrJobStarter * self() { return m_self; } static KrJobStarter * m_self; }; #endif // __KIO_JOB_WRAPPER__ diff --git a/krusader/VFS/krarchandler.cpp b/krusader/VFS/krarchandler.cpp index e7385fbc..425ba6d4 100644 --- a/krusader/VFS/krarchandler.cpp +++ b/krusader/VFS/krarchandler.cpp @@ -1,708 +1,710 @@ /*************************************************************************** krarchandler.cpp ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krarchandler.h" -#include -#include -#include -#include +// QtCore +#include +#include +#include +// QtWidgets +#include #include #include #include #include #include #include #include #include "../krglobal.h" #include "../defaults.h" #include "../krservices.h" #include "../Dialogs/krpleasewait.h" #if 0 class DefaultKRarcObserver : public KRarcObserver { public: DefaultKRarcObserver() {} virtual ~DefaultKRarcObserver() {} virtual void processEvents() Q_DECL_OVERRIDE { usleep(1000); qApp->processEvents(); } virtual void subJobStarted(const QString & jobTitle, int count) Q_DECL_OVERRIDE { krApp->startWaiting(jobTitle, count, true); } virtual void subJobStopped() Q_DECL_OVERRIDE { krApp->stopWait(); } virtual bool wasCancelled() Q_DECL_OVERRIDE { return krApp->wasWaitingCancelled(); } virtual void error(const QString & error) Q_DECL_OVERRIDE { KMessageBox::error(krApp, error, i18n("Error")); } virtual void detailedError(const QString & error, const QString & details) Q_DECL_OVERRIDE { KMessageBox::detailedError(krApp, error, details, i18n("Error")); } virtual void incrementProgress(int c) Q_DECL_OVERRIDE { krApp->plzWait->incProgress(c); } }; #endif static QStringList arcProtocols = QString("tar;bzip;bzip2;lzma;xz;gzip;krarc;zip").split(';'); KWallet::Wallet * KRarcHandler::wallet = 0; QStringList KRarcHandler::supportedPackers() { QStringList packers; // we will simply try to find the packers here.. if (KrServices::cmdExist("tar")) packers.append("tar"); if (KrServices::cmdExist("gzip")) packers.append("gzip"); if (KrServices::cmdExist("bzip2")) packers.append("bzip2"); if (KrServices::cmdExist("lzma")) packers.append("lzma"); if (KrServices::cmdExist("xz")) packers.append("xz"); if (KrServices::cmdExist("unzip")) packers.append("unzip"); if (KrServices::cmdExist("zip")) packers.append("zip"); if (KrServices::cmdExist("zip")) packers.append("cbz"); if (KrServices::cmdExist("lha")) packers.append("lha"); if (KrServices::cmdExist("cpio")) packers.append("cpio"); if (KrServices::cmdExist("unrar")) packers.append("unrar"); if (KrServices::cmdExist("rar")) packers.append("rar"); if (KrServices::cmdExist("rar")) packers.append("cbr"); if (KrServices::cmdExist("arj")) packers.append("arj"); if (KrServices::cmdExist("unarj")) packers.append("unarj"); if (KrServices::cmdExist("unace")) packers.append("unace"); if (KrServices::cmdExist("dpkg")) packers.append("dpkg"); if (KrServices::cmdExist("7z") || KrServices::cmdExist("7za")) packers.append("7z"); if (KrServices::cmdExist("rpm") && KrServices::cmdExist("rpm2cpio")) packers.append("rpm"); // qDebug() << "Supported Packers:" << endl; //QStringList::Iterator it; //for( it = packers.begin(); it != packers.end(); ++it ) // qDebug() << *it << endl; return packers; } bool KRarcHandler::arcSupported(QString type) { // lst will contain the supported unpacker list... KConfigGroup group(krConfig, "Archives"); QStringList lst = group.readEntry("Supported Packers", QStringList()); // Let's notice that in some cases the QString `type` that arrives here // represents a mimetype, and in some other cases it represents // a short identifier. // If `type` is not a short identifier then it's supposed that `type` is a mime type if (type.length() > maxLenType) { type = getShortTypeFromMime(type); } if ((type == "zip" || type == "/zip") && lst.contains("unzip")) return true; else if (type == "tar" && lst.contains("tar")) return true; else if (type == "tbz" && lst.contains("tar")) return true; else if (type == "tgz" && lst.contains("tar")) return true; else if (type == "tlz" && lst.contains("tar")) return true; else if (type == "txz" && lst.contains("tar")) return true; else if (type == "tarz" && lst.contains("tar")) return true; else if (type == "gzip" && lst.contains("gzip")) return true; else if (type == "bzip2" && lst.contains("bzip2")) return true; else if (type == "lzma" && lst.contains("lzma")) return true; else if (type == "xz" && lst.contains("xz")) return true; else if (type == "lha" && lst.contains("lha")) return true; else if (type == "ace" && lst.contains("unace")) return true; else if (type == "rpm" && lst.contains("cpio")) return true; else if (type == "cpio" && lst.contains("cpio")) return true; else if (type == "rar" && (lst.contains("unrar") || lst.contains("rar"))) return true; else if (type == "arj" && (lst.contains("unarj") || lst.contains("arj"))) return true; else if (type == "deb" && (lst.contains("dpkg") && lst.contains("tar"))) return true; else if (type == "7z" && lst.contains("7z")) return true; // not supported return false; } long KRarcHandler::arcFileCount(QString archive, QString type, QString password, KRarcObserver *observer) { int divideWith = 1; // first check if supported if (!arcSupported(type)) return 0; // bzip2, gzip, etc. archives contain only one file if (type == "bzip2" || type == "gzip" || type == "lzma" || type == "xz") return 1L; // set the right lister to do the job QStringList lister; if (type == "zip") lister << KrServices::fullPathName("unzip") << "-ZTs"; else if (type == "tar") lister << KrServices::fullPathName("tar") << "-tvf"; else if (type == "tgz") lister << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tarz") lister << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tbz") lister << KrServices::fullPathName("tar") << "-tjvf"; else if (type == "tlz") lister << KrServices::fullPathName("tar") << "--lzma" << "-tvf"; else if (type == "txz") lister << KrServices::fullPathName("tar") << "--xz" << "-tvf"; else if (type == "lha") lister << KrServices::fullPathName("lha") << "l"; else if (type == "rar") lister << KrServices::fullPathName(KrServices::cmdExist("rar") ? "rar" : "unrar") << "l" << "-v"; else if (type == "ace") lister << KrServices::fullPathName("unace") << "l"; else if (type == "arj") { if (KrServices::cmdExist("arj")) lister << KrServices::fullPathName("arj") << "v" << "-y" << "-v", divideWith = 4; else lister << KrServices::fullPathName("unarj") << "l"; } else if (type == "rpm") lister << KrServices::fullPathName("rpm") << "--dump" << "-lpq"; else if (type == "deb") lister << KrServices::fullPathName("dpkg") << "-c"; else if (type == "7z") lister << KrServices::fullPathName("7z") << "-y" << "l"; else return 0L; if (!password.isNull()) { if (type == "arj") lister << QString("-g%1").arg(password); if (type == "ace" || type == "rar" || type == "7z") lister << QString("-p%1").arg(password); } // tell the user to wait observer->subJobStarted(i18n("Counting files in archive"), 0); // count the number of files in the archive long count = 1; KProcess list; list << lister << archive; if (type == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! list.setStandardInputFile("/dev/ptmx"); list.setOutputChannelMode(KProcess::SeparateChannels); // without this output redirection has no effect list.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (list.waitForStarted()) while (list.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) list.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); if (list.exitStatus() != QProcess::NormalExit || !checkStatus(type, list.exitCode())) { observer->detailedError(i18n("Failed to list the content of the archive (%1).", archive), QString::fromLocal8Bit(list.readAllStandardError())); return 0; } count = list.readAllStandardOutput().count('\n'); //make sure you call stopWait after this function return... // observer->subJobStopped(); return count / divideWith; } bool KRarcHandler::unpack(QString archive, QString type, QString password, QString dest, KRarcObserver *observer) { KConfigGroup group(krConfig, "Archives"); if (group.readEntry("Test Before Unpack", _TestBeforeUnpack)) { // test first - or be sorry later... if (type != "rpm" && type != "deb" && !test(archive, type, password, observer, 0)) { observer->error(i18n("Failed to unpack %1.", archive)); return false; } } // count the files in the archive long count = arcFileCount(archive, type, password, observer); if (count == 0) return false; // not supported if (count == 1) count = 0; // choose the right packer for the job QString cpioName; QStringList packer; // set the right packer to do the job if (type == "zip") packer << KrServices::fullPathName("unzip") << "-o" ; else if (type == "tar") packer << KrServices::fullPathName("tar") << "-xvf"; else if (type == "tgz") packer << KrServices::fullPathName("tar") << "-xvzf"; else if (type == "tarz") packer << KrServices::fullPathName("tar") << "-xvzf"; else if (type == "tbz") packer << KrServices::fullPathName("tar") << "-xjvf"; else if (type == "tlz") packer << KrServices::fullPathName("tar") << "--lzma" << "-xvf"; else if (type == "txz") packer << KrServices::fullPathName("tar") << "--xz" << "-xvf"; else if (type == "gzip") packer << KrServices::fullPathName("gzip") << "-cd"; else if (type == "bzip2") packer << KrServices::fullPathName("bzip2") << "-cdk"; else if (type == "lzma") packer << KrServices::fullPathName("lzma") << "-cdk"; else if (type == "xz") packer << KrServices::fullPathName("xz") << "-cdk"; else if (type == "lha") packer << KrServices::fullPathName("lha") << "xf"; else if (type == "rar") packer << KrServices::fullPathName(KrServices::cmdExist("rar") ? "rar" : "unrar") << "-y" << "x"; else if (type == "ace") packer << KrServices::fullPathName("unace") << "x"; else if (type == "arj") { if (KrServices::cmdExist("arj")) packer << KrServices::fullPathName("arj") << "-y" << "-v" << "x"; else packer << KrServices::fullPathName("unarj") << "x"; } else if (type == "7z") packer << KrServices::fullPathName("7z") << "-y" << "x"; else if (type == "rpm") { // TODO use QTemporaryFile (setAutoRemove(false) when asynchrone) cpioName = QDir::tempPath() + QStringLiteral("/contents.cpio"); KrLinecountingProcess cpio; cpio << KrServices::fullPathName("rpm2cpio") << archive; cpio.setStandardOutputFile(cpioName); // TODO maybe no tmpfile but a pipe (setStandardOutputProcess(packer)) cpio.start(); if (!cpio.waitForFinished() || cpio.exitStatus() != QProcess::NormalExit || !checkStatus("cpio", cpio.exitCode())) { observer->detailedError(i18n("Failed to convert rpm (%1) to cpio.", archive), cpio.getErrorMsg()); return 0; } archive = cpioName; packer << KrServices::fullPathName("cpio") << "--force-local" << "--no-absolute-filenames" << "-iuvdF"; } else if (type == "deb") { // TODO use QTemporaryFile (setAutoRemove(false) when asynchrone) cpioName = QDir::tempPath() + QStringLiteral("/contents.tar"); KrLinecountingProcess dpkg; dpkg << KrServices::fullPathName("dpkg") << "--fsys-tarfile" << archive; dpkg.setStandardOutputFile(cpioName); // TODO maybe no tmpfile but a pipe (setStandardOutputProcess(packer)) dpkg.start(); if (!dpkg.waitForFinished() || dpkg.exitStatus() != QProcess::NormalExit || !checkStatus("deb", dpkg.exitCode())) { observer->detailedError(i18n("Failed to convert deb (%1) to tar.", archive), dpkg.getErrorMsg()); return 0; } archive = cpioName; packer << KrServices::fullPathName("tar") << "xvf"; } else return false; if (!password.isNull()) { if (type == "zip") packer << "-P" << password; if (type == "arj") packer << QString("-g%1").arg(password); if (type == "ace" || type == "rar" || type == "7z") packer << QString("-p%1").arg(password); } // unpack the files KrLinecountingProcess proc; proc << packer << archive; if (type == "bzip2" || type == "gzip" || type == "lzma" || type == "xz") { QString arcname = archive.mid(archive.lastIndexOf("/") + 1); if (arcname.contains(".")) arcname = arcname.left(arcname.lastIndexOf(".")); proc.setStandardOutputFile(dest + '/' + arcname); } if (type == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); proc.setWorkingDirectory(dest); // tell the user to wait observer->subJobStarted(i18n("Unpacking File(s)"), count); if (count != 0) { connect(&proc, SIGNAL(newOutputLines(int)), observer, SLOT(incrementProgress(int))); if (type == "rpm") connect(&proc, SIGNAL(newErrorLines(int)), observer, SLOT(incrementProgress(int))); } // start the unpacking process proc.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (proc.waitForStarted()) while (proc.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) proc.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); if (!cpioName.isEmpty()) QFile(cpioName).remove(); /* remove the cpio file */ // check the return value if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(type, proc.exitCode())) { observer->detailedError(i18n("Failed to unpack %1.", archive), observer->wasCancelled() ? i18n("User cancelled.") : proc.getErrorMsg()); return false; } return true; // SUCCESS } bool KRarcHandler::test(QString archive, QString type, QString password, KRarcObserver *observer, long count) { // choose the right packer for the job QStringList packer; // set the right packer to do the job if (type == "zip") packer << KrServices::fullPathName("unzip") << "-t"; else if (type == "tar") packer << KrServices::fullPathName("tar") << "-tvf"; else if (type == "tgz") packer << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tarz") packer << KrServices::fullPathName("tar") << "-tvzf"; else if (type == "tbz") packer << KrServices::fullPathName("tar") << "-tjvf"; else if (type == "tlz") packer << KrServices::fullPathName("tar") << "--lzma" << "-tvf"; else if (type == "txz") packer << KrServices::fullPathName("tar") << "--xz" << "-tvf"; else if (type == "gzip") packer << KrServices::fullPathName("gzip") << "-tv"; else if (type == "bzip2") packer << KrServices::fullPathName("bzip2") << "-tv"; else if (type == "lzma") packer << KrServices::fullPathName("lzma") << "-tv"; else if (type == "xz") packer << KrServices::fullPathName("xz") << "-tv"; else if (type == "rar") packer << KrServices::fullPathName(KrServices::cmdExist("rar") ? "rar" : "unrar") << "t"; else if (type == "ace") packer << KrServices::fullPathName("unace") << "t"; else if (type == "lha") packer << KrServices::fullPathName("lha") << "t"; else if (type == "arj") packer << KrServices::fullPathName(KrServices::cmdExist("arj") ? "arj" : "unarj") << "t"; else if (type == "cpio") packer << KrServices::fullPathName("cpio") << "--only-verify-crc" << "-tvF"; else if (type == "7z") packer << KrServices::fullPathName("7z") << "-y" << "t"; else return false; if (!password.isNull()) { if (type == "zip") packer << "-P" << password; if (type == "arj") packer << QString("-g%1").arg(password); if (type == "ace" || type == "rar" || type == "7z") packer << QString("-p%1").arg(password); } // unpack the files KrLinecountingProcess proc; proc << packer << archive; if (type == "ace" && QFile("/dev/ptmx").exists()) // Don't remove, unace crashes if missing!!! proc.setStandardInputFile("/dev/ptmx"); // tell the user to wait observer->subJobStarted(i18n("Testing Archive"), count); if (count != 0) connect(&proc, SIGNAL(newOutputLines(int)), observer, SLOT(incrementProgress(int))); // start the unpacking process proc.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (proc.waitForStarted()) while (proc.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) proc.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); // check the return value if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(type, proc.exitCode())) return false; return true; // SUCCESS } bool KRarcHandler::pack(QStringList fileNames, QString type, QString dest, long count, QMap extraProps, KRarcObserver *observer) { // set the right packer to do the job QStringList packer; if (type == "zip") { packer << KrServices::fullPathName("zip") << "-ry"; } else if (type == "cbz") { packer << KrServices::fullPathName("zip") << "-ry"; type = "zip"; } else if (type == "tar") { packer << KrServices::fullPathName("tar") << "-cvf"; } else if (type == "tar.gz") { packer << KrServices::fullPathName("tar") << "-cvzf"; type = "tgz"; } else if (type == "tar.bz2") { packer << KrServices::fullPathName("tar") << "-cvjf"; type = "tbz"; } else if (type == "tar.lzma") { packer << KrServices::fullPathName("tar") << "--lzma" << "-cvf"; type = "tlz"; } else if (type == "tar.xz") { packer << KrServices::fullPathName("tar") << "--xz" << "-cvf"; type = "txz"; } else if (type == "rar") { packer << KrServices::fullPathName("rar") << "-r" << "a"; } else if (type == "cbr") { packer << KrServices::fullPathName("rar") << "-r" << "a"; type = "rar"; } else if (type == "lha") { packer << KrServices::fullPathName("lha") << "a"; } else if (type == "arj") { packer << KrServices::fullPathName("arj") << "-r" << "-y" << "a"; } else if (type == "7z") { packer << KrServices::fullPathName("7z") << "-y" << "a"; } else return false; QString password; if (extraProps.count("Password") > 0) { password = extraProps[ "Password" ]; if (!password.isNull()) { if (type == "zip") packer << "-P" << password; else if (type == "arj") packer << QString("-g%1").arg(password); else if (type == "ace" || type == "7z") packer << QString("-p%1").arg(password); else if (type == "rar") { if (extraProps.count("EncryptHeaders") > 0) packer << QString("-hp%1").arg(password); else packer << QString("-p%1").arg(password); } else password.clear(); } } if (extraProps.count("VolumeSize") > 0) { QString sizeStr = extraProps[ "VolumeSize" ]; KIO::filesize_t size = sizeStr.toLongLong(); if (size >= 10000) { if (type == "arj" || type == "rar") packer << QString("-v%1b").arg(sizeStr); } } if (extraProps.count("CompressionLevel") > 0) { int level = extraProps[ "CompressionLevel" ].toInt() - 1; if (level < 0) level = 0; if (level > 8) level = 8; if (type == "rar") { static const int rarLevels[] = { 0, 1, 2, 2, 3, 3, 4, 4, 5 }; packer << QString("-m%1").arg(rarLevels[ level ]); } else if (type == "arj") { static const int arjLevels[] = { 0, 4, 4, 3, 3, 2, 2, 1, 1 }; packer << QString("-m%1").arg(arjLevels[ level ]); } else if (type == "zip") { static const int zipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 }; packer << QString("-%1").arg(zipLevels[ level ]); } else if (type == "7z") { static const int sevenZipLevels[] = { 0, 1, 2, 4, 5, 6, 7, 8, 9 }; packer << QString("-mx%1").arg(sevenZipLevels[ level ]); } } if (extraProps.count("CommandLineSwitches") > 0) packer << QString("%1").arg(extraProps[ "CommandLineSwitches" ]); // prepare to pack KrLinecountingProcess proc; proc << packer << dest; for (QStringList::Iterator file = fileNames.begin(); file != fileNames.end(); ++file) { proc << *file; } // tell the user to wait observer->subJobStarted(i18n("Packing File(s)"), count); if (count != 0) connect(&proc, SIGNAL(newOutputLines(int)), observer, SLOT(incrementProgress(int))); // start the packing process proc.start(); // TODO make use of asynchronous process starting. waitForStarted(int msec = 30000) is blocking // it would be better to connect to started(), error() and finished() if (proc.waitForStarted()) while (proc.state() == QProcess::Running) { observer->processEvents(); if (observer->wasCancelled()) proc.kill(); } ; // busy wait - need to find something better... observer->subJobStopped(); // check the return value if (proc.exitStatus() != QProcess::NormalExit || !checkStatus(type, proc.exitCode())) { observer->detailedError(i18n("Failed to pack %1.", dest), observer->wasCancelled() ? i18n("User cancelled.") : proc.getErrorMsg()); return false; } KConfigGroup group(krConfig, "Archives"); if (group.readEntry("Test Archives", _TestArchives) && !test(dest, type, password, observer, count)) { observer->error(i18n("Failed to pack %1.", dest)); return false; } return true; // SUCCESS } bool KRarcHandler::openWallet() { if (!wallet) { // find a suitable parent window QWidget *actWindow = QApplication::activeWindow(); if (!actWindow) actWindow = (QWidget*) QApplication::desktop(); wallet = KWallet::Wallet::openWallet(KWallet::Wallet::NetworkWallet(), actWindow->effectiveWinId()); } return (wallet != 0); } QString KRarcHandler::getPassword(QString path) { QString password; QString key = "krarc-" + path; if (!KWallet::Wallet::keyDoesNotExist(KWallet::Wallet::NetworkWallet(), KWallet::Wallet::PasswordFolder(), key)) { if (!KWallet::Wallet::isOpen(KWallet::Wallet::NetworkWallet()) && wallet != 0) { delete wallet; wallet = 0; } if (openWallet() && wallet->hasFolder(KWallet::Wallet::PasswordFolder())) { wallet->setFolder(KWallet::Wallet::PasswordFolder()); QMap map; if (wallet->readMap(key, map) == 0) { QMap::const_iterator it = map.constFind("password"); if (it != map.constEnd()) password = it.value(); } } } bool keep = true; QString user = "archive"; QPointer passDlg = new KPasswordDialog(0L, KPasswordDialog::ShowKeepPassword); passDlg->setPrompt(i18n("This archive is encrypted, please supply the password:") ), passDlg->setUsername(user); passDlg->setPassword(password); if (passDlg->exec() == KPasswordDialog::Accepted) { password = passDlg->password(); if (keep) { if (!KWallet::Wallet::isOpen(KWallet::Wallet::NetworkWallet()) && wallet != 0) { delete wallet; wallet = 0; } if (openWallet()) { bool ok = true; if (!wallet->hasFolder(KWallet::Wallet::PasswordFolder())) ok = wallet->createFolder(KWallet::Wallet::PasswordFolder()); if (ok) { wallet->setFolder(KWallet::Wallet::PasswordFolder()); QMap map; map.insert("login", "archive"); map.insert("password", password); wallet->writeMap(key, map); } } } delete passDlg; return password; } delete passDlg; return ""; } bool KRarcHandler::isArchive(const QUrl &url) { QString protocol = url.scheme(); if (arcProtocols.indexOf(protocol) != -1) return true; else return false; } QString KRarcHandler::getType(bool &encrypted, QString fileName, QString mime, bool checkEncrypted, bool fast) { QString result = detectArchive(encrypted, fileName, checkEncrypted, fast); if (result.isNull()) { // Then the type is based on the mime type return getShortTypeFromMime(mime); } return result; } bool KRarcHandler::checkStatus(QString type, int exitCode) { // if this code is changed, the code of kio_krarcProtocol::checkStatus() must be reviewed if (type == "zip" || type == "rar" || type == "7z") return exitCode == 0 || exitCode == 1; else if (type == "ace" || type == "bzip2" || type == "lha" || type == "rpm" || type == "cpio" || type == "tar" || type == "tarz" || type == "tbz" || type == "tgz" || type == "arj" || type == "deb" || type == "tlz" || type == "txz") return exitCode == 0; else if (type == "gzip" || type == "lzma" || type == "xz") return exitCode == 0 || exitCode == 2; else return exitCode == 0; } void KRarcHandler::checkIf7zIsEncrypted(bool &encrypted, QString fileName) { Kr7zEncryptionChecker proc; // TODO incorporate all this in Kr7zEncryptionChecker proc << KrServices::fullPathName("7z") << "-y" << "t"; proc << fileName; proc.start(); proc.waitForFinished(); encrypted = proc.isEncrypted(); } diff --git a/krusader/VFS/krarchandler.h b/krusader/VFS/krarchandler.h index 5bbcca82..1996cad2 100644 --- a/krusader/VFS/krarchandler.h +++ b/krusader/VFS/krarchandler.h @@ -1,97 +1,98 @@ /*************************************************************************** krarchandler.h ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description: this class will supply static archive handling functions. *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KRARCHANDLER_H #define KRARCHANDLER_H -#include -#include -#include +// QtCore +#include +#include +#include #include #include "../../krArc/krarcbasemanager.h" #include "../../krArc/krlinecountingprocess.h" #include "kr7zencryptionchecker.h" namespace KWallet { class Wallet; } class KRarcObserver : public QObject { Q_OBJECT public: virtual ~KRarcObserver() {} virtual void processEvents() = 0; virtual void subJobStarted(const QString & jobTitle, int count) = 0; virtual void subJobStopped() = 0; virtual bool wasCancelled() = 0; virtual void error(const QString & error) = 0; virtual void detailedError(const QString & error, const QString & details) = 0; public slots: virtual void incrementProgress(int) = 0; }; class KRarcHandler: public QObject, public KrArcBaseManager { Q_OBJECT public: // return the number of files in the archive static long arcFileCount(QString archive, QString type, QString password, KRarcObserver *observer); // unpack an archive to destination directory static bool unpack(QString archive, QString type, QString password, QString dest, KRarcObserver *observer ); // pack an archive to destination directory static bool pack(QStringList fileNames, QString type, QString dest, long count, QMap extraProps, KRarcObserver *observer ); // test an archive static bool test(QString archive, QString type, QString password, KRarcObserver *observer, long count = 0L ); // returns `true` if the right unpacker exist in the system static bool arcSupported(QString type); // return the list of supported packers static QStringList supportedPackers(); // returns `true` if the url is an archive (ie: tar:/home/test/file.tar.bz2) static bool isArchive(const QUrl &url); // used to determine the type of the archive QString getType(bool &encrypted, QString fileName, QString mime, bool checkEncrypted = true, bool fast = false); // queries the password from the user static QString getPassword(QString path); // detects the archive type void checkIf7zIsEncrypted(bool &, QString); private: // checks if the returned status is correct static bool checkStatus(QString type, int exitCode); static bool openWallet(); static KWallet::Wallet * wallet; }; #endif diff --git a/krusader/VFS/krpermhandler.cpp b/krusader/VFS/krpermhandler.cpp index 16beb81c..d359870a 100644 --- a/krusader/VFS/krpermhandler.cpp +++ b/krusader/VFS/krpermhandler.cpp @@ -1,345 +1,346 @@ /*************************************************************************** krpermhandler.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krpermhandler.h" -#include -#include -#include +// QtCore +#include +#include +#include #include QHash *KRpermHandler::passwdCache = 0L; QHash *KRpermHandler::groupCache = 0L; QHash *KRpermHandler::currentGroups = 0L; QHash *KRpermHandler::uidCache = 0L; QHash *KRpermHandler::gidCache = 0L; char KRpermHandler::writeable(QString perm, gid_t gid, uid_t uid, int rwx) { if (rwx != -1) return (rwx & W_OK) ? ALLOWED_PERM : NO_PERM; // root override if (getuid() == 0) return ALLOWED_PERM; // first check other permissions. if (perm[ 8 ] != '-') return ALLOWED_PERM; // now check group permission if ((perm[ 5 ] != '-') && (currentGroups->find(gid) != currentGroups->end())) return ALLOWED_PERM; // the last chance - user permissions if ((perm[ 2 ] != '-') && (uid == getuid())) return ALLOWED_PERM; // sorry ! return NO_PERM; } char KRpermHandler::readable(QString perm, gid_t gid, uid_t uid, int rwx) { if (rwx != -1) return (rwx & R_OK) ? ALLOWED_PERM : NO_PERM; // root override if (getuid() == 0) return ALLOWED_PERM; // first check other permissions. if (perm[ 7 ] != '-') return ALLOWED_PERM; // now check group permission if ((perm[ 4 ] != '-') && (currentGroups->find(gid) != currentGroups->end())) return ALLOWED_PERM; // the last chance - user permissions if ((perm[ 1 ] != '-') && (uid == getuid())) return ALLOWED_PERM; // sorry ! return NO_PERM; } char KRpermHandler::executable(QString perm, gid_t gid, uid_t uid, int rwx) { if (rwx != -1) return (rwx & X_OK) ? ALLOWED_PERM : NO_PERM; // first check other permissions. if (perm[ 9 ] != '-') return ALLOWED_PERM; // now check group permission if ((perm[ 6 ] != '-') && (currentGroups->find(gid) != currentGroups->end())) return ALLOWED_PERM; // the last chance - user permissions if ((perm[ 3 ] != '-') && (uid == getuid())) return ALLOWED_PERM; // sorry ! return NO_PERM; } bool KRpermHandler::fileWriteable(QString localFile) { QT_STATBUF stat_p; if (QT_STAT(localFile.toLocal8Bit(), &stat_p) == -1) return false; mode_t m = stat_p.st_mode; QString perm = mode2QString(m); return writeable(perm, stat_p.st_gid, stat_p.st_uid); } bool KRpermHandler::fileReadable(QString localFile) { QT_STATBUF stat_p; if (QT_STAT(localFile.toLocal8Bit(), &stat_p) == -1) return false; mode_t m = stat_p.st_mode; QString perm = mode2QString(m); return readable(perm, stat_p.st_gid, stat_p.st_uid); } bool KRpermHandler::fileExecutable(QString localFile) { QT_STATBUF stat_p; if (QT_STAT(localFile.toLocal8Bit(), &stat_p) == -1) return false; mode_t m = stat_p.st_mode; QString perm = mode2QString(m); return executable(perm, stat_p.st_gid, stat_p.st_uid); } QString KRpermHandler::mode2QString(mode_t m) { char perm[ 11 ]; for (int i = 0; i != 10; i++) perm[ i ] = '-'; perm[ 10 ] = 0; if (S_ISLNK(m)) perm[ 0 ] = 'l'; // check for symLink if (S_ISDIR(m)) perm[ 0 ] = 'd'; // check for directory //ReadUser = 0400, WriteUser = 0200, ExeUser = 0100, Suid = 04000 if (m & 0400) perm[ 1 ] = 'r'; if (m & 0200) perm[ 2 ] = 'w'; if (m & 0100) perm[ 3 ] = 'x'; if (m & 04000) perm[ 3 ] = 's'; //ReadGroup = 0040, WriteGroup = 0020, ExeGroup = 0010, Gid = 02000 if (m & 0040) perm[ 4 ] = 'r'; if (m & 0020) perm[ 5 ] = 'w'; if (m & 0010) perm[ 6 ] = 'x'; if (m & 02000) perm[ 6 ] = 's'; //ReadOther = 0004, WriteOther = 0002, ExeOther = 0001, Sticky = 01000 if (m & 0004) perm[ 7 ] = 'r'; if (m & 0002) perm[ 8 ] = 'w'; if (m & 0001) perm[ 9 ] = 'x'; if (m & 01000) perm[ 9 ] = 't'; return QString(perm); } void KRpermHandler::init() { // set the umask to 022 //umask( 022 ); // 50 groups should be enough gid_t groupList[ 50 ]; int groupNo = getgroups(50, groupList); // init the groups and user caches passwdCache = new QHash(); groupCache = new QHash(); currentGroups = new QHash(); uidCache = new QHash(); gidCache = new QHash(); // In kdewin32 implementation as of 4.1.2, getpwent always returns the same struct #ifndef Q_WS_WIN // fill the UID cache struct passwd *pass; while ((pass = getpwent()) != 0L) { passwdCache->insert(pass->pw_name, pass->pw_uid); (*uidCache)[ pass->pw_uid ] = QString(pass->pw_name); } delete pass; endpwent(); // fill the GID cache struct group *gr; while ((gr = getgrent()) != 0L) { groupCache->insert(gr->gr_name, gr->gr_gid); (*gidCache)[ gr->gr_gid ] = QString(gr->gr_name); } delete gr; endgrent(); #endif // fill the groups for the current user for (int i = 0; i < groupNo; ++i) { (*currentGroups)[ groupList[ i ] ] = char(1); } // just to be sure add the effective gid... (*currentGroups)[ getegid()] = char(1); } char KRpermHandler::ftpWriteable(QString fileOwner, QString userName, QString perm) { // first check other permissions. if (perm[ 8 ] != '-') return ALLOWED_PERM; // can't check group permission ! // so check the user permissions if ((perm[ 2 ] != '-') && (fileOwner == userName)) return ALLOWED_PERM; if ((perm[ 2 ] != '-') && (userName.isEmpty())) return UNKNOWN_PERM; if (perm[ 5 ] != '-') return UNKNOWN_PERM; return NO_PERM; } char KRpermHandler::ftpReadable(QString fileOwner, QString userName, QString perm) { // first check other permissions. if (perm[ 7 ] != '-') return ALLOWED_PERM; // can't check group permission ! // so check the user permissions if ((perm[ 1 ] != '-') && (fileOwner == userName)) return ALLOWED_PERM; if ((perm[ 1 ] != '-') && (userName.isEmpty())) return UNKNOWN_PERM; if (perm[ 4 ] != '-') return UNKNOWN_PERM; return NO_PERM; } char KRpermHandler::ftpExecutable(QString fileOwner, QString userName, QString perm) { // first check other permissions. if (perm[ 9 ] != '-') return ALLOWED_PERM; // can't check group permission ! // so check the user permissions if ((perm[ 3 ] != '-') && (fileOwner == userName)) return ALLOWED_PERM; if ((perm[ 3 ] != '-') && (userName.isEmpty())) return UNKNOWN_PERM; if (perm[ 6 ] != '-') return UNKNOWN_PERM; return NO_PERM; } bool KRpermHandler::dirExist(QString path) { QT_DIR * dir = QT_OPENDIR(path.toLocal8Bit()); if (!dir) return false; QT_CLOSEDIR(dir); // bug fix Karai Csaba (ckarai) return true; } bool KRpermHandler::fileExist(QString fullPath) { if (fullPath.right(1) == "/") fullPath = fullPath.left(fullPath.length() - 1) ; if (fullPath.left(1) != "/") return fileExist("/", fullPath); return fileExist(fullPath.left(fullPath.lastIndexOf("/")) , fullPath.mid(fullPath.lastIndexOf("/") + 1)); } bool KRpermHandler::fileExist(QString path, QString name) { if (QDir(path).exists(name)) return true; QT_DIR* dir = QT_OPENDIR(path.toLocal8Bit()); if (!dir) return false; QT_DIRENT* dirEnt; while ((dirEnt = QT_READDIR(dir))) { if (dirEnt->d_name == name) { QT_CLOSEDIR(dir); return true; } } QT_CLOSEDIR(dir); return false; } QString KRpermHandler::parseSize(KIO::filesize_t val) { return QLocale().toString(val); #if 0 QString temp; temp.sprintf("%llu", val); if (temp.length() <= 3) return temp; unsigned int i = temp.length() % 3; if (i == 0) i = 3; QString size = temp.left(i) + ","; while (i + 3 < temp.length()) { size = size + temp.mid(i, 3) + ","; i += 3; } size = size + temp.right(3); return size; #endif } QString KRpermHandler::date2qstring(QString date) { QString temp; int year; year = date[ 6 ].digitValue() * 10 + date[ 7 ].digitValue(); year > 80 ? year += 1900 : year += 2000; temp.sprintf("%d", year); temp = temp + date[ 3 ] + date[ 4 ] + date[ 0 ] + date[ 1 ] + date[ 9 ] + date[ 10 ] + date[ 12 ] + date[ 13 ]; return temp; } time_t KRpermHandler::QString2time(QString date) { struct tm t; t.tm_sec = 0; t.tm_min = (QString(date[ 12 ]) + QString(date[ 13 ])).toInt(); t.tm_hour = (QString(date[ 9 ]) + QString(date[ 10 ])).toInt(); t.tm_mday = (QString(date[ 0 ]) + QString(date[ 1 ])).toInt(); t.tm_mon = (QString(date[ 3 ]) + QString(date[ 4 ])).toInt() - 1; t.tm_year = (QString(date[ 6 ]) + QString(date[ 7 ])).toInt(); if (t.tm_year < 70) t.tm_year += 100; t.tm_isdst = -1; // daylight saving time information isn't available return mktime(&t); } gid_t KRpermHandler::group2gid(QString group) { if (groupCache->find(group) == groupCache->end()) return getgid(); return (*groupCache)[ group ]; } uid_t KRpermHandler::user2uid(QString user) { if (passwdCache->find(user) == passwdCache->end()) return getuid(); return (*passwdCache)[ user ]; } QString KRpermHandler::gid2group(gid_t groupId) { if (gidCache->find(groupId) == gidCache->end()) return QString("???"); return (*gidCache)[ groupId ]; } QString KRpermHandler::uid2user(uid_t userId) { if (uidCache->find(userId) == uidCache->end()) return QString("???"); return (*uidCache)[ userId ]; } diff --git a/krusader/VFS/krpermhandler.h b/krusader/VFS/krpermhandler.h index db5dd6df..d1ab795e 100644 --- a/krusader/VFS/krpermhandler.h +++ b/krusader/VFS/krpermhandler.h @@ -1,89 +1,90 @@ /*************************************************************************** krpermhandler.h ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KRPERMHANDLER_H #define KRPERMHANDLER_H -#include -#include -#include +// QtCore +#include +#include +#include #include #define NO_PERM 0 #define UNKNOWN_PERM 1 #define ALLOWED_PERM 2 class KRpermHandler { public: KRpermHandler() {} ~KRpermHandler() {} static void init(); static gid_t group2gid(QString group); static uid_t user2uid(QString user); static QString gid2group(gid_t groupId); static QString uid2user(uid_t userId); static char writeable(QString perm, gid_t gid, uid_t uid, int rwx = -1); static char readable(QString perm, gid_t gid, uid_t uid, int rwx = -1); static char executable(QString perm, gid_t gid, uid_t uid, int rwx = -1); static bool fileWriteable(QString localFile); static bool fileReadable(QString localFile); static bool fileExecutable(QString localFile); static char ftpWriteable(QString fileOwner, QString userName, QString perm); static char ftpReadable(QString fileOwner, QString userName, QString perm); static char ftpExecutable(QString fileOwner, QString userName, QString perm); static bool dirExist(QString path); static bool fileExist(QString fullPath); static bool fileExist(QString Path, QString name); static QString mode2QString(mode_t m); static QString parseSize(KIO::filesize_t val); static QString date2qstring(QString date); static time_t QString2time(QString date); private: // cache for passwd and group entries static QHash *passwdCache; static QHash *groupCache; static QHash *currentGroups; static QHash *uidCache; static QHash *gidCache; }; #endif diff --git a/krusader/VFS/krquery.cpp b/krusader/VFS/krquery.cpp index 7e510e85..1be376e7 100644 --- a/krusader/VFS/krquery.cpp +++ b/krusader/VFS/krquery.cpp @@ -1,762 +1,763 @@ /*************************************************************************** krquery.cpp ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "krquery.h" -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include #include #include #include #include #include "vfs.h" #include "krarchandler.h" #include "krpermhandler.h" #define STATUS_SEND_DELAY 250 #define MAX_LINE_LEN 1000 // set the defaults KRQuery::KRQuery(): QObject(), matchesCaseSensitive(true), bNull(true), contain(QString()), containCaseSensetive(true), containWholeWord(false), containRegExp(false), containOnRemote(false), minSize(0), maxSize(0), newerThen(0), olderThen(0), owner(QString()), group(QString()), perm(QString()), type(QString()), inArchive(false), recurse(true), followLinksP(true), receivedBuffer(0), receivedBufferLen(0), processEventsConnected(0), codec(QTextCodec::codecForLocale()) { QChar ch = '\n'; QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); encodedEnterArray = codec->fromUnicode(&ch, 1, &state); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); } // set the defaults KRQuery::KRQuery(const QString &name, bool matchCase) : QObject(), bNull(true), contain(QString()), containCaseSensetive(true), containWholeWord(false), containRegExp(false), containOnRemote(false), minSize(0), maxSize(0), newerThen(0), olderThen(0), owner(QString()), group(QString()), perm(QString()), type(QString()), inArchive(false), recurse(true), followLinksP(true), receivedBuffer(0), receivedBufferLen(0), processEventsConnected(0), codec(QTextCodec::codecForLocale()) { QChar ch = '\n'; QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); encodedEnterArray = codec->fromUnicode(&ch, 1, &state); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); setNameFilter(name, matchCase); } KRQuery::KRQuery(const KRQuery & that) : QObject(), receivedBuffer(0), receivedBufferLen(0), processEventsConnected(0) { *this = that; } KRQuery::~KRQuery() { if (receivedBuffer) delete []receivedBuffer; receivedBuffer = 0; } KRQuery& KRQuery::operator=(const KRQuery & old) { matches = old.matches; excludes = old.excludes; includedDirs = old.includedDirs; excludedDirs = old.excludedDirs; matchesCaseSensitive = old.matchesCaseSensitive; bNull = old.bNull; contain = old.contain; containCaseSensetive = old.containCaseSensetive; containWholeWord = old.containWholeWord; containRegExp = old.containRegExp; containOnRemote = old.containOnRemote; minSize = old.minSize; maxSize = old.maxSize; newerThen = old.newerThen; olderThen = old.olderThen; owner = old.owner; group = old.group; perm = old.perm; type = old.type; customType = old.customType; inArchive = old.inArchive; recurse = old.recurse; followLinksP = old.followLinksP; whereToSearch = old.whereToSearch; whereNotToSearch = old.whereNotToSearch; origFilter = old.origFilter; codec = old.codec; encodedEnterArray = old.encodedEnterArray; encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); return *this; } void KRQuery::load(KConfigGroup cfg) { *this = KRQuery(); // reset parameters first if(cfg.readEntry("IsNull", true)) return; #define LOAD(key, var) (var = cfg.readEntry(key, var)) LOAD("Matches", matches); LOAD("Excludes", excludes); LOAD("IncludedDirs", includedDirs); LOAD("ExcludedDirs", excludedDirs); LOAD("MatchesCaseSensitive", matchesCaseSensitive); LOAD("Contain", contain); LOAD("ContainCaseSensetive", containCaseSensetive); LOAD("ContainWholeWord", containWholeWord); LOAD("ContainRegExp", containRegExp); LOAD("ContainOnRemote", containOnRemote); LOAD("MinSize", minSize); LOAD("MaxSize", maxSize); newerThen = QDateTime::fromString(cfg.readEntry("NewerThan", QDateTime::fromTime_t(newerThen).toString())).toTime_t(); olderThen = QDateTime::fromString(cfg.readEntry("OlderThan", QDateTime::fromTime_t(olderThen).toString())).toTime_t(); LOAD("Owner", owner); LOAD("Group", group); LOAD("Perm", perm); LOAD("Type", type); LOAD("CustomType", customType); LOAD("InArchive", inArchive); LOAD("Recurse", recurse); LOAD("FollowLinks", followLinksP); // KF5 TODO? //LOAD("WhereToSearch", whereToSearch); //LOAD("WhereNotToSearch", whereNotToSearch); LOAD("OrigFilter", origFilter); codec = QTextCodec::codecForName(cfg.readEntry("Codec", codec->name())); if(!codec) codec = QTextCodec::codecForLocale(); LOAD("EncodedEnterArray", encodedEnterArray); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); #undef LOAD bNull = false; } void KRQuery::save(KConfigGroup cfg) { cfg.writeEntry("IsNull", bNull); if(bNull) return; cfg.writeEntry("Matches", matches); cfg.writeEntry("Excludes", excludes); cfg.writeEntry("IncludedDirs", includedDirs); cfg.writeEntry("ExcludedDirs", excludedDirs); cfg.writeEntry("MatchesCaseSensitive", matchesCaseSensitive); cfg.writeEntry("Contain", contain); cfg.writeEntry("ContainCaseSensetive", containCaseSensetive); cfg.writeEntry("ContainWholeWord", containWholeWord); cfg.writeEntry("ContainRegExp", containRegExp); cfg.writeEntry("ContainOnRemote", containOnRemote); cfg.writeEntry("MinSize", minSize); cfg.writeEntry("MaxSize", maxSize); cfg.writeEntry("NewerThan", QDateTime::fromTime_t(newerThen).toString()); cfg.writeEntry("OlderThan", QDateTime::fromTime_t(olderThen).toString()); cfg.writeEntry("Owner", owner); cfg.writeEntry("Group", group); cfg.writeEntry("Perm", perm); cfg.writeEntry("Type", type); cfg.writeEntry("CustomType", customType); cfg.writeEntry("InArchive", inArchive); cfg.writeEntry("Recurse", recurse); cfg.writeEntry("FollowLinks", followLinksP); // KF5 TODO? //cfg.writeEntry("WhereToSearch", whereToSearch); //cfg.writeEntry("WhereNotToSearch", whereNotToSearch); cfg.writeEntry("OrigFilter", origFilter); cfg.writeEntry("Codec", codec->name()); cfg.writeEntry("EncodedEnterArray", encodedEnterArray); cfg.writeEntry("EncodedEnter", encodedEnter); cfg.writeEntry("EncodedEnterLen", encodedEnterLen); } void KRQuery::connectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&KRQuery::processEvents)) processEventsConnected++; } void KRQuery::disconnectNotify(const QMetaMethod &signal) { if (signal == QMetaMethod::fromSignal(&KRQuery::processEvents)) processEventsConnected--; } bool KRQuery::checkPerm(QString filePerm) const { for (int i = 0; i < 9; ++i) if (perm[ i ] != '?' && perm[ i ] != filePerm[ i + 1 ]) return false; return true; } bool KRQuery::checkType(QString mime) const { if (type == mime) return true; if (type == i18n("Archives")) return KRarcHandler::arcSupported(mime); if (type == i18n("Folders")) return mime.contains("directory"); if (type == i18n("Image Files")) return mime.contains("image/"); if (type == i18n("Text Files")) return mime.contains("text/"); if (type == i18n("Video Files")) return mime.contains("video/"); if (type == i18n("Audio Files")) return mime.contains("audio/"); if (type == i18n("Custom")) return customType.contains(mime); return false; } bool KRQuery::match(const QString & name) const { return matchCommon(name, matches, excludes); } bool KRQuery::matchDirName(const QString & name) const { return matchCommon(name, includedDirs, excludedDirs); } bool KRQuery::matchCommon(const QString &nameIn, const QStringList &matchList, const QStringList &excludeList) const { if (excludeList.count() == 0 && matchList.count() == 0) /* true if there's no match condition */ return true; QString name(nameIn); int ndx = nameIn.lastIndexOf('/'); // virtual filenames may contain '/' if (ndx != -1) // but the end of the filename is OK name = nameIn.mid(ndx + 1); for (int i = 0; i < excludeList.count(); ++i) { if (QRegExp(excludeList[ i ], matchesCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard).exactMatch(name)) return false; } if (matchList.count() == 0) return true; for (int i = 0; i < matchList.count(); ++i) { if (QRegExp(matchList[ i ], matchesCaseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::Wildcard).exactMatch(name)) return true; } return false; } bool KRQuery::match(vfile *vf) const { if (vf->vfile_isDir() && !matchDirName(vf->vfile_getName())) return false; // see if the name matches if (!match(vf->vfile_getName())) return false; // checking the mime if (!type.isEmpty() && !checkType(vf->vfile_getMime(true))) return false; // check that the size fit KIO::filesize_t size = vf->vfile_getSize(); if (minSize && size < minSize) return false; if (maxSize && size > maxSize) return false; // check the time frame time_t mtime = vf->vfile_getTime_t(); if (olderThen && mtime > olderThen) return false; if (newerThen && mtime < newerThen) return false; // check owner name if (!owner.isEmpty() && vf->vfile_getOwner() != owner) return false; // check group name if (!group.isEmpty() && vf->vfile_getGroup() != group) return false; //check permission if (!perm.isEmpty() && !checkPerm(vf->vfile_getPerm())) return false; if (!contain.isEmpty()) { if ((totalBytes = vf->vfile_getSize()) == 0) totalBytes++; // sanity receivedBytes = 0; if (receivedBuffer) delete receivedBuffer; receivedBuffer = 0; receivedBufferLen = 0; fileName = vf->vfile_getName(); timer.start(); if (vf->vfile_getUrl().isLocalFile()) { if (!containsContent(vf->vfile_getUrl().path())) return false; } else { if (containOnRemote) { if (processEventsConnected == 0) return false; else if (containsContent(vf->vfile_getUrl())) return true; else return false; } else return false; } } return true; } bool KRQuery::match(KFileItem *kfi) const { mode_t mode = kfi->mode() | kfi->permissions(); QString perm = KRpermHandler::mode2QString(mode); if (kfi->isDir()) perm[ 0 ] = 'd'; vfile temp(kfi->text(), kfi->size(), perm, kfi->time(KFileItem::ModificationTime).toTime_t(), kfi->isLink(), false, kfi->user(), kfi->group(), kfi->user(), kfi->mimetype(), kfi->linkDest(), mode); return match(&temp); } // takes the string and adds BOLD to it, so that when it is displayed, // the grepped text will be bold void fixFoundTextForDisplay(QString& haystack, int start, int length) { QString before = haystack.left(start); QString text = haystack.mid(start, length); QString after = haystack.mid(start + length); before.replace('&', "&"); before.replace('<', "<"); before.replace('>', ">"); text.replace('&', "&"); text.replace('<', "<"); text.replace('>', ">"); after.replace('&', "&"); after.replace('<', "<"); after.replace('>', ">"); haystack = ("" + before + "" + text + "" + after + ""); } bool KRQuery::checkBuffer(const char * data, int len) const { bool result = false; char * mergedBuffer = new char [ len + receivedBufferLen ]; if (receivedBufferLen) memcpy(mergedBuffer, receivedBuffer, receivedBufferLen); if (len) memcpy(mergedBuffer + receivedBufferLen, data, len); int maxLen = len + receivedBufferLen; int maxBuffer = maxLen - encodedEnterLen; int lastLinePosition = 0; for (int enterIndex = 0; enterIndex < maxBuffer; enterIndex++) { if (memcmp(mergedBuffer + enterIndex, encodedEnter, encodedEnterLen) == 0) { QString str = codec->toUnicode(mergedBuffer + lastLinePosition, enterIndex + encodedEnterLen - lastLinePosition); if (str.endsWith('\n')) { str.chop(1); result = result || checkLine(str); lastLinePosition = enterIndex + encodedEnterLen; enterIndex = lastLinePosition; continue; } } } if (maxLen - lastLinePosition > MAX_LINE_LEN || len == 0) { QString str = codec->toUnicode(mergedBuffer + lastLinePosition, maxLen - lastLinePosition); result = result || checkLine(str); lastLinePosition = maxLen; } delete []receivedBuffer; receivedBuffer = 0; receivedBufferLen = maxLen - lastLinePosition; if (receivedBufferLen) { receivedBuffer = new char [ receivedBufferLen ]; memcpy(receivedBuffer, mergedBuffer + lastLinePosition, receivedBufferLen); } delete []mergedBuffer; return result; } bool KRQuery::checkLine(const QString & line, bool backwards) const { if (containRegExp) { QRegExp rexp(contain, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::RegExp); int ndx = backwards ? rexp.lastIndexIn(line) : rexp.indexIn(line); bool result = ndx >= 0; if (result) fixFoundTextForDisplay(lastSuccessfulGrep = line, lastSuccessfulGrepMatchIndex = ndx, lastSuccessfulGrepMatchLength = rexp.matchedLength()); return result; } int ndx = backwards ? -1 : 0; if (line.isNull()) return false; if (containWholeWord) { while ((ndx = (backwards) ? line.lastIndexOf(contain, ndx, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive) : line.indexOf(contain, ndx, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive) ) != -1) { QChar before = '\n'; QChar after = '\n'; if (ndx > 0) before = line.at(ndx - 1); if (ndx + contain.length() < line.length()) after = line.at(ndx + contain.length()); if (!before.isLetterOrNumber() && !after.isLetterOrNumber() && after != '_' && before != '_') { lastSuccessfulGrep = line; fixFoundTextForDisplay(lastSuccessfulGrep, lastSuccessfulGrepMatchIndex = ndx, lastSuccessfulGrepMatchLength = contain.length()); return true; } if (backwards) ndx -= line.length() + 1; else ndx++; } } else if ((ndx = (backwards) ? line.lastIndexOf(contain, -1, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive) : line.indexOf(contain, 0, containCaseSensetive ? Qt::CaseSensitive : Qt::CaseInsensitive)) != -1) { lastSuccessfulGrep = line; fixFoundTextForDisplay(lastSuccessfulGrep, lastSuccessfulGrepMatchIndex = ndx, lastSuccessfulGrepMatchLength = contain.length()); return true; } return false; } bool KRQuery::containsContent(QString file) const { QFile qf(file); if (!qf.open(QIODevice::ReadOnly)) return false; char buffer[ 1440 ]; // 2k buffer while (!qf.atEnd()) { int bytes = qf.read(buffer, sizeof(buffer)); if (bytes <= 0) break; receivedBytes += bytes; if (checkBuffer(buffer, bytes)) return true; if (checkTimer()) { bool stopped = false; emit((KRQuery *)this)->processEvents(stopped); if (stopped) return false; } } if (checkBuffer(buffer, 0)) return true; lastSuccessfulGrep.clear(); // nothing was found return false; } bool KRQuery::containsContent(QUrl url) const { KIO::TransferJob *contentReader = KIO::get(url, KIO::NoReload, KIO::HideProgressInfo); connect(contentReader, SIGNAL(data(KIO::Job *, const QByteArray &)), this, SLOT(containsContentData(KIO::Job *, const QByteArray &))); connect(contentReader, SIGNAL(result(KJob*)), this, SLOT(containsContentFinished(KJob*))); busy = true; containsContentResult = false; bool stopped = false; while (busy && !stopped) { checkTimer(); emit((KRQuery *)this)->processEvents(stopped); } if (busy) { contentReader->kill(KJob::EmitResult); busy = false; } return containsContentResult; } void KRQuery::containsContentData(KIO::Job *job, const QByteArray &array) { receivedBytes += array.size(); if (checkBuffer(array.data(), array.size())) { containsContentResult = true; containsContentFinished(job); job->kill(KJob::EmitResult); return; } checkTimer(); } void KRQuery::containsContentFinished(KJob *) { busy = false; } bool KRQuery::checkTimer() const { if (timer.elapsed() >= STATUS_SEND_DELAY) { int pcnt = (int)(100.*(double)receivedBytes / (double)totalBytes + .5); QString message = i18nc("%1=filename, %2=percentage", "Searching content of '%1' (%2%)", fileName, pcnt); timer.start(); emit((KRQuery *)this)->status(message); return true; } return false; } QStringList KRQuery::split(QString str) { QStringList list; int splitNdx = 0; int startNdx = 0; bool quotation = false; while (splitNdx < str.length()) { if (str[ splitNdx ] == '"') quotation = !quotation; if (!quotation && str[ splitNdx ] == ' ') { QString section = str.mid(startNdx, splitNdx - startNdx); startNdx = splitNdx + 1; if (section.startsWith('\"') && section.endsWith('\"') && section.length() >= 2) section = section.mid(1, section.length() - 2); if (!section.isEmpty()) list.append(section); } splitNdx++; } if (startNdx < splitNdx) { QString section = str.mid(startNdx, splitNdx - startNdx); if (section.startsWith('\"') && section.endsWith('\"') && section.length() >= 2) section = section.mid(1, section.length() - 2); if (!section.isEmpty()) list.append(section); } return list; } void KRQuery::setNameFilter(const QString &text, bool cs) { bNull = false; matchesCaseSensitive = cs; origFilter = text; QString matchText = text; QString excludeText; int excludeNdx = 0; bool quotationMark = 0; while (excludeNdx < matchText.length()) { if (matchText[ excludeNdx ] == '"') quotationMark = !quotationMark; if (!quotationMark) { if (matchText[ excludeNdx ] == '|') break; } excludeNdx++; } if (excludeNdx < matchText.length()) { excludeText = matchText.mid(excludeNdx + 1).trimmed(); matchText.truncate(excludeNdx); matchText = matchText.trimmed(); if (matchText.isEmpty()) matchText = '*'; } int i; matches = split(matchText); includedDirs.clear(); for (i = 0; i < matches.count();) { if (matches[ i ].endsWith('/')) { includedDirs.push_back(matches[ i ].left(matches[ i ].length() - 1)); matches.removeAll(matches.at(i)); continue; } if (!matches[ i ].contains("*") && !matches[ i ].contains("?")) matches[ i ] = '*' + matches[ i ] + '*'; i++; } excludes = split(excludeText); excludedDirs.clear(); for (i = 0; i < excludes.count();) { if (excludes[ i ].endsWith('/')) { excludedDirs.push_back(excludes[ i ].left(excludes[ i ].length() - 1)); excludes.removeAll(excludes.at(i)); continue; } if (!excludes[ i ].contains("*") && !excludes[ i ].contains("?")) excludes[ i ] = '*' + excludes[ i ] + '*'; i++; } } void KRQuery::setContent(const QString &content, bool cs, bool wholeWord, bool remoteSearch, QString encoding, bool regExp) { bNull = false; contain = content; containCaseSensetive = cs; containWholeWord = wholeWord; containRegExp = regExp; containOnRemote = remoteSearch; if (encoding.isEmpty()) codec = QTextCodec::codecForLocale(); else { codec = QTextCodec::codecForName(encoding.toLatin1()); if (codec == 0) codec = QTextCodec::codecForLocale(); } QChar ch = '\n'; QTextCodec::ConverterState state(QTextCodec::IgnoreHeader); encodedEnterArray = codec->fromUnicode(&ch, 1, &state); encodedEnter = encodedEnterArray.data(); encodedEnterLen = encodedEnterArray.size(); } void KRQuery::setMinimumFileSize(KIO::filesize_t minimumSize) { bNull = false; minSize = minimumSize; } void KRQuery::setMaximumFileSize(KIO::filesize_t maximumSize) { bNull = false; maxSize = maximumSize; } void KRQuery::setNewerThan(time_t time) { bNull = false; newerThen = time; } void KRQuery::setOlderThan(time_t time) { bNull = false; olderThen = time; } void KRQuery::setOwner(const QString &ownerIn) { bNull = false; owner = ownerIn; } void KRQuery::setGroup(const QString &groupIn) { bNull = false; group = groupIn; } void KRQuery::setPermissions(const QString &permIn) { bNull = false; perm = permIn; } void KRQuery::setMimeType(const QString &typeIn, QStringList customList) { bNull = false; type = typeIn; customType = customList; } bool KRQuery::isExcluded(const QUrl &url) { for (int i = 0; i < whereNotToSearch.count(); ++i) if (whereNotToSearch [ i ].isParentOf(url) || url.matches(whereNotToSearch [ i ], QUrl::StripTrailingSlash)) return true; if (!matchDirName(url.fileName())) return true; return false; } void KRQuery::setSearchInDirs(const QList &urls) { whereToSearch.clear(); for (int i = 0; i < urls.count(); ++i) { QString url = urls[ i ].url(); QUrl completed = QUrl::fromUserInput(KUrlCompletion::replacedPath(url, true, true), QString(), QUrl::AssumeLocalFile); whereToSearch.append(completed); } } void KRQuery::setDontSearchInDirs(const QList &urls) { whereNotToSearch.clear(); for (int i = 0; i < urls.count(); ++i) { QString url = urls[ i ].url(); QUrl completed = QUrl::fromUserInput(KUrlCompletion::replacedPath(url, true, true), QString(), QUrl::AssumeLocalFile); whereNotToSearch.append(completed); } } diff --git a/krusader/VFS/krquery.h b/krusader/VFS/krquery.h index 15ca1d3e..d750f54f 100644 --- a/krusader/VFS/krquery.h +++ b/krusader/VFS/krquery.h @@ -1,263 +1,264 @@ /*************************************************************************** krquery.h ------------------- copyright : (C) 2001 by Shie Erlich & Rafi Yanai email : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef KRQUERY_H #define KRQUERY_H -#include -#include -#include +// QtCore +#include +#include +#include #include #include class KFileItem; class QTextCodec; class vfile; class KRQuery : public QObject { Q_OBJECT public: // null query KRQuery(); // query only with name filter KRQuery(const QString &name, bool matchCase = true); // copy constructor KRQuery(const KRQuery &); // let operator KRQuery& operator=(const KRQuery &); // destructor virtual ~KRQuery(); //load parameters from config void load(KConfigGroup cfg); //save parameters to config void save(KConfigGroup cfg); // matching a file with the query bool match(vfile *file) const; // checks if the given vfile object matches the conditions // matching a KIO file with the query bool match(KFileItem *file) const; // checks if the given vfile object matches the conditions // matching a name with the query bool match(const QString &name) const; // matching the filename only // matching the name of the directory bool matchDirName(const QString &name) const; // sets the text for name filtering void setNameFilter(const QString &text, bool cs = true); // returns the current filter mask const QString& nameFilter() const { return origFilter; } // returns whether the filter is case sensitive bool isCaseSensitive() { return matchesCaseSensitive; } // returns if the filter is null (was cancelled) bool isNull() { return bNull; }; // sets the content part of the query void setContent(const QString &content, bool cs = true, bool wholeWord = false, bool remoteSearch = false, QString encoding = QString(), bool regExp = false); const QString content() { return contain; } // sets the minimum file size limit void setMinimumFileSize(KIO::filesize_t); // sets the maximum file size limit void setMaximumFileSize(KIO::filesize_t); // sets the time the file newer than void setNewerThan(time_t time); // sets the time the file older than void setOlderThan(time_t time); // sets the owner void setOwner(const QString &ownerIn); // sets the group void setGroup(const QString &groupIn); // sets the permissions void setPermissions(const QString &permIn); // sets the mimetype for the query // type, must be one of the following: // 1. a valid mime type name // 2. one of: i18n("Archives"), i18n("Folders"), i18n("Image Files") // i18n("Text Files"), i18n("Video Files"), i18n("Audio Files") // 3. i18n("Custom") in which case you must supply a list of valid mime-types // in the member QStringList customType void setMimeType(const QString &typeIn, QStringList customList = QStringList()); // true if setMimeType was called bool hasMimeType() { return type.isEmpty(); } // sets the search in archive flag void setSearchInArchives(bool flag) { inArchive = flag; } // gets the search in archive flag bool searchInArchives() { return inArchive; } // sets the recursive flag void setRecursive(bool flag) { recurse = flag; } // gets the recursive flag bool isRecursive() { return recurse; } // sets whether to follow symbolic links void setFollowLinks(bool flag) { followLinksP = flag; } // gets whether to follow symbolic links bool followLinks() { return followLinksP; } // sets the folders where the searcher will search void setSearchInDirs(const QList &urls); // gets the folders where the searcher searches const QList & searchInDirs() { return whereToSearch; } // sets the folders where search is not permitted void setDontSearchInDirs(const QList &urls); // gets the folders where search is not permitted const QList & dontSearchInDirs() { return whereNotToSearch; } // checks if a URL is excluded bool isExcluded(const QUrl &url); // gives whether we search for content bool isContentSearched() const { return !contain.isEmpty(); } bool checkLine(const QString &line, bool backwards = false) const; const QString& foundText() const { return lastSuccessfulGrep; } int matchIndex() const { return lastSuccessfulGrepMatchIndex; } int matchLength() const { return lastSuccessfulGrepMatchLength; } protected: // important to know whether the event processor is connected virtual void connectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; // important to know whether the event processor is connected virtual void disconnectNotify(const QMetaMethod &signal) Q_DECL_OVERRIDE; protected: QStringList matches; // what to search QStringList excludes; // what to exclude QStringList includedDirs; // what dirs to include QStringList excludedDirs; // what dirs to exclude bool matchesCaseSensitive; bool bNull; // flag if the query is null QString contain; // file must contain this string bool containCaseSensetive; bool containWholeWord; bool containRegExp; bool containOnRemote; KIO::filesize_t minSize; KIO::filesize_t maxSize; time_t newerThen; time_t olderThen; QString owner; QString group; QString perm; QString type; QStringList customType; bool inArchive; // if true- search in archive. bool recurse; // if true recurse ob sub-dirs... bool followLinksP; QList whereToSearch; // directories to search QList whereNotToSearch; // directories NOT to search signals: void status(const QString &name); void processEvents(bool & stopped); private: bool matchCommon(const QString &, const QStringList &, const QStringList &) const; bool checkPerm(QString perm) const; bool checkType(QString mime) const; bool containsContent(QString file) const; bool containsContent(QUrl url) const; bool checkBuffer(const char * data, int len) const; bool checkTimer() const; QStringList split(QString); private slots: void containsContentData(KIO::Job *, const QByteArray &); void containsContentFinished(KJob*); private: QString origFilter; mutable bool busy; mutable bool containsContentResult; mutable char * receivedBuffer; mutable int receivedBufferLen; mutable QString lastSuccessfulGrep; mutable int lastSuccessfulGrepMatchIndex; mutable int lastSuccessfulGrepMatchLength; mutable QString fileName; mutable KIO::filesize_t receivedBytes; mutable KIO::filesize_t totalBytes; mutable int processEventsConnected; mutable QTime timer; QTextCodec * codec; const char * encodedEnter; int encodedEnterLen; QByteArray encodedEnterArray; }; #endif diff --git a/krusader/VFS/krvfshandler.cpp b/krusader/VFS/krvfshandler.cpp index 812599e5..48509831 100644 --- a/krusader/VFS/krvfshandler.cpp +++ b/krusader/VFS/krvfshandler.cpp @@ -1,72 +1,73 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "krvfshandler.h" #include "normal_vfs.h" #include "ftp_vfs.h" #include "virt_vfs.h" #include "../krservices.h" -#include +// QtCore +#include KrVfsHandler::KrVfsHandler() { } KrVfsHandler::~KrVfsHandler() { } vfs::VFS_TYPE KrVfsHandler::getVfsType(const QUrl &url) { QString protocol = url.scheme(); if ((protocol == "krarc" || protocol == "tar" || protocol == "zip") && QDir(KrServices::getPath(url, QUrl::StripTrailingSlash)).exists()) return vfs::VFS_NORMAL; if (url.isLocalFile()) return vfs::VFS_NORMAL; if (protocol == QStringLiteral("virt")) return vfs::VFS_VIRT; return vfs::VFS_FTP; } vfs* KrVfsHandler::getVfs(const QUrl &url, QObject* parent, vfs* oldVfs) { vfs::VFS_TYPE newType, oldType = vfs::VFS_ERROR; if (oldVfs) oldType = oldVfs->vfs_getType(); newType = getVfsType(url); vfs* newVfs = oldVfs; if (oldType != newType) { switch (newType) { case(vfs::VFS_NORMAL) : newVfs = new normal_vfs(parent); break; case(vfs::VFS_FTP) : newVfs = new ftp_vfs(parent) ; break; case(vfs::VFS_VIRT) : newVfs = new virt_vfs(parent) ; break; case(vfs::VFS_ERROR) : newVfs = 0 ; break; } } return newVfs; } diff --git a/krusader/VFS/krvfshandler.h b/krusader/VFS/krvfshandler.h index 03dcc710..14e20ec9 100644 --- a/krusader/VFS/krvfshandler.h +++ b/krusader/VFS/krvfshandler.h @@ -1,40 +1,41 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef KRVFSHANDLER_H #define KRVFSHANDLER_H -#include -#include +// QtCore +#include +#include #include "vfs.h" class KrVfsHandler : public QObject { Q_OBJECT public: KrVfsHandler(); ~KrVfsHandler(); static vfs::VFS_TYPE getVfsType(const QUrl &url); static vfs* getVfs(const QUrl &url, QObject* parent = 0, vfs* oldVfs = 0); }; #endif diff --git a/krusader/VFS/normal_vfs.cpp b/krusader/VFS/normal_vfs.cpp index 5c14a982..2186a52a 100644 --- a/krusader/VFS/normal_vfs.cpp +++ b/krusader/VFS/normal_vfs.cpp @@ -1,462 +1,463 @@ /*************************************************************************** normal_vfs.cpp ------------------- copyright : (C) 2000 by Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "normal_vfs.h" #ifdef HAVE_POSIX_ACL #include #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS #include #endif #endif -#include -#include -#include +// QtCore +#include +#include +#include #include #include #include #include #include #include #include #include "../Dialogs/krdialogs.h" #include "../MountMan/kmountman.h" #include "krpermhandler.h" #include "../krglobal.h" #include "../defaults.h" #include "../krservices.h" normal_vfs::normal_vfs(QObject* panel): vfs(panel), watcher(0) { vfs_type = VFS_NORMAL; } bool normal_vfs::populateVfsList(const QUrl &origin, bool showHidden) { QString path = KrServices::getPath(origin, QUrl::StripTrailingSlash); #ifdef Q_WS_WIN if (! path.contains("/")) { //change C: to C:/ path = path + QString("/"); } #endif // set the writable attribute to true, if that's not the case - the KIO job // will give the warnings and errors isWritable = true; if (watcher) delete watcher; //stop watching the old dir watcher = 0; // set the origin... vfs_origin = origin; vfs_origin.setPath(path); //vfs_origin.vfs_origin = vfs_origin.adjusted(QUrl::StripTrailingSlash)); vfs_origin.setScheme("file"); // do not remove ! vfs_origin.setPath(QDir::cleanPath(vfs_origin.path())); // check that the new origin exists if (!QDir(path).exists()) { if (!quietMode) emit error(i18n("The folder %1 does not exist.", path)); return false; } KConfigGroup group(krConfig, "Advanced"); if (group.readEntry("AutoMount", _AutoMount) && !mountMan.isNull()) mountMan->autoMount(path); QT_DIR* dir = QT_OPENDIR(path.toLocal8Bit()); if (!dir) { if (!quietMode) emit error(i18n("Cannot open the folder %1.", path)); return false; } // change directory to the new directory QString save = QDir::currentPath(); if (! QDir::setCurrent(path)) { if (!quietMode) emit error(i18nc("%1=folder path", "Access to %1 denied", path)); QT_CLOSEDIR(dir); return false; } QT_DIRENT* dirEnt; QString name; while ((dirEnt = QT_READDIR(dir)) != NULL) { name = QString::fromLocal8Bit(dirEnt->d_name); // show hidden files ? if (!showHidden && name.left(1) == ".") continue ; // we don't need the ".",".." entries if (name == "." || name == "..") continue; vfile* temp = vfileFromName(name, dirEnt->d_name); foundVfile(temp); } // clean up QT_CLOSEDIR(dir); QDir::setCurrent(save); if (panelConnected) { watcher = new KDirWatch(); // connect the watcher connect(watcher, SIGNAL(dirty(const QString&)), this, SLOT(vfs_slotDirty(const QString&))); connect(watcher, SIGNAL(created(const QString&)), this, SLOT(vfs_slotCreated(const QString&))); connect(watcher, SIGNAL(deleted(const QString&)), this, SLOT(vfs_slotDeleted(const QString&))); watcher->addDir(vfs_getOrigin().adjusted(QUrl::StripTrailingSlash).path(), KDirWatch::WatchFiles); //start watching the new dir watcher->startScan(true); } return true; } // copy a file to the vfs (physical) void normal_vfs::vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir, PreserveMode pmode) { //if( watcher ) watcher->stopScan(); // we will refresh manually this time... if (watcher) { delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher watcher = 0; } QUrl dest = QUrl::fromLocalFile(vfs_workingDir() + '/' + dir); KIO::Job* job = PreservingCopyJob::createCopyJob(pmode, fileUrls, dest, mode, false, true); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob *))); if (mode == KIO::CopyJob::Move) // notify the other panel connect(job, SIGNAL(result(KJob*)), toNotify, SLOT(vfs_refresh(KJob*))); else job->ui()->setAutoErrorHandlingEnabled(true); } // remove a file from the vfs (physical) void normal_vfs::vfs_delFiles(const QStringList &fileNames, bool reallyDelete) { // if( watcher ) watcher->stopScan(); // we will refresh manually this time... if (watcher) { delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher watcher = 0; } // names -> urls QList filesUrls = vfs_getFiles(fileNames); KIO::Job *job; // delete of move to trash ? KConfigGroup group(krConfig, "General"); if (!reallyDelete && group.readEntry("Move To Trash", _MoveToTrash)) { job = KIO::trash(filesUrls); emit trashJobStarted(job); } else job = KIO::del(filesUrls); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } // return a path to the file QUrl normal_vfs::vfs_getFile(const QString& name) { QString url; if (vfs_workingDir() == "/") url = "/" + name; else url = vfs_workingDir() + '/' + name; return QUrl::fromLocalFile(url); } QList normal_vfs::vfs_getFiles(const QStringList &names) { QList urls; foreach (const QString &name, names) { urls.append(vfs_getFile(name)); } return urls; } void normal_vfs::vfs_mkdir(const QString& name) { if (!QDir(vfs_workingDir()).mkdir(name)) if (!quietMode) KMessageBox::sorry(parentWindow, i18n("Cannot create a folder. Check your permissions.")); vfs::vfs_refresh(); } void normal_vfs::vfs_rename(const QString& fileName, const QString& newName) { //if( watcher ) watcher->stopScan(); // we will refresh manually this time... if (watcher) { delete watcher; // stopScan is buggy, leaves reference on the directory, that's why we delete the watcher watcher = 0; } QList fileUrls; fileUrls.append(QUrl::fromLocalFile(vfs_workingDir() + '/' + fileName)); KIO::Job *job = KIO::move(fileUrls, QUrl::fromLocalFile(vfs_workingDir() + '/' + newName)); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } vfile* normal_vfs::vfileFromName(const QString& name, char * rawName) { QString path = vfs_workingDir() + '/' + name; QByteArray fileName = rawName == 0 ? path.toLocal8Bit() : (vfs_workingDir() + '/').toLocal8Bit().append(rawName); QT_STATBUF stat_p; stat_p.st_size = 0; stat_p.st_mode = 0; stat_p.st_mtime = 0; stat_p.st_uid = 0; stat_p.st_gid = 0; QT_LSTAT(fileName.data(), &stat_p); KIO::filesize_t size = stat_p.st_size; QString perm = KRpermHandler::mode2QString(stat_p.st_mode); bool symLink = S_ISLNK(stat_p.st_mode); bool brokenLink = false; if (S_ISDIR(stat_p.st_mode)) perm[0] = 'd'; QUrl mimeUrl = QUrl::fromLocalFile(path); QString mime; QString symDest; if (S_ISLNK(stat_p.st_mode)) { // who the link is pointing to ? // the path of the symlink target cannot be longer than the file size of the symlink char buffer[stat_p.st_size]; memset(buffer, 0, sizeof(buffer)); int bytesRead = readlink(fileName.data(), buffer, sizeof(buffer)); if (bytesRead != -1) { symDest = QString::fromLocal8Bit(buffer, bytesRead); if (QDir(symDest).exists()) perm[0] = 'd'; if (!QDir(vfs_workingDir()).exists(symDest)) brokenLink = true; } else krOut << "Failed to read link: " << path << endl; } int rwx = 0; if (::access(fileName.data(), R_OK) == 0) rwx |= R_OK; if (::access(fileName.data(), W_OK) == 0) rwx |= W_OK; #ifndef Q_CC_MSVC if (::access(fileName.data(), X_OK) == 0) rwx |= X_OK; #endif // create a new virtual file object vfile* temp = new vfile(name, size, perm, stat_p.st_mtime, symLink, brokenLink, stat_p.st_uid, stat_p.st_gid, mime, symDest, stat_p.st_mode, rwx); temp->vfile_setUrl(mimeUrl); return temp; } void normal_vfs::getACL(vfile *file, QString &acl, QString &defAcl) { Q_UNUSED(file); acl.clear(); defAcl.clear(); #ifdef HAVE_POSIX_ACL QString fileName = file->vfile_getUrl().adjusted(QUrl::StripTrailingSlash).path(); #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS if (acl_extended_file(fileName)) { #endif acl = getACL(fileName, ACL_TYPE_ACCESS); if (file->vfile_isDir()) defAcl = getACL(fileName, ACL_TYPE_DEFAULT); #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS } #endif #endif } QString normal_vfs::getACL(const QString & path, int type) { Q_UNUSED(path); Q_UNUSED(type); #ifdef HAVE_POSIX_ACL acl_t acl = 0; // do we have an acl for the file, and/or a default acl for the dir, if it is one? if ((acl = acl_get_file(path.toLocal8Bit(), type)) != 0) { bool aclExtended = false; #ifdef HAVE_NON_POSIX_ACL_EXTENSIONS aclExtended = acl_equiv_mode(acl, 0); #else acl_entry_t entry; int ret = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); while (ret == 1) { acl_tag_t currentTag; acl_get_tag_type(entry, ¤tTag); if (currentTag != ACL_USER_OBJ && currentTag != ACL_GROUP_OBJ && currentTag != ACL_OTHER) { aclExtended = true; break; } ret = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry); } #endif if (!aclExtended) { acl_free(acl); acl = 0; } } if (acl == 0) return QString(); char *aclString = acl_to_text(acl, 0); QString ret = QString::fromLatin1(aclString); acl_free((void*)aclString); acl_free(acl); return ret; #else return QString(); #endif } void normal_vfs::vfs_slotRefresh() { KConfigGroup group(krConfig, "Advanced"); int maxRefreshFrequency = group.readEntry("Max Refresh Frequency", 1000); vfs_refresh(); disconnect(&refreshTimer, SIGNAL(timeout()), this, SLOT(vfs_slotRefresh())); refreshTimer.setSingleShot(true); refreshTimer.start(maxRefreshFrequency); } bool normal_vfs::burstRefresh(const QString& path) { QString parentPath = path; int ndx = path.lastIndexOf(DIR_SEPARATOR); if (ndx >= 0) parentPath = path.left(ndx == 0 ? 1 : ndx); if (path == vfs_getOrigin().adjusted(QUrl::StripTrailingSlash).path() || parentPath == vfs_getOrigin().adjusted(QUrl::StripTrailingSlash).path()) { if (!refreshTimer.isActive()) { // the directory itself is dirty - full refresh is needed QTimer::singleShot(0, this, SLOT(vfs_slotRefresh())); // safety: dirty signal comes from KDirWatch! return true; } disconnect(&refreshTimer, SIGNAL(timeout()), this, SLOT(vfs_slotRefresh())); connect(&refreshTimer, SIGNAL(timeout()), this, SLOT(vfs_slotRefresh())); postponedRefreshURL = QUrl::fromLocalFile(path); return true; } return false; } void normal_vfs::vfs_slotDirty(const QString& path) { if (disableRefresh) { if (postponedRefreshURL.isEmpty()) postponedRefreshURL = vfs_getOrigin(); return; } if (burstRefresh(path)) return; QUrl url = QUrl::fromLocalFile(path); QString name = url.fileName(); if (name.left(1) == "." && !vfs_showHidden()) return; // do we have it already ? vfile * vf = vfs_search(name); if (!vf) return vfs_slotCreated(path); // we have an updated file.. vfile *newVf = vfileFromName(name, 0); *vf = *newVf; delete newVf; emit updatedVfile(vf); } void normal_vfs::vfs_slotCreated(const QString& path) { if (disableRefresh) { if (postponedRefreshURL.isEmpty()) postponedRefreshURL = vfs_getOrigin(); return; } if (burstRefresh(path)) return; QUrl url = QUrl::fromLocalFile(path); QString name = url.fileName(); if (name.left(1) == "." && !vfs_showHidden()) return; // if it's in the CVS - it's an update not new file if (vfs_search(name)) return vfs_slotDirty(path); vfile* vf = vfileFromName(name, 0); addToList(vf); emit addedVfile(vf); } void normal_vfs::vfs_slotDeleted(const QString& path) { if (disableRefresh) { if (postponedRefreshURL.isEmpty()) postponedRefreshURL = vfs_getOrigin(); return; } if (burstRefresh(path)) return; QUrl url = QUrl::fromLocalFile(path); QString name = url.fileName(); // if it's not in the CVS - do nothing vfile *vf = vfs_search(name); if (vf) { emit deletedVfile(name); removeFromList(name); delete vf; } } diff --git a/krusader/VFS/normal_vfs.h b/krusader/VFS/normal_vfs.h index 20106488..df6d7c27 100644 --- a/krusader/VFS/normal_vfs.h +++ b/krusader/VFS/normal_vfs.h @@ -1,105 +1,106 @@ /*************************************************************************** normal_vfs.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef NORMAL_VFS_H #define NORMAL_VFS_H -#include -#include -#include +// QtCore +#include +#include +#include #include #include #include "vfs.h" /** * The normal_vfs class is Krusader implemention for local directories. * As this is the most common case, we try to make it as fast and efficient * as possible. */ class normal_vfs : public vfs { Q_OBJECT public: // the constructor simply uses the inherited constructor normal_vfs(QObject* panel); ~normal_vfs() { if (watcher) delete watcher; } /// Copy a file to the vfs (physical). virtual void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir = "", PreserveMode pmode = PM_DEFAULT) Q_DECL_OVERRIDE; /// Remove a file from the vfs (physical) virtual void vfs_delFiles(const QStringList &fileNames, bool reallyDelete = false) Q_DECL_OVERRIDE; /// Return a list of URLs for multiple files virtual QList vfs_getFiles(const QStringList &names) Q_DECL_OVERRIDE; /// Return a URL to a single file virtual QUrl vfs_getFile(const QString& name) Q_DECL_OVERRIDE; /// Create a new directory virtual void vfs_mkdir(const QString& name) Q_DECL_OVERRIDE; /// Rename file virtual void vfs_rename(const QString& fileName, const QString& newName) Q_DECL_OVERRIDE; /// return the VFS working dir virtual QString vfs_workingDir() Q_DECL_OVERRIDE { #ifdef Q_OS_WIN QString path = vfs_origin.toLocalFile(); if(path.endsWith('/')) path.chop(1); return path; #else return vfs_origin.adjusted(QUrl::StripTrailingSlash).path(); #endif } /// Get ACL permissions static void getACL(vfile *file, QString &acl, QString &defAcl); public slots: void vfs_slotRefresh(); void vfs_slotDirty(const QString& path); void vfs_slotCreated(const QString& path); void vfs_slotDeleted(const QString& path); protected: /// Re-reads files and stats and fills the vfile list virtual bool populateVfsList(const QUrl &origin, bool showHidden) Q_DECL_OVERRIDE; QTimer refreshTimer; //< Timer to exclude sudden refreshes KDirWatch *watcher; //< The internal dir watcher - use to detect changes in directories vfile* vfileFromName(const QString& name, char * d_name); private: bool burstRefresh(const QString &path); static QString getACL(const QString & path, int type); }; #endif diff --git a/krusader/VFS/packjob.cpp b/krusader/VFS/packjob.cpp index ae0e13bd..776ac79a 100644 --- a/krusader/VFS/packjob.cpp +++ b/krusader/VFS/packjob.cpp @@ -1,179 +1,180 @@ /*************************************************************************** packjob.cpp - description ------------------- copyright : (C) 2009 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "packjob.h" #include "krarchandler.h" -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include #include extern KRarcHandler arcHandler; PackJob::PackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps) : AbstractThreadedJob() { startAbstractJobThread(new PackThread(srcUrl, destUrl, fileNames, type, packProps)); } PackJob * PackJob::createPacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps) { return new PackJob(srcUrl, destUrl, fileNames, type, packProps); } PackThread::PackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps) : AbstractJobThread(), _sourceUrl(srcUrl), _destUrl(destUrl), _fileNames(fileNames), _type(type), _packProperties(packProps) { } void PackThread::slotStart() { QUrl newSource = downloadIfRemote(_sourceUrl, _fileNames); if (newSource.isEmpty()) return; KIO::filesize_t totalSize = 0; unsigned long totalDirs = 0, totalFiles = 0; calcSpaceLocal(newSource, _fileNames, totalSize, totalDirs, totalFiles); QString arcFile = tempFileIfRemote(_destUrl, _type); QString arcDir = newSource.adjusted(QUrl::StripTrailingSlash).path(); setProgressTitle(i18n("Processed files")); QString save = QDir::currentPath(); QDir::setCurrent(arcDir); bool result = KRarcHandler::pack(_fileNames, _type, arcFile, totalFiles + totalDirs, _packProperties, observer()); QDir::setCurrent(save); if (isExited()) return; if (!result) { sendError(KIO::ERR_INTERNAL, i18n("Error while packing")); return; } if (!uploadTempFiles()) return; sendSuccess(); } TestArchiveJob::TestArchiveJob(const QUrl &srcUrl, const QStringList & fileNames) : AbstractThreadedJob() { startAbstractJobThread(new TestArchiveThread(srcUrl, fileNames)); } TestArchiveJob * TestArchiveJob::testArchives(const QUrl &srcUrl, const QStringList & fileNames) { return new TestArchiveJob(srcUrl, fileNames); } TestArchiveThread::TestArchiveThread(const QUrl &srcUrl, const QStringList & fileNames) : AbstractJobThread(), _sourceUrl(srcUrl), _fileNames(fileNames) { } void TestArchiveThread::slotStart() { // Gets a QUrl of the source folder, which may be remote QUrl newSource = downloadIfRemote(_sourceUrl, _fileNames); if (newSource.isEmpty()) return; for (int i = 0; i < _fileNames.count(); ++i) { QString path, type, password, arcName = _fileNames[i]; if (!getArchiveInformation(path, type, password, arcName, newSource)) return; // test the archive if (!KRarcHandler::test(path, type, password, observer(), 0)) { sendError(KIO::ERR_NO_CONTENT, i18nc("%1=archive filename", "%1, test failed.", arcName)); return ; } } sendMessage(i18n("Archive tests passed.")); sendSuccess(); } UnpackJob::UnpackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames) : AbstractThreadedJob() { startAbstractJobThread(new UnpackThread(srcUrl, destUrl, fileNames)); } UnpackJob * UnpackJob::createUnpacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames) { return new UnpackJob(srcUrl, destUrl, fileNames); } UnpackThread::UnpackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames) : AbstractJobThread(), _sourceUrl(srcUrl), _destUrl(destUrl), _fileNames(fileNames) { } void UnpackThread::slotStart() { // Gets a QUrl of the source folder, which may be remote QUrl newSource = downloadIfRemote(_sourceUrl, _fileNames); if (newSource.isEmpty()) return; QString localDest = tempDirIfRemote(_destUrl); for (int i = 0; i < _fileNames.count(); ++i) { QString path, type, password, arcName = _fileNames[i]; if (!getArchiveInformation(path, type, password, arcName, newSource)) return; setProgressTitle(i18n("Processed files")); // unpack the files bool result = KRarcHandler::unpack(path, type, password, localDest, observer()); if (isExited()) return; if (!result) { sendError(KIO::ERR_INTERNAL, i18n("Error while unpacking")); return; } } if (!uploadTempFiles()) return; sendSuccess(); } diff --git a/krusader/VFS/packjob.h b/krusader/VFS/packjob.h index adf239ea..ff99441e 100644 --- a/krusader/VFS/packjob.h +++ b/krusader/VFS/packjob.h @@ -1,134 +1,135 @@ /*************************************************************************** packjob.h - description ------------------- copyright : (C) 2009 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef PACKJOB_H #define PACKJOB_H -#include +// QtCore +#include #include "abstractthreadedjob.h" class PackThread; class TestArchiveThread; class UnpackThread; class PackJob : public AbstractThreadedJob { Q_OBJECT private: PackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps); public: static PackJob * createPacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps); }; class PackThread : public AbstractJobThread { Q_OBJECT public: PackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames, const QString &type, const QMap &packProps); virtual ~PackThread() {} protected slots: virtual void slotStart() Q_DECL_OVERRIDE; private: QUrl _sourceUrl; QUrl _destUrl; QStringList _fileNames; QString _type; QMap _packProperties; }; class TestArchiveJob : public AbstractThreadedJob { Q_OBJECT private: TestArchiveJob(const QUrl &srcUrl, const QStringList & fileNames); public: static TestArchiveJob * testArchives(const QUrl &srcUrl, const QStringList & fileNames); }; class TestArchiveThread : public AbstractJobThread { Q_OBJECT public: TestArchiveThread(const QUrl &srcUrl, const QStringList & fileNames); virtual ~TestArchiveThread() {} protected slots: virtual void slotStart() Q_DECL_OVERRIDE; private: QUrl _sourceUrl; QStringList _fileNames; }; class UnpackJob : public AbstractThreadedJob { Q_OBJECT private: UnpackJob(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames); public: static UnpackJob * createUnpacker(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames); }; class UnpackThread : public AbstractJobThread { Q_OBJECT public: UnpackThread(const QUrl &srcUrl, const QUrl &destUrl, const QStringList & fileNames); virtual ~UnpackThread() {} protected slots: virtual void slotStart() Q_DECL_OVERRIDE; private: QUrl _sourceUrl; QUrl _destUrl; QStringList _fileNames; }; #endif // __PACK_JOB_H__ diff --git a/krusader/VFS/preservingcopyjob.h b/krusader/VFS/preservingcopyjob.h index 1b2e4a69..57f373fa 100644 --- a/krusader/VFS/preservingcopyjob.h +++ b/krusader/VFS/preservingcopyjob.h @@ -1,53 +1,54 @@ /*************************************************************************** preservingcopyjob.h - description ------------------- copyright : (C) 2005 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef PRESERVINGCOPYJOB_H #define PRESERVINGCOPYJOB_H -#include -#include -#include +// QtCore +#include +#include +#include #include typedef enum { PM_NONE = 0, PM_PRESERVE_ATTR = 1, PM_DEFAULT = 2 } PreserveMode; class PreservingCopyJob { public: static KIO::Job *createCopyJob(PreserveMode pmode, const QList& src, const QUrl &dest, KIO::CopyJob::CopyMode mode, bool /* asMethod */, bool showProgressInfo); }; #endif /* __PRESERVING_COPY_JOB_H__ */ diff --git a/krusader/VFS/vfile.cpp b/krusader/VFS/vfile.cpp index 428c0f76..794fb4f4 100644 --- a/krusader/VFS/vfile.cpp +++ b/krusader/VFS/vfile.cpp @@ -1,321 +1,322 @@ /*************************************************************************** vfile.cpp ------------------- copyright : (C) 2000 by Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "vfile.h" -#include -#include -#include +// QtCore +#include +#include +#include #include #include "krpermhandler.h" #include "normal_vfs.h" bool vfile::vfile_userDefinedFolderIcons = true; bool vfile::vfile_useMimeTypeMagic = true; vfile::vfile(const QString& name, // useful construtor const KIO::filesize_t size, const QString& perm, const time_t mtime, const bool symLink, const bool brokenLink, const uid_t owner, const gid_t group, const QString& mime, const QString& symDest, const mode_t mode, const int rwx) { vfile_name = name; vfile_size = size; vfile_owner.clear(); vfile_ownerId = owner; vfile_group.clear(); vfile_groupId = group; vfile_userName.clear(); vfile_perm = perm; vfile_time_t = mtime; vfile_symLink = symLink; vfile_brokenLink = brokenLink, vfile_mimeType = mime; vfile_symDest = symDest; vfile_mode = mode; vfile_isdir = (perm[ 0 ] == 'd'); if (vfile_isDir() && !vfile_symLink) vfile_size = 0; vfile_rwx = rwx; vfile_acl_loaded = false; } vfile::vfile(const QString& name, // useful construtor const KIO::filesize_t size, const QString& perm, const time_t mtime, const bool symLink, const bool brokenLink, const QString& owner, const QString& group, const QString& userName, const QString& mime, const QString& symDest, const mode_t mode, const int rwx, const QString& aclString, const QString& aclDfltString) { vfile_name = name; vfile_size = size; vfile_owner = owner; vfile_group = group; vfile_userName = userName; vfile_ownerId = KRpermHandler::user2uid(owner) ; vfile_groupId = KRpermHandler::group2gid(group); vfile_perm = perm; vfile_time_t = mtime; vfile_symLink = symLink; vfile_brokenLink = brokenLink, vfile_mimeType = mime; vfile_symDest = symDest; vfile_mode = mode; vfile_isdir = (perm[ 0 ] == 'd'); if (vfile_isDir() && !vfile_symLink) vfile_size = 0; vfile_acl = aclString; vfile_def_acl = aclDfltString; vfile_has_acl = !aclString.isNull() || !aclDfltString.isNull(); vfile_acl_loaded = true; vfile_rwx = rwx; } char vfile::vfile_isReadable() const { if (vfile_rwx == PERM_ALL) return ALLOWED_PERM; else if (vfile_userName.isNull()) return KRpermHandler::readable(vfile_perm, vfile_groupId, vfile_ownerId, vfile_rwx); else return KRpermHandler::ftpReadable(vfile_owner, vfile_userName, vfile_perm); } char vfile::vfile_isWriteable() const { if (vfile_rwx == PERM_ALL) return ALLOWED_PERM; else if (vfile_userName.isNull()) return KRpermHandler::writeable(vfile_perm, vfile_groupId, vfile_ownerId, vfile_rwx); else return KRpermHandler::ftpWriteable(vfile_owner, vfile_userName, vfile_perm); } char vfile::vfile_isExecutable() const { if (vfile_rwx == PERM_ALL) { if ((vfile_mode & 0111) || vfile_isdir) return ALLOWED_PERM; else return NO_PERM; } else if (vfile_userName.isNull()) return KRpermHandler::executable(vfile_perm, vfile_groupId, vfile_ownerId, vfile_rwx); else return KRpermHandler::ftpExecutable(vfile_owner, vfile_userName, vfile_perm); } const QString& vfile::vfile_getMime(bool fast) { Q_UNUSED(fast) if (vfile_mimeType.isEmpty()) { if(vfile_isdir) vfile_mimeType = "inode/directory"; else if(vfile_isBrokenLink()) vfile_mimeType = "unknown"; else { QMimeDatabase db; QMimeType mt = db.mimeTypeForUrl(vfile_getUrl()); vfile_mimeType = mt.isValid() ? mt.name() : "unknown"; if (mt.isValid()) vfile_icon = mt.iconName(); if (vfile_mimeType == "inode/directory") { vfile_perm[0] = 'd'; vfile_isdir = true; } } if (vfile_isdir && vfile_userDefinedFolderIcons) { QUrl url = vfile_getUrl(); if (url.isLocalFile()) { QString file = url.toLocalFile() + "/.directory"; KDesktopFile cfg(file); QString icon = cfg.readIcon(); if(icon.startsWith(QLatin1String("./"))) // relative path icon = url.toLocalFile() + '/' + icon; if (!icon.isEmpty()) vfile_icon = icon; } } } return vfile_mimeType; } QString vfile::vfile_getIcon() { if (vfile_icon.isEmpty()) { QString mime = vfile_getMime(!vfile_useMimeTypeMagic); if (vfile_isBrokenLink()) vfile_icon = "file-broken"; else if (vfile_icon.isEmpty()) { QMimeDatabase db; QMimeType mt = db.mimeTypeForName(mime); vfile_icon = mt.isValid() ? mt.iconName() : "file-broken"; } } return vfile_icon; } const QString& vfile::vfile_getOwner() { if (vfile_owner.isEmpty()) vfile_owner = KRpermHandler::uid2user(vfile_getUid()); return vfile_owner; } const QString& vfile::vfile_getGroup() { if (vfile_group.isEmpty()) vfile_group = KRpermHandler::gid2group(vfile_getGid()); return vfile_group; } const QString& vfile::vfile_getACL() { if (!vfile_acl_loaded) vfile_loadACL(); return vfile_acl; } const QString& vfile::vfile_getDefaultACL() { if (!vfile_acl_loaded) vfile_loadACL(); return vfile_def_acl; } void vfile::vfile_loadACL() { if (vfile_url.isLocalFile()) { normal_vfs::getACL(this, vfile_acl, vfile_def_acl); vfile_has_acl = !vfile_acl.isNull() || !vfile_def_acl.isNull(); } vfile_acl_loaded = true; } const KIO::UDSEntry vfile::vfile_getEntry() { KIO::UDSEntry entry; entry.insert(KIO::UDSEntry::UDS_NAME, vfile_getName()); entry.insert(KIO::UDSEntry::UDS_SIZE, vfile_getSize()); entry.insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, vfile_getTime_t()); entry.insert(KIO::UDSEntry::UDS_USER, vfile_getOwner()); entry.insert(KIO::UDSEntry::UDS_GROUP, vfile_getGroup()); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, vfile_getMime()); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, vfile_getMode() & S_IFMT); entry.insert(KIO::UDSEntry::UDS_ACCESS, vfile_getMode() & 07777); if (vfile_isSymLink()) entry.insert(KIO::UDSEntry::UDS_LINK_DEST, vfile_getSymDest()); if (!vfile_acl_loaded) vfile_loadACL(); if (vfile_has_acl) { entry.insert(KIO::UDSEntry::UDS_EXTENDED_ACL, 1); if (!vfile_acl.isNull()) entry.insert(KIO::UDSEntry::UDS_ACL_STRING, vfile_acl); if (!vfile_def_acl.isNull()) entry.insert(KIO::UDSEntry::UDS_DEFAULT_ACL_STRING, vfile_acl); } return entry; } bool vfile::operator==(const vfile& vf) const { bool equal; if (!vfile_acl_loaded) const_cast(this)->vfile_loadACL(); if (!vf.vfile_acl_loaded) const_cast(&vf)->vfile_loadACL(); equal = (vfile_name == vf.vfile_getName()) && (vfile_size == vf.vfile_getSize()) && (vfile_perm == vf.vfile_getPerm()) && (vfile_time_t == vf.vfile_getTime_t()) && (vfile_ownerId == vf.vfile_getUid()) && (vfile_groupId == vf.vfile_getGid()) && (vfile_has_acl == vf.vfile_has_acl) && (!vfile_has_acl || ((vfile_acl == vf.vfile_acl) && (vfile_def_acl == vf.vfile_def_acl))); return equal; } vfile& vfile::operator= (const vfile & vf) { vfile_name = vf.vfile_name ; vfile_size = vf.vfile_size ; vfile_mode = vf.vfile_mode ; vfile_ownerId = vf.vfile_ownerId ; vfile_groupId = vf.vfile_groupId ; vfile_owner = vf.vfile_owner ; vfile_group = vf.vfile_group ; vfile_userName = vf.vfile_userName ; vfile_perm = vf.vfile_perm ; vfile_time_t = vf.vfile_time_t ; vfile_symLink = vf.vfile_symLink ; vfile_brokenLink = vf.vfile_brokenLink; vfile_mimeType = vf.vfile_mimeType ; vfile_symDest = vf.vfile_symDest ; vfile_url = vf.vfile_url ; vfile_isdir = vf.vfile_isdir ; vfile_has_acl = vf.vfile_has_acl ; vfile_acl = vf.vfile_acl ; vfile_def_acl = vf.vfile_def_acl ; vfile_rwx = vf.vfile_rwx ; vfile_acl_loaded = vf.vfile_acl_loaded; vfile_icon = vf.vfile_icon ; return (*this); } diff --git a/krusader/VFS/vfile.h b/krusader/VFS/vfile.h index 66e59f6f..0883bd6e 100644 --- a/krusader/VFS/vfile.h +++ b/krusader/VFS/vfile.h @@ -1,201 +1,202 @@ /*************************************************************************** vfile.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef VFILE_H #define VFILE_H #include -#include -#include -#include +// QtCore +#include +#include +#include #include #include #define PERM_ALL -2 /** * The Virtual File class handles all the details of maintaining a single * file component within the virtual file system (vfs). a vfile object * contains the necessary details about a file and member functions which * allow the object to give out the needed details about the file. */ class vfile : public QObject { Q_OBJECT public: vfile() {} /** * Use this constructor when you know the following files properties: \n * file name, file size, file permissions,is the file a link,owner uid & group uid. */ vfile(const QString& name, const KIO::filesize_t size, const QString& perm, const time_t mtime, const bool symLink, const bool brokenLink, const uid_t owner, const gid_t group, const QString& mime, const QString& symDest, const mode_t mode, const int rwx = -1); vfile(const QString& name, const KIO::filesize_t size, const QString& perm, const time_t mtime, const bool symLink, const bool brokenLink, const QString& owner, const QString& group, const QString& userName, const QString& mime, const QString& symDest, const mode_t mode, const int rwx = -1, const QString& aclString = QString(), const QString& aclDfltString = QString()); bool operator==(const vfile& vf) const; vfile& operator= (const vfile& vf); inline bool operator!=(const vfile& vf) { return !((*this) == vf); } // following functions give-out file details inline const QString& vfile_getName() const { return vfile_name; } inline KIO::filesize_t vfile_getSize() const { return vfile_size; } inline const QString& vfile_getPerm() const { return vfile_perm; } inline bool vfile_isDir() const { return vfile_isdir; } inline bool vfile_isSymLink() const { return vfile_symLink; } inline bool vfile_isBrokenLink() const { return vfile_brokenLink; } inline const QString& vfile_getSymDest() const { return vfile_symDest; } inline mode_t vfile_getMode() const { return vfile_mode; } inline uid_t vfile_getUid() const { return vfile_ownerId; } inline gid_t vfile_getGid() const { return vfile_groupId; } inline time_t vfile_getTime_t() const { return vfile_time_t; } inline const QUrl& vfile_getUrl() const { return vfile_url; } const QString& vfile_getMime(bool fast = false); const QString& vfile_getOwner(); const QString& vfile_getGroup(); const QString& vfile_getACL(); const QString& vfile_getDefaultACL(); const KIO::UDSEntry vfile_getEntry(); //< return the UDSEntry from the vfile char vfile_isReadable() const; char vfile_isWriteable() const; char vfile_isExecutable() const; /** * Set the file size. * used ONLY when calculating a directory's space, needs to change the * displayed size of the viewitem and thus the vfile. For INTERNAL USE ! */ inline void vfile_setSize(KIO::filesize_t size) { vfile_size = size; } inline void vfile_setUrl(const QUrl &url) { vfile_url = url; } inline void vfile_setIcon(const QString& icn) { vfile_icon = icn; } QString vfile_getIcon(); virtual ~vfile() {} inline static void vfile_loadUserDefinedFolderIcons(bool load) { vfile_userDefinedFolderIcons = load; } inline static void vfile_enableMimeTypeMagic(bool enable) { vfile_useMimeTypeMagic = enable; } private: void vfile_loadACL(); protected: // the file information list QString vfile_name; //< file name KIO::filesize_t vfile_size; //< file size mode_t vfile_mode; //< file mode uid_t vfile_ownerId; //< file owner id gid_t vfile_groupId; //< file group id QString vfile_owner; //< file owner name QString vfile_group; //< file group name QString vfile_userName; //< the current username QString vfile_perm; //< file permissions string time_t vfile_time_t; //< file modification in time_t format bool vfile_symLink; //< true if the file is a symlink bool vfile_brokenLink; QString vfile_mimeType; //< file mimetype QString vfile_symDest; //< if it's a sym link - its detination QUrl vfile_url; //< file URL - empty by default QString vfile_icon; //< the name of the icon file bool vfile_isdir; //< flag, if it's a directory int vfile_rwx; //< flag, showing read, write, execute properties bool vfile_acl_loaded;// * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef _VFILECONTAINER_H__ #define _VFILECONTAINER_H__ -#include +// QtCore +#include class vfile; class VfileContainer : public QObject { Q_OBJECT public: VfileContainer(QObject *parent) : QObject(parent) {} virtual ~VfileContainer() {} virtual QList vfiles() = 0; virtual unsigned long numVfiles() = 0; virtual bool isRoot() = 0; signals: void startUpdate(); // emitted when the container has refreshed its list of vfiles. void addedVfile(vfile* vf); void deletedVfile(const QString& name); void updatedVfile(vfile* vf); void cleared(); }; #endif // _VFILECONTAINER_H__ diff --git a/krusader/VFS/vfs.cpp b/krusader/VFS/vfs.cpp index 75bd5bd6..85fc494c 100644 --- a/krusader/VFS/vfs.cpp +++ b/krusader/VFS/vfs.cpp @@ -1,409 +1,411 @@ /*************************************************************************** vfs.cpp ------------------- copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net ------------------------------------------------------------------------ the vfs class is an extendable class which by itself does (almost) nothing. other VFSs like the normal_vfs inherits from this class and make it possible to use a consistent API for all types of VFSs. *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "vfs.h" -#include -#include -#include -#include +// QtCore +#include +#include +#include +// QtWidgets +#include #include #include #include #include #include "../krglobal.h" #include "../defaults.h" #include "../MountMan/kmountman.h" #include "kiojobwrapper.h" vfs::vfs(QObject* panel, bool quiet) : VfileContainer(0), vfs_busy(false), quietMode(quiet), disableRefresh(false), postponedRefreshURL(), invalidated(true), panelConnected(false), vfs_tempFilesP(0), vfileIterator(0), deletePossible(true), deleteRequested(false) { setVfsFilesP(new vfileDict()); if (panel) { panelConnected = true; } else quietMode = true; } vfs::~vfs() { if (!deletePossible) fprintf(stderr, "INTERNAL ERROR: trying to delete vfs while it is used! This may cause crash. Hoping the best...\n"); clear(); // please don't remove this line. This informs the view about deleting the references delete vfs_filesP; delete vfs_tempFilesP; } bool vfs::isRoot() { QString protocol = vfs_getOrigin().scheme(); bool isFtp = (protocol == "ftp" || protocol == "smb" || protocol == "sftp" || protocol == "fish"); QString origin = vfs_getOrigin().toDisplayString(QUrl::StripTrailingSlash); if (origin.right(1) != "/" && !((vfs_getType() == vfs::VFS_FTP) && isFtp && origin.indexOf('/', origin.indexOf(":/") + 3) == -1)) return false; return true; } KIO::filesize_t vfs::vfs_totalSize() { KIO::filesize_t temp = 0; class vfile* vf = vfs_getFirstFile(); while (vf != 0) { if ((vf->vfile_getName() != ".") && (vf->vfile_getName() != "..") && !(vf->vfile_isDir())) temp += vf->vfile_getSize(); vf = vfs_getNextFile(); } return temp; } bool vfs::vfs_refresh(KJob* job) { if (job && job->error()) { if (job->uiDelegate()) job->uiDelegate()->showErrorMessage(); } return vfs_refresh(vfs_origin); } QUrl vfs::ensureTrailingSlash(const QUrl &url) { QUrl adjustedUrl = url; if (!adjustedUrl.path().endsWith('/')) { adjustedUrl.setPath(adjustedUrl.path() + '/'); } return adjustedUrl; } void vfs::setVfsFilesP(vfileDict* dict) { vfs_filesP = dict; vfs_tempFilesP = new vfileDict(); vfileIterator = vfs_filesP->begin(); } bool vfs::vfs_refresh() { if (vfs_busy) return false; if (invalidated) // invalidated fs requires total refresh return vfs_refresh(vfs_getOrigin()); if (disableRefresh) { postponedRefreshURL = vfs_getOrigin(); return false; } vfs_busy = true; // and populate it KConfigGroup ga(krConfig, "Advanced"); int maxIncrementalRefreshFileNr = ga.readEntry("Max Incremental Refresh File Nr", 50); KConfigGroup gl(krConfig, "Look&Feel"); bool showHidden = gl.readEntry("Show Hidden", _ShowHidden); bool res = populateVfsList(vfs_getOrigin(), showHidden); QString name; if (res) { // check if the maximum incremental refresh number is achieved int diff = vfs_filesP->count() - vfs_tempFilesP->count(); if (diff < 0) diff = -diff; if (diff >= maxIncrementalRefreshFileNr) { // total filesystem refresh is cheaper than incremental refresh for many files clear(); delete vfs_filesP; setVfsFilesP(vfs_tempFilesP); vfs_busy = false; emit startUpdate(); return true; } // compare the two list emiting signals when needed;; QList keys = vfs_filesP->keys(); foreach(const QString &name, keys) { vfile* vf = (*vfs_filesP)[name]; if (vf == 0) continue; vfile* newVf = (*vfs_tempFilesP)[name]; if (!newVf) { if (name != "..") { // the file was deleted.. emit deletedVfile(name); delete(*vfs_filesP)[ name ]; vfs_filesP->remove(name); } } else { if (*vf != *newVf) { // the file was changed.. *vf = *newVf; emit updatedVfile(vf); } } if ((*vfs_tempFilesP)[ name ]) delete(*vfs_tempFilesP)[ name ]; vfs_tempFilesP->remove(name); } // everything thats left is a new file QHashIterator it(*vfs_tempFilesP); while (it.hasNext()) { vfile *vf = it.next().value(); // sanity checking if (!vf || (*vfs_filesP)[vf->vfile_getName()]) continue; vfile* newVf = new vfile(); *newVf = *vf; vfs_filesP->insert(newVf->vfile_getName(), newVf); emit addedVfile(newVf); } } // delete the temporary vfiles vfs_tempFilesP->clear(); vfs_busy = false; emit incrementalRefreshFinished(vfs_origin); return res; } bool vfs::vfs_refresh(const QUrl &origin) { if (vfs_busy) return false; if (disableRefresh) { postponedRefreshURL = origin; if (!origin.matches(vfs_getOrigin(), QUrl::StripTrailingSlash)) invalidated = true; vfs_origin = origin; return true; } if (!invalidated && origin.matches(vfs_getOrigin(), QUrl::StripTrailingSlash)) return vfs_refresh(); vfs_busy = true; KConfigGroup group(krConfig, "Look&Feel"); bool showHidden = group.readEntry("Show Hidden", _ShowHidden); vfs_tempFilesP->clear(); // and re-populate it if (!populateVfsList(origin, showHidden)) { vfs_busy = false; return false; } clear(); delete vfs_filesP; setVfsFilesP(vfs_tempFilesP); vfs_busy = false; emit startUpdate(); invalidated = false; return true; } bool vfs::vfs_enableRefresh(bool enable) { if (vfs_type != VFS_NORMAL) return true; if (disableRefresh == !enable) return true; // if gets called twice by mistake disableRefresh = quietMode = !enable; bool res = true; if (enable && !postponedRefreshURL.isEmpty()) res = vfs_refresh(postponedRefreshURL); postponedRefreshURL = QUrl(); return res; } void vfs::clear() { emit cleared(); QHashIterator< QString, vfile *> lit(*vfs_filesP); while (lit.hasNext()) delete lit.next().value(); vfs_filesP->clear(); } bool vfs::vfs_processEvents() { if (deleteRequested) return false; deletePossible = false; qApp->processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents); deletePossible = true; if (deleteRequested) { emit deleteAllowed(); return false; } return true; } void vfs::vfs_requestDelete() { if (deletePossible) emit deleteAllowed(); deleteRequested = true; } void vfs::setMountMan(KMountMan *mtMan) { mountMan = mtMan; } /// to be implemented void vfs::slotKdsResult(KJob* job) { if (job && !job->error()) { KIO::DirectorySizeJob* kds = static_cast(job); *kds_totalSize += kds->totalSize(); *kds_totalFiles += kds->totalFiles(); *kds_totalDirs += kds->totalSubdirs(); } *kds_busy = true; } void vfs::vfs_calcSpace(QString name , KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop) { calculateURLSize(vfs_getFile(name), totalSize, totalFiles, totalDirs, stop); } void vfs::calculateURLSize(QUrl url, KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop) { if (stop && *stop) return ; kds_busy = stop; kds_totalSize = totalSize ; kds_totalFiles = totalFiles; kds_totalDirs = totalDirs; if (url.isLocalFile()) { vfs_calcSpaceLocal(url.adjusted(QUrl::StripTrailingSlash).path(), totalSize, totalFiles, totalDirs, stop); return; } else { stat_busy = true; KIOJobWrapper * statJob = KIOJobWrapper::stat(url); statJob->connectTo(SIGNAL(result(KJob*)), this, SLOT(slotStatResultArrived(KJob*))); statJob->start(); while (!(*stop) && stat_busy) { usleep(1000); } if (entry.count() == 0) return; // statJob failed KFileItem kfi(entry, url, true); if (kfi.isFile() || kfi.isLink()) { (*totalFiles)++; *totalSize += kfi.size(); return; } } KIOJobWrapper* kds = KIOJobWrapper::directorySize(url); kds->connectTo(SIGNAL(result(KJob*)), this, SLOT(slotKdsResult(KJob*))); kds->start(); while (!(*stop)) { // we are in a sepetate thread - so sleeping is OK usleep(1000); } } void vfs::vfs_calcSpaceLocal(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool* stop) { if (*stop) return; if (!name.contains("/")) name = vfs_workingDir() + '/' + name; if (name == "/proc") return; QT_STATBUF stat_p; // KDE lstat is necessary as QFileInfo and KFileItem // if the name is wrongly encoded, then we zero the size out stat_p.st_size = 0; stat_p.st_mode = 0; QT_LSTAT(name.toLocal8Bit(), &stat_p); // reports wrong size for a symbolic link if (S_ISLNK(stat_p.st_mode) || !S_ISDIR(stat_p.st_mode)) { // single files are easy : ) ++(*totalFiles); (*totalSize) += stat_p.st_size; } else { // handle directories // avoid a nasty crash on un-readable dirs bool readable = ::access(name.toLocal8Bit(), R_OK | X_OK) == 0; if (!readable) return; QDir dir(name); if (!dir.exists()) return; ++(*totalDirs); dir.setFilter(QDir::TypeMask | QDir::System | QDir::Hidden); dir.setSorting(QDir::Name | QDir::DirsFirst); // recurse on all the files in the directory QFileInfoList fileList = dir.entryInfoList(); for (int k = 0; k != fileList.size(); k++) { if (*stop) return; QFileInfo qfiP = fileList[ k ]; if (qfiP.fileName() != "." && qfiP.fileName() != "..") vfs_calcSpaceLocal(name + '/' + qfiP.fileName(), totalSize, totalFiles, totalDirs, stop); } } } void vfs::slotStatResultArrived(KJob* job) { if (!job || job->error()) entry = KIO::UDSEntry(); else entry = static_cast(job)->statResult(); stat_busy = false; } QList vfs::vfs_search(const KRQuery& filter) { QList result; for (vfile *vf = vfs_getFirstFile(); vf != 0 ; vf = vfs_getNextFile()) if (filter.match(vf)) result.append(vf); return result; } bool vfs::vfs_showHidden() { KConfigGroup gl(krConfig, "Look&Feel"); return gl.readEntry("Show Hidden", _ShowHidden); } diff --git a/krusader/VFS/vfs.h b/krusader/VFS/vfs.h index b3cb20e7..b06ac7c2 100644 --- a/krusader/VFS/vfs.h +++ b/krusader/VFS/vfs.h @@ -1,233 +1,235 @@ /*************************************************************************** vfs.h ------------------- begin : Thu May 4 2000 copyright : (C) 2000 by Shie Erlich & Rafi Yanai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef VFS_H #define VFS_H #include "vfilecontainer.h" -#include -#include -#include -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include +#include +#include +// QtWidgets +#include #include "vfile.h" #include "preservingcopyjob.h" #include "krquery.h" class KMountMan; /** * The vfs class is an extendable class which by itself does (almost) * nothing. other VFSs like the normal_vfs inherits from this class and * make it possible to use a consistent API for all types of VFSs. */ class vfs : public VfileContainer { Q_OBJECT public: typedef QHash vfileDict; enum VFS_TYPE {VFS_ERROR = 0, VFS_NORMAL, VFS_FTP, VFS_VIRT}; /** * Creates a vfs. * @param panel the panel father * @param quiet if true, the VFS will not display error messages */ vfs(QObject* panel, bool quiet = false); virtual ~vfs(); // VfileContainer implementation virtual QList vfiles() { return vfs_filesP->values(); } virtual unsigned long numVfiles() { return vfs_filesP->count(); } virtual bool isRoot(); /// Copy a file to the vfs (physical). virtual void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir = "", PreserveMode pmode = PM_DEFAULT) = 0; /// Remove a file from the vfs (physical) virtual void vfs_delFiles(const QStringList &fileNames, bool reallyDelete = false) = 0; /// Return a list of URLs for multiple files virtual QList vfs_getFiles(const QStringList &names) = 0; /// Return a URL to a single file, with no trailing slash virtual QUrl vfs_getFile(const QString& name) = 0; /// Create a new directory virtual void vfs_mkdir(const QString& name) = 0; /// Rename file virtual void vfs_rename(const QString& fileName, const QString& newName) = 0; /// Calculate the amount of space occupied by a file or directory (recursive). virtual void vfs_calcSpace(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop); /// Calculate the amount of space occupied by a local file or directory (recursive). virtual void vfs_calcSpaceLocal(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop); /// Return the VFS working dir virtual QString vfs_workingDir() = 0; /// Return true if the VFS url is writable virtual bool vfs_isWritable() { return isWritable; } /// Return vfile* or 0 if not found inline vfile* vfs_search(const QString& name) { return (*vfs_filesP)[name]; } /// Return an empty vfile* list if not found QList vfs_search(const KRQuery& filter); /// The total size of all the files in the VFS, KIO::filesize_t vfs_totalSize(); /// Returns the VFS url. inline QUrl vfs_getOrigin() { return vfs_origin; } /// Return the VFS type. inline VFS_TYPE vfs_getType() { return vfs_type; } /// Returns true if vfs is busy inline bool vfs_isBusy() { return vfs_busy; } /// Returns true if hidden files has to be shown bool vfs_showHidden(); /// Return the first file in the VFS and set the internal iterator to the beginning of the list. inline vfile* vfs_getFirstFile() { vfileIterator = vfs_filesP->begin(); return (vfileIterator == vfs_filesP->end() ? 0 : *vfileIterator); } /// Return the next file in the list and advance the iterator. inline vfile* vfs_getNextFile() { if (vfileIterator == vfs_filesP->end() || ++vfileIterator == vfs_filesP->end()) return 0; else return *vfileIterator; } /// returns true if the vfs can be deleted without crash virtual bool vfs_canDelete() { return deletePossible; } /// process the application events virtual bool vfs_processEvents(); /// process the application events virtual void vfs_requestDelete(); /// process the application events virtual bool vfs_isDeleting() { return deleteRequested; } virtual QString metaInformation() { return QString(); } // set the parent window to be used for dialogs void setParentWindow(QWidget *widget) { parentWindow = widget; } // set the mount manager void setMountMan(KMountMan *mtMan); static QUrl ensureTrailingSlash(const QUrl &url); public slots: /// Re-reads files and stats and fills the vfile list bool vfs_refresh(const QUrl &origin); /// Used to refresh the VFS when a job finishs. it calls the refresh() slot /// or display a error message if the job fails bool vfs_refresh(KJob * job); bool vfs_refresh(); void vfs_setQuiet(bool beQuiet) { quietMode = beQuiet; } bool vfs_enableRefresh(bool enable); void vfs_invalidate() { invalidated = true; } signals: void startJob(KIO::Job* job); void incrementalRefreshFinished(const QUrl&); //< emitted when the incremental refresh was finished void deleteAllowed(); void trashJobStarted(KIO::Job *job); void error(QString msg); protected: /// Feel the vfs dictionary with vfiles, must be implemented for each vfs virtual bool populateVfsList(const QUrl &origin, bool showHidden) = 0; /// Called by populateVfsList for each file void foundVfile(vfile *vf) { vfs_tempFilesP->insert(vf->vfile_getName(), vf); } /// Set the vfile list pointer void setVfsFilesP(vfileDict* dict); /// clear and delete all current vfiles inline void clear(); /// Add a new vfile to the list. inline void addToList(vfile *data) { vfs_filesP->insert(data->vfile_getName(), data); } /// Deletes a vfile from the list. inline void removeFromList(QString name) { vfs_filesP->remove(name); } /// Deletes a vfile from the list. void calculateURLSize(QUrl url, KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop); VFS_TYPE vfs_type; //< the vfs type. QUrl vfs_origin; //< the path or file the VFS originates from. bool vfs_busy; //< true if vfs is busy with refreshing bool quietMode; //< if true the vfs won't display error messages or emit signals bool disableRefresh; //< true if refresh is disabled bool isWritable; //< true if it's writable QUrl postponedRefreshURL; //< true if vfs_refresh() was called when refresh is disabled. bool invalidated; //< the content of the cache is invalidated bool panelConnected; //< indicates that there's a panel connected. Important for disabling the dir watcher QPointer parentWindow; QPointer mountMan; protected slots: /// The slot for the KIO::DirectorySizeJob void slotKdsResult(KJob *job); void slotStatResultArrived(KJob *job); private: vfileDict* vfs_filesP; //< Point to a lists of virtual files (vfile). vfileDict* vfs_tempFilesP;//< Temporary files are stored here QHash::iterator vfileIterator; //< Point to a dictionary of virtual files (vfile). // used in the calcSpace function bool* kds_busy; bool stat_busy; bool deletePossible; bool deleteRequested; KIO::UDSEntry entry; KIO::filesize_t* kds_totalSize; unsigned long* kds_totalFiles; unsigned long* kds_totalDirs; }; #endif diff --git a/krusader/VFS/virt_vfs.cpp b/krusader/VFS/virt_vfs.cpp index 64a372e3..7fcf84e0 100644 --- a/krusader/VFS/virt_vfs.cpp +++ b/krusader/VFS/virt_vfs.cpp @@ -1,373 +1,374 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #include "virt_vfs.h" -#include +// QtCore +#include #include #include #include #include #include #include #include #include "krpermhandler.h" #include "../krglobal.h" #include "../krservices.h" #include "../defaults.h" #define VIRT_VFS_DB "virt_vfs.db" QHash *> virt_vfs::virtVfsDict; QHash virt_vfs::metaInfoDict; KConfig* virt_vfs::virt_vfs_db = 0; virt_vfs::virt_vfs(QObject* panel, bool quiet) : vfs(panel, quiet) { // set the writable attribute isWritable = true; if (virtVfsDict.isEmpty()) { restore(); } vfs_type = VFS_VIRT; } virt_vfs::~virt_vfs() {} bool virt_vfs::populateVfsList(const QUrl &origin, bool /*showHidden*/) { vfs_origin = origin.adjusted(QUrl::StripTrailingSlash); path = origin.adjusted(QUrl::StripTrailingSlash).path().mid(1); if (path.isEmpty()) path = '/'; QList* urlList; if (virtVfsDict.find(path) == virtVfsDict.end()) { urlList = new QList(); virtVfsDict.insert(path, urlList); virtVfsDict[ "/" ] ->append(QUrl("virt:/" + path)); } else { urlList = virtVfsDict[ path ]; metaInfo = metaInfoDict[ path ]; } save(); if (urlList->isEmpty()) return true; QList::iterator it; for (it = urlList->begin() ; it != urlList->end() ; /*++it*/) { QUrl url = *it; // translate url->vfile and remove urls that no longer exist from the list vfile* vf = stat(url); if (!vf) { it = urlList->erase(it); // the iterator is advanced automatically continue; } foundVfile(vf); ++it; } return true; } void virt_vfs::vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode /*mode*/, QObject* /*toNotify*/, QString /*dir*/, PreserveMode /*pmode*/) { if (path == "/") { if (!quietMode) KMessageBox::error(parentWindow, i18n("You cannot copy files directly to the 'virt:/' folder.\nYou can create a sub folder and copy your files into it."), i18n("Error")); return ; } if (virtVfsDict.find(path) == virtVfsDict.end()) { QList *urlList = new QList(); virtVfsDict.insert(path, urlList); virtVfsDict[ "/" ] ->append(QUrl("virt:/" + path)); } QList* urlList = virtVfsDict[ path ]; foreach (const QUrl &fileUrl, fileUrls) { if (!urlList->contains(fileUrl)) urlList->push_back(fileUrl); } vfs_refresh(); } void virt_vfs::vfs_delFiles(const QStringList &fileNames, bool reallyDelete) { if (path == "/") { foreach (const QString &filename, fileNames) { virtVfsDict[ "/" ] ->removeAll(QUrl(QStringLiteral("virt:/") + filename)); delete virtVfsDict[ filename ]; virtVfsDict.remove(filename); metaInfoDict.remove(filename); } vfs_refresh(); return ; } // names -> urls QList filesUrls = vfs_getFiles(fileNames); KIO::Job *job; // delete of move to trash ? KConfigGroup group(krConfig, "General"); if (!reallyDelete && group.readEntry("Move To Trash", _MoveToTrash)) { job = KIO::trash(filesUrls); if(parentWindow) emit trashJobStarted(job); } else job = KIO::del(filesUrls); // refresh will remove the deleted files... connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } void virt_vfs::vfs_removeFiles(QStringList *fileNames) { if (path == "/") return; // removing the URLs from the collection for (int i = 0 ; i < fileNames->count(); ++i) { if (virtVfsDict.find(path) != virtVfsDict.end()) { QList* urlList = virtVfsDict[ path ]; urlList->removeAll(vfs_getFile((*fileNames)[ i ])); } } vfs_refresh(); } QList virt_vfs::vfs_getFiles(const QStringList &names) { QUrl url; QList urls; foreach (const QString &name, names) { urls.append(vfs_getFile(name)); } return urls; } QUrl virt_vfs::vfs_getFile(const QString& name) { vfile * vf = vfs_search(name); if (!vf) return QUrl(); // empty return vf->vfile_getUrl(); } void virt_vfs::vfs_mkdir(const QString& name) { if (path != "/") { if (!quietMode) KMessageBox::error(parentWindow, i18n("Creating new folders is allowed only in the 'virt:/' folder."), i18n("Error")); return ; } QList* temp = new QList(); virtVfsDict.insert(name, temp); virtVfsDict[ "/" ] ->append(QUrl(QStringLiteral("virt:/") + name)); vfs_refresh(); } void virt_vfs::vfs_rename(const QString& fileName, const QString& newName) { vfile* vf = vfs_search(fileName); if (!vf) return ; // not found if (path == "/") { virtVfsDict[ "/" ] ->append(QUrl(QStringLiteral("virt:/") + newName)); virtVfsDict[ "/" ] ->removeAll(QUrl(QStringLiteral("virt:/") + fileName)); virtVfsDict.insert(newName, virtVfsDict.take(fileName)); vfs_refresh(); return ; } QUrl url = vf->vfile_getUrl(); QList fileUrls; fileUrls.append(url); QUrl dest = url; // keep same url scheme and host as source. dest.setPath(newName); // add the new url to the list // the list is refreshed only existing files remain - // so we don't have to worry if the job was successful virtVfsDict[ path ] ->append(dest); KIO::Job *job = KIO::move(fileUrls, dest); connect(job, SIGNAL(result(KJob*)), this, SLOT(vfs_refresh(KJob*))); } void virt_vfs::slotStatResult(KJob* job) { if (!job || job->error()) entry = KIO::UDSEntry(); else entry = static_cast(job)->statResult(); busy = false; } vfile* virt_vfs::stat(const QUrl &url) { if (url.scheme() == "virt") { QString path = url.path().mid(1); if (path.isEmpty()) path = '/'; vfile * temp = new vfile(path, 0, "drwxr-xr-x", time(0), false, false, getuid(), getgid(), "inode/directory", "", 0); temp->vfile_setUrl(url); return temp; } KFileItem* kfi; if (url.isLocalFile()) { kfi = new KFileItem(url); kfi->setDelayedMimeTypes(true); } else { busy = true; KIO::StatJob* statJob = KIO::stat(url, KIO::HideProgressInfo); connect(statJob, SIGNAL(result(KJob*)), this, SLOT(slotStatResult(KJob*))); while (busy && vfs_processEvents()); if (entry.count() == 0) return 0; // statJob failed kfi = new KFileItem(entry, url, true); } if (kfi->time(KFileItem::ModificationTime).isNull()) { delete kfi; return 0; // file not found } vfile *temp; // get file statistics QString name; if (url.isLocalFile()) name = url.path(); else name = url.toDisplayString(); KIO::filesize_t size = kfi->size(); time_t mtime = kfi->time(KFileItem::ModificationTime).toTime_t(); bool symLink = kfi->isLink(); mode_t mode = kfi->mode() | kfi->permissions(); QString perm = KRpermHandler::mode2QString(mode); // set the mimetype QString mime; QString symDest; if (symLink) { symDest = kfi->linkDest(); if (kfi->isDir()) perm[ 0 ] = 'd'; } // create a new virtual file object if (kfi->user().isEmpty()) temp = new vfile(name, size, perm, mtime, symLink, false, getuid(), getgid(), mime, symDest, mode); else { QString currentUser = url.userName(); if (currentUser.contains("@")) /* remove the FTP proxy tags from the username */ currentUser.truncate(currentUser.indexOf('@')); if (currentUser.isEmpty()) currentUser = KRpermHandler::uid2user(getuid()); temp = new vfile(name, size, perm, mtime, symLink, false, kfi->user(), kfi->group(), currentUser, mime, symDest, mode); } temp->vfile_setUrl(kfi->url()); delete kfi; return temp; } KConfig* virt_vfs::getVirtDB() { if (!virt_vfs_db) { // virt_vfs_db = new KConfig("data",VIRT_VFS_DB,KConfig::NoGlobals); virt_vfs_db = new KConfig(VIRT_VFS_DB, KConfig:: CascadeConfig, QStandardPaths::DataLocation); } return virt_vfs_db; } bool virt_vfs::save() { KConfig* db = getVirtDB(); db->deleteGroup("virt_db"); KConfigGroup group(db, "virt_db"); QHashIterator< QString, QList *> lit(virtVfsDict); while (lit.hasNext()) { QList * curr = lit.next().value(); QList::iterator url; QStringList entry; for (url = curr->begin() ; url != curr->end() ; ++url) { entry.append((*url).toDisplayString()); } // KDE 4.0 workaround, Item_ is added as KConfig fails on 1 char names (such as /) group.writeEntry("Item_" + lit.key(), entry); group.writeEntry("MetaInfo_" + lit.key(), metaInfoDict[lit.key()]); } db->sync(); return true; } bool virt_vfs::restore() { KConfig* db = getVirtDB(); KConfigGroup dbGrp(db, "virt_db"); QMap map = db->entryMap("virt_db"); QMap::Iterator it; QList* urlList; for (it = map.begin(); it != map.end(); ++it) { if(!it.key().startsWith(QLatin1String("Item_"))) continue; urlList = new QList(KrServices::toUrlList(dbGrp.readEntry(it.key(), QStringList()))); // KDE 4.0 workaround, Item_ is removed (KConfig fails on 1 char names (such as /)) QString key = it.key().mid(5); // remove Item_ virtVfsDict.insert(key, urlList); metaInfoDict.insert(key, dbGrp.readEntry("MetaInfo_" + key, QString())); } if (!virtVfsDict["/" ]) { urlList = new QList(); virtVfsDict.insert("/", urlList); } return true; } void virt_vfs::vfs_calcSpace(QString name , KIO::filesize_t* totalSize, unsigned long* totalFiles, unsigned long* totalDirs, bool* stop) { if (stop && *stop) return ; if (path == "/") { QList* urlList = virtVfsDict[ name ]; if (urlList) for (int i = 0; (i != urlList->size()) && !(*stop); i++) calculateURLSize((*urlList)[ i ], totalSize, totalFiles, totalDirs, stop); return; } return vfs::vfs_calcSpace(name, totalSize, totalFiles, totalDirs, stop); } void virt_vfs::setMetaInformation(QString info) { metaInfo = info; metaInfoDict[path] = metaInfo; vfs_refresh(); } diff --git a/krusader/VFS/virt_vfs.h b/krusader/VFS/virt_vfs.h index 1058f57f..7147c847 100644 --- a/krusader/VFS/virt_vfs.h +++ b/krusader/VFS/virt_vfs.h @@ -1,86 +1,87 @@ /***************************************************************************** * Copyright (C) 2003 Shie Erlich * * Copyright (C) 2003 Rafi Yanai * * * * 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 package 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 package; if not, write to the Free Software * * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *****************************************************************************/ #ifndef VIRT_VFS_H #define VIRT_VFS_H -#include +// QtCore +#include #include #include "vfs.h" class virt_vfs : public vfs { Q_OBJECT public: virt_vfs(QObject* panel, bool quiet = false); ~virt_vfs(); /// Copy a file to the vfs (physical). void vfs_addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QObject* toNotify, QString dir = "", PreserveMode pmode = PM_DEFAULT) Q_DECL_OVERRIDE; /// Remove a file from the vfs (physical) void vfs_delFiles(const QStringList &fileNames, bool reallyDelete = true) Q_DECL_OVERRIDE; /// Remove a file from the collection (only its link, not the file) void vfs_removeFiles(QStringList *fileNames); /// Return a list of URLs for multiple files QList vfs_getFiles(const QStringList &names) Q_DECL_OVERRIDE; /// Return a URL to a single file QUrl vfs_getFile(const QString& name) Q_DECL_OVERRIDE; /// Create a new directory void vfs_mkdir(const QString& name) Q_DECL_OVERRIDE; /// Rename file void vfs_rename(const QString& fileName, const QString& newName) Q_DECL_OVERRIDE; /// Calculate the amount of space occupied by a file or directory (recursive). virtual void vfs_calcSpace(QString name , KIO::filesize_t *totalSize, unsigned long *totalFiles, unsigned long *totalDirs, bool * stop) Q_DECL_OVERRIDE; /// Return the VFS working dir QString vfs_workingDir() Q_DECL_OVERRIDE { return QString(); } virtual QString metaInformation() Q_DECL_OVERRIDE { return metaInfo; } void setMetaInformation(QString info); protected slots: void slotStatResult(KJob *job); protected: /// Save the dictionary to file bool save(); /// Restore the dictionary from file bool restore(); /// return the URLs DB KConfig* getVirtDB(); bool populateVfsList(const QUrl &origin, bool showHidden) Q_DECL_OVERRIDE; vfile* stat(const QUrl &url); static QHash *> virtVfsDict; static QHash metaInfoDict; static KConfig* virt_vfs_db; bool busy; QString path; QString metaInfo; KIO::UDSEntry entry; }; #endif diff --git a/krusader/VFS/virtualcopyjob.cpp b/krusader/VFS/virtualcopyjob.cpp index 58482a29..65c45a09 100644 --- a/krusader/VFS/virtualcopyjob.cpp +++ b/krusader/VFS/virtualcopyjob.cpp @@ -1,413 +1,414 @@ /*************************************************************************** virtualcopyjob.cpp - description ------------------- copyright : (C) 2006 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD S o u r c e F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #include "virtualcopyjob.h" #include "vfs.h" #include "vfile.h" -#include +// QtCore +#include #include #include #include #include #include #define REPORT_TIMEOUT 200 class MyUiDelegate : public KIO::JobUiDelegate { public: MyUiDelegate(VirtualCopyJob * ref) : KIO::JobUiDelegate(), copyJobRef(ref) {} virtual KIO::RenameDialog_Result askFileRename(KJob * job, const QString & caption, const QUrl& src, const QUrl & dest, KIO::RenameDialog_Options mode, QString& newDest, KIO::filesize_t sizeSrc = (KIO::filesize_t) - 1, KIO::filesize_t sizeDest = (KIO::filesize_t) - 1, const QDateTime &ctimeSrc = QDateTime(), const QDateTime &ctimeDest = QDateTime(), const QDateTime &mtimeSrc = QDateTime(), const QDateTime &mtimeDest = QDateTime()) Q_DECL_OVERRIDE { if (copyJobRef->isSkipAll()) { if (mode & KIO::M_MULTI) return KIO::R_AUTO_SKIP; else return KIO::R_SKIP; } if (copyJobRef->isOverwriteAll()) { if (mode & KIO::M_MULTI) return KIO::R_OVERWRITE_ALL; else return KIO::R_OVERWRITE; } KIO::RenameDialog_Mode mmode = (KIO::RenameDialog_Mode)0; if (copyJobRef->isMulti()) mmode = (KIO::RenameDialog_Mode)(mmode | KIO::M_MULTI | KIO::M_SKIP); else mmode = (KIO::RenameDialog_Mode)(mmode /*| KIO::M_SINGLE*/); if (mode & KIO::M_OVERWRITE) mmode = (KIO::RenameDialog_Mode)(mmode | KIO::M_OVERWRITE); if (mode & KIO::M_OVERWRITE_ITSELF) mmode = (KIO::RenameDialog_Mode)(mmode | KIO::M_OVERWRITE_ITSELF); KIO::RenameDialog_Result res = KIO::JobUiDelegate::askFileRename(job, caption, src, dest, mode, newDest, sizeSrc, sizeDest, ctimeSrc, ctimeDest, mtimeSrc, mtimeDest); if (res == KIO::R_AUTO_SKIP) { copyJobRef->setSkipAll(); if (!(mode & KIO::M_MULTI)) res = KIO::R_SKIP; } if (res == KIO::R_OVERWRITE_ALL) { copyJobRef->setOverwriteAll(); if (!(mode & KIO::M_MULTI)) res = KIO::R_OVERWRITE; } return res; } virtual KIO::SkipDialog_Result askSkip(KJob * job, KIO::SkipDialog_Options options, const QString & error_text) Q_DECL_OVERRIDE { if (copyJobRef->isSkipAll()) { if (options & KIO::SkipDialog_MultipleItems) return KIO::S_AUTO_SKIP; else return KIO::S_SKIP; } KIO::SkipDialog_Result res = KIO::JobUiDelegate::askSkip(job, copyJobRef->isMulti() ? KIO::SkipDialog_MultipleItems: (KIO::SkipDialog_Option)0, error_text); if (res == KIO::S_AUTO_SKIP) { copyJobRef->setSkipAll(); if (!(options & KIO::SkipDialog_MultipleItems)) res = KIO::S_SKIP; } return res; } private: VirtualCopyJob * copyJobRef; }; VirtualCopyJob::VirtualCopyJob(const QStringList *names, vfs * vfs, const QUrl &dest, const QUrl& baseURL, PreserveMode pmode, KIO::CopyJob::CopyMode mode, bool showProgressInfo, bool autoStart) : KIO::Job(), m_overwriteAll(false), m_skipAll(false), m_multi(false), m_totalSize(0), m_totalFiles(0), m_totalSubdirs(0), m_processedSize(0), m_processedFiles(0), m_processedSubdirs(0), m_tempSize(0), m_tempFiles(0), m_dirsToGetSize(), m_filesToCopy(), m_size(), m_filenum(), m_subdirs(), m_baseURL(baseURL), m_dest(dest), m_pmode(pmode), m_mode(mode), m_showProgressInfo(showProgressInfo), m_state(ST_STARTING), m_reportTimer(), m_current(), m_currentDir(), m_dirStack() { m_dest = vfs->ensureTrailingSlash(m_dest); vfile * file = vfs->vfs_getFirstFile(); while (file) { if (names->contains(file->vfile_getName())) { QString relativeDir = QDir(baseURL.path()).relativeFilePath(KIO::upUrl(file->vfile_getUrl()).path()); if (m_filesToCopy.find(relativeDir) == m_filesToCopy.end()) { m_filesToCopy.insert(relativeDir, new QList()); // initialize the dir content m_size[ relativeDir ] = 0; m_filenum[ relativeDir ] = 0; m_subdirs[ relativeDir ] = 0; } QList *list = m_filesToCopy[ relativeDir ]; if (!list->contains(file->vfile_getUrl())) { if (file->vfile_isDir()) { m_dirsToGetSize.append(file->vfile_getUrl()); m_totalSubdirs++; m_subdirs[ relativeDir ]++; } else { m_totalFiles++; m_filenum[ relativeDir ]++; m_totalSize += file->vfile_getSize(); m_size[ relativeDir ] += file->vfile_getSize(); } list->append(file->vfile_getUrl()); } } file = vfs->vfs_getNextFile(); } if (showProgressInfo) { setUiDelegate(new MyUiDelegate(this)); KIO::getJobTracker()->registerJob(this); } if (autoStart) QTimer::singleShot(0, this, SLOT(slotStart())); } VirtualCopyJob::~VirtualCopyJob() { QHashIterator< QString, QList *> lit(m_filesToCopy); while (lit.hasNext()) delete lit.next().value(); } void VirtualCopyJob::slotStart() { connect(&m_reportTimer, SIGNAL(timeout()), this, SLOT(slotReport())); m_reportTimer.setSingleShot(false); m_reportTimer.start(REPORT_TIMEOUT); statNextDir(); } void VirtualCopyJob::slotReport() { switch (m_state) { case ST_CREATING_DIRECTORY: break; case ST_CALCULATING_TOTAL_SIZE: setTotalAmount(KJob::Bytes, m_totalSize); setTotalAmount(KJob::Directories, m_totalSubdirs); setTotalAmount(KJob::Files, m_totalFiles); break; case ST_COPYING: { setProcessedAmount(KJob::Directories, m_processedSubdirs); setProcessedAmount(KJob::Files, m_processedFiles + m_tempFiles); setProcessedAmount(KJob::Bytes, m_processedSize + m_tempSize); double percDbl = ((double)(m_processedSize + m_tempSize) / (double)m_totalSize) * 100. + 0.5; unsigned long perc = (long)percDbl; if (perc > 100) perc = 100; setPercent(perc); break; } default: break; } } void VirtualCopyJob::statNextDir() { m_state = ST_CALCULATING_TOTAL_SIZE; if (m_dirsToGetSize.count() == 0) { slotReport(); // report the total size values createNextDir(); return; } QUrl dirToCheck = m_dirsToGetSize.first(); m_dirsToGetSize.pop_front(); m_currentDir = QDir(m_baseURL.path()).relativeFilePath(KIO::upUrl(dirToCheck).path()); KIO::DirectorySizeJob* kds = KIO::directorySize(dirToCheck); connect(kds, SIGNAL(result(KJob*)), this, SLOT(slotKdsResult(KJob*))); } void VirtualCopyJob::slotKdsResult(KJob * job) { KIO::DirectorySizeJob* kds = static_cast(job); m_totalSize += kds->totalSize(); m_totalFiles += kds->totalFiles(); m_totalSubdirs += kds->totalSubdirs(); m_size[ m_currentDir ] += kds->totalSize(); m_filenum[ m_currentDir ] += kds->totalFiles(); m_subdirs[ m_currentDir ] += kds->totalSubdirs(); statNextDir(); } void VirtualCopyJob::createNextDir() { m_state = ST_CREATING_DIRECTORY; if (m_totalFiles + m_totalSubdirs > 1) m_multi = true; QHashIterator *> diter(m_filesToCopy); if (!diter.hasNext()) { emitResult(); return; } m_currentDir = diter.next().key(); m_current = m_dest; if (m_currentDir != "./" && !m_currentDir.isEmpty()) { m_current = m_current.adjusted(QUrl::StripTrailingSlash); m_current.setPath(m_current.path() + '/' + (m_currentDir)); } KIO::Job *job = KIO::stat(m_current, KIO::HideProgressInfo); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotStatResult(KJob*))); } void VirtualCopyJob::slotStatResult(KJob *job) { QUrl url = (static_cast(job))->url(); if (job && job->error()) { if (job->error() == KIO::ERR_DOES_NOT_EXIST && !url.matches(KIO::upUrl(url), QUrl::StripTrailingSlash)) { m_dirStack.push_back(url.fileName()); KIO::Job *job = KIO::stat(KIO::upUrl(url), KIO::HideProgressInfo); connect(job, SIGNAL(result(KJob*)), this, SLOT(slotStatResult(KJob*))); return; } job->uiDelegate()->showErrorMessage(); directoryFinished(m_currentDir); createNextDir(); return; } if (m_dirStack.count()) { url.setPath(vfs::ensureTrailingSlash(url).path() + m_dirStack.last()); m_dirStack.pop_back(); KIO::Job *mkdir_job = KIO::mkdir(url); connect(mkdir_job, SIGNAL(result(KJob*)), this, SLOT(slotMkdirResult(KJob*))); } else copyCurrentDir(); } void VirtualCopyJob::slotMkdirResult(KJob *job) { QUrl url = (static_cast(job))->url(); if (job && job->error()) { if (uiDelegate() && !m_skipAll) { KIO::JobUiDelegate *ui = static_cast(uiDelegate()); KIO::SkipDialog_Result skipResult = ui->askSkip(this, m_multi ? KIO::SkipDialog_MultipleItems: (KIO::SkipDialog_Option)0, job->errorString()); switch (skipResult) { case KIO::S_CANCEL: setError(KIO::ERR_USER_CANCELED); emitResult(); return; case KIO::S_AUTO_SKIP: m_skipAll = true; break; case KIO::S_SKIP: default: break; } } directoryFinished(m_currentDir); createNextDir(); return; } if (m_dirStack.count()) { url.setPath(vfs::ensureTrailingSlash(url).path() + m_dirStack.last()); m_dirStack.pop_back(); KIO::Job *mkdir_job = KIO::mkdir(url); connect(mkdir_job, SIGNAL(result(KJob*)), this, SLOT(slotMkdirResult(KJob*))); } else copyCurrentDir(); } void VirtualCopyJob::copyCurrentDir() { m_state = ST_COPYING; KIO::Job * copy_job = PreservingCopyJob::createCopyJob(m_pmode, *m_filesToCopy[ m_currentDir ], m_current, m_mode, false, false); copy_job->setParentJob(this); copy_job->setUiDelegate(new MyUiDelegate(this)); connect(copy_job, SIGNAL(copying(KIO::Job *, const QUrl &, const QUrl &)), this, SLOT(slotCopying(KIO::Job *, const QUrl &, const QUrl &))); connect(copy_job, SIGNAL(moving(KIO::Job *, const QUrl &, const QUrl &)), this, SLOT(slotMoving(KIO::Job *, const QUrl &, const QUrl &))); connect(copy_job, SIGNAL(processedFiles(KIO::Job *, unsigned long)), this, SLOT(slotProcessedFiles(KIO::Job *, unsigned long))); connect(copy_job, SIGNAL(processedSize(KJob *, qulonglong)), this, SLOT(slotProcessedSize(KJob *, qulonglong))); connect(copy_job, SIGNAL(result(KJob*)), this, SLOT(slotCopyResult(KJob*))); } void VirtualCopyJob::slotCopyResult(KJob *job) { if (job && job->error()) { setError(job->error()); setErrorText(job->errorText()); if (job->error() == KIO::ERR_USER_CANCELED) { emitResult(); return; } if (uiDelegate()) uiDelegate()->showErrorMessage(); setError(0); } directoryFinished(m_currentDir); createNextDir(); } void VirtualCopyJob::directoryFinished(const QString &name) { delete m_filesToCopy[ name ]; m_filesToCopy.remove(name); m_processedSize += m_size[ name ]; m_processedFiles += m_filenum[ name ]; m_processedSubdirs += m_subdirs[ name ]; m_tempSize = m_tempFiles = 0; m_size.remove(name); m_filenum.remove(name); m_subdirs.remove(name); } void VirtualCopyJob::slotCopying(KIO::Job *, const QUrl &src, const QUrl &dest) { emit description(this, i18nc("@title job", "Copying"), qMakePair(i18n("Source"), src.toDisplayString()), qMakePair(i18n("Destination"), dest.toDisplayString())); } void VirtualCopyJob::slotMoving(KIO::Job *, const QUrl &src, const QUrl &dest) { emit description(this, i18nc("@title job", "Moving"), qMakePair(i18n("Source"), src.toDisplayString()), qMakePair(i18n("Destination"), dest.toDisplayString())); } void VirtualCopyJob::slotProcessedFiles(KIO::Job *, unsigned long filenum) { m_tempFiles = filenum; } void VirtualCopyJob::slotProcessedSize(KJob *, qulonglong size) { m_tempSize = size; } diff --git a/krusader/VFS/virtualcopyjob.h b/krusader/VFS/virtualcopyjob.h index 4ab9568a..510aefcc 100644 --- a/krusader/VFS/virtualcopyjob.h +++ b/krusader/VFS/virtualcopyjob.h @@ -1,147 +1,148 @@ /*************************************************************************** virtualcopyjob.h - description ------------------- copyright : (C) 2006 + by Csaba Karai e-mail : krusader@users.sourceforge.net web site : http://krusader.sourceforge.net --------------------------------------------------------------------------- Description *************************************************************************** A db dD d8888b. db db .d8888. .d8b. d8888b. d88888b d8888b. 88 ,8P' 88 `8D 88 88 88' YP d8' `8b 88 `8D 88' 88 `8D 88,8P 88oobY' 88 88 `8bo. 88ooo88 88 88 88ooooo 88oobY' 88`8b 88`8b 88 88 `Y8b. 88~~~88 88 88 88~~~~~ 88`8b 88 `88. 88 `88. 88b d88 db 8D 88 88 88 .8D 88. 88 `88. YP YD 88 YD ~Y8888P' `8888Y' YP YP Y8888D' Y88888P 88 YD H e a d e r F i l e *************************************************************************** * * * 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. * * * ***************************************************************************/ #ifndef VIRTUALCOPYJOB_H #define VIRTUALCOPYJOB_H -#include -#include -#include -#include +// QtCore +#include +#include +#include +#include #include #include "preservingcopyjob.h" class vfs; typedef enum { ST_STARTING = 0, ST_CALCULATING_TOTAL_SIZE = 1, ST_CREATING_DIRECTORY = 2, ST_COPYING = 3 } State; class VirtualCopyJob : public KIO::Job { Q_OBJECT public: VirtualCopyJob(const QStringList *names, vfs * vfs, const QUrl &dest, const QUrl& baseURL, PreserveMode pmode, KIO::CopyJob::CopyMode mode, bool showProgressInfo, bool autoStart = true); virtual ~VirtualCopyJob(); inline bool isSkipAll() { return m_skipAll; } inline void setSkipAll() { m_skipAll = true; } inline bool isOverwriteAll() { return m_overwriteAll; } inline void setOverwriteAll() { m_overwriteAll = true; } inline bool isMulti() { return m_multi; } protected: void statNextDir(); void createNextDir(); void copyCurrentDir(); void directoryFinished(const QString &); public slots: void slotStart(); protected slots: void slotReport(); void slotKdsResult(KJob *); void slotStatResult(KJob *); void slotMkdirResult(KJob *); void slotCopyResult(KJob *); void slotCopying(KIO::Job *, const QUrl &, const QUrl &); void slotMoving(KIO::Job *, const QUrl &, const QUrl &); void slotProcessedFiles(KIO::Job *, unsigned long); void slotProcessedSize(KJob *, qulonglong); signals: void totalFiles(KIO::Job *job, unsigned long files); void totalDirs(KIO::Job *job, unsigned long dirs); void processedFiles(KIO::Job *job, unsigned long files); void processedDirs(KIO::Job *job, unsigned long dirs); private: bool m_overwriteAll; bool m_skipAll; bool m_multi; KIO::filesize_t m_totalSize; unsigned long m_totalFiles; unsigned long m_totalSubdirs; qulonglong m_processedSize; unsigned long m_processedFiles; unsigned long m_processedSubdirs; qulonglong m_tempSize; unsigned long m_tempFiles; QList m_dirsToGetSize; QHash *> m_filesToCopy; QMap m_size; QMap m_filenum; QMap m_subdirs; QUrl m_baseURL; QUrl m_dest; PreserveMode m_pmode; KIO::CopyJob::CopyMode m_mode; bool m_showProgressInfo; State m_state; QTimer m_reportTimer; QUrl m_current; QString m_currentDir; QStringList m_dirStack; }; #endif /* __VIRTUAL_COPY_JOB_H__ */