#ifndef EXTRACT_CALLBACKS_H #define EXTRACT_CALLBACKS_H #include "7z_includes.h" #include "extract_delegate.h" #include 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 _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 _outFileStream; public: void Init(IInArchive *archiveHandler, const UString &directoryPath); UInt64 NumErrors; bool PasswordIsDefined; QList allFiles; UString Password; Byte * data; UInt64 newFileSize; QMap indexesToPages; CArchiveExtractCallback(const QMap & 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ñ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ú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 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