Sandboxie/SandboxiePlus/MiscHelpers/Archive/ArchiveThread.cpp

420 lines
11 KiB
C++
Raw Permalink Normal View History

2022-11-12 09:45:35 +00:00
#include "stdafx.h"
#include "ArchiveThread.h"
#include "SplitFile.h"
#include "../Common/Common.h"
#include "../Common/OtherFunctions.h"
int _QStringList_pType = qRegisterMetaType<QStringList>("QStringList");
CArchiveThread::CArchiveThread(const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QStringList& Parts)
{
#ifdef USE_7Z
m_Worker = new C7zWorker(ArchivePath, WorkingPath, Password, PartSize, Parts);
m_Worker->moveToThread(this);
start();
m_Worker->m_Lock.Lock();
#else
ASSERT(0);
#endif
}
CArchiveThread::CArchiveThread(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QString &CommentPath)
{
m_Worker = new CRarWorker(WinRarPath, ArchivePath, WorkingPath, Password, PartSize, CommentPath);
m_Worker->moveToThread(this);
start();
m_Worker->m_Lock.Lock();
}
void CArchiveThread::Terminate()
{
stop();
delete m_Worker;
delete this;
}
QStringList CArchiveThread::ListParts(const QString &ArchivePath, bool NamesOnly)
{
QStringList Parts;
StrPair PathName = Split2(ArchivePath, "/", true);
StrPair NameEx = Split2(PathName.second, ".", true);
QString PatternStr;
if(NameEx.second == "rar")
PatternStr = QRegularExpression::escape(NameEx.first) + "(\\.part[0-9]*)?\\.rar";
else
PatternStr = QRegularExpression::escape(NameEx.first + "." + NameEx.second) + "(\\.[0-9]*)?";
QRegularExpression Pattern = QRegularExpression(QRegularExpression::anchoredPattern(PatternStr), QRegularExpression::CaseInsensitiveOption);
QDir Dir(PathName.first);
foreach (const QString& File, Dir.entryList())
{
if (File.compare(".") == 0 || File.compare("..") == 0)
continue;
QRegularExpressionMatch Result = Pattern.match(File);
if(Result.hasMatch())
{
if(NamesOnly)
Parts.append(File);
else
Parts.append(PathName.first + "/" + File);
}
}
return Parts;
}
QStringList CArchiveThread::GetErrors()
{
QStringList Errors;
if(IsBusy())
return Errors;
Errors = m_Worker->m_Errors;
if(!Errors.isEmpty() && HasUsedPassword())
Errors.append("Wrong Password ?");
m_Worker->m_Errors.clear();
return Errors;
}
//////////////////////////////////////////////////////////////////////////
2024-03-10 08:01:02 +00:00
// Building 7z Library worker
2022-11-12 09:45:35 +00:00
//
#ifdef USE_7Z
C7zWorker::C7zWorker(const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QStringList& Parts)
: CArchive(ArchivePath)
{
SetPassword(Password);
SetPartSize(PartSize);
m_WorkingPath = WorkingPath;
SetPartList(Parts);
if(QFile::exists(ArchivePath))
{
2023-07-31 20:20:29 +01:00
if(Open() != ERR_7Z_OK)
2022-11-12 09:45:35 +00:00
m_Errors.append("Open Failed");
}
}
C7zWorker::~C7zWorker()
{
Close();
}
QMap<QString, quint64> C7zWorker::GetFileList()
{
QMap<QString, quint64> FileList;
if(!m_Mutex.tryLock(100))
{
2023-08-06 19:14:29 +01:00
//LogLine(LOG_DEBUG | LOG_ERROR, tr("attempted to get the file list of an already busy archive thread"));
2022-11-12 09:45:35 +00:00
return FileList;
}
if(m_Archive)
{
foreach(const SFile& File, m_Files)
{
if(File.Properties["IsDir"].toBool())
continue;
FileList.insert(File.Properties["Path"].toString(), File.Properties["Size"].toULongLong());
}
}
//else
//LogLine(LOG_DEBUG | LOG_ERROR, tr("Archive %1, is not open for extraction").arg(m_ArchivePath));
m_Mutex.unlock();
return FileList;
}
void C7zWorker::OnExtractAllFiles()
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
SArcInfo Info = GetArcInfo(m_ArchivePath);
2022-12-07 16:32:40 +00:00
if(Info.FormatIndex == 0) // not an archive just a split file
2022-11-12 09:45:35 +00:00
{
if(!QDir().exists(m_WorkingPath))
QDir().mkpath(m_WorkingPath);
if(Info.PartNumber == -1) // single aprt
{
if(!QFile::rename(m_ArchivePath,m_WorkingPath + Info.FileName))
m_Errors.append("Failed to move file");
}
else // multi part, to be merged
{
int Pos = m_ArchivePath.indexOf(QRegularExpression("\\.[0-9]+$"));
if(Pos != -1)
m_ArchivePath.truncate(Pos);
CSplitFile SplitFile(m_ArchivePath);
if(!SplitFile.open(QIODevice::ReadOnly))
m_Errors.append("Failed to open temp file");
else
{
QFile File(m_WorkingPath + Info.FileName);
if(!File.open(QIODevice::WriteOnly))
m_Errors.append("Failed to open file");
else
{
const qint64 Size = 16*1024;
char Buffer[Size];
while(!SplitFile.atEnd())
{
qint64 Temp = SplitFile.read(Buffer, Size);
File.write(Buffer, Temp);
}
}
}
}
}
else
if(!Extract(m_WorkingPath))
m_Errors.append("Extraction Failed");
}
void C7zWorker::OnInsertAllFiles()
{
OnInsertFiles(ListDir(m_WorkingPath));
}
void C7zWorker::OnExtractFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
if(!QDir().exists(m_WorkingPath))
QDir().mkpath(m_WorkingPath);
QMap<int, QIODevice*> Files;
foreach(const QString& Name, FileList)
{
int ArcIndex = FindByPath(Name);
if(ArcIndex != -1)
Files.insert(ArcIndex, new QFile(PrepareExtraction(Name, m_WorkingPath)));
//else
//LogLine(LOG_DEBUG, tr("file %1 couldn't be find in archive %2").arg(Name, m_ArchivePath)); // should not happen
}
if(!Extract(&Files))
m_Errors.append("Extraction Failed");
}
void C7zWorker::OnInsertFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QMap<int, QIODevice*> Files;
foreach(const QString& File, FileList)
{
StrPair RootName = Split2(File, "\\", true);
if(RootName.second.isEmpty())
{
RootName.second = RootName.first;
RootName.first = "";
}
int ArcIndex = AddFile(RootName.second);
if(ArcIndex != -1)
{
QString FileName = (RootName.first.isEmpty() ? m_WorkingPath : RootName.first) + RootName.second;
Files.insert(ArcIndex, new QFile(FileName));
}
//else
//LogLine(LOG_DEBUG, tr("file %1 is already present in archive %2").arg(RootName.second, m_ArchivePath)); // should not happen
}
if(!Update(&Files))
m_Errors.append("Insertion Failed");
}
#endif
//////////////////////////////////////////////////////////////////////////
// Extern WinRar worker
//
CRarWorker::CRarWorker(const QString &WinRarPath, const QString &ArchivePath, const QString &WorkingPath, const QString &Password, quint64 PartSize, const QString &CommentPath)
{
m_WinRarPath = WinRarPath;
if(CommentPath.contains(" "))
m_CommentPath = "\"" + CommentPath + "\"";
else
m_CommentPath = CommentPath;
m_ArchivePath = ArchivePath;
m_WorkingPath = WorkingPath;
CreateDir(m_WorkingPath);
m_Password = Password;
m_PartSize = PartSize;
if(!QFile::exists(WinRarPath + "rar.exe"))
m_Errors.append("WinRar is not present or the path is wrong");
}
QMap<QString, quint64> CRarWorker::GetFileList()
{
QMap<QString, quint64> FileList;
if(!m_Mutex.tryLock(100))
{
2023-08-06 19:14:29 +01:00
//LogLine(LOG_DEBUG | LOG_ERROR, tr("attempted to get the file list of an already busy archive thread"));
2022-11-12 09:45:35 +00:00
return FileList;
}
QStringList Arguments;
Arguments.append("v");
if(!m_Password.isEmpty())
Arguments.append("-p" + m_Password);
Arguments.append(m_ArchivePath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "unrar.exe", Arguments);
/*for(;;)
{
bool bDone = pWinRar->waitForFinished(1000);
QStringList Test;
while(pWinRar->canReadLine())
{
QString Line = pWinRar->readLine();
Test.append(Line);
}
if(bDone)
break;
}*/
pWinRar->waitForFinished(-1);
QStringList Test;
int Index = -1;
QString Name;
while(pWinRar->canReadLine())
{
QString Line = pWinRar->readLine().trimmed();
if(Line == "-------------------------------------------------------------------------------")
{
if(Index == -1)
{
Index = 0;
continue;
}
break;
}
else if(Index == -1)
continue;
Index++;
if(Index % 2 == 1)
Name = Line.replace("\\","/");
else
FileList.insert(Name,Split2(Line," ").first.toULongLong());
}
delete pWinRar;
m_Mutex.unlock();
return FileList;
}
void CRarWorker::OnExtractAllFiles()
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("x");
if(!m_Password.isEmpty())
Arguments.append("-p" + m_Password);
Arguments.append(m_ArchivePath);
Arguments.append(m_WorkingPath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "unrar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}
void CRarWorker::OnInsertAllFiles()
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("a");
Arguments.append("-m0");
if(!m_Password.isEmpty())
Arguments.append("-hp" + m_Password);
if(m_PartSize != -1)
Arguments.append("-v" + QString::number(m_PartSize) + "b");
if(!m_CommentPath.isEmpty())
Arguments.append("-z" + m_CommentPath);
Arguments.append(m_ArchivePath);
Arguments.append(m_WorkingPath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "rar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}
void CRarWorker::OnExtractFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("x");
if(!m_Password.isEmpty())
Arguments.append("-p" + m_Password);
Arguments.append(m_ArchivePath);
foreach(const QString& File, FileList)
Arguments.append(File);
Arguments.append(m_WorkingPath);
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "unrar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
}
void CRarWorker::OnInsertFiles(QStringList FileList)
{
QMutexLocker Locker(&m_Mutex);
m_Lock.Release();
QStringList Arguments;
Arguments.append("a");
Arguments.append("-m0");
Arguments.append("-ep");
Arguments.append("-ap" + Split2(Split2(m_ArchivePath, "/", true).second, ".", true).first.replace(" ", "_"));
if(!m_Password.isEmpty())
Arguments.append("-hp" + m_Password);
if(m_PartSize != -1)
Arguments.append("-v" + QString::number(m_PartSize) + "b");
if(!m_CommentPath.isEmpty())
Arguments.append("-z" + m_CommentPath);
Arguments.append(m_ArchivePath);
foreach(const QString& File, FileList)
{
StrPair RootName = Split2(File, "\\", true);
if(RootName.second.isEmpty())
{
RootName.second = RootName.first;
RootName.first = "";
}
QString FileName = (RootName.first.isEmpty() ? m_WorkingPath : RootName.first) + RootName.second;
Arguments.append(FileName);
}
QProcess* pWinRar = new QProcess(this);
pWinRar->start(m_WinRarPath + "rar.exe", Arguments);
pWinRar->waitForFinished(-1);
if(int ExitCode = pWinRar->exitCode())
m_Errors.append(QString("WinRar returrned error code %1").arg(ExitCode));
delete pWinRar;
2022-12-07 16:32:40 +00:00
}