This commit is contained in:
Igor Pavlov
2003-12-11 00:00:00 +00:00
committed by Kornel Lesiński
commit 8c1b5c7b7e
982 changed files with 118799 additions and 0 deletions

122
7zip/Archive/Zip/DllExports.cpp Executable file
View File

@@ -0,0 +1,122 @@
// DLLExports.cpp
#include "StdAfx.h"
#include <initguid.h>
#include "Common/ComTry.h"
#include "ZipHandler.h"
#include "Windows/PropVariant.h"
#include "../../ICoder.h"
#include "../../IPassword.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;
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
g_hInstance = hInstance;
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;
}
propVariant.Detach(value);
return S_OK;
}

3
7zip/Archive/Zip/StdAfx.cpp Executable file
View File

@@ -0,0 +1,3 @@
// StdAfx.cpp
#include "stdafx.h"

31
7zip/Archive/Zip/StdAfx.h Executable file
View File

@@ -0,0 +1,31 @@
// stdafx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#include <windows.h>
#include <time.h>
#include <limits.h>
#include <memory>
/*
#define _ATL_APARTMENT_THREADED
// #define _ATL_FREE_THREADED
#define _ATL_NO_UUIDOF
#include <atlbase.h>
extern CComModule _Module;
#include <atlcom.h>
#include <shlobj.h>
#include <shlguid.h>
#include <new.h>
*/
#endif

7
7zip/Archive/Zip/Zip.def Executable file
View File

@@ -0,0 +1,7 @@
; Zip.def
LIBRARY Zip.dll
EXPORTS
CreateObject PRIVATE
GetHandlerProperty PRIVATE

441
7zip/Archive/Zip/Zip.dsp Executable file
View File

@@ -0,0 +1,441 @@
# 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 "CRYPTO_ZIP" /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 "CRYPTO_ZIP" /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=.\DllExports.cpp
# End Source File
# Begin Source File
SOURCE=.\resource.h
# 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
# Begin Source File
SOURCE=.\Zip.def
# End Source File
# End Group
# Begin Group "Common"
# PROP Default_Filter ""
# 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\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
# 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.h
# End Source File
# Begin Source File
SOURCE=..\Common\CoderMixer.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CoderMixer.h
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.cpp
# End Source File
# Begin Source File
SOURCE=..\Common\CrossThreadProgress.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
# End Group
# Begin Group "7zip common"
# PROP Default_Filter ""
# 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\OffsetStream.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\OffsetStream.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\StreamBinder.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamBinder.h
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamObjects.cpp
# End Source File
# Begin Source File
SOURCE=..\..\Common\StreamObjects.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 "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 "Format Common"
# PROP Default_Filter ""
# End Group
# Begin Group "Crypto"
# PROP Default_Filter ""
# 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\7zMethods.cpp
# End Source File
# Begin Source File
SOURCE=..\7z\7zMethods.h
# End Source File
# End Group
# Begin Source File
SOURCE=".\7-zip.ico"
# End Source File
# Begin Source File
SOURCE=.\zip.ico
# End Source File
# Begin Source File
SOURCE=.\zip1.ico
# End Source File
# End Target
# End Project

29
7zip/Archive/Zip/Zip.dsw Executable file
View File

@@ -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>
{{{
}}}
###############################################################################

270
7zip/Archive/Zip/ZipAddCommon.cpp Executable file
View File

@@ -0,0 +1,270 @@
// AddCommon.cpp
#include "StdAfx.h"
#include "Common/CRC.h"
#include "Windows/PropVariant.h"
#include "Windows/Defs.h"
#include "../../ICoder.h"
#include "../../IPassword.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 {
static const BYTE kMethodIDForEmptyStream = NFileHeader::NCompressionMethod::kStored;
static const BYTE kExtractVersionForEmptyStream = NFileHeader::NCompressionMethod::kStoreExtractVersion;
CAddCommon::CAddCommon(const CCompressionMethodMode &options):
_options(options),
_copyCoderSpec(NULL),
_mixerCoderSpec(0)
{}
static HRESULT GetStreamCRC(IInStream *inStream, UINT32 &resultCRC)
{
CCRC crc;
crc.Init();
const UINT32 kBufferSize = (1 << 14);
BYTE buffer[kBufferSize];
while(true)
{
UINT32 realProcessedSize;
RINOK(inStream->Read(buffer, kBufferSize, &realProcessedSize));
if(realProcessedSize == 0)
{
resultCRC = crc.GetDigest();
return S_OK;
}
crc.Update(buffer, realProcessedSize);
}
}
HRESULT CAddCommon::Compress(IInStream *inStream, IOutStream *outStream,
UINT64 inSize, ICompressProgressInfo *progress, CCompressingResult &operationResult)
{
/*
if(inSize == 0)
{
operationResult.PackSize = 0;
operationResult.Method = kMethodIDForEmptyStream;
operationResult.ExtractVersion = kExtractVersionForEmptyStream;
return S_OK;
}
*/
int numTestMethods = _options.MethodSequence.Size();
BYTE method;
UINT64 resultSize = 0;
for(int i = 0; i < numTestMethods; i++)
{
if (_options.PasswordIsDefined)
{
if (!_cryptoEncoder)
{
#ifdef CRYPTO_ZIP
_cryptoEncoder = new NCrypto::NZip::CEncoder;
#else
// change it;
/*
RINOK(_cryptoLib.LoadAndCreateCoder(
GetBaseFolderPrefix() + TEXT("\\Crypto\\Zip.dll"),
CLSID_CCryptoZipEncoder, &_cryptoEncoder));
*/
#endif
}
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
RINOK(_cryptoEncoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword));
RINOK(cryptoSetPassword->CryptoSetPassword(
(const BYTE *)(const char *)_options.Password, _options.Password.Length()));
UINT32 crc;
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(GetStreamCRC(inStream, crc));
CMyComPtr<ICryptoSetCRC> cryptoSetCRC;
RINOK(_cryptoEncoder.QueryInterface(IID_ICryptoSetCRC, &cryptoSetCRC));
RINOK(cryptoSetCRC->CryptoSetCRC(crc));
}
RINOK(outStream->Seek(0, STREAM_SEEK_SET, NULL));
RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
method = _options.MethodSequence[i];
switch(method)
{
case NFileHeader::NCompressionMethod::kStored:
{
if(_copyCoderSpec == NULL)
{
_copyCoderSpec = new NCompress::CCopyCoder;
_copyCoder = _copyCoderSpec;
}
if (_options.PasswordIsDefined)
{
if (!_mixerCoder || _mixerCoderMethod != method)
{
_mixerCoder.Release();
_mixerCoderSpec = new CCoderMixer;
_mixerCoder = _mixerCoderSpec;
_mixerCoderSpec->AddCoder(_copyCoder);
_mixerCoderSpec->AddCoder(_cryptoEncoder);
_mixerCoderSpec->FinishAddingCoders();
_mixerCoderMethod = method;
}
_mixerCoderSpec->ReInit();
_mixerCoderSpec->SetCoderInfo(0, NULL, NULL);
_mixerCoderSpec->SetCoderInfo(1, NULL, NULL);
_mixerCoderSpec->SetProgressCoderIndex(0);
RINOK(_mixerCoder->Code(inStream, outStream,
NULL, NULL, progress));
}
else
{
RINOK(_copyCoder->Code(inStream, outStream,
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[2] =
{
_options.NumPasses, _options.NumFastBytes
};
PROPID propIDs[2] =
{
NCoderPropID::kNumPasses,
NCoderPropID::kNumFastBytes
};
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
RINOK(_compressEncoder.QueryInterface(
IID_ICompressSetCoderProperties, &setCoderProperties));
setCoderProperties->SetCoderProperties(propIDs, properties, 2);
}
}
if (_options.PasswordIsDefined)
{
if (!_mixerCoder || _mixerCoderMethod != method)
{
_mixerCoder.Release();
_mixerCoderSpec = new CCoderMixer;
_mixerCoder = _mixerCoderSpec;
_mixerCoderSpec->AddCoder(_compressEncoder);
_mixerCoderSpec->AddCoder(_cryptoEncoder);
_mixerCoderSpec->FinishAddingCoders();
_mixerCoderMethod = method;
}
_mixerCoderSpec->ReInit();
_mixerCoderSpec->SetCoderInfo(0, NULL, NULL);
_mixerCoderSpec->SetCoderInfo(1, NULL, NULL);
_mixerCoderSpec->SetProgressCoderIndex(0);
RINOK(_mixerCoder->Code(inStream, outStream,
NULL, NULL, progress));
}
else
{
RINOK(_compressEncoder->Code(inStream, outStream, NULL, NULL, progress));
}
operationResult.ExtractVersion = NFileHeader::NCompressionMethod::kDeflateExtractVersion;
break;
}
}
outStream->Seek(0, STREAM_SEEK_CUR, &resultSize);
if (_options.PasswordIsDefined)
{
if(resultSize < inSize + 12)
break;
}
else if(resultSize < inSize)
break;
}
outStream->SetSize(resultSize);
operationResult.PackSize = resultSize;
operationResult.Method = method;
return S_OK;
}
}}

56
7zip/Archive/Zip/ZipAddCommon.h Executable file
View File

@@ -0,0 +1,56 @@
// Zip/AddCommon.h
#pragma once
#ifndef __ZIP_ADDCOMMON_H
#define __ZIP_ADDCOMMON_H
#include "../../ICoder.h"
#include "../../IProgress.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/CoderMixer.h"
#ifndef COMPRESS_DEFLATE
#include "../Common/CoderLoader.h"
#endif
#include "ZipCompressionMode.h"
namespace NArchive {
namespace NZip {
struct CCompressingResult
{
BYTE Method;
UINT64 PackSize;
BYTE ExtractVersion;
};
class CAddCommon
{
CCompressionMethodMode _options;
NCompress::CCopyCoder *_copyCoderSpec;
CMyComPtr<ICompressCoder> _copyCoder;
#ifndef COMPRESS_DEFLATE
CCoderLibrary _compressLib;
#endif
CMyComPtr<ICompressCoder> _compressEncoder;
#ifndef CRYPTO_ZIP
CCoderLibrary _cryptoLib;
#endif
CMyComPtr<ICompressCoder> _cryptoEncoder;
CCoderMixer *_mixerCoderSpec;
CMyComPtr<ICompressCoder> _mixerCoder;
BYTE _mixerCoderMethod;
// CMyComPtr<ICryptoGetTextPassword> getTextPassword;
public:
CAddCommon(const CCompressionMethodMode &options);
HRESULT Compress(IInStream *inStream, IOutStream *outStream,
UINT64 inSize, ICompressProgressInfo *progress, CCompressingResult &operationResult);
};
}}
#endif

View File

@@ -0,0 +1,26 @@
// CompressionMode.h
#pragma once
#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 PasswordIsDefined;
AString Password;
};
}}
#endif

612
7zip/Archive/Zip/ZipHandler.cpp Executable file
View File

@@ -0,0 +1,612 @@
// Zip/Handler.cpp
#include "StdAfx.h"
#include "ZipHandler.h"
#include "Common/Defs.h"
#include "Common/CRC.h"
#include "Common/StringConvert.h"
#include "Common/ComTry.h"
#include "Windows/Time.h"
#include "Windows/PropVariant.h"
#include "../../IPassword.h"
// #include "../../../Compress/Interface/CompressInterface.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
// #include "Interface/EnumStatProp.h"
#include "../../Common/StreamObjects.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/ItemNameUtils.h"
#include "../Common/OutStreamWithCRC.h"
#include "../Common/CoderMixer.h"
#include "../7z/7zMethods.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
#include "../../Compress/Implode/ImplodeDecoder.h"
#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
#ifdef CRYPTO_ZIP
#include "../../Crypto/Zip/ZipCipher.h"
#else
// {23170F69-40C1-278B-06F1-0101000000000}
DEFINE_GUID(CLSID_CCryptoZipDecoder,
0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00);
#endif
#ifndef EXCLUDE_COM
#include "../Common/CoderLoader.h"
#endif
// using namespace std;
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, kpidCommented, VT_BOOL},
{ 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"Shrunk",
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";
CHandler::CHandler():
m_ArchiveIsOpen(false)
{
InitMethodProperties();
m_Method.MethodSequence.Add(NFileHeader::NCompressionMethod::kDeflated);
m_Method.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
}
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;
}
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 kpidCommented:
propVariant = item.IsCommented();
break;
case kpidCRC:
propVariant = item.FileCRC;
break;
case kpidMethod:
{
UString method;
if (item.CompressionMethod < kNumMethods)
method = kMethods[item.CompressionMethod];
else
method = kUnknownMethod;
propVariant = method;
// propVariant = item.CompressionMethod;
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_Archive.Close();
m_ArchiveIsOpen = false;
return S_OK;
}
//////////////////////////////////////
// CHandler::DecompressItems
struct CMethodItem
{
BYTE ZipMethod;
CMyComPtr<ICompressCoder> Coder;
};
STDMETHODIMP CHandler::Extract(const UINT32* indices, UINT32 numItems,
INT32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)
{
COM_TRY_BEGIN
CMyComPtr<ICryptoGetTextPassword> getTextPassword;
bool testMode = (_aTestMode != 0);
CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;
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;
#ifndef EXCLUDE_COM
N7z::LoadMethodMap();
CCoderLibraries libraries;
#endif
CObjectVector<CMethodItem> methodItems;
/*
CCoderLibraries _libraries;
#ifndef COMPRESS_IMPLODE
CCoderLibrary implodeLib;
#endif
CMyComPtr<ICompressCoder> implodeDecoder;
CMyComPtr<ICompressCoder> deflateDecoder;
CMyComPtr<ICompressCoder> deflate64Decoder;
CMyComPtr<ICompressCoder> bzip2Decoder;
#ifndef CRYPTO_ZIP
CCoderLibrary cryptoLib;
#endif
*/
CMyComPtr<ICompressCoder> cryptoDecoder;
CCoderMixer *mixerCoderSpec;
CMyComPtr<ICompressCoder> mixerCoder;
UINT16 mixerCoderMethod;
for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked,
currentTotalPacked += currentItemPacked)
{
currentItemUnPacked = 0;
currentItemPacked = 0;
RINOK(extractCallback->SetCompleted(&currentTotalUnPacked));
CMyComPtr<ISequentialOutStream> realOutStream;
INT32 askMode;
askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
NArchive::NExtract::NAskMode::kExtract;
INT32 index = allFilesMode ? i : indices[i];
const CItemEx &item = m_Items[index];
RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
if(item.IsDirectory() || item.IgnoreItem())
{
// if (!testMode)
{
RINOK(extractCallback->PrepareOperation(askMode));
RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
}
continue;
}
if (!testMode && (!realOutStream))
continue;
RINOK(extractCallback->PrepareOperation(askMode));
currentItemUnPacked = item.UnPackSize;
currentItemPacked = item.PackSize;
{
COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
outStreamSpec->Init(realOutStream);
realOutStream.Release();
CMyComPtr<ISequentialInStream> inStream;
inStream.Attach(m_Archive.CreateLimitedStream(item.GetDataPosition(),
item.PackSize));
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
localProgressSpec->Init(extractCallback, false);
CLocalCompressProgressInfo *localCompressProgressSpec =
new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(progress,
&currentTotalPacked,
&currentTotalUnPacked);
if (item.IsEncrypted())
{
if (!cryptoDecoder)
{
#ifdef CRYPTO_ZIP
cryptoDecoder = new NCrypto::NZip::CDecoder;
#else
RINOK(cryptoLib.LoadAndCreateCoder(
GetBaseFolderPrefix() + TEXT("\\Crypto\\Zip.dll"),
CLSID_CCryptoZipDecoder, &cryptoDecoder));
#endif
}
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
RINOK(cryptoDecoder.QueryInterface(
IID_ICryptoSetPassword, &cryptoSetPassword));
if (!getTextPassword)
extractCallback.QueryInterface(
IID_ICryptoGetTextPassword, &getTextPassword);
if (getTextPassword)
{
CMyComBSTR password;
RINOK(getTextPassword->CryptoGetTextPassword(&password));
AString anOemPassword = UnicodeStringToMultiByte(
(const wchar_t *)password, CP_OEMCP);
RINOK(cryptoSetPassword->CryptoSetPassword(
(const BYTE *)(const char *)anOemPassword, anOemPassword.Length()));
}
else
{
RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
}
}
int m;
for (m = 0; m < methodItems.Size(); m++)
if (methodItems[m].ZipMethod == item.CompressionMethod)
break;
if (m == methodItems.Size())
{
CMethodItem mi;
mi.ZipMethod = item.CompressionMethod;
#ifdef EXCLUDE_COM
switch(item.CompressionMethod)
{
case NFileHeader::NCompressionMethod::kStored:
mi.Coder = new NCompress::CCopyCoder;
break;
case NFileHeader::NCompressionMethod::kImploded:
mi.Coder = new NCompress::NImplode::NDecoder::CCoder;
break;
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:
RINOK(extractCallback->SetOperationResult(
NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
#else
N7z::CMethodID methodID = { { 0x04, 0x01 } , 3 };
methodID.ID[2] = item.CompressionMethod;
if (item.CompressionMethod == NFileHeader::NCompressionMethod::kStored)
{
methodID.ID[0] = 0;
methodID.IDSize = 1;
}
else if (item.CompressionMethod == NFileHeader::NCompressionMethod::kBZip2)
{
methodID.ID[1] = 0x02;
methodID.ID[2] = 0x02;
}
N7z::CMethodInfo methodInfo;
if (!N7z::GetMethodInfo(methodID, methodInfo))
{
RINOK(extractCallback->SetOperationResult(
NArchive::NExtract::NOperationResult::kUnSupportedMethod));
continue;
}
RINOK(libraries.CreateCoder(methodInfo.FilePath,
methodInfo.Decoder, &mi.Coder));
#endif
m = methodItems.Add(mi);
}
ICompressCoder *coder = methodItems[m].Coder;
CMyComPtr<ICompressSetDecoderProperties> compressSetDecoderProperties;
if (coder->QueryInterface(IID_ICompressSetDecoderProperties, (void **)&compressSetDecoderProperties) == S_OK)
{
// BYTE properties = (item.Flags & 6);
BYTE properties = item.Flags;
CSequentialInStreamImp *inStreamSpec = new CSequentialInStreamImp;
CMyComPtr<ISequentialInStream> inStreamProperties(inStreamSpec);
inStreamSpec->Init(&properties, 1);
RINOK(compressSetDecoderProperties->SetDecoderProperties(inStreamProperties));
}
// case NFileHeader::NCompressionMethod::kImploded:
// switch(item.CompressionMethod)
try
{
HRESULT result;
if (item.IsEncrypted())
{
if (!mixerCoder || mixerCoderMethod != item.CompressionMethod)
{
mixerCoder.Release();
mixerCoderSpec = new CCoderMixer;
mixerCoder = mixerCoderSpec;
mixerCoderSpec->AddCoder(cryptoDecoder);
mixerCoderSpec->AddCoder(coder);
mixerCoderSpec->FinishAddingCoders();
mixerCoderMethod = item.CompressionMethod;
}
mixerCoderSpec->ReInit();
switch(item.CompressionMethod)
{
case NFileHeader::NCompressionMethod::kStored:
mixerCoderSpec->SetCoderInfo(0, &currentItemPacked,
&currentItemUnPacked);
mixerCoderSpec->SetCoderInfo(1, NULL, NULL);
break;
default:
mixerCoderSpec->SetCoderInfo(0, &currentItemPacked, NULL);
mixerCoderSpec->SetCoderInfo(1, NULL, &currentItemUnPacked);
break;
}
mixerCoderSpec->SetProgressCoderIndex(1);
result = mixerCoder->Code(inStream, outStream,
NULL, NULL, compressProgress);
}
else
{
result = coder->Code(inStream, outStream,
NULL, &currentItemUnPacked, compressProgress);
}
if (result == S_FALSE)
throw "data error";
if (result != S_OK)
return result;
}
catch(...)
{
outStream.Release();
RINOK(extractCallback->SetOperationResult(
NArchive::NExtract::NOperationResult::kDataError));
continue;
}
bool crcOK = outStreamSpec->GetCRC() == item.FileCRC;
outStream.Release();
RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK :
NArchive::NExtract::NOperationResult::kCRCError))
}
}
return S_OK;
COM_TRY_END
}
}}

73
7zip/Archive/Zip/ZipHandler.h Executable file
View File

@@ -0,0 +1,73 @@
// Zip/Handler.h
#pragma once
#ifndef __ZIP_HANDLER_H
#define __ZIP_HANDLER_H
#include "Common/DynamicBuffer.h"
#include "../../ICoder.h"
#include "../IArchive.h"
#include "ZipIn.h"
#include "ZipCompressionMode.h"
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)(IOutStream *outStream, UINT32 numItems,
IArchiveUpdateCallback *updateCallback);
STDMETHOD(GetFileTimeType)(UINT32 *timeType);
// ISetProperties
STDMETHOD(SetProperties)(const BSTR *names, const PROPVARIANT *values, INT32 numProperties);
CHandler();
private:
CObjectVector<CItemEx> m_Items;
CInArchive m_Archive;
bool m_ArchiveIsOpen;
CCompressionMethodMode m_Method;
void InitMethodProperties()
{
m_Method.NumPasses = 1;
m_Method.NumFastBytes = 32;
}
};
}}
#endif

View File

@@ -0,0 +1,284 @@
// 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"
using namespace NWindows;
using namespace NCOM;
using namespace NTime;
namespace NArchive {
namespace NZip {
STDMETHODIMP CHandler::GetFileTimeType(UINT32 *timeType)
{
*timeType = NFileTimeType::kDOS;
return S_OK;
}
STDMETHODIMP CHandler::UpdateItems(IOutStream *outStream, UINT32 numItems,
IArchiveUpdateCallback *updateCallback)
{
COM_TRY_BEGIN
CObjectVector<CUpdateItem> updateItems;
for(int 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;
updateItem.Name = UnicodeStringToMultiByte(
NItemName::MakeLegalName(name), CP_OEMCP);
if (!isDirectoryStatusDefined)
updateItem.IsDirectory = ((updateItem.Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
if (updateItem.IsDirectory)
updateItem.Name += '/';
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 = *(UINT64 *)(&propVariant.uhVal);
}
if(size > 0xFFFFFFFF)
return E_NOTIMPL;
updateItem.Size = size;
}
updateItems.Add(updateItem);
}
CMyComPtr<ICryptoGetTextPassword2> getTextPassword;
if (!getTextPassword)
{
CMyComPtr<IArchiveUpdateCallback> udateCallBack2(updateCallback);
udateCallBack2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword);
}
if (getTextPassword)
{
CMyComBSTR password;
INT32 passwordIsDefined;
RINOK(getTextPassword->CryptoGetTextPassword2(
&passwordIsDefined, &password));
if (m_Method.PasswordIsDefined = IntToBool(passwordIsDefined))
m_Method.Password = UnicodeStringToMultiByte(
(const wchar_t *)password, CP_OEMCP);
}
else
m_Method.PasswordIsDefined = false;
return Update(m_Items, updateItems, outStream,
m_ArchiveIsOpen ? &m_Archive : NULL, &m_Method, updateCallback);
COM_TRY_END
}
static const UINT32 kNumPassesNormal = 1;
static const UINT32 kNumPassesMX = 3;
static const UINT32 kMatchFastLenNormal = 32;
static const UINT32 kMatchFastLenMX = 64;
STDMETHODIMP CHandler::SetProperties(const BSTR *names, const PROPVARIANT *values, INT32 numProperties)
{
InitMethodProperties();
BYTE mainMethod = NFileHeader::NCompressionMethod::kDeflated;
for (int i = 0; i < numProperties; i++)
{
UString name = UString(names[i]);
name.MakeUpper();
const PROPVARIANT &value = values[i];
if (name[0] == 'X')
{
name.Delete(0);
UINT32 level = 9;
if (value.vt == VT_UI4)
{
if (!name.IsEmpty())
return E_INVALIDARG;
level = value.ulVal;
}
else if (value.vt == VT_EMPTY)
{
if(!name.IsEmpty())
{
const wchar_t *start = name;
const wchar_t *end;
UINT64 v = ConvertStringToUINT64(start, &end);
if (end - start != name.Length())
return E_INVALIDARG;
level = (UINT32)v;
}
}
else
return E_INVALIDARG;
if (level == 0)
{
mainMethod = NFileHeader::NCompressionMethod::kStored;
}
else if (level < 7)
{
InitMethodProperties();
if (mainMethod == NFileHeader::NCompressionMethod::kStored)
mainMethod = NFileHeader::NCompressionMethod::kDeflated;
}
else
{
m_Method.NumPasses = kNumPassesMX;
m_Method.NumFastBytes = kMatchFastLenMX;
if (mainMethod == NFileHeader::NCompressionMethod::kStored)
mainMethod = NFileHeader::NCompressionMethod::kDeflated;
}
continue;
}
else if (name == L"M")
{
if (value.vt == VT_BSTR)
{
UString valueString = value.bstrVal;
valueString.MakeUpper();
if (valueString == L"COPY")
mainMethod = NFileHeader::NCompressionMethod::kStored;
else if (valueString == L"DEFLATE")
mainMethod = NFileHeader::NCompressionMethod::kDeflated;
else if (valueString == L"DEFLATE64")
mainMethod = NFileHeader::NCompressionMethod::kDeflated64;
else if (valueString == L"BZIP2")
mainMethod = NFileHeader::NCompressionMethod::kBZip2;
else
return E_INVALIDARG;
}
else if (value.vt == VT_UI4)
{
switch(value.ulVal)
{
case NFileHeader::NCompressionMethod::kStored:
case NFileHeader::NCompressionMethod::kDeflated:
case NFileHeader::NCompressionMethod::kDeflated64:
case NFileHeader::NCompressionMethod::kBZip2:
mainMethod = value.ulVal;
break;
default:
return E_INVALIDARG;
}
}
else
return E_INVALIDARG;
}
else if (name == L"PASS")
{
if (value.vt != VT_UI4)
return E_INVALIDARG;
m_Method.NumPasses = value.ulVal;
if (m_Method.NumPasses < 1 || m_Method.NumPasses > 4)
return E_INVALIDARG;
}
else if (name == L"FB")
{
if (value.vt != VT_UI4)
return E_INVALIDARG;
m_Method.NumFastBytes = value.ulVal;
if (m_Method.NumFastBytes < 3 || m_Method.NumFastBytes > 255)
return E_INVALIDARG;
}
else
return E_INVALIDARG;
}
m_Method.MethodSequence.Clear();
if (mainMethod != NFileHeader::NCompressionMethod::kStored)
m_Method.MethodSequence.Add(mainMethod);
m_Method.MethodSequence.Add(NFileHeader::NCompressionMethod::kStored);
return S_OK;
}
}}

32
7zip/Archive/Zip/ZipHeader.cpp Executable file
View File

@@ -0,0 +1,32 @@
// 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;
class CMarkersInitializer
{
public:
CMarkersInitializer()
{
kLocalFileHeader--;
kDataDescriptor--;
kCentralFileHeader--;
kEndOfCentralDir--;
}
};
static CMarkersInitializer g_MarkerInitializer;
}
}}

227
7zip/Archive/Zip/ZipHeader.h Executable file
View File

@@ -0,0 +1,227 @@
// Archive/Zip/Header.h
#pragma once
#ifndef __ARCHIVE_ZIP_HEADER_H
#define __ARCHIVE_ZIP_HEADER_H
#include "Common/Types.h"
namespace NArchive {
namespace NZip {
#pragma pack( push, PragmaZipHeaders)
#pragma pack( push, 1)
namespace NSignature
{
extern UINT32 kLocalFileHeader;
extern UINT32 kDataDescriptor;
extern UINT32 kCentralFileHeader;
extern UINT32 kEndOfCentralDir;
static const UINT32 kMarkerSize = 4;
}
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
};
const int kNumCompressionMethods = 11;
const BYTE kMadeByProgramVersion = 20;
const BYTE kDeflateExtractVersion = 20;
const BYTE kStoreExtractVersion = 10;
const BYTE kSupportedVersion = 20;
}
struct CLocalBlock
{
CVersion ExtractVersion;
UINT16 Flags;
UINT16 CompressionMethod;
UINT32 Time;
UINT32 FileCRC;
UINT32 PackSize;
UINT32 UnPackSize;
UINT16 NameSize;
UINT16 ExtraSize;
};
struct CDataDescriptor
{
UINT32 Signature;
UINT32 FileCRC;
UINT32 PackSize;
UINT32 UnPackSize;
};
struct CLocalBlockFull
{
UINT32 Signature;
CLocalBlock Header;
};
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 */
}
}
#pragma pack(pop)
#pragma pack(pop, PragmaZipHeaders)
}}
#endif

376
7zip/Archive/Zip/ZipIn.cpp Executable file
View File

@@ -0,0 +1,376 @@
// 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"
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();
}
//////////////////////////////////////
// Markers
inline bool TestMarkerCandidate(const void *testBytes, UINT32 &value)
{
value = *((const UINT32 *)(testBytes));
return (value == NSignature::kLocalFileHeader) ||
(value == NSignature::kEndOfCentralDir);
}
bool CInArchive::FindAndReadMarker(const UINT64 *searchHeaderSizeLimit)
{
m_ArchiveInfo.StartPosition = 0;
m_Position = m_StreamStartPosition;
if(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL) != 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;
while(true)
{
if (searchHeaderSizeLimit != NULL)
if (curTestPos - m_StreamStartPosition > *searchHeaderSizeLimit)
return false;
UINT32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev;
ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize);
UINT32 numBytesInBuffer = numBytesPrev + processedSize;
if (numBytesInBuffer < NSignature::kMarkerSize)
return false;
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_Position = curTestPos + NSignature::kMarkerSize;
if(m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL) != S_OK)
return false;
return true;
}
}
numBytesPrev = numBytesInBuffer - numTests;
memmove(buffer, buffer + numTests, numBytesPrev);
}
}
//////////////////////////////////////
// Read Operations
HRESULT CInArchive::ReadBytes(void *data, UINT32 size, UINT32 *processedSize)
{
UINT32 realProcessedSize;
HRESULT result = m_Stream->Read(data, size, &realProcessedSize);
if(processedSize != NULL)
*processedSize = realProcessedSize;
IncreasePositionValue(realProcessedSize);
return result;
}
void CInArchive::IncreasePositionValue(UINT64 addValue)
{
m_Position += addValue;
}
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);
}
//////////////////////////////////
// Read headers
bool CInArchive::ReadSignature(UINT32 &signature)
{
return ReadBytesAndTestSize(&signature, sizeof(signature));
}
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);
}
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));
}
// FSeek -= sizeof(UINT32); // atention it's not real position
while(m_Signature == NSignature::kLocalFileHeader)
{
// FSeek points to next byte after signature
NFileHeader::CLocalBlock localHeader;
CItemEx itemInfo;
itemInfo.LocalHeaderPosition =
UINT32(m_Position - m_StreamStartPosition - sizeof(UINT32)); // points to signature;
SafeReadBytes(&localHeader, sizeof(localHeader));
UINT32 fileNameSize = localHeader.NameSize;
itemInfo.Name = ReadFileName(fileNameSize);
/*
if (!NItemName::IsNameLegal(itemInfo.Name))
ThrowIncorrectArchiveException();
*/
itemInfo.ExtractVersion.Version = localHeader.ExtractVersion.Version;
itemInfo.ExtractVersion.HostOS = localHeader.ExtractVersion.HostOS;
itemInfo.Flags = localHeader.Flags & NFileHeader::NFlags::kUsedBitsMask;
itemInfo.CompressionMethod = localHeader.CompressionMethod;
itemInfo.Time = localHeader.Time;
itemInfo.FileCRC = localHeader.FileCRC;
itemInfo.PackSize = localHeader.PackSize;
itemInfo.UnPackSize = localHeader.UnPackSize;
itemInfo.LocalExtraSize = localHeader.ExtraSize;
itemInfo.FileHeaderWithNameSize = sizeof(UINT32) + sizeof(localHeader) + fileNameSize;
IncreaseRealPosition(localHeader.ExtraSize);
if (itemInfo.HasDescriptor())
{
const int kBufferSize = (1 << 12);
BYTE buffer[kBufferSize];
UINT32 numBytesInBuffer = 0;
UINT32 packedSize = 0;
bool descriptorWasFound = false;
while (true)
{
UINT32 processedSize;
RINOK(ReadBytes(buffer + numBytesInBuffer,
kBufferSize - numBytesInBuffer, &processedSize));
numBytesInBuffer += processedSize;
if (numBytesInBuffer < sizeof(NFileHeader::CDataDescriptor))
ThrowIncorrectArchiveException();
int i;
for (i = 0; i <= numBytesInBuffer -
sizeof(NFileHeader::CDataDescriptor); i++)
{
const NFileHeader::CDataDescriptor &descriptor =
*(NFileHeader::CDataDescriptor *)(buffer + i);
if (descriptor.Signature == NSignature::kDataDescriptor &&
descriptor.PackSize == packedSize + i)
{
descriptorWasFound = true;
itemInfo.FileCRC = descriptor.FileCRC;
itemInfo.PackSize = descriptor.PackSize;
itemInfo.UnPackSize = descriptor.UnPackSize;
IncreaseRealPosition(INT64(INT32(0 - (numBytesInBuffer - i -
sizeof(NFileHeader::CDataDescriptor)))));
break;
};
}
if (descriptorWasFound)
break;
packedSize += i;
int j;
for (j = 0; i < numBytesInBuffer; i++, j++)
buffer[j] = buffer[i];
numBytesInBuffer = j;
}
}
else
IncreaseRealPosition(localHeader.PackSize);
items.Add(itemInfo);
if (progress != 0)
{
UINT64 numItems = items.Size();
RINOK(progress->SetCompleted(&numItems));
}
if (!ReadSignature(m_Signature))
break;
}
UINT32 centralDirectorySize = 0;
UINT64 centralDirectoryStartOffset = m_Position - sizeof(UINT32);
for(int i = 0; i < items.Size(); i++)
{
if (progress != 0)
{
UINT64 numItems = items.Size();
RINOK(progress->SetCompleted(&numItems));
}
// if(m_Signature == NSignature::kEndOfCentralDir)
// break;
if(m_Signature != NSignature::kCentralFileHeader)
ThrowIncorrectArchiveException();
NFileHeader::CBlock header;
SafeReadBytes(&header, sizeof(header));
UINT32 localHeaderOffset = header.LocalHeaderOffset;
header.Flags &= NFileHeader::NFlags::kUsedBitsMask;
int index;
int left = 0, right = items.Size();
while(true)
{
if (left >= right)
ThrowIncorrectArchiveException();
index = (left + right) / 2;
UINT32 position = items[index].LocalHeaderPosition;
if (localHeaderOffset == position)
break;
if (localHeaderOffset < position)
right = index;
else
left = index + 1;
}
CItemEx &itemInfo = items[index];
itemInfo.MadeByVersion.Version = header.MadeByVersion.Version;
itemInfo.MadeByVersion.HostOS = header.MadeByVersion.HostOS;
CVersion centalHeaderExtractVersion;
centalHeaderExtractVersion.Version = header.ExtractVersion.Version;
centalHeaderExtractVersion.HostOS = header.ExtractVersion.HostOS;
if (
// itemInfo.ExtractVersion != centalHeaderExtractVersion ||
itemInfo.Flags != header.Flags ||
itemInfo.CompressionMethod != header.CompressionMethod ||
// itemInfo.Time != header.Time ||
itemInfo.FileCRC != header.FileCRC ||
itemInfo.PackSize != header.PackSize ||
itemInfo.UnPackSize != header.UnPackSize)
ThrowIncorrectArchiveException();
AString centralName = ReadFileName(header.NameSize);
if (itemInfo.Name.Length() != centralName.Length())
ThrowIncorrectArchiveException(); // test it maybe better compare names
itemInfo.Name = centralName;
itemInfo.CentralExtraPosition = m_Position;
itemInfo.CentralExtraSize = header.ExtraSize;
itemInfo.CommentSize = header.CommentSize;
if (header.DiskNumberStart != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
itemInfo.InternalAttributes = header.InternalAttributes;
itemInfo.ExternalAttributes = header.ExternalAttributes;
// May be these strings must be deleted
if (itemInfo.IsDirectory())
{
// if (itemInfo.PackSize != 0 /* || itemInfo.UnPackSize != 0 */)
// ThrowIncorrectArchiveException();
itemInfo.UnPackSize = 0;
}
UINT32 currentRecordSize = sizeof(UINT32) + sizeof(header) +
header.NameSize + header.ExtraSize + header.CommentSize;
centralDirectorySize += currentRecordSize;
IncreaseRealPosition(header.ExtraSize + header.CommentSize);
if (!ReadSignature(m_Signature))
break;
}
if(m_Signature != NSignature::kEndOfCentralDir)
ThrowIncorrectArchiveException();
CEndOfCentralDirectoryRecord endOfCentralDirHeader;
SafeReadBytes(&endOfCentralDirHeader, sizeof(endOfCentralDirHeader));
if (endOfCentralDirHeader.ThisDiskNumber != 0 ||
endOfCentralDirHeader.StartCentralDirectoryDiskNumber != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
if (endOfCentralDirHeader.NumEntriesInCentaralDirectoryOnThisDisk != ((UINT16)items.Size()) ||
endOfCentralDirHeader.NumEntriesInCentaralDirectory != ((UINT16)items.Size()) ||
endOfCentralDirHeader.CentralDirectorySize != centralDirectorySize ||
(endOfCentralDirHeader.CentralDirectoryStartOffset != centralDirectoryStartOffset &&
(!items.IsEmpty())))
ThrowIncorrectArchiveException();
m_ArchiveInfo.CommentPosition = m_Position;
m_ArchiveInfo.CommentSize = endOfCentralDirHeader.CommentSize;
return S_OK;
}
ISequentialInStream* CInArchive::CreateLimitedStream(UINT64 position, UINT64 size)
{
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<ISequentialInStream> inStream(streamSpec);
SeekInArchive(position);
streamSpec->Init(m_Stream, 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);
}
}}

84
7zip/Archive/Zip/ZipIn.h Executable file
View File

@@ -0,0 +1,84 @@
// Archive/ZipIn.h
#pragma once
#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 CCauseType
{
kUnexpectedEndOfArchive = 0,
kArchiceHeaderCRCError,
kFileHeaderCRCError,
kIncorrectArchive,
kDataDescroptorsAreNotSupported,
kMultiVolumeArchiveAreNotSupported,
kReadStreamError,
kSeekStreamError
}
Cause;
CInArchiveException(CCauseType cause): Cause(cause) {}
};
class CInArchiveInfo
{
public:
UINT64 StartPosition;
UINT64 CommentPosition;
UINT16 CommentSize;
bool IsCommented() const { return (CommentSize != 0); };
};
class CProgressVirt
{
public:
STDMETHOD(SetCompleted)(const UINT64 *numFiles) PURE;
};
class CInArchive
{
CMyComPtr<IInStream> m_Stream;
UINT32 m_Signature;
UINT64 m_StreamStartPosition;
UINT64 m_Position;
CInArchiveInfo m_ArchiveInfo;
AString m_NameBuffer;
bool FindAndReadMarker(const UINT64 *searchHeaderSizeLimit);
bool ReadSignature(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 IncreasePositionValue(UINT64 addValue);
void IncreaseRealPosition(UINT64 addValue);
void ThrowIncorrectArchiveException();
public:
HRESULT ReadHeaders(CObjectVector<CItemEx> &items, CProgressVirt *progress);
bool Open(IInStream *inStream, const UINT64 *searchHeaderSizeLimit);
void Close();
void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
void DirectGetBytes(void *data, UINT32 num);
bool SeekInArchive(UINT64 position);
ISequentialInStream *CreateLimitedStream(UINT64 position, UINT64 size);
IInStream* CreateStream();
};
}}
#endif

132
7zip/Archive/Zip/ZipItem.cpp Executable file
View File

@@ -0,0 +1,132 @@
// Archive/ZipItem.cpp
#include "StdAfx.h"
#include "ZipHeader.h"
#include "ZipItem.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 CItem::IsEncrypted() const
{ return (Flags & NFileHeader::NFlags::kEncryptedMask) != 0; }
bool CItem::HasDescriptor() const
{ return (Flags & NFileHeader::NFlags::kDescriptorUsedMask) != 0; }
bool CItem::IsImplodeBigDictionary() const
{
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
throw 12312212;
return (Flags & NFileHeader::NFlags::kImplodeDictionarySizeMask) != 0;
}
bool CItem::IsImplodeLiteralsOn() const
{
if (CompressionMethod != NFileHeader::NCompressionMethod::kImploded)
throw 12312213;
return (Flags & NFileHeader::NFlags::kImplodeLiteralsOnMask) != 0;
}
static const char *kUnknownAttributes = "Unknown file attributes";
bool CItem::IsDirectory() const
{
if (!Name.IsEmpty())
{
#ifdef WIN32
LPCSTR prev = CharPrevExA(GetCodePage(), Name, &Name[Name.Length()], 0);
if (*prev == '/')
return true;
#else
if (Name[Name.Length() - 1) == '/')
return true;
#endif
}
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 CItem::GetWinAttributes() const
{
DWORD winAttributes;
switch(MadeByVersion.HostOS)
{
case NFileHeader::NHostOS::kFAT:
case NFileHeader::NHostOS::kNTFS:
winAttributes = ExternalAttributes;
break;
default:
winAttributes = 0; // must be converted from unix value;;
}
if (IsDirectory()) // test it;
winAttributes |= FILE_ATTRIBUTE_DIRECTORY;
return winAttributes;
}
void CItem::ClearFlags()
{ Flags = 0; }
void CItem::SetFlagBits(int startBitNumber, int numBits, int value)
{
WORD mask = ((1 << numBits) - 1) << startBitNumber;
Flags &= ~mask;
Flags |= value << startBitNumber;
}
void CItem::SetBitMask(int bitMask, bool enable)
{
if(enable)
Flags |= bitMask;
else
Flags &= ~bitMask;
}
void CItem::SetEncrypted(bool encrypted)
{ SetBitMask(NFileHeader::NFlags::kEncryptedMask, encrypted); }
}}

72
7zip/Archive/Zip/ZipItem.h Executable file
View File

@@ -0,0 +1,72 @@
// Archive/ZipItem.h
#pragma once
#ifndef __ARCHIVE_ZIP_ITEM_H
#define __ARCHIVE_ZIP_ITEM_H
#include "Common/Types.h"
#include "Common/String.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);
class CItem
{
public:
CVersion MadeByVersion;
CVersion ExtractVersion;
UINT16 Flags;
UINT16 CompressionMethod;
UINT32 Time;
UINT32 FileCRC;
UINT32 PackSize;
UINT32 UnPackSize;
UINT16 InternalAttributes;
UINT32 ExternalAttributes;
AString Name;
UINT32 LocalHeaderPosition;
UINT16 LocalExtraSize;
UINT16 CentralExtraSize;
UINT16 CommentSize;
bool IsEncrypted() const;
bool IsImplodeBigDictionary() const;
bool IsImplodeLiteralsOn() const;
bool IsDirectory() const;
bool IgnoreItem() const { return false; }
UINT32 GetWinAttributes() const;
bool HasDescriptor() const;
#ifdef WIN32
WORD GetCodePage() const
{ return (MadeByVersion.HostOS == NFileHeader::NHostOS::kFAT) ? CP_OEMCP : CP_ACP; }
#endif
private:
void SetFlagBits(int startBitNumber, int numBits, int value);
void SetBitMask(int bitMask, bool enable);
public:
void ClearFlags();
void SetEncrypted(bool encrypted);
};
}}
#endif

47
7zip/Archive/Zip/ZipItemEx.h Executable file
View File

@@ -0,0 +1,47 @@
// Archive/ZipItemEx.h
#pragma once
#ifndef __ARCHIVE_ZIP_ITEMEX_H
#define __ARCHIVE_ZIP_ITEMEX_H
#include "Common/Vector.h"
#include "ZipHeader.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
class CItemEx: public CItem
{
public:
UINT16 FileHeaderWithNameSize;
UINT64 CentralExtraPosition;
UINT32 GetLocalFullSize() const
{ return FileHeaderWithNameSize + LocalExtraSize + PackSize +
(HasDescriptor() ? sizeof(NFileHeader::CDataDescriptor) : 0); };
UINT32 GetCentralExtraPlusCommentSize() const
{ return CentralExtraSize + CommentSize; };
UINT64 GetCommentPosition() const
{ return CentralExtraPosition + CentralExtraSize; };
bool IsCommented() const
{ return CommentSize != 0; };
UINT64 GetLocalExtraPosition() const
{ return LocalHeaderPosition + FileHeaderWithNameSize; };
UINT64 GetDataPosition() const
{ return GetLocalExtraPosition() + LocalExtraSize; };
};
}}
#endif

134
7zip/Archive/Zip/ZipOut.cpp Executable file
View File

@@ -0,0 +1,134 @@
// ZipOut.cpp
#include "StdAfx.h"
#include "ZipOut.h"
#include "Common/StringConvert.h"
#include "Common/CRC.h"
#include "../../Common/OffsetStream.h"
namespace NArchive {
namespace NZip {
void COutArchive::Create(IOutStream *outStream)
{
m_Stream = outStream;
m_BasePosition = 0;
}
void COutArchive::MoveBasePosition(UINT32 distanceToMove)
{
m_BasePosition += distanceToMove; // test overflow
}
void COutArchive::PrepareWriteCompressedData(UINT16 fileNameLength)
{
m_LocalFileHeaderSize = sizeof(NFileHeader::CLocalBlockFull) + fileNameLength;
}
void COutArchive::WriteBytes(const void *buffer, UINT32 size)
{
UINT32 processedSize;
if(m_Stream->Write(buffer, size, &processedSize) != S_OK)
throw 0;
if(processedSize != size)
throw 0;
m_BasePosition += size;
}
void COutArchive::WriteLocalHeader(const CItem &item)
{
NFileHeader::CLocalBlockFull fileHeader;
fileHeader.Signature = NSignature::kLocalFileHeader;
NFileHeader::CLocalBlock &header = fileHeader.Header;
header.ExtractVersion.HostOS = item.ExtractVersion.HostOS;
header.ExtractVersion.Version = item.ExtractVersion.Version;
header.Flags = item.Flags;
header.CompressionMethod = item.CompressionMethod;
header.Time = item.Time;
header.FileCRC = item.FileCRC;
header.PackSize = item.PackSize;
header.UnPackSize = item.UnPackSize;
header.NameSize = item.Name.Length();
header.ExtraSize = item.LocalExtraSize; // test it;
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
WriteBytes(&fileHeader, sizeof(fileHeader));
WriteBytes((const char *)item.Name, header.NameSize);
MoveBasePosition(header.ExtraSize + header.PackSize);
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
}
void COutArchive::WriteCentralHeader(const CItem &item)
{
NFileHeader::CBlockFull fileHeader;
fileHeader.Signature = NSignature::kCentralFileHeader;
NFileHeader::CBlock &header = fileHeader.Header;
header.MadeByVersion.HostOS = item.MadeByVersion.HostOS;
header.MadeByVersion.Version = item.MadeByVersion.Version;
header.ExtractVersion.HostOS = item.ExtractVersion.HostOS;
header.ExtractVersion.Version = item.ExtractVersion.Version;
header.Flags = item.Flags;
header.CompressionMethod = item.CompressionMethod;
header.Time = item.Time;
header.FileCRC = item.FileCRC;
header.PackSize = item.PackSize;
header.UnPackSize = item.UnPackSize;
header.NameSize = item.Name.Length();
header.ExtraSize = item.CentralExtraSize; // test it;
header.CommentSize = item.CommentSize;
header.DiskNumberStart = 0;
header.InternalAttributes = item.InternalAttributes;
header.ExternalAttributes = item.ExternalAttributes;
header.LocalHeaderOffset = item.LocalHeaderPosition;
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
WriteBytes(&fileHeader, sizeof(fileHeader));
WriteBytes((const char *)item.Name, header.NameSize);
}
void COutArchive::WriteEndOfCentralDir(const COutArchiveInfo &archiveInfo)
{
CEndOfCentralDirectoryRecordFull fileHeader;
fileHeader.Signature = NSignature::kEndOfCentralDir;
CEndOfCentralDirectoryRecord &header = fileHeader.Header;
header.ThisDiskNumber = 0;
header.StartCentralDirectoryDiskNumber = 0;
header.NumEntriesInCentaralDirectoryOnThisDisk = archiveInfo.NumEntriesInCentaralDirectory;
header.NumEntriesInCentaralDirectory = archiveInfo.NumEntriesInCentaralDirectory;
header.CentralDirectorySize = archiveInfo.CentralDirectorySize;
header.CentralDirectoryStartOffset = archiveInfo.CentralDirectoryStartOffset;
header.CommentSize = archiveInfo.CommentSize;
m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL);
WriteBytes(&fileHeader, sizeof(fileHeader));
}
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();
}
}}

53
7zip/Archive/Zip/ZipOut.h Executable file
View File

@@ -0,0 +1,53 @@
// ZipOut.h
#pragma once
#ifndef __ZIP_OUT_H
#define __ZIP_OUT_H
#include "Common/MyCom.h"
#include "../../IStream.h"
#include "ZipHeader.h"
#include "ZipItem.h"
namespace NArchive {
namespace NZip {
class COutArchiveInfo
{
public:
UINT16 NumEntriesInCentaralDirectory;
UINT32 CentralDirectorySize;
UINT32 CentralDirectoryStartOffset;
UINT16 CommentSize;
};
class COutArchive
{
CMyComPtr<IOutStream> m_Stream;
UINT32 m_BasePosition;
UINT32 m_LocalFileHeaderSize;
void WriteBytes(const void *buffer, UINT32 size);
public:
void Create(IOutStream *outStream);
void MoveBasePosition(UINT32 distanceToMove);
UINT32 GetCurrentPosition() const { return m_BasePosition; };
void PrepareWriteCompressedData(UINT16 fileNameLength);
void WriteLocalHeader(const CItem &item);
void WriteCentralHeader(const CItem &item);
void WriteEndOfCentralDir(const COutArchiveInfo &archiveInfo);
void CreateStreamForCompressing(IOutStream **outStream);
void CreateStreamForCopying(ISequentialOutStream **outStream);
void SeekToPackedDataPosition();
};
}}
#endif

357
7zip/Archive/Zip/ZipUpdate.cpp Executable file
View File

@@ -0,0 +1,357 @@
// ZipUpdate.cpp
#include "StdAfx.h"
#include "ZipUpdate.h"
#include "ZipAddCommon.h"
#include "ZipOut.h"
#include "Common/Defs.h"
#include "Common/StringConvert.h"
#include "Windows/Defs.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/LimitedStreams.h"
#include "../../Compress/Copy/CopyCoder.h"
#include "../Common/InStreamWithCRC.h"
using namespace std;
namespace NArchive {
namespace NZip {
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 CopyBlock(ISequentialInStream *inStream,
ISequentialOutStream *outStream, ICompressProgressInfo *progress)
{
CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
}
HRESULT CopyBlockToArchive(ISequentialInStream *inStream,
COutArchive &outArchive, ICompressProgressInfo *progress)
{
CMyComPtr<ISequentialOutStream> outStream;
outArchive.CreateStreamForCopying(&outStream);
return CopyBlock(inStream, outStream, progress);
}
static HRESULT WriteRange(IInStream *inStream,
COutArchive &outArchive,
const CUpdateRange &range,
IProgress *progress,
UINT64 &currentComplexity)
{
UINT64 position;
inStream->Seek(range.Position, STREAM_SEEK_SET, &position);
CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
streamSpec->Init(inStream, range.Size);
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(progress, true);
CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(localProgress, &currentComplexity, &currentComplexity);
HRESULT result = CopyBlockToArchive(inStreamLimited, outArchive, compressProgress);
currentComplexity += range.Size;
return result;
}
static HRESULT UpdateOneFile(IInStream *inStream,
COutArchive &archive,
const CCompressionMethodMode &options,
CAddCommon &compressor,
const CUpdateItem &updateItem,
UINT64 &currentComplexity,
IArchiveUpdateCallback *updateCallback,
CItemEx &fileHeader)
{
CMyComPtr<IInStream> fileInStream;
RINOK(updateCallback->GetStream(updateItem.IndexInClient, &fileInStream));
bool isDirectory;
UINT32 fileSize = updateItem.Size;
fileHeader.UnPackSize = fileSize;
if (updateItem.NewProperties)
{
isDirectory = updateItem.IsDirectory;
fileHeader.Name = updateItem.Name;
fileHeader.ExternalAttributes = updateItem.Attributes;
fileHeader.Time = updateItem.Time;
}
else
isDirectory = fileHeader.IsDirectory();
archive.PrepareWriteCompressedData(fileHeader.Name.Length());
fileHeader.LocalHeaderPosition = archive.GetCurrentPosition();
fileHeader.MadeByVersion.HostOS = kMadeByHostOS;
fileHeader.MadeByVersion.Version = NFileHeader::NCompressionMethod::kMadeByProgramVersion;
fileHeader.ExtractVersion.HostOS = kExtractHostOS;
fileHeader.InternalAttributes = 0; // test it
fileHeader.ClearFlags();
if(isDirectory)
{
fileHeader.ExtractVersion.Version = kExtractVersionForDirectory;
fileHeader.CompressionMethod = kMethodForDirectory;
fileHeader.PackSize = 0;
fileHeader.FileCRC = 0; // test it
}
else
{
{
CInStreamWithCRC *inStreamSpec = new CInStreamWithCRC;
CMyComPtr<IInStream> inStream(inStreamSpec);
inStreamSpec->Init(fileInStream);
CCompressingResult compressingResult;
CMyComPtr<IOutStream> outStream;
archive.CreateStreamForCompressing(&outStream);
CLocalProgress *localProgressSpec = new CLocalProgress;
CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
localProgressSpec->Init(updateCallback, true);
CLocalCompressProgressInfo *localCompressProgressSpec =
new CLocalCompressProgressInfo;
CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
localCompressProgressSpec->Init(localProgress, &currentComplexity, NULL);
RINOK(compressor.Compress(inStream, outStream,
fileSize, compressProgress, compressingResult));
fileHeader.PackSize = (UINT32)compressingResult.PackSize;
fileHeader.CompressionMethod = compressingResult.Method;
fileHeader.ExtractVersion.Version = compressingResult.ExtractVersion;
fileHeader.FileCRC = inStreamSpec->GetCRC();
fileHeader.UnPackSize = (UINT32)inStreamSpec->GetSize();
}
}
fileHeader.SetEncrypted(options.PasswordIsDefined);
fileHeader.CommentSize = (updateItem.Commented) ?
WORD(updateItem.CommentRange.Size) : 0;
fileHeader.LocalExtraSize = 0;
fileHeader.CentralExtraSize = 0;
archive.WriteLocalHeader(fileHeader);
currentComplexity += fileSize;
return updateCallback->SetOperationResult(
NArchive::NUpdate::NOperationResult::kOK);
}
static HRESULT Update2(COutArchive &archive,
IInStream *inStream,
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
const CCompressionMethodMode *options,
bool commentRangeAssigned,
const CUpdateRange &commentRange,
IArchiveUpdateCallback *updateCallback)
{
UINT64 complexity = 0;
UINT64 estimatedArchiveSize = (1<<20); // sfx part
int i;
for(i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &updateItem = updateItems[i];
if (updateItem.NewData)
{
complexity += updateItem.Size;
if (updateItem.Commented)
complexity += updateItem.CommentRange.Size;
estimatedArchiveSize += updateItem.Name.Length() * 2 + 100;
}
else
{
const CItemEx &inputItem = inputItems[updateItem.IndexInArchive];
complexity += inputItem.GetLocalFullSize();
complexity += inputItem.GetCentralExtraPlusCommentSize();
}
}
complexity += updateItems.Size();
complexity += updateItems.Size();
estimatedArchiveSize += complexity;
if (estimatedArchiveSize > 0xFFFFFFFF)
return E_NOTIMPL;
if (commentRangeAssigned)
complexity += commentRange.Size;
complexity++; // end of central
updateCallback->SetTotal(complexity);
auto_ptr<CAddCommon> compressor;
complexity = 0;
CObjectVector<CItemEx> items;
for(i = 0; i < updateItems.Size(); i++)
{
const CUpdateItem &updateItem = updateItems[i];
RINOK(updateCallback->SetCompleted(&complexity));
CItemEx item;
if (!updateItem.NewProperties || !updateItem.NewData)
item = inputItems[updateItem.IndexInArchive];
if (updateItem.NewData)
{
if(compressor.get() == NULL)
{
compressor = auto_ptr<CAddCommon>(new CAddCommon(*options));
}
RINOK(UpdateOneFile(inStream, archive, *options,
*compressor, updateItem, complexity, updateCallback, item));
}
else
{
// item = inputItems[copyIndices[copyIndexIndex++]];
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.CentralExtraSize = 0;
item.LocalExtraSize = 0;
archive.PrepareWriteCompressedData(item.Name.Length());
item.LocalHeaderPosition = archive.GetCurrentPosition();
archive.SeekToPackedDataPosition();
RINOK(WriteRange(inStream, archive, range,
updateCallback, complexity));
archive.WriteLocalHeader(item);
}
else
{
CUpdateRange range(item.LocalHeaderPosition, item.GetLocalFullSize());
// set new header position
item.LocalHeaderPosition = archive.GetCurrentPosition();
RINOK(WriteRange(inStream, archive, range,
updateCallback, complexity));
archive.MoveBasePosition(range.Size);
}
}
items.Add(item);
complexity++;
}
DWORD centralDirStartPosition = archive.GetCurrentPosition();
for(i = 0; i < items.Size(); i++)
{
archive.WriteCentralHeader(items[i]);
const CUpdateItem &updateItem = updateItems[i];
if (updateItem.NewProperties)
{
if (updateItem.Commented)
{
const CUpdateRange range = updateItem.CommentRange;
RINOK(WriteRange(inStream, archive, range,
updateCallback, complexity));
archive.MoveBasePosition(range.Size);
}
}
else
{
const CItemEx item = items[i];
CUpdateRange range(item.CentralExtraPosition,
item.GetCentralExtraPlusCommentSize());
RINOK(WriteRange(inStream, archive, range,
updateCallback, complexity));
archive.MoveBasePosition(range.Size);
}
complexity++;
}
COutArchiveInfo archiveInfo;
archiveInfo.NumEntriesInCentaralDirectory = items.Size();
archiveInfo.CentralDirectorySize = archive.GetCurrentPosition() -
centralDirStartPosition;
archiveInfo.CentralDirectoryStartOffset = centralDirStartPosition;
archiveInfo.CommentSize = commentRangeAssigned ? WORD(commentRange.Size) : 0;
archive.WriteEndOfCentralDir(archiveInfo);
if (commentRangeAssigned)
RINOK(WriteRange(inStream, archive, commentRange,
updateCallback, complexity));
complexity++; // end of central
return S_OK;
}
HRESULT Update(
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
IOutStream *outStream,
CInArchive *inArchive,
CCompressionMethodMode *compressionMethodMode,
IArchiveUpdateCallback *updateCallback)
{
DWORD startBlockSize;
bool commentRangeAssigned;
CUpdateRange commentRange;
if(inArchive != 0)
{
CInArchiveInfo archiveInfo;
inArchive->GetArchiveInfo(archiveInfo);
startBlockSize = archiveInfo.StartPosition;
commentRangeAssigned = archiveInfo.IsCommented();
if (commentRangeAssigned)
{
commentRange.Position = archiveInfo.CommentPosition;
commentRange.Size = archiveInfo.CommentSize;
}
}
else
{
startBlockSize = 0;
commentRangeAssigned = false;
}
COutArchive outArchive;
outArchive.Create(outStream);
if (startBlockSize > 0)
{
CMyComPtr<ISequentialInStream> inStream;
inStream.Attach(inArchive->CreateLimitedStream(0, startBlockSize));
RINOK(CopyBlockToArchive(inStream, outArchive, NULL));
outArchive.MoveBasePosition(startBlockSize);
}
CMyComPtr<IInStream> inStream;
if(inArchive != 0)
inStream.Attach(inArchive->CreateStream());
return Update2(outArchive, inStream,
inputItems, updateItems,
compressionMethodMode,
commentRangeAssigned, commentRange, updateCallback);
}
}}

59
7zip/Archive/Zip/ZipUpdate.h Executable file
View File

@@ -0,0 +1,59 @@
// Zip/Update.h
#pragma once
#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
{
UINT32 Position;
UINT32 Size;
CUpdateRange() {};
CUpdateRange(UINT32 position, UINT32 size):
Position(position), Size(size) {};
};
struct CUpdateItem
{
bool NewData;
bool NewProperties;
bool IsDirectory;
int IndexInArchive;
int IndexInClient;
UINT32 Attributes;
UINT32 Time;
UINT32 Size;
AString Name;
// bool ExistInArchive;
bool Commented;
CUpdateRange CommentRange;
/*
bool IsDirectory() const
{ return ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); };
*/
};
HRESULT Update(
const CObjectVector<CItemEx> &inputItems,
const CObjectVector<CUpdateItem> &updateItems,
IOutStream *outStream,
CInArchive *inArchive,
CCompressionMethodMode *compressionMethodMode,
IArchiveUpdateCallback *updateCallback);
}}
#endif

16
7zip/Archive/Zip/resource.h Executable file
View File

@@ -0,0 +1,16 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by resource.rc
//
#define IDI_ICON1 101
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 102
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

130
7zip/Archive/Zip/resource.rc Executable file
View File

@@ -0,0 +1,130 @@
//Microsoft Developer Studio generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Russian resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_RUS)
#ifdef _WIN32
LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT
#pragma code_page(1251)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE DISCARDABLE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
#endif // Russian resources
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// English (U.S.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
#pragma code_page(1252)
#endif //_WIN32
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON DISCARDABLE "zip.ico"
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,12,0,0
PRODUCTVERSION 3,12,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "Comments", "\0"
VALUE "CompanyName", "Igor Pavlov\0"
VALUE "FileDescription", "Zip Plugin for 7-Zip\0"
VALUE "FileVersion", "3, 12, 0, 0\0"
VALUE "InternalName", "zip\0"
VALUE "LegalCopyright", "Copyright (C) 1999-2003 Igor Pavlov\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "zip.dll\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "7-Zip\0"
VALUE "ProductVersion", "3, 12, 0, 0\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
#endif // !_MAC
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

BIN
7zip/Archive/Zip/zip.ico Executable file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB