Sandboxie/SandboxiePlus/MiscHelpers/Archive/ArchiveFS.cpp

289 lines
6.0 KiB
C++

#include "stdafx.h"
#include "ArchiveFS.h"
#include "../Common/Common.h"
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngineIterator
//
class C7zFileEngineIterator : public QAbstractFileEngineIterator
{
public:
C7zFileEngineIterator(QDir::Filters filters, const QStringList& filterNames,
const QStringList& allEntries)
: QAbstractFileEngineIterator(filters, filterNames), entries(allEntries), index(0) {}
~C7zFileEngineIterator() {}
QString next() override
{
if (!hasNext())
return QString();
++index;
return currentFilePath();
}
bool hasNext() const override
{
return index < entries.size();
}
QString currentFileName() const override
{
if (index <= 0 || index > entries.size())
return QString();
return entries.at(index - 1);
}
private:
mutable QStringList entries;
mutable int index;
};
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngine
//
//QAtomicInt g_7zFileEngineCount;
C7zFileEngine::C7zFileEngine(const QString& filename, CArchive* pArchive, QMutex* pMutex)
: _flags(0), _size(0), _pos(0), _pArchive(pArchive), _pMutex(pMutex)
{
//g_7zFileEngineCount++;
setFileName(filename);
}
C7zFileEngine::~C7zFileEngine()
{
close();
//g_7zFileEngineCount--;
//qDebug() << "g_7zFileEngineCount" << g_7zFileEngineCount;
}
bool C7zFileEngine::open(QIODevice::OpenMode openMode)
{
close();
//if (openMode & QIODevice::WriteOnly) {
//
//} else
if (openMode & QIODevice::ReadOnly) {
QMutexLocker Lock(_pMutex);
QMap<int, QIODevice*> Files;
Files.insert(_index, new QBuffer(&_data));
_pArchive->Extract(&Files);
_size = _data.size();
_pos = 0;
} else
//if (openMode & QIODevice::Append) {
//
//} else
{
qWarning("Bad file open mode: %d", (int)openMode);
return false;
}
return true;
}
bool C7zFileEngine::close()
{
if (!isOpened())
return false;
_data.clear();
_size = 0;
_pos = 0;
return true;
}
bool C7zFileEngine::flush()
{
return true;
}
qint64 C7zFileEngine::size() const
{
return _size;
}
qint64 C7zFileEngine::pos() const
{
return _pos;
}
bool C7zFileEngine::seek(qint64 pos)
{
_pos = pos;
return true;
}
bool C7zFileEngine::isSequential() const
{
return false;
}
bool C7zFileEngine::remove()
{
return false;
}
bool C7zFileEngine::mkdir(const QString& dirName, bool createParentDirectories) const
{
return false;
}
bool C7zFileEngine::rmdir(const QString& dirName, bool recurseParentDirectories) const
{
return false;
}
bool C7zFileEngine::caseSensitive() const
{
return false;
}
bool C7zFileEngine::isRelativePath() const
{
return false;
}
QAbstractFileEngine::Iterator *C7zFileEngine::beginEntryList(QDir::Filters filters, const QStringList &filterNames)
{
QMutexLocker Lock(_pMutex);
QStringList allEntries;
for (int i = 0; i < _pArchive->FileCount(); i++) {
QString Path = _pArchive->FileProperty(i, "Path").toString();
if (!_filename.isEmpty()) {
if (!Path.startsWith(_filename))
continue;
Path = Path.mid(_filename.length() + 1);
}
if (!Path.isEmpty() && !Path.contains("\\"))
allEntries.append(Path);
}
return new C7zFileEngineIterator(filters, filterNames, allEntries);
}
QAbstractFileEngine::FileFlags C7zFileEngine::fileFlags(FileFlags type) const
{
return type & _flags;
}
QString C7zFileEngine::fileName(FileName file) const
{
return _filename;
}
QDateTime C7zFileEngine::fileTime(FileTime time) const
{
switch (time)
{
case QAbstractFileEngine::ModificationTime:
default:
return _datetime;
break;
};
}
void C7zFileEngine::setFileName(const QString& file)
{
int pos = file.indexOf(":") + 2;
_filename = file.mid(pos);
if (_filename.isEmpty()) { // root
_flags = ExistsFlag | DirectoryType | ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm;
return;
}
QMutexLocker Lock(_pMutex);
_index = _pArchive->FindByPath(_filename);
if (_index != -1) {
_flags = ExistsFlag | ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm;
if (_pArchive->FileProperty(_index, "IsDir").toBool())
_flags |= DirectoryType;
else
_flags |= FileType;
}
}
bool C7zFileEngine::atEnd() const
{
return _pos >= _data.size();
}
qint64 C7zFileEngine::read(char* data, qint64 maxlen)
{
qint64 togo = qMin(maxlen, _size - _pos);
if (togo > 0) {
memcpy(data, _data.constData() + _pos, togo);
_pos += togo;
}
return togo;
}
qint64 C7zFileEngine::readLine(char* data, qint64 maxlen)
{
return -1; // todo
}
qint64 C7zFileEngine::write(const char* data, qint64 len)
{
return -1;
}
bool C7zFileEngine::isOpened() const
{
return _size != 0;
}
QFile::FileError C7zFileEngine::error() const
{
return QFile::UnspecifiedError;
}
QString C7zFileEngine::errorString() const
{
return "";
}
bool C7zFileEngine::supportsExtension(Extension extension) const
{
return extension == QAbstractFileEngine::AtEndExtension;
}
//////////////////////////////////////////////////////////////////////////////////////////
// C7zFileEngineHandler
//
C7zFileEngineHandler::C7zFileEngineHandler(const QString& ArchivePath, const QString& Scheme, QObject* parent)
: QObject(parent), m_pArchive(NULL)
{
CArchive* pArchive = new CArchive(ArchivePath);
if (pArchive->Open() > 0)
m_pArchive = pArchive;
else
delete pArchive;
m_Scheme = Scheme + ":";
}
C7zFileEngineHandler::~C7zFileEngineHandler()
{
delete m_pArchive;
}
QAbstractFileEngine* C7zFileEngineHandler::create(const QString& filename) const
{
if (m_pArchive && filename.startsWith(m_Scheme))
return new C7zFileEngine(filename, m_pArchive, &m_Mutex);
return NULL;
}