diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2007-01-20 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:49 +0300 |
commit | d9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch) | |
tree | c722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/Zip | |
parent | 804edc5756fede54dbb1aefda6d39d306111938d (diff) |
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/Zip')
25 files changed, 5282 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Zip/DllExports.cpp b/CPP/7zip/Archive/Zip/DllExports.cpp new file mode 100755 index 00000000..da2a15a4 --- /dev/null +++ b/CPP/7zip/Archive/Zip/DllExports.cpp @@ -0,0 +1,152 @@ +// DLLExports.cpp + +#include "StdAfx.h" + +#include "Common/MyInitGuid.h" +#include "Common/ComTry.h" +#include "ZipHandler.h" +#include "Windows/PropVariant.h" +#include "../../ICoder.h" +#include "../../IPassword.h" +#include "../../Crypto/WzAES/WzAES.h" +#include "../Common/CodecsPath.h" + +// {23170F69-40C1-278B-0401-080000000100} +DEFINE_GUID(CLSID_CCompressDeflateEncoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00); + +// {23170F69-40C1-278B-0401-080000000000} +DEFINE_GUID(CLSID_CCompressDeflateDecoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-0401-090000000100} +DEFINE_GUID(CLSID_CCompressDeflate64Encoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00); + +// {23170F69-40C1-278B-0401-090000000000} +DEFINE_GUID(CLSID_CCompressDeflate64Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-0402-020000000100} +DEFINE_GUID(CLSID_CCompressBZip2Encoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00); + +// {23170F69-40C1-278B-0402-020000000000} +DEFINE_GUID(CLSID_CCompressBZip2Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-0401-060000000000} +DEFINE_GUID(CLSID_CCompressImplodeDecoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278B-06F1-0101000000100} +DEFINE_GUID(CLSID_CCryptoZipEncoder, +0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00); + +// {23170F69-40C1-278B-06F1-0101000000000} +DEFINE_GUID(CLSID_CCryptoZipDecoder, +0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00); + +// {23170F69-40C1-278A-1000-000110010000} +DEFINE_GUID(CLSID_CZipHandler, + 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00); + +HINSTANCE g_hInstance; +#ifndef _UNICODE +bool g_IsNT = false; +static bool IsItWindowsNT() +{ + OSVERSIONINFO versionInfo; + versionInfo.dwOSVersionInfoSize = sizeof(versionInfo); + if (!::GetVersionEx(&versionInfo)) + return false; + return (versionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); +} +#endif + +void GetCryptoFolderPrefix(TCHAR *path) +{ + CSysString s = GetCodecsFolderPrefix(); + lstrcpy(path, s); +} + +extern "C" +BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/) +{ + if (dwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = hInstance; + #ifndef _UNICODE + g_IsNT = IsItWindowsNT(); + #endif + } + return TRUE; +} + + +STDAPI CreateObject( + const GUID *classID, + const GUID *interfaceID, + void **outObject) +{ + COM_TRY_BEGIN + *outObject = 0; + if (*classID != CLSID_CZipHandler) + return CLASS_E_CLASSNOTAVAILABLE; + int needIn = *interfaceID == IID_IInArchive; + int needOut = *interfaceID == IID_IOutArchive; + if (needIn || needOut) + { + NArchive::NZip::CHandler *temp = new NArchive::NZip::CHandler; + if (needIn) + { + CMyComPtr<IInArchive> inArchive = (IInArchive *)temp; + *outObject = inArchive.Detach(); + } + else + { + CMyComPtr<IOutArchive> outArchive = (IOutArchive *)temp; + *outObject = outArchive.Detach(); + } + } + else + return E_NOINTERFACE; + COM_TRY_END + return S_OK; +} + +STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value) +{ + NWindows::NCOM::CPropVariant propVariant; + switch(propID) + { + case NArchive::kName: + propVariant = L"Zip"; + break; + case NArchive::kClassID: + { + if ((value->bstrVal = ::SysAllocStringByteLen( + (const char *)&CLSID_CZipHandler, sizeof(GUID))) != 0) + value->vt = VT_BSTR; + return S_OK; + } + case NArchive::kExtension: + propVariant = L"zip jar xpi"; + break; + case NArchive::kUpdate: + propVariant = true; + break; + case NArchive::kKeepName: + propVariant = false; + break; + case NArchive::kStartSignature: + { + const char sig[] = { 0x50, 0x4B, 0x03, 0x04 }; + if ((value->bstrVal = ::SysAllocStringByteLen(sig, 4)) != 0) + value->vt = VT_BSTR; + return S_OK; + } + } + propVariant.Detach(value); + return S_OK; +} diff --git a/CPP/7zip/Archive/Zip/StdAfx.cpp b/CPP/7zip/Archive/Zip/StdAfx.cpp new file mode 100755 index 00000000..d0feea85 --- /dev/null +++ b/CPP/7zip/Archive/Zip/StdAfx.cpp @@ -0,0 +1,3 @@ +// StdAfx.cpp + +#include "StdAfx.h" diff --git a/CPP/7zip/Archive/Zip/StdAfx.h b/CPP/7zip/Archive/Zip/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/CPP/7zip/Archive/Zip/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/Zip/Zip.dsp b/CPP/7zip/Archive/Zip/Zip.dsp new file mode 100755 index 00000000..2ac27f4f --- /dev/null +++ b/CPP/7zip/Archive/Zip/Zip.dsp @@ -0,0 +1,651 @@ +# Microsoft Developer Studio Project File - Name="Zip" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=Zip - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "Zip.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "Zip.mak" CFG="Zip - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "Zip - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "Zip - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "Zip - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZIP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZIP_EXPORTS" /D "COMPRESS_MT" /Yu"StdAfx.h" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"C:\Program Files\7-Zip\Formats\zip.dll" /opt:NOWIN98 +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "Zip - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 1 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZIP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ZIP_EXPORTS" /D "COMPRESS_MT" /Yu"StdAfx.h" /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x419 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"C:\Program Files\7-Zip\Formats\zip.dll" /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "Zip - Win32 Release" +# Name "Zip - Win32 Debug" +# Begin Group "spec" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Archive.def +# End Source File +# Begin Source File + +SOURCE=.\DllExports.cpp +# End Source File +# Begin Source File + +SOURCE=.\resource.rc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.cpp +# ADD CPP /Yc +# End Source File +# Begin Source File + +SOURCE=.\StdAfx.h +# End Source File +# End Group +# Begin Group "Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Alloc.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\AutoPtr.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\CRC.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\IntToString.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\NewHandler.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Random.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Random.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\String.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringConvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\StringToInt.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Common\Vector.h +# End Source File +# End Group +# Begin Group "Windows" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\DLL.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\FileFind.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\PropVariant.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Synchronization.h +# End Source File +# Begin Source File + +SOURCE=..\..\..\Windows\Thread.h +# End Source File +# End Group +# Begin Group "Archive Common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\Common\CodecsPath.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CodecsPath.h +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderLoader.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\CoderLoader.h +# End Source File +# Begin Source File + +SOURCE=..\Common\FilterCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\FilterCoder.h +# End Source File +# Begin Source File + +SOURCE=..\Common\InStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\InStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ItemNameUtils.h +# End Source File +# Begin Source File + +SOURCE=..\Common\OutStreamWithCRC.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\OutStreamWithCRC.h +# End Source File +# Begin Source File + +SOURCE=..\Common\ParseProperties.cpp +# End Source File +# Begin Source File + +SOURCE=..\Common\ParseProperties.h +# End Source File +# End Group +# Begin Group "7zip common" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Common\InBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\InBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LimitedStreams.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LSBFDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\LSBFDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MemBlocks.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\MemBlocks.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OffsetStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OffsetStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutBuffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutMemStream.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\OutMemStream.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressMt.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressMt.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\ProgressUtils.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamObjects.h +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Common\StreamUtils.h +# End Source File +# End Group +# Begin Group "Engine" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ZipAddCommon.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipAddCommon.h +# End Source File +# Begin Source File + +SOURCE=.\ZipCompressionMode.h +# End Source File +# Begin Source File + +SOURCE=.\ZipHandler.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipHandler.h +# End Source File +# Begin Source File + +SOURCE=.\ZipHandlerOut.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipHeader.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipHeader.h +# End Source File +# Begin Source File + +SOURCE=.\ZipIn.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipIn.h +# End Source File +# Begin Source File + +SOURCE=.\ZipItem.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipItem.h +# End Source File +# Begin Source File + +SOURCE=.\ZipItemEx.h +# End Source File +# Begin Source File + +SOURCE=.\ZipOut.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipOut.h +# End Source File +# Begin Source File + +SOURCE=.\ZipUpdate.cpp +# End Source File +# Begin Source File + +SOURCE=.\ZipUpdate.h +# End Source File +# End Group +# Begin Group "Crypto" + +# PROP Default_Filter "" +# Begin Group "WzAes" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\WzAES\WzAES.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\WzAES\WzAES.h +# End Source File +# End Group +# Begin Group "Hash" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Crypto\Hash\HmacSha1.cpp + +!IF "$(CFG)" == "Zip - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Zip - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\HmacSha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\Pbkdf2HmacSha1.cpp + +!IF "$(CFG)" == "Zip - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Zip - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\Pbkdf2HmacSha1.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\RandGen.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\RandGen.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\RotateDefs.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\Sha1.cpp + +!IF "$(CFG)" == "Zip - Win32 Release" + +# ADD CPP /O2 +# SUBTRACT CPP /YX /Yc /Yu + +!ELSEIF "$(CFG)" == "Zip - Win32 Debug" + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Hash\Sha1.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\..\Crypto\Zip\ZipCipher.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Zip\ZipCipher.h +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Zip\ZipCrypto.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Crypto\Zip\ZipCrypto.h +# End Source File +# End Group +# Begin Group "7z" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\7z\7zMethodID.cpp +# End Source File +# Begin Source File + +SOURCE=..\7z\7zMethodID.h +# End Source File +# Begin Source File + +SOURCE=..\7z\7zMethods.cpp +# End Source File +# Begin Source File + +SOURCE=..\7z\7zMethods.h +# End Source File +# End Group +# Begin Group "Compress" + +# PROP Default_Filter "" +# Begin Group "Shrink" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Shrink\ShrinkDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Shrink\ShrinkDecoder.h +# End Source File +# End Group +# Begin Group "copy" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Copy\CopyCoder.h +# End Source File +# End Group +# Begin Group "Implode" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\Implode\ImplodeDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Implode\ImplodeDecoder.h +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Implode\ImplodeHuffmanDecoder.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\Implode\ImplodeHuffmanDecoder.h +# End Source File +# End Group +# Begin Group "LZ" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=..\..\Compress\LZ\LZOutWindow.cpp +# End Source File +# Begin Source File + +SOURCE=..\..\Compress\LZ\LZOutWindow.h +# End Source File +# End Group +# End Group +# Begin Source File + +SOURCE=.\zip.ico +# End Source File +# End Target +# End Project diff --git a/CPP/7zip/Archive/Zip/Zip.dsw b/CPP/7zip/Archive/Zip/Zip.dsw new file mode 100755 index 00000000..0a355329 --- /dev/null +++ b/CPP/7zip/Archive/Zip/Zip.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "Zip"=.\Zip.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.cpp b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp new file mode 100755 index 00000000..7eb2787f --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.cpp @@ -0,0 +1,309 @@ +// AddCommon.cpp + +#include "StdAfx.h" + +#include "Common/CRC.h" +#include "Windows/PropVariant.h" +#include "Windows/Defs.h" +#include "../../ICoder.h" +#include "../../IPassword.h" +#include "../Common/InStreamWithCRC.h" +#include "../7z/7zMethods.h" + +#include "ZipAddCommon.h" +#include "ZipHeader.h" + +#ifdef COMPRESS_DEFLATE +#include "../../Compress/Deflate/DeflateEncoder.h" +#else +// {23170F69-40C1-278B-0401-080000000100} +DEFINE_GUID(CLSID_CCompressDeflateEncoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x01, 0x00); +#endif + +#ifdef COMPRESS_DEFLATE64 +#include "../../Compress/Deflate/DeflateEncoder.h" +#else +// {23170F69-40C1-278B-0401-090000000100} +DEFINE_GUID(CLSID_CCompressDeflate64Encoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00); +#endif + +#ifdef COMPRESS_BZIP2 +#include "../../Compress/BZip2/BZip2Encoder.h" +#else +// {23170F69-40C1-278B-0402-020000000100} +DEFINE_GUID(CLSID_CCompressBZip2Encoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00); +#endif + + +#ifdef CRYPTO_ZIP +#include "../../Crypto/Zip/ZipCipher.h" +#else +// {23170F69-40C1-278B-06F1-0101000000100} +DEFINE_GUID(CLSID_CCryptoZipEncoder, +0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00); +#endif + +namespace NArchive { +namespace NZip { + +CAddCommon::CAddCommon(const CCompressionMethodMode &options): + _options(options), + _copyCoderSpec(NULL), + _cryptoStreamSpec(0) + {} + +static HRESULT GetStreamCRC(ISequentialInStream *inStream, UInt32 &resultCRC) +{ + CCRC crc; + crc.Init(); + const UInt32 kBufferSize = (1 << 14); + Byte buffer[kBufferSize]; + for (;;) + { + UInt32 realProcessedSize; + RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize)); + if(realProcessedSize == 0) + { + resultCRC = crc.GetDigest(); + return S_OK; + } + crc.Update(buffer, realProcessedSize); + } +} + +HRESULT CAddCommon::Compress(ISequentialInStream *inStream, IOutStream *outStream, + ICompressProgressInfo *progress, CCompressingResult &operationResult) +{ + CSequentialInStreamWithCRC *inSecCrcStreamSpec = 0; + CInStreamWithCRC *inCrcStreamSpec = 0; + CMyComPtr<ISequentialInStream> inCrcStream; + { + CMyComPtr<IInStream> inStream2; + // we don't support stdin, since stream from stdin can require 64-bit size header + RINOK(inStream->QueryInterface(IID_IInStream, (void **)&inStream2)); + if (inStream2) + { + inCrcStreamSpec = new CInStreamWithCRC; + inCrcStream = inCrcStreamSpec; + inCrcStreamSpec->SetStream(inStream2); + inCrcStreamSpec->Init(); + } + else + { + inSecCrcStreamSpec = new CSequentialInStreamWithCRC; + inCrcStream = inSecCrcStreamSpec; + inSecCrcStreamSpec->SetStream(inStream); + inSecCrcStreamSpec->Init(); + } + } + + int numTestMethods = _options.MethodSequence.Size(); + if (numTestMethods > 1 || _options.PasswordIsDefined) + { + if (inCrcStreamSpec == 0) + { + if (_options.PasswordIsDefined) + return E_NOTIMPL; + numTestMethods = 1; + } + } + Byte method = 0; + COutStreamReleaser outStreamReleaser; + for(int i = 0; i < numTestMethods; i++) + { + if (inCrcStreamSpec != 0) + RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL)); + if (_options.PasswordIsDefined) + { + if (!_cryptoStream) + { + _cryptoStreamSpec = new CFilterCoder; + _cryptoStream = _cryptoStreamSpec; + } + if (_options.IsAesMode) + { + _cryptoStreamSpec->Filter = _aesFilter = _filterAesSpec = new NCrypto::NWzAES::CEncoder; + _filterAesSpec->SetKeyMode(_options.AesKeyMode); + RINOK(_filterAesSpec->CryptoSetPassword( + (const Byte *)(const char *)_options.Password, _options.Password.Length())); + RINOK(_filterAesSpec->WriteHeader(outStream)); + } + else + { + _cryptoStreamSpec->Filter = _zipCryptoFilter = _filterSpec = new NCrypto::NZip::CEncoder; + RINOK(_filterSpec->CryptoSetPassword( + (const Byte *)(const char *)_options.Password, _options.Password.Length())); + UInt32 crc = 0; + RINOK(GetStreamCRC(inStream, crc)); + RINOK(inCrcStreamSpec->Seek(0, STREAM_SEEK_SET, NULL)); + RINOK(_filterSpec->CryptoSetCRC(crc)); + RINOK(_filterSpec->WriteHeader(outStream)); + } + RINOK(_cryptoStreamSpec->SetOutStream(outStream)); + outStreamReleaser.FilterCoder = _cryptoStreamSpec; + } + + method = _options.MethodSequence[i]; + switch(method) + { + case NFileHeader::NCompressionMethod::kStored: + { + if(_copyCoderSpec == NULL) + { + _copyCoderSpec = new NCompress::CCopyCoder; + _copyCoder = _copyCoderSpec; + } + CMyComPtr<ISequentialOutStream> outStreamNew; + if (_options.PasswordIsDefined) + outStreamNew = _cryptoStream; + else + outStreamNew = outStream; + RINOK(_copyCoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); + operationResult.ExtractVersion = NFileHeader::NCompressionMethod::kStoreExtractVersion; + break; + } + default: + { + if(!_compressEncoder) + { + // RINOK(m_MatchFinder.CoCreateInstance(CLSID_CMatchFinderBT3)); + #ifndef COMPRESS_DEFLATE + UString methodName; + N7z::LoadMethodMap(); + #endif + switch(method) + { + case NFileHeader::NCompressionMethod::kDeflated: + { + #ifdef COMPRESS_DEFLATE + _compressEncoder = new NCompress::NDeflate::NEncoder::CCOMCoder; + #else + methodName = L"Deflate"; + #endif + break; + } + case NFileHeader::NCompressionMethod::kDeflated64: + { + #ifdef COMPRESS_DEFLATE64 + _compressEncoder = new NCompress::NDeflate::NEncoder::CCOMCoder64; + #else + methodName = L"Deflate64"; + #endif + break; + } + case NFileHeader::NCompressionMethod::kBZip2: + { + #ifdef COMPRESS_BZIP2 + _compressEncoder = new NCompress::NBZip2::CEncoder; + #else + methodName = L"BZip2"; + #endif + break; + } + } + #ifndef COMPRESS_DEFLATE + N7z::CMethodInfo2 methodInfo; + if (!N7z::GetMethodInfo(methodName, methodInfo)) + return E_NOTIMPL; + RINOK(_compressLib.LoadAndCreateCoder( + methodInfo.FilePath, methodInfo.Encoder, &_compressEncoder)); + #endif + + if (method == NFileHeader::NCompressionMethod::kDeflated || + method == NFileHeader::NCompressionMethod::kDeflated64) + { + NWindows::NCOM::CPropVariant properties[] = + { + _options.NumPasses, + _options.NumFastBytes, + _options.NumMatchFinderCycles + }; + PROPID propIDs[] = + { + NCoderPropID::kNumPasses, + NCoderPropID::kNumFastBytes, + NCoderPropID::kMatchFinderCycles + }; + int numProps = sizeof(propIDs) / sizeof(propIDs[0]); + if (!_options.NumMatchFinderCyclesDefined) + numProps--; + CMyComPtr<ICompressSetCoderProperties> setCoderProperties; + _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); + if (setCoderProperties) + { + RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps)); + } + } + else if (method == NFileHeader::NCompressionMethod::kBZip2) + { + NWindows::NCOM::CPropVariant properties[] = + { + _options.DicSize, + _options.NumPasses + #ifdef COMPRESS_MT + , _options.NumThreads + #endif + }; + PROPID propIDs[] = + { + NCoderPropID::kDictionarySize, + NCoderPropID::kNumPasses + #ifdef COMPRESS_MT + , NCoderPropID::kNumThreads + #endif + }; + CMyComPtr<ICompressSetCoderProperties> setCoderProperties; + _compressEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties); + if (setCoderProperties) + { + RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0]))); + } + } + } + CMyComPtr<ISequentialOutStream> outStreamNew; + if (_options.PasswordIsDefined) + outStreamNew = _cryptoStream; + else + outStreamNew = outStream; + RINOK(_compressEncoder->Code(inCrcStream, outStreamNew, NULL, NULL, progress)); + operationResult.ExtractVersion = NFileHeader::NCompressionMethod::kDeflateExtractVersion; + break; + } + } + + RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &operationResult.PackSize)); + + if (inCrcStreamSpec != 0) + { + operationResult.CRC = inCrcStreamSpec->GetCRC(); + operationResult.UnpackSize = inCrcStreamSpec->GetSize(); + } + else + { + operationResult.CRC = inSecCrcStreamSpec->GetCRC(); + operationResult.UnpackSize = inSecCrcStreamSpec->GetSize(); + } + + if (_options.PasswordIsDefined) + { + if (operationResult.PackSize < operationResult.UnpackSize + + (_options.IsAesMode ? _filterAesSpec->GetHeaderSize() : NCrypto::NZip::kHeaderSize)) + break; + } + else if (operationResult.PackSize < operationResult.UnpackSize) + break; + } + if (_options.IsAesMode) + { + RINOK(_filterAesSpec->WriteFooter(outStream)); + RINOK(outStream->Seek(0, STREAM_SEEK_CUR, &operationResult.PackSize)); + } + operationResult.Method = method; + return outStream->SetSize(operationResult.PackSize); +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipAddCommon.h b/CPP/7zip/Archive/Zip/ZipAddCommon.h new file mode 100755 index 00000000..26cec643 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipAddCommon.h @@ -0,0 +1,58 @@ +// Zip/AddCommon.h + +#ifndef __ZIP_ADDCOMMON_H +#define __ZIP_ADDCOMMON_H + +#include "../../ICoder.h" +#include "../../IProgress.h" +#include "../../Compress/Copy/CopyCoder.h" +#ifndef COMPRESS_DEFLATE +#include "../Common/CoderLoader.h" +#endif +#include "../Common/FilterCoder.h" +#include "ZipCompressionMode.h" +#include "../../Crypto/Zip/ZipCipher.h" +#include "../../Crypto/WzAES/WzAES.h" + +namespace NArchive { +namespace NZip { + +struct CCompressingResult +{ + UInt64 UnpackSize; + UInt64 PackSize; + UInt32 CRC; + UInt16 Method; + Byte ExtractVersion; +}; + +class CAddCommon +{ + CCompressionMethodMode _options; + NCompress::CCopyCoder *_copyCoderSpec; + CMyComPtr<ICompressCoder> _copyCoder; + + #ifndef COMPRESS_DEFLATE + CCoderLibrary _compressLib; + #endif + CMyComPtr<ICompressCoder> _compressEncoder; + + CFilterCoder *_cryptoStreamSpec; + CMyComPtr<ISequentialOutStream> _cryptoStream; + + NCrypto::NZip::CEncoder *_filterSpec; + NCrypto::NWzAES::CEncoder *_filterAesSpec; + + CMyComPtr<ICompressFilter> _zipCryptoFilter; + CMyComPtr<ICompressFilter> _aesFilter; + + +public: + CAddCommon(const CCompressionMethodMode &options); + HRESULT Compress(ISequentialInStream *inStream, IOutStream *outStream, + ICompressProgressInfo *progress, CCompressingResult &operationResult); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipCompressionMode.h b/CPP/7zip/Archive/Zip/ZipCompressionMode.h new file mode 100755 index 00000000..f1c79918 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipCompressionMode.h @@ -0,0 +1,39 @@ +// CompressionMode.h + +#ifndef __ZIP_COMPRESSIONMETHOD_H +#define __ZIP_COMPRESSIONMETHOD_H + +#include "Common/Vector.h" +#include "Common/String.h" + +namespace NArchive { +namespace NZip { + +struct CCompressionMethodMode +{ + CRecordVector<Byte> MethodSequence; + // bool MaximizeRatio; + UInt32 NumPasses; + UInt32 NumFastBytes; + bool NumMatchFinderCyclesDefined; + UInt32 NumMatchFinderCycles; + UInt32 DicSize; + #ifdef COMPRESS_MT + UInt32 NumThreads; + #endif + bool PasswordIsDefined; + AString Password; + bool IsAesMode; + Byte AesKeyMode; + + CCompressionMethodMode(): + NumMatchFinderCyclesDefined(false), + PasswordIsDefined(false), + IsAesMode(false), + AesKeyMode(3) + {} +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipHandler.cpp b/CPP/7zip/Archive/Zip/ZipHandler.cpp new file mode 100755 index 00000000..4672d768 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHandler.cpp @@ -0,0 +1,766 @@ +// ZipHandler.cpp + +#include "StdAfx.h" + +#include "ZipHandler.h" + +#include "Common/Defs.h" +#include "Common/CRC.h" +#include "Common/StringConvert.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/Time.h" +#include "Windows/PropVariant.h" + +#include "../../IPassword.h" + +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamObjects.h" + +#include "../../Compress/Copy/CopyCoder.h" + +#include "../Common/ItemNameUtils.h" +#include "../Common/OutStreamWithCRC.h" +#include "../Common/FilterCoder.h" +#include "../7z/7zMethods.h" + +#include "../../Compress/Shrink/ShrinkDecoder.h" +#include "../../Compress/Implode/ImplodeDecoder.h" + +#ifdef COMPRESS_DEFLATE +#include "../../Compress/Deflate/DeflateDecoder.h" +#else +// {23170F69-40C1-278B-0401-080000000000} +DEFINE_GUID(CLSID_CCompressDeflateDecoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00); +#endif + +#ifdef COMPRESS_DEFLATE64 +#include "../../Compress/Deflate/DeflateDecoder.h" +#else +// {23170F69-40C1-278B-0401-090000000000} +DEFINE_GUID(CLSID_CCompressDeflate64Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00); +#endif + +/* +#ifdef COMPRESS_IMPLODE +#else +// {23170F69-40C1-278B-0401-060000000000} +DEFINE_GUID(CLSID_CCompressImplodeDecoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00); +#endif +*/ + +#ifdef COMPRESS_BZIP2 +#include "../../Compress/BZip2/BZip2Decoder.h" +#else +// {23170F69-40C1-278B-0402-020000000000} +DEFINE_GUID(CLSID_CCompressBZip2Decoder, +0x23170F69, 0x40C1, 0x278B, 0x04, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00); +#endif + +#include "../../Crypto/Zip/ZipCipher.h" +#include "../../Crypto/WzAES/WzAES.h" + +#ifndef EXCLUDE_COM +#include "../Common/CoderLoader.h" +#endif + +using namespace NWindows; +using namespace NTime; + +namespace NArchive { +namespace NZip { + +const wchar_t *kHostOS[] = +{ + L"FAT", + L"AMIGA", + L"VMS", + L"Unix", + L"VM_CMS", + L"Atari", // what if it's a minix filesystem? [cjh] + L"HPFS", // filesystem used by OS/2 (and NT 3.x) + L"Mac", + L"Z_System", + L"CPM", + L"TOPS20", // pkzip 2.50 NTFS + L"NTFS", // filesystem used by Windows NT + L"QDOS ", // SMS/QDOS + L"Acorn", // Archimedes Acorn RISC OS + L"VFAT", // filesystem used by Windows 95, NT + L"MVS", + L"BeOS", // hybrid POSIX/database filesystem + // BeBOX or PowerMac + L"Tandem", + L"THEOS" +}; + + +static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); + +static const wchar_t *kUnknownOS = L"Unknown"; + + +/* +enum // PropID +{ + kpidUnPackVersion, +}; +*/ + +STATPROPSTG kProperties[] = +{ + { NULL, kpidPath, VT_BSTR}, + { NULL, kpidIsFolder, VT_BOOL}, + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackedSize, VT_UI8}, + { NULL, kpidLastWriteTime, VT_FILETIME}, + { NULL, kpidAttributes, VT_UI4}, + + { NULL, kpidEncrypted, VT_BOOL}, + { NULL, kpidComment, VT_BSTR}, + + { NULL, kpidCRC, VT_UI4}, + + { NULL, kpidMethod, VT_BSTR}, + { NULL, kpidHostOS, VT_BSTR} + + // { L"UnPack Version", kpidUnPackVersion, VT_UI1}, +}; + +const wchar_t *kMethods[] = +{ + L"Store", + L"Shrink", + L"Reduced1", + L"Reduced2", + L"Reduced2", + L"Reduced3", + L"Implode", + L"Tokenizing", + L"Deflate", + L"Deflate64", + L"PKImploding", + L"Unknown", + L"BZip2" +}; + +const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]); +// const wchar_t *kUnknownMethod = L"Unknown"; +const wchar_t *kPPMdMethod = L"PPMd"; +const wchar_t *kAESMethod = L"AES"; +const wchar_t *kZipCryptoMethod = L"ZipCrypto"; + +CHandler::CHandler(): + m_ArchiveIsOpen(false) +{ + InitMethodProperties(); +} + +STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value) +{ + value->vt = VT_EMPTY; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties) +{ + *numProperties = sizeof(kProperties) / sizeof(kProperties[0]); + return S_OK; +} + +STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType) +{ + if(index >= sizeof(kProperties) / sizeof(kProperties[0])) + return E_INVALIDARG; + const STATPROPSTG &srcItem = kProperties[index]; + *propID = srcItem.propid; + *varType = srcItem.vt; + *name = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties) +{ + *numProperties = 0; + return S_OK; +} + +STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */, + BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) +{ + return E_NOTIMPL; +} + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = m_Items.Size(); + return S_OK; +} + +static void MyStrNCpy(char *dest, const char *src, int size) +{ + for (int i = 0; i < size; i++) + { + char c = src[i]; + dest[i] = c; + if (c == 0) + break; + } +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID aPropID, PROPVARIANT *aValue) +{ + COM_TRY_BEGIN + NWindows::NCOM::CPropVariant propVariant; + const CItemEx &item = m_Items[index]; + switch(aPropID) + { + case kpidPath: + propVariant = NItemName::GetOSName2( + MultiByteToUnicodeString(item.Name, item.GetCodePage())); + break; + case kpidIsFolder: + propVariant = item.IsDirectory(); + break; + case kpidSize: + propVariant = item.UnPackSize; + break; + case kpidPackedSize: + propVariant = item.PackSize; + break; + case kpidLastWriteTime: + { + FILETIME aLocalFileTime, anUTCFileTime; + if (DosTimeToFileTime(item.Time, aLocalFileTime)) + { + if (!LocalFileTimeToFileTime(&aLocalFileTime, &anUTCFileTime)) + anUTCFileTime.dwHighDateTime = anUTCFileTime.dwLowDateTime = 0; + } + else + anUTCFileTime.dwHighDateTime = anUTCFileTime.dwLowDateTime = 0; + propVariant = anUTCFileTime; + break; + } + case kpidAttributes: + propVariant = item.GetWinAttributes(); + break; + case kpidEncrypted: + propVariant = item.IsEncrypted(); + break; + case kpidComment: + { + int size = (int)item.Comment.GetCapacity(); + if (size > 0) + { + AString s; + char *p = s.GetBuffer(size + 1); + MyStrNCpy(p, (const char *)(const Byte *)item.Comment, size); + p[size] = '\0'; + s.ReleaseBuffer(); + propVariant = MultiByteToUnicodeString(s, item.GetCodePage()); + } + break; + } + case kpidCRC: + if (item.IsThereCrc()) + propVariant = item.FileCRC; + break; + case kpidMethod: + { + UInt16 methodId = item.CompressionMethod; + UString method; + if (item.IsEncrypted()) + { + if (methodId == NFileHeader::NCompressionMethod::kWzAES) + { + method = kAESMethod; + CWzAesExtraField aesField; + if (item.CentralExtra.GetWzAesField(aesField)) + { + method += L"-"; + wchar_t s[32]; + ConvertUInt64ToString((aesField.Strength + 1) * 64 , s); + method += s; + method += L" "; + methodId = aesField.Method; + } + } + else + { + method += kZipCryptoMethod; + method += L" "; + } + } + if (methodId < kNumMethods) + method += kMethods[methodId]; + else if (methodId == NFileHeader::NCompressionMethod::kWzPPMd) + method += kPPMdMethod; + else + { + wchar_t s[32]; + ConvertUInt64ToString(methodId, s); + method += s; + } + propVariant = method; + break; + } + case kpidHostOS: + propVariant = (item.MadeByVersion.HostOS < kNumHostOSes) ? + (kHostOS[item.MadeByVersion.HostOS]) : kUnknownOS; + break; + } + propVariant.Detach(aValue); + return S_OK; + COM_TRY_END +} + +class CPropgressImp: public CProgressVirt +{ + CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback; +public: + STDMETHOD(SetCompleted)(const UInt64 *numFiles); + void Init(IArchiveOpenCallback *openArchiveCallback) + { m_OpenArchiveCallback = openArchiveCallback; } +}; + +STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles) +{ + if (m_OpenArchiveCallback) + return m_OpenArchiveCallback->SetCompleted(numFiles, NULL); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback) +{ + COM_TRY_BEGIN + // try + { + if(!m_Archive.Open(inStream, maxCheckStartPosition)) + return S_FALSE; + m_ArchiveIsOpen = true; + m_Items.Clear(); + if (openArchiveCallback != NULL) + { + RINOK(openArchiveCallback->SetTotal(NULL, NULL)); + } + CPropgressImp propgressImp; + propgressImp.Init(openArchiveCallback); + RINOK(m_Archive.ReadHeaders(m_Items, &propgressImp)); + } + /* + catch(...) + { + return S_FALSE; + } + */ + COM_TRY_END + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + m_Items.Clear(); + m_Archive.Close(); + m_ArchiveIsOpen = false; + return S_OK; +} + +////////////////////////////////////// +// CHandler::DecompressItems + +struct CMethodItem +{ + UInt16 ZipMethod; + CMyComPtr<ICompressCoder> Coder; +}; + +class CZipDecoder +{ + NCrypto::NZip::CDecoder *_zipCryptoDecoderSpec; + NCrypto::NWzAES::CDecoder *_aesDecoderSpec; + CMyComPtr<ICompressFilter> _zipCryptoDecoder; + CMyComPtr<ICompressFilter> _aesDecoder; + CFilterCoder *filterStreamSpec; + CMyComPtr<ISequentialInStream> filterStream; + CMyComPtr<ICryptoGetTextPassword> getTextPassword; + #ifndef EXCLUDE_COM + CCoderLibraries libraries; + #endif + CObjectVector<CMethodItem> methodItems; + +public: + CZipDecoder(): _zipCryptoDecoderSpec(0), _aesDecoderSpec(0), filterStreamSpec(0) {} + + static void Init() + { + #ifndef EXCLUDE_COM + N7z::LoadMethodMap(); + #endif + } + + HRESULT Decode(CInArchive &archive, const CItemEx &item, + ISequentialOutStream *realOutStream, + IArchiveExtractCallback *extractCallback, + ICompressProgressInfo *compressProgress, + UInt32 numThreads, Int32 &res); +}; + +HRESULT CZipDecoder::Decode(CInArchive &archive, const CItemEx &item, + ISequentialOutStream *realOutStream, + IArchiveExtractCallback *extractCallback, + ICompressProgressInfo *compressProgress, + UInt32 numThreads, Int32 &res) +{ + res = NArchive::NExtract::NOperationResult::kDataError; + CInStreamReleaser inStreamReleaser; + + bool needCRC = true; + bool aesMode = false; + UInt16 methodId = item.CompressionMethod; + if (item.IsEncrypted()) + if (methodId == NFileHeader::NCompressionMethod::kWzAES) + { + CWzAesExtraField aesField; + if (item.CentralExtra.GetWzAesField(aesField)) + { + aesMode = true; + needCRC = aesField.NeedCrc(); + } + } + + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;; + CMyComPtr<ISequentialOutStream> outStream = outStreamSpec; + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(needCRC); + + UInt64 authenticationPos; + + CMyComPtr<ISequentialInStream> inStream; + { + UInt64 packSize = item.PackSize; + if (aesMode) + { + if (packSize < NCrypto::NWzAES::kMacSize) + return S_OK; + packSize -= NCrypto::NWzAES::kMacSize; + } + UInt64 dataPos = item.GetDataPosition(); + inStream.Attach(archive.CreateLimitedStream(dataPos, packSize)); + authenticationPos = dataPos + packSize; + } + + CMyComPtr<ICompressFilter> cryptoFilter; + if (item.IsEncrypted()) + { + if (aesMode) + { + CWzAesExtraField aesField; + if (!item.CentralExtra.GetWzAesField(aesField)) + return S_OK; + methodId = aesField.Method; + if (!_aesDecoder) + { + _aesDecoderSpec = new NCrypto::NWzAES::CDecoder; + _aesDecoder = _aesDecoderSpec; + } + cryptoFilter = _aesDecoder; + Byte properties = aesField.Strength; + RINOK(_aesDecoderSpec->SetDecoderProperties2(&properties, 1)); + } + else + { + if (!_zipCryptoDecoder) + { + _zipCryptoDecoderSpec = new NCrypto::NZip::CDecoder; + _zipCryptoDecoder = _zipCryptoDecoderSpec; + } + cryptoFilter = _zipCryptoDecoder; + } + CMyComPtr<ICryptoSetPassword> cryptoSetPassword; + RINOK(cryptoFilter.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword)); + + if (!getTextPassword) + extractCallback->QueryInterface(IID_ICryptoGetTextPassword, (void **)&getTextPassword); + + if (getTextPassword) + { + CMyComBSTR password; + RINOK(getTextPassword->CryptoGetTextPassword(&password)); + AString charPassword; + if (aesMode) + { + charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_ACP); + /* + for (int i = 0;; i++) + { + wchar_t c = password[i]; + if (c == 0) + break; + if (c >= 0x80) + { + res = NArchive::NExtract::NOperationResult::kDataError; + return S_OK; + } + charPassword += (char)c; + } + */ + } + else + { + // we use OEM. WinZip/Windows probably use ANSI for some files + charPassword = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); + } + HRESULT res = cryptoSetPassword->CryptoSetPassword( + (const Byte *)(const char *)charPassword, charPassword.Length()); + if (res != S_OK) + return S_OK; + } + else + { + RINOK(cryptoSetPassword->CryptoSetPassword(0, 0)); + } + } + + int m; + for (m = 0; m < methodItems.Size(); m++) + if (methodItems[m].ZipMethod == methodId) + break; + + if (m == methodItems.Size()) + { + CMethodItem mi; + mi.ZipMethod = methodId; + if (methodId == NFileHeader::NCompressionMethod::kStored) + mi.Coder = new NCompress::CCopyCoder; + else if (methodId == NFileHeader::NCompressionMethod::kShrunk) + mi.Coder = new NCompress::NShrink::CDecoder; + else if (methodId == NFileHeader::NCompressionMethod::kImploded) + mi.Coder = new NCompress::NImplode::NDecoder::CCoder; + else + { + #ifdef EXCLUDE_COM + switch(methodId) + { + case NFileHeader::NCompressionMethod::kDeflated: + mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder; + break; + case NFileHeader::NCompressionMethod::kDeflated64: + mi.Coder = new NCompress::NDeflate::NDecoder::CCOMCoder64; + break; + case NFileHeader::NCompressionMethod::kBZip2: + mi.Coder = new NCompress::NBZip2::CDecoder; + break; + default: + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + #else + N7z::CMethodID methodID = { { 0x04, 0x01 } , 3 }; + if (methodId > 0xFF) + { + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + methodID.ID[2] = (Byte)methodId; + if (methodId == NFileHeader::NCompressionMethod::kStored) + { + methodID.ID[0] = 0; + methodID.IDSize = 1; + } + else if (methodId == NFileHeader::NCompressionMethod::kBZip2) + { + methodID.ID[1] = 0x02; + methodID.ID[2] = 0x02; + } + + N7z::CMethodInfo methodInfo; + if (!N7z::GetMethodInfo(methodID, methodInfo)) + { + res = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + return S_OK; + } + RINOK(libraries.CreateCoder(methodInfo.FilePath, methodInfo.Decoder, &mi.Coder)); + #endif + } + m = methodItems.Add(mi); + } + ICompressCoder *coder = methodItems[m].Coder; + + { + CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; + coder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties); + if (setDecoderProperties) + { + Byte properties = (Byte)item.Flags; + RINOK(setDecoderProperties->SetDecoderProperties2(&properties, 1)); + } + } + + #ifdef COMPRESS_MT + { + CMyComPtr<ICompressSetCoderMt> setCoderMt; + coder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt); + if (setCoderMt) + { + RINOK(setCoderMt->SetNumberOfThreads(numThreads)); + } + } + #endif + + { + HRESULT result; + CMyComPtr<ISequentialInStream> inStreamNew; + if (item.IsEncrypted()) + { + if (!filterStream) + { + filterStreamSpec = new CFilterCoder; + filterStream = filterStreamSpec; + } + filterStreamSpec->Filter = cryptoFilter; + if (aesMode) + { + RINOK(_aesDecoderSpec->ReadHeader(inStream)); + } + else + { + RINOK(_zipCryptoDecoderSpec->ReadHeader(inStream)); + } + RINOK(filterStreamSpec->SetInStream(inStream)); + inStreamReleaser.FilterCoder = filterStreamSpec; + inStreamNew = filterStream; + + if (aesMode) + { + if (!_aesDecoderSpec->CheckPasswordVerifyCode()) + return S_OK; + } + } + else + inStreamNew = inStream; + result = coder->Code(inStreamNew, outStream, NULL, &item.UnPackSize, compressProgress); + if (result == S_FALSE) + return S_OK; + RINOK(result); + } + bool crcOK = true; + bool authOk = true; + if (needCRC) + crcOK = (outStreamSpec->GetCRC() == item.FileCRC); + if (aesMode) + { + inStream.Attach(archive.CreateLimitedStream(authenticationPos, NCrypto::NWzAES::kMacSize)); + if (_aesDecoderSpec->CheckMac(inStream, authOk) != S_OK) + authOk = false; + } + + res = ((crcOK && authOk) ? + NArchive::NExtract::NOperationResult::kOK : + NArchive::NExtract::NOperationResult::kCRCError); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + CZipDecoder myDecoder; + bool testMode = (_aTestMode != 0); + UInt64 totalUnPacked = 0, totalPacked = 0; + bool allFilesMode = (numItems == UInt32(-1)); + if (allFilesMode) + numItems = m_Items.Size(); + if(numItems == 0) + return S_OK; + UInt32 i; + for(i = 0; i < numItems; i++) + { + const CItemEx &item = m_Items[allFilesMode ? i : indices[i]]; + totalUnPacked += item.UnPackSize; + totalPacked += item.PackSize; + } + extractCallback->SetTotal(totalUnPacked); + + UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; + UInt64 currentItemUnPacked, currentItemPacked; + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = localProgressSpec; + CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; + CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec; + + CZipDecoder::Init(); + + for (i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, + currentTotalPacked += currentItemPacked) + { + currentItemUnPacked = 0; + currentItemPacked = 0; + + RINOK(extractCallback->SetCompleted(¤tTotalUnPacked)); + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + Int32 index = allFilesMode ? i : indices[i]; + + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); + + CItemEx item = m_Items[index]; + if (!item.FromLocal) + { + HRESULT res = m_Archive.ReadLocalItemAfterCdItem(item); + if (res == S_FALSE) + { + if (item.IsDirectory() || realOutStream || testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); + } + continue; + } + RINOK(res); + } + + if (item.IsDirectory() || item.IgnoreItem()) + { + // if (!testMode) + { + RINOK(extractCallback->PrepareOperation(askMode)); + realOutStream.Release(); + RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); + } + continue; + } + + currentItemUnPacked = item.UnPackSize; + currentItemPacked = item.PackSize; + + if (!testMode && (!realOutStream)) + continue; + + RINOK(extractCallback->PrepareOperation(askMode)); + + localProgressSpec->Init(extractCallback, false); + localCompressProgressSpec->Init(progress, ¤tTotalPacked, ¤tTotalUnPacked); + + Int32 res; + RINOK(myDecoder.Decode(m_Archive, item, realOutStream, extractCallback, + compressProgress, _numThreads, res)); + realOutStream.Release(); + + RINOK(extractCallback->SetOperationResult(res)) + } + return S_OK; + COM_TRY_END +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipHandler.h b/CPP/7zip/Archive/Zip/ZipHandler.h new file mode 100755 index 00000000..ea6becd0 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHandler.h @@ -0,0 +1,100 @@ +// Zip/Handler.h + +#ifndef __ZIP_HANDLER_H +#define __ZIP_HANDLER_H + +#include "Common/DynamicBuffer.h" +#include "../../ICoder.h" +#include "../IArchive.h" + +#include "ZipIn.h" +#include "ZipCompressionMode.h" + +#ifdef COMPRESS_MT +#include "../../../Windows/System.h" +#endif + +namespace NArchive { +namespace NZip { + +class CHandler: + public IInArchive, + public IOutArchive, + public ISetProperties, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP3( + IInArchive, + IOutArchive, + ISetProperties + ) + + STDMETHOD(Open)(IInStream *aStream, + const UInt64 *aMaxCheckStartPosition, + IArchiveOpenCallback *anOpenArchiveCallback); + STDMETHOD(Close)(); + STDMETHOD(GetNumberOfItems)(UInt32 *numItems); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *anExtractCallback); + + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); + + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); + STDMETHOD(GetPropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + // IOutArchive + STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback); + STDMETHOD(GetFileTimeType)(UInt32 *timeType); + + // ISetProperties + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties); + + CHandler(); +private: + CObjectVector<CItemEx> m_Items; + CInArchive m_Archive; + bool m_ArchiveIsOpen; + + int m_Level; + int m_MainMethod; + UInt32 m_DicSize; + UInt32 m_NumPasses; + UInt32 m_NumFastBytes; + UInt32 m_NumMatchFinderCycles; + bool m_NumMatchFinderCyclesDefined; + + bool m_IsAesMode; + Byte m_AesKeyMode; + + #ifdef COMPRESS_MT + UInt32 _numThreads; + #endif + + void InitMethodProperties() + { + m_Level = -1; + m_MainMethod = -1; + m_DicSize = + m_NumPasses = + m_NumFastBytes = + m_NumMatchFinderCycles = 0xFFFFFFFF; + m_NumMatchFinderCyclesDefined = false; + m_IsAesMode = false; + m_AesKeyMode = 3; // aes-256 + #ifdef COMPRESS_MT + _numThreads = NWindows::NSystem::GetNumberOfProcessors();; + #endif + } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp new file mode 100755 index 00000000..e2394172 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHandlerOut.cpp @@ -0,0 +1,393 @@ +// Zip/HandlerOut.cpp + +#include "StdAfx.h" + +#include "ZipHandler.h" +#include "ZipUpdate.h" + +#include "Common/StringConvert.h" +#include "Common/ComTry.h" +#include "Common/StringToInt.h" + +#include "Windows/PropVariant.h" +#include "Windows/Time.h" + +#include "../../IPassword.h" +#include "../Common/ItemNameUtils.h" +#include "../Common/ParseProperties.h" +#include "../../Crypto/WzAES/WzAES.h" + +using namespace NWindows; +using namespace NCOM; +using namespace NTime; + +namespace NArchive { +namespace NZip { + +static const UInt32 kDeflateNumPassesX1 = 1; +static const UInt32 kDeflateNumPassesX7 = 3; +static const UInt32 kDeflateNumPassesX9 = 10; + +static const UInt32 kNumFastBytesX1 = 32; +static const UInt32 kNumFastBytesX7 = 64; +static const UInt32 kNumFastBytesX9 = 128; + +static const UInt32 kBZip2NumPassesX1 = 1; +static const UInt32 kBZip2NumPassesX7 = 2; +static const UInt32 kBZip2NumPassesX9 = 7; + +static const UInt32 kBZip2DicSizeX1 = 100000; +static const UInt32 kBZip2DicSizeX3 = 500000; +static const UInt32 kBZip2DicSizeX5 = 900000; + +STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType) +{ + *timeType = NFileTimeType::kDOS; + return S_OK; +} + +static bool IsAsciiString(const UString &s) +{ + for (int i = 0; i < s.Length(); i++) + { + wchar_t c = s[i]; + if (c < 0x20 || c > 0x7F) + return false; + } + return true; +} + +STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, + IArchiveUpdateCallback *updateCallback) +{ + COM_TRY_BEGIN + CObjectVector<CUpdateItem> updateItems; + for(UInt32 i = 0; i < numItems; i++) + { + CUpdateItem updateItem; + Int32 newData; + Int32 newProperties; + UInt32 indexInArchive; + if (!updateCallback) + return E_FAIL; + RINOK(updateCallback->GetUpdateItemInfo(i, + &newData, // 1 - compress 0 - copy + &newProperties, + &indexInArchive)); + updateItem.NewProperties = IntToBool(newProperties); + updateItem.NewData = IntToBool(newData); + updateItem.IndexInArchive = indexInArchive; + updateItem.IndexInClient = i; + // bool existInArchive = (indexInArchive != UInt32(-1)); + if (IntToBool(newProperties)) + { + FILETIME utcFileTime; + UString name; + bool isDirectoryStatusDefined; + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant)); + if (propVariant.vt == VT_EMPTY) + updateItem.Attributes = 0; + else if (propVariant.vt != VT_UI4) + return E_INVALIDARG; + else + updateItem.Attributes = propVariant.ulVal; + } + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant)); + if (propVariant.vt != VT_FILETIME) + return E_INVALIDARG; + utcFileTime = propVariant.filetime; + } + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant)); + if (propVariant.vt == VT_EMPTY) + name.Empty(); + else if (propVariant.vt != VT_BSTR) + return E_INVALIDARG; + else + name = propVariant.bstrVal; + } + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant)); + if (propVariant.vt == VT_EMPTY) + isDirectoryStatusDefined = false; + else if (propVariant.vt != VT_BOOL) + return E_INVALIDARG; + else + { + updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE); + isDirectoryStatusDefined = true; + } + } + FILETIME localFileTime; + if(!FileTimeToLocalFileTime(&utcFileTime, &localFileTime)) + return E_INVALIDARG; + if(!FileTimeToDosTime(localFileTime, updateItem.Time)) + { + // return E_INVALIDARG; + } + + if (!isDirectoryStatusDefined) + updateItem.IsDirectory = ((updateItem.Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + + name = NItemName::MakeLegalName(name); + bool needSlash = updateItem.IsDirectory; + const wchar_t kSlash = L'/'; + if (!name.IsEmpty()) + { + if (name[name.Length() - 1] == kSlash) + { + if (!updateItem.IsDirectory) + return E_INVALIDARG; + needSlash = false; + } + } + if (needSlash) + name += kSlash; + updateItem.Name = UnicodeStringToMultiByte(name, CP_OEMCP); + if (updateItem.Name.Length() > 0xFFFF) + return E_INVALIDARG; + + updateItem.IndexInClient = i; + /* + if(existInArchive) + { + const CItemEx &itemInfo = m_Items[indexInArchive]; + // updateItem.Commented = itemInfo.IsCommented(); + updateItem.Commented = false; + if(updateItem.Commented) + { + updateItem.CommentRange.Position = itemInfo.GetCommentPosition(); + updateItem.CommentRange.Size = itemInfo.CommentSize; + } + } + else + updateItem.Commented = false; + */ + } + if (IntToBool(newData)) + { + UInt64 size; + { + NCOM::CPropVariant propVariant; + RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant)); + if (propVariant.vt != VT_UI8) + return E_INVALIDARG; + size = propVariant.uhVal.QuadPart; + } + updateItem.Size = size; + } + updateItems.Add(updateItem); + } + + CMyComPtr<ICryptoGetTextPassword2> getTextPassword; + if (!getTextPassword) + { + CMyComPtr<IArchiveUpdateCallback> udateCallBack2(updateCallback); + udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); + } + CCompressionMethodMode options; + + if (getTextPassword) + { + CMyComBSTR password; + Int32 passwordIsDefined; + RINOK(getTextPassword->CryptoGetTextPassword2(&passwordIsDefined, &password)); + options.PasswordIsDefined = IntToBool(passwordIsDefined); + if (options.PasswordIsDefined) + { + if (!IsAsciiString((const wchar_t *)password)) + return E_INVALIDARG; + if (m_IsAesMode) + { + if (options.Password.Length() > NCrypto::NWzAES::kPasswordSizeMax) + return E_INVALIDARG; + } + options.Password = UnicodeStringToMultiByte((const wchar_t *)password, CP_OEMCP); + options.IsAesMode = m_IsAesMode; + options.AesKeyMode = m_AesKeyMode; + } + } + else + options.PasswordIsDefined = false; + + int level = m_Level; + if (level < 0) + level = 5; + + Byte mainMethod; + if (m_MainMethod < 0) + mainMethod = (Byte)(((level == 0) ? + NFileHeader::NCompressionMethod::kStored : + NFileHeader::NCompressionMethod::kDeflated)); + else + mainMethod = (Byte)m_MainMethod; + options.MethodSequence.Add(mainMethod); + if (mainMethod != NFileHeader::NCompressionMethod::kStored) + options.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored); + bool isDeflate = (mainMethod == NFileHeader::NCompressionMethod::kDeflated) || + (mainMethod == NFileHeader::NCompressionMethod::kDeflated64); + bool isBZip2 = (mainMethod == NFileHeader::NCompressionMethod::kBZip2); + options.NumPasses = m_NumPasses; + options.DicSize = m_DicSize; + options.NumFastBytes = m_NumFastBytes; + options.NumMatchFinderCycles = m_NumMatchFinderCycles; + options.NumMatchFinderCyclesDefined = m_NumMatchFinderCyclesDefined; + #ifdef COMPRESS_MT + options.NumThreads = _numThreads; + #endif + if (isDeflate) + { + if (options.NumPasses == 0xFFFFFFFF) + options.NumPasses = (level >= 9 ? kDeflateNumPassesX9 : + (level >= 7 ? kDeflateNumPassesX7 : + kDeflateNumPassesX1)); + if (options.NumFastBytes == 0xFFFFFFFF) + options.NumFastBytes = (level >= 9 ? kNumFastBytesX9 : + (level >= 7 ? kNumFastBytesX7 : + kNumFastBytesX1)); + } + if (isBZip2) + { + if (options.NumPasses == 0xFFFFFFFF) + options.NumPasses = (level >= 9 ? kBZip2NumPassesX9 : + (level >= 7 ? kBZip2NumPassesX7 : + kBZip2NumPassesX1)); + if (options.DicSize == 0xFFFFFFFF) + options.DicSize = (level >= 5 ? kBZip2DicSizeX5 : + (level >= 3 ? kBZip2DicSizeX3 : + kBZip2DicSizeX1)); + } + + return Update(m_Items, updateItems, outStream, + m_ArchiveIsOpen ? &m_Archive : NULL, &options, updateCallback); + COM_TRY_END +} + +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) +{ + #ifdef COMPRESS_MT + const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); + _numThreads = numProcessors; + #endif + InitMethodProperties(); + for (int i = 0; i < numProperties; i++) + { + UString name = UString(names[i]); + name.MakeUpper(); + if (name.IsEmpty()) + return E_INVALIDARG; + + const PROPVARIANT &prop = values[i]; + + if (name[0] == L'X') + { + UInt32 level = 9; + RINOK(ParsePropValue(name.Mid(1), prop, level)); + m_Level = level; + continue; + } + else if (name == L"M") + { + if (prop.vt == VT_BSTR) + { + UString valueString = prop.bstrVal; + valueString.MakeUpper(); + if (valueString == L"COPY") + m_MainMethod = NFileHeader::NCompressionMethod::kStored; + else if (valueString == L"DEFLATE") + m_MainMethod = NFileHeader::NCompressionMethod::kDeflated; + else if (valueString == L"DEFLATE64") + m_MainMethod = NFileHeader::NCompressionMethod::kDeflated64; + else if (valueString == L"BZIP2") + m_MainMethod = NFileHeader::NCompressionMethod::kBZip2; + else + return E_INVALIDARG; + } + else if (prop.vt == VT_UI4) + { + switch(prop.ulVal) + { + case NFileHeader::NCompressionMethod::kStored: + case NFileHeader::NCompressionMethod::kDeflated: + case NFileHeader::NCompressionMethod::kDeflated64: + case NFileHeader::NCompressionMethod::kBZip2: + m_MainMethod = (Byte)prop.ulVal; + break; + default: + return E_INVALIDARG; + } + } + else + return E_INVALIDARG; + } + else if (name.Left(2) == L"EM") + { + if (prop.vt == VT_BSTR) + { + UString valueString = prop.bstrVal; + valueString.MakeUpper(); + if (valueString.Left(3) == L"AES") + { + valueString = valueString.Mid(3); + if (valueString == L"128") + m_AesKeyMode = 1; + else if (valueString == L"192") + m_AesKeyMode = 2; + else if (valueString == L"256" || valueString.IsEmpty()) + m_AesKeyMode = 3; + else + return E_INVALIDARG; + m_IsAesMode = true; + } + else if (valueString == L"ZIPCRYPTO") + m_IsAesMode = false; + else + return E_INVALIDARG; + } + else + return E_INVALIDARG; + } + else if (name[0] == L'D') + { + UInt32 dicSize = kBZip2DicSizeX5; + RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize)); + m_DicSize = dicSize; + } + else if (name.Left(4) == L"PASS") + { + UInt32 num = kDeflateNumPassesX9; + RINOK(ParsePropValue(name.Mid(4), prop, num)); + m_NumPasses = num; + } + else if (name.Left(2) == L"FB") + { + UInt32 num = kNumFastBytesX9; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + m_NumFastBytes = num; + } + else if (name.Left(2) == L"MC") + { + UInt32 num = 0xFFFFFFFF; + RINOK(ParsePropValue(name.Mid(2), prop, num)); + m_NumMatchFinderCycles = num; + m_NumMatchFinderCyclesDefined = true; + } + else if (name.Left(2) == L"MT") + { + #ifdef COMPRESS_MT + RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads)); + #endif + } + else + return E_INVALIDARG; + } + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipHeader.cpp b/CPP/7zip/Archive/Zip/ZipHeader.cpp new file mode 100755 index 00000000..fd8856bb --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHeader.cpp @@ -0,0 +1,36 @@ +// Archive/Zip/Header.h + +#include "StdAfx.h" + +#include "ZipHeader.h" + +namespace NArchive { +namespace NZip { + +namespace NSignature +{ + UInt32 kLocalFileHeader = 0x04034B50 + 1; + UInt32 kDataDescriptor = 0x08074B50 + 1; + UInt32 kCentralFileHeader = 0x02014B50 + 1; + UInt32 kEndOfCentralDir = 0x06054B50 + 1; + UInt32 kZip64EndOfCentralDir = 0x06064B50 + 1; + UInt32 kZip64EndOfCentralDirLocator = 0x07064B50 + 1; + + class CMarkersInitializer + { + public: + CMarkersInitializer() + { + kLocalFileHeader--; + kDataDescriptor--; + kCentralFileHeader--; + kEndOfCentralDir--; + kZip64EndOfCentralDir--; + kZip64EndOfCentralDirLocator--; + } + }; + static CMarkersInitializer g_MarkerInitializer; +} + +}} + diff --git a/CPP/7zip/Archive/Zip/ZipHeader.h b/CPP/7zip/Archive/Zip/ZipHeader.h new file mode 100755 index 00000000..ac98ea76 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipHeader.h @@ -0,0 +1,248 @@ +// Archive/Zip/Header.h + +#ifndef __ARCHIVE_ZIP_HEADER_H +#define __ARCHIVE_ZIP_HEADER_H + +#include "Common/Types.h" + +namespace NArchive { +namespace NZip { + +namespace NSignature +{ + extern UInt32 kLocalFileHeader; + extern UInt32 kDataDescriptor; + extern UInt32 kCentralFileHeader; + extern UInt32 kEndOfCentralDir; + extern UInt32 kZip64EndOfCentralDir; + extern UInt32 kZip64EndOfCentralDirLocator; + + static const UInt32 kMarkerSize = 4; +} + +const UInt32 kEcdSize = 22; +const UInt32 kZip64EcdSize = 44; +const UInt32 kZip64EcdLocatorSize = 20; +/* +struct CEndOfCentralDirectoryRecord +{ + UInt16 ThisDiskNumber; + UInt16 StartCentralDirectoryDiskNumber; + UInt16 NumEntriesInCentaralDirectoryOnThisDisk; + UInt16 NumEntriesInCentaralDirectory; + UInt32 CentralDirectorySize; + UInt32 CentralDirectoryStartOffset; + UInt16 CommentSize; +}; + +struct CEndOfCentralDirectoryRecordFull +{ + UInt32 Signature; + CEndOfCentralDirectoryRecord Header; +}; +*/ + +namespace NFileHeader +{ + /* + struct CVersion + { + Byte Version; + Byte HostOS; + }; + */ + + namespace NCompressionMethod + { + enum EType + { + kStored = 0, + kShrunk = 1, + kReduced1 = 2, + kReduced2 = 3, + kReduced3 = 4, + kReduced4 = 5, + kImploded = 6, + kReservedTokenizing = 7, // reserved for tokenizing + kDeflated = 8, + kDeflated64 = 9, + kPKImploding = 10, + + kBZip2 = 12, + kWzPPMd = 0x62, + kWzAES = 0x63 + }; + const int kNumCompressionMethods = 11; + const Byte kMadeByProgramVersion = 20; + + const Byte kDeflateExtractVersion = 20; + const Byte kStoreExtractVersion = 10; + + const Byte kSupportedVersion = 20; + } + + namespace NExtraID + { + enum + { + kZip64 = 0x01, + kWzAES = 0x9901 + }; + } + + const UInt32 kLocalBlockSize = 26; + /* + struct CLocalBlock + { + CVersion ExtractVersion; + + UInt16 Flags; + UInt16 CompressionMethod; + UInt32 Time; + UInt32 FileCRC; + UInt32 PackSize; + UInt32 UnPackSize; + UInt16 NameSize; + UInt16 ExtraSize; + }; + */ + + const UInt32 kDataDescriptorSize = 16; + /* + struct CDataDescriptor + { + UInt32 Signature; + UInt32 FileCRC; + UInt32 PackSize; + UInt32 UnPackSize; + }; + + struct CLocalBlockFull + { + UInt32 Signature; + CLocalBlock Header; + }; + */ + + const UInt32 kCentralBlockSize = 42; + /* + struct CBlock + { + CVersion MadeByVersion; + CVersion ExtractVersion; + UInt16 Flags; + UInt16 CompressionMethod; + UInt32 Time; + UInt32 FileCRC; + UInt32 PackSize; + UInt32 UnPackSize; + UInt16 NameSize; + UInt16 ExtraSize; + UInt16 CommentSize; + UInt16 DiskNumberStart; + UInt16 InternalAttributes; + UInt32 ExternalAttributes; + UInt32 LocalHeaderOffset; + }; + + struct CBlockFull + { + UInt32 Signature; + CBlock Header; + }; + */ + + namespace NFlags + { + const int kNumUsedBits = 4; + const int kUsedBitsMask = (1 << kNumUsedBits) - 1; + + const int kEncryptedMask = 1 << 0; + const int kDescriptorUsedMask = 1 << 3; + + const int kImplodeDictionarySizeMask = 1 << 1; + const int kImplodeLiteralsOnMask = 1 << 2; + + const int kDeflateTypeBitStart = 1; + const int kNumDeflateTypeBits = 2; + const int kNumDeflateTypes = (1 << kNumDeflateTypeBits); + const int kDeflateTypeMask = (1 << kNumDeflateTypeBits) - 1; + } + + namespace NHostOS + { + enum EEnum + { + kFAT = 0, // filesystem used by MS-DOS, OS/2, Win32 + // pkzip 2.50 (FAT / VFAT / FAT32 file systems) + kAMIGA = 1, + kVMS = 2, // VAX/VMS + kUnix = 3, + kVM_CMS = 4, + kAtari = 5, // what if it's a minix filesystem? [cjh] + kHPFS = 6, // filesystem used by OS/2 (and NT 3.x) + kMac = 7, + kZ_System = 8, + kCPM = 9, + kTOPS20 = 10, // pkzip 2.50 NTFS + kNTFS = 11, // filesystem used by Windows NT + kQDOS = 12, // SMS/QDOS + kAcorn = 13, // Archimedes Acorn RISC OS + kVFAT = 14, // filesystem used by Windows 95, NT + kMVS = 15, + kBeOS = 16, // hybrid POSIX/database filesystem + // BeBOX or PowerMac + kTandem = 17, + kTHEOS = 18 + }; + // const int kNumHostSystems = 19; + } + namespace NUnixAttribute + { + const UInt32 kIFMT = 0170000; /* Unix file type mask */ + + const UInt32 kIFDIR = 0040000; /* Unix directory */ + const UInt32 kIFREG = 0100000; /* Unix regular file */ + const UInt32 kIFSOCK = 0140000; /* Unix socket (BSD, not SysV or Amiga) */ + const UInt32 kIFLNK = 0120000; /* Unix symbolic link (not SysV, Amiga) */ + const UInt32 kIFBLK = 0060000; /* Unix block special (not Amiga) */ + const UInt32 kIFCHR = 0020000; /* Unix character special (not Amiga) */ + const UInt32 kIFIFO = 0010000; /* Unix fifo (BCC, not MSC or Amiga) */ + + const UInt32 kISUID = 04000; /* Unix set user id on execution */ + const UInt32 kISGID = 02000; /* Unix set group id on execution */ + const UInt32 kISVTX = 01000; /* Unix directory permissions control */ + const UInt32 kENFMT = kISGID; /* Unix record locking enforcement flag */ + const UInt32 kIRWXU = 00700; /* Unix read, write, execute: owner */ + const UInt32 kIRUSR = 00400; /* Unix read permission: owner */ + const UInt32 kIWUSR = 00200; /* Unix write permission: owner */ + const UInt32 kIXUSR = 00100; /* Unix execute permission: owner */ + const UInt32 kIRWXG = 00070; /* Unix read, write, execute: group */ + const UInt32 kIRGRP = 00040; /* Unix read permission: group */ + const UInt32 kIWGRP = 00020; /* Unix write permission: group */ + const UInt32 kIXGRP = 00010; /* Unix execute permission: group */ + const UInt32 kIRWXO = 00007; /* Unix read, write, execute: other */ + const UInt32 kIROTH = 00004; /* Unix read permission: other */ + const UInt32 kIWOTH = 00002; /* Unix write permission: other */ + const UInt32 kIXOTH = 00001; /* Unix execute permission: other */ + } + + namespace NAmigaAttribute + { + const UInt32 kIFMT = 06000; /* Amiga file type mask */ + const UInt32 kIFDIR = 04000; /* Amiga directory */ + const UInt32 kIFREG = 02000; /* Amiga regular file */ + const UInt32 kIHIDDEN = 00200; /* to be supported in AmigaDOS 3.x */ + const UInt32 kISCRIPT = 00100; /* executable script (text command file) */ + const UInt32 kIPURE = 00040; /* allow loading into resident memory */ + const UInt32 kIARCHIVE = 00020; /* not modified since bit was last set */ + const UInt32 kIREAD = 00010; /* can be opened for reading */ + const UInt32 kIWRITE = 00004; /* can be opened for writing */ + const UInt32 kIEXECUTE = 00002; /* executable image, a loadable runfile */ + const UInt32 kIDELETE = 00001; /* can be deleted */ + } +} + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipIn.cpp b/CPP/7zip/Archive/Zip/ZipIn.cpp new file mode 100755 index 00000000..c9e3a7d1 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipIn.cpp @@ -0,0 +1,797 @@ +// Archive/ZipIn.cpp + +#include "StdAfx.h" + +#include "ZipIn.h" +#include "Windows/Defs.h" +#include "Common/StringConvert.h" +#include "Common/DynamicBuffer.h" +#include "../../Common/LimitedStreams.h" +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace NZip { + +// static const char kEndOfString = '\0'; + +bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit) +{ + m_Stream = inStream; + if(m_Stream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition) != S_OK) + return false; + m_Position = m_StreamStartPosition; + return FindAndReadMarker(searchHeaderSizeLimit); +} + +void CInArchive::Close() +{ + m_Stream.Release(); +} + +HRESULT CInArchive::Seek(UInt64 offset) +{ + return m_Stream->Seek(offset, STREAM_SEEK_SET, NULL); +} + +////////////////////////////////////// +// Markers + +static inline bool TestMarkerCandidate(const Byte *p, UInt32 &value) +{ + value = p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24); + return (value == NSignature::kLocalFileHeader) || + (value == NSignature::kEndOfCentralDir); +} + +bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit) +{ + m_ArchiveInfo.Clear(); + m_Position = m_StreamStartPosition; + if(Seek(m_StreamStartPosition) != S_OK) + return false; + + Byte marker[NSignature::kMarkerSize]; + UInt32 processedSize; + ReadBytes(marker, NSignature::kMarkerSize, &processedSize); + if(processedSize != NSignature::kMarkerSize) + return false; + if (TestMarkerCandidate(marker, m_Signature)) + return true; + + CByteDynamicBuffer dynamicBuffer; + static const UInt32 kSearchMarkerBufferSize = 0x10000; + dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize); + Byte *buffer = dynamicBuffer; + UInt32 numBytesPrev = NSignature::kMarkerSize - 1; + memmove(buffer, marker + 1, numBytesPrev); + UInt64 curTestPos = m_StreamStartPosition + 1; + for (;;) + { + if (searchHeaderSizeLimit != NULL) + if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit) + break; + UInt32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev; + ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize); + UInt32 numBytesInBuffer = numBytesPrev + processedSize; + if (numBytesInBuffer < NSignature::kMarkerSize) + break; + UInt32 numTests = numBytesInBuffer - NSignature::kMarkerSize + 1; + for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++) + { + if (TestMarkerCandidate(buffer + pos, m_Signature)) + { + m_ArchiveInfo.StartPosition = curTestPos; + // m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition; + // m_ArchiveInfo.Base = 0; + m_Position = curTestPos + NSignature::kMarkerSize; + if(Seek(m_Position) != S_OK) + return false; + return true; + } + } + numBytesPrev = numBytesInBuffer - numTests; + memmove(buffer, buffer + numTests, numBytesPrev); + } + return false; +} + +HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessedSize; + HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize); + if(processedSize != NULL) + *processedSize = realProcessedSize; + m_Position += realProcessedSize; + return result; +} + +void CInArchive::IncreaseRealPosition(UInt64 addValue) +{ + if(m_Stream->Seek(addValue, STREAM_SEEK_CUR, &m_Position) != S_OK) + throw CInArchiveException(CInArchiveException::kSeekStreamError); +} + +bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size) +{ + UInt32 realProcessedSize; + if(ReadBytes(data, size, &realProcessedSize) != S_OK) + throw CInArchiveException(CInArchiveException::kReadStreamError); + return (realProcessedSize == size); +} + +void CInArchive::SafeReadBytes(void *data, UInt32 size) +{ + if(!ReadBytesAndTestSize(data, size)) + throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive); +} + +void CInArchive::ReadBuffer(CByteBuffer &buffer, UInt32 size) +{ + buffer.SetCapacity(size); + if (size > 0) + SafeReadBytes(buffer, size); +} + +Byte CInArchive::ReadByte() +{ + Byte b; + SafeReadBytes(&b, 1); + return b; +} + +UInt16 CInArchive::ReadUInt16() +{ + UInt16 value = 0; + for (int i = 0; i < 2; i++) + value |= (((UInt16)ReadByte()) << (8 * i)); + return value; +} + +UInt32 CInArchive::ReadUInt32() +{ + UInt32 value = 0; + for (int i = 0; i < 4; i++) + value |= (((UInt32)ReadByte()) << (8 * i)); + return value; +} + +UInt64 CInArchive::ReadUInt64() +{ + UInt64 value = 0; + for (int i = 0; i < 8; i++) + value |= (((UInt64)ReadByte()) << (8 * i)); + return value; +} + +bool CInArchive::ReadUInt32(UInt32 &value) +{ + value = 0; + for (int i = 0; i < 4; i++) + { + Byte b; + if (!ReadBytesAndTestSize(&b, 1)) + return false; + value |= (UInt32(b) << (8 * i)); + } + return true; +} + + +AString CInArchive::ReadFileName(UInt32 nameSize) +{ + if (nameSize == 0) + return AString(); + SafeReadBytes(m_NameBuffer.GetBuffer(nameSize), nameSize); + m_NameBuffer.ReleaseBuffer(nameSize); + return m_NameBuffer; +} + +void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const +{ + archiveInfo = m_ArchiveInfo; +} + +/* +void CInArchive::ThrowIncorrectArchiveException() +{ + throw CInArchiveException(CInArchiveException::kIncorrectArchive); +} +*/ + +static UInt32 GetUInt32(const Byte *data) +{ + return + ((UInt32)(Byte)data[0]) | + (((UInt32)(Byte)data[1]) << 8) | + (((UInt32)(Byte)data[2]) << 16) | + (((UInt32)(Byte)data[3]) << 24); +} + +/* +static UInt16 GetUInt16(const Byte *data) +{ + return + ((UInt16)(Byte)data[0]) | + (((UInt16)(Byte)data[1]) << 8); +} +*/ + +static UInt64 GetUInt64(const Byte *data) +{ + return GetUInt32(data) | ((UInt64)GetUInt32(data + 4) << 32); +} + + + +void CInArchive::ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, + UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber) +{ + extraBlock.Clear(); + UInt32 remain = extraSize; + while(remain >= 4) + { + CExtraSubBlock subBlock; + subBlock.ID = ReadUInt16(); + UInt32 dataSize = ReadUInt16(); + remain -= 4; + if (dataSize > remain) // it's bug + dataSize = remain; + if (subBlock.ID == NFileHeader::NExtraID::kZip64) + { + if (unpackSize == 0xFFFFFFFF) + { + if (dataSize < 8) + break; + unpackSize = ReadUInt64(); + remain -= 8; + dataSize -= 8; + } + if (packSize == 0xFFFFFFFF) + { + if (dataSize < 8) + break; + packSize = ReadUInt64(); + remain -= 8; + dataSize -= 8; + } + if (localHeaderOffset == 0xFFFFFFFF) + { + if (dataSize < 8) + break; + localHeaderOffset = ReadUInt64(); + remain -= 8; + dataSize -= 8; + } + if (diskStartNumber == 0xFFFF) + { + if (dataSize < 4) + break; + diskStartNumber = ReadUInt32(); + remain -= 4; + dataSize -= 4; + } + for (UInt32 i = 0; i < dataSize; i++) + ReadByte(); + } + else + { + ReadBuffer(subBlock.Data, dataSize); + extraBlock.SubBlocks.Add(subBlock); + } + remain -= dataSize; + } + IncreaseRealPosition(remain); +} + +HRESULT CInArchive::ReadLocalItem(CItemEx &item) +{ + item.ExtractVersion.Version = ReadByte(); + item.ExtractVersion.HostOS = ReadByte(); + item.Flags = ReadUInt16(); // & NFileHeader::NFlags::kUsedBitsMask; + item.CompressionMethod = ReadUInt16(); + item.Time = ReadUInt32(); + item.FileCRC = ReadUInt32(); + item.PackSize = ReadUInt32(); + item.UnPackSize = ReadUInt32(); + UInt32 fileNameSize = ReadUInt16(); + item.LocalExtraSize = ReadUInt16(); + item.Name = ReadFileName(fileNameSize); + item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize; + if (item.LocalExtraSize > 0) + { + UInt64 localHeaderOffset = 0; + UInt32 diskStartNumber = 0; + ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize, + localHeaderOffset, diskStartNumber); + } + /* + if (item.IsDirectory()) + item.UnPackSize = 0; // check It + */ + return S_OK; +} + +HRESULT CInArchive::ReadLocalItemAfterCdItem(CItemEx &item) +{ + if (item.FromLocal) + return S_OK; + try + { + RINOK(Seek(m_ArchiveInfo.Base + item.LocalHeaderPosition)); + CItemEx localItem; + if (ReadUInt32() != NSignature::kLocalFileHeader) + return S_FALSE; + RINOK(ReadLocalItem(localItem)); + if (item.Flags != localItem.Flags) + { + if (item.CompressionMethod != NFileHeader::NCompressionMethod::kDeflated || + (item.Flags & 0xFFFC) != (localItem.Flags & 0xFFFC)) + return S_FALSE; + } + + if (item.CompressionMethod != localItem.CompressionMethod || + // item.Time != localItem.Time || + (!localItem.HasDescriptor() && + ( + item.FileCRC != localItem.FileCRC || + item.PackSize != localItem.PackSize || + item.UnPackSize != localItem.UnPackSize + ) + ) || + item.Name.Length() != localItem.Name.Length() + ) + return S_FALSE; + item.FileHeaderWithNameSize = localItem.FileHeaderWithNameSize; + item.LocalExtraSize = localItem.LocalExtraSize; + item.LocalExtra = localItem.LocalExtra; + item.FromLocal = true; + } + catch(...) { return S_FALSE; } + return S_OK; +} + +HRESULT CInArchive::ReadLocalItemDescriptor(CItemEx &item) +{ + if (item.HasDescriptor()) + { + const int kBufferSize = (1 << 12); + Byte buffer[kBufferSize]; + + UInt32 numBytesInBuffer = 0; + UInt32 packedSize = 0; + + bool descriptorWasFound = false; + for (;;) + { + UInt32 processedSize; + RINOK(ReadBytes(buffer + numBytesInBuffer, kBufferSize - numBytesInBuffer, &processedSize)); + numBytesInBuffer += processedSize; + if (numBytesInBuffer < NFileHeader::kDataDescriptorSize) + return S_FALSE; + UInt32 i; + for (i = 0; i <= numBytesInBuffer - NFileHeader::kDataDescriptorSize; i++) + { + // descriptorSignature field is Info-ZIP's extension + // to Zip specification. + UInt32 descriptorSignature = GetUInt32(buffer + i); + + // !!!! It must be fixed for Zip64 archives + UInt32 descriptorPackSize = GetUInt32(buffer + i + 8); + if (descriptorSignature== NSignature::kDataDescriptor && descriptorPackSize == packedSize + i) + { + descriptorWasFound = true; + item.FileCRC = GetUInt32(buffer + i + 4); + item.PackSize = descriptorPackSize; + item.UnPackSize = GetUInt32(buffer + i + 12); + IncreaseRealPosition(Int64(Int32(0 - (numBytesInBuffer - i - NFileHeader::kDataDescriptorSize)))); + break; + } + } + if (descriptorWasFound) + break; + packedSize += i; + int j; + for (j = 0; i < numBytesInBuffer; i++, j++) + buffer[j] = buffer[i]; + numBytesInBuffer = j; + } + } + else + IncreaseRealPosition(item.PackSize); + return S_OK; +} + +HRESULT CInArchive::ReadLocalItemAfterCdItemFull(CItemEx &item) +{ + if (item.FromLocal) + return S_OK; + try + { + RINOK(ReadLocalItemAfterCdItem(item)); + if (item.HasDescriptor()) + { + RINOK(Seek(m_ArchiveInfo.Base + item.GetDataPosition() + item.PackSize)); + if (ReadUInt32() != NSignature::kDataDescriptor) + return S_FALSE; + UInt32 crc = ReadUInt32(); + UInt32 packSize = ReadUInt32(); + UInt32 unpackSize = ReadUInt32(); + if (crc != item.FileCRC || item.PackSize != packSize || item.UnPackSize != unpackSize) + return S_FALSE; + } + } + catch(...) { return S_FALSE; } + return S_OK; +} + +HRESULT CInArchive::ReadCdItem(CItemEx &item) +{ + item.FromCentral = true; + item.MadeByVersion.Version = ReadByte(); + item.MadeByVersion.HostOS = ReadByte(); + item.ExtractVersion.Version = ReadByte(); + item.ExtractVersion.HostOS = ReadByte(); + item.Flags = ReadUInt16(); // & NFileHeader::NFlags::kUsedBitsMask; + item.CompressionMethod = ReadUInt16(); + item.Time = ReadUInt32(); + item.FileCRC = ReadUInt32(); + item.PackSize = ReadUInt32(); + item.UnPackSize = ReadUInt32(); + UInt16 headerNameSize = ReadUInt16(); + UInt16 headerExtraSize = ReadUInt16(); + UInt16 headerCommentSize = ReadUInt16(); + UInt32 headerDiskNumberStart = ReadUInt16(); + item.InternalAttributes = ReadUInt16(); + item.ExternalAttributes = ReadUInt32(); + item.LocalHeaderPosition = ReadUInt32(); + item.Name = ReadFileName(headerNameSize); + + if (headerExtraSize > 0) + { + ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize, + item.LocalHeaderPosition, headerDiskNumberStart); + } + + if (headerDiskNumberStart != 0) + throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + + // May be these strings must be deleted + /* + if (item.IsDirectory()) + item.UnPackSize = 0; + */ + + ReadBuffer(item.Comment, headerCommentSize); + return S_OK; +} + +HRESULT CInArchive::TryEcd64(UInt64 offset, CCdInfo &cdInfo) +{ + RINOK(Seek(offset)); + const UInt32 kEcd64Size = 56; + Byte buf[kEcd64Size]; + if(!ReadBytesAndTestSize(buf, kEcd64Size)) + return S_FALSE; + if (GetUInt32(buf) != NSignature::kZip64EndOfCentralDir) + return S_FALSE; + // cdInfo.NumEntries = GetUInt64(buf + 24); + cdInfo.Size = GetUInt64(buf + 40); + cdInfo.Offset = GetUInt64(buf + 48); + return S_OK; +} + +HRESULT CInArchive::FindCd(CCdInfo &cdInfo) +{ + UInt64 endPosition; + RINOK(m_Stream->Seek(0, STREAM_SEEK_END, &endPosition)); + const UInt32 kBufSizeMax = (1 << 16) + kEcdSize + kZip64EcdLocatorSize; + Byte buf[kBufSizeMax]; + UInt32 bufSize = (endPosition < kBufSizeMax) ? (UInt32)endPosition : kBufSizeMax; + if (bufSize < kEcdSize) + return S_FALSE; + UInt64 startPosition = endPosition - bufSize; + RINOK(m_Stream->Seek(startPosition, STREAM_SEEK_SET, &m_Position)); + if (m_Position != startPosition) + return S_FALSE; + if (!ReadBytesAndTestSize(buf, bufSize)) + return S_FALSE; + for (int i = (int)(bufSize - kEcdSize); i >= 0; i--) + { + if (GetUInt32(buf + i) == NSignature::kEndOfCentralDir) + { + if (i >= kZip64EcdLocatorSize) + { + const Byte *locator = buf + i - kZip64EcdLocatorSize; + if (GetUInt32(locator) == NSignature::kZip64EndOfCentralDirLocator) + { + UInt64 ecd64Offset = GetUInt64(locator + 8); + if (TryEcd64(ecd64Offset, cdInfo) == S_OK) + return S_OK; + if (TryEcd64(m_ArchiveInfo.StartPosition + ecd64Offset, cdInfo) == S_OK) + { + m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition; + return S_OK; + } + } + } + if (GetUInt32(buf + i + 4) == 0) + { + // cdInfo.NumEntries = GetUInt16(buf + i + 10); + cdInfo.Size = GetUInt32(buf + i + 12); + cdInfo.Offset = GetUInt32(buf + i + 16); + return S_OK; + } + } + } + return S_FALSE; +} + +HRESULT CInArchive::TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize) +{ + items.Clear(); + RINOK(m_Stream->Seek(cdOffset, STREAM_SEEK_SET, &m_Position)); + if (m_Position != cdOffset) + return S_FALSE; + while(m_Position - cdOffset < cdSize) + { + if(ReadUInt32() != NSignature::kCentralFileHeader) + return S_FALSE; + CItemEx cdItem; + RINOK(ReadCdItem(cdItem)); + items.Add(cdItem); + } + return (m_Position - cdOffset == cdSize) ? S_OK : S_FALSE; +} + +HRESULT CInArchive::ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize) +{ + m_ArchiveInfo.Base = 0; + CCdInfo cdInfo; + RINOK(FindCd(cdInfo)); + HRESULT res = S_FALSE; + cdSize = cdInfo.Size; + cdOffset = cdInfo.Offset; + res = TryReadCd(items, m_ArchiveInfo.Base + cdOffset, cdSize); + if (res == S_FALSE && m_ArchiveInfo.Base == 0) + { + res = TryReadCd(items, cdInfo.Offset + m_ArchiveInfo.StartPosition, cdSize); + if (res == S_OK) + m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition; + } + if (!ReadUInt32(m_Signature)) + return S_FALSE; + return res; +} + +HRESULT CInArchive::ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset) +{ + items.Clear(); + while (m_Signature == NSignature::kLocalFileHeader) + { + // FSeek points to next byte after signature + // NFileHeader::CLocalBlock localHeader; + CItemEx item; + item.LocalHeaderPosition = m_Position - m_StreamStartPosition - 4; // points to signature; + RINOK(ReadLocalItem(item)); + item.FromLocal = true; + ReadLocalItemDescriptor(item); + items.Add(item); + if (progress != 0) + { + UInt64 numItems = items.Size(); + RINOK(progress->SetCompleted(&numItems)); + } + if (!ReadUInt32(m_Signature)) + break; + } + cdOffset = m_Position - 4; + for(int i = 0; i < items.Size(); i++) + { + if (progress != 0) + { + UInt64 numItems = items.Size(); + RINOK(progress->SetCompleted(&numItems)); + } + if(m_Signature != NSignature::kCentralFileHeader) + return S_FALSE; + + CItemEx cdItem; + RINOK(ReadCdItem(cdItem)); + + if (i == 0) + { + if (cdItem.LocalHeaderPosition == 0) + m_ArchiveInfo.Base = m_ArchiveInfo.StartPosition; + } + + int index; + int left = 0, right = items.Size(); + for (;;) + { + if (left >= right) + return S_FALSE; + index = (left + right) / 2; + UInt64 position = items[index].LocalHeaderPosition - m_ArchiveInfo.Base; + if (cdItem.LocalHeaderPosition == position) + break; + if (cdItem.LocalHeaderPosition < position) + right = index; + else + left = index + 1; + } + CItemEx &item = items[index]; + item.LocalHeaderPosition = cdItem.LocalHeaderPosition; + item.MadeByVersion = cdItem.MadeByVersion; + item.CentralExtra = cdItem.CentralExtra; + + if ( + // item.ExtractVersion != cdItem.ExtractVersion || + item.Flags != cdItem.Flags || + item.CompressionMethod != cdItem.CompressionMethod || + // item.Time != cdItem.Time || + item.FileCRC != cdItem.FileCRC) + return S_FALSE; + + if (item.Name.Length() != cdItem.Name.Length() || + item.PackSize != cdItem.PackSize || + item.UnPackSize != cdItem.UnPackSize + ) + return S_FALSE; + item.Name = cdItem.Name; + item.InternalAttributes = cdItem.InternalAttributes; + item.ExternalAttributes = cdItem.ExternalAttributes; + item.Comment = cdItem.Comment; + item.FromCentral = cdItem.FromCentral; + if (!ReadUInt32(m_Signature)) + return S_FALSE; + } + return S_OK; +} + +HRESULT CInArchive::ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress) +{ + // m_Signature must be kLocalFileHeaderSignature or + // kEndOfCentralDirSignature + // m_Position points to next byte after signature + + items.Clear(); + if (progress != 0) + { + UInt64 numItems = items.Size(); + RINOK(progress->SetCompleted(&numItems)); + } + + UInt64 cdSize, cdStartOffset; + HRESULT res = ReadCd(items, cdStartOffset, cdSize); + if (res != S_FALSE && res != S_OK) + return res; + + /* + if (res != S_OK) + return res; + res = S_FALSE; + */ + + if (res == S_FALSE) + { + m_ArchiveInfo.Base = 0; + RINOK(m_Stream->Seek(m_ArchiveInfo.StartPosition, STREAM_SEEK_SET, &m_Position)); + if (m_Position != m_ArchiveInfo.StartPosition) + return S_FALSE; + if (!ReadUInt32(m_Signature)) + return S_FALSE; + RINOK(ReadLocalsAndCd(items, progress, cdStartOffset)); + cdSize = (m_Position - 4) - cdStartOffset; + cdStartOffset -= m_ArchiveInfo.Base; + } + + UInt32 thisDiskNumber = 0; + UInt32 startCDDiskNumber = 0; + UInt64 numEntriesInCDOnThisDisk = 0; + UInt64 numEntriesInCD = 0; + UInt64 cdSizeFromRecord = 0; + UInt64 cdStartOffsetFromRecord = 0; + bool isZip64 = false; + UInt64 zip64EcdStartOffset = m_Position - 4 - m_ArchiveInfo.Base; + if(m_Signature == NSignature::kZip64EndOfCentralDir) + { + isZip64 = true; + UInt64 recordSize = ReadUInt64(); + /* UInt16 versionMade = */ ReadUInt16(); + /* UInt16 versionNeedExtract = */ ReadUInt16(); + thisDiskNumber = ReadUInt32(); + startCDDiskNumber = ReadUInt32(); + numEntriesInCDOnThisDisk = ReadUInt64(); + numEntriesInCD = ReadUInt64(); + cdSizeFromRecord = ReadUInt64(); + cdStartOffsetFromRecord = ReadUInt64(); + IncreaseRealPosition(recordSize - kZip64EcdSize); + if (!ReadUInt32(m_Signature)) + return S_FALSE; + if (thisDiskNumber != 0 || startCDDiskNumber != 0) + throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if (numEntriesInCDOnThisDisk != items.Size() || + numEntriesInCD != items.Size() || + cdSizeFromRecord != cdSize || + (cdStartOffsetFromRecord != cdStartOffset && + (!items.IsEmpty()))) + return S_FALSE; + } + if(m_Signature == NSignature::kZip64EndOfCentralDirLocator) + { + /* UInt32 startEndCDDiskNumber = */ ReadUInt32(); + UInt64 endCDStartOffset = ReadUInt64(); + /* UInt32 numberOfDisks = */ ReadUInt32(); + if (zip64EcdStartOffset != endCDStartOffset) + return S_FALSE; + if (!ReadUInt32(m_Signature)) + return S_FALSE; + } + if(m_Signature != NSignature::kEndOfCentralDir) + return S_FALSE; + + UInt16 thisDiskNumber16 = ReadUInt16(); + if (!isZip64 || thisDiskNumber16) + thisDiskNumber = thisDiskNumber16; + + UInt16 startCDDiskNumber16 = ReadUInt16(); + if (!isZip64 || startCDDiskNumber16 != 0xFFFF) + startCDDiskNumber = startCDDiskNumber16; + + UInt16 numEntriesInCDOnThisDisk16 = ReadUInt16(); + if (!isZip64 || numEntriesInCDOnThisDisk16 != 0xFFFF) + numEntriesInCDOnThisDisk = numEntriesInCDOnThisDisk16; + + UInt16 numEntriesInCD16 = ReadUInt16(); + if (!isZip64 || numEntriesInCD16 != 0xFFFF) + numEntriesInCD = numEntriesInCD16; + + UInt32 cdSizeFromRecord32 = ReadUInt32(); + if (!isZip64 || cdSizeFromRecord32 != 0xFFFFFFFF) + cdSizeFromRecord = cdSizeFromRecord32; + + UInt32 cdStartOffsetFromRecord32 = ReadUInt32(); + if (!isZip64 || cdStartOffsetFromRecord32 != 0xFFFFFFFF) + cdStartOffsetFromRecord = cdStartOffsetFromRecord32; + + UInt16 commentSize = ReadUInt16(); + ReadBuffer(m_ArchiveInfo.Comment, commentSize); + + if (thisDiskNumber != 0 || startCDDiskNumber != 0) + throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported); + if ((UInt16)numEntriesInCDOnThisDisk != ((UInt16)items.Size()) || + (UInt16)numEntriesInCD != ((UInt16)items.Size()) || + (UInt32)cdSizeFromRecord != (UInt32)cdSize || + ((UInt32)(cdStartOffsetFromRecord) != (UInt32)cdStartOffset && + (!items.IsEmpty()))) + return S_FALSE; + + return S_OK; +} + +ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size) +{ + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<ISequentialInStream> inStream(streamSpec); + SeekInArchive(m_ArchiveInfo.Base + position); + streamSpec->SetStream(m_Stream); + streamSpec->Init(size); + return inStream.Detach(); +} + +IInStream* CInArchive::CreateStream() +{ + CMyComPtr<IInStream> inStream = m_Stream; + return inStream.Detach(); +} + +bool CInArchive::SeekInArchive(UInt64 position) +{ + UInt64 newPosition; + if(m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition) != S_OK) + return false; + return (newPosition == position); +} + +}} + diff --git a/CPP/7zip/Archive/Zip/ZipIn.h b/CPP/7zip/Archive/Zip/ZipIn.h new file mode 100755 index 00000000..80de2272 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipIn.h @@ -0,0 +1,111 @@ +// Archive/ZipIn.h + +#ifndef __ZIP_IN_H +#define __ZIP_IN_H + +#include "Common/MyCom.h" +#include "../../IStream.h" + +#include "ZipHeader.h" +#include "ZipItemEx.h" + +namespace NArchive { +namespace NZip { + +class CInArchiveException +{ +public: + enum ECauseType + { + kUnexpectedEndOfArchive = 0, + kArchiceHeaderCRCError, + kFileHeaderCRCError, + kIncorrectArchive, + kDataDescroptorsAreNotSupported, + kMultiVolumeArchiveAreNotSupported, + kReadStreamError, + kSeekStreamError + } + Cause; + CInArchiveException(ECauseType cause): Cause(cause) {} +}; + +class CInArchiveInfo +{ +public: + UInt64 Base; + UInt64 StartPosition; + CByteBuffer Comment; + CInArchiveInfo(): Base(0), StartPosition(0) {} + void Clear() + { + Base = 0; + StartPosition = 0; + Comment.SetCapacity(0); + } +}; + +class CProgressVirt +{ +public: + STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE; +}; + +struct CCdInfo +{ + // UInt64 NumEntries; + UInt64 Size; + UInt64 Offset; +}; + +class CInArchive +{ + CMyComPtr<IInStream> m_Stream; + UInt32 m_Signature; + UInt64 m_StreamStartPosition; + UInt64 m_Position; + CInArchiveInfo m_ArchiveInfo; + AString m_NameBuffer; + + HRESULT Seek(UInt64 offset); + + bool FindAndReadMarker(const UInt64 *searchHeaderSizeLimit); + bool ReadUInt32(UInt32 &signature); + AString ReadFileName(UInt32 nameSize); + + HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize); + bool ReadBytesAndTestSize(void *data, UInt32 size); + void SafeReadBytes(void *data, UInt32 size); + void ReadBuffer(CByteBuffer &buffer, UInt32 size); + Byte ReadByte(); + UInt16 ReadUInt16(); + UInt32 ReadUInt32(); + UInt64 ReadUInt64(); + + void IncreaseRealPosition(UInt64 addValue); + + void ReadExtra(UInt32 extraSize, CExtraBlock &extraBlock, + UInt64 &unpackSize, UInt64 &packSize, UInt64 &localHeaderOffset, UInt32 &diskStartNumber); + HRESULT ReadLocalItem(CItemEx &item); + HRESULT ReadLocalItemDescriptor(CItemEx &item); + HRESULT ReadCdItem(CItemEx &item); + HRESULT TryEcd64(UInt64 offset, CCdInfo &cdInfo); + HRESULT FindCd(CCdInfo &cdInfo); + HRESULT TryReadCd(CObjectVector<CItemEx> &items, UInt64 cdOffset, UInt64 cdSize); + HRESULT ReadCd(CObjectVector<CItemEx> &items, UInt64 &cdOffset, UInt64 &cdSize); + HRESULT ReadLocalsAndCd(CObjectVector<CItemEx> &items, CProgressVirt *progress, UInt64 &cdOffset); +public: + HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress); + HRESULT ReadLocalItemAfterCdItem(CItemEx &item); + HRESULT ReadLocalItemAfterCdItemFull(CItemEx &item); + bool Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit); + void Close(); + void GetArchiveInfo(CInArchiveInfo &archiveInfo) const; + bool SeekInArchive(UInt64 position); + ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size); + IInStream* CreateStream(); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipItem.cpp b/CPP/7zip/Archive/Zip/ZipItem.cpp new file mode 100755 index 00000000..1934c357 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipItem.cpp @@ -0,0 +1,137 @@ +// Archive/ZipItem.cpp + +#include "StdAfx.h" + +#include "ZipHeader.h" +#include "ZipItem.h" +#include "../Common/ItemNameUtils.h" + +namespace NArchive { +namespace NZip { + +bool operator==(const CVersion &v1, const CVersion &v2) +{ + return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS); +} + +bool operator!=(const CVersion &v1, const CVersion &v2) +{ + return !(v1 == v2); +} + +bool CLocalItem::IsEncrypted() const +{ return (Flags & NFileHeader::NFlags::kEncryptedMask) != 0; } +bool CLocalItem::HasDescriptor() const + { return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; } + +bool CLocalItem::IsImplodeBigDictionary() const +{ +if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded) + throw 12312212; + return (Flags & NFileHeader::NFlags::kImplodeDictionarySizeMask) != 0; +} + +bool CLocalItem::IsImplodeLiteralsOn() const +{ + if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded) + throw 12312213; + return (Flags & NFileHeader::NFlags::kImplodeLiteralsOnMask) != 0; +} + +static const char *kUnknownAttributes = "Unknown file attributes"; + +bool CLocalItem::IsDirectory() const +{ + return NItemName::HasTailSlash(Name, GetCodePage()); +} + +bool CItem::IsDirectory() const +{ + if (NItemName::HasTailSlash(Name, GetCodePage())) + return true; + if (!FromCentral) + return false; + WORD highAttributes = WORD((ExternalAttributes >> 16 ) & 0xFFFF); + switch(MadeByVersion.HostOS) + { + case NFileHeader::NHostOS::kAMIGA: + switch (highAttributes & NFileHeader::NAmigaAttribute::kIFMT) + { + case NFileHeader::NAmigaAttribute::kIFDIR: + return true; + case NFileHeader::NAmigaAttribute::kIFREG: + return false; + default: + return false; // change it throw kUnknownAttributes; + } + case NFileHeader::NHostOS::kFAT: + case NFileHeader::NHostOS::kNTFS: + case NFileHeader::NHostOS::kHPFS: + case NFileHeader::NHostOS::kVFAT: + return ((ExternalAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0); + case NFileHeader::NHostOS::kAtari: + case NFileHeader::NHostOS::kMac: + case NFileHeader::NHostOS::kVMS: + case NFileHeader::NHostOS::kVM_CMS: + case NFileHeader::NHostOS::kAcorn: + case NFileHeader::NHostOS::kMVS: + return false; // change it throw kUnknownAttributes; + default: + /* + switch (highAttributes & NFileHeader::NUnixAttribute::kIFMT) + { + case NFileHeader::NUnixAttribute::kIFDIR: + return true; + default: + return false; + } + */ + return false; + } +} + +UInt32 CLocalItem::GetWinAttributes() const +{ + DWORD winAttributes = 0; + if (IsDirectory()) + winAttributes |= FILE_ATTRIBUTE_DIRECTORY; + return winAttributes; +} + +UInt32 CItem::GetWinAttributes() const +{ + DWORD winAttributes = 0; + switch(MadeByVersion.HostOS) + { + case NFileHeader::NHostOS::kFAT: + case NFileHeader::NHostOS::kNTFS: + if (FromCentral) + winAttributes = ExternalAttributes; + break; + default: + winAttributes = 0; // must be converted from unix value; + } + if (IsDirectory()) // test it; + winAttributes |= FILE_ATTRIBUTE_DIRECTORY; + return winAttributes; +} + +void CLocalItem::SetFlagBits(int startBitNumber, int numBits, int value) +{ + UInt16 mask = (UInt16)(((1 << numBits) - 1) << startBitNumber); + Flags &= ~mask; + Flags |= value << startBitNumber; +} + +void CLocalItem::SetBitMask(int bitMask, bool enable) +{ + if(enable) + Flags |= bitMask; + else + Flags &= ~bitMask; +} + +void CLocalItem::SetEncrypted(bool encrypted) + { SetBitMask(NFileHeader::NFlags::kEncryptedMask, encrypted); } + +}} diff --git a/CPP/7zip/Archive/Zip/ZipItem.h b/CPP/7zip/Archive/Zip/ZipItem.h new file mode 100755 index 00000000..765bfd85 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipItem.h @@ -0,0 +1,191 @@ +// Archive/ZipItem.h + +#ifndef __ARCHIVE_ZIP_ITEM_H +#define __ARCHIVE_ZIP_ITEM_H + +#include "Common/Types.h" +#include "Common/String.h" +#include "Common/Buffer.h" + +#include "ZipHeader.h" + +namespace NArchive { +namespace NZip { + +struct CVersion +{ + Byte Version; + Byte HostOS; +}; + +bool operator==(const CVersion &v1, const CVersion &v2); +bool operator!=(const CVersion &v1, const CVersion &v2); + +struct CExtraSubBlock +{ + UInt16 ID; + CByteBuffer Data; +}; + +struct CWzAesExtraField +{ + UInt16 VendorVersion; // 0x0001 - AE-1, 0x0002 - AE-2, + // UInt16 VendorId; // "AE" + Byte Strength; // 1 - 128-bit , 2 - 192-bit , 3 - 256-bit + UInt16 Method; + + CWzAesExtraField(): VendorVersion(2), Strength(3), Method(0) {} + + bool NeedCrc() const { return (VendorVersion == 1); } + + bool ParseFromSubBlock(const CExtraSubBlock &sb) + { + if (sb.ID != NFileHeader::NExtraID::kWzAES) + return false; + if (sb.Data.GetCapacity() < 7) + return false; + const Byte *p = (const Byte *)sb.Data; + VendorVersion = (((UInt16)p[1]) << 8) | p[0]; + if (p[2] != 'A' || p[3] != 'E') + return false; + Strength = p[4]; + Method = (((UInt16)p[6]) << 16) | p[5]; + return true; + } + void SetSubBlock(CExtraSubBlock &sb) const + { + sb.Data.SetCapacity(7); + sb.ID = NFileHeader::NExtraID::kWzAES; + Byte *p = (Byte *)sb.Data; + p[0] = (Byte)VendorVersion; + p[1] = (Byte)(VendorVersion >> 8); + p[2] = 'A'; + p[3] = 'E'; + p[4] = Strength; + p[5] = (Byte)Method; + p[6] = (Byte)(Method >> 8); + } +}; + +struct CExtraBlock +{ + CObjectVector<CExtraSubBlock> SubBlocks; + void Clear() { SubBlocks.Clear(); } + size_t GetSize() const + { + size_t res = 0; + for (int i = 0; i < SubBlocks.Size(); i++) + res += SubBlocks[i].Data.GetCapacity() + 2 + 2; + return res; + } + bool GetWzAesField(CWzAesExtraField &aesField) const + { + // size_t res = 0; + for (int i = 0; i < SubBlocks.Size(); i++) + if (aesField.ParseFromSubBlock(SubBlocks[i])) + return true; + return false; + } + + bool HasWzAesField() const + { + CWzAesExtraField aesField; + return GetWzAesField(aesField); + } + + void RemoveUnknownSubBlocks() + { + for (int i = SubBlocks.Size() - 1; i >= 0;) + { + const CExtraSubBlock &subBlock = SubBlocks[i]; + if (subBlock.ID != NFileHeader::NExtraID::kWzAES) + SubBlocks.Delete(i); + else + i--; + } + } +}; + + +class CLocalItem +{ +public: + CVersion ExtractVersion; + UInt16 Flags; + UInt16 CompressionMethod; + UInt32 Time; + UInt32 FileCRC; + UInt64 PackSize; + UInt64 UnPackSize; + + AString Name; + + CExtraBlock LocalExtra; + + bool IsEncrypted() const; + + bool IsImplodeBigDictionary() const; + bool IsImplodeLiteralsOn() const; + + bool IsDirectory() const; + bool IgnoreItem() const { return false; } + UInt32 GetWinAttributes() const; + + bool HasDescriptor() const; + +private: + void SetFlagBits(int startBitNumber, int numBits, int value); + void SetBitMask(int bitMask, bool enable); +public: + void ClearFlags() { Flags = 0; } + void SetEncrypted(bool encrypted); + + WORD GetCodePage() const + { + return CP_OEMCP; + } +}; + +class CItem: public CLocalItem +{ +public: + CVersion MadeByVersion; + UInt16 InternalAttributes; + UInt32 ExternalAttributes; + + UInt64 LocalHeaderPosition; + + CExtraBlock CentralExtra; + CByteBuffer Comment; + + bool FromLocal; + bool FromCentral; + + bool IsDirectory() const; + UInt32 GetWinAttributes() const; + + bool IsThereCrc() const + { + if (CompressionMethod == NFileHeader::NCompressionMethod::kWzAES) + { + CWzAesExtraField aesField; + if (CentralExtra.GetWzAesField(aesField)) + return aesField.NeedCrc(); + } + return true; + } + + WORD GetCodePage() const + { + return (WORD)((MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT + || MadeByVersion.HostOS == NFileHeader::NHostOS::kNTFS + ) ? CP_OEMCP : CP_ACP); + } + CItem() : FromLocal(false), FromCentral(false) {} +}; + +}} + +#endif + + diff --git a/CPP/7zip/Archive/Zip/ZipItemEx.h b/CPP/7zip/Archive/Zip/ZipItemEx.h new file mode 100755 index 00000000..3cacc0e7 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipItemEx.h @@ -0,0 +1,29 @@ +// Archive/ZipItemEx.h + +#ifndef __ARCHIVE_ZIP_ITEMEX_H +#define __ARCHIVE_ZIP_ITEMEX_H + +#include "ZipHeader.h" +#include "ZipItem.h" + +namespace NArchive { +namespace NZip { + +class CItemEx: public CItem +{ +public: + UInt32 FileHeaderWithNameSize; + UInt16 LocalExtraSize; + + UInt64 GetLocalFullSize() const + { return FileHeaderWithNameSize + LocalExtraSize + PackSize + + (HasDescriptor() ? NFileHeader::kDataDescriptorSize : 0); }; + UInt64 GetLocalExtraPosition() const + { return LocalHeaderPosition + FileHeaderWithNameSize; }; + UInt64 GetDataPosition() const + { return GetLocalExtraPosition() + LocalExtraSize; }; +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipOut.cpp b/CPP/7zip/Archive/Zip/ZipOut.cpp new file mode 100755 index 00000000..7575d320 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipOut.cpp @@ -0,0 +1,259 @@ +// ZipOut.cpp + +#include "StdAfx.h" + +#include "ZipOut.h" +#include "Common/StringConvert.h" +#include "Common/CRC.h" +#include "../../Common/OffsetStream.h" +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace NZip { + +void COutArchive::Create(IOutStream *outStream) +{ + m_Stream = outStream; + m_BasePosition = 0; +} + +void COutArchive::MoveBasePosition(UInt64 distanceToMove) +{ + m_BasePosition += distanceToMove; // test overflow +} + +void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption) +{ + m_IsZip64 = isZip64; + m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0; + if (aesEncryption) + m_ExtraSize += 4 + 7; + m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize; +} + +void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption) +{ + // We test it to 0xF8000000 to support case when compressed size + // can be larger than uncompressed size. + PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000, aesEncryption); +} + +void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption) +{ + bool isUnPack64 = unPackSize >= 0xFFFFFFFF; + bool isPack64 = packSize >= 0xFFFFFFFF; + bool isZip64 = isPack64 || isUnPack64; + PrepareWriteCompressedDataZip64(fileNameLength, isZip64, aesEncryption); +} + +void COutArchive::WriteBytes(const void *buffer, UInt32 size) +{ + UInt32 processedSize; + if(WriteStream(m_Stream, buffer, size, &processedSize) != S_OK) + throw 0; + if(processedSize != size) + throw 0; + m_BasePosition += size; +} + +void COutArchive::WriteByte(Byte b) +{ + WriteBytes(&b, 1); +} + +void COutArchive::WriteUInt16(UInt16 value) +{ + for (int i = 0; i < 2; i++) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +void COutArchive::WriteUInt32(UInt32 value) +{ + for (int i = 0; i < 4; i++) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +void COutArchive::WriteUInt64(UInt64 value) +{ + for (int i = 0; i < 8; i++) + { + WriteByte((Byte)value); + value >>= 8; + } +} + +void COutArchive::WriteExtra(const CExtraBlock &extra) +{ + if (extra.SubBlocks.Size() != 0) + { + for (int i = 0; i < extra.SubBlocks.Size(); i++) + { + const CExtraSubBlock &subBlock = extra.SubBlocks[i]; + WriteUInt16(subBlock.ID); + WriteUInt16((UInt16)subBlock.Data.GetCapacity()); + WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity()); + } + } +} + +HRESULT COutArchive::WriteLocalHeader(const CLocalItem &item) +{ + m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); + + bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; + + WriteUInt32(NSignature::kLocalFileHeader); + WriteByte(item.ExtractVersion.Version); + WriteByte(item.ExtractVersion.HostOS); + WriteUInt16(item.Flags); + WriteUInt16(item.CompressionMethod); + WriteUInt32(item.Time); + WriteUInt32(item.FileCRC); + WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize); + WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize); + WriteUInt16((UInt16)item.Name.Length()); + { + UInt16 localExtraSize = (UInt16)((isZip64 ? (4 + 16): 0) + item.LocalExtra.GetSize()); + if (localExtraSize > m_ExtraSize) + return E_FAIL; + } + WriteUInt16((UInt16)m_ExtraSize); // test it; + WriteBytes((const char *)item.Name, item.Name.Length()); + + UInt32 extraPos = 0; + if (isZip64) + { + extraPos += 4 + 16; + WriteUInt16(NFileHeader::NExtraID::kZip64); + WriteUInt16(16); + WriteUInt64(item.UnPackSize); + WriteUInt64(item.PackSize); + } + + WriteExtra(item.LocalExtra); + extraPos += (UInt32)item.LocalExtra.GetSize(); + for (; extraPos < m_ExtraSize; extraPos++) + WriteByte(0); + + MoveBasePosition(item.PackSize); + return m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); +} + +void COutArchive::WriteCentralHeader(const CItem &item) +{ + m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); + + bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; + bool isPack64 = item.PackSize >= 0xFFFFFFFF; + bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; + bool isZip64 = isPack64 || isUnPack64 || isPosition64; + + WriteUInt32(NSignature::kCentralFileHeader); + WriteByte(item.MadeByVersion.Version); + WriteByte(item.MadeByVersion.HostOS); + WriteByte(item.ExtractVersion.Version); + WriteByte(item.ExtractVersion.HostOS); + WriteUInt16(item.Flags); + WriteUInt16(item.CompressionMethod); + WriteUInt32(item.Time); + WriteUInt32(item.FileCRC); + WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize); + WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize); + WriteUInt16((UInt16)item.Name.Length()); + UInt16 zip64ExtraSize = (UInt16)((isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0)); + UInt16 centralExtraSize = (UInt16)(isZip64 ? (4 + zip64ExtraSize) : 0); + centralExtraSize = (UInt16)(centralExtraSize + item.CentralExtra.GetSize()); + WriteUInt16(centralExtraSize); // test it; + WriteUInt16((UInt16)item.Comment.GetCapacity()); + WriteUInt16(0); // DiskNumberStart; + WriteUInt16(item.InternalAttributes); + WriteUInt32(item.ExternalAttributes); + WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); + WriteBytes((const char *)item.Name, item.Name.Length()); + if (isZip64) + { + WriteUInt16(NFileHeader::NExtraID::kZip64); + WriteUInt16(zip64ExtraSize); + if(isUnPack64) + WriteUInt64(item.UnPackSize); + if(isPack64) + WriteUInt64(item.PackSize); + if(isPosition64) + WriteUInt64(item.LocalHeaderPosition); + } + WriteExtra(item.CentralExtra); + if (item.Comment.GetCapacity() > 0) + WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity()); +} + +void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment) +{ + m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); + + UInt64 cdOffset = GetCurrentPosition(); + for(int i = 0; i < items.Size(); i++) + WriteCentralHeader(items[i]); + UInt64 cd64EndOffset = GetCurrentPosition(); + UInt64 cdSize = cd64EndOffset - cdOffset; + bool cdOffset64 = cdOffset >= 0xFFFFFFFF; + bool cdSize64 = cdSize >= 0xFFFFFFFF; + bool items64 = items.Size() >= 0xFFFF; + bool isZip64 = (cdOffset64 || cdSize64 || items64); + + if (isZip64) + { + WriteUInt32(NSignature::kZip64EndOfCentralDir); + WriteUInt64(kZip64EcdSize); // ThisDiskNumber = 0; + WriteUInt16(45); // version + WriteUInt16(45); // version + WriteUInt32(0); // ThisDiskNumber = 0; + WriteUInt32(0); // StartCentralDirectoryDiskNumber;; + WriteUInt64((UInt64)items.Size()); + WriteUInt64((UInt64)items.Size()); + WriteUInt64((UInt64)cdSize); + WriteUInt64((UInt64)cdOffset); + + WriteUInt32(NSignature::kZip64EndOfCentralDirLocator); + WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory + WriteUInt64(cd64EndOffset); + WriteUInt32(1); // total number of disks + } + WriteUInt32(NSignature::kEndOfCentralDir); + WriteUInt16(0); // ThisDiskNumber = 0; + WriteUInt16(0); // StartCentralDirectoryDiskNumber; + WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size())); + WriteUInt16((UInt16)(items64 ? 0xFFFF: items.Size())); + WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize); + WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset); + UInt16 commentSize = (UInt16)comment.GetCapacity(); + WriteUInt16(commentSize); + if (commentSize > 0) + WriteBytes((const Byte *)comment, commentSize); +} + +void COutArchive::CreateStreamForCompressing(IOutStream **outStream) +{ + COffsetOutStream *streamSpec = new COffsetOutStream; + CMyComPtr<IOutStream> tempStream(streamSpec); + streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize); + *outStream = tempStream.Detach(); +} + +void COutArchive::SeekToPackedDataPosition() +{ + m_Stream->Seek(m_BasePosition + m_LocalFileHeaderSize, STREAM_SEEK_SET, NULL); +} + +void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream) +{ + CMyComPtr<ISequentialOutStream> tempStream(m_Stream); + *outStream = tempStream.Detach(); +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipOut.h b/CPP/7zip/Archive/Zip/ZipOut.h new file mode 100755 index 00000000..e08c306e --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipOut.h @@ -0,0 +1,51 @@ +// ZipOut.h + +#ifndef __ZIP_OUT_H +#define __ZIP_OUT_H + +#include "Common/MyCom.h" + +#include "../../IStream.h" + +#include "ZipItem.h" + +namespace NArchive { +namespace NZip { + +class COutArchive +{ + CMyComPtr<IOutStream> m_Stream; + + UInt64 m_BasePosition; + UInt32 m_LocalFileHeaderSize; + UInt32 m_ExtraSize; + bool m_IsZip64; + + void WriteBytes(const void *buffer, UInt32 size); + void WriteByte(Byte b); + void WriteUInt16(UInt16 value); + void WriteUInt32(UInt32 value); + void WriteUInt64(UInt64 value); + + void WriteExtraHeader(const CItem &item); + void WriteCentralHeader(const CItem &item); + void WriteExtra(const CExtraBlock &extra); +public: + void Create(IOutStream *outStream); + void MoveBasePosition(UInt64 distanceToMove); + UInt64 GetCurrentPosition() const { return m_BasePosition; }; + void PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64, bool aesEncryption); + void PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize, bool aesEncryption); + void PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize, bool aesEncryption); + HRESULT WriteLocalHeader(const CLocalItem &item); + + void WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment); + + void CreateStreamForCompressing(IOutStream **outStream); + void CreateStreamForCopying(ISequentialOutStream **outStream); + void SeekToPackedDataPosition(); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.cpp b/CPP/7zip/Archive/Zip/ZipUpdate.cpp new file mode 100755 index 00000000..f66fcef9 --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipUpdate.cpp @@ -0,0 +1,734 @@ +// ZipUpdate.cpp + +#include "StdAfx.h" + +#include <stdio.h> + +#include "ZipUpdate.h" +#include "ZipAddCommon.h" +#include "ZipOut.h" + +#include "Common/Defs.h" +#include "Common/AutoPtr.h" +#include "Common/StringConvert.h" +#include "Windows/Defs.h" +#include "Windows/Thread.h" + +#include "../../Common/ProgressUtils.h" +#ifdef COMPRESS_MT +#include "../../Common/ProgressMt.h" +#endif +#include "../../Common/LimitedStreams.h" +#include "../../Common/OutMemStream.h" + +#include "../../Compress/Copy/CopyCoder.h" + +using namespace NWindows; +using namespace NSynchronization; + +namespace NArchive { +namespace NZip { + +class CCriticalSectionLock2 +{ + CCriticalSection *_object; + void Unlock() { if (_object != 0) _object->Leave(); } +public: + CCriticalSectionLock2(): _object(0) {} + void Set(CCriticalSection &object) { _object = &object; _object->Enter(); } + ~CCriticalSectionLock2() { Unlock(); } +}; + +static const Byte kMadeByHostOS = NFileHeader::NHostOS::kFAT; +static const Byte kExtractHostOS = NFileHeader::NHostOS::kFAT; + +static const Byte kMethodForDirectory = NFileHeader::NCompressionMethod::kStored; +static const Byte kExtractVersionForDirectory = NFileHeader::NCompressionMethod::kStoreExtractVersion; + +static HRESULT CopyBlockToArchive(ISequentialInStream *inStream, + COutArchive &outArchive, ICompressProgressInfo *progress) +{ + CMyComPtr<ISequentialOutStream> outStream; + outArchive.CreateStreamForCopying(&outStream); + CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder; + return copyCoder->Code(inStream, outStream, NULL, NULL, progress); +} + +static HRESULT WriteRange(IInStream *inStream, COutArchive &outArchive, + const CUpdateRange &range, ICompressProgressInfo *progress) +{ + UInt64 position; + RINOK(inStream->Seek(range.Position, STREAM_SEEK_SET, &position)); + + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; + CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec); + streamSpec->SetStream(inStream); + streamSpec->Init(range.Size); + + RINOK(CopyBlockToArchive(inStreamLimited, outArchive, progress)); + return progress->SetRatioInfo(&range.Size, &range.Size); +} + +static void SetFileHeader( + COutArchive &archive, + const CCompressionMethodMode &options, + const CUpdateItem &updateItem, + CItem &item) +{ + item.UnPackSize = updateItem.Size; + bool isDirectory; + + if (updateItem.NewProperties) + { + isDirectory = updateItem.IsDirectory; + item.Name = updateItem.Name; + item.ExternalAttributes = updateItem.Attributes; + item.Time = updateItem.Time; + } + else + isDirectory = item.IsDirectory(); + + item.LocalHeaderPosition = archive.GetCurrentPosition(); + item.MadeByVersion.HostOS = kMadeByHostOS; + item.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion; + + item.ExtractVersion.HostOS = kExtractHostOS; + + item.InternalAttributes = 0; // test it + item.ClearFlags(); + item.SetEncrypted(!isDirectory && options.PasswordIsDefined); + if (isDirectory) + { + item.ExtractVersion.Version = kExtractVersionForDirectory; + item.CompressionMethod = kMethodForDirectory; + item.PackSize = 0; + item.FileCRC = 0; // test it + } +} + +static void SetItemInfoFromCompressingResult(const CCompressingResult &compressingResult, + bool isAesMode, Byte aesKeyMode, CItem &item) +{ + item.ExtractVersion.Version = compressingResult.ExtractVersion; + item.CompressionMethod = compressingResult.Method; + item.FileCRC = compressingResult.CRC; + item.UnPackSize = compressingResult.UnpackSize; + item.PackSize = compressingResult.PackSize; + + item.LocalExtra.Clear(); + item.CentralExtra.Clear(); + + if (isAesMode) + { + CWzAesExtraField wzAesField; + wzAesField.Strength = aesKeyMode; + wzAesField.Method = compressingResult.Method; + item.CompressionMethod = NFileHeader::NCompressionMethod::kWzAES; + item.FileCRC = 0; + CExtraSubBlock sb; + wzAesField.SetSubBlock(sb); + item.LocalExtra.SubBlocks.Add(sb); + item.CentralExtra.SubBlocks.Add(sb); + } +} + +#ifdef COMPRESS_MT + +static DWORD WINAPI CoderThread(void *threadCoderInfo); + +struct CThreadInfo +{ + NWindows::CThread Thread; + CAutoResetEvent *CompressEvent; + CAutoResetEvent *CompressionCompletedEvent; + bool ExitThread; + + CMtCompressProgress *ProgressSpec; + CMyComPtr<ICompressProgressInfo> Progress; + + COutMemStream *OutStreamSpec; + CMyComPtr<IOutStream> OutStream; + CMyComPtr<ISequentialInStream> InStream; + + CAddCommon Coder; + HRESULT Result; + CCompressingResult CompressingResult; + + bool IsFree; + UInt32 UpdateIndex; + + CThreadInfo(const CCompressionMethodMode &options): + CompressEvent(NULL), + CompressionCompletedEvent(NULL), + ExitThread(false), + ProgressSpec(0), + OutStreamSpec(0), + Coder(options) + {} + + void CreateEvents() + { + CompressEvent = new CAutoResetEvent(false); + CompressionCompletedEvent = new CAutoResetEvent(false); + } + bool CreateThread() { return Thread.Create(CoderThread, this); } + ~CThreadInfo(); + + void WaitAndCode(); + void StopWaitClose() + { + ExitThread = true; + if (OutStreamSpec != 0) + OutStreamSpec->StopWriting(E_ABORT); + if (CompressEvent != NULL) + CompressEvent->Set(); + Thread.Wait(); + Thread.Close(); + } + +}; + +CThreadInfo::~CThreadInfo() +{ + if (CompressEvent != NULL) + delete CompressEvent; + if (CompressionCompletedEvent != NULL) + delete CompressionCompletedEvent; +} + +void CThreadInfo::WaitAndCode() +{ + for (;;) + { + CompressEvent->Lock(); + if (ExitThread) + return; + Result = Coder.Compress(InStream, OutStream, Progress, CompressingResult); + if (Result == S_OK && Progress) + Result = Progress->SetRatioInfo(&CompressingResult.UnpackSize, &CompressingResult.PackSize); + CompressionCompletedEvent->Set(); + } +} + +static DWORD WINAPI CoderThread(void *threadCoderInfo) +{ + ((CThreadInfo *)threadCoderInfo)->WaitAndCode(); + return 0; +} + +class CThreads +{ +public: + CObjectVector<CThreadInfo> Threads; + ~CThreads() + { + for (int i = 0; i < Threads.Size(); i++) + Threads[i].StopWaitClose(); + } +}; + +struct CMemBlocks2: public CMemLockBlocks +{ + CCompressingResult CompressingResult; + bool Defined; + bool Skip; + CMemBlocks2(): Defined(false), Skip(false) {} +}; + +class CMemRefs +{ +public: + CMemBlockManagerMt *Manager; + CObjectVector<CMemBlocks2> Refs; + CMemRefs(CMemBlockManagerMt *manager): Manager(manager) {} ; + ~CMemRefs() + { + for (int i = 0; i < Refs.Size(); i++) + Refs[i].FreeOpt(Manager); + } +}; + +#endif + + +static HRESULT UpdateItemOldData(COutArchive &archive, + IInStream *inStream, + const CUpdateItem &updateItem, CItemEx &item, ICompressProgressInfo *progress, + UInt64 &complexity) +{ + if (updateItem.NewProperties) + { + if (item.HasDescriptor()) + return E_NOTIMPL; + + // use old name size. + // CUpdateRange range(item.GetLocalExtraPosition(), item.LocalExtraSize + item.PackSize); + CUpdateRange range(item.GetDataPosition(), item.PackSize); + + // item.ExternalAttributes = updateItem.Attributes; + // Test it + item.Name = updateItem.Name; + item.Time = updateItem.Time; + item.CentralExtra.RemoveUnknownSubBlocks(); + item.LocalExtra.RemoveUnknownSubBlocks(); + + archive.PrepareWriteCompressedData2((UInt16)item.Name.Length(), item.UnPackSize, item.PackSize, item.LocalExtra.HasWzAesField()); + item.LocalHeaderPosition = archive.GetCurrentPosition(); + archive.SeekToPackedDataPosition(); + RINOK(WriteRange(inStream, archive, range, progress)); + complexity += range.Size; + archive.WriteLocalHeader(item); + } + else + { + CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize()); + + // set new header position + item.LocalHeaderPosition = archive.GetCurrentPosition(); + + RINOK(WriteRange(inStream, archive, range, progress)); + complexity += range.Size; + archive.MoveBasePosition(range.Size); + } + return S_OK; +} + +static HRESULT WriteDirHeader(COutArchive &archive, const CCompressionMethodMode *options, + const CUpdateItem &updateItem, CItemEx &item) +{ + SetFileHeader(archive, *options, updateItem, item); + archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), updateItem.Size, options->IsAesMode); + return archive.WriteLocalHeader(item); +} + +static HRESULT Update2St(COutArchive &archive, + CInArchive *inArchive, + IInStream *inStream, + const CObjectVector<CItemEx> &inputItems, + const CObjectVector<CUpdateItem> &updateItems, + const CCompressionMethodMode *options, + const CByteBuffer &comment, + IArchiveUpdateCallback *updateCallback) +{ + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; + localProgressSpec->Init(updateCallback, true); + + CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo; + CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec; + + CAddCommon compressor(*options); + + CObjectVector<CItem> items; + UInt64 complexity = 0; + + for (int itemIndex = 0; itemIndex < updateItems.Size(); itemIndex++) + { + RINOK(updateCallback->SetCompleted(&complexity)); + const CUpdateItem &updateItem = updateItems[itemIndex]; + CItemEx item; + if (!updateItem.NewProperties || !updateItem.NewData) + { + item = inputItems[updateItem.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + return E_NOTIMPL; + } + + if (updateItem.NewData) + { + bool isDirectory = ((updateItem.NewProperties) ? updateItem.IsDirectory : item.IsDirectory()); + if (isDirectory) + { + RINOK(WriteDirHeader(archive, options, updateItem, item)); + } + else + { + CMyComPtr<ISequentialInStream> fileInStream; + HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream); + if (res == S_FALSE) + { + complexity += updateItem.Size + NFileHeader::kLocalBlockSize; + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + continue; + } + RINOK(res); + + // file Size can be 64-bit !!! + SetFileHeader(archive, *options, updateItem, item); + archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), updateItem.Size, options->IsAesMode); + CCompressingResult compressingResult; + CMyComPtr<IOutStream> outStream; + archive.CreateStreamForCompressing(&outStream); + localCompressProgressSpec->Init(localProgress, &complexity, NULL); + RINOK(compressor.Compress(fileInStream, outStream, compressProgress, compressingResult)); + SetItemInfoFromCompressingResult(compressingResult, options->IsAesMode, options->AesKeyMode, item); + RINOK(archive.WriteLocalHeader(item)); + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + complexity += item.UnPackSize; + } + } + else + { + localCompressProgressSpec->Init(localProgress, &complexity, NULL); + RINOK(UpdateItemOldData(archive, inStream, updateItem, item, compressProgress, complexity)); + } + items.Add(item); + complexity += NFileHeader::kLocalBlockSize; + } + archive.WriteCentralDir(items, comment); + return S_OK; +} + +static HRESULT Update2(COutArchive &archive, + CInArchive *inArchive, + IInStream *inStream, + const CObjectVector<CItemEx> &inputItems, + const CObjectVector<CUpdateItem> &updateItems, + const CCompressionMethodMode *options, + const CByteBuffer &comment, + IArchiveUpdateCallback *updateCallback) +{ + UInt64 complexity = 0; + UInt64 numFilesToCompress = 0; + UInt64 numBytesToCompress = 0; + + int i; + for(i = 0; i < updateItems.Size(); i++) + { + const CUpdateItem &updateItem = updateItems[i]; + if (updateItem.NewData) + { + complexity += updateItem.Size; + numBytesToCompress += updateItem.Size; + numFilesToCompress++; + /* + if (updateItem.Commented) + complexity += updateItem.CommentRange.Size; + */ + } + else + { + CItemEx inputItem = inputItems[updateItem.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(inputItem) != S_OK) + return E_NOTIMPL; + complexity += inputItem.GetLocalFullSize(); + // complexity += inputItem.GetCentralExtraPlusCommentSize(); + } + complexity += NFileHeader::kLocalBlockSize; + complexity += NFileHeader::kCentralBlockSize; + } + + if (comment != 0) + complexity += comment.GetCapacity(); + complexity++; // end of central + updateCallback->SetTotal(complexity); + + CAddCommon compressor(*options); + + complexity = 0; + + #ifdef COMPRESS_MT + + const size_t kNumMaxThreads = (1 << 10); + UInt32 numThreads = options->NumThreads; + if (numThreads > kNumMaxThreads) + numThreads = kNumMaxThreads; + + const size_t kMemPerThread = (1 << 25); + const size_t kBlockSize = 1 << 16; + + CCompressionMethodMode options2; + if (options != 0) + options2 = *options; + + bool mtMode = ((options != 0) && (numThreads > 1)); + + if (numFilesToCompress <= 1) + mtMode = false; + + if (mtMode) + { + Byte method = options->MethodSequence.Front(); + if (method == NFileHeader::NCompressionMethod::kStored && !options->PasswordIsDefined) + mtMode = false; + if (method == NFileHeader::NCompressionMethod::kBZip2) + { + UInt64 averageSize = numBytesToCompress / numFilesToCompress; + UInt32 blockSize = options->DicSize; + if (blockSize == 0) + blockSize = 1; + UInt64 averageNumberOfBlocks = averageSize / blockSize; + UInt32 numBZip2Threads = 32; + if (averageNumberOfBlocks < numBZip2Threads) + numBZip2Threads = (UInt32)averageNumberOfBlocks; + if (numBZip2Threads < 1) + numBZip2Threads = 1; + numThreads = numThreads / numBZip2Threads; + options2.NumThreads = numBZip2Threads; + if (numThreads <= 1) + mtMode = false; + } + } + + if (!mtMode) + #endif + return Update2St(archive, inArchive,inStream, + inputItems, updateItems, options, comment, updateCallback); + + + #ifdef COMPRESS_MT + + CObjectVector<CItem> items; + + CLocalProgress *localProgressSpec = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec; + localProgressSpec->Init(updateCallback, true); + + CMtCompressProgressMixer mtCompressProgressMixer; + mtCompressProgressMixer.Init(numThreads + 1, localProgress); + + // we need one item for main stream + CMtCompressProgress *progressMainSpec = new CMtCompressProgress(); + CMyComPtr<ICompressProgressInfo> progressMain = progressMainSpec; + progressMainSpec->Init(&mtCompressProgressMixer, (int)numThreads); + + CMemBlockManagerMt memManager(kBlockSize); + CMemRefs refs(&memManager); + + CThreads threads; + CRecordVector<HANDLE> compressingCompletedEvents; + CRecordVector<int> threadIndices; // list threads in order of updateItems + + { + if (!memManager.AllocateSpaceAlways((size_t)numThreads * (kMemPerThread / kBlockSize))) + return E_OUTOFMEMORY; + for(i = 0; i < updateItems.Size(); i++) + refs.Refs.Add(CMemBlocks2()); + + UInt32 i; + for (i = 0; i < numThreads; i++) + threads.Threads.Add(CThreadInfo(options2)); + + for (i = 0; i < numThreads; i++) + { + CThreadInfo &threadInfo = threads.Threads[i]; + threadInfo.CreateEvents(); + threadInfo.OutStreamSpec = new COutMemStream(&memManager); + threadInfo.OutStream = threadInfo.OutStreamSpec; + threadInfo.IsFree = true; + threadInfo.ProgressSpec = new CMtCompressProgress(); + threadInfo.Progress = threadInfo.ProgressSpec; + threadInfo.ProgressSpec->Init(&mtCompressProgressMixer, (int)i); + if (!threadInfo.CreateThread()) + return ::GetLastError(); + } + } + int mtItemIndex = 0; + + int itemIndex = 0; + int lastRealStreamItemIndex = -1; + + while (itemIndex < updateItems.Size()) + { + if ((UInt32)threadIndices.Size() < numThreads && mtItemIndex < updateItems.Size()) + { + const CUpdateItem &updateItem = updateItems[mtItemIndex++]; + if (!updateItem.NewData) + continue; + CItemEx item; + if (updateItem.NewProperties) + { + if (updateItem.IsDirectory) + continue; + } + else + { + item = inputItems[updateItem.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + return E_NOTIMPL; + if (item.IsDirectory()) + continue; + } + CMyComPtr<ISequentialInStream> fileInStream; + { + NWindows::NSynchronization::CCriticalSectionLock lock(mtCompressProgressMixer.CriticalSection); + HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream); + if (res == S_FALSE) + { + complexity += updateItem.Size; + complexity++; + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + refs.Refs[mtItemIndex - 1].Skip = true; + continue; + } + RINOK(res); + RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + } + + for (UInt32 i = 0; i < numThreads; i++) + { + CThreadInfo &threadInfo = threads.Threads[i]; + if (threadInfo.IsFree) + { + threadInfo.IsFree = false; + threadInfo.InStream = fileInStream; + threadInfo.OutStreamSpec->Init(); + threadInfo.ProgressSpec->Reinit(); + threadInfo.CompressEvent->Set(); + threadInfo.UpdateIndex = mtItemIndex - 1; + + compressingCompletedEvents.Add(*threadInfo.CompressionCompletedEvent); + threadIndices.Add(i); + break; + } + } + continue; + } + + if (refs.Refs[itemIndex].Skip) + { + itemIndex++; + continue; + } + + const CUpdateItem &updateItem = updateItems[itemIndex]; + + CItemEx item; + if (!updateItem.NewProperties || !updateItem.NewData) + { + item = inputItems[updateItem.IndexInArchive]; + if (inArchive->ReadLocalItemAfterCdItemFull(item) != S_OK) + return E_NOTIMPL; + } + + if (updateItem.NewData) + { + bool isDirectory = ((updateItem.NewProperties) ? updateItem.IsDirectory : item.IsDirectory()); + if (isDirectory) + { + RINOK(WriteDirHeader(archive, options, updateItem, item)); + } + else + { + if (lastRealStreamItemIndex < itemIndex) + { + lastRealStreamItemIndex = itemIndex; + SetFileHeader(archive, *options, updateItem, item); + // file Size can be 64-bit !!! + archive.PrepareWriteCompressedData((UInt16)item.Name.Length(), updateItem.Size, options->IsAesMode); + } + + CMemBlocks2 &memRef = refs.Refs[itemIndex]; + if (memRef.Defined) + { + CMyComPtr<IOutStream> outStream; + archive.CreateStreamForCompressing(&outStream); + memRef.WriteToStream(memManager.GetBlockSize(), outStream); + SetItemInfoFromCompressingResult(memRef.CompressingResult, + options->IsAesMode, options->AesKeyMode, item); + SetFileHeader(archive, *options, updateItem, item); + RINOK(archive.WriteLocalHeader(item)); + complexity += item.UnPackSize; + // RINOK(updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK)); + memRef.FreeOpt(&memManager); + } + else + { + { + CThreadInfo &thread = threads.Threads[threadIndices.Front()]; + if (!thread.OutStreamSpec->WasUnlockEventSent()) + { + CMyComPtr<IOutStream> outStream; + archive.CreateStreamForCompressing(&outStream); + thread.OutStreamSpec->SetOutStream(outStream); + thread.OutStreamSpec->SetRealStreamMode(); + } + } + + DWORD result = ::WaitForMultipleObjects(compressingCompletedEvents.Size(), + &compressingCompletedEvents.Front(), FALSE, INFINITE); + int t = (int)(result - WAIT_OBJECT_0); + CThreadInfo &threadInfo = threads.Threads[threadIndices[t]]; + threadInfo.InStream.Release(); + threadInfo.IsFree = true; + RINOK(threadInfo.Result); + threadIndices.Delete(t); + compressingCompletedEvents.Delete(t); + if (t == 0) + { + RINOK(threadInfo.OutStreamSpec->WriteToRealStream()); + threadInfo.OutStreamSpec->ReleaseOutStream(); + SetItemInfoFromCompressingResult(threadInfo.CompressingResult, + options->IsAesMode, options->AesKeyMode, item); + SetFileHeader(archive, *options, updateItem, item); + RINOK(archive.WriteLocalHeader(item)); + complexity += item.UnPackSize; + } + else + { + CMemBlocks2 &memRef = refs.Refs[threadInfo.UpdateIndex]; + threadInfo.OutStreamSpec->DetachData(memRef); + memRef.CompressingResult = threadInfo.CompressingResult; + memRef.Defined = true; + continue; + } + } + } + } + else + { + progressMainSpec->Reinit(); + RINOK(UpdateItemOldData(archive, inStream, updateItem, item, progressMain, complexity)); + } + items.Add(item); + complexity += NFileHeader::kLocalBlockSize; + itemIndex++; + } + archive.WriteCentralDir(items, comment); + return S_OK; + #endif +} + +HRESULT Update( + const CObjectVector<CItemEx> &inputItems, + const CObjectVector<CUpdateItem> &updateItems, + ISequentialOutStream *seqOutStream, + CInArchive *inArchive, + CCompressionMethodMode *compressionMethodMode, + IArchiveUpdateCallback *updateCallback) +{ + CMyComPtr<IOutStream> outStream; + RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream)); + if (!outStream) + return E_NOTIMPL; + + CInArchiveInfo archiveInfo; + if(inArchive != 0) + { + inArchive->GetArchiveInfo(archiveInfo); + if (archiveInfo.Base != 0) + return E_NOTIMPL; + } + else + archiveInfo.StartPosition = 0; + + COutArchive outArchive; + outArchive.Create(outStream); + if (archiveInfo.StartPosition > 0) + { + CMyComPtr<ISequentialInStream> inStream; + inStream.Attach(inArchive->CreateLimitedStream(0, archiveInfo.StartPosition)); + RINOK(CopyBlockToArchive(inStream, outArchive, NULL)); + outArchive.MoveBasePosition(archiveInfo.StartPosition); + } + CMyComPtr<IInStream> inStream; + if(inArchive != 0) + inStream.Attach(inArchive->CreateStream()); + + return Update2(outArchive, inArchive, inStream, + inputItems, updateItems, + compressionMethodMode, + archiveInfo.Comment, updateCallback); +} + +}} diff --git a/CPP/7zip/Archive/Zip/ZipUpdate.h b/CPP/7zip/Archive/Zip/ZipUpdate.h new file mode 100755 index 00000000..d846b05f --- /dev/null +++ b/CPP/7zip/Archive/Zip/ZipUpdate.h @@ -0,0 +1,52 @@ +// Zip/Update.h + +#ifndef __ZIP_UPDATE_H +#define __ZIP_UPDATE_H + +#include "Common/Vector.h" +#include "Common/Types.h" + +#include "../../ICoder.h" +#include "../IArchive.h" + +#include "ZipCompressionMode.h" +#include "ZipIn.h" + +namespace NArchive { +namespace NZip { + +struct CUpdateRange +{ + UInt64 Position; + UInt64 Size; + CUpdateRange() {}; + CUpdateRange(UInt64 position, UInt64 size): Position(position), Size(size) {}; +}; + +struct CUpdateItem +{ + bool NewData; + bool NewProperties; + bool IsDirectory; + int IndexInArchive; + int IndexInClient; + UInt32 Attributes; + UInt32 Time; + UInt64 Size; + AString Name; + // bool Commented; + // CUpdateRange CommentRange; + CUpdateItem(): Size(0) {} +}; + +HRESULT Update( + const CObjectVector<CItemEx> &inputItems, + const CObjectVector<CUpdateItem> &updateItems, + ISequentialOutStream *seqOutStream, + CInArchive *inArchive, + CCompressionMethodMode *compressionMethodMode, + IArchiveUpdateCallback *updateCallback); + +}} + +#endif diff --git a/CPP/7zip/Archive/Zip/makefile b/CPP/7zip/Archive/Zip/makefile new file mode 100755 index 00000000..eaf1031f --- /dev/null +++ b/CPP/7zip/Archive/Zip/makefile @@ -0,0 +1,124 @@ +PROG = zip.dll +DEF_FILE = ../Archive.def +CFLAGS = $(CFLAGS) -I ../../../ -DCOMPRESS_MT +LIBS = $(LIBS) oleaut32.lib user32.lib + +ZIP_OBJS = \ + $O\DllExports.obj \ + $O\ZipAddCommon.obj \ + $O\ZipHandler.obj \ + $O\ZipHandlerOut.obj \ + $O\ZipHeader.obj \ + $O\ZipIn.obj \ + $O\ZipItem.obj \ + $O\ZipOut.obj \ + $O\ZipUpdate.obj \ + +COMMON_OBJS = \ + $O\Alloc.obj \ + $O\CRC.obj \ + $O\IntToString.obj \ + $O\NewHandler.obj \ + $O\String.obj \ + $O\StringConvert.obj \ + $O\StringToInt.obj \ + $O\Vector.obj \ + +WIN_OBJS = \ + $O\DLL.obj \ + $O\FileFind.obj \ + $O\PropVariant.obj \ + $O\Synchronization.obj \ + +7ZIP_COMMON_OBJS = \ + $O\InBuffer.obj \ + $O\LimitedStreams.obj \ + $O\LSBFDecoder.obj \ + $O\MemBlocks.obj \ + $O\OffsetStream.obj \ + $O\OutBuffer.obj \ + $O\OutMemStream.obj \ + $O\ProgressMt.obj \ + $O\ProgressUtils.obj \ + $O\StreamObjects.obj \ + $O\StreamUtils.obj \ + +AR_COMMON_OBJS = \ + $O\CodecsPath.obj \ + $O\CoderLoader.obj \ + $O\FilterCoder.obj \ + $O\InStreamWithCRC.obj \ + $O\ItemNameUtils.obj \ + $O\OutStreamWithCRC.obj \ + $O\ParseProperties.obj \ + +7Z_OBJS = \ + $O\7zMethodID.obj \ + $O\7zMethods.obj \ + +IMPLODE_OBJS = \ + $O\ImplodeDecoder.obj \ + $O\ImplodeHuffmanDecoder.obj \ + +SHRINK_OBJS = \ + $O\ShrinkDecoder.obj \ + +CRYPTO_HASH_OBJS = \ + $O\HmacSha1.obj \ + $O\Pbkdf2HmacSha1.obj \ + $O\RandGen.obj \ + $O\Sha1.obj \ + +CRYPTO_WZAES_OBJS = \ + $O\WzAES.obj \ + +CRYPTO_ZIP_OBJS = \ + $O\ZipCipher.obj \ + $O\ZipCrypto.obj \ + + +OBJS = \ + $O\StdAfx.obj \ + $(ZIP_OBJS) \ + $(COMMON_OBJS) \ + $(WIN_OBJS) \ + $(7ZIP_COMMON_OBJS) \ + $(AR_COMMON_OBJS) \ + $(7Z_OBJS) \ + $(CRYPTO_HASH_OBJS) \ + $(CRYPTO_WZAES_OBJS) \ + $(CRYPTO_ZIP_OBJS) \ + $(IMPLODE_OBJS) \ + $(SHRINK_OBJS) \ + $O\CopyCoder.obj \ + $O\LZOutWindow.obj \ + $O\resource.res + +!include "../../../Build.mak" + +$(ZIP_OBJS): $(*B).cpp + $(COMPL) +$(COMMON_OBJS): ../../../Common/$(*B).cpp + $(COMPL) +$(WIN_OBJS): ../../../Windows/$(*B).cpp + $(COMPL) +$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp + $(COMPL) +$(AR_COMMON_OBJS): ../Common/$(*B).cpp + $(COMPL) +$(7Z_OBJS): ../7z/$(*B).cpp + $(COMPL) +$(CRYPTO_HASH_OBJS): ../../Crypto/Hash/$(*B).cpp + $(COMPL_O2) +$(CRYPTO_ZIP_OBJS): ../../Crypto/Zip/$(*B).cpp + $(COMPL) +$(CRYPTO_WZAES_OBJS): ../../Crypto/WzAES/$(*B).cpp + $(COMPL_O2) +$(IMPLODE_OBJS): ../../Compress/Implode/$(*B).cpp + $(COMPL) +$(SHRINK_OBJS): ../../Compress/Shrink/$(*B).cpp + $(COMPL) +$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp + $(COMPL) +$O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp + $(COMPL) diff --git a/CPP/7zip/Archive/Zip/resource.rc b/CPP/7zip/Archive/Zip/resource.rc new file mode 100755 index 00000000..388f349e --- /dev/null +++ b/CPP/7zip/Archive/Zip/resource.rc @@ -0,0 +1,5 @@ +#include "../../MyVersionInfo.rc" + +MY_VERSION_INFO_DLL("Zip Plugin", "zip") + +101 ICON "zip.ico" diff --git a/CPP/7zip/Archive/Zip/zip.ico b/CPP/7zip/Archive/Zip/zip.ico Binary files differnew file mode 100755 index 00000000..2af46066 --- /dev/null +++ b/CPP/7zip/Archive/Zip/zip.ico |