mirror of
				https://github.com/YACReader/yacreader
				synced 2025-11-04 01:05:06 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			319 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			319 lines
		
	
	
		
			9.5 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
 | 
						|
{
 | 
						|
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;
 | 
						|
 | 
						|
    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
 | 
						|
}
 | 
						|
 | 
						|
STDMETHODIMP YCArchiveExtractCallback::SetTotal(UInt64 /* size */)
 | 
						|
{
 | 
						|
    return S_OK;
 | 
						|
}
 | 
						|
 | 
						|
STDMETHODIMP YCArchiveExtractCallback::SetCompleted(const UInt64 * /* completeValue */)
 | 
						|
{
 | 
						|
    return S_OK;
 | 
						|
}
 | 
						|
 | 
						|
STDMETHODIMP 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<CBufPtrSeqOutStream> outStreamLocal(outStreamSpec);
 | 
						|
            data = (Byte *)MidAlloc(newFileSize);
 | 
						|
            outStreamSpec->Init(data, newFileSize);
 | 
						|
            *outStream = outStreamLocal.Detach();
 | 
						|
        } else {
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return S_OK;
 | 
						|
}
 | 
						|
 | 
						|
STDMETHODIMP 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;
 | 
						|
}
 | 
						|
 | 
						|
STDMETHODIMP 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;
 | 
						|
}
 | 
						|
 | 
						|
STDMETHODIMP YCArchiveExtractCallback::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
 |