yacreader/compressed_archive/extract_callbacks.h
Luis Ángel San Martín 27b7176e41 Update implementation to use 7zip 23.01
Mostly changes in macros
2023-07-17 10:36:33 +02:00

301 lines
9.1 KiB
C++

#ifndef EXTRACT_CALLBACKS_H
#define EXTRACT_CALLBACKS_H
#include "7z_includes.h"
#include "extract_delegate.h"
#include <QDebug>
using namespace NWindows;
//////////////////////////////////////////////////////////////
// Archive Extracting callback class
static const wchar_t *kCantDeleteOutputFile = L"ERROR: Can not delete output file ";
static const char *kTestingString = "Testing ";
static const char *kExtractingString = "Extracting ";
static const char *kSkippingString = "Skipping ";
static const char *kUnsupportedMethod = "Unsupported Method";
static const char *kCRCFailed = "CRC Failed";
static const char *kDataError = "Data Error";
static const char *kUnknownError = "Unknown Error";
static const wchar_t *kEmptyFileAlias = L"[Content]";
static HRESULT IsArchiveItemProp(IInArchive *archive, UInt32 index, PROPID propID, bool &result)
{
NCOM::CPropVariant prop;
RINOK(archive->GetProperty(index, propID, &prop));
if (prop.vt == VT_BOOL)
result = VARIANT_BOOLToBool(prop.boolVal);
else if (prop.vt == VT_EMPTY)
result = false;
else
return E_FAIL;
return S_OK;
}
static HRESULT IsArchiveItemFolder(IInArchive *archive, UInt32 index, bool &result)
{
return IsArchiveItemProp(archive, index, kpidIsDir, result);
}
class YCArchiveExtractCallback : public IArchiveExtractCallback,
public ICryptoGetTextPassword,
public CMyUnknownImp
{
Z7_IFACES_IMP_UNK_2(IArchiveExtractCallback, ICryptoGetTextPassword)
Z7_IFACE_COM7_IMP(IProgress)
private:
CMyComPtr<IInArchive> _archiveHandler;
UString _directoryPath; // Output directory
UString _filePath; // name inside arcvhive
UString _diskFilePath; // full path to file on disk
bool _extractMode;
bool all;
ExtractDelegate *delegate;
UInt32 _index;
struct CProcessedFileInfo {
FILETIME MTime;
UInt32 Attrib;
bool isDir;
bool AttribDefined;
bool MTimeDefined;
} _processedFileInfo;
COutFileStream *_outFileStreamSpec;
CMyComPtr<ISequentialOutStream> _outFileStream;
public:
void Init(IInArchive *archiveHandler, const UString &directoryPath);
UInt64 NumErrors;
bool PasswordIsDefined;
QList<QByteArray> allFiles;
UString Password;
Byte *data;
UInt64 newFileSize;
QMap<qint32, qint32> indexesToPages;
YCArchiveExtractCallback(const QMap<qint32, qint32> &indexesToPages, bool c = false, ExtractDelegate *d = 0)
: PasswordIsDefined(false), all(c), delegate(d), indexesToPages(indexesToPages) { }
~YCArchiveExtractCallback() { MidFree(data); }
};
void YCArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)
{
NumErrors = 0;
_archiveHandler = archiveHandler;
directoryPath; // unused
}
Z7_COM7F_IMF(YCArchiveExtractCallback::SetTotal(UInt64 /* size */))
{
return S_OK;
}
Z7_COM7F_IMF(YCArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */))
{
return S_OK;
}
Z7_COM7F_IMF(YCArchiveExtractCallback::GetStream(UInt32 index,
ISequentialOutStream **outStream, Int32 askExtractMode))
{
*outStream = 0;
_outFileStream.Release();
if (indexesToPages.isEmpty())
_index = index;
else
_index = indexesToPages.value(index);
{
// Get Name
NCOM::CPropVariant prop;
RINOK(_archiveHandler->GetProperty(index, kpidPath, &prop));
UString fullPath;
if (prop.vt == VT_EMPTY)
fullPath = kEmptyFileAlias;
else {
if (prop.vt != VT_BSTR)
return E_FAIL;
fullPath = prop.bstrVal;
}
_filePath = fullPath;
}
askExtractMode; // unused
// if (askExtractMode != NArchive::NExtract::NAskMode::kExtract)
// return S_OK;
{
// Get Attrib
NCOM::CPropVariant prop;
RINOK(_archiveHandler->GetProperty(index, kpidAttrib, &prop));
if (prop.vt == VT_EMPTY) {
_processedFileInfo.Attrib = 0;
_processedFileInfo.AttribDefined = false;
} else {
if (prop.vt != VT_UI4)
return E_FAIL;
_processedFileInfo.Attrib = prop.ulVal;
_processedFileInfo.AttribDefined = true;
}
}
RINOK(IsArchiveItemFolder(_archiveHandler, index, _processedFileInfo.isDir));
{
// Get Modified Time
NCOM::CPropVariant prop;
RINOK(_archiveHandler->GetProperty(index, kpidMTime, &prop));
_processedFileInfo.MTimeDefined = false;
switch (prop.vt) {
case VT_EMPTY:
// _processedFileInfo.MTime = _utcMTimeDefault;
break;
case VT_FILETIME:
_processedFileInfo.MTime = prop.filetime;
_processedFileInfo.MTimeDefined = true;
break;
default:
return E_FAIL;
}
}
// se necesita conocer el tama?o del archivo para poder reservar suficiente memoria
bool newFileSizeDefined;
{
// Get Size
NCOM::CPropVariant prop;
RINOK(_archiveHandler->GetProperty(index, kpidSize, &prop));
newFileSizeDefined = (prop.vt != VT_EMPTY);
if (newFileSizeDefined)
ConvertPropVariantToUInt64(prop, newFileSize);
}
// No hay que crear ning?n fichero, ni directorios intermedios
/*{
// Create folders for file
int slashPos = _filePath.ReverseFind(WCHAR_PATH_SEPARATOR);
if (slashPos >= 0)
NFile::NDirectory::CreateComplexDirectory(_directoryPath + _filePath.Left(slashPos));
}
UString fullProcessedPath = _directoryPath + _filePath;
_diskFilePath = fullProcessedPath;
*/
if (_processedFileInfo.isDir) {
// NFile::NDirectory::CreateComplexDirectory(fullProcessedPath);
} else {
/*NFile::NFind::CFileInfoW fi;
if (fi.Find(fullProcessedPath))
{
if (!NFile::NDirectory::DeleteFileAlways(fullProcessedPath))
{
qDebug() <<(UString(kCantDeleteOutputFile) + fullProcessedPath);
return E_ABORT;
}
}*/
if (newFileSizeDefined) {
CBufPtrSeqOutStream *outStreamSpec = new CBufPtrSeqOutStream;
CMyComPtr<ISequentialOutStream> outStreamLocal(outStreamSpec);
data = (Byte *)MidAlloc(newFileSize);
outStreamSpec->Init(data, newFileSize);
*outStream = outStreamLocal.Detach();
} else {
}
}
return S_OK;
}
Z7_COM7F_IMF(YCArchiveExtractCallback::PrepareOperation(Int32 askExtractMode))
{
_extractMode = false;
switch (askExtractMode) {
case NArchive::NExtract::NAskMode::kExtract:
_extractMode = true;
break;
};
/* switch (askExtractMode)
{
case NArchive::NExtract::NAskMode::kExtract: qDebug() << (kExtractingString); break;
case NArchive::NExtract::NAskMode::kTest: qDebug() <<(kTestingString); break;
case NArchive::NExtract::NAskMode::kSkip: qDebug() <<(kSkippingString); break;
};*/
// qDebug() << _filePath;
return S_OK;
}
Z7_COM7F_IMF(YCArchiveExtractCallback::SetOperationResult(Int32 operationResult))
{
switch (operationResult) {
case NArchive::NExtract::NOperationResult::kOK:
if (all && !_processedFileInfo.isDir) {
QByteArray rawData((char *)data, newFileSize);
MidFree(data);
data = 0;
if (delegate != 0)
delegate->fileExtracted(_index, rawData);
else {
allFiles.append(rawData);
}
}
break;
default: {
NumErrors++;
qDebug() << " ";
switch (operationResult) {
case NArchive::NExtract::NOperationResult::kUnsupportedMethod:
if (delegate != 0)
delegate->unknownError(_index);
qDebug() << kUnsupportedMethod;
break;
case NArchive::NExtract::NOperationResult::kCRCError:
if (delegate != 0)
delegate->crcError(_index);
qDebug() << kCRCFailed;
break;
case NArchive::NExtract::NOperationResult::kDataError:
if (delegate != 0)
delegate->unknownError(_index);
qDebug() << kDataError;
break;
default:
if (delegate != 0)
delegate->unknownError(_index);
qDebug() << kUnknownError;
}
}
}
/*
if (_outFileStream != NULL)
{
if (_processedFileInfo.MTimeDefined)
_outFileStreamSpec->SetMTime(&_processedFileInfo.MTime);
RINOK(_outFileStreamSpec->Close());
}
_outFileStream.Release();
if (_extractMode && _processedFileInfo.AttribDefined)
NFile::NDirectory::MySetFileAttributes(_diskFilePath, _processedFileInfo.Attrib);*/
// qDebug() << endl;
return S_OK;
}
Z7_COM7F_IMF(YCArchiveExtractCallback::CryptoGetTextPassword(BSTR *password))
{
if (!PasswordIsDefined) {
// You can ask real password here from user
// Password = GetPassword(OutStream);
// PasswordIsDefined = true;
qDebug() << "Password is not defined" << Qt::endl;
return E_ABORT;
}
return StringToBstr(Password, password);
}
#endif