diff --git a/include/libc7zip.h b/include/libc7zip.h index 94fd324..960ac4a 100644 --- a/include/libc7zip.h +++ b/include/libc7zip.h @@ -40,6 +40,12 @@ typedef void (*set_completed_cb_t)(int64_t id, int64_t complete_value); typedef out_stream *(*get_stream_cb_t)(int64_t id, int64_t index); typedef void (*set_operation_result_cb_t)(int64_t id, int32_t operation_result); +// MultiVolumeCallback functions +typedef char *(*get_first_volume_name_cb_t)(int64_t id); +typedef int (*move_to_volume_cb_t)(int64_t id, char *volumeName); +typedef unsigned long long (*get_current_volume_size_cb_t)(int64_t id); +typedef in_stream *(*open_current_volume_stream_cb_t)(int64_t id); + typedef struct in_stream_def { int64_t id; seek_cb_t seek_cb; @@ -65,6 +71,25 @@ MYEXPORT void out_stream_free(out_stream *s); struct archive; typedef struct archive archive; MYEXPORT archive *archive_open(lib *l, in_stream *is, int32_t by_signature); +MYEXPORT archive *archive_open_ex(lib *l, in_stream *is, const char *password, int32_t by_signature); + +struct multivolume_callback; +typedef struct multivolume_callback multivolume_callback; + +typedef struct multivolume_callback_def { + int64_t id; + get_first_volume_name_cb_t get_first_volume_name_cb; + move_to_volume_cb_t move_to_volume_cb; + get_current_volume_size_cb_t get_current_volume_size_cb; + open_current_volume_stream_cb_t open_current_volume_stream_cb; +} multivolume_callback_def; + +MYEXPORT multivolume_callback *multivolume_callback_new(); +MYEXPORT multivolume_callback_def *multivolume_callback_get_def(multivolume_callback *ec); +MYEXPORT void multivolume_callback_free(multivolume_callback *ec); + +MYEXPORT archive *archive_multiopen(lib *l, multivolume_callback *mc, const char *password, int32_t by_signature); + MYEXPORT void archive_close(archive *a); MYEXPORT void archive_free(archive *a); MYEXPORT int64_t archive_get_item_count(archive *a); diff --git a/src/context.cc b/src/context.cc index 33e1975..a635cc3 100644 --- a/src/context.cc +++ b/src/context.cc @@ -80,6 +80,37 @@ struct out_stream { CbSequentialOutStream *strm; }; + +class CbMultiVolumeCallback : public C7ZipMultiVolumes { +public: + multivolume_callback_def m_def; + + CbMultiVolumeCallback() { + // muffin + } + + virtual wstring GetFirstVolumeName() { + return FromCString(m_def.get_first_volume_name_cb(m_def.id)); + } + virtual bool MoveToVolume(const wstring & volumeName) { + char *retVolCName = ToCString(volumeName); + std::string _volumeName = retVolCName; + free(retVolCName); + return (bool)m_def.move_to_volume_cb(m_def.id, (char *)_volumeName.c_str()); + } + virtual unsigned __int64 GetCurrentVolumeSize() { + return m_def.get_current_volume_size_cb(m_def.id); + } + virtual C7ZipInStream * OpenCurrentVolumeStream() { + in_stream *is = m_def.open_current_volume_stream_cb(m_def.id); + return is->strm; + } + + virtual ~CbMultiVolumeCallback() { + // muffin + } +}; + class CbExtractCallback : public C7ZipExtractCallback { public: extract_callback_def m_def; @@ -198,6 +229,47 @@ MYEXPORT archive *archive_open(lib *l, in_stream *s, int32_t by_signature) { return a; } +MYEXPORT archive *archive_open_ex(lib *l, in_stream *s, const char *password, int32_t by_signature) { + C7ZipArchive *arch = NULL; + if (!l->_lib->OpenArchive(s->strm, &arch, FromCString((char *)password), by_signature != 0)) { + return NULL; + } + + archive *a = (archive*)calloc(1, sizeof(archive)); + a->arch = arch; + return a; +} + +struct multivolume_callback { + CbMultiVolumeCallback *cb; +}; + +MYEXPORT multivolume_callback *multivolume_callback_new() { + multivolume_callback *mc = (multivolume_callback *)calloc(1, sizeof(multivolume_callback)); + mc->cb = new CbMultiVolumeCallback(); + return mc; +} + +MYEXPORT multivolume_callback_def *multivolume_callback_get_def(multivolume_callback *mc) { + return &mc->cb->m_def; +} + +MYEXPORT void multivolume_callback_free(multivolume_callback *mc) { + delete mc->cb; + free(mc); +} + +MYEXPORT archive *archive_multiopen(lib *l, multivolume_callback *mc, const char *password, int32_t by_signature) { + C7ZipArchive *arch = NULL; + if (!l->_lib->OpenMultiVolumeArchive(mc->cb, &arch, FromCString((char *)password), by_signature != 0)) { + return NULL; + } + + archive *a = (archive*)calloc(1, sizeof(archive)); + a->arch = arch; + return a; +} + MYEXPORT void archive_close(archive *a) { a->arch->Close(); } diff --git a/vendor/lib7zip/Lib7Zip/7ZipArchive.cpp b/vendor/lib7zip/Lib7Zip/7ZipArchive.cpp index 662b2df..d5aff46 100644 --- a/vendor/lib7zip/Lib7Zip/7ZipArchive.cpp +++ b/vendor/lib7zip/Lib7Zip/7ZipArchive.cpp @@ -140,10 +140,15 @@ class CCustomArchiveExtractCallback: C7ZipSequentialOutStreamWrap * _outFileStreamSpec; CMyComPtr _outFileStream; C7ZipSequentialOutStream * m_pSequentialOutStream; -public: - CCustomArchiveExtractCallback(C7ZipExtractCallback *pCallback) : - m_pCallback(pCallback) { + const C7ZipArchive * m_pArchive; + const C7ZipArchiveItem * m_pItem; +public: + CCustomArchiveExtractCallback(C7ZipExtractCallback *pCallback,const C7ZipArchive * pArchive,const C7ZipArchiveItem * pItem) : + m_pCallback(pCallback), + m_pArchive(pArchive), + m_pItem(pItem) + { } }; @@ -253,7 +258,8 @@ bool C7ZipArchiveImpl::Extract(const C7ZipArchiveItem * pArchiveItem, C7ZipSeque } bool C7ZipArchiveImpl::ExtractSeveral(unsigned int *indexList, int numIndices, C7ZipExtractCallback *pCallback) { - CCustomArchiveExtractCallback *extractCallbackSpec = new CCustomArchiveExtractCallback(pCallback); + C7ZipArchiveItem * pItem = dynamic_cast(m_ArchiveItems[0]); + CCustomArchiveExtractCallback *extractCallbackSpec = new CCustomArchiveExtractCallback(pCallback, this, pItem); CMyComPtr extractCallback(extractCallbackSpec); return m_pInArchive->Extract(indexList, numIndices, false, extractCallbackSpec) == S_OK; @@ -387,7 +393,20 @@ STDMETHODIMP CCustomArchiveExtractCallback::SetOperationResult(Int32 operationRe STDMETHODIMP CCustomArchiveExtractCallback::CryptoGetTextPassword(BSTR *password) { - return E_NOTIMPL; + wstring strPassword(L""); + + if (m_pItem->IsPasswordSet()) + strPassword = m_pItem->GetArchiveItemPassword(); + else if (m_pArchive->IsPasswordSet()) + strPassword = m_pArchive->GetArchivePassword(); + +#ifdef _WIN32 + return StringToBstr(strPassword.c_str(), password); +#else + *password = ::SysAllocString(strPassword.c_str()); + + return S_OK; +#endif } // ------------------------------