#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 YCArchiveExtractCallback : public IArchiveExtractCallback, public ICryptoGetTextPassword, public CMyUnknownImp { Z7_IFACES_IMP_UNK_2(IArchiveExtractCallback, ICryptoGetTextPassword) Z7_IFACE_COM7_IMP(IProgress) 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; YCArchiveExtractCallback(const QMap &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 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