Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/Zip
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/Zip')
-rwxr-xr-xCPP/7zip/Archive/Zip/DllExports.cpp152
-rwxr-xr-xCPP/7zip/Archive/Zip/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Zip/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Zip/Zip.dsp651
-rwxr-xr-xCPP/7zip/Archive/Zip/Zip.dsw29
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipAddCommon.cpp309
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipAddCommon.h58
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipCompressionMode.h39
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.cpp766
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandler.h100
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHandlerOut.cpp393
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.cpp36
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipHeader.h248
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.cpp797
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipIn.h111
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.cpp137
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItem.h191
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipItemEx.h29
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipOut.cpp259
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipOut.h51
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.cpp734
-rwxr-xr-xCPP/7zip/Archive/Zip/ZipUpdate.h52
-rwxr-xr-xCPP/7zip/Archive/Zip/makefile124
-rwxr-xr-xCPP/7zip/Archive/Zip/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Zip/zip.icobin0 -> 3638 bytes
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(&currentTotalUnPacked));
+ 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, &currentTotalPacked, &currentTotalUnPacked);
+
+ 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
new file mode 100755
index 00000000..2af46066
--- /dev/null
+++ b/CPP/7zip/Archive/Zip/zip.ico
Binary files differ