mirror of
https://github.com/YACReader/yacreader
synced 2025-05-28 03:10:27 -04:00
334 lines
8.7 KiB
C++
334 lines
8.7 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 CArchiveExtractCallback:
|
||
public IArchiveExtractCallback,
|
||
public ICryptoGetTextPassword,
|
||
public CMyUnknownImp
|
||
{
|
||
public:
|
||
MY_UNKNOWN_IMP1(ICryptoGetTextPassword)
|
||
|
||
// IProgress
|
||
STDMETHOD(SetTotal)(UInt64 size);
|
||
STDMETHOD(SetCompleted)(const UInt64 *completeValue);
|
||
|
||
// IArchiveExtractCallback
|
||
STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream, Int32 askExtractMode);
|
||
STDMETHOD(PrepareOperation)(Int32 askExtractMode);
|
||
STDMETHOD(SetOperationResult)(Int32 resultEOperationResult);
|
||
|
||
// ICryptoGetTextPassword
|
||
STDMETHOD(CryptoGetTextPassword)(BSTR *aPassword);
|
||
|
||
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;
|
||
|
||
CArchiveExtractCallback(const QMap<qint32, qint32> & indexesToPages ,bool c = false,ExtractDelegate * d = 0) : PasswordIsDefined(false),all(c),delegate(d),indexesToPages(indexesToPages) {}
|
||
~CArchiveExtractCallback() {MidFree(data);}
|
||
};
|
||
|
||
void CArchiveExtractCallback::Init(IInArchive *archiveHandler, const UString &directoryPath)
|
||
{
|
||
NumErrors = 0;
|
||
_archiveHandler = archiveHandler;
|
||
directoryPath;//unused
|
||
}
|
||
|
||
STDMETHODIMP CArchiveExtractCallback::SetTotal(UInt64 /* size */)
|
||
{
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHODIMP CArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)
|
||
{
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHODIMP CArchiveExtractCallback::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<6D>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)
|
||
newFileSize = ConvertPropVariantToUInt64(prop);
|
||
}
|
||
|
||
//No hay que crear ning<6E>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<CBufPtrSeqOutStream> outStreamLocal(outStreamSpec);
|
||
data = (Byte *)MidAlloc(newFileSize);
|
||
outStreamSpec->Init(data, newFileSize);
|
||
*outStream = outStreamLocal.Detach();
|
||
}
|
||
else
|
||
{
|
||
|
||
}
|
||
|
||
}
|
||
return S_OK;
|
||
}
|
||
|
||
STDMETHODIMP CArchiveExtractCallback::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;
|
||
}
|
||
|
||
STDMETHODIMP CArchiveExtractCallback::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;
|
||
}
|
||
|
||
|
||
STDMETHODIMP CArchiveExtractCallback::CryptoGetTextPassword(BSTR *password)
|
||
{
|
||
if (!PasswordIsDefined)
|
||
{
|
||
// You can ask real password here from user
|
||
// Password = GetPassword(OutStream);
|
||
// PasswordIsDefined = true;
|
||
qDebug() << "Password is not defined" << endl;
|
||
return E_ABORT;
|
||
}
|
||
return StringToBstr(Password, password);
|
||
}
|
||
|
||
#endif
|