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
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive')
-rwxr-xr-xCPP/7zip/Archive/7z/7z.dsp593
-rwxr-xr-xCPP/7zip/Archive/7z/7z.dsw29
-rwxr-xr-xCPP/7zip/Archive/7z/7z.icobin0 -> 4710 bytes
-rwxr-xr-xCPP/7zip/Archive/7z/7zCompressionMode.cpp3
-rwxr-xr-xCPP/7zip/Archive/7z/7zCompressionMode.h64
-rwxr-xr-xCPP/7zip/Archive/7z/7zDecode.cpp444
-rwxr-xr-xCPP/7zip/Archive/7z/7zDecode.h71
-rwxr-xr-xCPP/7zip/Archive/7z/7zEncode.cpp614
-rwxr-xr-xCPP/7zip/Archive/7z/7zEncode.h58
-rwxr-xr-xCPP/7zip/Archive/7z/7zExtract.cpp265
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderInStream.cpp129
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderInStream.h66
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderOutStream.cpp162
-rwxr-xr-xCPP/7zip/Archive/7z/7zFolderOutStream.h57
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.cpp794
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandler.h249
-rwxr-xr-xCPP/7zip/Archive/7z/7zHandlerOut.cpp1148
-rwxr-xr-xCPP/7zip/Archive/7z/7zHeader.cpp19
-rwxr-xr-xCPP/7zip/Archive/7z/7zHeader.h96
-rwxr-xr-xCPP/7zip/Archive/7z/7zIn.cpp1335
-rwxr-xr-xCPP/7zip/Archive/7z/7zIn.h288
-rwxr-xr-xCPP/7zip/Archive/7z/7zItem.h181
-rwxr-xr-xCPP/7zip/Archive/7z/7zMethodID.cpp76
-rwxr-xr-xCPP/7zip/Archive/7z/7zMethodID.h29
-rwxr-xr-xCPP/7zip/Archive/7z/7zMethods.cpp174
-rwxr-xr-xCPP/7zip/Archive/7z/7zMethods.h36
-rwxr-xr-xCPP/7zip/Archive/7z/7zOut.cpp1136
-rwxr-xr-xCPP/7zip/Archive/7z/7zOut.h192
-rwxr-xr-xCPP/7zip/Archive/7z/7zProperties.cpp166
-rwxr-xr-xCPP/7zip/Archive/7z/7zProperties.h22
-rwxr-xr-xCPP/7zip/Archive/7z/7zSpecStream.cpp24
-rwxr-xr-xCPP/7zip/Archive/7z/7zSpecStream.h35
-rwxr-xr-xCPP/7zip/Archive/7z/7zUpdate.cpp1099
-rwxr-xr-xCPP/7zip/Archive/7z/7zUpdate.h79
-rwxr-xr-xCPP/7zip/Archive/7z/DllExports.cpp113
-rwxr-xr-xCPP/7zip/Archive/7z/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/7z/StdAfx.h9
-rwxr-xr-xCPP/7zip/Archive/7z/makefile89
-rwxr-xr-xCPP/7zip/Archive/7z/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Archive.def3
-rwxr-xr-xCPP/7zip/Archive/Arj/Arj.dsp329
-rwxr-xr-xCPP/7zip/Archive/Arj/Arj.dsw29
-rwxr-xr-xCPP/7zip/Archive/Arj/ArjHandler.cpp485
-rwxr-xr-xCPP/7zip/Archive/Arj/ArjHandler.h47
-rwxr-xr-xCPP/7zip/Archive/Arj/ArjHeader.h121
-rwxr-xr-xCPP/7zip/Archive/Arj/ArjIn.cpp283
-rwxr-xr-xCPP/7zip/Archive/Arj/ArjIn.h75
-rwxr-xr-xCPP/7zip/Archive/Arj/ArjItem.h75
-rwxr-xr-xCPP/7zip/Archive/Arj/DllExports.cpp72
-rwxr-xr-xCPP/7zip/Archive/Arj/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Arj/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Arj/arj.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Arj/makefile66
-rwxr-xr-xCPP/7zip/Archive/Arj/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2.dsp281
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2.dsw29
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Handler.cpp287
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Handler.h83
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp156
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Item.h20
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Update.cpp84
-rwxr-xr-xCPP/7zip/Archive/BZip2/BZip2Update.h24
-rwxr-xr-xCPP/7zip/Archive/BZip2/DllExports.cpp127
-rwxr-xr-xCPP/7zip/Archive/BZip2/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/BZip2/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/BZip2/bz2.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/BZip2/makefile55
-rwxr-xr-xCPP/7zip/Archive/BZip2/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Cab/Cab.dsp395
-rwxr-xr-xCPP/7zip/Archive/Cab/Cab.dsw29
-rwxr-xr-xCPP/7zip/Archive/Cab/CabBlockInStream.cpp194
-rwxr-xr-xCPP/7zip/Archive/Cab/CabBlockInStream.h56
-rwxr-xr-xCPP/7zip/Archive/Cab/CabHandler.cpp812
-rwxr-xr-xCPP/7zip/Archive/Cab/CabHandler.h45
-rwxr-xr-xCPP/7zip/Archive/Cab/CabHeader.cpp19
-rwxr-xr-xCPP/7zip/Archive/Cab/CabHeader.h42
-rwxr-xr-xCPP/7zip/Archive/Cab/CabIn.cpp343
-rwxr-xr-xCPP/7zip/Archive/Cab/CabIn.h166
-rwxr-xr-xCPP/7zip/Archive/Cab/CabItem.h62
-rwxr-xr-xCPP/7zip/Archive/Cab/DllExports.cpp72
-rwxr-xr-xCPP/7zip/Archive/Cab/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Cab/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Cab/cab.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Cab/makefile70
-rwxr-xr-xCPP/7zip/Archive/Cab/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Chm/Chm.dsp337
-rwxr-xr-xCPP/7zip/Archive/Chm/Chm.dsw29
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmHandler.cpp731
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmHandler.h46
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmHeader.cpp24
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmHeader.h28
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmIn.cpp925
-rwxr-xr-xCPP/7zip/Archive/Chm/ChmIn.h242
-rwxr-xr-xCPP/7zip/Archive/Chm/DllExports.cpp77
-rwxr-xr-xCPP/7zip/Archive/Chm/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Chm/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Chm/makefile68
-rwxr-xr-xCPP/7zip/Archive/Chm/resource.rc3
-rwxr-xr-xCPP/7zip/Archive/Common/CodecsPath.cpp34
-rwxr-xr-xCPP/7zip/Archive/Common/CodecsPath.h12
-rwxr-xr-xCPP/7zip/Archive/Common/CoderLoader.cpp31
-rwxr-xr-xCPP/7zip/Archive/Common/CoderLoader.h147
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2.cpp121
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2.h168
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2MT.cpp359
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2MT.h121
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2ST.cpp238
-rwxr-xr-xCPP/7zip/Archive/Common/CoderMixer2ST.h88
-rwxr-xr-xCPP/7zip/Archive/Common/CrossThreadProgress.cpp15
-rwxr-xr-xCPP/7zip/Archive/Common/CrossThreadProgress.h31
-rwxr-xr-xCPP/7zip/Archive/Common/DummyOutStream.cpp20
-rwxr-xr-xCPP/7zip/Archive/Common/DummyOutStream.h23
-rwxr-xr-xCPP/7zip/Archive/Common/FilterCoder.cpp243
-rwxr-xr-xCPP/7zip/Archive/Common/FilterCoder.h130
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.cpp41
-rwxr-xr-xCPP/7zip/Archive/Common/InStreamWithCRC.h65
-rwxr-xr-xCPP/7zip/Archive/Common/ItemNameUtils.cpp59
-rwxr-xr-xCPP/7zip/Archive/Common/ItemNameUtils.h24
-rwxr-xr-xCPP/7zip/Archive/Common/MultiStream.cpp201
-rwxr-xr-xCPP/7zip/Archive/Common/MultiStream.h76
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.cpp24
-rwxr-xr-xCPP/7zip/Archive/Common/OutStreamWithCRC.h37
-rwxr-xr-xCPP/7zip/Archive/Common/ParseProperties.cpp171
-rwxr-xr-xCPP/7zip/Archive/Common/ParseProperties.h17
-rwxr-xr-xCPP/7zip/Archive/Common/StdAfx.h9
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHandler.cpp289
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHandler.h47
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHeader.cpp23
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioHeader.h70
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioIn.cpp271
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioIn.h41
-rwxr-xr-xCPP/7zip/Archive/Cpio/CpioItem.h55
-rwxr-xr-xCPP/7zip/Archive/Cpio/DllExports.cpp65
-rwxr-xr-xCPP/7zip/Archive/Cpio/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Cpio/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Cpio/cpio.dsp265
-rwxr-xr-xCPP/7zip/Archive/Cpio/cpio.dsw29
-rwxr-xr-xCPP/7zip/Archive/Cpio/cpio.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Cpio/makefile55
-rwxr-xr-xCPP/7zip/Archive/Cpio/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Deb/Deb.dsp269
-rwxr-xr-xCPP/7zip/Archive/Deb/Deb.dsw29
-rwxr-xr-xCPP/7zip/Archive/Deb/DebHandler.cpp255
-rwxr-xr-xCPP/7zip/Archive/Deb/DebHandler.h47
-rwxr-xr-xCPP/7zip/Archive/Deb/DebHeader.cpp13
-rwxr-xr-xCPP/7zip/Archive/Deb/DebHeader.h38
-rwxr-xr-xCPP/7zip/Archive/Deb/DebIn.cpp165
-rwxr-xr-xCPP/7zip/Archive/Deb/DebIn.h29
-rwxr-xr-xCPP/7zip/Archive/Deb/DebItem.h32
-rwxr-xr-xCPP/7zip/Archive/Deb/DllExports.cpp73
-rwxr-xr-xCPP/7zip/Archive/Deb/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Deb/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Deb/deb.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Deb/makefile54
-rwxr-xr-xCPP/7zip/Archive/Deb/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/GZip/DllExports.cpp125
-rwxr-xr-xCPP/7zip/Archive/GZip/GZip.dsp321
-rwxr-xr-xCPP/7zip/Archive/GZip/GZip.dsw29
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHandler.cpp361
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHandler.h79
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHandlerOut.cpp200
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHeader.cpp20
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipHeader.h85
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipIn.cpp121
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipIn.h31
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipItem.h59
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipOut.cpp69
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipOut.h29
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipUpdate.cpp120
-rwxr-xr-xCPP/7zip/Archive/GZip/GZipUpdate.h32
-rwxr-xr-xCPP/7zip/Archive/GZip/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/GZip/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/GZip/gz.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/GZip/makefile60
-rwxr-xr-xCPP/7zip/Archive/GZip/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/IArchive.h173
-rwxr-xr-xCPP/7zip/Archive/Iso/DllExports.cpp88
-rwxr-xr-xCPP/7zip/Archive/Iso/Iso.dsp273
-rwxr-xr-xCPP/7zip/Archive/Iso/Iso.dsw29
-rwxr-xr-xCPP/7zip/Archive/Iso/Iso.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHandler.cpp301
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHandler.h59
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHeader.cpp21
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoHeader.h61
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoIn.cpp438
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoIn.h301
-rwxr-xr-xCPP/7zip/Archive/Iso/IsoItem.h145
-rwxr-xr-xCPP/7zip/Archive/Iso/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Iso/StdAfx.h9
-rwxr-xr-xCPP/7zip/Archive/Iso/makefile55
-rwxr-xr-xCPP/7zip/Archive/Iso/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Lzh/DllExports.cpp72
-rwxr-xr-xCPP/7zip/Archive/Lzh/Lzh.def7
-rwxr-xr-xCPP/7zip/Archive/Lzh/Lzh.dsp333
-rwxr-xr-xCPP/7zip/Archive/Lzh/Lzh.dsw29
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhCRC.cpp43
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhCRC.h27
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhHandler.cpp464
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhHandler.h47
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhHeader.h19
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhIn.cpp171
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhIn.h29
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhItem.h172
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp27
-rwxr-xr-xCPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h38
-rwxr-xr-xCPP/7zip/Archive/Lzh/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Lzh/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Lzh/lzh.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Lzh/makefile65
-rwxr-xr-xCPP/7zip/Archive/Lzh/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Nsis/DllExports.cpp110
-rwxr-xr-xCPP/7zip/Archive/Nsis/Nsis.dsp337
-rwxr-xr-xCPP/7zip/Archive/Nsis/Nsis.dsw29
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisDecode.cpp150
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisDecode.h47
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisHandler.cpp484
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisHandler.h41
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisIn.cpp1169
-rwxr-xr-xCPP/7zip/Archive/Nsis/NsisIn.h166
-rwxr-xr-xCPP/7zip/Archive/Nsis/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Nsis/StdAfx.h9
-rwxr-xr-xCPP/7zip/Archive/Nsis/makefile67
-rwxr-xr-xCPP/7zip/Archive/Nsis/resource.rc3
-rwxr-xr-xCPP/7zip/Archive/RPM/DllExports.cpp68
-rwxr-xr-xCPP/7zip/Archive/RPM/Rpm.dsp205
-rwxr-xr-xCPP/7zip/Archive/RPM/Rpm.dsw29
-rwxr-xr-xCPP/7zip/Archive/RPM/RpmHandler.cpp194
-rwxr-xr-xCPP/7zip/Archive/RPM/RpmHandler.h46
-rwxr-xr-xCPP/7zip/Archive/RPM/RpmHeader.h63
-rwxr-xr-xCPP/7zip/Archive/RPM/RpmIn.cpp112
-rwxr-xr-xCPP/7zip/Archive/RPM/RpmIn.h15
-rwxr-xr-xCPP/7zip/Archive/RPM/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/RPM/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/RPM/makefile42
-rwxr-xr-xCPP/7zip/Archive/RPM/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/RPM/rpm.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Rar/DllExports.cpp142
-rwxr-xr-xCPP/7zip/Archive/Rar/Rar.dsp459
-rwxr-xr-xCPP/7zip/Archive/Rar/Rar.dsw29
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHandler.cpp941
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHandler.h63
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHeader.cpp21
-rwxr-xr-xCPP/7zip/Archive/Rar/RarHeader.h224
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.cpp535
-rwxr-xr-xCPP/7zip/Archive/Rar/RarIn.h124
-rwxr-xr-xCPP/7zip/Archive/Rar/RarItem.cpp118
-rwxr-xr-xCPP/7zip/Archive/Rar/RarItem.h91
-rwxr-xr-xCPP/7zip/Archive/Rar/RarVolumeInStream.cpp79
-rwxr-xr-xCPP/7zip/Archive/Rar/RarVolumeInStream.h50
-rwxr-xr-xCPP/7zip/Archive/Rar/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Rar/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Rar/makefile90
-rwxr-xr-xCPP/7zip/Archive/Rar/rar.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Rar/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Split/DllExports.cpp65
-rwxr-xr-xCPP/7zip/Archive/Split/Split.dsp237
-rwxr-xr-xCPP/7zip/Archive/Split/Split.dsw29
-rwxr-xr-xCPP/7zip/Archive/Split/Split.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Split/SplitHandler.cpp415
-rwxr-xr-xCPP/7zip/Archive/Split/SplitHandler.h62
-rwxr-xr-xCPP/7zip/Archive/Split/SplitHandlerOut.cpp102
-rwxr-xr-xCPP/7zip/Archive/Split/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Split/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Split/makefile51
-rwxr-xr-xCPP/7zip/Archive/Split/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Tar/DllExports.cpp86
-rwxr-xr-xCPP/7zip/Archive/Tar/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Tar/StdAfx.h9
-rwxr-xr-xCPP/7zip/Archive/Tar/Tar.dsp297
-rwxr-xr-xCPP/7zip/Archive/Tar/Tar.dsw29
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.cpp282
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandler.h56
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHandlerOut.cpp126
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHeader.cpp25
-rwxr-xr-xCPP/7zip/Archive/Tar/TarHeader.h99
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.cpp248
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.h30
-rwxr-xr-xCPP/7zip/Archive/Tar/TarItem.h69
-rwxr-xr-xCPP/7zip/Archive/Tar/TarOut.cpp191
-rwxr-xr-xCPP/7zip/Archive/Tar/TarOut.h28
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.cpp162
-rwxr-xr-xCPP/7zip/Archive/Tar/TarUpdate.h36
-rwxr-xr-xCPP/7zip/Archive/Tar/makefile59
-rwxr-xr-xCPP/7zip/Archive/Tar/resource.rc5
-rwxr-xr-xCPP/7zip/Archive/Tar/tar.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Z/DllExports.cpp91
-rwxr-xr-xCPP/7zip/Archive/Z/StdAfx.cpp3
-rwxr-xr-xCPP/7zip/Archive/Z/StdAfx.h8
-rwxr-xr-xCPP/7zip/Archive/Z/Z.dsp237
-rwxr-xr-xCPP/7zip/Archive/Z/Z.dsw29
-rwxr-xr-xCPP/7zip/Archive/Z/Z.icobin0 -> 3638 bytes
-rwxr-xr-xCPP/7zip/Archive/Z/ZHandler.cpp202
-rwxr-xr-xCPP/7zip/Archive/Z/ZHandler.h47
-rwxr-xr-xCPP/7zip/Archive/Z/makefile52
-rwxr-xr-xCPP/7zip/Archive/Z/resource.rc5
-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
-rwxr-xr-xCPP/7zip/Archive/makefile23
321 files changed, 42768 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/7z/7z.dsp b/CPP/7zip/Archive/7z/7z.dsp
new file mode 100755
index 00000000..e57115ef
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7z.dsp
@@ -0,0 +1,593 @@
+# Microsoft Developer Studio Project File - Name="7z" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=7z - 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 "7z.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 "7z.mak" CFG="7z - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "7z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "7z - 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)" == "7z - 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 "MY7Z_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "MY7Z_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\7z.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "7z - 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 "MY7Z_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 "MY7Z_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\7z.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "7z - Win32 Release"
+# Name "7z - 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"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\7zCompressionMode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zCompressionMode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zEncode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zEncode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zExtract.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zFolderInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zFolderInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zFolderOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zFolderOutStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethodID.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethods.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zMethods.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zProperties.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zProperties.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zSpecStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zSpecStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zUpdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\7zUpdate.h
+# End Source File
+# End Group
+# Begin Group "Interface"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\IArchive.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\ICoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IMyUnknown.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IPassword.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IProgress.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\IStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\PropID.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\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\DynamicBuffer.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\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 "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\CoderMixer2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\CoderMixer2.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\CoderMixer2MT.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\CoderMixer2MT.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\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\MultiStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\MultiStream.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 "7-Zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Common\InOutTempBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\InOutTempBuffer.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\LockedStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LockedStream.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\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
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.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\FileDir.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileDir.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\FileIO.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileIO.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\FileName.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\Handle.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 "Compress"
+
+# 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 Source File
+
+SOURCE=.\7z.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/7z/7z.dsw b/CPP/7zip/Archive/7z/7z.dsw
new file mode 100755
index 00000000..702a86c7
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7z.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "7z"=".\7z.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/7z/7z.ico b/CPP/7zip/Archive/7z/7z.ico
new file mode 100755
index 00000000..319753a1
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7z.ico
Binary files differ
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.cpp b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
new file mode 100755
index 00000000..6774fc48
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.cpp
@@ -0,0 +1,3 @@
+// CompressionMethod.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/7z/7zCompressionMode.h b/CPP/7zip/Archive/7z/7zCompressionMode.h
new file mode 100755
index 00000000..fe54e8a6
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zCompressionMode.h
@@ -0,0 +1,64 @@
+// 7zCompressionMode.h
+
+#ifndef __7Z_COMPRESSION_MODE_H
+#define __7Z_COMPRESSION_MODE_H
+
+#include "../../../Windows/PropVariant.h"
+
+#include "7zMethodID.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CProperty
+{
+ PROPID PropID;
+ NWindows::NCOM::CPropVariant Value;
+};
+
+struct CMethodFull
+{
+ CMethodID MethodID;
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+ bool IsSimpleCoder() const
+ { return (NumInStreams == 1) && (NumOutStreams == 1); }
+
+ #ifdef EXCLUDE_COM
+ #else
+ CLSID EncoderClassID;
+ CSysString FilePath;
+ #endif
+
+ CObjectVector<CProperty> CoderProperties;
+};
+
+struct CBind
+{
+ UInt32 InCoder;
+ UInt32 InStream;
+ UInt32 OutCoder;
+ UInt32 OutStream;
+};
+
+struct CCompressionMethodMode
+{
+ CObjectVector<CMethodFull> Methods;
+ CRecordVector<CBind> Binds;
+ #ifdef COMPRESS_MT
+ UInt32 NumThreads;
+ #endif
+ bool PasswordIsDefined;
+ UString Password;
+
+ bool IsEmpty() const { return (Methods.IsEmpty() && !PasswordIsDefined); }
+ CCompressionMethodMode(): PasswordIsDefined(false)
+ #ifdef COMPRESS_MT
+ , NumThreads(1)
+ #endif
+ {}
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zDecode.cpp b/CPP/7zip/Archive/7z/7zDecode.cpp
new file mode 100755
index 00000000..5c58f817
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -0,0 +1,444 @@
+// 7zDecode.cpp
+
+#include "StdAfx.h"
+
+#include "7zDecode.h"
+
+#include "../../IPassword.h"
+#include "../../Common/LockedStream.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../Common/FilterCoder.h"
+
+#include "7zMethods.h"
+
+#ifdef COMPRESS_LZMA
+#include "../../Compress/LZMA/LZMADecoder.h"
+static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+#endif
+
+#ifdef COMPRESS_PPMD
+#include "../../Compress/PPMD/PPMDDecoder.h"
+static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
+#endif
+
+#ifdef COMPRESS_BCJ_X86
+#include "../../Compress/Branch/x86.h"
+static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+#endif
+
+#ifdef COMPRESS_BCJ2
+#include "../../Compress/Branch/x86_2.h"
+static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
+#endif
+
+#ifdef COMPRESS_DEFLATE
+#ifndef COMPRESS_DEFLATE_DECODER
+#define COMPRESS_DEFLATE_DECODER
+#endif
+#endif
+
+#ifdef COMPRESS_DEFLATE_DECODER
+#include "../../Compress/Deflate/DeflateDecoder.h"
+static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
+#endif
+
+#ifdef COMPRESS_BZIP2
+#ifndef COMPRESS_BZIP2_DECODER
+#define COMPRESS_BZIP2_DECODER
+#endif
+#endif
+
+#ifdef COMPRESS_BZIP2_DECODER
+#include "../../Compress/BZip2/BZip2Decoder.h"
+static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
+#endif
+
+#ifdef COMPRESS_COPY
+#include "../../Compress/Copy/CopyCoder.h"
+static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
+#endif
+
+#ifdef CRYPTO_7ZAES
+#include "../../Crypto/7zAES/7zAES.h"
+static NArchive::N7z::CMethodID k_7zAES = { { 0x6, 0xF1, 0x07, 0x01 }, 4 };
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
+ CBindInfoEx &bindInfo)
+{
+ bindInfo.Clear();
+ int i;
+ for (i = 0; i < folder.BindPairs.Size(); i++)
+ {
+ NCoderMixer2::CBindPair bindPair;
+ bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
+ bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
+ bindInfo.BindPairs.Add(bindPair);
+ }
+ UInt32 outStreamIndex = 0;
+ for (i = 0; i < folder.Coders.Size(); i++)
+ {
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ const CCoderInfo &coderInfo = folder.Coders[i];
+ coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
+ coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
+ bindInfo.Coders.Add(coderStreamsInfo);
+ const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
+ bindInfo.CoderMethodIDs.Add(altCoderInfo.MethodID);
+ for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
+ if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
+ bindInfo.OutStreams.Add(outStreamIndex);
+ }
+ for (i = 0; i < folder.PackStreams.Size(); i++)
+ bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
+}
+
+static bool AreCodersEqual(const NCoderMixer2::CCoderStreamsInfo &a1,
+ const NCoderMixer2::CCoderStreamsInfo &a2)
+{
+ return (a1.NumInStreams == a2.NumInStreams) &&
+ (a1.NumOutStreams == a2.NumOutStreams);
+}
+
+static bool AreBindPairsEqual(const NCoderMixer2::CBindPair &a1, const NCoderMixer2::CBindPair &a2)
+{
+ return (a1.InIndex == a2.InIndex) &&
+ (a1.OutIndex == a2.OutIndex);
+}
+
+static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
+{
+ if (a1.Coders.Size() != a2.Coders.Size())
+ return false;
+ int i;
+ for (i = 0; i < a1.Coders.Size(); i++)
+ if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
+ return false;
+ if (a1.BindPairs.Size() != a2.BindPairs.Size())
+ return false;
+ for (i = 0; i < a1.BindPairs.Size(); i++)
+ if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+ return false;
+ for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
+ if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
+ return false;
+ if (a1.InStreams.Size() != a2.InStreams.Size())
+ return false;
+ if (a1.OutStreams.Size() != a2.OutStreams.Size())
+ return false;
+ return true;
+}
+
+CDecoder::CDecoder(bool multiThread)
+{
+ #ifndef _ST_MODE
+ multiThread = true;
+ #endif
+ _multiThread = multiThread;
+ _bindInfoExPrevIsDefined = false;
+ #ifndef EXCLUDE_COM
+ LoadMethodMap();
+ #endif
+}
+
+HRESULT CDecoder::Decode(IInStream *inStream,
+ UInt64 startPos,
+ const UInt64 *packSizes,
+ const CFolder &folderInfo,
+ ISequentialOutStream *outStream,
+ ICompressProgressInfo *compressProgress
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ #ifdef COMPRESS_MT
+ , bool mtMode, UInt32 numThreads
+ #endif
+ )
+{
+ CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+
+ CLockedInStream lockedInStream;
+ lockedInStream.Init(inStream);
+
+ for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
+ {
+ CLockedSequentialInStreamImp *lockedStreamImpSpec = new
+ CLockedSequentialInStreamImp;
+ CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(&lockedInStream, startPos);
+ startPos += packSizes[j];
+
+ CLimitedSequentialInStream *streamSpec = new
+ CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream = streamSpec;
+ streamSpec->SetStream(lockedStreamImp);
+ streamSpec->Init(packSizes[j]);
+ inStreams.Add(inStream);
+ }
+
+ int numCoders = folderInfo.Coders.Size();
+
+ CBindInfoEx bindInfo;
+ ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
+ bool createNewCoders;
+ if (!_bindInfoExPrevIsDefined)
+ createNewCoders = true;
+ else
+ createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
+ if (createNewCoders)
+ {
+ int i;
+ _decoders.Clear();
+ // _decoders2.Clear();
+
+ _mixerCoder.Release();
+
+ if (_multiThread)
+ {
+ _mixerCoderMTSpec = new NCoderMixer2::CCoderMixer2MT;
+ _mixerCoder = _mixerCoderMTSpec;
+ _mixerCoderCommon = _mixerCoderMTSpec;
+ }
+ else
+ {
+ #ifdef _ST_MODE
+ _mixerCoderSTSpec = new NCoderMixer2::CCoderMixer2ST;
+ _mixerCoder = _mixerCoderSTSpec;
+ _mixerCoderCommon = _mixerCoderSTSpec;
+ #endif
+ }
+ _mixerCoderCommon->SetBindInfo(bindInfo);
+
+ for (i = 0; i < numCoders; i++)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
+ #ifndef EXCLUDE_COM
+ CMethodInfo methodInfo;
+ if (!GetMethodInfo(altCoderInfo.MethodID, methodInfo))
+ return E_NOTIMPL;
+ #endif
+
+ if (coderInfo.IsSimpleCoder())
+ {
+ CMyComPtr<ICompressCoder> decoder;
+ CMyComPtr<ICompressFilter> filter;
+
+ #ifdef COMPRESS_LZMA
+ if (altCoderInfo.MethodID == k_LZMA)
+ decoder = new NCompress::NLZMA::CDecoder;
+ #endif
+
+ #ifdef COMPRESS_PPMD
+ if (altCoderInfo.MethodID == k_PPMD)
+ decoder = new NCompress::NPPMD::CDecoder;
+ #endif
+
+ #ifdef COMPRESS_BCJ_X86
+ if (altCoderInfo.MethodID == k_BCJ_X86)
+ filter = new CBCJ_x86_Decoder;
+ #endif
+
+ #ifdef COMPRESS_DEFLATE_DECODER
+ if (altCoderInfo.MethodID == k_Deflate)
+ decoder = new NCompress::NDeflate::NDecoder::CCOMCoder;
+ #endif
+
+ #ifdef COMPRESS_BZIP2_DECODER
+ if (altCoderInfo.MethodID == k_BZip2)
+ decoder = new NCompress::NBZip2::CDecoder;
+ #endif
+
+ #ifdef COMPRESS_COPY
+ if (altCoderInfo.MethodID == k_Copy)
+ decoder = new NCompress::CCopyCoder;
+ #endif
+
+ #ifdef CRYPTO_7ZAES
+ if (altCoderInfo.MethodID == k_7zAES)
+ filter = new NCrypto::NSevenZ::CDecoder;
+ #endif
+
+ if (filter)
+ {
+ CFilterCoder *coderSpec = new CFilterCoder;
+ decoder = coderSpec;
+ coderSpec->Filter = filter;
+ }
+ #ifndef EXCLUDE_COM
+ if (decoder == 0)
+ {
+ RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath,
+ methodInfo.Decoder, &decoder));
+ }
+ #endif
+
+ if (decoder == 0)
+ return E_NOTIMPL;
+
+ _decoders.Add((IUnknown *)decoder);
+
+ if (_multiThread)
+ _mixerCoderMTSpec->AddCoder(decoder);
+ #ifdef _ST_MODE
+ else
+ _mixerCoderSTSpec->AddCoder(decoder, false);
+ #endif
+ }
+ else
+ {
+ CMyComPtr<ICompressCoder2> decoder;
+
+ #ifdef COMPRESS_BCJ2
+ if (altCoderInfo.MethodID == k_BCJ2)
+ decoder = new CBCJ2_x86_Decoder;
+ #endif
+
+ #ifndef EXCLUDE_COM
+ if (decoder == 0)
+ {
+ RINOK(_libraries.CreateCoder2(methodInfo.FilePath,
+ methodInfo.Decoder, &decoder));
+ }
+ #endif
+
+ if (decoder == 0)
+ return E_NOTIMPL;
+
+ _decoders.Add((IUnknown *)decoder);
+ if (_multiThread)
+ _mixerCoderMTSpec->AddCoder2(decoder);
+ #ifdef _ST_MODE
+ else
+ _mixerCoderSTSpec->AddCoder2(decoder, false);
+ #endif
+ }
+ }
+ _bindInfoExPrev = bindInfo;
+ _bindInfoExPrevIsDefined = true;
+ }
+ int i;
+ _mixerCoderCommon->ReInit();
+
+ UInt32 packStreamIndex = 0, unPackStreamIndex = 0;
+ UInt32 coderIndex = 0;
+ // UInt32 coder2Index = 0;
+
+ for (i = 0; i < numCoders; i++)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
+ CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
+
+ {
+ CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+ decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ if (setDecoderProperties)
+ {
+ const CByteBuffer &properties = altCoderInfo.Properties;
+ size_t size = properties.GetCapacity();
+ if (size > 0xFFFFFFFF)
+ return E_NOTIMPL;
+ if (size > 0)
+ {
+ RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, (UInt32)size));
+ }
+ }
+ }
+
+ #ifdef COMPRESS_MT
+ if (mtMode)
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(numThreads));
+ }
+ }
+ #endif
+
+ #ifndef _NO_CRYPTO
+ {
+ CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+ decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+ if (cryptoSetPassword)
+ {
+ if (getTextPassword == 0)
+ return E_FAIL;
+ CMyComBSTR password;
+ RINOK(getTextPassword->CryptoGetTextPassword(&password));
+ CByteBuffer buffer;
+ UString unicodePassword(password);
+ const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+ buffer.SetCapacity(sizeInBytes);
+ for (int i = 0; i < unicodePassword.Length(); i++)
+ {
+ wchar_t c = unicodePassword[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword(
+ (const Byte *)buffer, sizeInBytes));
+ }
+ }
+ #endif
+
+ coderIndex++;
+
+ UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
+ UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
+ CRecordVector<const UInt64 *> packSizesPointers;
+ CRecordVector<const UInt64 *> unPackSizesPointers;
+ packSizesPointers.Reserve(numInStreams);
+ unPackSizesPointers.Reserve(numOutStreams);
+ UInt32 j;
+ for (j = 0; j < numOutStreams; j++, unPackStreamIndex++)
+ unPackSizesPointers.Add(&folderInfo.UnPackSizes[unPackStreamIndex]);
+
+ for (j = 0; j < numInStreams; j++, packStreamIndex++)
+ {
+ int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
+ if (bindPairIndex >= 0)
+ packSizesPointers.Add(
+ &folderInfo.UnPackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
+ else
+ {
+ int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+ if (index < 0)
+ return E_FAIL;
+ packSizesPointers.Add(&packSizes[index]);
+ }
+ }
+
+ _mixerCoderCommon->SetCoderInfo(i,
+ &packSizesPointers.Front(),
+ &unPackSizesPointers.Front());
+ }
+ UInt32 mainCoder, temp;
+ bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
+
+ if (_multiThread)
+ _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
+ /*
+ else
+ _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
+ */
+
+ if (numCoders == 0)
+ return 0;
+ CRecordVector<ISequentialInStream *> inStreamPointers;
+ inStreamPointers.Reserve(inStreams.Size());
+ for (i = 0; i < inStreams.Size(); i++)
+ inStreamPointers.Add(inStreams[i]);
+ ISequentialOutStream *outStreamPointer = outStream;
+ return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
+ inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zDecode.h b/CPP/7zip/Archive/7z/7zDecode.h
new file mode 100755
index 00000000..50f80d4c
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zDecode.h
@@ -0,0 +1,71 @@
+// 7zDecode.h
+
+#ifndef __7Z_DECODE_H
+#define __7Z_DECODE_H
+
+#include "../../IStream.h"
+#include "../../IPassword.h"
+
+#include "../Common/CoderMixer2.h"
+#include "../Common/CoderMixer2MT.h"
+#ifdef _ST_MODE
+#include "../Common/CoderMixer2ST.h"
+#endif
+#ifndef EXCLUDE_COM
+#include "../Common/CoderLoader.h"
+#endif
+
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CBindInfoEx: public NCoderMixer2::CBindInfo
+{
+ CRecordVector<CMethodID> CoderMethodIDs;
+ void Clear()
+ {
+ CBindInfo::Clear();
+ CoderMethodIDs.Clear();
+ }
+};
+
+class CDecoder
+{
+ #ifndef EXCLUDE_COM
+ CCoderLibraries _libraries;
+ #endif
+
+ bool _bindInfoExPrevIsDefined;
+ CBindInfoEx _bindInfoExPrev;
+
+ bool _multiThread;
+ #ifdef _ST_MODE
+ NCoderMixer2::CCoderMixer2ST *_mixerCoderSTSpec;
+ #endif
+ NCoderMixer2::CCoderMixer2MT *_mixerCoderMTSpec;
+ NCoderMixer2::CCoderMixer2 *_mixerCoderCommon;
+
+ CMyComPtr<ICompressCoder2> _mixerCoder;
+ CObjectVector<CMyComPtr<IUnknown> > _decoders;
+ // CObjectVector<CMyComPtr<ICompressCoder2> > _decoders2;
+public:
+ CDecoder(bool multiThread);
+ HRESULT Decode(IInStream *inStream,
+ UInt64 startPos,
+ const UInt64 *packSizes,
+ const CFolder &folder,
+ ISequentialOutStream *outStream,
+ ICompressProgressInfo *compressProgress
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPasswordSpec
+ #endif
+ #ifdef COMPRESS_MT
+ , bool mtMode, UInt32 numThreads
+ #endif
+ );
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
new file mode 100755
index 00000000..a9fe2d0a
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zEncode.cpp
@@ -0,0 +1,614 @@
+// Encode.cpp
+
+#include "StdAfx.h"
+
+#include "7zEncode.h"
+#include "7zSpecStream.h"
+#include "7zMethods.h"
+
+#include "../../IPassword.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/InOutTempBuffer.h"
+#include "../../Common/StreamObjects.h"
+#include "../Common/FilterCoder.h"
+
+#ifdef COMPRESS_COPY
+static NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };
+#include "../../Compress/Copy/CopyCoder.h"
+#endif
+
+static NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+static NArchive::N7z::CMethodID k_LZMA2 = { { 0x3, 0x1, 0x2 }, 3 };
+
+#ifdef COMPRESS_LZMA
+#include "../../Compress/LZMA/LZMAEncoder.h"
+#endif
+
+#ifdef COMPRESS_PPMD
+#include "../../Compress/PPMD/PPMDEncoder.h"
+static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
+#endif
+
+#ifdef COMPRESS_BCJ_X86
+static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+#include "../../Compress/Branch/x86.h"
+#endif
+
+#ifdef COMPRESS_BCJ2
+static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
+#include "../../Compress/Branch/x86_2.h"
+#endif
+
+#ifdef COMPRESS_DEFLATE
+#ifndef COMPRESS_DEFLATE_ENCODER
+#define COMPRESS_DEFLATE_ENCODER
+#endif
+#endif
+
+#ifdef COMPRESS_DEFLATE_ENCODER
+#include "../../Compress/Deflate/DeflateEncoder.h"
+static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
+#endif
+
+#ifdef COMPRESS_BZIP2
+#ifndef COMPRESS_BZIP2_ENCODER
+#define COMPRESS_BZIP2_ENCODER
+#endif
+#endif
+
+#ifdef COMPRESS_BZIP2_ENCODER
+#include "../../Compress/BZip2/BZip2Encoder.h"
+static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
+#endif
+
+static NArchive::N7z::CMethodID k_AES = { { 0x6, 0xF1, 0x7, 0x1}, 4 };
+
+#ifndef EXCLUDE_COM
+static const wchar_t *kCryproMethod = L"7zAES";
+/*
+// {23170F69-40C1-278B-06F1-070100000100}
+DEFINE_GUID(CLSID_CCrypto7zAESEncoder,
+0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00);
+*/
+#endif
+
+#ifdef CRYPTO_7ZAES
+#include "../../Crypto/7zAES/7zAES.h"
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+static void ConvertBindInfoToFolderItemInfo(const NCoderMixer2::CBindInfo &bindInfo,
+ const CRecordVector<CMethodID> decompressionMethods,
+ CFolder &folder)
+{
+ folder.Coders.Clear();
+ // bindInfo.CoderMethodIDs.Clear();
+ // folder.OutStreams.Clear();
+ folder.PackStreams.Clear();
+ folder.BindPairs.Clear();
+ int i;
+ for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+ {
+ CBindPair bindPair;
+ bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
+ bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
+ folder.BindPairs.Add(bindPair);
+ }
+ for (i = 0; i < bindInfo.Coders.Size(); i++)
+ {
+ CCoderInfo coderInfo;
+ const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
+ coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
+ coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
+
+ // coderInfo.MethodID = decompressionMethods[i];
+ // if (coderInfo.AltCoders.Size() == 0)
+ coderInfo.AltCoders.Add(CAltCoderInfo());
+ CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();
+ altCoderInfo.MethodID = decompressionMethods[i];
+
+ folder.Coders.Add(coderInfo);
+ }
+ for (i = 0; i < bindInfo.InStreams.Size(); i++)
+ folder.PackStreams.Add(bindInfo.InStreams[i]);
+}
+
+HRESULT CEncoder::CreateMixerCoder(const UInt64 *inSizeForReduce)
+{
+ _mixerCoderSpec = new NCoderMixer2::CCoderMixer2MT;
+ _mixerCoder = _mixerCoderSpec;
+ _mixerCoderSpec->SetBindInfo(_bindInfo);
+ for (int i = 0; i < _options.Methods.Size(); i++)
+ {
+ const CMethodFull &methodFull = _options.Methods[i];
+ _codersInfo.Add(CCoderInfo());
+ CCoderInfo &encodingInfo = _codersInfo.Back();
+ CMyComPtr<ICompressCoder> encoder;
+ CMyComPtr<ICompressFilter> filter;
+ CMyComPtr<ICompressCoder2> encoder2;
+
+ if (methodFull.IsSimpleCoder())
+ {
+ #ifdef COMPRESS_LZMA
+ if (methodFull.MethodID == k_LZMA)
+ encoder = new NCompress::NLZMA::CEncoder;
+ #endif
+
+ #ifdef COMPRESS_PPMD
+ if (methodFull.MethodID == k_PPMD)
+ encoder = new NCompress::NPPMD::CEncoder;
+ #endif
+
+ #ifdef COMPRESS_BCJ_X86
+ if (methodFull.MethodID == k_BCJ_X86)
+ filter = new CBCJ_x86_Encoder;
+ #endif
+
+ #ifdef COMPRESS_COPY
+ if (methodFull.MethodID == k_Copy)
+ encoder = new NCompress::CCopyCoder;
+ #endif
+
+ #ifdef COMPRESS_BZIP2_ENCODER
+ if (methodFull.MethodID == k_BZip2)
+ encoder = new NCompress::NBZip2::CEncoder;
+ #endif
+
+ #ifdef COMPRESS_DEFLATE_ENCODER
+ if (methodFull.MethodID == k_Deflate)
+ encoder = new NCompress::NDeflate::NEncoder::CCOMCoder;
+ #endif
+
+ #ifdef CRYPTO_7ZAES
+ if (methodFull.MethodID == k_AES)
+ filter = new NCrypto::NSevenZ::CEncoder;
+ #endif
+
+ if (filter)
+ {
+ CFilterCoder *coderSpec = new CFilterCoder;
+ encoder = coderSpec;
+ coderSpec->Filter = filter;
+ }
+
+ #ifndef EXCLUDE_COM
+ if (encoder == 0)
+ {
+ RINOK(_libraries.CreateCoderSpec(methodFull.FilePath,
+ methodFull.EncoderClassID, &encoder));
+ }
+ #endif
+
+ if (encoder == 0)
+ return E_FAIL;
+
+ }
+ else
+ {
+ #ifdef COMPRESS_BCJ2
+ if (methodFull.MethodID == k_BCJ2)
+ encoder2 = new CBCJ2_x86_Encoder;
+ #endif
+
+ #ifndef EXCLUDE_COM
+ if (encoder2 == 0)
+ {
+ RINOK(_libraries.CreateCoder2(methodFull.FilePath,
+ methodFull.EncoderClassID, &encoder2));
+ }
+ #else
+
+ if (encoder2 == 0)
+ return E_FAIL;
+ #endif
+ }
+
+ bool tryReduce = false;
+ UInt32 reducedDictionarySize = 1 << 10;
+ if (inSizeForReduce != 0 && (methodFull.MethodID == k_LZMA || methodFull.MethodID == k_LZMA2))
+ {
+ for (;;)
+ {
+ const UInt32 step = (reducedDictionarySize >> 1);
+ if (reducedDictionarySize >= *inSizeForReduce)
+ {
+ tryReduce = true;
+ break;
+ }
+ reducedDictionarySize += step;
+ if (reducedDictionarySize >= *inSizeForReduce)
+ {
+ tryReduce = true;
+ break;
+ }
+ if (reducedDictionarySize >= ((UInt32)11 << 30))
+ break;
+ reducedDictionarySize += step;
+ }
+ }
+
+ CMyComPtr<IUnknown> encoderCommon = methodFull.IsSimpleCoder() ? (IUnknown *)encoder : (IUnknown *)encoder2;
+
+ #ifdef COMPRESS_MT
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
+ }
+ }
+ #endif
+
+ if (methodFull.CoderProperties.Size() > 0)
+ {
+ CRecordVector<PROPID> propIDs;
+ int numProperties = methodFull.CoderProperties.Size();
+ NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties];
+ try
+ {
+ for (int i = 0; i < numProperties; i++)
+ {
+ const CProperty &property = methodFull.CoderProperties[i];
+ propIDs.Add(property.PropID);
+ NWindows::NCOM::CPropVariant value = property.Value;
+ if (tryReduce && property.PropID == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)
+ value.ulVal = reducedDictionarySize;
+ values[i] = value;
+ }
+ CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+ RINOK(encoderCommon.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));
+ RINOK(setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties));
+ }
+ catch(...)
+ {
+ delete []values;
+ throw;
+ }
+ delete []values;
+ }
+
+ CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
+
+ encoderCommon.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);
+
+ if (writeCoderProperties != NULL)
+ {
+ CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->Init();
+ writeCoderProperties->WriteCoderProperties(outStream);
+
+ size_t size = outStreamSpec->GetSize();
+
+ // encodingInfo.Properties.SetCapacity(size);
+ if (encodingInfo.AltCoders.Size() == 0)
+ encodingInfo.AltCoders.Add(CAltCoderInfo());
+ CAltCoderInfo &altCoderInfo = encodingInfo.AltCoders.Front();
+ altCoderInfo.Properties.SetCapacity(size);
+
+ memmove(altCoderInfo.Properties, outStreamSpec->GetBuffer(), size);
+ }
+
+ CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+ encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+
+ if (cryptoSetPassword)
+ {
+ CByteBuffer buffer;
+ const UInt32 sizeInBytes = _options.Password.Length() * 2;
+ buffer.SetCapacity(sizeInBytes);
+ for (int i = 0; i < _options.Password.Length(); i++)
+ {
+ wchar_t c = _options.Password[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+ }
+
+ if (methodFull.IsSimpleCoder())
+ _mixerCoderSpec->AddCoder(encoder);
+ else
+ _mixerCoderSpec->AddCoder2(encoder2);
+ }
+ return S_OK;
+}
+
+HRESULT CEncoder::Encode(ISequentialInStream *inStream,
+ const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ CFolder &folderItem,
+ ISequentialOutStream *outStream,
+ CRecordVector<UInt64> &packSizes,
+ ICompressProgressInfo *compressProgress)
+{
+ if (_mixerCoderSpec == NULL)
+ {
+ RINOK(CreateMixerCoder(inSizeForReduce));
+ }
+ _mixerCoderSpec->ReInit();
+ // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
+
+ CObjectVector<CInOutTempBuffer> inOutTempBuffers;
+ CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
+ CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
+ int numMethods = _bindInfo.Coders.Size();
+ int i;
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ inOutTempBuffers.Add(CInOutTempBuffer());
+ inOutTempBuffers.Back().Create();
+ inOutTempBuffers.Back().InitWriting();
+ }
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ CSequentialOutTempBufferImp *tempBufferSpec =
+ new CSequentialOutTempBufferImp;
+ CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
+ tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
+ tempBuffers.Add(tempBuffer);
+ tempBufferSpecs.Add(tempBufferSpec);
+ }
+
+ for (i = 0; i < numMethods; i++)
+ _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
+
+ if (_bindInfo.InStreams.IsEmpty())
+ return E_FAIL;
+ UInt32 mainCoderIndex, mainStreamIndex;
+ _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
+ _mixerCoderSpec->SetProgressCoderIndex(mainCoderIndex);
+ if (inStreamSize != NULL)
+ {
+ CRecordVector<const UInt64 *> sizePointers;
+ for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
+ if (i == mainStreamIndex)
+ sizePointers.Add(inStreamSize);
+ else
+ sizePointers.Add(NULL);
+ _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
+ }
+
+
+ // UInt64 outStreamStartPos;
+ // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
+
+ CSequentialInStreamSizeCount2 *inStreamSizeCountSpec =
+ new CSequentialInStreamSizeCount2;
+ CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+ CSequentialOutStreamSizeCount *outStreamSizeCountSpec =
+ new CSequentialOutStreamSizeCount;
+ CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
+
+ inStreamSizeCountSpec->Init(inStream);
+ outStreamSizeCountSpec->SetStream(outStream);
+ outStreamSizeCountSpec->Init();
+
+ CRecordVector<ISequentialInStream *> inStreamPointers;
+ CRecordVector<ISequentialOutStream *> outStreamPointers;
+ inStreamPointers.Add(inStreamSizeCount);
+ outStreamPointers.Add(outStreamSizeCount);
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ outStreamPointers.Add(tempBuffers[i - 1]);
+
+ RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
+ &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
+
+ ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods,
+ folderItem);
+
+ packSizes.Add(outStreamSizeCountSpec->GetSize());
+
+ for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
+ inOutTempBuffer.FlushWrite();
+ inOutTempBuffer.InitReading();
+ inOutTempBuffer.WriteToStream(outStream);
+ packSizes.Add(inOutTempBuffer.GetDataSize());
+ }
+
+ for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
+ {
+ int binder = _bindInfo.FindBinderForInStream(
+ _bindReverseConverter->DestOutToSrcInMap[i]);
+ UInt64 streamSize;
+ if (binder < 0)
+ streamSize = inStreamSizeCountSpec->GetSize();
+ else
+ streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
+ folderItem.UnPackSizes.Add(streamSize);
+ }
+ for (i = numMethods - 1; i >= 0; i--)
+ {
+ // folderItem.Coders[numMethods - 1 - i].Properties = _codersInfo[i].Properties;
+ for (int j = 0; j < _codersInfo[i].AltCoders.Size(); j++)
+ folderItem.Coders[numMethods - 1 - i].AltCoders[j].Properties
+ = _codersInfo[i].AltCoders[j].Properties;
+ }
+ return S_OK;
+}
+
+
+CEncoder::CEncoder(const CCompressionMethodMode &options):
+ _bindReverseConverter(0)
+{
+ if (options.IsEmpty())
+ throw 1;
+
+ _options = options;
+ _mixerCoderSpec = NULL;
+
+ if (options.Methods.IsEmpty())
+ {
+ // it has only password method;
+ if (!options.PasswordIsDefined)
+ throw 1;
+ if (!options.Binds.IsEmpty())
+ throw 1;
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ CMethodFull method;
+
+ method.NumInStreams = 1;
+ method.NumOutStreams = 1;
+ coderStreamsInfo.NumInStreams = method.NumOutStreams;
+ coderStreamsInfo.NumOutStreams = method.NumInStreams;
+ method.MethodID = k_AES;
+
+
+ #ifndef EXCLUDE_COM
+ CMethodInfo2 methodInfo;
+ if (!GetMethodInfo(kCryproMethod, methodInfo))
+ throw 2;
+ method.FilePath = methodInfo.FilePath;
+ method.EncoderClassID = methodInfo.Encoder;
+ // method.EncoderClassID = CLSID_CCrypto7zAESEncoder;
+ #endif
+
+ _options.Methods.Add(method);
+ _bindInfo.Coders.Add(coderStreamsInfo);
+
+ _bindInfo.InStreams.Add(0);
+ _bindInfo.OutStreams.Add(0);
+ }
+ else
+ {
+
+ UInt32 numInStreams = 0, numOutStreams = 0;
+ int i;
+ for (i = 0; i < options.Methods.Size(); i++)
+ {
+ const CMethodFull &methodFull = options.Methods[i];
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
+ coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
+ if (options.Binds.IsEmpty())
+ {
+ if (i < options.Methods.Size() - 1)
+ {
+ NCoderMixer2::CBindPair bindPair;
+ bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
+ bindPair.OutIndex = numOutStreams;
+ _bindInfo.BindPairs.Add(bindPair);
+ }
+ else
+ _bindInfo.OutStreams.Insert(0, numOutStreams);
+ for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
+ _bindInfo.OutStreams.Add(numOutStreams + j);
+ }
+
+ numInStreams += coderStreamsInfo.NumInStreams;
+ numOutStreams += coderStreamsInfo.NumOutStreams;
+
+ _bindInfo.Coders.Add(coderStreamsInfo);
+ }
+
+ if (!options.Binds.IsEmpty())
+ {
+ for (i = 0; i < options.Binds.Size(); i++)
+ {
+ NCoderMixer2::CBindPair bindPair;
+ const CBind &bind = options.Binds[i];
+ bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
+ bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
+ _bindInfo.BindPairs.Add(bindPair);
+ }
+ for (i = 0; i < (int)numOutStreams; i++)
+ if (_bindInfo.FindBinderForOutStream(i) == -1)
+ _bindInfo.OutStreams.Add(i);
+ }
+
+ for (i = 0; i < (int)numInStreams; i++)
+ if (_bindInfo.FindBinderForInStream(i) == -1)
+ _bindInfo.InStreams.Add(i);
+
+ if (_bindInfo.InStreams.IsEmpty())
+ throw 1; // this is error
+
+ // Make main stream first in list
+ int inIndex = _bindInfo.InStreams[0];
+ for (;;)
+ {
+ UInt32 coderIndex, coderStreamIndex;
+ _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
+ UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
+ int binder = _bindInfo.FindBinderForOutStream(outIndex);
+ if (binder >= 0)
+ {
+ inIndex = _bindInfo.BindPairs[binder].InIndex;
+ continue;
+ }
+ for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
+ if (_bindInfo.OutStreams[i] == outIndex)
+ {
+ _bindInfo.OutStreams.Delete(i);
+ _bindInfo.OutStreams.Insert(0, outIndex);
+ break;
+ }
+ break;
+ }
+
+ if (_options.PasswordIsDefined)
+ {
+ int numCryptoStreams = _bindInfo.OutStreams.Size();
+
+ for (i = 0; i < numCryptoStreams; i++)
+ {
+ NCoderMixer2::CBindPair bindPair;
+ bindPair.InIndex = numInStreams + i;
+ bindPair.OutIndex = _bindInfo.OutStreams[i];
+ _bindInfo.BindPairs.Add(bindPair);
+ }
+ _bindInfo.OutStreams.Clear();
+
+ /*
+ if (numCryptoStreams == 0)
+ numCryptoStreams = 1;
+ */
+
+ for (i = 0; i < numCryptoStreams; i++)
+ {
+ NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
+ CMethodFull method;
+ method.NumInStreams = 1;
+ method.NumOutStreams = 1;
+ coderStreamsInfo.NumInStreams = method.NumOutStreams;
+ coderStreamsInfo.NumOutStreams = method.NumInStreams;
+ method.MethodID = k_AES;
+
+ #ifndef EXCLUDE_COM
+ CMethodInfo2 methodInfo;
+ if (!GetMethodInfo(kCryproMethod, methodInfo))
+ throw 2;
+ method.FilePath = methodInfo.FilePath;
+ method.EncoderClassID = methodInfo.Encoder;
+ // method.EncoderClassID = CLSID_CCrypto7zAESEncoder;
+ #endif
+
+ _options.Methods.Add(method);
+ _bindInfo.Coders.Add(coderStreamsInfo);
+ _bindInfo.OutStreams.Add(numOutStreams + i);
+ }
+ }
+
+ }
+
+ for (int i = _options.Methods.Size() - 1; i >= 0; i--)
+ {
+ const CMethodFull &methodFull = _options.Methods[i];
+ _decompressionMethods.Add(methodFull.MethodID);
+ }
+
+ _bindReverseConverter = new NCoderMixer2::CBindReverseConverter(_bindInfo);
+ _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
+}
+
+CEncoder::~CEncoder()
+{
+ delete _bindReverseConverter;
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zEncode.h b/CPP/7zip/Archive/7z/7zEncode.h
new file mode 100755
index 00000000..efd8bba6
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zEncode.h
@@ -0,0 +1,58 @@
+// 7zEncode.h
+
+#ifndef __7Z_ENCODE_H
+#define __7Z_ENCODE_H
+
+// #include "../../Common/StreamObjects.h"
+
+#include "7zCompressionMode.h"
+
+#include "../Common/CoderMixer2.h"
+#include "../Common/CoderMixer2MT.h"
+#ifdef _ST_MODE
+#include "../Common/CoderMixer2ST.h"
+#endif
+#ifndef EXCLUDE_COM
+#include "../Common/CoderLoader.h"
+#endif
+#include "7zMethods.h"
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CEncoder
+{
+ #ifndef EXCLUDE_COM
+ // CMethodMap _methodMap;
+ // it must be in top of objects
+ CCoderLibraries _libraries;
+ #endif
+
+ NCoderMixer2::CCoderMixer2MT *_mixerCoderSpec;
+ CMyComPtr<ICompressCoder2> _mixerCoder;
+
+ CObjectVector<CCoderInfo> _codersInfo;
+
+ CCompressionMethodMode _options;
+ NCoderMixer2::CBindInfo _bindInfo;
+ NCoderMixer2::CBindInfo _decompressBindInfo;
+ NCoderMixer2::CBindReverseConverter *_bindReverseConverter;
+ CRecordVector<CMethodID> _decompressionMethods;
+
+ HRESULT CreateMixerCoder(const UInt64 *inSizeForReduce);
+
+public:
+ CEncoder(const CCompressionMethodMode &options);
+ ~CEncoder();
+ HRESULT Encode(ISequentialInStream *inStream,
+ const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
+ CFolder &folderItem,
+ ISequentialOutStream *outStream,
+ CRecordVector<UInt64> &packSizes,
+ ICompressProgressInfo *compressProgress);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zExtract.cpp b/CPP/7zip/Archive/7z/7zExtract.cpp
new file mode 100755
index 00000000..540241f7
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zExtract.cpp
@@ -0,0 +1,265 @@
+// 7zExtract.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zFolderOutStream.h"
+#include "7zMethods.h"
+#include "7zDecode.h"
+// #include "7z1Decode.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CExtractFolderInfo
+{
+ #ifdef _7Z_VOL
+ int VolumeIndex;
+ #endif
+ CNum FileIndex;
+ CNum FolderIndex;
+ CBoolVector ExtractStatuses;
+ UInt64 UnPackSize;
+ CExtractFolderInfo(
+ #ifdef _7Z_VOL
+ int volumeIndex,
+ #endif
+ CNum fileIndex, CNum folderIndex):
+ #ifdef _7Z_VOL
+ VolumeIndex(volumeIndex),
+ #endif
+ FileIndex(fileIndex),
+ FolderIndex(folderIndex),
+ UnPackSize(0)
+ {
+ if (fileIndex != kNumNoIndex)
+ {
+ ExtractStatuses.Reserve(1);
+ ExtractStatuses.Add(true);
+ }
+ };
+};
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec)
+{
+ COM_TRY_BEGIN
+ bool testMode = (testModeSpec != 0);
+ CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec;
+ UInt64 importantTotalUnPacked = 0;
+
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems =
+ #ifdef _7Z_VOL
+ _refs.Size();
+ #else
+ _database.Files.Size();
+ #endif
+
+ if(numItems == 0)
+ return S_OK;
+
+ /*
+ if(_volumes.Size() != 1)
+ return E_FAIL;
+ const CVolume &volume = _volumes.Front();
+ const CArchiveDatabaseEx &_database = volume.Database;
+ IInStream *_inStream = volume.Stream;
+ */
+
+ CObjectVector<CExtractFolderInfo> extractFolderInfoVector;
+ for(UInt32 ii = 0; ii < numItems; ii++)
+ {
+ // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex];
+ UInt32 ref2Index = allFilesMode ? ii : indices[ii];
+ // const CRef2 &ref2 = _refs[ref2Index];
+
+ // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++)
+ {
+ #ifdef _7Z_VOL
+ // const CRef &ref = ref2.Refs[ri];
+ const CRef &ref = _refs[ref2Index];
+
+ int volumeIndex = ref.VolumeIndex;
+ const CVolume &volume = _volumes[volumeIndex];
+ const CArchiveDatabaseEx &database = volume.Database;
+ UInt32 fileIndex = ref.ItemIndex;
+ #else
+ const CArchiveDatabaseEx &database = _database;
+ UInt32 fileIndex = ref2Index;
+ #endif
+
+ CNum folderIndex = database.FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex == kNumNoIndex)
+ {
+ extractFolderInfoVector.Add(CExtractFolderInfo(
+ #ifdef _7Z_VOL
+ volumeIndex,
+ #endif
+ fileIndex, kNumNoIndex));
+ continue;
+ }
+ if (extractFolderInfoVector.IsEmpty() ||
+ folderIndex != extractFolderInfoVector.Back().FolderIndex
+ #ifdef _7Z_VOL
+ || volumeIndex != extractFolderInfoVector.Back().VolumeIndex
+ #endif
+ )
+ {
+ extractFolderInfoVector.Add(CExtractFolderInfo(
+ #ifdef _7Z_VOL
+ volumeIndex,
+ #endif
+ kNumNoIndex, folderIndex));
+ const CFolder &folderInfo = database.Folders[folderIndex];
+ UInt64 unPackSize = folderInfo.GetUnPackSize();
+ importantTotalUnPacked += unPackSize;
+ extractFolderInfoVector.Back().UnPackSize = unPackSize;
+ }
+
+ CExtractFolderInfo &efi = extractFolderInfoVector.Back();
+
+ // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex];
+ CNum startIndex = database.FolderStartFileIndex[folderIndex];
+ for (CNum index = efi.ExtractStatuses.Size();
+ index <= fileIndex - startIndex; index++)
+ {
+ // UInt64 unPackSize = _database.Files[startIndex + index].UnPackSize;
+ // Count partial_folder_size
+ // efi.UnPackSize += unPackSize;
+ // importantTotalUnPacked += unPackSize;
+ efi.ExtractStatuses.Add(index == fileIndex - startIndex);
+ }
+ }
+ }
+
+ extractCallback->SetTotal(importantTotalUnPacked);
+
+ CDecoder decoder(
+ #ifdef _ST_MODE
+ false
+ #else
+ true
+ #endif
+ );
+ // CDecoder1 decoder;
+
+ UInt64 currentImportantTotalUnPacked = 0;
+ UInt64 totalFolderUnPacked;
+
+ for(int i = 0; i < extractFolderInfoVector.Size(); i++,
+ currentImportantTotalUnPacked += totalFolderUnPacked)
+ {
+ const CExtractFolderInfo &efi = extractFolderInfoVector[i];
+ totalFolderUnPacked = efi.UnPackSize;
+
+ RINOK(extractCallback->SetCompleted(&currentImportantTotalUnPacked));
+
+ CFolderOutStream *folderOutStream = new CFolderOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(folderOutStream);
+
+ #ifdef _7Z_VOL
+ const CVolume &volume = _volumes[efi.VolumeIndex];
+ const CArchiveDatabaseEx &database = volume.Database;
+ #else
+ const CArchiveDatabaseEx &database = _database;
+ #endif
+
+ CNum startIndex;
+ if (efi.FileIndex != kNumNoIndex)
+ startIndex = efi.FileIndex;
+ else
+ startIndex = database.FolderStartFileIndex[efi.FolderIndex];
+
+
+ HRESULT result = folderOutStream->Init(&database,
+ #ifdef _7Z_VOL
+ volume.StartRef2Index,
+ #else
+ 0,
+ #endif
+ startIndex,
+ &efi.ExtractStatuses, extractCallback, testMode);
+
+ RINOK(result);
+
+ if (efi.FileIndex != kNumNoIndex)
+ continue;
+
+ CNum folderIndex = efi.FolderIndex;
+ const CFolder &folderInfo = database.Folders[folderIndex];
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress, NULL, &currentImportantTotalUnPacked);
+
+ CNum packStreamIndex = database.FolderStartPackStreamIndex[folderIndex];
+ UInt64 folderStartPackPos = database.GetFolderStreamPos(folderIndex, 0);
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ if (extractCallback)
+ extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ #endif
+
+ try
+ {
+ HRESULT result = decoder.Decode(
+ #ifdef _7Z_VOL
+ volume.Stream,
+ #else
+ _inStream,
+ #endif
+ folderStartPackPos,
+ &database.PackSizes[packStreamIndex],
+ folderInfo,
+ outStream,
+ compressProgress
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ #ifdef COMPRESS_MT
+ , true, _numThreads
+ #endif
+ );
+
+ if (result == S_FALSE)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ if (result == E_NOTIMPL)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ if (result != S_OK)
+ return result;
+ if (folderOutStream->WasWritingFinished() != S_OK)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ }
+ catch(...)
+ {
+ RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.cpp b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
new file mode 100755
index 00000000..fb1cfd3a
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.cpp
@@ -0,0 +1,129 @@
+// 7zFolderInStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderInStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+CFolderInStream::CFolderInStream()
+{
+ _inStreamWithHashSpec = new CSequentialInStreamWithCRC;
+ _inStreamWithHash = _inStreamWithHashSpec;
+}
+
+void CFolderInStream::Init(IArchiveUpdateCallback *updateCallback,
+ const UInt32 *fileIndices, UInt32 numFiles)
+{
+ _updateCallback = updateCallback;
+ _numFiles = numFiles;
+ _fileIndex = 0;
+ _fileIndices = fileIndices;
+ Processed.Clear();
+ CRCs.Clear();
+ Sizes.Clear();
+ _fileIsOpen = false;
+ _currentSizeIsDefined = false;
+}
+
+HRESULT CFolderInStream::OpenStream()
+{
+ _filePos = 0;
+ while (_fileIndex < _numFiles)
+ {
+ _currentSizeIsDefined = false;
+ CMyComPtr<ISequentialInStream> stream;
+ HRESULT result = _updateCallback->GetStream(_fileIndices[_fileIndex], &stream);
+ if (result != S_OK && result != S_FALSE)
+ return result;
+ _fileIndex++;
+ _inStreamWithHashSpec->SetStream(stream);
+ _inStreamWithHashSpec->Init();
+ if (!stream)
+ {
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ Sizes.Add(0);
+ Processed.Add(result == S_OK);
+ AddDigest();
+ continue;
+ }
+ CMyComPtr<IStreamGetSize> streamGetSize;
+ if (stream.QueryInterface(IID_IStreamGetSize, &streamGetSize) == S_OK)
+ {
+ if(streamGetSize)
+ {
+ _currentSizeIsDefined = true;
+ RINOK(streamGetSize->GetSize(&_currentSize));
+ }
+ }
+
+ _fileIsOpen = true;
+ return S_OK;
+ }
+ return S_OK;
+}
+
+void CFolderInStream::AddDigest()
+{
+ CRCs.Add(_inStreamWithHashSpec->GetCRC());
+}
+
+HRESULT CFolderInStream::CloseStream()
+{
+ RINOK(_updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK));
+ _inStreamWithHashSpec->ReleaseStream();
+ _fileIsOpen = false;
+ Processed.Add(true);
+ Sizes.Add(_filePos);
+ AddDigest();
+ return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ while ((_fileIndex < _numFiles || _fileIsOpen) && size > 0)
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 localProcessedSize;
+ RINOK(_inStreamWithHash->Read(
+ ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
+ if (localProcessedSize == 0)
+ {
+ RINOK(CloseStream());
+ continue;
+ }
+ realProcessedSize += localProcessedSize;
+ _filePos += localProcessedSize;
+ size -= localProcessedSize;
+ break;
+ }
+ else
+ {
+ RINOK(OpenStream());
+ }
+ }
+ if (processedSize != 0)
+ *processedSize = realProcessedSize;
+ return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::GetSubStreamSize(UInt64 subStream, UInt64 *value)
+{
+ *value = 0;
+ if (subStream < Sizes.Size())
+ {
+ *value= Sizes[(int)(size_t)subStream];
+ return S_OK;
+ }
+ if (subStream > Sizes.Size())
+ return E_FAIL;
+ if (!_currentSizeIsDefined)
+ return S_FALSE;
+ *value = _currentSize;
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zFolderInStream.h b/CPP/7zip/Archive/7z/7zFolderInStream.h
new file mode 100755
index 00000000..9a720c8b
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderInStream.h
@@ -0,0 +1,66 @@
+// 7z/FolderInStream.h
+
+#ifndef __7Z_FOLDERINSTREAM_H
+#define __7Z_FOLDERINSTREAM_H
+
+#include "7zItem.h"
+#include "7zHeader.h"
+
+#include "../IArchive.h"
+#include "../Common/InStreamWithCRC.h"
+#include "../../IStream.h"
+#include "../../ICoder.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderInStream:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
+ public CMyUnknownImp
+{
+public:
+
+ MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+
+ CFolderInStream();
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+private:
+ CSequentialInStreamWithCRC *_inStreamWithHashSpec;
+ CMyComPtr<ISequentialInStream> _inStreamWithHash;
+ CMyComPtr<IArchiveUpdateCallback> _updateCallback;
+
+ bool _currentSizeIsDefined;
+ UInt64 _currentSize;
+
+ bool _fileIsOpen;
+ UInt64 _filePos;
+
+ const UInt32 *_fileIndices;
+ UInt32 _numFiles;
+ UInt32 _fileIndex;
+
+ HRESULT OpenStream();
+ HRESULT CloseStream();
+ void AddDigest();
+public:
+ void Init(IArchiveUpdateCallback *updateCallback,
+ const UInt32 *fileIndices, UInt32 numFiles);
+ CRecordVector<bool> Processed;
+ CRecordVector<UInt32> CRCs;
+ CRecordVector<UInt64> Sizes;
+ UInt64 GetFullSize() const
+ {
+ UInt64 size = 0;
+ for (int i = 0; i < Sizes.Size(); i++)
+ size += Sizes[i];
+ return size;
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.cpp b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
new file mode 100755
index 00000000..93bed3d9
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.cpp
@@ -0,0 +1,162 @@
+// 7zFolderOutStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zFolderOutStream.h"
+
+namespace NArchive {
+namespace N7z {
+
+CFolderOutStream::CFolderOutStream()
+{
+ _outStreamWithHashSpec = new COutStreamWithCRC;
+ _outStreamWithHash = _outStreamWithHashSpec;
+}
+
+HRESULT CFolderOutStream::Init(
+ const CArchiveDatabaseEx *archiveDatabase,
+ UInt32 ref2Offset,
+ UInt32 startIndex,
+ const CBoolVector *extractStatuses,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode)
+{
+ _archiveDatabase = archiveDatabase;
+ _ref2Offset = ref2Offset;
+ _startIndex = startIndex;
+
+ _extractStatuses = extractStatuses;
+ _extractCallback = extractCallback;
+ _testMode = testMode;
+
+ _currentIndex = 0;
+ _fileIsOpen = false;
+ return WriteEmptyFiles();
+}
+
+HRESULT CFolderOutStream::OpenFile()
+{
+ Int32 askMode;
+ if((*_extractStatuses)[_currentIndex])
+ askMode = _testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ else
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+ CMyComPtr<ISequentialOutStream> realOutStream;
+
+ UInt32 index = _startIndex + _currentIndex;
+ RINOK(_extractCallback->GetStream(_ref2Offset + index, &realOutStream, askMode));
+
+ _outStreamWithHashSpec->SetStream(realOutStream);
+ _outStreamWithHashSpec->Init();
+ if (askMode == NArchive::NExtract::NAskMode::kExtract &&
+ (!realOutStream))
+ {
+ const CFileItem &fileInfo = _archiveDatabase->Files[index];
+ if (!fileInfo.IsAnti && !fileInfo.IsDirectory)
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+ }
+ return _extractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CFolderOutStream::WriteEmptyFiles()
+{
+ for(;_currentIndex < _extractStatuses->Size(); _currentIndex++)
+ {
+ UInt32 index = _startIndex + _currentIndex;
+ const CFileItem &fileInfo = _archiveDatabase->Files[index];
+ if (!fileInfo.IsAnti && !fileInfo.IsDirectory && fileInfo.UnPackSize != 0)
+ return S_OK;
+ RINOK(OpenFile());
+ RINOK(_extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kOK));
+ _outStreamWithHashSpec->ReleaseStream();
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CFolderOutStream::Write(const void *data,
+ UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ while(_currentIndex < _extractStatuses->Size())
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 index = _startIndex + _currentIndex;
+ const CFileItem &fileInfo = _archiveDatabase->Files[index];
+ UInt64 fileSize = fileInfo.UnPackSize;
+
+ UInt32 numBytesToWrite = (UInt32)MyMin(fileSize - _filePos,
+ UInt64(size - realProcessedSize));
+
+ UInt32 processedSizeLocal;
+ RINOK(_outStreamWithHash->Write((const Byte *)data + realProcessedSize,
+ numBytesToWrite, &processedSizeLocal));
+
+ _filePos += processedSizeLocal;
+ realProcessedSize += processedSizeLocal;
+ if (_filePos == fileSize)
+ {
+ bool digestsAreEqual;
+ if (fileInfo.IsFileCRCDefined)
+ digestsAreEqual = fileInfo.FileCRC == _outStreamWithHashSpec->GetCRC();
+ else
+ digestsAreEqual = true;
+
+ RINOK(_extractCallback->SetOperationResult(
+ digestsAreEqual ?
+ NArchive::NExtract::NOperationResult::kOK :
+ NArchive::NExtract::NOperationResult::kCRCError));
+ _outStreamWithHashSpec->ReleaseStream();
+ _fileIsOpen = false;
+ _currentIndex++;
+ }
+ if (realProcessedSize == size)
+ {
+ if (processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return WriteEmptyFiles();
+ }
+ }
+ else
+ {
+ RINOK(OpenFile());
+ _fileIsOpen = true;
+ _filePos = 0;
+ }
+ }
+ if (processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::FlushCorrupted(Int32 resultEOperationResult)
+{
+ while(_currentIndex < _extractStatuses->Size())
+ {
+ if (_fileIsOpen)
+ {
+ RINOK(_extractCallback->SetOperationResult(resultEOperationResult));
+ _outStreamWithHashSpec->ReleaseStream();
+ _fileIsOpen = false;
+ _currentIndex++;
+ }
+ else
+ {
+ RINOK(OpenFile());
+ _fileIsOpen = true;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CFolderOutStream::WasWritingFinished()
+{
+ if (_currentIndex == _extractStatuses->Size())
+ return S_OK;
+ return E_FAIL;
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zFolderOutStream.h b/CPP/7zip/Archive/7z/7zFolderOutStream.h
new file mode 100755
index 00000000..c132c79a
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zFolderOutStream.h
@@ -0,0 +1,57 @@
+// 7zFolderOutStream.h
+
+#ifndef __7Z_FOLDEROUTSTREAM_H
+#define __7Z_FOLDEROUTSTREAM_H
+
+#include "7zIn.h"
+
+#include "../../IStream.h"
+#include "../IArchive.h"
+#include "../Common/OutStreamWithCRC.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ CFolderOutStream();
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+
+ COutStreamWithCRC *_outStreamWithHashSpec;
+ CMyComPtr<ISequentialOutStream> _outStreamWithHash;
+ const CArchiveDatabaseEx *_archiveDatabase;
+ const CBoolVector *_extractStatuses;
+ UInt32 _startIndex;
+ UInt32 _ref2Offset;
+ int _currentIndex;
+ // UInt64 _currentDataPos;
+ CMyComPtr<IArchiveExtractCallback> _extractCallback;
+ bool _testMode;
+
+ bool _fileIsOpen;
+ UInt64 _filePos;
+
+ HRESULT OpenFile();
+ HRESULT WriteEmptyFiles();
+public:
+ HRESULT Init(
+ const CArchiveDatabaseEx *archiveDatabase,
+ UInt32 ref2Offset,
+ UInt32 startIndex,
+ const CBoolVector *extractStatuses,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode);
+ HRESULT FlushCorrupted(Int32 resultEOperationResult);
+ HRESULT WasWritingFinished();
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zHandler.cpp b/CPP/7zip/Archive/7z/7zHandler.cpp
new file mode 100755
index 00000000..3321fd71
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandler.cpp
@@ -0,0 +1,794 @@
+// 7zHandler.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zProperties.h"
+
+#include "../../../Common/IntToString.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Windows/Defs.h"
+
+#include "../Common/ItemNameUtils.h"
+#ifdef _7Z_VOL
+#include "../Common/MultiStream.h"
+#endif
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+#include "../Common/ParseProperties.h"
+#endif
+#endif
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+CHandler::CHandler()
+{
+ #ifdef COMPRESS_MT
+ _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ #endif
+ #ifndef EXTRACT_ONLY
+ Init();
+ #endif
+ #ifndef EXCLUDE_COM
+ LoadMethodMap();
+ #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems =
+ #ifdef _7Z_VOL
+ _refs.Size();
+ #else
+ *numItems = _database.Files.Size();
+ #endif
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID /* propID */, PROPVARIANT *value)
+{
+ value->vt = VT_EMPTY;
+ return S_OK;
+}
+
+#ifdef _SFX
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
+{
+ return E_NOTIMPL;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
+ BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
+{
+ return E_NOTIMPL;
+}
+
+#endif
+
+
+STDMETHODIMP CHandler::GetNumberOfArchiveProperties(UInt32 *numProperties)
+{
+ *numProperties = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 /* index */,
+ BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
+{
+ return E_NOTIMPL;
+}
+
+
+static void MySetFileTime(bool timeDefined, FILETIME unixTime,
+ NWindows::NCOM::CPropVariant &propVariant)
+{
+ if (timeDefined)
+ propVariant = unixTime;
+}
+
+#ifndef _SFX
+
+static UString ConvertUInt32ToString(UInt32 value)
+{
+ wchar_t buffer[32];
+ ConvertUInt64ToString(value, buffer);
+ return buffer;
+}
+
+static UString GetStringForSizeValue(UInt32 value)
+{
+ for (int i = 31; i >= 0; i--)
+ if ((UInt32(1) << i) == value)
+ return ConvertUInt32ToString(i);
+ UString result;
+ if (value % (1 << 20) == 0)
+ {
+ result += ConvertUInt32ToString(value >> 20);
+ result += L"m";
+ }
+ else if (value % (1 << 10) == 0)
+ {
+ result += ConvertUInt32ToString(value >> 10);
+ result += L"k";
+ }
+ else
+ {
+ result += ConvertUInt32ToString(value);
+ result += L"b";
+ }
+ return result;
+}
+
+static CMethodID k_Copy = { { 0x0 }, 1 };
+static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+static CMethodID k_BCJ = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
+static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
+static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
+static CMethodID k_Deflate64 = { { 0x4, 0x1, 0x9 }, 3 };
+static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
+
+static wchar_t GetHex(Byte value)
+{
+ return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
+}
+static inline UString GetHex2(Byte value)
+{
+ UString result;
+ result += GetHex((Byte)(value >> 4));
+ result += GetHex((Byte)(value & 0xF));
+ return result;
+}
+
+#endif
+
+static CMethodID k_AES = { { 0x6, 0xF1, 0x7, 0x1}, 4 };
+
+static inline UInt32 GetUInt32FromMemLE(const Byte *p)
+{
+ return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
+}
+
+bool CHandler::IsEncrypted(UInt32 index2) const
+{
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _database.Folders[folderIndex];
+ for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ for (int j = 0; j < coderInfo.AltCoders.Size(); j++)
+ if (coderInfo.AltCoders[j].MethodID == k_AES)
+ return true;
+ }
+ }
+ return false;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+
+ /*
+ const CRef2 &ref2 = _refs[index];
+ if (ref2.Refs.IsEmpty())
+ return E_FAIL;
+ const CRef &ref = ref2.Refs.Front();
+ */
+
+ #ifdef _7Z_VOL
+ const CRef &ref = _refs[index];
+ const CVolume &volume = _volumes[ref.VolumeIndex];
+ const CArchiveDatabaseEx &_database = volume.Database;
+ UInt32 index2 = ref.ItemIndex;
+ const CFileItem &item = _database.Files[index2];
+ #else
+ const CFileItem &item = _database.Files[index];
+ UInt32 index2 = index;
+ #endif
+
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ if (!item.Name.IsEmpty())
+ propVariant = NItemName::GetOSName(item.Name);
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = item.IsDirectory;
+ break;
+ case kpidSize:
+ {
+ propVariant = item.UnPackSize;
+ // propVariant = ref2.UnPackSize;
+ break;
+ }
+ case kpidPosition:
+ {
+ /*
+ if (ref2.Refs.Size() > 1)
+ propVariant = ref2.StartPos;
+ else
+ */
+ if (item.IsStartPosDefined)
+ propVariant = item.StartPos;
+ break;
+ }
+ case kpidPackedSize:
+ {
+ // propVariant = ref2.PackSize;
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
+ propVariant = _database.GetFolderFullPackSize(folderIndex);
+ /*
+ else
+ propVariant = UInt64(0);
+ */
+ }
+ else
+ propVariant = UInt64(0);
+ }
+ break;
+ }
+ case kpidLastAccessTime:
+ MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, propVariant);
+ break;
+ case kpidCreationTime:
+ MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, propVariant);
+ break;
+ case kpidLastWriteTime:
+ MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, propVariant);
+ break;
+ case kpidAttributes:
+ if (item.AreAttributesDefined)
+ propVariant = item.Attributes;
+ break;
+ case kpidCRC:
+ if (item.IsFileCRCDefined)
+ propVariant = item.FileCRC;
+ break;
+ case kpidEncrypted:
+ {
+ propVariant = IsEncrypted(index2);
+ break;
+ }
+ #ifndef _SFX
+ case kpidMethod:
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _database.Folders[folderIndex];
+ UString methodsString;
+ for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
+ {
+ const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ if (!methodsString.IsEmpty())
+ methodsString += L' ';
+ CMethodInfo methodInfo;
+
+ bool methodIsKnown;
+
+ for (int j = 0; j < coderInfo.AltCoders.Size(); j++)
+ {
+ if (j > 0)
+ methodsString += L"|";
+ const CAltCoderInfo &altCoderInfo = coderInfo.AltCoders[j];
+
+ UString methodName;
+ #ifdef NO_REGISTRY
+
+ methodIsKnown = true;
+ if (altCoderInfo.MethodID == k_Copy)
+ methodName = L"Copy";
+ else if (altCoderInfo.MethodID == k_LZMA)
+ methodName = L"LZMA";
+ else if (altCoderInfo.MethodID == k_BCJ)
+ methodName = L"BCJ";
+ else if (altCoderInfo.MethodID == k_BCJ2)
+ methodName = L"BCJ2";
+ else if (altCoderInfo.MethodID == k_PPMD)
+ methodName = L"PPMD";
+ else if (altCoderInfo.MethodID == k_Deflate)
+ methodName = L"Deflate";
+ else if (altCoderInfo.MethodID == k_Deflate64)
+ methodName = L"Deflate64";
+ else if (altCoderInfo.MethodID == k_BZip2)
+ methodName = L"BZip2";
+ else if (altCoderInfo.MethodID == k_AES)
+ methodName = L"7zAES";
+ else
+ methodIsKnown = false;
+
+ #else
+
+ methodIsKnown = GetMethodInfo(
+ altCoderInfo.MethodID, methodInfo);
+ methodName = methodInfo.Name;
+
+ #endif
+
+ if (methodIsKnown)
+ {
+ methodsString += methodName;
+ if (altCoderInfo.MethodID == k_LZMA)
+ {
+ if (altCoderInfo.Properties.GetCapacity() >= 5)
+ {
+ methodsString += L":";
+ UInt32 dicSize = GetUInt32FromMemLE(
+ ((const Byte *)altCoderInfo.Properties + 1));
+ methodsString += GetStringForSizeValue(dicSize);
+ }
+ }
+ else if (altCoderInfo.MethodID == k_PPMD)
+ {
+ if (altCoderInfo.Properties.GetCapacity() >= 5)
+ {
+ Byte order = *(const Byte *)altCoderInfo.Properties;
+ methodsString += L":o";
+ methodsString += ConvertUInt32ToString(order);
+ methodsString += L":mem";
+ UInt32 dicSize = GetUInt32FromMemLE(
+ ((const Byte *)altCoderInfo.Properties + 1));
+ methodsString += GetStringForSizeValue(dicSize);
+ }
+ }
+ else if (altCoderInfo.MethodID == k_AES)
+ {
+ if (altCoderInfo.Properties.GetCapacity() >= 1)
+ {
+ methodsString += L":";
+ const Byte *data = (const Byte *)altCoderInfo.Properties;
+ Byte firstByte = *data++;
+ UInt32 numCyclesPower = firstByte & 0x3F;
+ methodsString += ConvertUInt32ToString(numCyclesPower);
+ /*
+ if ((firstByte & 0xC0) != 0)
+ {
+ methodsString += L":";
+ return S_OK;
+ UInt32 saltSize = (firstByte >> 7) & 1;
+ UInt32 ivSize = (firstByte >> 6) & 1;
+ if (altCoderInfo.Properties.GetCapacity() >= 2)
+ {
+ Byte secondByte = *data++;
+ saltSize += (secondByte >> 4);
+ ivSize += (secondByte & 0x0F);
+ }
+ }
+ */
+ }
+ }
+ else
+ {
+ if (altCoderInfo.Properties.GetCapacity() > 0)
+ {
+ methodsString += L":[";
+ for (size_t bi = 0; bi < altCoderInfo.Properties.GetCapacity(); bi++)
+ {
+ if (bi > 5 && bi + 1 < altCoderInfo.Properties.GetCapacity())
+ {
+ methodsString += L"..";
+ break;
+ }
+ else
+ methodsString += GetHex2(altCoderInfo.Properties[bi]);
+ }
+ methodsString += L"]";
+ }
+ }
+ }
+ else
+ {
+ methodsString += altCoderInfo.MethodID.ConvertToString();
+ }
+ }
+ }
+ propVariant = methodsString;
+ }
+ }
+ break;
+ case kpidBlock:
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ propVariant = (UInt32)folderIndex;
+ }
+ break;
+ case kpidPackedSize0:
+ case kpidPackedSize1:
+ case kpidPackedSize2:
+ case kpidPackedSize3:
+ case kpidPackedSize4:
+ {
+ CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
+ if (folderIndex != kNumNoIndex)
+ {
+ const CFolder &folderInfo = _database.Folders[folderIndex];
+ if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
+ folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
+ {
+ propVariant = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
+ }
+ else
+ propVariant = UInt64(0);
+ }
+ else
+ propVariant = UInt64(0);
+ }
+ break;
+ #endif
+ case kpidIsAnti:
+ propVariant = item.IsAnti;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+static const wchar_t *kExt = L"7z";
+static const wchar_t *kAfterPart = L".7z";
+
+#ifdef _7Z_VOL
+
+class CVolumeName
+{
+ bool _first;
+ UString _unchangedPart;
+ UString _changedPart;
+ UString _afterPart;
+public:
+ bool InitName(const UString &name)
+ {
+ _first = true;
+ int dotPos = name.ReverseFind('.');
+ UString basePart = name;
+ if (dotPos >= 0)
+ {
+ UString ext = name.Mid(dotPos + 1);
+ if (ext.CompareNoCase(kExt)==0 ||
+ ext.CompareNoCase(L"EXE") == 0)
+ {
+ _afterPart = kAfterPart;
+ basePart = name.Left(dotPos);
+ }
+ }
+
+ int numLetters = 1;
+ bool splitStyle = false;
+ if (basePart.Right(numLetters) == L"1")
+ {
+ while (numLetters < basePart.Length())
+ {
+ if (basePart[basePart.Length() - numLetters - 1] != '0')
+ break;
+ numLetters++;
+ }
+ }
+ else
+ return false;
+ _unchangedPart = basePart.Left(basePart.Length() - numLetters);
+ _changedPart = basePart.Right(numLetters);
+ return true;
+ }
+
+ UString GetNextName()
+ {
+ UString newName;
+ // if (_newStyle || !_first)
+ {
+ int i;
+ int numLetters = _changedPart.Length();
+ for (i = numLetters - 1; i >= 0; i--)
+ {
+ wchar_t c = _changedPart[i];
+ if (c == L'9')
+ {
+ c = L'0';
+ newName = c + newName;
+ if (i == 0)
+ newName = UString(L'1') + newName;
+ continue;
+ }
+ c++;
+ newName = UString(c) + newName;
+ i--;
+ for (; i >= 0; i--)
+ newName = _changedPart[i] + newName;
+ break;
+ }
+ _changedPart = newName;
+ }
+ _first = false;
+ return _unchangedPart + _changedPart + _afterPart;
+ }
+};
+
+#endif
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ #ifndef _SFX
+ _fileInfoPopIDs.Clear();
+ #endif
+ try
+ {
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
+ #ifdef _7Z_VOL
+ CVolumeName seqName;
+
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ #endif
+
+ #ifndef _NO_CRYPTO
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ if (openArchiveCallback)
+ {
+ openArchiveCallbackTemp.QueryInterface(
+ IID_ICryptoGetTextPassword, &getTextPassword);
+ }
+ #endif
+ #ifdef _7Z_VOL
+ if (openArchiveCallback)
+ {
+ openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
+ }
+ for (;;)
+ {
+ CMyComPtr<IInStream> inStream;
+ if (!_volumes.IsEmpty())
+ {
+ if (!openVolumeCallback)
+ break;
+ if(_volumes.Size() == 1)
+ {
+ UString baseName;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant));
+ if (propVariant.vt != VT_BSTR)
+ break;
+ baseName = propVariant.bstrVal;
+ }
+ seqName.InitName(baseName);
+ }
+
+ UString fullName = seqName.GetNextName();
+ HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!stream)
+ break;
+ }
+ else
+ inStream = stream;
+
+ CInArchive archive;
+ RINOK(archive.Open(inStream, maxCheckStartPosition));
+
+ _volumes.Add(CVolume());
+ CVolume &volume = _volumes.Back();
+ CArchiveDatabaseEx &database = volume.Database;
+ volume.Stream = inStream;
+ volume.StartRef2Index = _refs.Size();
+
+ HRESULT result = archive.ReadDatabase(database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ if (result != S_OK)
+ {
+ _volumes.Clear();
+ return result;
+ }
+ database.Fill();
+ for(int i = 0; i < database.Files.Size(); i++)
+ {
+ CRef refNew;
+ refNew.VolumeIndex = _volumes.Size() - 1;
+ refNew.ItemIndex = i;
+ _refs.Add(refNew);
+ /*
+ const CFileItem &file = database.Files[i];
+ int j;
+ */
+ /*
+ for (j = _refs.Size() - 1; j >= 0; j--)
+ {
+ CRef2 &ref2 = _refs[j];
+ const CRef &ref = ref2.Refs.Back();
+ const CVolume &volume2 = _volumes[ref.VolumeIndex];
+ const CArchiveDatabaseEx &database2 = volume2.Database;
+ const CFileItem &file2 = database2.Files[ref.ItemIndex];
+ if (file2.Name.CompareNoCase(file.Name) == 0)
+ {
+ if (!file.IsStartPosDefined)
+ continue;
+ if (file.StartPos != ref2.StartPos + ref2.UnPackSize)
+ continue;
+ ref2.Refs.Add(refNew);
+ break;
+ }
+ }
+ */
+ /*
+ j = -1;
+ if (j < 0)
+ {
+ CRef2 ref2New;
+ ref2New.Refs.Add(refNew);
+ j = _refs.Add(ref2New);
+ }
+ CRef2 &ref2 = _refs[j];
+ ref2.UnPackSize += file.UnPackSize;
+ ref2.PackSize += database.GetFilePackSize(i);
+ if (ref2.Refs.Size() == 1 && file.IsStartPosDefined)
+ ref2.StartPos = file.StartPos;
+ */
+ }
+ if (database.Files.Size() != 1)
+ break;
+ const CFileItem &file = database.Files.Front();
+ if (!file.IsStartPosDefined)
+ break;
+ }
+ #else
+ CInArchive archive;
+ RINOK(archive.Open(stream, maxCheckStartPosition));
+ HRESULT result = archive.ReadDatabase(_database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ RINOK(result);
+ _database.Fill();
+ _inStream = stream;
+ #endif
+ }
+ catch(...)
+ {
+ Close();
+ return S_FALSE;
+ }
+ // _inStream = stream;
+ #ifndef _SFX
+ FillPopIDs();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ #ifdef _7Z_VOL
+ _volumes.Clear();
+ _refs.Clear();
+ #else
+ _inStream.Release();
+ _database.Clear();
+ #endif
+ return S_OK;
+ COM_TRY_END
+}
+
+#ifdef _7Z_VOL
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ if (index != 0)
+ return E_INVALIDARG;
+ *stream = 0;
+ CMultiStream *streamSpec = new CMultiStream;
+ CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+
+ UInt64 pos = 0;
+ const UString *fileName;
+ for (int i = 0; i < _refs.Size(); i++)
+ {
+ const CRef &ref = _refs[i];
+ const CVolume &volume = _volumes[ref.VolumeIndex];
+ const CArchiveDatabaseEx &database = volume.Database;
+ const CFileItem &file = database.Files[ref.ItemIndex];
+ if (i == 0)
+ fileName = &file.Name;
+ else
+ if (fileName->Compare(file.Name) != 0)
+ return S_FALSE;
+ if (!file.IsStartPosDefined)
+ return S_FALSE;
+ if (file.StartPos != pos)
+ return S_FALSE;
+ CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex];
+ if (folderIndex == kNumNoIndex)
+ {
+ if (file.UnPackSize != 0)
+ return E_FAIL;
+ continue;
+ }
+ if (database.NumUnPackStreamsVector[folderIndex] != 1)
+ return S_FALSE;
+ const CFolder &folder = database.Folders[folderIndex];
+ if (folder.Coders.Size() != 1)
+ return S_FALSE;
+ const CCoderInfo &coder = folder.Coders.Front();
+ if (coder.NumInStreams != 1 || coder.NumOutStreams != 1)
+ return S_FALSE;
+ const CAltCoderInfo &altCoder = coder.AltCoders.Front();
+ if (altCoder.MethodID.IDSize != 1 || altCoder.MethodID.ID[0] != 0)
+ return S_FALSE;
+
+ pos += file.UnPackSize;
+ CMultiStream::CSubStreamInfo subStreamInfo;
+ subStreamInfo.Stream = volume.Stream;
+ subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0);
+ subStreamInfo.Size = file.UnPackSize;
+ streamSpec->Streams.Add(subStreamInfo);
+ }
+ streamSpec->Init();
+ *stream = streamTemp.Detach();
+ return S_OK;
+}
+#endif
+
+
+#ifdef __7Z_SET_PROPERTIES
+#ifdef EXTRACT_ONLY
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ COM_TRY_BEGIN
+ #ifdef COMPRESS_MT
+ const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+ _numThreads = numProcessors;
+ #endif
+
+ for (int i = 0; i < numProperties; i++)
+ {
+ UString name = names[i];
+ name.MakeUpper();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+ const PROPVARIANT &value = values[i];
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ if (index == 0)
+ {
+ if(name.Left(2).CompareNoCase(L"MT") == 0)
+ {
+ #ifdef COMPRESS_MT
+ RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
+ #endif
+ continue;
+ }
+ else
+ return E_INVALIDARG;
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+#endif
+#endif
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zHandler.h b/CPP/7zip/Archive/7z/7zHandler.h
new file mode 100755
index 00000000..8be9f398
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandler.h
@@ -0,0 +1,249 @@
+// 7z/Handler.h
+
+#ifndef __7Z_HANDLER_H
+#define __7Z_HANDLER_H
+
+#include "../IArchive.h"
+#include "7zIn.h"
+
+#include "7zCompressionMode.h"
+
+#ifndef _SFX
+#include "7zMethods.h"
+#endif
+
+#ifdef COMPRESS_MT
+#include "../../../Windows/System.h"
+#endif
+
+namespace NArchive {
+namespace N7z {
+
+#ifdef _7Z_VOL
+struct CRef
+{
+ int VolumeIndex;
+ int ItemIndex;
+};
+
+/*
+struct CRef2
+{
+ CRecordVector<CRef> Refs;
+ UInt64 UnPackSize;
+ UInt64 PackSize;
+ UInt64 StartPos;
+ CRef2(): UnPackSize(0), PackSize(0), StartPos(0) {}
+};
+*/
+
+struct CVolume
+{
+ int StartRef2Index;
+ CMyComPtr<IInStream> Stream;
+ CArchiveDatabaseEx Database;
+};
+#endif
+
+#ifndef EXTRACT_ONLY
+
+struct COneMethodInfo
+{
+ CObjectVector<CProperty> CoderProperties;
+ UString MethodName;
+};
+#endif
+
+// {23170F69-40C1-278A-1000-000110070000}
+DEFINE_GUID(CLSID_CFormat7z,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x07, 0x00, 0x00);
+
+#ifndef __7Z_SET_PROPERTIES
+
+#ifdef EXTRACT_ONLY
+#ifdef COMPRESS_MT
+#define __7Z_SET_PROPERTIES
+#endif
+#else
+#define __7Z_SET_PROPERTIES
+#endif
+
+#endif
+
+
+class CHandler:
+ public IInArchive,
+ #ifdef _7Z_VOL
+ public IInArchiveGetStream,
+ #endif
+ #ifdef __7Z_SET_PROPERTIES
+ public ISetProperties,
+ #endif
+ #ifndef EXTRACT_ONLY
+ public IOutArchive,
+ #endif
+ public CMyUnknownImp
+{
+public:
+ #if !defined(_7Z_VOL) && !defined(__7Z_SET_PROPERTIES) && defined(EXTRACT_ONLY)
+ MY_UNKNOWN_IMP
+ #else
+ MY_QUERYINTERFACE_BEGIN
+ #ifdef _7Z_VOL
+ MY_QUERYINTERFACE_ENTRY(IInArchiveGetStream)
+ #endif
+ #ifdef __7Z_SET_PROPERTIES
+ MY_QUERYINTERFACE_ENTRY(ISetProperties)
+ #endif
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY(IOutArchive)
+ #endif
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+ #endif
+
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+ #ifdef _7Z_VOL
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+ #endif
+
+ #ifdef __7Z_SET_PROPERTIES
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ // IOutArchiveHandler
+ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback);
+
+ STDMETHOD(GetFileTimeType)(UInt32 *type);
+
+ // ISetProperties
+
+ HRESULT SetSolidSettings(const UString &s);
+ HRESULT SetSolidSettings(const PROPVARIANT &value);
+ #endif
+
+ CHandler();
+
+private:
+ #ifdef _7Z_VOL
+ CObjectVector<CVolume> _volumes;
+ CObjectVector<CRef> _refs;
+ #else
+ CMyComPtr<IInStream> _inStream;
+ NArchive::N7z::CArchiveDatabaseEx _database;
+ #endif
+
+ #ifdef COMPRESS_MT
+ UInt32 _numThreads;
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ CObjectVector<COneMethodInfo> _methods;
+ CRecordVector<CBind> _binds;
+ bool _removeSfxBlock;
+ UInt64 _numSolidFiles;
+ UInt64 _numSolidBytes;
+ bool _numSolidBytesDefined;
+ bool _solidExtension;
+
+ bool _compressHeaders;
+ bool _compressHeadersFull;
+ bool _encryptHeaders;
+
+ bool WriteModified;
+ bool WriteCreated;
+ bool WriteAccessed;
+
+
+ bool _autoFilter;
+ UInt32 _level;
+
+ bool _volumeMode;
+
+
+ HRESULT SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value);
+ HRESULT SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString);
+
+ HRESULT SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback);
+
+ HRESULT SetCompressionMethod(CCompressionMethodMode &method,
+ CObjectVector<COneMethodInfo> &methodsInfo
+ #ifdef COMPRESS_MT
+ , UInt32 numThreads
+ #endif
+ );
+
+ HRESULT SetCompressionMethod(
+ CCompressionMethodMode &method,
+ CCompressionMethodMode &headerMethod);
+
+ #endif
+
+ bool IsEncrypted(UInt32 index2) const;
+ #ifndef _SFX
+
+ CRecordVector<UInt64> _fileInfoPopIDs;
+ void FillPopIDs();
+
+ #endif
+
+ #ifndef EXTRACT_ONLY
+
+ void InitSolidFiles() { _numSolidFiles = UInt64(Int64(-1)); }
+ void InitSolidSize() { _numSolidBytes = UInt64(Int64(-1)); }
+ void InitSolid()
+ {
+ InitSolidFiles();
+ InitSolidSize();
+ _solidExtension = false;
+ _numSolidBytesDefined = false;
+ }
+
+ void Init()
+ {
+ _removeSfxBlock = false;
+ _compressHeaders = true;
+ _compressHeadersFull = true;
+ _encryptHeaders = false;
+
+ WriteModified = true;
+ WriteCreated = false;
+ WriteAccessed = false;
+
+ #ifdef COMPRESS_MT
+ _numThreads = NWindows::NSystem::GetNumberOfProcessors();
+ #endif
+
+ _level = 5;
+ _autoFilter = true;
+ _volumeMode = false;
+ InitSolid();
+ }
+ #endif
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zHandlerOut.cpp b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
new file mode 100755
index 00000000..8be88c38
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHandlerOut.cpp
@@ -0,0 +1,1148 @@
+// 7z/OutHandler.cpp
+
+#include "StdAfx.h"
+
+#include "7zHandler.h"
+#include "7zOut.h"
+#include "7zUpdate.h"
+#include "7zMethods.h"
+
+#include "../../../Windows/PropVariant.h"
+
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringToInt.h"
+#include "../../IPassword.h"
+#include "../../ICoder.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/ParseProperties.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+#ifdef COMPRESS_LZMA
+static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+static CMethodID k_LZMA2 = { { 0x3, 0x1, 0x2 }, 3 };
+#endif
+
+#ifdef COMPRESS_PPMD
+static CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };
+#endif
+
+#ifdef COMPRESS_BCJ_X86
+static CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+#endif
+
+#ifdef COMPRESS_BCJ2
+static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
+#endif
+
+#ifdef COMPRESS_COPY
+static CMethodID k_Copy = { { 0x0 }, 1 };
+#endif
+
+#ifdef COMPRESS_DEFLATE
+#ifndef COMPRESS_DEFLATE_ENCODER
+#define COMPRESS_DEFLATE_ENCODER
+#endif
+#endif
+
+#ifdef COMPRESS_DEFLATE_ENCODER
+static CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };
+#endif
+
+#ifdef COMPRESS_BZIP2
+#ifndef COMPRESS_BZIP2_ENCODER
+#define COMPRESS_BZIP2_ENCODER
+#endif
+#endif
+
+#ifdef COMPRESS_BZIP2_ENCODER
+static CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };
+#endif
+
+const wchar_t *kCopyMethod = L"Copy";
+const wchar_t *kLZMAMethodName = L"LZMA";
+const wchar_t *kLZMA2MethodName = L"LZMA2";
+const wchar_t *kBZip2MethodName = L"BZip2";
+const wchar_t *kPpmdMethodName = L"PPMd";
+const wchar_t *kDeflateMethodName = L"Deflate";
+const wchar_t *kDeflate64MethodName = L"Deflate64";
+
+static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
+static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
+
+static const UInt32 kLzmaAlgorithmX1 = 0;
+static const UInt32 kLzmaAlgorithmX5 = 1;
+
+static const UInt32 kLzmaDicSizeX1 = 1 << 16;
+static const UInt32 kLzmaDicSizeX3 = 1 << 20;
+static const UInt32 kLzmaDicSizeX5 = 1 << 22;
+static const UInt32 kLzmaDicSizeX7 = 1 << 24;
+static const UInt32 kLzmaDicSizeX9 = 1 << 26;
+
+static const UInt32 kLzmaFastBytesX1 = 32;
+static const UInt32 kLzmaFastBytesX7 = 64;
+
+static const UInt32 kPpmdMemSizeX1 = (1 << 22);
+static const UInt32 kPpmdMemSizeX5 = (1 << 24);
+static const UInt32 kPpmdMemSizeX7 = (1 << 26);
+static const UInt32 kPpmdMemSizeX9 = (192 << 20);
+
+static const UInt32 kPpmdOrderX1 = 4;
+static const UInt32 kPpmdOrderX5 = 6;
+static const UInt32 kPpmdOrderX7 = 16;
+static const UInt32 kPpmdOrderX9 = 32;
+
+static const UInt32 kDeflateFastBytesX1 = 32;
+static const UInt32 kDeflateFastBytesX7 = 64;
+static const UInt32 kDeflateFastBytesX9 = 128;
+
+static const UInt32 kDeflatePassesX1 = 1;
+static const UInt32 kDeflatePassesX7 = 3;
+static const UInt32 kDeflatePassesX9 = 10;
+
+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;
+
+const wchar_t *kDefaultMethodName = kLZMAMethodName;
+
+static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
+static const UInt32 kDictionaryForHeaders = 1 << 20;
+static const UInt32 kNumFastBytesForHeaders = 273;
+static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;
+
+static bool IsCopyMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kCopyMethod) == 0); }
+
+static bool IsLZMAMethod(const UString &methodName)
+{
+ return
+ (methodName.CompareNoCase(kLZMAMethodName) == 0) ||
+ (methodName.CompareNoCase(kLZMA2MethodName) == 0);
+}
+
+/*
+static bool IsLZMethod(const UString &methodName)
+ { return IsLZMAMethod(methodName); }
+*/
+
+static bool IsBZip2Method(const UString &methodName)
+ { return (methodName.CompareNoCase(kBZip2MethodName) == 0); }
+
+static bool IsPpmdMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kPpmdMethodName) == 0); }
+
+static bool IsDeflateMethod(const UString &methodName)
+ { return (methodName.CompareNoCase(kDeflateMethodName) == 0) ||
+ (methodName.CompareNoCase(kDeflate64MethodName) == 0); }
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kWindows;
+ return S_OK;
+}
+
+HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode,
+ IArchiveUpdateCallback *updateCallback)
+{
+ 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));
+ methodMode.PasswordIsDefined = IntToBool(passwordIsDefined);
+ if (methodMode.PasswordIsDefined)
+ methodMode.Password = password;
+ }
+ else
+ methodMode.PasswordIsDefined = false;
+ return S_OK;
+}
+
+struct CNameToPropID
+{
+ PROPID PropID;
+ VARTYPE VarType;
+ const wchar_t *Name;
+};
+
+CNameToPropID g_NameToPropID[] =
+{
+ { NCoderPropID::kOrder, VT_UI4, L"O" },
+ { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
+ { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
+ { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
+
+ { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
+ { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
+ { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
+ { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
+ { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
+ { NCoderPropID::kNumThreads, VT_UI4, L"mt" }
+};
+
+bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType,
+ NCOM::CPropVariant &destProp)
+{
+ if (varType == srcProp.vt)
+ {
+ destProp = srcProp;
+ return true;
+ }
+ if (varType == VT_UI1)
+ {
+ if(srcProp.vt == VT_UI4)
+ {
+ UInt32 value = srcProp.ulVal;
+ if (value > 0xFF)
+ return false;
+ destProp = Byte(value);
+ return true;
+ }
+ }
+ return false;
+}
+
+const int kNumNameToPropIDItems = sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]);
+
+int FindPropIdFromStringName(const UString &name)
+{
+ for (int i = 0; i < kNumNameToPropIDItems; i++)
+ if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
+ return i;
+ return -1;
+}
+
+HRESULT CHandler::SetCompressionMethod(
+ CCompressionMethodMode &methodMode,
+ CCompressionMethodMode &headerMethod)
+{
+ HRESULT res = SetCompressionMethod(methodMode, _methods
+ #ifdef COMPRESS_MT
+ , _numThreads
+ #endif
+ );
+ RINOK(res);
+ methodMode.Binds = _binds;
+ if (_compressHeadersFull)
+ _compressHeaders = true;
+
+ if (_compressHeaders)
+ {
+ // headerMethod.Methods.Add(methodMode.Methods.Back());
+
+ CObjectVector<COneMethodInfo> headerMethodInfoVector;
+ COneMethodInfo oneMethodInfo;
+ oneMethodInfo.MethodName = kLZMAMethodName;
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kMatchFinder;
+ property.Value = kLzmaMatchFinderForHeaders;
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kAlgorithm;
+ property.Value = kAlgorithmForHeaders;
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kNumFastBytes;
+ property.Value = UInt32(kNumFastBytesForHeaders);
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kDictionarySize;
+ property.Value = UInt32(kDictionaryForHeaders);
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ headerMethodInfoVector.Add(oneMethodInfo);
+ HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector
+ #ifdef COMPRESS_MT
+ ,1
+ #endif
+ );
+ RINOK(res);
+ }
+ return S_OK;
+}
+
+static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID,
+ const NWindows::NCOM::CPropVariant &value)
+{
+ int j;
+ for (j = 0; j < oneMethodInfo.CoderProperties.Size(); j++)
+ if (oneMethodInfo.CoderProperties[j].PropID == propID)
+ break;
+ if (j != oneMethodInfo.CoderProperties.Size())
+ return;
+ CProperty property;
+ property.PropID = propID;
+ property.Value = value;
+ oneMethodInfo.CoderProperties.Add(property);
+}
+
+HRESULT CHandler::SetCompressionMethod(
+ CCompressionMethodMode &methodMode,
+ CObjectVector<COneMethodInfo> &methodsInfo
+ #ifdef COMPRESS_MT
+ , UInt32 numThreads
+ #endif
+ )
+{
+ #ifndef EXCLUDE_COM
+ /*
+ CObjectVector<CMethodInfo2> methodInfoVector;
+ if (!NRegistryInfo::EnumerateAllMethods(methodInfoVector))
+ return E_FAIL;
+ */
+ #endif
+
+
+ UInt32 level = _level;
+
+ if (methodsInfo.IsEmpty())
+ {
+ COneMethodInfo oneMethodInfo;
+ oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName);
+ methodsInfo.Add(oneMethodInfo);
+ }
+
+ bool needSolid = false;
+ for(int i = 0; i < methodsInfo.Size(); i++)
+ {
+ COneMethodInfo &oneMethodInfo = methodsInfo[i];
+ if (oneMethodInfo.MethodName.IsEmpty())
+ oneMethodInfo.MethodName = kDefaultMethodName;
+
+ if (!IsCopyMethod(oneMethodInfo.MethodName))
+ needSolid = true;
+
+ if (IsLZMAMethod(oneMethodInfo.MethodName))
+ {
+ UInt32 dicSize =
+ (level >= 9 ? kLzmaDicSizeX9 :
+ (level >= 7 ? kLzmaDicSizeX7 :
+ (level >= 5 ? kLzmaDicSizeX5 :
+ (level >= 3 ? kLzmaDicSizeX3 :
+ kLzmaDicSizeX1))));
+
+ UInt32 algorithm =
+ (level >= 5 ? kLzmaAlgorithmX5 :
+ kLzmaAlgorithmX1);
+
+ UInt32 fastBytes =
+ (level >= 7 ? kLzmaFastBytesX7 :
+ kLzmaFastBytesX1);
+
+ const wchar_t *matchFinder =
+ (level >= 5 ? kLzmaMatchFinderX5 :
+ kLzmaMatchFinderX1);
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algorithm);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
+ #ifdef COMPRESS_MT
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+ #endif
+ }
+ else if (IsDeflateMethod(oneMethodInfo.MethodName))
+ {
+ UInt32 fastBytes =
+ (level >= 9 ? kDeflateFastBytesX9 :
+ (level >= 7 ? kDeflateFastBytesX7 :
+ kDeflateFastBytesX1));
+
+ UInt32 numPasses =
+ (level >= 9 ? kDeflatePassesX9 :
+ (level >= 7 ? kDeflatePassesX7 :
+ kDeflatePassesX1));
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
+ }
+ else if (IsBZip2Method(oneMethodInfo.MethodName))
+ {
+ UInt32 numPasses =
+ (level >= 9 ? kBZip2NumPassesX9 :
+ (level >= 7 ? kBZip2NumPassesX7 :
+ kBZip2NumPassesX1));
+
+ UInt32 dicSize =
+ (level >= 5 ? kBZip2DicSizeX5 :
+ (level >= 3 ? kBZip2DicSizeX3 :
+ kBZip2DicSizeX1));
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
+ #ifdef COMPRESS_MT
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
+ #endif
+ }
+ else if (IsPpmdMethod(oneMethodInfo.MethodName))
+ {
+ UInt32 useMemSize =
+ (level >= 9 ? kPpmdMemSizeX9 :
+ (level >= 7 ? kPpmdMemSizeX7 :
+ (level >= 5 ? kPpmdMemSizeX5 :
+ kPpmdMemSizeX1)));
+
+ UInt32 order =
+ (level >= 9 ? kPpmdOrderX9 :
+ (level >= 7 ? kPpmdOrderX7 :
+ (level >= 5 ? kPpmdOrderX5 :
+ kPpmdOrderX1)));
+
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
+ SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
+ }
+
+
+ CMethodFull methodFull;
+ methodFull.NumInStreams = 1;
+ methodFull.NumOutStreams = 1;
+
+ bool defined = false;
+
+ #ifdef COMPRESS_LZMA
+ if (oneMethodInfo.MethodName.CompareNoCase(L"LZMA") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_LZMA;
+ }
+ #endif
+
+ #ifdef COMPRESS_PPMD
+ if (oneMethodInfo.MethodName.CompareNoCase(L"PPMD") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_PPMD;
+ }
+ #endif
+
+ #ifdef COMPRESS_BCJ_X86
+ if (oneMethodInfo.MethodName.CompareNoCase(L"BCJ") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_BCJ_X86;
+ }
+ #endif
+
+ #ifdef COMPRESS_BCJ2
+ if (oneMethodInfo.MethodName.CompareNoCase(L"BCJ2") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_BCJ2;
+ methodFull.NumInStreams = 4;
+ methodFull.NumOutStreams = 1;
+ }
+ #endif
+
+ #ifdef COMPRESS_DEFLATE_ENCODER
+ if (oneMethodInfo.MethodName.CompareNoCase(L"Deflate") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_Deflate;
+ }
+ #endif
+
+ #ifdef COMPRESS_BZIP2_ENCODER
+ if (oneMethodInfo.MethodName.CompareNoCase(L"BZip2") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_BZip2;
+ }
+ #endif
+
+ #ifdef COMPRESS_COPY
+ if (oneMethodInfo.MethodName.CompareNoCase(L"Copy") == 0)
+ {
+ defined = true;
+ methodFull.MethodID = k_Copy;
+ }
+
+ #endif
+
+ #ifndef EXCLUDE_COM
+
+ if (!defined)
+ {
+ CMethodInfo2 methodInfo;
+ if (!GetMethodInfo(oneMethodInfo.MethodName, methodInfo))
+ return E_INVALIDARG;
+ if (!methodInfo.EncoderIsAssigned)
+ return E_INVALIDARG;
+
+ methodFull.MethodID = methodInfo.MethodID;
+ methodFull.NumInStreams = methodInfo.NumInStreams;
+ methodFull.NumOutStreams = methodInfo.NumOutStreams;
+
+ methodFull.EncoderClassID = methodInfo.Encoder;
+ methodFull.FilePath = methodInfo.FilePath;
+ defined = true;
+ }
+
+ #endif
+ if (!defined)
+ return E_INVALIDARG;
+
+ methodFull.CoderProperties = oneMethodInfo.CoderProperties;
+ methodMode.Methods.Add(methodFull);
+
+ if (!_numSolidBytesDefined)
+ {
+ for (int j = 0; j < methodFull.CoderProperties.Size(); j++)
+ {
+ const CProperty &prop = methodFull.CoderProperties[j];
+ if ((prop.PropID == NCoderPropID::kDictionarySize ||
+ prop.PropID == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4)
+ {
+ _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7;
+ const UInt64 kMinSize = (1 << 24);
+ if (_numSolidBytes < kMinSize)
+ _numSolidBytes = kMinSize;
+ _numSolidBytesDefined = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!needSolid && !_numSolidBytesDefined)
+ {
+ _numSolidBytesDefined = true;
+ _numSolidBytes = 0;
+ }
+ return S_OK;
+}
+
+static HRESULT GetTime(IArchiveUpdateCallback *updateCallback, int index, PROPID propID, CArchiveFileTime &filetime, bool &filetimeIsDefined)
+{
+ filetimeIsDefined = false;
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(index, propID, &propVariant));
+ if (propVariant.vt == VT_FILETIME)
+ {
+ filetime = propVariant.filetime;
+ filetimeIsDefined = true;
+ }
+ else if (propVariant.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+
+ const CArchiveDatabaseEx *database = 0;
+ #ifdef _7Z_VOL
+ if(_volumes.Size() > 1)
+ return E_FAIL;
+ const CVolume *volume = 0;
+ if (_volumes.Size() == 1)
+ {
+ volume = &_volumes.Front();
+ database = &volume->Database;
+ }
+ #else
+ if (_inStream != 0)
+ database = &_database;
+ #endif
+
+ // CRecordVector<bool> compressStatuses;
+ CObjectVector<CUpdateItem> updateItems;
+ // CRecordVector<UInt32> copyIndices;
+
+ // CMyComPtr<IUpdateCallback2> updateCallback2;
+ // updateCallback->QueryInterface(&updateCallback2);
+
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(i,
+ &newData, &newProperties, &indexInArchive));
+ CUpdateItem updateItem;
+ updateItem.NewProperties = IntToBool(newProperties);
+ updateItem.NewData = IntToBool(newData);
+ updateItem.IndexInArchive = indexInArchive;
+ updateItem.IndexInClient = i;
+ updateItem.IsAnti = false;
+ updateItem.Size = 0;
+
+ if (updateItem.IndexInArchive != -1)
+ {
+ const CFileItem &fileItem = database->Files[updateItem.IndexInArchive];
+ updateItem.Name = fileItem.Name;
+ updateItem.IsDirectory = fileItem.IsDirectory;
+ updateItem.Size = fileItem.UnPackSize;
+ updateItem.IsAnti = fileItem.IsAnti;
+
+ updateItem.CreationTime = fileItem.CreationTime;
+ updateItem.IsCreationTimeDefined = fileItem.IsCreationTimeDefined;
+ updateItem.LastWriteTime = fileItem.LastWriteTime;
+ updateItem.IsLastWriteTimeDefined = fileItem.IsLastWriteTimeDefined;
+ updateItem.LastAccessTime = fileItem.LastAccessTime;
+ updateItem.IsLastAccessTimeDefined = fileItem.IsLastAccessTimeDefined;
+ }
+
+ if (updateItem.NewProperties)
+ {
+ bool nameIsDefined;
+ bool folderStatusIsDefined;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ updateItem.AttributesAreDefined = false;
+ else if (propVariant.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.Attributes = propVariant.ulVal;
+ updateItem.AttributesAreDefined = true;
+ }
+ }
+
+ RINOK(GetTime(updateCallback, i, kpidCreationTime, updateItem.CreationTime, updateItem.IsCreationTimeDefined));
+ RINOK(GetTime(updateCallback, i, kpidLastWriteTime, updateItem.LastWriteTime , updateItem.IsLastWriteTimeDefined));
+ RINOK(GetTime(updateCallback, i, kpidLastAccessTime, updateItem.LastAccessTime, updateItem.IsLastAccessTimeDefined));
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ nameIsDefined = false;
+ else if (propVariant.vt != VT_BSTR)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal);
+ nameIsDefined = true;
+ }
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ folderStatusIsDefined = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ {
+ updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);
+ folderStatusIsDefined = true;
+ }
+ }
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ updateItem.IsAnti = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE);
+ }
+
+ if (updateItem.IsAnti)
+ {
+ updateItem.AttributesAreDefined = false;
+
+ updateItem.IsCreationTimeDefined = false;
+ updateItem.IsLastWriteTimeDefined = false;
+ updateItem.IsLastAccessTimeDefined = false;
+
+ updateItem.Size = 0;
+ }
+
+ if (!folderStatusIsDefined && updateItem.AttributesAreDefined)
+ updateItem.SetDirectoryStatusFromAttributes();
+ }
+
+ if (updateItem.NewData)
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ updateItem.Size = (UInt64)propVariant.uhVal.QuadPart;
+ if (updateItem.Size != 0 && updateItem.IsAnti)
+ return E_INVALIDARG;
+ }
+ updateItems.Add(updateItem);
+ }
+
+ CCompressionMethodMode methodMode, headerMethod;
+ RINOK(SetCompressionMethod(methodMode, headerMethod));
+ #ifdef COMPRESS_MT
+ methodMode.NumThreads = _numThreads;
+ headerMethod.NumThreads = 1;
+ #endif
+
+ RINOK(SetPassword(methodMode, updateCallback));
+
+ bool useAdditionalHeaderStreams = true;
+ bool compressMainHeader = false;
+
+ if (_compressHeadersFull)
+ {
+ useAdditionalHeaderStreams = false;
+ compressMainHeader = true;
+ }
+ if (methodMode.PasswordIsDefined)
+ {
+ useAdditionalHeaderStreams = false;
+ compressMainHeader = true;
+ if(_encryptHeaders)
+ RINOK(SetPassword(headerMethod, updateCallback));
+ }
+
+ if (numItems < 2)
+ compressMainHeader = false;
+
+ CUpdateOptions options;
+ options.Method = &methodMode;
+ options.HeaderMethod = (_compressHeaders ||
+ (methodMode.PasswordIsDefined && _encryptHeaders)) ?
+ &headerMethod : 0;
+ options.UseFilters = _level != 0 && _autoFilter;
+ options.MaxFilter = _level >= 8;
+
+ options.HeaderOptions.UseAdditionalHeaderStreams = useAdditionalHeaderStreams;
+ options.HeaderOptions.CompressMainHeader = compressMainHeader;
+ options.HeaderOptions.WriteModified = WriteModified;
+ options.HeaderOptions.WriteCreated = WriteCreated;
+ options.HeaderOptions.WriteAccessed = WriteAccessed;
+
+ options.NumSolidFiles = _numSolidFiles;
+ options.NumSolidBytes = _numSolidBytes;
+ options.SolidExtension = _solidExtension;
+ options.RemoveSfxBlock = _removeSfxBlock;
+ options.VolumeMode = _volumeMode;
+ return Update(
+ #ifdef _7Z_VOL
+ volume ? volume->Stream: 0,
+ volume ? database: 0,
+ #else
+ _inStream,
+ database,
+ #endif
+ updateItems, outStream, updateCallback, options);
+ COM_TRY_END
+}
+
+static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream)
+{
+ stream = 0;
+ int index = ParseStringToUInt32(srcString, coder);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.Delete(0, index);
+ if (srcString[0] == 'S')
+ {
+ srcString.Delete(0);
+ int index = ParseStringToUInt32(srcString, stream);
+ if (index == 0)
+ return E_INVALIDARG;
+ srcString.Delete(0, index);
+ }
+ return S_OK;
+}
+
+static HRESULT GetBindInfo(UString &srcString, CBind &bind)
+{
+ RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));
+ if (srcString[0] != ':')
+ return E_INVALIDARG;
+ srcString.Delete(0);
+ RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));
+ if (!srcString.IsEmpty())
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+static void SplitParams(const UString &srcString, UStringVector &subStrings)
+{
+ subStrings.Clear();
+ UString name;
+ int len = srcString.Length();
+ if (len == 0)
+ return;
+ for (int i = 0; i < len; i++)
+ {
+ wchar_t c = srcString[i];
+ if (c == L':')
+ {
+ subStrings.Add(name);
+ name.Empty();
+ }
+ else
+ name += c;
+ }
+ subStrings.Add(name);
+}
+
+static void SplitParam(const UString &param, UString &name, UString &value)
+{
+ int eqPos = param.Find(L'=');
+ if (eqPos >= 0)
+ {
+ name = param.Left(eqPos);
+ value = param.Mid(eqPos + 1);
+ return;
+ }
+ for(int i = 0; i < param.Length(); i++)
+ {
+ wchar_t c = param[i];
+ if (c >= L'0' && c <= L'9')
+ {
+ name = param.Left(i);
+ value = param.Mid(i);
+ return;
+ }
+ }
+ name = param;
+}
+
+HRESULT CHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
+{
+ CProperty property;
+ if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0)
+ {
+ UInt32 dicSize;
+ RINOK(ParsePropDictionaryValue(value, dicSize));
+ if (name.CompareNoCase(L"D") == 0)
+ property.PropID = NCoderPropID::kDictionarySize;
+ else
+ property.PropID = NCoderPropID::kUsedMemorySize;
+ property.Value = dicSize;
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ else
+ {
+ int index = FindPropIdFromStringName(name);
+ if (index < 0)
+ return E_INVALIDARG;
+
+ const CNameToPropID &nameToPropID = g_NameToPropID[index];
+ property.PropID = nameToPropID.PropID;
+
+ NCOM::CPropVariant propValue;
+
+
+ if (nameToPropID.VarType == VT_BSTR)
+ propValue = value;
+ else
+ {
+ UInt32 number;
+ if (ParseStringToUInt32(value, number) == value.Length())
+ propValue = number;
+ else
+ propValue = value;
+ }
+
+ if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))
+ return E_INVALIDARG;
+
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
+{
+ UStringVector params;
+ SplitParams(srcString, params);
+ if (params.Size() > 0)
+ oneMethodInfo.MethodName = params[0];
+ for (int i = 1; i < params.Size(); i++)
+ {
+ const UString &param = params[i];
+ UString name, value;
+ SplitParam(param, name, value);
+ RINOK(SetParam(oneMethodInfo, name, value));
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetSolidSettings(const UString &s)
+{
+ UString s2 = s;
+ s2.MakeUpper();
+ if (s2.IsEmpty() || s2.Compare(L"ON") == 0)
+ {
+ InitSolid();
+ return S_OK;
+ }
+ if (s2.Compare(L"OFF") == 0)
+ {
+ _numSolidFiles = 1;
+ return S_OK;
+ }
+ for (int i = 0; i < s2.Length();)
+ {
+ const wchar_t *start = ((const wchar_t *)s2) + i;
+ const wchar_t *end;
+ UInt64 v = ConvertStringToUInt64(start, &end);
+ if (start == end)
+ {
+ if (s2[i++] != 'E')
+ return E_INVALIDARG;
+ _solidExtension = true;
+ continue;
+ }
+ i += (int)(end - start);
+ if (i == s2.Length())
+ return E_INVALIDARG;
+ wchar_t c = s2[i++];
+ switch(c)
+ {
+ case 'F':
+ if (v < 1)
+ v = 1;
+ _numSolidFiles = v;
+ break;
+ case 'B':
+ _numSolidBytes = v;
+ _numSolidBytesDefined = true;
+ break;
+ case 'K':
+ _numSolidBytes = (v << 10);
+ _numSolidBytesDefined = true;
+ break;
+ case 'M':
+ _numSolidBytes = (v << 20);
+ _numSolidBytesDefined = true;
+ break;
+ case 'G':
+ _numSolidBytes = (v << 30);
+ _numSolidBytesDefined = true;
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CHandler::SetSolidSettings(const PROPVARIANT &value)
+{
+ switch(value.vt)
+ {
+ case VT_EMPTY:
+ InitSolid();
+ return S_OK;
+ case VT_BSTR:
+ return SetSolidSettings(value.bstrVal);
+ default:
+ return E_INVALIDARG;
+ }
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ COM_TRY_BEGIN
+ _methods.Clear();
+ _binds.Clear();
+ Init();
+ #ifdef COMPRESS_MT
+ const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+ #endif
+
+ UInt32 mainDicSize = 0xFFFFFFFF;
+ UInt32 mainDicMethodIndex = 0xFFFFFFFF;
+
+ UInt32 minNumber = 0;
+
+ for (int i = 0; i < numProperties; i++)
+ {
+ UString name = names[i];
+ name.MakeUpper();
+ if (name.IsEmpty())
+ return E_INVALIDARG;
+
+ const PROPVARIANT &value = values[i];
+
+ if (name[0] == 'X')
+ {
+ name.Delete(0);
+ _level = 9;
+ RINOK(ParsePropValue(name, value, _level));
+ continue;
+ }
+
+ if (name[0] == 'B')
+ {
+ name.Delete(0);
+ CBind bind;
+ RINOK(GetBindInfo(name, bind));
+ _binds.Add(bind);
+ continue;
+ }
+
+ if (name[0] == L'S')
+ {
+ name.Delete(0);
+ if (name.IsEmpty())
+ {
+ RINOK(SetSolidSettings(value));
+ }
+ else
+ {
+ RINOK(SetSolidSettings(name));
+ }
+ continue;
+ }
+
+
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ UString realName = name.Mid(index);
+ if (index == 0)
+ {
+ if(name.Left(2).CompareNoCase(L"MT") == 0)
+ {
+ #ifdef COMPRESS_MT
+ RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
+ #endif
+ continue;
+ }
+ else if (name.CompareNoCase(L"RSFX") == 0)
+ {
+ RINOK(SetBoolProperty(_removeSfxBlock, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"F") == 0)
+ {
+ RINOK(SetBoolProperty(_autoFilter, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"HC") == 0)
+ {
+ RINOK(SetBoolProperty(_compressHeaders, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"HCF") == 0)
+ {
+ RINOK(SetBoolProperty(_compressHeadersFull, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"HE") == 0)
+ {
+ RINOK(SetBoolProperty(_encryptHeaders, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"TM") == 0)
+ {
+ RINOK(SetBoolProperty(WriteModified, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"TC") == 0)
+ {
+ RINOK(SetBoolProperty(WriteCreated, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"TA") == 0)
+ {
+ RINOK(SetBoolProperty(WriteAccessed, value));
+ continue;
+ }
+ else if (name.CompareNoCase(L"V") == 0)
+ {
+ RINOK(SetBoolProperty(_volumeMode, value));
+ continue;
+ }
+ number = 0;
+ }
+ if (number > 10000)
+ return E_FAIL;
+ if (number < minNumber)
+ return E_INVALIDARG;
+ number -= minNumber;
+ for(int j = _methods.Size(); j <= (int)number; j++)
+ {
+ COneMethodInfo oneMethodInfo;
+ _methods.Add(oneMethodInfo);
+ }
+
+ COneMethodInfo &oneMethodInfo = _methods[number];
+
+ if (realName.Length() == 0)
+ {
+ if (value.vt != VT_BSTR)
+ return E_INVALIDARG;
+
+ // oneMethodInfo.MethodName = UnicodeStringToMultiByte(UString(value.bstrVal));
+ RINOK(SetParams(oneMethodInfo, value.bstrVal));
+ }
+ else
+ {
+ CProperty property;
+ if (realName.Left(1).CompareNoCase(L"D") == 0)
+ {
+ UInt32 dicSize;
+ RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
+ property.PropID = NCoderPropID::kDictionarySize;
+ property.Value = dicSize;
+ oneMethodInfo.CoderProperties.Add(property);
+ if (number <= mainDicMethodIndex)
+ mainDicSize = dicSize;
+ }
+ else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
+ {
+ UInt32 dicSize;
+ RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
+ property.PropID = NCoderPropID::kUsedMemorySize;
+ property.Value = dicSize;
+ oneMethodInfo.CoderProperties.Add(property);
+ if (number <= mainDicMethodIndex)
+ mainDicSize = dicSize;
+ }
+ else
+ {
+ int index = FindPropIdFromStringName(realName);
+ if (index < 0)
+ return E_INVALIDARG;
+
+ const CNameToPropID &nameToPropID = g_NameToPropID[index];
+ property.PropID = nameToPropID.PropID;
+
+ if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
+ return E_INVALIDARG;
+
+ oneMethodInfo.CoderProperties.Add(property);
+ }
+ }
+ }
+
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zHeader.cpp b/CPP/7zip/Archive/7z/7zHeader.cpp
new file mode 100755
index 00000000..cff4d121
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHeader.cpp
@@ -0,0 +1,19 @@
+// 7z/Header.cpp
+
+#include "StdAfx.h"
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+Byte kSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C};
+Byte kFinishSignature[kSignatureSize] = {'7' + 1, 'z', 0xBC, 0xAF, 0x27, 0x1C + 1};
+
+class SignatureInitializer
+{
+public:
+ SignatureInitializer() { kSignature[0]--; kFinishSignature[0]--;};
+} g_SignatureInitializer;
+
+}}
+
diff --git a/CPP/7zip/Archive/7z/7zHeader.h b/CPP/7zip/Archive/7z/7zHeader.h
new file mode 100755
index 00000000..59bc7fe5
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zHeader.h
@@ -0,0 +1,96 @@
+// 7z/7zHeader.h
+
+#ifndef __7Z_HEADER_H
+#define __7Z_HEADER_H
+
+#include "7zMethodID.h"
+
+namespace NArchive {
+namespace N7z {
+
+const int kSignatureSize = 6;
+extern Byte kSignature[kSignatureSize];
+
+// #define _7Z_VOL
+// 7z-MultiVolume is not finished yet.
+// It can work already, but I still do not like some
+// things of that new multivolume format.
+// So please keep it commented.
+
+#ifdef _7Z_VOL
+extern Byte kFinishSignature[kSignatureSize];
+#endif
+
+struct CArchiveVersion
+{
+ Byte Major;
+ Byte Minor;
+};
+
+const Byte kMajorVersion = 0;
+
+struct CStartHeader
+{
+ UInt64 NextHeaderOffset;
+ UInt64 NextHeaderSize;
+ UInt32 NextHeaderCRC;
+};
+
+const UInt32 kStartHeaderSize = 20;
+
+#ifdef _7Z_VOL
+struct CFinishHeader: public CStartHeader
+{
+ UInt64 ArchiveStartOffset; // data offset from end if that struct
+ UInt64 AdditionalStartBlockSize; // start signature & start header size
+};
+
+const UInt32 kFinishHeaderSize = kStartHeaderSize + 16;
+#endif
+
+namespace NID
+{
+ enum EEnum
+ {
+ kEnd,
+
+ kHeader,
+
+ kArchiveProperties,
+
+ kAdditionalStreamsInfo,
+ kMainStreamsInfo,
+ kFilesInfo,
+
+ kPackInfo,
+ kUnPackInfo,
+ kSubStreamsInfo,
+
+ kSize,
+ kCRC,
+
+ kFolder,
+
+ kCodersUnPackSize,
+ kNumUnPackStream,
+
+ kEmptyStream,
+ kEmptyFile,
+ kAnti,
+
+ kName,
+ kCreationTime,
+ kLastAccessTime,
+ kLastWriteTime,
+ kWinAttributes,
+ kComment,
+
+ kEncodedHeader,
+
+ kStartPos
+ };
+}
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zIn.cpp b/CPP/7zip/Archive/7z/7zIn.cpp
new file mode 100755
index 00000000..53d78b1a
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zIn.cpp
@@ -0,0 +1,1335 @@
+// 7zIn.cpp
+
+#include "StdAfx.h"
+
+#include "7zIn.h"
+#include "7zMethods.h"
+#include "7zDecode.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Common/StreamUtils.h"
+#include "../../../Common/CRC.h"
+
+// define FORMAT_7Z_RECOVERY if you want to recover multivolume archives with empty StartHeader
+// #define FORMAT_7Z_RECOVERY
+
+namespace NArchive {
+namespace N7z {
+
+class CStreamSwitch
+{
+ CInArchive *_archive;
+ bool _needRemove;
+public:
+ CStreamSwitch(): _needRemove(false) {}
+ ~CStreamSwitch() { Remove(); }
+ void Remove();
+ void Set(CInArchive *archive, const Byte *data, size_t size);
+ void Set(CInArchive *archive, const CByteBuffer &byteBuffer);
+ HRESULT Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector);
+};
+
+void CStreamSwitch::Remove()
+{
+ if (_needRemove)
+ {
+ _archive->DeleteByteStream();
+ _needRemove = false;
+ }
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const Byte *data, size_t size)
+{
+ Remove();
+ _archive = archive;
+ _archive->AddByteStream(data, size);
+ _needRemove = true;
+}
+
+void CStreamSwitch::Set(CInArchive *archive, const CByteBuffer &byteBuffer)
+{
+ Set(archive, byteBuffer, byteBuffer.GetCapacity());
+}
+
+HRESULT CStreamSwitch::Set(CInArchive *archive, const CObjectVector<CByteBuffer> *dataVector)
+{
+ Remove();
+ Byte external;
+ RINOK(archive->ReadByte(external));
+ if (external != 0)
+ {
+ CNum dataIndex;
+ RINOK(archive->ReadNum(dataIndex));
+ Set(archive, (*dataVector)[dataIndex]);
+ }
+ return S_OK;
+}
+
+
+CInArchiveException::CInArchiveException(CCauseType cause):
+ Cause(cause)
+{}
+
+HRESULT CInArchive::ReadDirect(IInStream *stream, void *data, UInt32 size,
+ UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = ReadStream(stream, data, size, &realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ _position += realProcessedSize;
+ return result;
+}
+
+HRESULT CInArchive::ReadDirect(void *data, UInt32 size, UInt32 *processedSize)
+{
+ return ReadDirect(_stream, data, size, processedSize);
+}
+
+HRESULT CInArchive::SafeReadDirect(void *data, UInt32 size)
+{
+ UInt32 realProcessedSize;
+ RINOK(ReadDirect(data, size, &realProcessedSize));
+ if (realProcessedSize != size)
+ throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
+ return S_OK;
+}
+
+HRESULT CInArchive::SafeReadDirectByte(Byte &b)
+{
+ return SafeReadDirect(&b, 1);
+}
+
+HRESULT CInArchive::SafeReadDirectUInt32(UInt32 &value)
+{
+ value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(b));
+ value |= (UInt32(b) << (8 * i));
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::SafeReadDirectUInt64(UInt64 &value)
+{
+ value = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ Byte b;
+ RINOK(SafeReadDirectByte(b));
+ value |= (UInt64(b) << (8 * i));
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadNumber(UInt64 &value)
+{
+ Byte firstByte;
+ RINOK(ReadByte(firstByte));
+ Byte mask = 0x80;
+ value = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ if ((firstByte & mask) == 0)
+ {
+ UInt64 highPart = firstByte & (mask - 1);
+ value += (highPart << (i * 8));
+ return S_OK;
+ }
+ Byte b;
+ RINOK(ReadByte(b));
+ value |= (UInt64(b) << (8 * i));
+ mask >>= 1;
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadNum(CNum &value)
+{
+ UInt64 value64;
+ RINOK(ReadNumber(value64));
+ if (value64 > kNumMax)
+ return E_FAIL;
+ value = (CNum)value64;
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadUInt32(UInt32 &value)
+{
+ value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(ReadByte(b));
+ value |= (UInt32(b) << (8 * i));
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadUInt64(UInt64 &value)
+{
+ value = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ Byte b;
+ RINOK(ReadByte(b));
+ value |= (UInt64(b) << (8 * i));
+ }
+ return S_OK;
+}
+
+static inline bool TestSignatureCandidate(const void *testBytes)
+{
+ for (int i = 0; i < kSignatureSize; i++)
+ if (((const Byte *)testBytes)[i] != kSignature[i])
+ return false;
+ return true;
+}
+
+#ifdef _7Z_VOL
+static inline bool TestFinishSignatureCandidate(const void *testBytes)
+{
+ for (int i = 0; i < kSignatureSize; i++)
+ if (((const Byte *)testBytes)[i] != kFinishSignature[i])
+ return false;
+ return true;
+}
+#endif
+
+HRESULT CInArchive::FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ _position = _arhiveBeginStreamPosition;
+ RINOK(stream->Seek(_arhiveBeginStreamPosition, STREAM_SEEK_SET, NULL));
+
+ Byte signature[kSignatureSize];
+ UInt32 processedSize;
+ RINOK(ReadDirect(stream, signature, kSignatureSize, &processedSize));
+ if(processedSize != kSignatureSize)
+ return S_FALSE;
+ if (TestSignatureCandidate(signature))
+ return S_OK;
+
+ CByteBuffer byteBuffer;
+ const UInt32 kBufferSize = (1 << 16);
+ byteBuffer.SetCapacity(kBufferSize);
+ Byte *buffer = byteBuffer;
+ UInt32 numPrevBytes = kSignatureSize - 1;
+ memmove(buffer, signature + 1, numPrevBytes);
+ UInt64 curTestPos = _arhiveBeginStreamPosition + 1;
+ for (;;)
+ {
+ if (searchHeaderSizeLimit != NULL)
+ if (curTestPos - _arhiveBeginStreamPosition > *searchHeaderSizeLimit)
+ break;
+ UInt32 numReadBytes = kBufferSize - numPrevBytes;
+ RINOK(ReadDirect(stream, buffer + numPrevBytes, numReadBytes, &processedSize));
+ UInt32 numBytesInBuffer = numPrevBytes + processedSize;
+ if (numBytesInBuffer < kSignatureSize)
+ break;
+ UInt32 numTests = numBytesInBuffer - kSignatureSize + 1;
+ for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
+ {
+ if (TestSignatureCandidate(buffer + pos))
+ {
+ _arhiveBeginStreamPosition = curTestPos;
+ _position = curTestPos + kSignatureSize;
+ return stream->Seek(_position, STREAM_SEEK_SET, NULL);
+ }
+ }
+ numPrevBytes = numBytesInBuffer - numTests;
+ memmove(buffer, buffer + numTests, numPrevBytes);
+ }
+ return S_FALSE;
+}
+
+// Out: _position must point to end of signature
+
+#ifdef _7Z_VOL
+HRESULT CInArchive::FindFinishSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &_position));
+ if (_position < kSignatureSize)
+ return S_FALSE;
+
+ CByteBuffer byteBuffer;
+ const UInt32 kBufferSize = (1 << 18);
+ byteBuffer.SetCapacity(kBufferSize);
+ Byte *buffer = byteBuffer;
+ UInt32 numPrevBytes = 0;
+ UInt64 limitPos = 0;
+ if (searchHeaderSizeLimit != NULL)
+ if (*searchHeaderSizeLimit < _position)
+ limitPos = _position - *searchHeaderSizeLimit;
+
+ while(_position >= limitPos)
+ {
+ UInt32 numReadBytes = kBufferSize - numPrevBytes;
+ if (numReadBytes > _position)
+ numReadBytes = (UInt32)_position;
+ UInt32 numBytesInBuffer = numPrevBytes + numReadBytes;
+ if (numBytesInBuffer < kSignatureSize)
+ return S_FALSE;
+ _position -= numReadBytes;
+ RINOK(stream->Seek(_position, STREAM_SEEK_SET, &_position));
+ UInt32 startPos = kBufferSize - numBytesInBuffer;
+ UInt32 processedSize;
+ RINOK(ReadDirect(stream, buffer + startPos, numReadBytes, &processedSize));
+ if (processedSize != numReadBytes)
+ return S_FALSE;
+ _position -= processedSize;
+ for(UInt32 pos = kBufferSize; pos >= startPos + kSignatureSize; pos--)
+ {
+ if (TestFinishSignatureCandidate(buffer + pos - kSignatureSize))
+ {
+ _position += pos - startPos;
+ return stream->Seek(_position, STREAM_SEEK_SET, NULL);
+ }
+ }
+ numPrevBytes = kSignatureSize - 1;
+ memmove(buffer + kBufferSize - numPrevBytes, buffer + startPos + 1, numPrevBytes);
+ }
+ return S_FALSE;
+}
+#endif
+
+// S_FALSE means that file is not archive
+HRESULT CInArchive::Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
+{
+ Close();
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_arhiveBeginStreamPosition))
+ _position = _arhiveBeginStreamPosition;
+ #ifdef _7Z_VOL
+ HRESULT result = FindFinishSignature(stream, searchHeaderSizeLimit);
+ if (result == S_OK)
+ _finishSignature = true;
+ else
+ {
+ if (result != S_FALSE)
+ return result;
+ _finishSignature = false;
+ RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
+ }
+ #else
+ RINOK(FindAndReadSignature(stream, searchHeaderSizeLimit));
+ #endif
+ _stream = stream;
+ return S_OK;
+}
+
+void CInArchive::Close()
+{
+ _stream.Release();
+}
+
+HRESULT CInArchive::SkeepData(UInt64 size)
+{
+ for (UInt64 i = 0; i < size; i++)
+ {
+ Byte temp;
+ RINOK(ReadByte(temp));
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::SkeepData()
+{
+ UInt64 size;
+ RINOK(ReadNumber(size));
+ return SkeepData(size);
+}
+
+HRESULT CInArchive::ReadArchiveProperties(CInArchiveInfo & /* archiveInfo */)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(ReadID(type));
+ if (type == NID::kEnd)
+ break;
+ SkeepData();
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::GetNextFolderItem(CFolder &folder)
+{
+ CNum numCoders;
+ RINOK(ReadNum(numCoders));
+
+ folder.Coders.Clear();
+ folder.Coders.Reserve((int)numCoders);
+ CNum numInStreams = 0;
+ CNum numOutStreams = 0;
+ CNum i;
+ for (i = 0; i < numCoders; i++)
+ {
+ folder.Coders.Add(CCoderInfo());
+ CCoderInfo &coder = folder.Coders.Back();
+
+ for (;;)
+ {
+ coder.AltCoders.Add(CAltCoderInfo());
+ CAltCoderInfo &altCoder = coder.AltCoders.Back();
+ Byte mainByte = 0;
+ RINOK(ReadByte(mainByte));
+ altCoder.MethodID.IDSize = (Byte)(mainByte & 0xF);
+ RINOK(ReadBytes(altCoder.MethodID.ID, altCoder.MethodID.IDSize));
+ if ((mainByte & 0x10) != 0)
+ {
+ RINOK(ReadNum(coder.NumInStreams));
+ RINOK(ReadNum(coder.NumOutStreams));
+ }
+ else
+ {
+ coder.NumInStreams = 1;
+ coder.NumOutStreams = 1;
+ }
+ if ((mainByte & 0x20) != 0)
+ {
+ CNum propertiesSize = 0;
+ RINOK(ReadNum(propertiesSize));
+ altCoder.Properties.SetCapacity((size_t)propertiesSize);
+ RINOK(ReadBytes((Byte *)altCoder.Properties, (size_t)propertiesSize));
+ }
+ if ((mainByte & 0x80) == 0)
+ break;
+ }
+ numInStreams += coder.NumInStreams;
+ numOutStreams += coder.NumOutStreams;
+ }
+
+ CNum numBindPairs;
+ // RINOK(ReadNumber(numBindPairs));
+ numBindPairs = numOutStreams - 1;
+ folder.BindPairs.Clear();
+ folder.BindPairs.Reserve(numBindPairs);
+ for (i = 0; i < numBindPairs; i++)
+ {
+ CBindPair bindPair;
+ RINOK(ReadNum(bindPair.InIndex));
+ RINOK(ReadNum(bindPair.OutIndex));
+ folder.BindPairs.Add(bindPair);
+ }
+
+ CNum numPackedStreams = numInStreams - numBindPairs;
+ folder.PackStreams.Reserve(numPackedStreams);
+ if (numPackedStreams == 1)
+ {
+ for (CNum j = 0; j < numInStreams; j++)
+ if (folder.FindBindPairForInStream(j) < 0)
+ {
+ folder.PackStreams.Add(j);
+ break;
+ }
+ }
+ else
+ for(i = 0; i < numPackedStreams; i++)
+ {
+ CNum packStreamInfo;
+ RINOK(ReadNum(packStreamInfo));
+ folder.PackStreams.Add(packStreamInfo);
+ }
+
+ return S_OK;
+}
+
+HRESULT CInArchive::WaitAttribute(UInt64 attribute)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(ReadID(type));
+ if (type == attribute)
+ return S_OK;
+ if (type == NID::kEnd)
+ return S_FALSE;
+ RINOK(SkeepData());
+ }
+}
+
+HRESULT CInArchive::ReadHashDigests(int numItems,
+ CRecordVector<bool> &digestsDefined,
+ CRecordVector<UInt32> &digests)
+{
+ RINOK(ReadBoolVector2(numItems, digestsDefined));
+ digests.Clear();
+ digests.Reserve(numItems);
+ for(int i = 0; i < numItems; i++)
+ {
+ UInt32 crc = 0;
+ if (digestsDefined[i])
+ RINOK(ReadUInt32(crc));
+ digests.Add(crc);
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadPackInfo(
+ UInt64 &dataOffset,
+ CRecordVector<UInt64> &packSizes,
+ CRecordVector<bool> &packCRCsDefined,
+ CRecordVector<UInt32> &packCRCs)
+{
+ RINOK(ReadNumber(dataOffset));
+ CNum numPackStreams;
+ RINOK(ReadNum(numPackStreams));
+
+ RINOK(WaitAttribute(NID::kSize));
+ packSizes.Clear();
+ packSizes.Reserve(numPackStreams);
+ for(CNum i = 0; i < numPackStreams; i++)
+ {
+ UInt64 size;
+ RINOK(ReadNumber(size));
+ packSizes.Add(size);
+ }
+
+ UInt64 type;
+ for (;;)
+ {
+ RINOK(ReadID(type));
+ if (type == NID::kEnd)
+ break;
+ if (type == NID::kCRC)
+ {
+ RINOK(ReadHashDigests(numPackStreams, packCRCsDefined, packCRCs));
+ continue;
+ }
+ RINOK(SkeepData());
+ }
+ if (packCRCsDefined.IsEmpty())
+ {
+ packCRCsDefined.Reserve(numPackStreams);
+ packCRCsDefined.Clear();
+ packCRCs.Reserve(numPackStreams);
+ packCRCs.Clear();
+ for(CNum i = 0; i < numPackStreams; i++)
+ {
+ packCRCsDefined.Add(false);
+ packCRCs.Add(0);
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadUnPackInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ CObjectVector<CFolder> &folders)
+{
+ RINOK(WaitAttribute(NID::kFolder));
+ CNum numFolders;
+ RINOK(ReadNum(numFolders));
+
+ {
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, dataVector));
+ folders.Clear();
+ folders.Reserve((UInt32)numFolders);
+ for(CNum i = 0; i < numFolders; i++)
+ {
+ folders.Add(CFolder());
+ RINOK(GetNextFolderItem(folders.Back()));
+ }
+ }
+
+ RINOK(WaitAttribute(NID::kCodersUnPackSize));
+
+ CNum i;
+ for(i = 0; i < numFolders; i++)
+ {
+ CFolder &folder = folders[i];
+ CNum numOutStreams = folder.GetNumOutStreams();
+ folder.UnPackSizes.Reserve(numOutStreams);
+ for(CNum j = 0; j < numOutStreams; j++)
+ {
+ UInt64 unPackSize;
+ RINOK(ReadNumber(unPackSize));
+ folder.UnPackSizes.Add(unPackSize);
+ }
+ }
+
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(ReadID(type));
+ if (type == NID::kEnd)
+ return S_OK;
+ if (type == NID::kCRC)
+ {
+ CRecordVector<bool> crcsDefined;
+ CRecordVector<UInt32> crcs;
+ RINOK(ReadHashDigests(numFolders, crcsDefined, crcs));
+ for(i = 0; i < numFolders; i++)
+ {
+ CFolder &folder = folders[i];
+ folder.UnPackCRCDefined = crcsDefined[i];
+ folder.UnPackCRC = crcs[i];
+ }
+ continue;
+ }
+ RINOK(SkeepData());
+ }
+}
+
+HRESULT CInArchive::ReadSubStreamsInfo(
+ const CObjectVector<CFolder> &folders,
+ CRecordVector<CNum> &numUnPackStreamsInFolders,
+ CRecordVector<UInt64> &unPackSizes,
+ CRecordVector<bool> &digestsDefined,
+ CRecordVector<UInt32> &digests)
+{
+ numUnPackStreamsInFolders.Clear();
+ numUnPackStreamsInFolders.Reserve(folders.Size());
+ UInt64 type;
+ for (;;)
+ {
+ RINOK(ReadID(type));
+ if (type == NID::kNumUnPackStream)
+ {
+ for(int i = 0; i < folders.Size(); i++)
+ {
+ CNum value;
+ RINOK(ReadNum(value));
+ numUnPackStreamsInFolders.Add(value);
+ }
+ continue;
+ }
+ if (type == NID::kCRC || type == NID::kSize)
+ break;
+ if (type == NID::kEnd)
+ break;
+ RINOK(SkeepData());
+ }
+
+ if (numUnPackStreamsInFolders.IsEmpty())
+ for(int i = 0; i < folders.Size(); i++)
+ numUnPackStreamsInFolders.Add(1);
+
+ int i;
+ for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+ {
+ // v3.13 incorrectly worked with empty folders
+ // v4.07: we check that folder is empty
+ CNum numSubstreams = numUnPackStreamsInFolders[i];
+ if (numSubstreams == 0)
+ continue;
+ UInt64 sum = 0;
+ for (CNum j = 1; j < numSubstreams; j++)
+ {
+ UInt64 size;
+ if (type == NID::kSize)
+ {
+ RINOK(ReadNumber(size));
+ unPackSizes.Add(size);
+ sum += size;
+ }
+ }
+ unPackSizes.Add(folders[i].GetUnPackSize() - sum);
+ }
+ if (type == NID::kSize)
+ {
+ RINOK(ReadID(type));
+ }
+
+ int numDigests = 0;
+ int numDigestsTotal = 0;
+ for(i = 0; i < folders.Size(); i++)
+ {
+ CNum numSubstreams = numUnPackStreamsInFolders[i];
+ if (numSubstreams != 1 || !folders[i].UnPackCRCDefined)
+ numDigests += numSubstreams;
+ numDigestsTotal += numSubstreams;
+ }
+
+ for (;;)
+ {
+ if (type == NID::kCRC)
+ {
+ CRecordVector<bool> digestsDefined2;
+ CRecordVector<UInt32> digests2;
+ RINOK(ReadHashDigests(numDigests, digestsDefined2, digests2));
+ int digestIndex = 0;
+ for (i = 0; i < folders.Size(); i++)
+ {
+ CNum numSubstreams = numUnPackStreamsInFolders[i];
+ const CFolder &folder = folders[i];
+ if (numSubstreams == 1 && folder.UnPackCRCDefined)
+ {
+ digestsDefined.Add(true);
+ digests.Add(folder.UnPackCRC);
+ }
+ else
+ for (CNum j = 0; j < numSubstreams; j++, digestIndex++)
+ {
+ digestsDefined.Add(digestsDefined2[digestIndex]);
+ digests.Add(digests2[digestIndex]);
+ }
+ }
+ }
+ else if (type == NID::kEnd)
+ {
+ if (digestsDefined.IsEmpty())
+ {
+ digestsDefined.Clear();
+ digests.Clear();
+ for (int i = 0; i < numDigestsTotal; i++)
+ {
+ digestsDefined.Add(false);
+ digests.Add(0);
+ }
+ }
+ return S_OK;
+ }
+ else
+ {
+ RINOK(SkeepData());
+ }
+ RINOK(ReadID(type));
+ }
+}
+
+HRESULT CInArchive::ReadStreamsInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ UInt64 &dataOffset,
+ CRecordVector<UInt64> &packSizes,
+ CRecordVector<bool> &packCRCsDefined,
+ CRecordVector<UInt32> &packCRCs,
+ CObjectVector<CFolder> &folders,
+ CRecordVector<CNum> &numUnPackStreamsInFolders,
+ CRecordVector<UInt64> &unPackSizes,
+ CRecordVector<bool> &digestsDefined,
+ CRecordVector<UInt32> &digests)
+{
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(ReadID(type));
+ switch(type)
+ {
+ case NID::kEnd:
+ return S_OK;
+ case NID::kPackInfo:
+ {
+ RINOK(ReadPackInfo(dataOffset, packSizes,
+ packCRCsDefined, packCRCs));
+ break;
+ }
+ case NID::kUnPackInfo:
+ {
+ RINOK(ReadUnPackInfo(dataVector, folders));
+ break;
+ }
+ case NID::kSubStreamsInfo:
+ {
+ RINOK(ReadSubStreamsInfo(folders, numUnPackStreamsInFolders,
+ unPackSizes, digestsDefined, digests));
+ break;
+ }
+ }
+ }
+}
+
+HRESULT CInArchive::ReadFileNames(CObjectVector<CFileItem> &files)
+{
+ for(int i = 0; i < files.Size(); i++)
+ {
+ UString &name = files[i].Name;
+ name.Empty();
+ for (;;)
+ {
+ wchar_t c;
+ RINOK(ReadWideCharLE(c));
+ if (c == L'\0')
+ break;
+ name += c;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadBoolVector(int numItems, CBoolVector &v)
+{
+ v.Clear();
+ v.Reserve(numItems);
+ Byte b = 0;
+ Byte mask = 0;
+ for(int i = 0; i < numItems; i++)
+ {
+ if (mask == 0)
+ {
+ RINOK(ReadByte(b));
+ mask = 0x80;
+ }
+ v.Add((b & mask) != 0);
+ mask >>= 1;
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadBoolVector2(int numItems, CBoolVector &v)
+{
+ Byte allAreDefined;
+ RINOK(ReadByte(allAreDefined));
+ if (allAreDefined == 0)
+ return ReadBoolVector(numItems, v);
+ v.Clear();
+ v.Reserve(numItems);
+ for (int i = 0; i < numItems; i++)
+ v.Add(true);
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadTime(const CObjectVector<CByteBuffer> &dataVector,
+ CObjectVector<CFileItem> &files, UInt64 type)
+{
+ CBoolVector boolVector;
+ RINOK(ReadBoolVector2(files.Size(), boolVector))
+
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+
+ for(int i = 0; i < files.Size(); i++)
+ {
+ CFileItem &file = files[i];
+ CArchiveFileTime fileTime;
+ fileTime.dwLowDateTime = 0;
+ fileTime.dwHighDateTime = 0;
+ bool defined = boolVector[i];
+ if (defined)
+ {
+ UInt32 low, high;
+ RINOK(ReadUInt32(low));
+ RINOK(ReadUInt32(high));
+ fileTime.dwLowDateTime = low;
+ fileTime.dwHighDateTime = high;
+ }
+ switch(type)
+ {
+ case NID::kCreationTime:
+ file.IsCreationTimeDefined = defined;
+ if (defined)
+ file.CreationTime = fileTime;
+ break;
+ case NID::kLastWriteTime:
+ file.IsLastWriteTimeDefined = defined;
+ if (defined)
+ file.LastWriteTime = fileTime;
+ break;
+ case NID::kLastAccessTime:
+ file.IsLastAccessTimeDefined = defined;
+ if (defined)
+ file.LastAccessTime = fileTime;
+ break;
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadAndDecodePackedStreams(UInt64 baseOffset,
+ UInt64 &dataOffset, CObjectVector<CByteBuffer> &dataVector
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ CRecordVector<UInt64> packSizes;
+ CRecordVector<bool> packCRCsDefined;
+ CRecordVector<UInt32> packCRCs;
+ CObjectVector<CFolder> folders;
+
+ CRecordVector<CNum> numUnPackStreamsInFolders;
+ CRecordVector<UInt64> unPackSizes;
+ CRecordVector<bool> digestsDefined;
+ CRecordVector<UInt32> digests;
+
+ RINOK(ReadStreamsInfo(NULL,
+ dataOffset,
+ packSizes,
+ packCRCsDefined,
+ packCRCs,
+ folders,
+ numUnPackStreamsInFolders,
+ unPackSizes,
+ digestsDefined,
+ digests));
+
+ // database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
+
+ CNum packIndex = 0;
+ CDecoder decoder(
+ #ifdef _ST_MODE
+ false
+ #else
+ true
+ #endif
+ );
+ UInt64 dataStartPos = baseOffset + dataOffset;
+ for(int i = 0; i < folders.Size(); i++)
+ {
+ const CFolder &folder = folders[i];
+ dataVector.Add(CByteBuffer());
+ CByteBuffer &data = dataVector.Back();
+ UInt64 unPackSize = folder.GetUnPackSize();
+ if (unPackSize > kNumMax)
+ return E_FAIL;
+ if (unPackSize > 0xFFFFFFFF)
+ return E_FAIL;
+ data.SetCapacity((size_t)unPackSize);
+
+ CSequentialOutStreamImp2 *outStreamSpec = new CSequentialOutStreamImp2;
+ CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
+ outStreamSpec->Init(data, (size_t)unPackSize);
+
+ HRESULT result = decoder.Decode(_stream, dataStartPos,
+ &packSizes[packIndex], folder, outStream, NULL
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ #ifdef COMPRESS_MT
+ , false, 1
+ #endif
+ );
+ RINOK(result);
+
+ if (folder.UnPackCRCDefined)
+ if (!CCRC::VerifyDigest(folder.UnPackCRC, data, (UInt32)unPackSize))
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+ for (int j = 0; j < folder.PackStreams.Size(); j++)
+ dataStartPos += packSizes[packIndex++];
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadHeader(CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ UInt64 type;
+ RINOK(ReadID(type));
+
+ if (type == NID::kArchiveProperties)
+ {
+ RINOK(ReadArchiveProperties(database.ArchiveInfo));
+ RINOK(ReadID(type));
+ }
+
+ CObjectVector<CByteBuffer> dataVector;
+
+ if (type == NID::kAdditionalStreamsInfo)
+ {
+ HRESULT result = ReadAndDecodePackedStreams(
+ database.ArchiveInfo.StartPositionAfterHeader,
+ database.ArchiveInfo.DataStartPosition2,
+ dataVector
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ RINOK(result);
+ database.ArchiveInfo.DataStartPosition2 += database.ArchiveInfo.StartPositionAfterHeader;
+ RINOK(ReadID(type));
+ }
+
+ CRecordVector<UInt64> unPackSizes;
+ CRecordVector<bool> digestsDefined;
+ CRecordVector<UInt32> digests;
+
+ if (type == NID::kMainStreamsInfo)
+ {
+ RINOK(ReadStreamsInfo(&dataVector,
+ database.ArchiveInfo.DataStartPosition,
+ database.PackSizes,
+ database.PackCRCsDefined,
+ database.PackCRCs,
+ database.Folders,
+ database.NumUnPackStreamsVector,
+ unPackSizes,
+ digestsDefined,
+ digests));
+ database.ArchiveInfo.DataStartPosition += database.ArchiveInfo.StartPositionAfterHeader;
+ RINOK(ReadID(type));
+ }
+ else
+ {
+ for(int i = 0; i < database.Folders.Size(); i++)
+ {
+ database.NumUnPackStreamsVector.Add(1);
+ CFolder &folder = database.Folders[i];
+ unPackSizes.Add(folder.GetUnPackSize());
+ digestsDefined.Add(folder.UnPackCRCDefined);
+ digests.Add(folder.UnPackCRC);
+ }
+ }
+
+ database.Files.Clear();
+
+ if (type == NID::kEnd)
+ return S_OK;
+ if (type != NID::kFilesInfo)
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+
+ CNum numFiles;
+ RINOK(ReadNum(numFiles));
+ database.Files.Reserve(numFiles);
+ CNum i;
+ for(i = 0; i < numFiles; i++)
+ database.Files.Add(CFileItem());
+
+ database.ArchiveInfo.FileInfoPopIDs.Add(NID::kSize);
+ if (!database.PackSizes.IsEmpty())
+ database.ArchiveInfo.FileInfoPopIDs.Add(NID::kPackInfo);
+ if (numFiles > 0 && !digests.IsEmpty())
+ database.ArchiveInfo.FileInfoPopIDs.Add(NID::kCRC);
+
+ CBoolVector emptyStreamVector;
+ emptyStreamVector.Reserve((int)numFiles);
+ for(i = 0; i < numFiles; i++)
+ emptyStreamVector.Add(false);
+ CBoolVector emptyFileVector;
+ CBoolVector antiFileVector;
+ CNum numEmptyStreams = 0;
+
+ // int sizePrev = -1;
+ // int posPrev = 0;
+
+ for (;;)
+ {
+ /*
+ if (sizePrev >= 0)
+ if (sizePrev != _inByteBack->GetProcessedSize() - posPrev)
+ throw 2;
+ */
+ UInt64 type;
+ RINOK(ReadID(type));
+ if (type == NID::kEnd)
+ break;
+ UInt64 size;
+ RINOK(ReadNumber(size));
+
+ // sizePrev = size;
+ // posPrev = _inByteBack->GetProcessedSize();
+
+ database.ArchiveInfo.FileInfoPopIDs.Add(type);
+ switch(type)
+ {
+ case NID::kName:
+ {
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+ RINOK(ReadFileNames(database.Files))
+ break;
+ }
+ case NID::kWinAttributes:
+ {
+ CBoolVector boolVector;
+ RINOK(ReadBoolVector2(database.Files.Size(), boolVector))
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = database.Files[i];
+ file.AreAttributesDefined = boolVector[i];
+ if (file.AreAttributesDefined)
+ {
+ RINOK(ReadUInt32(file.Attributes));
+ }
+ }
+ break;
+ }
+ case NID::kStartPos:
+ {
+ CBoolVector boolVector;
+ RINOK(ReadBoolVector2(database.Files.Size(), boolVector))
+ CStreamSwitch streamSwitch;
+ RINOK(streamSwitch.Set(this, &dataVector));
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = database.Files[i];
+ file.IsStartPosDefined = boolVector[i];
+ if (file.IsStartPosDefined)
+ {
+ RINOK(ReadUInt64(file.StartPos));
+ }
+ }
+ break;
+ }
+ case NID::kEmptyStream:
+ {
+ RINOK(ReadBoolVector(numFiles, emptyStreamVector))
+ for (i = 0; i < (CNum)emptyStreamVector.Size(); i++)
+ if (emptyStreamVector[i])
+ numEmptyStreams++;
+ emptyFileVector.Reserve(numEmptyStreams);
+ antiFileVector.Reserve(numEmptyStreams);
+ for (i = 0; i < numEmptyStreams; i++)
+ {
+ emptyFileVector.Add(false);
+ antiFileVector.Add(false);
+ }
+ break;
+ }
+ case NID::kEmptyFile:
+ {
+ RINOK(ReadBoolVector(numEmptyStreams, emptyFileVector))
+ break;
+ }
+ case NID::kAnti:
+ {
+ RINOK(ReadBoolVector(numEmptyStreams, antiFileVector))
+ break;
+ }
+ case NID::kCreationTime:
+ case NID::kLastWriteTime:
+ case NID::kLastAccessTime:
+ {
+ RINOK(ReadTime(dataVector, database.Files, type))
+ break;
+ }
+ default:
+ {
+ database.ArchiveInfo.FileInfoPopIDs.DeleteBack();
+ RINOK(SkeepData(size));
+ }
+ }
+ }
+
+ CNum emptyFileIndex = 0;
+ CNum sizeIndex = 0;
+ for(i = 0; i < numFiles; i++)
+ {
+ CFileItem &file = database.Files[i];
+ file.HasStream = !emptyStreamVector[i];
+ if(file.HasStream)
+ {
+ file.IsDirectory = false;
+ file.IsAnti = false;
+ file.UnPackSize = unPackSizes[sizeIndex];
+ file.FileCRC = digests[sizeIndex];
+ file.IsFileCRCDefined = digestsDefined[sizeIndex];
+ sizeIndex++;
+ }
+ else
+ {
+ file.IsDirectory = !emptyFileVector[emptyFileIndex];
+ file.IsAnti = antiFileVector[emptyFileIndex];
+ emptyFileIndex++;
+ file.UnPackSize = 0;
+ file.IsFileCRCDefined = false;
+ }
+ }
+ return S_OK;
+}
+
+
+void CArchiveDatabaseEx::FillFolderStartPackStream()
+{
+ FolderStartPackStreamIndex.Clear();
+ FolderStartPackStreamIndex.Reserve(Folders.Size());
+ CNum startPos = 0;
+ for(int i = 0; i < Folders.Size(); i++)
+ {
+ FolderStartPackStreamIndex.Add(startPos);
+ startPos += (CNum)Folders[i].PackStreams.Size();
+ }
+}
+
+void CArchiveDatabaseEx::FillStartPos()
+{
+ PackStreamStartPositions.Clear();
+ PackStreamStartPositions.Reserve(PackSizes.Size());
+ UInt64 startPos = 0;
+ for(int i = 0; i < PackSizes.Size(); i++)
+ {
+ PackStreamStartPositions.Add(startPos);
+ startPos += PackSizes[i];
+ }
+}
+
+void CArchiveDatabaseEx::FillFolderStartFileIndex()
+{
+ FolderStartFileIndex.Clear();
+ FolderStartFileIndex.Reserve(Folders.Size());
+ FileIndexToFolderIndexMap.Clear();
+ FileIndexToFolderIndexMap.Reserve(Files.Size());
+
+ int folderIndex = 0;
+ CNum indexInFolder = 0;
+ for (int i = 0; i < Files.Size(); i++)
+ {
+ const CFileItem &file = Files[i];
+ bool emptyStream = !file.HasStream;
+ if (emptyStream && indexInFolder == 0)
+ {
+ FileIndexToFolderIndexMap.Add(kNumNoIndex);
+ continue;
+ }
+ if (indexInFolder == 0)
+ {
+ // v3.13 incorrectly worked with empty folders
+ // v4.07: Loop for skipping empty folders
+ for (;;)
+ {
+ if (folderIndex >= Folders.Size())
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+ FolderStartFileIndex.Add(i); // check it
+ if (NumUnPackStreamsVector[folderIndex] != 0)
+ break;
+ folderIndex++;
+ }
+ }
+ FileIndexToFolderIndexMap.Add(folderIndex);
+ if (emptyStream)
+ continue;
+ indexInFolder++;
+ if (indexInFolder >= NumUnPackStreamsVector[folderIndex])
+ {
+ folderIndex++;
+ indexInFolder = 0;
+ }
+ }
+}
+
+HRESULT CInArchive::ReadDatabase(CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ )
+{
+ database.Clear();
+ database.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;
+
+
+ RINOK(SafeReadDirect(&database.ArchiveInfo.Version.Major, 1));
+ RINOK(SafeReadDirect(&database.ArchiveInfo.Version.Minor, 1));
+ if (database.ArchiveInfo.Version.Major != kMajorVersion)
+ throw CInArchiveException(CInArchiveException::kUnsupportedVersion);
+
+ #ifdef _7Z_VOL
+ if (_finishSignature)
+ {
+ RINOK(_stream->Seek(_position - (4 + kFinishHeaderSize) -
+ (kSignatureSize + 2), STREAM_SEEK_SET, &_position));
+ }
+ #endif
+
+ UInt32 crcFromArchive;
+ UInt64 nextHeaderOffset;
+ UInt64 nextHeaderSize;
+ UInt32 nextHeaderCRC;
+ CCRC crc;
+ RINOK(SafeReadDirectUInt32(crcFromArchive));
+ RINOK(SafeReadDirectUInt64(nextHeaderOffset));
+ RINOK(SafeReadDirectUInt64(nextHeaderSize));
+ RINOK(SafeReadDirectUInt32(nextHeaderCRC));
+
+ #ifdef FORMAT_7Z_RECOVERY
+ if (crcFromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
+ {
+ UInt64 cur, cur2;
+ RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &cur));
+ const int kCheckSize = 500;
+ Byte buf[kCheckSize];
+ RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));
+ int checkSize = kCheckSize;
+ if (cur2 - cur < kCheckSize)
+ checkSize = (int)(cur2 - cur);
+ RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));
+
+ UInt32 realProcessedSize;
+ RINOK(ReadDirect(buf, (UInt32)kCheckSize, &realProcessedSize));
+
+ int i;
+ for (i = (int)realProcessedSize - 2; i >= 0; i--)
+ if (buf[i] == 0x17 && buf[i + 1] == 0x6 || buf[i] == 0x01 && buf[i + 1] == 0x04)
+ break;
+ if (i < 0)
+ return S_FALSE;
+ nextHeaderSize = realProcessedSize - i;
+ nextHeaderOffset = cur2 - cur + i;
+ nextHeaderCRC = CCRC::CalculateDigest(buf + i, (size_t)nextHeaderSize);
+ RINOK(_stream->Seek(cur, STREAM_SEEK_SET, &_position));
+ }
+ #endif
+
+ crc.UpdateUInt64(nextHeaderOffset);
+ crc.UpdateUInt64(nextHeaderSize);
+ crc.UpdateUInt32(nextHeaderCRC);
+
+ #ifdef FORMAT_7Z_RECOVERY
+ crcFromArchive = crc.GetDigest();
+ #endif
+
+ #ifdef _7Z_VOL
+ UInt64 archiveStartOffset; // data offset from end if that struct
+ UInt64 additionalStartBlockSize; // start signature & start header size
+ if (_finishSignature)
+ {
+ RINOK(SafeReadDirectUInt64(archiveStartOffset));
+ crc.UpdateUInt64(archiveStartOffset);
+ RINOK(SafeReadDirectUInt64(additionalStartBlockSize));
+ crc.UpdateUInt64(additionalStartBlockSize);
+ database.ArchiveInfo.StartPositionAfterHeader = _position + archiveStartOffset;
+ }
+ else
+ #endif
+ {
+ database.ArchiveInfo.StartPositionAfterHeader = _position;
+ }
+ if (crc.GetDigest() != crcFromArchive)
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+
+ if (nextHeaderSize == 0)
+ return S_OK;
+
+ if (nextHeaderSize >= 0xFFFFFFFF)
+ return E_FAIL;
+
+ RINOK(_stream->Seek(nextHeaderOffset, STREAM_SEEK_CUR, &_position));
+
+ CByteBuffer buffer2;
+ buffer2.SetCapacity((size_t)nextHeaderSize);
+ RINOK(SafeReadDirect(buffer2, (UInt32)nextHeaderSize));
+ if (!CCRC::VerifyDigest(nextHeaderCRC, buffer2, (UInt32)nextHeaderSize))
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+
+ CStreamSwitch streamSwitch;
+ streamSwitch.Set(this, buffer2);
+
+ CObjectVector<CByteBuffer> dataVector;
+
+ for (;;)
+ {
+ UInt64 type;
+ RINOK(ReadID(type));
+ if (type == NID::kHeader)
+ break;
+ if (type != NID::kEncodedHeader)
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+ HRESULT result = ReadAndDecodePackedStreams(
+ database.ArchiveInfo.StartPositionAfterHeader,
+ database.ArchiveInfo.DataStartPosition2,
+ dataVector
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+ RINOK(result);
+ if (dataVector.Size() == 0)
+ return S_OK;
+ if (dataVector.Size() > 1)
+ throw CInArchiveException(CInArchiveException::kIncorrectHeader);
+ streamSwitch.Remove();
+ streamSwitch.Set(this, dataVector.Front());
+ }
+
+ return ReadHeader(database
+ #ifndef _NO_CRYPTO
+ , getTextPassword
+ #endif
+ );
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zIn.h b/CPP/7zip/Archive/7z/7zIn.h
new file mode 100755
index 00000000..4f27aa75
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zIn.h
@@ -0,0 +1,288 @@
+// 7zIn.h
+
+#ifndef __7Z_IN_H
+#define __7Z_IN_H
+
+#include "../../IStream.h"
+#include "../../IPassword.h"
+#include "../../../Common/MyCom.h"
+#include "../../Common/InBuffer.h"
+
+#include "7zHeader.h"
+#include "7zItem.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CInArchiveException
+{
+public:
+ enum CCauseType
+ {
+ kUnsupportedVersion = 0,
+ kUnexpectedEndOfArchive = 0,
+ kIncorrectHeader,
+ } Cause;
+ CInArchiveException(CCauseType cause);
+};
+
+struct CInArchiveInfo
+{
+ CArchiveVersion Version;
+ UInt64 StartPosition;
+ UInt64 StartPositionAfterHeader;
+ UInt64 DataStartPosition;
+ UInt64 DataStartPosition2;
+ CRecordVector<UInt64> FileInfoPopIDs;
+ void Clear()
+ {
+ FileInfoPopIDs.Clear();
+ }
+};
+
+
+struct CArchiveDatabaseEx: public CArchiveDatabase
+{
+ CInArchiveInfo ArchiveInfo;
+ CRecordVector<UInt64> PackStreamStartPositions;
+ CRecordVector<CNum> FolderStartPackStreamIndex;
+ CRecordVector<CNum> FolderStartFileIndex;
+ CRecordVector<CNum> FileIndexToFolderIndexMap;
+
+ void Clear()
+ {
+ CArchiveDatabase::Clear();
+ ArchiveInfo.Clear();
+ PackStreamStartPositions.Clear();
+ FolderStartPackStreamIndex.Clear();
+ FolderStartFileIndex.Clear();
+ FileIndexToFolderIndexMap.Clear();
+ }
+
+ void FillFolderStartPackStream();
+ void FillStartPos();
+ void FillFolderStartFileIndex();
+
+ void Fill()
+ {
+ FillFolderStartPackStream();
+ FillStartPos();
+ FillFolderStartFileIndex();
+ }
+
+ UInt64 GetFolderStreamPos(int folderIndex, int indexInFolder) const
+ {
+ return ArchiveInfo.DataStartPosition +
+ PackStreamStartPositions[FolderStartPackStreamIndex[folderIndex] +
+ indexInFolder];
+ }
+
+ UInt64 GetFolderFullPackSize(int folderIndex) const
+ {
+ CNum packStreamIndex = FolderStartPackStreamIndex[folderIndex];
+ const CFolder &folder = Folders[folderIndex];
+ UInt64 size = 0;
+ for (int i = 0; i < folder.PackStreams.Size(); i++)
+ size += PackSizes[packStreamIndex + i];
+ return size;
+ }
+
+ UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const
+ {
+ return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex];
+ }
+
+ UInt64 GetFilePackSize(CNum fileIndex) const
+ {
+ CNum folderIndex = FileIndexToFolderIndexMap[fileIndex];
+ if (folderIndex >= 0)
+ {
+ if (FolderStartFileIndex[folderIndex] == fileIndex)
+ return GetFolderFullPackSize(folderIndex);
+ }
+ return 0;
+ }
+};
+
+class CInByte2
+{
+ const Byte *_buffer;
+ size_t _size;
+ size_t _pos;
+public:
+ void Init(const Byte *buffer, size_t size)
+ {
+ _buffer = buffer;
+ _size = size;
+ _pos = 0;
+ }
+ bool ReadByte(Byte &b)
+ {
+ if(_pos >= _size)
+ return false;
+ b = _buffer[_pos++];
+ return true;
+ }
+ void ReadBytes(void *data, size_t size, size_t &processedSize)
+ {
+ for(processedSize = 0; processedSize < size && _pos < _size; processedSize++)
+ ((Byte *)data)[processedSize] = _buffer[_pos++];
+ }
+
+ bool ReadBytes(void *data, size_t size)
+ {
+ size_t processedSize;
+ ReadBytes(data, size, processedSize);
+ return (processedSize == size);
+ }
+
+ size_t GetProcessedSize() const { return _pos; }
+};
+
+class CStreamSwitch;
+class CInArchive
+{
+ friend class CStreamSwitch;
+
+ CMyComPtr<IInStream> _stream;
+ #ifdef _7Z_VOL
+ bool _finishSignature;
+ #endif
+
+ CObjectVector<CInByte2> _inByteVector;
+ CInByte2 *_inByteBack;
+
+ UInt64 _arhiveBeginStreamPosition;
+ UInt64 _position;
+
+ void AddByteStream(const Byte *buffer, size_t size)
+ {
+ _inByteVector.Add(CInByte2());
+ _inByteBack = &_inByteVector.Back();
+ _inByteBack->Init(buffer, size);
+ }
+
+ void DeleteByteStream()
+ {
+ _inByteVector.DeleteBack();
+ if (!_inByteVector.IsEmpty())
+ _inByteBack = &_inByteVector.Back();
+ }
+
+private:
+ HRESULT FindAndReadSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
+ #ifdef _7Z_VOL
+ HRESULT FindFinishSignature(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
+ #endif
+
+ HRESULT ReadFileNames(CObjectVector<CFileItem> &files);
+
+ HRESULT ReadDirect(IInStream *stream, void *data, UInt32 size,
+ UInt32 *processedSize);
+ HRESULT ReadDirect(void *data, UInt32 size, UInt32 *processedSize);
+ HRESULT SafeReadDirect(void *data, UInt32 size);
+ HRESULT SafeReadDirectByte(Byte &b);
+ HRESULT SafeReadDirectUInt32(UInt32 &value);
+ HRESULT SafeReadDirectUInt64(UInt64 &value);
+
+ HRESULT ReadBytes(void *data, size_t size)
+ {
+ if (!_inByteBack->ReadBytes(data, size))
+ return E_FAIL;
+ return S_OK;
+ }
+
+ HRESULT ReadByte(Byte &b)
+ {
+ if (!_inByteBack->ReadByte(b))
+ return E_FAIL;
+ return S_OK;
+ }
+
+ HRESULT ReadWideCharLE(wchar_t &c)
+ {
+ Byte b1 = 0;
+ if (!_inByteBack->ReadByte(b1))
+ return E_FAIL;
+ Byte b2 = 0;
+ if (!_inByteBack->ReadByte(b2))
+ return E_FAIL;
+ c = (wchar_t)(((wchar_t)(b2) << 8) + b1);
+ return S_OK;
+ }
+
+ HRESULT ReadNumber(UInt64 &value);
+ HRESULT ReadNum(CNum &value);
+ HRESULT ReadID(UInt64 &value) { return ReadNumber(value); }
+ HRESULT ReadUInt32(UInt32 &value);
+ HRESULT ReadUInt64(UInt64 &value);
+
+ HRESULT SkeepData(UInt64 size);
+ HRESULT SkeepData();
+ HRESULT WaitAttribute(UInt64 attribute);
+
+ HRESULT ReadArchiveProperties(CInArchiveInfo &archiveInfo);
+ HRESULT GetNextFolderItem(CFolder &itemInfo);
+ HRESULT ReadHashDigests(int numItems,
+ CRecordVector<bool> &digestsDefined, CRecordVector<UInt32> &digests);
+
+ HRESULT ReadPackInfo(
+ UInt64 &dataOffset,
+ CRecordVector<UInt64> &packSizes,
+ CRecordVector<bool> &packCRCsDefined,
+ CRecordVector<UInt32> &packCRCs);
+
+ HRESULT ReadUnPackInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ CObjectVector<CFolder> &folders);
+
+ HRESULT ReadSubStreamsInfo(
+ const CObjectVector<CFolder> &folders,
+ CRecordVector<CNum> &numUnPackStreamsInFolders,
+ CRecordVector<UInt64> &unPackSizes,
+ CRecordVector<bool> &digestsDefined,
+ CRecordVector<UInt32> &digests);
+
+ HRESULT ReadStreamsInfo(
+ const CObjectVector<CByteBuffer> *dataVector,
+ UInt64 &dataOffset,
+ CRecordVector<UInt64> &packSizes,
+ CRecordVector<bool> &packCRCsDefined,
+ CRecordVector<UInt32> &packCRCs,
+ CObjectVector<CFolder> &folders,
+ CRecordVector<CNum> &numUnPackStreamsInFolders,
+ CRecordVector<UInt64> &unPackSizes,
+ CRecordVector<bool> &digestsDefined,
+ CRecordVector<UInt32> &digests);
+
+
+ HRESULT GetNextFileItem(CFileItem &itemInfo);
+ HRESULT ReadBoolVector(int numItems, CBoolVector &v);
+ HRESULT ReadBoolVector2(int numItems, CBoolVector &v);
+ HRESULT ReadTime(const CObjectVector<CByteBuffer> &dataVector,
+ CObjectVector<CFileItem> &files, UInt64 type);
+ HRESULT ReadAndDecodePackedStreams(UInt64 baseOffset, UInt64 &dataOffset,
+ CObjectVector<CByteBuffer> &dataVector
+ #ifndef _NO_CRYPTO
+ , ICryptoGetTextPassword *getTextPassword
+ #endif
+ );
+ HRESULT ReadHeader(CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ ,ICryptoGetTextPassword *getTextPassword
+ #endif
+ );
+public:
+ HRESULT Open(IInStream *stream, const UInt64 *searchHeaderSizeLimit); // S_FALSE means is not archive
+ void Close();
+
+ HRESULT ReadDatabase(CArchiveDatabaseEx &database
+ #ifndef _NO_CRYPTO
+ ,ICryptoGetTextPassword *getTextPassword
+ #endif
+ );
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zItem.h b/CPP/7zip/Archive/7z/7zItem.h
new file mode 100755
index 00000000..08ea61f4
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zItem.h
@@ -0,0 +1,181 @@
+// 7zItem.h
+
+#ifndef __7Z_ITEM_H
+#define __7Z_ITEM_H
+
+#include "../../../Common/Buffer.h"
+#include "7zMethodID.h"
+#include "7zHeader.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CAltCoderInfo
+{
+ CMethodID MethodID;
+ CByteBuffer Properties;
+};
+
+typedef UInt32 CNum;
+const CNum kNumMax = 0x7FFFFFFF;
+const CNum kNumNoIndex = 0xFFFFFFFF;
+
+struct CCoderInfo
+{
+ CNum NumInStreams;
+ CNum NumOutStreams;
+ CObjectVector<CAltCoderInfo> AltCoders;
+ bool IsSimpleCoder() const { return (NumInStreams == 1) && (NumOutStreams == 1); }
+};
+
+struct CBindPair
+{
+ CNum InIndex;
+ CNum OutIndex;
+};
+
+struct CFolder
+{
+ CObjectVector<CCoderInfo> Coders;
+ CRecordVector<CBindPair> BindPairs;
+ CRecordVector<CNum> PackStreams;
+ CRecordVector<UInt64> UnPackSizes;
+ UInt32 UnPackCRC;
+ bool UnPackCRCDefined;
+
+ CFolder(): UnPackCRCDefined(false) {}
+
+ UInt64 GetUnPackSize() const // test it
+ {
+ if (UnPackSizes.IsEmpty())
+ return 0;
+ for (int i = UnPackSizes.Size() - 1; i >= 0; i--)
+ if (FindBindPairForOutStream(i) < 0)
+ return UnPackSizes[i];
+ throw 1;
+ }
+
+ CNum GetNumOutStreams() const
+ {
+ CNum result = 0;
+ for (int i = 0; i < Coders.Size(); i++)
+ result += Coders[i].NumOutStreams;
+ return result;
+ }
+
+ int FindBindPairForInStream(CNum inStreamIndex) const
+ {
+ for(int i = 0; i < BindPairs.Size(); i++)
+ if (BindPairs[i].InIndex == inStreamIndex)
+ return i;
+ return -1;
+ }
+ int FindBindPairForOutStream(CNum outStreamIndex) const
+ {
+ for(int i = 0; i < BindPairs.Size(); i++)
+ if (BindPairs[i].OutIndex == outStreamIndex)
+ return i;
+ return -1;
+ }
+ int FindPackStreamArrayIndex(CNum inStreamIndex) const
+ {
+ for(int i = 0; i < PackStreams.Size(); i++)
+ if (PackStreams[i] == inStreamIndex)
+ return i;
+ return -1;
+ }
+};
+
+typedef FILETIME CArchiveFileTime;
+
+class CFileItem
+{
+public:
+ CArchiveFileTime CreationTime;
+ CArchiveFileTime LastWriteTime;
+ CArchiveFileTime LastAccessTime;
+ UInt64 UnPackSize;
+ UInt64 StartPos;
+ UInt32 Attributes;
+ UInt32 FileCRC;
+ UString Name;
+
+ bool HasStream; // Test it !!! it means that there is
+ // stream in some folder. It can be empty stream
+ bool IsDirectory;
+ bool IsAnti;
+ bool IsFileCRCDefined;
+ bool AreAttributesDefined;
+ bool IsCreationTimeDefined;
+ bool IsLastWriteTimeDefined;
+ bool IsLastAccessTimeDefined;
+ bool IsStartPosDefined;
+
+ /*
+ const bool HasStream() const {
+ return !IsDirectory && !IsAnti && UnPackSize != 0; }
+ */
+ CFileItem():
+ HasStream(true),
+ IsDirectory(false),
+ IsAnti(false),
+ IsFileCRCDefined(false),
+ AreAttributesDefined(false),
+ IsCreationTimeDefined(false),
+ IsLastWriteTimeDefined(false),
+ IsLastAccessTimeDefined(false),
+ IsStartPosDefined(false)
+ {}
+ void SetAttributes(UInt32 attributes)
+ {
+ AreAttributesDefined = true;
+ Attributes = attributes;
+ }
+ void SetCreationTime(const CArchiveFileTime &creationTime)
+ {
+ IsCreationTimeDefined = true;
+ CreationTime = creationTime;
+ }
+ void SetLastWriteTime(const CArchiveFileTime &lastWriteTime)
+ {
+ IsLastWriteTimeDefined = true;
+ LastWriteTime = lastWriteTime;
+ }
+ void SetLastAccessTime(const CArchiveFileTime &lastAccessTime)
+ {
+ IsLastAccessTimeDefined = true;
+ LastAccessTime = lastAccessTime;
+ }
+};
+
+struct CArchiveDatabase
+{
+ CRecordVector<UInt64> PackSizes;
+ CRecordVector<bool> PackCRCsDefined;
+ CRecordVector<UInt32> PackCRCs;
+ CObjectVector<CFolder> Folders;
+ CRecordVector<CNum> NumUnPackStreamsVector;
+ CObjectVector<CFileItem> Files;
+ void Clear()
+ {
+ PackSizes.Clear();
+ PackCRCsDefined.Clear();
+ PackCRCs.Clear();
+ Folders.Clear();
+ NumUnPackStreamsVector.Clear();
+ Files.Clear();
+ }
+ bool IsEmpty() const
+ {
+ return (PackSizes.IsEmpty() &&
+ PackCRCsDefined.IsEmpty() &&
+ PackCRCs.IsEmpty() &&
+ Folders.IsEmpty() &&
+ NumUnPackStreamsVector.IsEmpty() &&
+ Files.IsEmpty());
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zMethodID.cpp b/CPP/7zip/Archive/7z/7zMethodID.cpp
new file mode 100755
index 00000000..0d45b732
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zMethodID.cpp
@@ -0,0 +1,76 @@
+// 7zMethodID.cpp
+
+#include "StdAfx.h"
+
+#include "7zMethodID.h"
+
+namespace NArchive {
+namespace N7z {
+
+static wchar_t GetHex(Byte value)
+{
+ return (wchar_t)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+static bool HexCharToInt(wchar_t value, Byte &result)
+{
+ if (value >= '0' && value <= '9')
+ result = (Byte)(value - '0');
+ else if (value >= 'a' && value <= 'f')
+ result = (Byte)(10 + value - 'a');
+ else if (value >= 'A' && value <= 'F')
+ result = (Byte)(10 + value - 'A');
+ else
+ return false;
+ return true;
+}
+
+static bool TwoHexCharsToInt(wchar_t valueHigh, wchar_t valueLow, Byte &result)
+{
+ Byte resultHigh, resultLow;
+ if (!HexCharToInt(valueHigh, resultHigh))
+ return false;
+ if (!HexCharToInt(valueLow, resultLow))
+ return false;
+ result = (Byte)((resultHigh << 4) + resultLow);
+ return true;
+}
+
+UString CMethodID::ConvertToString() const
+{
+ UString result;
+ for (int i = 0; i < IDSize; i++)
+ {
+ Byte b = ID[i];
+ result += GetHex((Byte)(b >> 4));
+ result += GetHex((Byte)(b & 0xF));
+ }
+ return result;
+}
+
+bool CMethodID::ConvertFromString(const UString &srcString)
+{
+ int length = srcString.Length();
+ if ((length & 1) != 0 || (length >> 1) > kMethodIDSize)
+ return false;
+ IDSize = (Byte)(length / 2);
+ UInt32 i;
+ for(i = 0; i < IDSize; i++)
+ if (!TwoHexCharsToInt(srcString[i * 2], srcString[i * 2 + 1], ID[i]))
+ return false;
+ for(; i < kMethodIDSize; i++)
+ ID[i] = 0;
+ return true;
+}
+
+bool operator==(const CMethodID &a1, const CMethodID &a2)
+{
+ if (a1.IDSize != a2.IDSize)
+ return false;
+ for (UInt32 i = 0; i < a1.IDSize; i++)
+ if (a1.ID[i] != a2.ID[i])
+ return false;
+ return true;
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zMethodID.h b/CPP/7zip/Archive/7z/7zMethodID.h
new file mode 100755
index 00000000..54561054
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zMethodID.h
@@ -0,0 +1,29 @@
+// 7zMethodID.h
+
+#ifndef __7Z_METHOD_ID_H
+#define __7Z_METHOD_ID_H
+
+#include "../../../Common/String.h"
+#include "../../../Common/Types.h"
+
+namespace NArchive {
+namespace N7z {
+
+const int kMethodIDSize = 15;
+
+struct CMethodID
+{
+ Byte ID[kMethodIDSize];
+ Byte IDSize;
+ UString ConvertToString() const;
+ bool ConvertFromString(const UString &srcString);
+};
+
+bool operator==(const CMethodID &a1, const CMethodID &a2);
+
+inline bool operator!=(const CMethodID &a1, const CMethodID &a2)
+ { return !(a1 == a2); }
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zMethods.cpp b/CPP/7zip/Archive/7z/7zMethods.cpp
new file mode 100755
index 00000000..19270aa4
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zMethods.cpp
@@ -0,0 +1,174 @@
+// 7zMethods.cpp
+
+#include "StdAfx.h"
+
+#include "7zMethods.h"
+
+#include "../../../Windows/FileFind.h"
+#include "../../../Windows/DLL.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Windows/Synchronization.h"
+
+#include "../../ICoder.h"
+#include "../Common/CodecsPath.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace N7z {
+
+static CObjectVector<CMethodInfo2> g_Methods;
+static bool g_Loaded = false;
+
+typedef UInt32 (WINAPI *GetNumberOfMethodsFunc)(UInt32 *numMethods);
+
+typedef UInt32 (WINAPI *GetMethodPropertyFunc)(
+ UInt32 index, PROPID propID, PROPVARIANT *value);
+
+static void Load(const CSysString &folderPrefix)
+{
+ NFile::NFind::CEnumerator enumerator(folderPrefix + CSysString(TEXT("*")));
+ NFile::NFind::CFileInfo fileInfo;
+ while (enumerator.Next(fileInfo))
+ {
+ if (fileInfo.IsDirectory())
+ continue;
+ CSysString filePath = folderPrefix + fileInfo.Name;
+ {
+ NDLL::CLibrary library;
+ if (!library.LoadEx(filePath, LOAD_LIBRARY_AS_DATAFILE))
+ continue;
+ }
+ NDLL::CLibrary library;
+ if (!library.Load(filePath))
+ continue;
+ GetMethodPropertyFunc getMethodProperty = (GetMethodPropertyFunc)
+ library.GetProcAddress("GetMethodProperty");
+ if (getMethodProperty == NULL)
+ continue;
+
+ UInt32 numMethods = 1;
+ GetNumberOfMethodsFunc getNumberOfMethodsFunc = (GetNumberOfMethodsFunc)
+ library.GetProcAddress("GetNumberOfMethods");
+ if (getNumberOfMethodsFunc != NULL)
+ if (getNumberOfMethodsFunc(&numMethods) != S_OK)
+ continue;
+
+ for(UInt32 i = 0; i < numMethods; i++)
+ {
+ CMethodInfo2 info;
+ info.FilePath = filePath;
+
+ NWindows::NCOM::CPropVariant propVariant;
+ if (getMethodProperty(i, NMethodPropID::kID, &propVariant) != S_OK)
+ continue;
+ if (propVariant.vt != VT_BSTR)
+ continue;
+ info.MethodID.IDSize = (Byte)SysStringByteLen(propVariant.bstrVal);
+ memmove(info.MethodID.ID, propVariant.bstrVal, info.MethodID.IDSize);
+ propVariant.Clear();
+
+ if (getMethodProperty(i, NMethodPropID::kName, &propVariant) != S_OK)
+ continue;
+ if (propVariant.vt == VT_EMPTY)
+ {
+ }
+ else if (propVariant.vt == VT_BSTR)
+ info.Name = propVariant.bstrVal;
+ else
+ continue;
+ propVariant.Clear();
+
+ if (getMethodProperty (i, NMethodPropID::kEncoder, &propVariant) != S_OK)
+ continue;
+ if (propVariant.vt == VT_EMPTY)
+ info.EncoderIsAssigned = false;
+ else if (propVariant.vt == VT_BSTR)
+ {
+ info.EncoderIsAssigned = true;
+ info.Encoder = *(const GUID *)propVariant.bstrVal;
+ }
+ else
+ continue;
+ propVariant.Clear();
+
+ if (getMethodProperty (i, NMethodPropID::kDecoder, &propVariant) != S_OK)
+ continue;
+ if (propVariant.vt == VT_EMPTY)
+ info.DecoderIsAssigned = false;
+ else if (propVariant.vt == VT_BSTR)
+ {
+ info.DecoderIsAssigned = true;
+ info.Decoder = *(const GUID *)propVariant.bstrVal;
+ }
+ else
+ continue;
+ propVariant.Clear();
+
+ if (getMethodProperty (i, NMethodPropID::kInStreams, &propVariant) != S_OK)
+ continue;
+ if (propVariant.vt == VT_EMPTY)
+ info.NumInStreams = 1;
+ else if (propVariant.vt == VT_UI4)
+ info.NumInStreams = propVariant.ulVal;
+ else
+ continue;
+ propVariant.Clear();
+
+ if (getMethodProperty (i, NMethodPropID::kOutStreams, &propVariant) != S_OK)
+ continue;
+ if (propVariant.vt == VT_EMPTY)
+ info.NumOutStreams = 1;
+ else if (propVariant.vt == VT_UI4)
+ info.NumOutStreams = propVariant.ulVal;
+ else
+ continue;
+ propVariant.Clear();
+
+ g_Methods.Add(info);
+ }
+ }
+}
+
+static NSynchronization::CCriticalSection g_CriticalSection;
+
+void LoadMethodMap()
+{
+ NSynchronization::CCriticalSectionLock lock(g_CriticalSection);
+ if (g_Loaded)
+ return;
+ g_Loaded = true;
+ Load(GetCodecsFolderPrefix());
+}
+
+bool GetMethodInfo(const CMethodID &methodID, CMethodInfo &methodInfo)
+{
+ for(int i = 0; i < g_Methods.Size(); i++)
+ {
+ const CMethodInfo2 &method = g_Methods[i];
+ if (method.MethodID == methodID)
+ {
+ methodInfo = (CMethodInfo)method;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GetMethodInfo(const UString &name, CMethodInfo2 &methodInfo)
+{
+ for(int i = 0; i < g_Methods.Size(); i++)
+ {
+ const CMethodInfo2 &method = g_Methods[i];
+ if (method.Name.CompareNoCase(name) == 0)
+ {
+ methodInfo = method;
+ return true;
+ }
+ }
+ return false;
+}
+
+}}
+
+
diff --git a/CPP/7zip/Archive/7z/7zMethods.h b/CPP/7zip/Archive/7z/7zMethods.h
new file mode 100755
index 00000000..231f3183
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zMethods.h
@@ -0,0 +1,36 @@
+// 7zMethods.h
+
+#ifndef __7Z_METHODS_H
+#define __7Z_METHODS_H
+
+#include "7zMethodID.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CMethodInfo
+{
+ UString Name;
+ bool EncoderIsAssigned;
+ bool DecoderIsAssigned;
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+ CLSID Encoder;
+ CLSID Decoder;
+ // UString Description;
+ CSysString FilePath;
+};
+
+struct CMethodInfo2: public CMethodInfo
+{
+ CMethodID MethodID;
+};
+
+void LoadMethodMap();
+bool GetMethodInfo(const CMethodID &methodID, CMethodInfo &methodInfo);
+bool GetMethodInfo(const UString &name, CMethodInfo2 &methodInfo);
+
+}}
+
+#endif
+
diff --git a/CPP/7zip/Archive/7z/7zOut.cpp b/CPP/7zip/Archive/7z/7zOut.cpp
new file mode 100755
index 00000000..5a81a0d5
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zOut.cpp
@@ -0,0 +1,1136 @@
+// 7zOut.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/AutoPtr.h"
+#include "../../Common/StreamObjects.h"
+
+#include "7zOut.h"
+
+static HRESULT WriteBytes(ISequentialOutStream *stream, const void *data, size_t size)
+{
+ while (size > 0)
+ {
+ UInt32 curSize = (UInt32)MyMin(size, (size_t)0xFFFFFFFF);
+ UInt32 processedSize;
+ RINOK(stream->Write(data, curSize, &processedSize));
+ if(processedSize == 0)
+ return E_FAIL;
+ data = (const void *)((const Byte *)data + processedSize);
+ size -= processedSize;
+ }
+ return S_OK;
+}
+
+namespace NArchive {
+namespace N7z {
+
+HRESULT COutArchive::WriteDirect(const void *data, UInt32 size)
+{
+ return ::WriteBytes(SeqStream, data, size);
+}
+
+HRESULT COutArchive::WriteDirectUInt32(UInt32 value)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ RINOK(WriteDirectByte((Byte)value));
+ value >>= 8;
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteDirectUInt64(UInt64 value)
+{
+ for (int i = 0; i < 8; i++)
+ {
+ RINOK(WriteDirectByte((Byte)value));
+ value >>= 8;
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteSignature()
+{
+ RINOK(WriteDirect(kSignature, kSignatureSize));
+ RINOK(WriteDirectByte(kMajorVersion));
+ return WriteDirectByte(2);
+}
+
+#ifdef _7Z_VOL
+HRESULT COutArchive::WriteFinishSignature()
+{
+ RINOK(WriteDirect(kFinishSignature, kSignatureSize));
+ CArchiveVersion av;
+ av.Major = kMajorVersion;
+ av.Minor = 2;
+ RINOK(WriteDirectByte(av.Major));
+ return WriteDirectByte(av.Minor);
+}
+#endif
+
+HRESULT COutArchive::WriteStartHeader(const CStartHeader &h)
+{
+ CCRC crc;
+ crc.UpdateUInt64(h.NextHeaderOffset);
+ crc.UpdateUInt64(h.NextHeaderSize);
+ crc.UpdateUInt32(h.NextHeaderCRC);
+ RINOK(WriteDirectUInt32(crc.GetDigest()));
+ RINOK(WriteDirectUInt64(h.NextHeaderOffset));
+ RINOK(WriteDirectUInt64(h.NextHeaderSize));
+ return WriteDirectUInt32(h.NextHeaderCRC);
+}
+
+#ifdef _7Z_VOL
+HRESULT COutArchive::WriteFinishHeader(const CFinishHeader &h)
+{
+ CCRC crc;
+ crc.UpdateUInt64(h.NextHeaderOffset);
+ crc.UpdateUInt64(h.NextHeaderSize);
+ crc.UpdateUInt32(h.NextHeaderCRC);
+ crc.UpdateUInt64(h.ArchiveStartOffset);
+ crc.UpdateUInt64(h.AdditionalStartBlockSize);
+ RINOK(WriteDirectUInt32(crc.GetDigest()));
+ RINOK(WriteDirectUInt64(h.NextHeaderOffset));
+ RINOK(WriteDirectUInt64(h.NextHeaderSize));
+ RINOK(WriteDirectUInt32(h.NextHeaderCRC));
+ RINOK(WriteDirectUInt64(h.ArchiveStartOffset));
+ return WriteDirectUInt64(h.AdditionalStartBlockSize);
+}
+#endif
+
+HRESULT COutArchive::Create(ISequentialOutStream *stream, bool endMarker)
+{
+ Close();
+ #ifdef _7Z_VOL
+ // endMarker = false;
+ _endMarker = endMarker;
+ #endif
+ SeqStream = stream;
+ if (!endMarker)
+ {
+ SeqStream.QueryInterface(IID_IOutStream, &Stream);
+ if (!Stream)
+ {
+ return E_NOTIMPL;
+ // endMarker = true;
+ }
+ }
+ #ifdef _7Z_VOL
+ if (endMarker)
+ {
+ /*
+ CStartHeader sh;
+ sh.NextHeaderOffset = (UInt32)(Int32)-1;
+ sh.NextHeaderSize = (UInt32)(Int32)-1;
+ sh.NextHeaderCRC = 0;
+ WriteStartHeader(sh);
+ */
+ }
+ else
+ #endif
+ {
+ if (!Stream)
+ return E_FAIL;
+ WriteSignature();
+ RINOK(Stream->Seek(0, STREAM_SEEK_CUR, &_prefixHeaderPos));
+ }
+ return S_OK;
+}
+
+void COutArchive::Close()
+{
+ SeqStream.Release();
+ Stream.Release();
+}
+
+HRESULT COutArchive::SkeepPrefixArchiveHeader()
+{
+ #ifdef _7Z_VOL
+ if (_endMarker)
+ return S_OK;
+ #endif
+ return Stream->Seek(24, STREAM_SEEK_CUR, NULL);
+}
+
+HRESULT COutArchive::WriteBytes(const void *data, size_t size)
+{
+ if (_mainMode)
+ {
+ if (_dynamicMode)
+ _dynamicBuffer.Write(data, size);
+ else
+ _outByte.WriteBytes(data, size);
+ _crc.Update(data, size);
+ }
+ else
+ {
+ if (_countMode)
+ _countSize += size;
+ else
+ RINOK(_outByte2.Write(data, size));
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteBytes(const CByteBuffer &data)
+{
+ return WriteBytes(data, data.GetCapacity());
+}
+
+HRESULT COutArchive::WriteByte(Byte b)
+{
+ return WriteBytes(&b, 1);
+}
+
+HRESULT COutArchive::WriteUInt32(UInt32 value)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ RINOK(WriteByte((Byte)value));
+ value >>= 8;
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteNumber(UInt64 value)
+{
+ Byte firstByte = 0;
+ Byte mask = 0x80;
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ if (value < ((UInt64(1) << ( 7 * (i + 1)))))
+ {
+ firstByte |= Byte(value >> (8 * i));
+ break;
+ }
+ firstByte |= mask;
+ mask >>= 1;
+ }
+ RINOK(WriteByte(firstByte));
+ for (;i > 0; i--)
+ {
+ RINOK(WriteByte((Byte)value));
+ value >>= 8;
+ }
+ return S_OK;
+}
+
+static UInt32 GetBigNumberSize(UInt64 value)
+{
+ int i;
+ for (i = 0; i < 8; i++)
+ if (value < ((UInt64(1) << ( 7 * (i + 1)))))
+ break;
+ return 1 + i;
+}
+
+#ifdef _7Z_VOL
+UInt32 COutArchive::GetVolHeadersSize(UInt64 dataSize, int nameLength, bool props)
+{
+ UInt32 result = GetBigNumberSize(dataSize) * 2 + 41;
+ if (nameLength != 0)
+ {
+ nameLength = (nameLength + 1) * 2;
+ result += nameLength + GetBigNumberSize(nameLength) + 2;
+ }
+ if (props)
+ {
+ result += 20;
+ }
+ if (result >= 128)
+ result++;
+ result += kSignatureSize + 2 + kFinishHeaderSize;
+ return result;
+}
+
+UInt64 COutArchive::GetVolPureSize(UInt64 volSize, int nameLength, bool props)
+{
+ UInt32 headersSizeBase = COutArchive::GetVolHeadersSize(1, nameLength, props);
+ int testSize;
+ if (volSize > headersSizeBase)
+ testSize = volSize - headersSizeBase;
+ else
+ testSize = 1;
+ UInt32 headersSize = COutArchive::GetVolHeadersSize(testSize, nameLength, props);
+ UInt64 pureSize = 1;
+ if (volSize > headersSize)
+ pureSize = volSize - headersSize;
+ return pureSize;
+}
+#endif
+
+HRESULT COutArchive::WriteFolder(const CFolder &folder)
+{
+ RINOK(WriteNumber(folder.Coders.Size()));
+ int i;
+ for (i = 0; i < folder.Coders.Size(); i++)
+ {
+ const CCoderInfo &coder = folder.Coders[i];
+ for (int j = 0; j < coder.AltCoders.Size(); j++)
+ {
+ const CAltCoderInfo &altCoder = coder.AltCoders[j];
+ size_t propertiesSize = altCoder.Properties.GetCapacity();
+
+ Byte b;
+ b = (Byte)(altCoder.MethodID.IDSize & 0xF);
+ bool isComplex = !coder.IsSimpleCoder();
+ b |= (isComplex ? 0x10 : 0);
+ b |= ((propertiesSize != 0) ? 0x20 : 0 );
+ b |= ((j == coder.AltCoders.Size() - 1) ? 0 : 0x80 );
+ RINOK(WriteByte(b));
+ RINOK(WriteBytes(altCoder.MethodID.ID, altCoder.MethodID.IDSize));
+ if (isComplex)
+ {
+ RINOK(WriteNumber(coder.NumInStreams));
+ RINOK(WriteNumber(coder.NumOutStreams));
+ }
+ if (propertiesSize == 0)
+ continue;
+ RINOK(WriteNumber(propertiesSize));
+ RINOK(WriteBytes(altCoder.Properties, propertiesSize));
+ }
+ }
+ for (i = 0; i < folder.BindPairs.Size(); i++)
+ {
+ const CBindPair &bindPair = folder.BindPairs[i];
+ RINOK(WriteNumber(bindPair.InIndex));
+ RINOK(WriteNumber(bindPair.OutIndex));
+ }
+ if (folder.PackStreams.Size() > 1)
+ for (i = 0; i < folder.PackStreams.Size(); i++)
+ {
+ RINOK(WriteNumber(folder.PackStreams[i]));
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteBoolVector(const CBoolVector &boolVector)
+{
+ Byte b = 0;
+ Byte mask = 0x80;
+ for(int i = 0; i < boolVector.Size(); i++)
+ {
+ if (boolVector[i])
+ b |= mask;
+ mask >>= 1;
+ if (mask == 0)
+ {
+ RINOK(WriteByte(b));
+ mask = 0x80;
+ b = 0;
+ }
+ }
+ if (mask != 0x80)
+ {
+ RINOK(WriteByte(b));
+ }
+ return S_OK;
+}
+
+
+HRESULT COutArchive::WriteHashDigests(
+ const CRecordVector<bool> &digestsDefined,
+ const CRecordVector<UInt32> &digests)
+{
+ int numDefined = 0;
+ int i;
+ for(i = 0; i < digestsDefined.Size(); i++)
+ if (digestsDefined[i])
+ numDefined++;
+ if (numDefined == 0)
+ return S_OK;
+
+ RINOK(WriteByte(NID::kCRC));
+ if (numDefined == digestsDefined.Size())
+ {
+ RINOK(WriteByte(1));
+ }
+ else
+ {
+ RINOK(WriteByte(0));
+ RINOK(WriteBoolVector(digestsDefined));
+ }
+ for(i = 0; i < digests.Size(); i++)
+ {
+ if(digestsDefined[i])
+ RINOK(WriteUInt32(digests[i]));
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WritePackInfo(
+ UInt64 dataOffset,
+ const CRecordVector<UInt64> &packSizes,
+ const CRecordVector<bool> &packCRCsDefined,
+ const CRecordVector<UInt32> &packCRCs)
+{
+ if (packSizes.IsEmpty())
+ return S_OK;
+ RINOK(WriteByte(NID::kPackInfo));
+ RINOK(WriteNumber(dataOffset));
+ RINOK(WriteNumber(packSizes.Size()));
+ RINOK(WriteByte(NID::kSize));
+ for(int i = 0; i < packSizes.Size(); i++)
+ RINOK(WriteNumber(packSizes[i]));
+
+ RINOK(WriteHashDigests(packCRCsDefined, packCRCs));
+
+ return WriteByte(NID::kEnd);
+}
+
+HRESULT COutArchive::WriteUnPackInfo(
+ bool externalFolders,
+ CNum externalFoldersStreamIndex,
+ const CObjectVector<CFolder> &folders)
+{
+ if (folders.IsEmpty())
+ return S_OK;
+
+ RINOK(WriteByte(NID::kUnPackInfo));
+
+ RINOK(WriteByte(NID::kFolder));
+ RINOK(WriteNumber(folders.Size()));
+ if (externalFolders)
+ {
+ RINOK(WriteByte(1));
+ RINOK(WriteNumber(externalFoldersStreamIndex));
+ }
+ else
+ {
+ RINOK(WriteByte(0));
+ for(int i = 0; i < folders.Size(); i++)
+ RINOK(WriteFolder(folders[i]));
+ }
+
+ RINOK(WriteByte(NID::kCodersUnPackSize));
+ int i;
+ for(i = 0; i < folders.Size(); i++)
+ {
+ const CFolder &folder = folders[i];
+ for (int j = 0; j < folder.UnPackSizes.Size(); j++)
+ RINOK(WriteNumber(folder.UnPackSizes[j]));
+ }
+
+ CRecordVector<bool> unPackCRCsDefined;
+ CRecordVector<UInt32> unPackCRCs;
+ for(i = 0; i < folders.Size(); i++)
+ {
+ const CFolder &folder = folders[i];
+ unPackCRCsDefined.Add(folder.UnPackCRCDefined);
+ unPackCRCs.Add(folder.UnPackCRC);
+ }
+ RINOK(WriteHashDigests(unPackCRCsDefined, unPackCRCs));
+
+ return WriteByte(NID::kEnd);
+}
+
+HRESULT COutArchive::WriteSubStreamsInfo(
+ const CObjectVector<CFolder> &folders,
+ const CRecordVector<CNum> &numUnPackStreamsInFolders,
+ const CRecordVector<UInt64> &unPackSizes,
+ const CRecordVector<bool> &digestsDefined,
+ const CRecordVector<UInt32> &digests)
+{
+ RINOK(WriteByte(NID::kSubStreamsInfo));
+
+ int i;
+ for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+ {
+ if (numUnPackStreamsInFolders[i] != 1)
+ {
+ RINOK(WriteByte(NID::kNumUnPackStream));
+ for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+ RINOK(WriteNumber(numUnPackStreamsInFolders[i]));
+ break;
+ }
+ }
+
+
+ bool needFlag = true;
+ CNum index = 0;
+ for(i = 0; i < numUnPackStreamsInFolders.Size(); i++)
+ for (CNum j = 0; j < numUnPackStreamsInFolders[i]; j++)
+ {
+ if (j + 1 != numUnPackStreamsInFolders[i])
+ {
+ if (needFlag)
+ RINOK(WriteByte(NID::kSize));
+ needFlag = false;
+ RINOK(WriteNumber(unPackSizes[index]));
+ }
+ index++;
+ }
+
+ CRecordVector<bool> digestsDefined2;
+ CRecordVector<UInt32> digests2;
+
+ int digestIndex = 0;
+ for (i = 0; i < folders.Size(); i++)
+ {
+ int numSubStreams = (int)numUnPackStreamsInFolders[i];
+ if (numSubStreams == 1 && folders[i].UnPackCRCDefined)
+ digestIndex++;
+ else
+ for (int j = 0; j < numSubStreams; j++, digestIndex++)
+ {
+ digestsDefined2.Add(digestsDefined[digestIndex]);
+ digests2.Add(digests[digestIndex]);
+ }
+ }
+ RINOK(WriteHashDigests(digestsDefined2, digests2));
+ return WriteByte(NID::kEnd);
+}
+
+HRESULT COutArchive::WriteTime(
+ const CObjectVector<CFileItem> &files, Byte type,
+ bool isExternal, CNum externalDataIndex)
+{
+ /////////////////////////////////////////////////
+ // CreationTime
+ CBoolVector boolVector;
+ boolVector.Reserve(files.Size());
+ bool thereAreDefined = false;
+ bool allDefined = true;
+ int i;
+ for(i = 0; i < files.Size(); i++)
+ {
+ const CFileItem &item = files[i];
+ bool defined;
+ switch(type)
+ {
+ case NID::kCreationTime:
+ defined = item.IsCreationTimeDefined;
+ break;
+ case NID::kLastWriteTime:
+ defined = item.IsLastWriteTimeDefined;
+ break;
+ case NID::kLastAccessTime:
+ defined = item.IsLastAccessTimeDefined;
+ break;
+ default:
+ throw 1;
+ }
+ boolVector.Add(defined);
+ thereAreDefined = (thereAreDefined || defined);
+ allDefined = (allDefined && defined);
+ }
+ if (!thereAreDefined)
+ return S_OK;
+ RINOK(WriteByte(type));
+ size_t dataSize = 1 + 1;
+ if (isExternal)
+ dataSize += GetBigNumberSize(externalDataIndex);
+ else
+ dataSize += files.Size() * 8;
+ if (allDefined)
+ {
+ RINOK(WriteNumber(dataSize));
+ WriteByte(1);
+ }
+ else
+ {
+ RINOK(WriteNumber(1 + (boolVector.Size() + 7) / 8 + dataSize));
+ WriteByte(0);
+ RINOK(WriteBoolVector(boolVector));
+ }
+ if (isExternal)
+ {
+ RINOK(WriteByte(1));
+ RINOK(WriteNumber(externalDataIndex));
+ return S_OK;
+ }
+ RINOK(WriteByte(0));
+ for(i = 0; i < files.Size(); i++)
+ {
+ if (boolVector[i])
+ {
+ const CFileItem &item = files[i];
+ CArchiveFileTime timeValue;
+ timeValue.dwLowDateTime = 0;
+ timeValue.dwHighDateTime = 0;
+ switch(type)
+ {
+ case NID::kCreationTime:
+ timeValue = item.CreationTime;
+ break;
+ case NID::kLastWriteTime:
+ timeValue = item.LastWriteTime;
+ break;
+ case NID::kLastAccessTime:
+ timeValue = item.LastAccessTime;
+ break;
+ }
+ RINOK(WriteUInt32(timeValue.dwLowDateTime));
+ RINOK(WriteUInt32(timeValue.dwHighDateTime));
+ }
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::EncodeStream(CEncoder &encoder, const Byte *data, size_t dataSize,
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
+{
+ CSequentialInStreamImp *streamSpec = new CSequentialInStreamImp;
+ CMyComPtr<ISequentialInStream> stream = streamSpec;
+ streamSpec->Init(data, dataSize);
+ CFolder folderItem;
+ folderItem.UnPackCRCDefined = true;
+ folderItem.UnPackCRC = CCRC::CalculateDigest(data, dataSize);
+ UInt64 dataSize64 = dataSize;
+ RINOK(encoder.Encode(stream, NULL, &dataSize64, folderItem, SeqStream, packSizes, NULL));
+ folders.Add(folderItem);
+ return S_OK;
+}
+
+HRESULT COutArchive::EncodeStream(CEncoder &encoder, const CByteBuffer &data,
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders)
+{
+ return EncodeStream(encoder, data, data.GetCapacity(), packSizes, folders);
+}
+
+static void WriteUInt32ToBuffer(Byte *data, UInt32 value)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ *data++ = (Byte)value;
+ value >>= 8;
+ }
+}
+
+static void WriteUInt64ToBuffer(Byte *data, UInt64 value)
+{
+ for (int i = 0; i < 8; i++)
+ {
+ *data++ = (Byte)value;
+ value >>= 8;
+ }
+}
+
+
+HRESULT COutArchive::WriteHeader(const CArchiveDatabase &database,
+ const CCompressionMethodMode *options,
+ const CHeaderOptions &headerOptions,
+ UInt64 &headerOffset)
+{
+ CObjectVector<CFolder> folders;
+
+ bool compressHeaders = (options != NULL);
+ CMyAutoPtr<CEncoder> encoder;
+ if (compressHeaders)
+ {
+ // it's for gcc2.95.2
+ CMyAutoPtr<CEncoder> tmp(new CEncoder(*options));
+ encoder = tmp;
+ }
+
+ CRecordVector<UInt64> packSizes;
+
+ CNum dataIndex = 0;
+
+ //////////////////////////
+ // Folders
+
+ CNum externalFoldersStreamIndex = 0;
+ bool externalFolders = (compressHeaders && database.Folders.Size() > 8);
+ if (externalFolders)
+ {
+ _mainMode = false;
+ _countMode = true;
+ _countSize = 0;
+ int i;
+ for(i = 0; i < database.Folders.Size(); i++)
+ {
+ RINOK(WriteFolder(database.Folders[i]));
+ }
+
+ _countMode = false;
+
+ CByteBuffer foldersData;
+ foldersData.SetCapacity(_countSize);
+ _outByte2.Init(foldersData, foldersData.GetCapacity());
+
+ for(i = 0; i < database.Folders.Size(); i++)
+ {
+ RINOK(WriteFolder(database.Folders[i]));
+ }
+
+ {
+ externalFoldersStreamIndex = dataIndex++;
+ RINOK(EncodeStream(*encoder, foldersData, packSizes, folders));
+ }
+ }
+
+
+ int i;
+
+ /////////////////////////////////
+ // Names
+
+ CNum numDefinedNames = 0;
+ size_t namesDataSize = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ const UString &name = database.Files[i].Name;
+ if (!name.IsEmpty())
+ numDefinedNames++;
+ namesDataSize += (name.Length() + 1) * 2;
+ }
+
+ CByteBuffer namesData;
+ CNum externalNamesStreamIndex = 0;
+ bool externalNames = (compressHeaders && database.Files.Size() > 8);
+ if (numDefinedNames > 0)
+ {
+ namesData.SetCapacity((size_t)namesDataSize);
+ size_t pos = 0;
+ for(int i = 0; i < database.Files.Size(); i++)
+ {
+ const UString &name = database.Files[i].Name;
+ for (int t = 0; t < name.Length(); t++)
+ {
+ wchar_t c = name[t];
+ namesData[pos++] = Byte(c);
+ namesData[pos++] = Byte(c >> 8);
+ }
+ namesData[pos++] = 0;
+ namesData[pos++] = 0;
+ }
+
+ if (externalNames)
+ {
+ externalNamesStreamIndex = dataIndex++;
+ RINOK(EncodeStream(*encoder, namesData, packSizes, folders));
+ }
+ }
+
+ /////////////////////////////////
+ // Write Attributes
+ CBoolVector attributesBoolVector;
+ attributesBoolVector.Reserve(database.Files.Size());
+ int numDefinedAttributes = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ bool defined = database.Files[i].AreAttributesDefined;
+ attributesBoolVector.Add(defined);
+ if (defined)
+ numDefinedAttributes++;
+ }
+
+ CByteBuffer attributesData;
+ CNum externalAttributesStreamIndex = 0;
+ bool externalAttributes = (compressHeaders && numDefinedAttributes > 8);
+ if (numDefinedAttributes > 0)
+ {
+ attributesData.SetCapacity(numDefinedAttributes * 4);
+ size_t pos = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ const CFileItem &file = database.Files[i];
+ if (file.AreAttributesDefined)
+ {
+ WriteUInt32ToBuffer(attributesData + pos, file.Attributes);
+ pos += 4;
+ }
+ }
+ if (externalAttributes)
+ {
+ externalAttributesStreamIndex = dataIndex++;
+ RINOK(EncodeStream(*encoder, attributesData, packSizes, folders));
+ }
+ }
+
+ /////////////////////////////////
+ // Write StartPos
+ CBoolVector startsBoolVector;
+ startsBoolVector.Reserve(database.Files.Size());
+ int numDefinedStarts = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ bool defined = database.Files[i].IsStartPosDefined;
+ startsBoolVector.Add(defined);
+ if (defined)
+ numDefinedStarts++;
+ }
+
+ CByteBuffer startsData;
+ CNum externalStartStreamIndex = 0;
+ bool externalStarts = (compressHeaders && numDefinedStarts > 8);
+ if (numDefinedStarts > 0)
+ {
+ startsData.SetCapacity(numDefinedStarts * 8);
+ size_t pos = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ const CFileItem &file = database.Files[i];
+ if (file.IsStartPosDefined)
+ {
+ WriteUInt64ToBuffer(startsData + pos, file.StartPos);
+ pos += 8;
+ }
+ }
+ if (externalStarts)
+ {
+ externalStartStreamIndex = dataIndex++;
+ RINOK(EncodeStream(*encoder, startsData, packSizes, folders));
+ }
+ }
+
+ /////////////////////////////////
+ // Write Last Write Time
+ CNum externalLastWriteTimeStreamIndex = 0;
+ bool externalLastWriteTime = false;
+ // /*
+ CNum numDefinedLastWriteTimes = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ if (database.Files[i].IsLastWriteTimeDefined)
+ numDefinedLastWriteTimes++;
+
+ externalLastWriteTime = (compressHeaders && numDefinedLastWriteTimes > 64);
+ if (numDefinedLastWriteTimes > 0)
+ {
+ CByteBuffer lastWriteTimeData;
+ lastWriteTimeData.SetCapacity(numDefinedLastWriteTimes * 8);
+ size_t pos = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ const CFileItem &file = database.Files[i];
+ if (file.IsLastWriteTimeDefined)
+ {
+ WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwLowDateTime);
+ pos += 4;
+ WriteUInt32ToBuffer(lastWriteTimeData + pos, file.LastWriteTime.dwHighDateTime);
+ pos += 4;
+ }
+ }
+ if (externalLastWriteTime)
+ {
+ externalLastWriteTimeStreamIndex = dataIndex++;
+ RINOK(EncodeStream(*encoder, lastWriteTimeData, packSizes, folders));
+ }
+ }
+ // */
+
+
+ UInt64 packedSize = 0;
+ for(i = 0; i < database.PackSizes.Size(); i++)
+ packedSize += database.PackSizes[i];
+ UInt64 headerPackSize = 0;
+ for (i = 0; i < packSizes.Size(); i++)
+ headerPackSize += packSizes[i];
+
+ headerOffset = packedSize + headerPackSize;
+
+ _mainMode = true;
+
+ _outByte.SetStream(SeqStream);
+ _outByte.Init();
+ _crc.Init();
+
+
+ RINOK(WriteByte(NID::kHeader));
+
+ // Archive Properties
+
+ if (folders.Size() > 0)
+ {
+ RINOK(WriteByte(NID::kAdditionalStreamsInfo));
+ RINOK(WritePackInfo(packedSize, packSizes,
+ CRecordVector<bool>(), CRecordVector<UInt32>()));
+ RINOK(WriteUnPackInfo(false, 0, folders));
+ RINOK(WriteByte(NID::kEnd));
+ }
+
+ ////////////////////////////////////////////////////
+
+ if (database.Folders.Size() > 0)
+ {
+ RINOK(WriteByte(NID::kMainStreamsInfo));
+ RINOK(WritePackInfo(0, database.PackSizes,
+ database.PackCRCsDefined,
+ database.PackCRCs));
+
+ RINOK(WriteUnPackInfo(externalFolders, externalFoldersStreamIndex, database.Folders));
+
+ CRecordVector<UInt64> unPackSizes;
+ CRecordVector<bool> digestsDefined;
+ CRecordVector<UInt32> digests;
+ for (i = 0; i < database.Files.Size(); i++)
+ {
+ const CFileItem &file = database.Files[i];
+ if (!file.HasStream)
+ continue;
+ unPackSizes.Add(file.UnPackSize);
+ digestsDefined.Add(file.IsFileCRCDefined);
+ digests.Add(file.FileCRC);
+ }
+
+ RINOK(WriteSubStreamsInfo(
+ database.Folders,
+ database.NumUnPackStreamsVector,
+ unPackSizes,
+ digestsDefined,
+ digests));
+ RINOK(WriteByte(NID::kEnd));
+ }
+
+ if (database.Files.IsEmpty())
+ {
+ RINOK(WriteByte(NID::kEnd));
+ return _outByte.Flush();
+ }
+
+ RINOK(WriteByte(NID::kFilesInfo));
+ RINOK(WriteNumber(database.Files.Size()));
+
+ CBoolVector emptyStreamVector;
+ emptyStreamVector.Reserve(database.Files.Size());
+ int numEmptyStreams = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ if (database.Files[i].HasStream)
+ emptyStreamVector.Add(false);
+ else
+ {
+ emptyStreamVector.Add(true);
+ numEmptyStreams++;
+ }
+ if (numEmptyStreams > 0)
+ {
+ RINOK(WriteByte(NID::kEmptyStream));
+ RINOK(WriteNumber((emptyStreamVector.Size() + 7) / 8));
+ RINOK(WriteBoolVector(emptyStreamVector));
+
+ CBoolVector emptyFileVector, antiVector;
+ emptyFileVector.Reserve(numEmptyStreams);
+ antiVector.Reserve(numEmptyStreams);
+ CNum numEmptyFiles = 0, numAntiItems = 0;
+ for(i = 0; i < database.Files.Size(); i++)
+ {
+ const CFileItem &file = database.Files[i];
+ if (!file.HasStream)
+ {
+ emptyFileVector.Add(!file.IsDirectory);
+ if (!file.IsDirectory)
+ numEmptyFiles++;
+ antiVector.Add(file.IsAnti);
+ if (file.IsAnti)
+ numAntiItems++;
+ }
+ }
+
+ if (numEmptyFiles > 0)
+ {
+ RINOK(WriteByte(NID::kEmptyFile));
+ RINOK(WriteNumber((emptyFileVector.Size() + 7) / 8));
+ RINOK(WriteBoolVector(emptyFileVector));
+ }
+
+ if (numAntiItems > 0)
+ {
+ RINOK(WriteByte(NID::kAnti));
+ RINOK(WriteNumber((antiVector.Size() + 7) / 8));
+ RINOK(WriteBoolVector(antiVector));
+ }
+ }
+
+ if (numDefinedNames > 0)
+ {
+ /////////////////////////////////////////////////
+ RINOK(WriteByte(NID::kName));
+ if (externalNames)
+ {
+ RINOK(WriteNumber(1 + GetBigNumberSize(externalNamesStreamIndex)));
+ RINOK(WriteByte(1));
+ RINOK(WriteNumber(externalNamesStreamIndex));
+ }
+ else
+ {
+ RINOK(WriteNumber(1 + namesData.GetCapacity()));
+ RINOK(WriteByte(0));
+ RINOK(WriteBytes(namesData));
+ }
+
+ }
+
+ if (headerOptions.WriteCreated)
+ {
+ RINOK(WriteTime(database.Files, NID::kCreationTime, false, 0));
+ }
+ if (headerOptions.WriteModified)
+ {
+ RINOK(WriteTime(database.Files, NID::kLastWriteTime,
+ // false, 0));
+ externalLastWriteTime, externalLastWriteTimeStreamIndex));
+ }
+ if (headerOptions.WriteAccessed)
+ {
+ RINOK(WriteTime(database.Files, NID::kLastAccessTime, false, 0));
+ }
+
+ if (numDefinedAttributes > 0)
+ {
+ RINOK(WriteByte(NID::kWinAttributes));
+ size_t size = 2;
+ if (numDefinedAttributes != database.Files.Size())
+ size += (attributesBoolVector.Size() + 7) / 8 + 1;
+ if (externalAttributes)
+ size += GetBigNumberSize(externalAttributesStreamIndex);
+ else
+ size += attributesData.GetCapacity();
+
+ RINOK(WriteNumber(size));
+ if (numDefinedAttributes == database.Files.Size())
+ {
+ RINOK(WriteByte(1));
+ }
+ else
+ {
+ RINOK(WriteByte(0));
+ RINOK(WriteBoolVector(attributesBoolVector));
+ }
+
+ if (externalAttributes)
+ {
+ RINOK(WriteByte(1));
+ RINOK(WriteNumber(externalAttributesStreamIndex));
+ }
+ else
+ {
+ RINOK(WriteByte(0));
+ RINOK(WriteBytes(attributesData));
+ }
+ }
+
+ if (numDefinedStarts > 0)
+ {
+ RINOK(WriteByte(NID::kStartPos));
+ size_t size = 2;
+ if (numDefinedStarts != database.Files.Size())
+ size += (startsBoolVector.Size() + 7) / 8 + 1;
+ if (externalStarts)
+ size += GetBigNumberSize(externalStartStreamIndex);
+ else
+ size += startsData.GetCapacity();
+
+ RINOK(WriteNumber(size));
+ if (numDefinedStarts == database.Files.Size())
+ {
+ RINOK(WriteByte(1));
+ }
+ else
+ {
+ RINOK(WriteByte(0));
+ RINOK(WriteBoolVector(startsBoolVector));
+ }
+
+ if (externalAttributes)
+ {
+ RINOK(WriteByte(1));
+ RINOK(WriteNumber(externalStartStreamIndex));
+ }
+ else
+ {
+ RINOK(WriteByte(0));
+ RINOK(WriteBytes(startsData));
+ }
+ }
+
+ RINOK(WriteByte(NID::kEnd)); // for files
+ RINOK(WriteByte(NID::kEnd)); // for headers
+
+ return _outByte.Flush();
+}
+
+HRESULT COutArchive::WriteDatabase(const CArchiveDatabase &database,
+ const CCompressionMethodMode *options,
+ const CHeaderOptions &headerOptions)
+{
+ UInt64 headerOffset;
+ UInt32 headerCRC;
+ UInt64 headerSize;
+ if (database.IsEmpty())
+ {
+ headerSize = 0;
+ headerOffset = 0;
+ headerCRC = CCRC::CalculateDigest(0, 0);
+ }
+ else
+ {
+ _dynamicBuffer.Init();
+ _dynamicMode = false;
+
+ if (options != 0)
+ if (options->IsEmpty())
+ options = 0;
+ const CCompressionMethodMode *additionalStreamsOptions = options;
+ if (!headerOptions.UseAdditionalHeaderStreams)
+ additionalStreamsOptions = 0;
+ /*
+ if (database.Files.Size() < 2)
+ compressMainHeader = false;
+ */
+ if (options != 0)
+ if (options->PasswordIsDefined || headerOptions.CompressMainHeader)
+ _dynamicMode = true;
+ RINOK(WriteHeader(database, additionalStreamsOptions, headerOptions, headerOffset));
+
+ if (_dynamicMode)
+ {
+ CCompressionMethodMode encryptOptions;
+ encryptOptions.PasswordIsDefined = options->PasswordIsDefined;
+ encryptOptions.Password = options->Password;
+ CEncoder encoder(headerOptions.CompressMainHeader ? *options : encryptOptions);
+ CRecordVector<UInt64> packSizes;
+ CObjectVector<CFolder> folders;
+ RINOK(EncodeStream(encoder, _dynamicBuffer,
+ _dynamicBuffer.GetSize(), packSizes, folders));
+ _dynamicMode = false;
+ _mainMode = true;
+
+ _outByte.SetStream(SeqStream);
+ _outByte.Init();
+ _crc.Init();
+
+ if (folders.Size() == 0)
+ throw 1;
+
+ RINOK(WriteID(NID::kEncodedHeader));
+ RINOK(WritePackInfo(headerOffset, packSizes,
+ CRecordVector<bool>(), CRecordVector<UInt32>()));
+ RINOK(WriteUnPackInfo(false, 0, folders));
+ RINOK(WriteByte(NID::kEnd));
+ for (int i = 0; i < packSizes.Size(); i++)
+ headerOffset += packSizes[i];
+ RINOK(_outByte.Flush());
+ }
+ headerCRC = _crc.GetDigest();
+ headerSize = _outByte.GetProcessedSize();
+ }
+ #ifdef _7Z_VOL
+ if (_endMarker)
+ {
+ CFinishHeader h;
+ h.NextHeaderSize = headerSize;
+ h.NextHeaderCRC = headerCRC;
+ h.NextHeaderOffset =
+ UInt64(0) - (headerSize +
+ 4 + kFinishHeaderSize);
+ h.ArchiveStartOffset = h.NextHeaderOffset - headerOffset;
+ h.AdditionalStartBlockSize = 0;
+ RINOK(WriteFinishHeader(h));
+ return WriteFinishSignature();
+ }
+ else
+ #endif
+ {
+ CStartHeader h;
+ h.NextHeaderSize = headerSize;
+ h.NextHeaderCRC = headerCRC;
+ h.NextHeaderOffset = headerOffset;
+ RINOK(Stream->Seek(_prefixHeaderPos, STREAM_SEEK_SET, NULL));
+ return WriteStartHeader(h);
+ }
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zOut.h b/CPP/7zip/Archive/7z/7zOut.h
new file mode 100755
index 00000000..cccc813a
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zOut.h
@@ -0,0 +1,192 @@
+// 7z/Out.h
+
+#ifndef __7Z_OUT_H
+#define __7Z_OUT_H
+
+#include "7zHeader.h"
+#include "7zItem.h"
+#include "7zCompressionMode.h"
+#include "7zEncode.h"
+
+#include "../../Common/OutBuffer.h"
+#include "../../../Common/DynamicBuffer.h"
+#include "../../../Common/CRC.h"
+
+namespace NArchive {
+namespace N7z {
+
+class CWriteBufferLoc
+{
+ Byte *_data;
+ size_t _size;
+ size_t _pos;
+public:
+ CWriteBufferLoc(): _size(0), _pos(0) {}
+ void Init(Byte *data, size_t size)
+ {
+ _pos = 0;
+ _data = data;
+ _size = size;
+ }
+ HRESULT Write(const void *data, size_t size)
+ {
+ if (_pos + size > _size)
+ return E_FAIL;
+ memmove(_data + _pos, data, size);
+ _pos += size;
+ return S_OK;
+ }
+};
+
+class CWriteDynamicBuffer
+{
+ CByteDynamicBuffer _buffer;
+ size_t _pos;
+public:
+ CWriteDynamicBuffer(): _pos(0) {}
+ void Init()
+ {
+ _pos = 0;
+ }
+ void Write(const void *data, size_t size)
+ {
+ if (_pos + size > _buffer.GetCapacity())
+ _buffer.EnsureCapacity(_pos + size);
+ memmove(((Byte *)_buffer) +_pos, data, size);
+ _pos += size;
+ }
+ operator Byte *() { return (Byte *)_buffer; };
+ operator const Byte *() const { return (const Byte *)_buffer; };
+ size_t GetSize() const { return _pos; }
+};
+
+struct CHeaderOptions
+{
+ bool UseAdditionalHeaderStreams;
+ bool CompressMainHeader;
+ bool WriteModified;
+ bool WriteCreated;
+ bool WriteAccessed;
+
+ CHeaderOptions():
+ UseAdditionalHeaderStreams(false),
+ CompressMainHeader(true),
+ WriteModified(true),
+ WriteCreated(false),
+ WriteAccessed(false) {}
+};
+
+class COutArchive
+{
+ UInt64 _prefixHeaderPos;
+
+ HRESULT WriteDirect(const void *data, UInt32 size);
+ HRESULT WriteDirectByte(Byte b) { return WriteDirect(&b, 1); }
+ HRESULT WriteDirectUInt32(UInt32 value);
+ HRESULT WriteDirectUInt64(UInt64 value);
+
+ HRESULT WriteBytes(const void *data, size_t size);
+ HRESULT WriteBytes(const CByteBuffer &data);
+ HRESULT WriteByte(Byte b);
+ HRESULT WriteUInt32(UInt32 value);
+ HRESULT WriteNumber(UInt64 value);
+ HRESULT WriteID(UInt64 value) { return WriteNumber(value); }
+
+ HRESULT WriteFolder(const CFolder &folder);
+ HRESULT WriteFileHeader(const CFileItem &itemInfo);
+ HRESULT WriteBoolVector(const CBoolVector &boolVector);
+ HRESULT WriteHashDigests(
+ const CRecordVector<bool> &digestsDefined,
+ const CRecordVector<UInt32> &hashDigests);
+
+ HRESULT WritePackInfo(
+ UInt64 dataOffset,
+ const CRecordVector<UInt64> &packSizes,
+ const CRecordVector<bool> &packCRCsDefined,
+ const CRecordVector<UInt32> &packCRCs);
+
+ HRESULT WriteUnPackInfo(
+ bool externalFolders,
+ CNum externalFoldersStreamIndex,
+ const CObjectVector<CFolder> &folders);
+
+ HRESULT WriteSubStreamsInfo(
+ const CObjectVector<CFolder> &folders,
+ const CRecordVector<CNum> &numUnPackStreamsInFolders,
+ const CRecordVector<UInt64> &unPackSizes,
+ const CRecordVector<bool> &digestsDefined,
+ const CRecordVector<UInt32> &hashDigests);
+
+ /*
+ HRESULT WriteStreamsInfo(
+ UInt64 dataOffset,
+ const CRecordVector<UInt64> &packSizes,
+ const CRecordVector<bool> &packCRCsDefined,
+ const CRecordVector<UInt32> &packCRCs,
+ bool externalFolders,
+ UInt64 externalFoldersStreamIndex,
+ const CObjectVector<CFolder> &folders,
+ const CRecordVector<CNum> &numUnPackStreamsInFolders,
+ const CRecordVector<UInt64> &unPackSizes,
+ const CRecordVector<bool> &digestsDefined,
+ const CRecordVector<UInt32> &hashDigests);
+ */
+
+
+ HRESULT WriteTime(const CObjectVector<CFileItem> &files, Byte type,
+ bool isExternal, CNum externalDataIndex);
+
+ HRESULT EncodeStream(CEncoder &encoder, const Byte *data, size_t dataSize,
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
+ HRESULT EncodeStream(CEncoder &encoder, const CByteBuffer &data,
+ CRecordVector<UInt64> &packSizes, CObjectVector<CFolder> &folders);
+ HRESULT WriteHeader(const CArchiveDatabase &database,
+ const CCompressionMethodMode *options,
+ const CHeaderOptions &headerOptions,
+ UInt64 &headerOffset);
+
+ bool _mainMode;
+
+ bool _dynamicMode;
+
+ bool _countMode;
+ size_t _countSize;
+ COutBuffer _outByte;
+ CWriteBufferLoc _outByte2;
+ CWriteDynamicBuffer _dynamicBuffer;
+ CCRC _crc;
+
+ #ifdef _7Z_VOL
+ bool _endMarker;
+ #endif
+
+ HRESULT WriteSignature();
+ #ifdef _7Z_VOL
+ HRESULT WriteFinishSignature();
+ #endif
+ HRESULT WriteStartHeader(const CStartHeader &h);
+ #ifdef _7Z_VOL
+ HRESULT WriteFinishHeader(const CFinishHeader &h);
+ #endif
+ CMyComPtr<IOutStream> Stream;
+public:
+
+ COutArchive() { _outByte.Create(1 << 16); }
+ CMyComPtr<ISequentialOutStream> SeqStream;
+ HRESULT Create(ISequentialOutStream *stream, bool endMarker);
+ void Close();
+ HRESULT SkeepPrefixArchiveHeader();
+ HRESULT WriteDatabase(const CArchiveDatabase &database,
+ const CCompressionMethodMode *options,
+ const CHeaderOptions &headerOptions);
+
+ #ifdef _7Z_VOL
+ static UInt32 GetVolHeadersSize(UInt64 dataSize, int nameLength = 0, bool props = false);
+ static UInt64 GetVolPureSize(UInt64 volSize, int nameLength = 0, bool props = false);
+ #endif
+
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zProperties.cpp b/CPP/7zip/Archive/7z/7zProperties.cpp
new file mode 100755
index 00000000..316f4f09
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zProperties.cpp
@@ -0,0 +1,166 @@
+// 7zProperties.cpp
+
+#include "StdAfx.h"
+
+#include "7zProperties.h"
+#include "7zHeader.h"
+#include "7zHandler.h"
+
+// #define _MULTI_PACK
+
+namespace NArchive {
+namespace N7z {
+
+struct CPropMap
+{
+ UInt64 FilePropID;
+ STATPROPSTG StatPROPSTG;
+};
+
+CPropMap kPropMap[] =
+{
+ { NID::kName, NULL, kpidPath, VT_BSTR},
+ { NID::kSize, NULL, kpidSize, VT_UI8},
+ { NID::kPackInfo, NULL, kpidPackedSize, VT_UI8},
+
+ #ifdef _MULTI_PACK
+ { 100, L"Pack0", kpidPackedSize0, VT_UI8},
+ { 101, L"Pack1", kpidPackedSize1, VT_UI8},
+ { 102, L"Pack2", kpidPackedSize2, VT_UI8},
+ { 103, L"Pack3", kpidPackedSize3, VT_UI8},
+ { 104, L"Pack4", kpidPackedSize4, VT_UI8},
+ #endif
+
+ { NID::kCreationTime, NULL, kpidCreationTime, VT_FILETIME},
+ { NID::kLastWriteTime, NULL, kpidLastWriteTime, VT_FILETIME},
+ { NID::kLastAccessTime, NULL, kpidLastAccessTime, VT_FILETIME},
+ { NID::kWinAttributes, NULL, kpidAttributes, VT_UI4},
+ { NID::kStartPos, NULL, kpidPosition, VT_UI4},
+
+
+ { NID::kCRC, NULL, kpidCRC, VT_UI4},
+
+ { NID::kAnti, L"Anti", kpidIsAnti, VT_BOOL},
+ // { 97, NULL, kpidSolid, VT_BOOL},
+ #ifndef _SFX
+ { 98, NULL, kpidMethod, VT_BSTR},
+ { 99, L"Block", kpidBlock, VT_UI4}
+ #endif
+ // { L"ID", kpidID, VT_BSTR},
+ // { L"UnPack Version", kpidUnPackVersion, VT_UI1},
+ // { L"Host OS", kpidHostOS, VT_BSTR}
+};
+
+static const int kPropMapSize = sizeof(kPropMap) / sizeof(kPropMap[0]);
+
+static int FindPropInMap(UInt64 filePropID)
+{
+ for (int i = 0; i < kPropMapSize; i++)
+ if (kPropMap[i].FilePropID == filePropID)
+ return i;
+ return -1;
+}
+
+static void CopyOneItem(CRecordVector<UInt64> &src,
+ CRecordVector<UInt64> &dest, UInt32 item)
+{
+ for (int i = 0; i < src.Size(); i++)
+ if (src[i] == item)
+ {
+ dest.Add(item);
+ src.Delete(i);
+ return;
+ }
+}
+
+static void RemoveOneItem(CRecordVector<UInt64> &src, UInt32 item)
+{
+ for (int i = 0; i < src.Size(); i++)
+ if (src[i] == item)
+ {
+ src.Delete(i);
+ return;
+ }
+}
+
+static void InsertToHead(CRecordVector<UInt64> &dest, UInt32 item)
+{
+ for (int i = 0; i < dest.Size(); i++)
+ if (dest[i] == item)
+ {
+ dest.Delete(i);
+ break;
+ }
+ dest.Insert(0, item);
+}
+
+void CHandler::FillPopIDs()
+{
+ _fileInfoPopIDs.Clear();
+
+ #ifdef _7Z_VOL
+ if(_volumes.Size() < 1)
+ return;
+ const CVolume &volume = _volumes.Front();
+ const CArchiveDatabaseEx &_database = volume.Database;
+ #endif
+
+ CRecordVector<UInt64> fileInfoPopIDs = _database.ArchiveInfo.FileInfoPopIDs;
+
+ RemoveOneItem(fileInfoPopIDs, NID::kEmptyStream);
+ RemoveOneItem(fileInfoPopIDs, NID::kEmptyFile);
+
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kName);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kAnti);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kSize);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kPackInfo);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCreationTime);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastWriteTime);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kLastAccessTime);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kWinAttributes);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kCRC);
+ CopyOneItem(fileInfoPopIDs, _fileInfoPopIDs, NID::kComment);
+ _fileInfoPopIDs += fileInfoPopIDs;
+
+ #ifndef _SFX
+ _fileInfoPopIDs.Add(98);
+ _fileInfoPopIDs.Add(99);
+ #endif
+ #ifdef _MULTI_PACK
+ _fileInfoPopIDs.Add(100);
+ _fileInfoPopIDs.Add(101);
+ _fileInfoPopIDs.Add(102);
+ _fileInfoPopIDs.Add(103);
+ _fileInfoPopIDs.Add(104);
+ #endif
+
+ #ifndef _SFX
+ InsertToHead(_fileInfoPopIDs, NID::kLastWriteTime);
+ InsertToHead(_fileInfoPopIDs, NID::kPackInfo);
+ InsertToHead(_fileInfoPopIDs, NID::kSize);
+ InsertToHead(_fileInfoPopIDs, NID::kName);
+ #endif
+}
+
+STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 *numProperties)
+{
+ *numProperties = _fileInfoPopIDs.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetPropertyInfo(UInt32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ if((int)index >= _fileInfoPopIDs.Size())
+ return E_INVALIDARG;
+ int indexInMap = FindPropInMap(_fileInfoPopIDs[index]);
+ if (indexInMap == -1)
+ return E_INVALIDARG;
+ const STATPROPSTG &srcItem = kPropMap[indexInMap].StatPROPSTG;
+ *propID = srcItem.propid;
+ *varType = srcItem.vt;
+ *name = 0;
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zProperties.h b/CPP/7zip/Archive/7z/7zProperties.h
new file mode 100755
index 00000000..a09839bb
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zProperties.h
@@ -0,0 +1,22 @@
+// 7zProperties.h
+
+#ifndef __7Z_PROPERTIES_H
+#define __7Z_PROPERTIES_H
+
+#include "../../PropID.h"
+
+namespace NArchive {
+namespace N7z {
+
+enum // PropID
+{
+ kpidPackedSize0 = kpidUserDefined,
+ kpidPackedSize1,
+ kpidPackedSize2,
+ kpidPackedSize3,
+ kpidPackedSize4,
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.cpp b/CPP/7zip/Archive/7z/7zSpecStream.cpp
new file mode 100755
index 00000000..80d303a4
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zSpecStream.cpp
@@ -0,0 +1,24 @@
+// 7zSpecStream.cpp
+
+#include "StdAfx.h"
+
+#include "7zSpecStream.h"
+
+STDMETHODIMP CSequentialInStreamSizeCount2::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (processedSize != 0)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+STDMETHODIMP CSequentialInStreamSizeCount2::GetSubStreamSize(
+ UInt64 subStream, UInt64 *value)
+{
+ if (_getSubStreamSize == NULL)
+ return E_NOTIMPL;
+ return _getSubStreamSize->GetSubStreamSize(subStream, value);
+}
+
diff --git a/CPP/7zip/Archive/7z/7zSpecStream.h b/CPP/7zip/Archive/7z/7zSpecStream.h
new file mode 100755
index 00000000..0253c421
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zSpecStream.h
@@ -0,0 +1,35 @@
+// 7zSpecStream.h
+
+#ifndef __7Z_SPEC_STREAM_H
+#define __7Z_SPEC_STREAM_H
+
+#include "../../IStream.h"
+#include "../../ICoder.h"
+#include "../../../Common/MyCom.h"
+
+class CSequentialInStreamSizeCount2:
+ public ISequentialInStream,
+ public ICompressGetSubStreamSize,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ CMyComPtr<ICompressGetSubStreamSize> _getSubStreamSize;
+ UInt64 _size;
+public:
+ void Init(ISequentialInStream *stream)
+ {
+ _stream = stream;
+ _getSubStreamSize = 0;
+ _stream.QueryInterface(IID_ICompressGetSubStreamSize, &_getSubStreamSize);
+ _size = 0;
+ }
+ UInt64 GetSize() const { return _size; }
+
+ MY_UNKNOWN_IMP1(ICompressGetSubStreamSize)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ STDMETHOD(GetSubStreamSize)(UInt64 subStream, UInt64 *value);
+};
+
+#endif
diff --git a/CPP/7zip/Archive/7z/7zUpdate.cpp b/CPP/7zip/Archive/7z/7zUpdate.cpp
new file mode 100755
index 00000000..b3d5009a
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zUpdate.cpp
@@ -0,0 +1,1099 @@
+// UpdateMain.cpp
+
+#include "StdAfx.h"
+
+#include "7zUpdate.h"
+#include "7zFolderInStream.h"
+#include "7zEncode.h"
+#include "7zHandler.h"
+#include "7zOut.h"
+
+#ifndef EXCLUDE_COM
+#include "7zMethods.h"
+#endif
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/LimitedStreams.h"
+#include "../Common/ItemNameUtils.h"
+
+namespace NArchive {
+namespace N7z {
+
+static const wchar_t *kMatchFinderForBCJ2_LZMA = L"BT2";
+static const UInt32 kDictionaryForBCJ2_LZMA = 1 << 20;
+static const UInt32 kAlgorithmForBCJ2_LZMA = 1;
+static const UInt32 kNumFastBytesForBCJ2_LZMA = 64;
+
+static HRESULT CopyBlock(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, ICompressProgressInfo *progress)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+}
+
+static HRESULT WriteRange(
+ ISequentialInStream *inStream,
+ ISequentialOutStream *outStream,
+ UInt64 size,
+ IProgress *progress,
+ UInt64 &currentComplexity)
+{
+ CLimitedSequentialInStream *streamSpec = new
+ CLimitedSequentialInStream;
+ CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
+ streamSpec->SetStream(inStream);
+ streamSpec->Init(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 = CopyBlock(inStreamLimited, outStream, compressProgress);
+ currentComplexity += size;
+ return result;
+}
+
+
+static HRESULT WriteRange(IInStream *inStream,
+ ISequentialOutStream *outStream,
+ UInt64 position,
+ UInt64 size,
+ IProgress *progress,
+ UInt64 &currentComplexity)
+{
+ inStream->Seek(position, STREAM_SEEK_SET, 0);
+ return WriteRange(inStream, outStream,
+ size, progress, currentComplexity);
+}
+
+static int GetReverseSlashPos(const UString &name)
+{
+ int slashPos = name.ReverseFind(L'/');
+ #ifdef _WIN32
+ int slash1Pos = name.ReverseFind(L'\\');
+ slashPos = MyMax(slashPos, slash1Pos);
+ #endif
+ return slashPos;
+}
+
+int CUpdateItem::GetExtensionPos() const
+{
+ int slashPos = GetReverseSlashPos(Name);
+ int dotPos = Name.ReverseFind(L'.');
+ if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+ return Name.Length();
+ return dotPos + 1;
+}
+
+UString CUpdateItem::GetExtension() const
+{
+ return Name.Mid(GetExtensionPos());
+}
+
+/*
+struct CFolderRef
+{
+ const CArchiveDatabaseEx *Database;
+ int FolderIndex;
+};
+*/
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareMethodIDs(const CMethodID &a1, const CMethodID &a2)
+{
+ for (int i = 0; i < a1.IDSize && i < a2.IDSize; i++)
+ RINOZ(MyCompare(a1.ID[i], a2.ID[i]));
+ return MyCompare(a1.IDSize, a2.IDSize);
+}
+
+static int CompareBuffers(const CByteBuffer &a1, const CByteBuffer &a2)
+{
+ size_t c1 = a1.GetCapacity();
+ size_t c2 = a2.GetCapacity();
+ RINOZ(MyCompare(c1, c2));
+ for (size_t i = 0; i < c1; i++)
+ RINOZ(MyCompare(a1[i], a2[i]));
+ return 0;
+}
+
+static int CompareAltCoders(const CAltCoderInfo &a1, const CAltCoderInfo &a2)
+{
+ RINOZ(CompareMethodIDs(a1.MethodID, a2.MethodID));
+ return CompareBuffers(a1.Properties, a2.Properties);
+}
+
+static int CompareCoders(const CCoderInfo &c1, const CCoderInfo &c2)
+{
+ RINOZ(MyCompare(c1.NumInStreams, c2.NumInStreams));
+ RINOZ(MyCompare(c1.NumOutStreams, c2.NumOutStreams));
+ int s1 = c1.AltCoders.Size();
+ int s2 = c2.AltCoders.Size();
+ RINOZ(MyCompare(s1, s2));
+ for (int i = 0; i < s1; i++)
+ RINOZ(CompareAltCoders(c1.AltCoders[i], c2.AltCoders[i]));
+ return 0;
+}
+
+static int CompareBindPairs(const CBindPair &b1, const CBindPair &b2)
+{
+ RINOZ(MyCompare(b1.InIndex, b2.InIndex));
+ return MyCompare(b1.OutIndex, b2.OutIndex);
+}
+
+static int CompareFolders(const CFolder &f1, const CFolder &f2)
+{
+ int s1 = f1.Coders.Size();
+ int s2 = f2.Coders.Size();
+ RINOZ(MyCompare(s1, s2));
+ int i;
+ for (i = 0; i < s1; i++)
+ RINOZ(CompareCoders(f1.Coders[i], f2.Coders[i]));
+ s1 = f1.BindPairs.Size();
+ s2 = f2.BindPairs.Size();
+ RINOZ(MyCompare(s1, s2));
+ for (i = 0; i < s1; i++)
+ RINOZ(CompareBindPairs(f1.BindPairs[i], f2.BindPairs[i]));
+ return 0;
+}
+
+static int CompareFiles(const CFileItem &f1, const CFileItem &f2)
+{
+ return MyStringCompareNoCase(f1.Name, f2.Name);
+}
+
+static int CompareFolderRefs(const int *p1, const int *p2, void *param)
+{
+ int i1 = *p1;
+ int i2 = *p2;
+ const CArchiveDatabaseEx &db = *(const CArchiveDatabaseEx *)param;
+ RINOZ(CompareFolders(
+ db.Folders[i1],
+ db.Folders[i2]));
+ RINOZ(MyCompare(
+ db.NumUnPackStreamsVector[i1],
+ db.NumUnPackStreamsVector[i2]));
+ if (db.NumUnPackStreamsVector[i1] == 0)
+ return 0;
+ return CompareFiles(
+ db.Files[db.FolderStartFileIndex[i1]],
+ db.Files[db.FolderStartFileIndex[i2]]);
+}
+
+////////////////////////////////////////////////////////////
+
+static int CompareEmptyItems(const int *p1, const int *p2, void *param)
+{
+ const CObjectVector<CUpdateItem> &updateItems = *(const CObjectVector<CUpdateItem> *)param;
+ const CUpdateItem &u1 = updateItems[*p1];
+ const CUpdateItem &u2 = updateItems[*p2];
+ if (u1.IsDirectory != u2.IsDirectory)
+ return (u1.IsDirectory) ? 1 : -1;
+ if (u1.IsDirectory)
+ {
+ if (u1.IsAnti != u2.IsAnti)
+ return (u1.IsAnti ? 1 : -1);
+ int n = MyStringCompareNoCase(u1.Name, u2.Name);
+ return -n;
+ }
+ if (u1.IsAnti != u2.IsAnti)
+ return (u1.IsAnti ? 1 : -1);
+ return MyStringCompareNoCase(u1.Name, u2.Name);
+}
+
+static const char *g_Exts =
+ " lzma 7z ace arc arj bz bz2 deb lzo lzx gz pak rpm sit tgz tbz tbz2 tgz cab ha lha lzh rar zoo"
+ " zip jar ear war msi"
+ " 3gp avi mov mpeg mpg mpe wmv"
+ " aac ape fla flac la mp3 m4a mp4 ofr ogg pac ra rm rka shn swa tta wv wma wav"
+ " swf "
+ " chm hxi hxs"
+ " gif jpeg jpg jp2 png tiff bmp ico psd psp"
+ " awg ps eps cgm dxf svg vrml wmf emf ai md"
+ " cad dwg pps key sxi"
+ " max 3ds"
+ " iso bin nrg mdf img pdi tar cpio xpi"
+ " vfd vhd vud vmc vsv"
+ " vmdk dsk nvram vmem vmsd vmsn vmss vmtm"
+ " inl inc idl acf asa h hpp hxx c cpp cxx rc java cs pas bas vb cls ctl frm dlg def"
+ " f77 f f90 f95"
+ " asm sql manifest dep "
+ " mak clw csproj vcproj sln dsp dsw "
+ " class "
+ " bat cmd"
+ " xml xsd xsl xslt hxk hxc htm html xhtml xht mht mhtml htw asp aspx css cgi jsp shtml"
+ " awk sed hta js php php3 php4 php5 phptml pl pm py pyo rb sh tcl vbs"
+ " text txt tex ans asc srt reg ini doc docx mcw dot rtf hlp xls xlr xlt xlw ppt pdf"
+ " sxc sxd sxi sxg sxw stc sti stw stm odt ott odg otg odp otp ods ots odf"
+ " abw afp cwk lwp wpd wps wpt wrf wri"
+ " abf afm bdf fon mgf otf pcf pfa snf ttf"
+ " dbf mdb nsf ntf wdb db fdb gdb"
+ " exe dll ocx vbx sfx sys tlb awx com obj lib out o so "
+ " pdb pch idb ncb opt";
+
+int GetExtIndex(const char *ext)
+{
+ int extIndex = 1;
+ const char *p = g_Exts;
+ for (;;)
+ {
+ char c = *p++;
+ if (c == 0)
+ return extIndex;
+ if (c == ' ')
+ continue;
+ int pos = 0;
+ for (;;)
+ {
+ char c2 = ext[pos++];
+ if (c2 == 0 && (c == 0 || c == ' '))
+ return extIndex;
+ if (c != c2)
+ break;
+ c = *p++;
+ }
+ extIndex++;
+ for (;;)
+ {
+ if (c == 0)
+ return extIndex;
+ if (c == ' ')
+ break;
+ c = *p++;
+ }
+ }
+}
+
+struct CRefItem
+{
+ UInt32 Index;
+ const CUpdateItem *UpdateItem;
+ UInt32 ExtensionPos;
+ UInt32 NamePos;
+ int ExtensionIndex;
+ CRefItem(UInt32 index, const CUpdateItem &updateItem, bool sortByType):
+ Index(index),
+ UpdateItem(&updateItem),
+ ExtensionPos(0),
+ NamePos(0),
+ ExtensionIndex(0)
+ {
+ if (sortByType)
+ {
+ int slashPos = GetReverseSlashPos(updateItem.Name);
+ NamePos = ((slashPos >= 0) ? (slashPos + 1) : 0);
+ int dotPos = updateItem.Name.ReverseFind(L'.');
+ if (dotPos < 0 || (dotPos < slashPos && slashPos >= 0))
+ ExtensionPos = updateItem.Name.Length();
+ else
+ {
+ ExtensionPos = dotPos + 1;
+ UString us = updateItem.Name.Mid(ExtensionPos);
+ if (!us.IsEmpty())
+ {
+ us.MakeLower();
+ int i;
+ AString s;
+ for (i = 0; i < us.Length(); i++)
+ {
+ wchar_t c = us[i];
+ if (c >= 0x80)
+ break;
+ s += (char)c;
+ }
+ if (i == us.Length())
+ ExtensionIndex = GetExtIndex(s);
+ else
+ ExtensionIndex = 0;
+ }
+ }
+ }
+ }
+};
+
+static int CompareUpdateItems(const CRefItem *p1, const CRefItem *p2, void *param)
+{
+ const CRefItem &a1 = *p1;
+ const CRefItem &a2 = *p2;
+ const CUpdateItem &u1 = *a1.UpdateItem;
+ const CUpdateItem &u2 = *a2.UpdateItem;
+ int n;
+ if (u1.IsDirectory != u2.IsDirectory)
+ return (u1.IsDirectory) ? 1 : -1;
+ if (u1.IsDirectory)
+ {
+ if (u1.IsAnti != u2.IsAnti)
+ return (u1.IsAnti ? 1 : -1);
+ n = MyStringCompareNoCase(u1.Name, u2.Name);
+ return -n;
+ }
+ bool sortByType = *(bool *)param;
+ if (sortByType)
+ {
+ RINOZ(MyCompare(a1.ExtensionIndex, a2.ExtensionIndex))
+ RINOZ(MyStringCompareNoCase(u1.Name + a1.ExtensionPos, u2.Name + a2.ExtensionPos));
+ RINOZ(MyStringCompareNoCase(u1.Name + a1.NamePos, u2.Name + a2.NamePos));
+ if (u1.IsLastWriteTimeDefined && u2.IsLastWriteTimeDefined)
+ RINOZ(CompareFileTime(&u1.LastWriteTime, &u2.LastWriteTime));
+ RINOZ(MyCompare(u1.Size, u2.Size))
+ }
+ return MyStringCompareNoCase(u1.Name, u2.Name);
+}
+
+struct CSolidGroup
+{
+ CCompressionMethodMode Method;
+ CRecordVector<UInt32> Indices;
+};
+
+static wchar_t *g_ExeExts[] =
+{
+ L"dll",
+ L"exe",
+ L"ocx",
+ L"sfx",
+ L"sys"
+};
+
+static bool IsExeFile(const UString &ext)
+{
+ for (int i = 0; i < sizeof(g_ExeExts) / sizeof(g_ExeExts[0]); i++)
+ if (ext.CompareNoCase(g_ExeExts[i]) == 0)
+ return true;
+ return false;
+}
+
+static CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };
+static CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+
+static bool GetMethodFull(const CMethodID &methodID,
+ UInt32 numInStreams, CMethodFull &methodResult)
+{
+ methodResult.MethodID = methodID;
+ methodResult.NumInStreams = numInStreams;
+ methodResult.NumOutStreams = 1;
+
+ #ifndef EXCLUDE_COM
+ CMethodInfo methodInfo;
+ if (!GetMethodInfo(methodID, methodInfo))
+ return false;
+ if (!methodInfo.EncoderIsAssigned)
+ return false;
+ methodResult.EncoderClassID = methodInfo.Encoder;
+ methodResult.FilePath = methodInfo.FilePath;
+ if (methodInfo.NumOutStreams != 1 || methodInfo.NumInStreams != numInStreams)
+ return false;
+ #endif
+ return true;
+}
+
+static bool MakeExeMethod(const CCompressionMethodMode &method,
+ bool bcj2Filter, CCompressionMethodMode &exeMethod)
+{
+ exeMethod = method;
+ if (bcj2Filter)
+ {
+ CMethodFull methodFull;
+ if (!GetMethodFull(k_BCJ2, 4, methodFull))
+ return false;
+ exeMethod.Methods.Insert(0, methodFull);
+ if (!GetMethodFull(k_LZMA, 1, methodFull))
+ return false;
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kAlgorithm;
+ property.Value = kAlgorithmForBCJ2_LZMA;
+ methodFull.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kMatchFinder;
+ property.Value = kMatchFinderForBCJ2_LZMA;
+ methodFull.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kDictionarySize;
+ property.Value = kDictionaryForBCJ2_LZMA;
+ methodFull.CoderProperties.Add(property);
+ }
+ {
+ CProperty property;
+ property.PropID = NCoderPropID::kNumFastBytes;
+ property.Value = kNumFastBytesForBCJ2_LZMA;
+ methodFull.CoderProperties.Add(property);
+ }
+
+ exeMethod.Methods.Add(methodFull);
+ exeMethod.Methods.Add(methodFull);
+ CBind bind;
+
+ bind.OutCoder = 0;
+ bind.InStream = 0;
+
+ bind.InCoder = 1;
+ bind.OutStream = 0;
+ exeMethod.Binds.Add(bind);
+
+ bind.InCoder = 2;
+ bind.OutStream = 1;
+ exeMethod.Binds.Add(bind);
+
+ bind.InCoder = 3;
+ bind.OutStream = 2;
+ exeMethod.Binds.Add(bind);
+ }
+ else
+ {
+ CMethodFull methodFull;
+ if (!GetMethodFull(k_BCJ_X86, 1, methodFull))
+ return false;
+ exeMethod.Methods.Insert(0, methodFull);
+ CBind bind;
+ bind.OutCoder = 0;
+ bind.InStream = 0;
+ bind.InCoder = 1;
+ bind.OutStream = 0;
+ exeMethod.Binds.Add(bind);
+ }
+ return true;
+}
+
+static void SplitFilesToGroups(
+ const CCompressionMethodMode &method,
+ bool useFilters, bool maxFilter,
+ const CObjectVector<CUpdateItem> &updateItems,
+ CObjectVector<CSolidGroup> &groups)
+{
+ if (method.Methods.Size() != 1 || method.Binds.Size() != 0)
+ useFilters = false;
+ groups.Clear();
+ groups.Add(CSolidGroup());
+ groups.Add(CSolidGroup());
+ CSolidGroup &generalGroup = groups[0];
+ CSolidGroup &exeGroup = groups[1];
+ generalGroup.Method = method;
+ int i;
+ for (i = 0; i < updateItems.Size(); i++)
+ {
+ const CUpdateItem &updateItem = updateItems[i];
+ if (!updateItem.NewData)
+ continue;
+ if (!updateItem.HasStream())
+ continue;
+ if (useFilters)
+ {
+ const UString name = updateItem.Name;
+ int dotPos = name.ReverseFind(L'.');
+ if (dotPos >= 0)
+ {
+ UString ext = name.Mid(dotPos + 1);
+ if (IsExeFile(ext))
+ {
+ exeGroup.Indices.Add(i);
+ continue;
+ }
+ }
+ }
+ generalGroup.Indices.Add(i);
+ }
+ if (exeGroup.Indices.Size() > 0)
+ if (!MakeExeMethod(method, maxFilter, exeGroup.Method))
+ exeGroup.Method = method;
+ for (i = 0; i < groups.Size();)
+ if (groups[i].Indices.Size() == 0)
+ groups.Delete(i);
+ else
+ i++;
+}
+
+static void FromUpdateItemToFileItem(const CUpdateItem &updateItem,
+ CFileItem &file)
+{
+ file.Name = NItemName::MakeLegalName(updateItem.Name);
+ if (updateItem.AttributesAreDefined)
+ file.SetAttributes(updateItem.Attributes);
+
+ if (updateItem.IsCreationTimeDefined)
+ file.SetCreationTime(updateItem.CreationTime);
+ if (updateItem.IsLastWriteTimeDefined)
+ file.SetLastWriteTime(updateItem.LastWriteTime);
+ if (updateItem.IsLastAccessTimeDefined)
+ file.SetLastAccessTime(updateItem.LastAccessTime);
+
+ file.UnPackSize = updateItem.Size;
+ file.IsDirectory = updateItem.IsDirectory;
+ file.IsAnti = updateItem.IsAnti;
+ file.HasStream = updateItem.HasStream();
+}
+
+static HRESULT Update2(
+ IInStream *inStream,
+ const CArchiveDatabaseEx *database,
+ const CObjectVector<CUpdateItem> &updateItems,
+ ISequentialOutStream *seqOutStream,
+ IArchiveUpdateCallback *updateCallback,
+ const CUpdateOptions &options)
+{
+ UInt64 numSolidFiles = options.NumSolidFiles;
+ if (numSolidFiles == 0)
+ numSolidFiles = 1;
+ /*
+ CMyComPtr<IOutStream> outStream;
+ RINOK(seqOutStream->QueryInterface(IID_IOutStream, (void **)&outStream));
+ if (!outStream)
+ return E_NOTIMPL;
+ */
+
+ UInt64 startBlockSize = database != 0 ?
+ database->ArchiveInfo.StartPosition: 0;
+ if (startBlockSize > 0 && !options.RemoveSfxBlock)
+ {
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
+ RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+ streamSpec->SetStream(inStream);
+ streamSpec->Init(startBlockSize);
+ RINOK(CopyBlock(limitedStream, seqOutStream, NULL));
+ }
+
+ CRecordVector<int> fileIndexToUpdateIndexMap;
+ if (database != 0)
+ {
+ fileIndexToUpdateIndexMap.Reserve(database->Files.Size());
+ for (int i = 0; i < database->Files.Size(); i++)
+ fileIndexToUpdateIndexMap.Add(-1);
+ }
+ int i;
+ for(i = 0; i < updateItems.Size(); i++)
+ {
+ int index = updateItems[i].IndexInArchive;
+ if (index != -1)
+ fileIndexToUpdateIndexMap[index] = i;
+ }
+
+ CRecordVector<int> folderRefs;
+ if (database != 0)
+ {
+ for(i = 0; i < database->Folders.Size(); i++)
+ {
+ CNum indexInFolder = 0;
+ CNum numCopyItems = 0;
+ CNum numUnPackStreams = database->NumUnPackStreamsVector[i];
+ for (CNum fileIndex = database->FolderStartFileIndex[i];
+ indexInFolder < numUnPackStreams; fileIndex++)
+ {
+ if (database->Files[fileIndex].HasStream)
+ {
+ indexInFolder++;
+ int updateIndex = fileIndexToUpdateIndexMap[fileIndex];
+ if (updateIndex >= 0)
+ if (!updateItems[updateIndex].NewData)
+ numCopyItems++;
+ }
+ }
+ if (numCopyItems != numUnPackStreams && numCopyItems != 0)
+ return E_NOTIMPL; // It needs repacking !!!
+ if (numCopyItems > 0)
+ folderRefs.Add(i);
+ }
+ folderRefs.Sort(CompareFolderRefs, (void *)database);
+ }
+
+ CArchiveDatabase newDatabase;
+
+ ////////////////////////////
+
+ COutArchive archive;
+ RINOK(archive.Create(seqOutStream, false));
+ RINOK(archive.SkeepPrefixArchiveHeader());
+ UInt64 complexity = 0;
+ for(i = 0; i < folderRefs.Size(); i++)
+ complexity += database->GetFolderFullPackSize(folderRefs[i]);
+ UInt64 inSizeForReduce = 0;
+ for(i = 0; i < updateItems.Size(); i++)
+ {
+ const CUpdateItem &updateItem = updateItems[i];
+ if (updateItem.NewData)
+ {
+ complexity += updateItem.Size;
+ if (numSolidFiles == 1)
+ {
+ if (updateItem.Size > inSizeForReduce)
+ inSizeForReduce = updateItem.Size;
+ }
+ else
+ inSizeForReduce += updateItem.Size;
+ }
+ }
+ RINOK(updateCallback->SetTotal(complexity));
+ complexity = 0;
+ RINOK(updateCallback->SetCompleted(&complexity));
+
+ /////////////////////////////////////////
+ // Write Copy Items
+
+ for(i = 0; i < folderRefs.Size(); i++)
+ {
+ int folderIndex = folderRefs[i];
+
+ RINOK(WriteRange(inStream, archive.SeqStream,
+ database->GetFolderStreamPos(folderIndex, 0),
+ database->GetFolderFullPackSize(folderIndex),
+ updateCallback, complexity));
+
+ const CFolder &folder = database->Folders[folderIndex];
+ CNum startIndex = database->FolderStartPackStreamIndex[folderIndex];
+ for (int j = 0; j < folder.PackStreams.Size(); j++)
+ {
+ newDatabase.PackSizes.Add(database->PackSizes[startIndex + j]);
+ // newDatabase.PackCRCsDefined.Add(database.PackCRCsDefined[startIndex + j]);
+ // newDatabase.PackCRCs.Add(database.PackCRCs[startIndex + j]);
+ }
+ newDatabase.Folders.Add(folder);
+
+ CNum numUnPackStreams = database->NumUnPackStreamsVector[folderIndex];
+ newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
+
+ CNum indexInFolder = 0;
+ for (CNum fi = database->FolderStartFileIndex[folderIndex];
+ indexInFolder < numUnPackStreams; fi++)
+ {
+ CFileItem file = database->Files[fi];
+ if (file.HasStream)
+ {
+ indexInFolder++;
+ int updateIndex = fileIndexToUpdateIndexMap[fi];
+ if (updateIndex >= 0)
+ {
+ const CUpdateItem &updateItem = updateItems[updateIndex];
+ if (updateItem.NewProperties)
+ {
+ CFileItem file2;
+ FromUpdateItemToFileItem(updateItem, file2);
+ file2.UnPackSize = file.UnPackSize;
+ file2.FileCRC = file.FileCRC;
+ file2.IsFileCRCDefined = file.IsFileCRCDefined;
+ file2.HasStream = file.HasStream;
+ file = file2;
+ }
+ }
+ newDatabase.Files.Add(file);
+ }
+ }
+ }
+
+ /////////////////////////////////////////
+ // Compress New Files
+
+ CObjectVector<CSolidGroup> groups;
+ SplitFilesToGroups(*options.Method, options.UseFilters, options.MaxFilter,
+ updateItems, groups);
+
+ const UInt32 kMinReduceSize = (1 << 16);
+ if (inSizeForReduce < kMinReduceSize)
+ inSizeForReduce = kMinReduceSize;
+
+ for (int groupIndex = 0; groupIndex < groups.Size(); groupIndex++)
+ {
+ const CSolidGroup &group = groups[groupIndex];
+ int numFiles = group.Indices.Size();
+ if (numFiles == 0)
+ continue;
+ CRecordVector<CRefItem> refItems;
+ refItems.Reserve(numFiles);
+ bool sortByType = (numSolidFiles > 1);
+ for (i = 0; i < numFiles; i++)
+ refItems.Add(CRefItem(group.Indices[i], updateItems[group.Indices[i]], sortByType));
+ refItems.Sort(CompareUpdateItems, (void *)&sortByType);
+
+ CRecordVector<UInt32> indices;
+ indices.Reserve(numFiles);
+
+ for (i = 0; i < numFiles; i++)
+ {
+ UInt32 index = refItems[i].Index;
+ indices.Add(index);
+ /*
+ const CUpdateItem &updateItem = updateItems[index];
+ CFileItem file;
+ if (updateItem.NewProperties)
+ FromUpdateItemToFileItem(updateItem, file);
+ else
+ file = database.Files[updateItem.IndexInArchive];
+ if (file.IsAnti || file.IsDirectory)
+ return E_FAIL;
+ newDatabase.Files.Add(file);
+ */
+ }
+
+ CEncoder encoder(group.Method);
+
+ for (i = 0; i < numFiles;)
+ {
+ UInt64 totalSize = 0;
+ int numSubFiles;
+ UString prevExtension;
+ for (numSubFiles = 0; i + numSubFiles < numFiles &&
+ numSubFiles < numSolidFiles; numSubFiles++)
+ {
+ const CUpdateItem &updateItem = updateItems[indices[i + numSubFiles]];
+ totalSize += updateItem.Size;
+ if (totalSize > options.NumSolidBytes)
+ break;
+ if (options.SolidExtension)
+ {
+ UString ext = updateItem.GetExtension();
+ if (numSubFiles == 0)
+ prevExtension = ext;
+ else
+ if (ext.CompareNoCase(prevExtension) != 0)
+ break;
+ }
+ }
+ if (numSubFiles < 1)
+ numSubFiles = 1;
+
+ CFolderInStream *inStreamSpec = new CFolderInStream;
+ CMyComPtr<ISequentialInStream> solidInStream(inStreamSpec);
+ inStreamSpec->Init(updateCallback, &indices[i], numSubFiles);
+
+ CFolder folderItem;
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
+ localProgressSpec->Init(updateCallback, true);
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(localProgress, &complexity, NULL);
+
+ RINOK(encoder.Encode(solidInStream, NULL, &inSizeForReduce, folderItem,
+ archive.SeqStream, newDatabase.PackSizes, compressProgress));
+ // for()
+ // newDatabase.PackCRCsDefined.Add(false);
+ // newDatabase.PackCRCs.Add(0);
+
+ newDatabase.Folders.Add(folderItem);
+
+ CNum numUnPackStreams = 0;
+ for (int subIndex = 0; subIndex < numSubFiles; subIndex++)
+ {
+ const CUpdateItem &updateItem = updateItems[indices[i + subIndex]];
+ CFileItem file;
+ if (updateItem.NewProperties)
+ FromUpdateItemToFileItem(updateItem, file);
+ else
+ file = database->Files[updateItem.IndexInArchive];
+ if (file.IsAnti || file.IsDirectory)
+ return E_FAIL;
+
+ /*
+ CFileItem &file = newDatabase.Files[
+ startFileIndexInDatabase + i + subIndex];
+ */
+ if (!inStreamSpec->Processed[subIndex])
+ {
+ continue;
+ // file.Name += L".locked";
+ }
+
+ file.FileCRC = inStreamSpec->CRCs[subIndex];
+ file.UnPackSize = inStreamSpec->Sizes[subIndex];
+ if (file.UnPackSize != 0)
+ {
+ file.IsFileCRCDefined = true;
+ file.HasStream = true;
+ numUnPackStreams++;
+ complexity += file.UnPackSize;
+ }
+ else
+ {
+ file.IsFileCRCDefined = false;
+ file.HasStream = false;
+ }
+ newDatabase.Files.Add(file);
+ }
+ // numUnPackStreams = 0 is very bad case for locked files
+ // v3.13 doesn't understand it.
+ newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
+ i += numSubFiles;
+ }
+ }
+
+ {
+ /////////////////////////////////////////
+ // Write Empty Files & Folders
+
+ CRecordVector<int> emptyRefs;
+ for(i = 0; i < updateItems.Size(); i++)
+ {
+ const CUpdateItem &updateItem = updateItems[i];
+ if (updateItem.NewData)
+ {
+ if (updateItem.HasStream())
+ continue;
+ }
+ else
+ if (updateItem.IndexInArchive != -1)
+ if (database->Files[updateItem.IndexInArchive].HasStream)
+ continue;
+ emptyRefs.Add(i);
+ }
+ emptyRefs.Sort(CompareEmptyItems, (void *)&updateItems);
+ for(i = 0; i < emptyRefs.Size(); i++)
+ {
+ const CUpdateItem &updateItem = updateItems[emptyRefs[i]];
+ CFileItem file;
+ if (updateItem.NewProperties)
+ FromUpdateItemToFileItem(updateItem, file);
+ else
+ file = database->Files[updateItem.IndexInArchive];
+ newDatabase.Files.Add(file);
+ }
+ }
+
+ /*
+ if (newDatabase.Files.Size() != updateItems.Size())
+ return E_FAIL;
+ */
+
+ return archive.WriteDatabase(newDatabase, options.HeaderMethod, options.HeaderOptions);
+}
+
+#ifdef _7Z_VOL
+
+static HRESULT WriteVolumeHeader(COutArchive &archive, CFileItem &file, const CUpdateOptions &options)
+{
+ CAltCoderInfo altCoder;
+ altCoder.MethodID.IDSize = 1;
+ altCoder.MethodID.ID[0] = 0;
+ CCoderInfo coder;
+ coder.NumInStreams = coder.NumOutStreams = 1;
+ coder.AltCoders.Add(altCoder);
+
+ CFolder folder;
+ folder.Coders.Add(coder);
+ folder.PackStreams.Add(0);
+
+ CNum numUnPackStreams = 0;
+ if (file.UnPackSize != 0)
+ {
+ file.IsFileCRCDefined = true;
+ file.HasStream = true;
+ numUnPackStreams++;
+ }
+ else
+ {
+ throw 1;
+ file.IsFileCRCDefined = false;
+ file.HasStream = false;
+ }
+ folder.UnPackSizes.Add(file.UnPackSize);
+
+ CArchiveDatabase newDatabase;
+ newDatabase.Files.Add(file);
+ newDatabase.Folders.Add(folder);
+ newDatabase.NumUnPackStreamsVector.Add(numUnPackStreams);
+ newDatabase.PackSizes.Add(file.UnPackSize);
+ newDatabase.PackCRCsDefined.Add(false);
+ newDatabase.PackCRCs.Add(file.FileCRC);
+
+ return archive.WriteDatabase(newDatabase,
+ options.HeaderMethod,
+ false,
+ false);
+}
+
+HRESULT UpdateVolume(
+ IInStream *inStream,
+ const CArchiveDatabaseEx *database,
+ CObjectVector<CUpdateItem> &updateItems,
+ ISequentialOutStream *seqOutStream,
+ IArchiveUpdateCallback *updateCallback,
+ const CUpdateOptions &options)
+{
+ if (updateItems.Size() != 1)
+ return E_NOTIMPL;
+
+ CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
+ RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
+ if (!volumeCallback)
+ return E_NOTIMPL;
+
+ CMyComPtr<ISequentialInStream> fileStream;
+ HRESULT result = updateCallback->GetStream(0, &fileStream);
+ if (result != S_OK && result != S_FALSE)
+ return result;
+ if (result == S_FALSE)
+ return E_FAIL;
+
+ CFileItem file;
+
+ const CUpdateItem &updateItem = updateItems[0];
+ if (updateItem.NewProperties)
+ FromUpdateItemToFileItem(updateItem, file);
+ else
+ file = database->Files[updateItem.IndexInArchive];
+ if (file.IsAnti || file.IsDirectory)
+ return E_FAIL;
+
+ UInt64 complexity = 0;
+ file.IsStartPosDefined = true;
+ file.StartPos = 0;
+ for (UInt64 volumeIndex = 0; true; volumeIndex++)
+ {
+ UInt64 volSize;
+ RINOK(volumeCallback->GetVolumeSize(volumeIndex, &volSize));
+ UInt64 pureSize = COutArchive::GetVolPureSize(volSize, file.Name.Length(), true);
+ CMyComPtr<ISequentialOutStream> volumeStream;
+ RINOK(volumeCallback->GetVolumeStream(volumeIndex, &volumeStream));
+
+ COutArchive archive;
+ RINOK(archive.Create(volumeStream, true));
+ RINOK(archive.SkeepPrefixArchiveHeader());
+
+ CSequentialInStreamWithCRC *inCrcStreamSpec = new CSequentialInStreamWithCRC;
+ CMyComPtr<ISequentialInStream> inCrcStream = inCrcStreamSpec;
+ inCrcStreamSpec->Init(fileStream);
+
+ RINOK(WriteRange(inCrcStream, volumeStream, pureSize,
+ updateCallback, complexity));
+ file.UnPackSize = inCrcStreamSpec->GetSize();
+ if (file.UnPackSize == 0)
+ break;
+ file.FileCRC = inCrcStreamSpec->GetCRC();
+ RINOK(WriteVolumeHeader(archive, file, options));
+ file.StartPos += file.UnPackSize;
+ if (file.UnPackSize < pureSize)
+ break;
+ }
+ return S_OK;
+}
+
+class COutVolumeStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ int _volIndex;
+ UInt64 _volSize;
+ UInt64 _curPos;
+ CMyComPtr<ISequentialOutStream> _volumeStream;
+ COutArchive _archive;
+ CCRC _crc;
+
+public:
+ MY_UNKNOWN_IMP
+
+ CFileItem _file;
+ CUpdateOptions _options;
+ CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ void Init(IArchiveUpdateCallback2 *volumeCallback,
+ const UString &name)
+ {
+ _file.Name = name;
+ _file.IsStartPosDefined = true;
+ _file.StartPos = 0;
+
+ VolumeCallback = volumeCallback;
+ _volIndex = 0;
+ _volSize = 0;
+ }
+
+ HRESULT Flush();
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+HRESULT COutVolumeStream::Flush()
+{
+ if (_volumeStream)
+ {
+ _file.UnPackSize = _curPos;
+ _file.FileCRC = _crc.GetDigest();
+ RINOK(WriteVolumeHeader(_archive, _file, _options));
+ _archive.Close();
+ _volumeStream.Release();
+ _file.StartPos += _file.UnPackSize;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COutVolumeStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if(processedSize != NULL)
+ *processedSize = 0;
+ while(size > 0)
+ {
+ if (!_volumeStream)
+ {
+ RINOK(VolumeCallback->GetVolumeSize(_volIndex, &_volSize));
+ RINOK(VolumeCallback->GetVolumeStream(_volIndex, &_volumeStream));
+ _volIndex++;
+ _curPos = 0;
+ RINOK(_archive.Create(_volumeStream, true));
+ RINOK(_archive.SkeepPrefixArchiveHeader());
+ _crc.Init();
+ continue;
+ }
+ UInt64 pureSize = COutArchive::GetVolPureSize(_volSize, _file.Name.Length());
+ UInt32 curSize = (UInt32)MyMin(UInt64(size), pureSize - _curPos);
+
+ _crc.Update(data, curSize);
+ UInt32 realProcessed;
+ RINOK(_volumeStream->Write(data, curSize, &realProcessed))
+ data = (void *)((Byte *)data + realProcessed);
+ size -= realProcessed;
+ if(processedSize != NULL)
+ *processedSize += realProcessed;
+ _curPos += realProcessed;
+ if (realProcessed != curSize && realProcessed == 0)
+ return E_FAIL;
+ if (_curPos == pureSize)
+ {
+ RINOK(Flush());
+ }
+ }
+ return S_OK;
+}
+
+#endif
+
+HRESULT Update(
+ IInStream *inStream,
+ const CArchiveDatabaseEx *database,
+ const CObjectVector<CUpdateItem> &updateItems,
+ ISequentialOutStream *seqOutStream,
+ IArchiveUpdateCallback *updateCallback,
+ const CUpdateOptions &options)
+{
+ #ifdef _7Z_VOL
+ if (seqOutStream)
+ #endif
+ return Update2(inStream, database, updateItems,
+ seqOutStream, updateCallback, options);
+ #ifdef _7Z_VOL
+ if (options.VolumeMode)
+ return UpdateVolume(inStream, database, updateItems,
+ seqOutStream, updateCallback, options);
+ COutVolumeStream *volStreamSpec = new COutVolumeStream;
+ CMyComPtr<ISequentialOutStream> volStream = volStreamSpec;
+ CMyComPtr<IArchiveUpdateCallback2> volumeCallback;
+ RINOK(updateCallback->QueryInterface(IID_IArchiveUpdateCallback2, (void **)&volumeCallback));
+ if (!volumeCallback)
+ return E_NOTIMPL;
+ volStreamSpec->Init(volumeCallback, L"a.7z");
+ volStreamSpec->_options = options;
+ RINOK(Update2(inStream, database, updateItems,
+ volStream, updateCallback, options));
+ return volStreamSpec->Flush();
+ #endif
+}
+
+}}
diff --git a/CPP/7zip/Archive/7z/7zUpdate.h b/CPP/7zip/Archive/7z/7zUpdate.h
new file mode 100755
index 00000000..385bd942
--- /dev/null
+++ b/CPP/7zip/Archive/7z/7zUpdate.h
@@ -0,0 +1,79 @@
+// 7zUpdate.h
+
+#ifndef __7Z_UPDATE_H
+#define __7Z_UPDATE_H
+
+#include "7zIn.h"
+#include "7zOut.h"
+#include "7zCompressionMode.h"
+
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace N7z {
+
+struct CUpdateItem
+{
+ bool NewData;
+ bool NewProperties;
+ int IndexInArchive;
+ int IndexInClient;
+
+ UInt32 Attributes;
+ FILETIME CreationTime;
+ FILETIME LastWriteTime;
+ FILETIME LastAccessTime;
+
+ UInt64 Size;
+ UString Name;
+
+ bool IsAnti;
+ bool IsDirectory;
+
+ bool IsCreationTimeDefined;
+ bool IsLastWriteTimeDefined;
+ bool IsLastAccessTimeDefined;
+ bool AttributesAreDefined;
+
+ const bool HasStream() const
+ { return !IsDirectory && !IsAnti && Size != 0; }
+ CUpdateItem():
+ IsAnti(false),
+ AttributesAreDefined(false),
+ IsCreationTimeDefined(false),
+ IsLastWriteTimeDefined(false),
+ IsLastAccessTimeDefined(false)
+ {}
+ void SetDirectoryStatusFromAttributes()
+ { IsDirectory = ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0); };
+
+ int GetExtensionPos() const;
+ UString GetExtension() const;
+};
+
+struct CUpdateOptions
+{
+ const CCompressionMethodMode *Method;
+ const CCompressionMethodMode *HeaderMethod;
+ bool UseFilters;
+ bool MaxFilter;
+
+ CHeaderOptions HeaderOptions;
+
+ UInt64 NumSolidFiles;
+ UInt64 NumSolidBytes;
+ bool SolidExtension;
+ bool RemoveSfxBlock;
+ bool VolumeMode;
+};
+
+HRESULT Update(
+ IInStream *inStream,
+ const CArchiveDatabaseEx *database,
+ const CObjectVector<CUpdateItem> &updateItems,
+ ISequentialOutStream *seqOutStream,
+ IArchiveUpdateCallback *updateCallback,
+ const CUpdateOptions &options);
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/7z/DllExports.cpp b/CPP/7zip/Archive/7z/DllExports.cpp
new file mode 100755
index 00000000..2d70d4de
--- /dev/null
+++ b/CPP/7zip/Archive/7z/DllExports.cpp
@@ -0,0 +1,113 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "../../../Common/MyInitGuid.h"
+#include "../../../Common/ComTry.h"
+#ifdef _WIN32
+#include "../../../Common/Alloc.h"
+#endif
+
+#include "../../ICoder.h"
+
+#include "7zHandler.h"
+
+#ifndef EXCLUDE_COM
+// {23170F69-40C1-278B-06F1-070100000100}
+DEFINE_GUID(CLSID_CCrypto7zAESEncoder,
+0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00);
+#endif
+
+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
+
+
+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
+ #ifdef _WIN32
+ SetLargePageSize();
+ #endif
+ }
+ return TRUE;
+}
+
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != NArchive::N7z::CLSID_CFormat7z)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID == IID_IInArchive)
+ {
+ CMyComPtr<IInArchive> inArchive = new NArchive::N7z::CHandler;
+ *outObject = inArchive.Detach();
+ }
+ #ifndef EXTRACT_ONLY
+ else if (*interfaceID == IID_IOutArchive)
+ {
+ CMyComPtr<IOutArchive> outArchive = new NArchive::N7z::CHandler;
+ *outObject = outArchive.Detach();
+ }
+ #endif
+ 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"7z";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&NArchive::N7z::CLSID_CFormat7z, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"7z";
+ break;
+ case NArchive::kUpdate:
+ propVariant = true;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)NArchive::N7z::kSignature,
+ NArchive::N7z::kSignatureSize)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/7z/StdAfx.cpp b/CPP/7zip/Archive/7z/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/7z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/7z/StdAfx.h b/CPP/7zip/Archive/7z/StdAfx.h
new file mode 100755
index 00000000..2e4be10b
--- /dev/null
+++ b/CPP/7zip/Archive/7z/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/Archive/7z/makefile b/CPP/7zip/Archive/7z/makefile
new file mode 100755
index 00000000..06bf2f37
--- /dev/null
+++ b/CPP/7zip/Archive/7z/makefile
@@ -0,0 +1,89 @@
+PROG = 7z.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../ -DCOMPRESS_MT
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+7Z_OBJS = \
+ $O\7zCompressionMode.obj \
+ $O\7zDecode.obj \
+ $O\7zEncode.obj \
+ $O\7zExtract.obj \
+ $O\7zFolderInStream.obj \
+ $O\7zFolderOutStream.obj \
+ $O\7zHandler.obj \
+ $O\7zHandlerOut.obj \
+ $O\7zHeader.obj \
+ $O\7zIn.obj \
+ $O\7zMethodID.obj \
+ $O\7zMethods.obj \
+ $O\7zOut.obj \
+ $O\7zProperties.obj \
+ $O\7zSpecStream.obj \
+ $O\7zUpdate.obj \
+ $O\DllExports.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\FileDir.obj \
+ $O\FileFind.obj \
+ $O\FileIO.obj \
+ $O\PropVariant.obj \
+ $O\Synchronization.obj
+
+7ZIP_COMMON_OBJS = \
+ $O\InOutTempBuffer.obj \
+ $O\LimitedStreams.obj \
+ $O\LockedStream.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamBinder.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\CodecsPath.obj \
+ $O\CoderLoader.obj \
+ $O\CoderMixer2.obj \
+ $O\CoderMixer2MT.obj \
+ $O\CrossThreadProgress.obj \
+ $O\FilterCoder.obj \
+ $O\InStreamWithCRC.obj \
+ $O\ItemNameUtils.obj \
+ $O\MultiStream.obj \
+ $O\OutStreamWithCRC.obj \
+ $O\ParseProperties.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(7Z_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(7Z_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/7z/resource.rc b/CPP/7zip/Archive/7z/resource.rc
new file mode 100755
index 00000000..8868173c
--- /dev/null
+++ b/CPP/7zip/Archive/7z/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("7z Plugin", "7z")
+
+101 ICON "7z.ico"
diff --git a/CPP/7zip/Archive/Archive.def b/CPP/7zip/Archive/Archive.def
new file mode 100755
index 00000000..befc7d83
--- /dev/null
+++ b/CPP/7zip/Archive/Archive.def
@@ -0,0 +1,3 @@
+EXPORTS
+ CreateObject PRIVATE
+ GetHandlerProperty PRIVATE
diff --git a/CPP/7zip/Archive/Arj/Arj.dsp b/CPP/7zip/Archive/Arj/Arj.dsp
new file mode 100755
index 00000000..3bc6fa91
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/Arj.dsp
@@ -0,0 +1,329 @@
+# Microsoft Developer Studio Project File - Name="arj" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=arj - 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 "arj.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 "arj.mak" CFG="arj - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "arj - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "arj - 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)" == "arj - 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 "ARJ_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARJ_EXPORTS" /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 0x419 /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\arj.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "arj - 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 "ARJ_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARJ_EXPORTS" /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 0x419 /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\arj.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "arj - Win32 Release"
+# Name "arj - 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\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.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\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\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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ArjHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ArjHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ArjHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ArjIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ArjIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ArjItem.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Group "Codecs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Arj\ArjDecoder1.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Arj\ArjDecoder1.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Arj\ArjDecoder2.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Arj\ArjDecoder2.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
+# 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
+# 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\MSBFDecoder.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\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.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 "Archive Common"
+
+# PROP Default_Filter ""
+# 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 Source File
+
+SOURCE=.\arj.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Arj/Arj.dsw b/CPP/7zip/Archive/Arj/Arj.dsw
new file mode 100755
index 00000000..7ce4bca5
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/Arj.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "arj"=.\arj.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Arj/ArjHandler.cpp b/CPP/7zip/Archive/Arj/ArjHandler.cpp
new file mode 100755
index 00000000..a61cc775
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/ArjHandler.cpp
@@ -0,0 +1,485 @@
+// ArjHandler.cpp
+
+#include "StdAfx.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 "ArjHandler.h"
+
+#include "../../ICoder.h"
+
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Compress/Arj/ArjDecoder1.h"
+#include "../../Compress/Arj/ArjDecoder2.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "../Common/OutStreamWithCRC.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NArj{
+
+const wchar_t *kHostOS[] =
+{
+ L"MSDOS",
+ L"PRIMOS",
+ L"Unix",
+ L"AMIGA",
+ L"Mac",
+ L"OS/2",
+ L"APPLE GS",
+ L"Atari ST",
+ L"Next",
+ L"VAX VMS",
+ L"WIN95"
+};
+
+
+const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
+
+const wchar_t *kUnknownOS = L"Unknown";
+
+
+/*
+enum // PropID
+{
+ kpidHostOS = kpidUserDefined,
+ kpidUnPackVersion,
+ kpidMethod,
+};
+*/
+
+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_UI1},
+ { NULL, kpidHostOS, VT_BSTR}
+
+ // { L"UnPack Version", kpidUnPackVersion, VT_UI1},
+ // { L"Method", kpidMethod, VT_UI1},
+ // { L"Host OS", kpidHostOS, VT_BSTR}
+};
+
+
+CHandler::CHandler()
+{}
+
+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 = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ const CItemEx &item = _items[index];
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant =
+ NItemName::GetOSName(MultiByteToUnicodeString(item.Name, CP_OEMCP));
+ /*
+ NItemName::GetOSName2(
+ MultiByteToUnicodeString(item.Name, item.GetCodePage()));
+ */
+ break;
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = item.Size;
+ break;
+ case kpidPackedSize:
+ propVariant = item.PackSize;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME localFileTime, utcFileTime;
+ if (DosTimeToFileTime(item.ModifiedTime, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ propVariant = utcFileTime;
+ 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:
+ propVariant = item.Method;
+ break;
+ case kpidHostOS:
+ propVariant = (item.HostOS < kNumHostOSes) ?
+ (kHostOS[item.HostOS]) : kUnknownOS;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+class CPropgressImp: public CProgressVirt
+{
+public:
+ CMyComPtr<IArchiveOpenCallback> Callback;
+ STDMETHOD(SetCompleted)(const UInt64 *numFiles);
+};
+
+STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles)
+{
+ if (Callback)
+ return Callback->SetCompleted(numFiles, NULL);
+ return S_OK;
+}
+*/
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *callback)
+{
+ COM_TRY_BEGIN
+ try
+ {
+ _items.Clear();
+ CInArchive archive;
+ if(!archive.Open(inStream, maxCheckStartPosition))
+ return S_FALSE;
+ if (callback != NULL)
+ {
+ RINOK(callback->SetTotal(NULL, NULL));
+ UInt64 numFiles = _items.Size();
+ RINOK(callback->SetCompleted(&numFiles, NULL));
+ }
+ for (;;)
+ {
+ CItemEx itemInfo;
+ bool filled;
+ HRESULT result = archive.GetNextItem(filled, itemInfo);
+ if (result == S_FALSE)
+ return S_FALSE;
+ if (result != S_OK)
+ return S_FALSE;
+ if (!filled)
+ break;
+ _items.Add(itemInfo);
+ archive.IncreaseRealPosition(itemInfo.PackSize);
+ if (callback != NULL)
+ {
+ UInt64 numFiles = _items.Size();
+ RINOK(callback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ _stream = inStream;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ COM_TRY_END
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _items.Clear();
+ _stream.Release();
+ return S_OK;
+}
+
+
+
+//////////////////////////////////////
+// CHandler::DecompressItems
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool testMode = (testModeSpec != 0);
+ UInt64 totalUnPacked = 0, totalPacked = 0;
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = _items.Size();
+ if(numItems == 0)
+ return S_OK;
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ {
+ const CItemEx &itemInfo = _items[allFilesMode ? i : indices[i]];
+ totalUnPacked += itemInfo.Size;
+ totalPacked += itemInfo.PackSize;
+ }
+ extractCallback->SetTotal(totalUnPacked);
+
+ UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
+ UInt64 currentItemUnPacked, currentItemPacked;
+
+ CMyComPtr<ICompressCoder> arj1Decoder;
+ CMyComPtr<ICompressCoder> arj2Decoder;
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ 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 &itemInfo = _items[index];
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ if(itemInfo.IsDirectory())
+ {
+ // if (!testMode)
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ continue;
+ }
+
+ if (!testMode && (!realOutStream))
+ continue;
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+ currentItemUnPacked = itemInfo.Size;
+ currentItemPacked = itemInfo.PackSize;
+
+ {
+ COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->SetStream(realOutStream);
+ outStreamSpec->Init();
+ realOutStream.Release();
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+
+ UInt64 pos;
+ _stream->Seek(itemInfo.DataPosition, STREAM_SEEK_SET, &pos);
+
+ streamSpec->SetStream(_stream);
+ streamSpec->Init(itemInfo.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 (itemInfo.IsEncrypted())
+ {
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+
+ HRESULT result;
+
+ switch(itemInfo.Method)
+ {
+ case NFileHeader::NCompressionMethod::kStored:
+ {
+ if(!copyCoder)
+ copyCoder = new NCompress::CCopyCoder;
+ try
+ {
+ if (itemInfo.IsEncrypted())
+ {
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ else
+ {
+ result = copyCoder->Code(inStream, outStream,
+ NULL, NULL, 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;
+ }
+ break;
+ }
+ case NFileHeader::NCompressionMethod::kCompressed1a:
+ case NFileHeader::NCompressionMethod::kCompressed1b:
+ case NFileHeader::NCompressionMethod::kCompressed1c:
+ {
+ if(!arj1Decoder)
+ {
+ arj1Decoder = new NCompress::NArj::NDecoder1::CCoder;
+ }
+ try
+ {
+ if (itemInfo.IsEncrypted())
+ {
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ else
+ {
+ result = arj1Decoder->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;
+ }
+ break;
+ }
+ case NFileHeader::NCompressionMethod::kCompressed2:
+ {
+ if(!arj2Decoder)
+ {
+ arj2Decoder = new NCompress::NArj::NDecoder2::CCoder;
+ }
+ try
+ {
+ if (itemInfo.IsEncrypted())
+ {
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ else
+ {
+ result = arj2Decoder->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;
+ }
+ break;
+ }
+ default:
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ bool crcOK = outStreamSpec->GetCRC() == itemInfo.FileCRC;
+ outStream.Release();
+ if(crcOK)
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
+ else
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kCRCError))
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+
+}}
diff --git a/CPP/7zip/Archive/Arj/ArjHandler.h b/CPP/7zip/Archive/Arj/ArjHandler.h
new file mode 100755
index 00000000..a1e69ba6
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/ArjHandler.h
@@ -0,0 +1,47 @@
+// ArjHandler.h
+
+#ifndef __ARJ_HANDLER_H
+#define __ARJ_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "ArjIn.h"
+
+namespace NArchive {
+namespace NArj {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *inStream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *callback);
+ 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);
+
+ CHandler();
+private:
+ CObjectVector<CItemEx> _items;
+ CMyComPtr<IInStream> _stream;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Arj/ArjHeader.h b/CPP/7zip/Archive/Arj/ArjHeader.h
new file mode 100755
index 00000000..58ee8c27
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/ArjHeader.h
@@ -0,0 +1,121 @@
+// Archive/Arj/Header.h
+
+#ifndef __ARCHIVE_ARJ_HEADER_H
+#define __ARCHIVE_ARJ_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NArj {
+
+const int kMaxBlockSize = 2600;
+
+namespace NSignature
+{
+ const Byte kSig0 = 0x60;
+ const Byte kSig1 = 0xEA;
+}
+
+/*
+struct CArchiveHeader
+{
+ // UInt16 BasicHeaderSize;
+ Byte FirstHeaderSize;
+ Byte Version;
+ Byte ExtractVersion;
+ Byte HostOS;
+ Byte Flags;
+ Byte SecuryVersion;
+ Byte FileType;
+ Byte Reserved;
+ UInt32 CreatedTime;
+ UInt32 ModifiedTime;
+ UInt32 ArchiveSize;
+ UInt32 SecurityEnvelopeFilePosition;
+ UInt16 FilespecPositionInFilename;
+ UInt16 LengthOfSecurityEnvelopeSata;
+ Byte EncryptionVersion;
+ Byte LastChapter;
+};
+*/
+
+namespace NFileHeader
+{
+ namespace NCompressionMethod
+ {
+ enum EType
+ {
+ kStored = 0,
+ kCompressed1a = 1,
+ kCompressed1b = 2,
+ kCompressed1c = 3,
+ kCompressed2 = 4,
+ kNoDataNoCRC = 8,
+ kNoData = 9,
+ };
+ }
+ namespace NFileType
+ {
+ enum EType
+ {
+ kBinary = 0,
+ k7BitText = 1,
+ kDirectory = 3,
+ kVolumeLablel = 4,
+ kChapterLabel = 5,
+ };
+ }
+ namespace NFlags
+ {
+ const Byte kGarbled = 1;
+ const Byte kVolume = 4;
+ const Byte kExtFile = 8;
+ const Byte kPathSym = 0x10;
+ const Byte kBackup= 0x20;
+ }
+
+ /*
+ struct CHeader
+ {
+ Byte FirstHeaderSize;
+ Byte Version;
+ Byte ExtractVersion;
+ Byte HostOS;
+ Byte Flags;
+ Byte Method;
+ Byte FileType;
+ Byte Reserved;
+ UInt32 ModifiedTime;
+ UInt32 PackSize;
+ UInt32 Size;
+ UInt32 FileCRC;
+ UInt16 FilespecPositionInFilename;
+ UInt16 FileAccessMode;
+ Byte FirstChapter;
+ Byte LastChapter;
+ };
+ */
+
+ namespace NHostOS
+ {
+ enum EEnum
+ {
+ kMSDOS = 0, // filesystem used by MS-DOS, OS/2, Win32
+ // pkarj 2.50 (FAT / VFAT / FAT32 file systems)
+ kPRIMOS = 1,
+ kUnix = 2, // VAX/VMS
+ kAMIGA = 3,
+ kMac = 4,
+ kOS_2 = 5, // what if it's a minix filesystem? [cjh]
+ kAPPLE_GS = 6, // filesystem used by OS/2 (and NT 3.x)
+ kAtari_ST = 7,
+ kNext = 8,
+ kVAX_VMS = 9,
+ kWIN95 = 10
+ };
+ }
+}
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Arj/ArjIn.cpp b/CPP/7zip/Archive/Arj/ArjIn.cpp
new file mode 100755
index 00000000..5d03ea65
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/ArjIn.cpp
@@ -0,0 +1,283 @@
+// Archive/arj/InEngine.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Buffer.h"
+#include "Common/CRC.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "ArjIn.h"
+
+namespace NArchive {
+namespace NArj {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = ReadStream(_stream, data, size, &realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ IncreasePositionValue(realProcessedSize);
+ return result;
+}
+
+static inline UInt16 GetUInt16FromMemLE(const Byte *p)
+{
+ return (UInt16)(p[0] | (((UInt16)p[1]) << 8));
+}
+
+static inline UInt32 GetUInt32FromMemLE(const Byte *p)
+{
+ return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
+}
+
+inline bool TestMarkerCandidate(const void *testBytes, UInt32 maxSize)
+{
+ if (maxSize < 2 + 2 + 4)
+ return false;
+ const Byte *block = ((const Byte *)(testBytes));
+ if (block[0] != NSignature::kSig0 || block[1] != NSignature::kSig1)
+ return false;
+ UInt32 blockSize = GetUInt16FromMemLE(block + 2);
+ if (maxSize < 2 + 2 + blockSize + 4)
+ return false;
+ block += 4;
+ if (blockSize == 0 || blockSize > 2600)
+ return false;
+ UInt32 crcFromFile = GetUInt32FromMemLE(block + blockSize);
+ return (CCRC::VerifyDigest(crcFromFile, block, blockSize));
+}
+
+bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
+{
+ // _archiveInfo.StartPosition = 0;
+ _position = _streamStartPosition;
+ if(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL) != S_OK)
+ return false;
+
+ const int kMarkerSizeMax = 2 + 2 + kMaxBlockSize + 4;
+
+ CByteBuffer byteBuffer;
+ static const UInt32 kSearchMarkerBufferSize = 0x10000;
+ byteBuffer.SetCapacity(kSearchMarkerBufferSize);
+ Byte *buffer = byteBuffer;
+
+ UInt32 processedSize;
+ ReadBytes(buffer, kMarkerSizeMax, &processedSize);
+ if (processedSize == 0)
+ return false;
+ if (TestMarkerCandidate(buffer, processedSize))
+ {
+ _position = _streamStartPosition;
+ if(_stream->Seek(_position, STREAM_SEEK_SET, NULL) != S_OK)
+ return false;
+ return true;
+ }
+
+ UInt32 numBytesPrev = processedSize - 1;
+ memmove(buffer, buffer + 1, numBytesPrev);
+ UInt64 curTestPos = _streamStartPosition + 1;
+ for (;;)
+ {
+ if (searchHeaderSizeLimit != NULL)
+ if (curTestPos - _streamStartPosition > *searchHeaderSizeLimit)
+ return false;
+ UInt32 numReadBytes = kSearchMarkerBufferSize - numBytesPrev;
+ ReadBytes(buffer + numBytesPrev, numReadBytes, &processedSize);
+ UInt32 numBytesInBuffer = numBytesPrev + processedSize;
+ if (numBytesInBuffer < 1)
+ return false;
+ UInt32 numTests = numBytesInBuffer;
+ for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
+ {
+ if (TestMarkerCandidate(buffer + pos, numBytesInBuffer - pos))
+ {
+ // _archiveInfo.StartPosition = curTestPos;
+ _position = curTestPos;
+ if(_stream->Seek(_position, STREAM_SEEK_SET, NULL) != S_OK)
+ return false;
+ return true;
+ }
+ }
+ numBytesPrev = numBytesInBuffer - numTests;
+ memmove(buffer, buffer + numTests, numBytesPrev);
+ }
+}
+
+void CInArchive::IncreasePositionValue(UInt64 addValue)
+{
+ _position += addValue;
+}
+
+void CInArchive::IncreaseRealPosition(UInt64 addValue)
+{
+ if(_stream->Seek(addValue, STREAM_SEEK_CUR, &_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);
+}
+
+Byte CInArchive::SafeReadByte()
+{
+ Byte b;
+ SafeReadBytes(&b, 1);
+ return b;
+}
+
+UInt16 CInArchive::SafeReadUInt16()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ Byte b = SafeReadByte();
+ value |= (UInt16(b) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::SafeReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b = SafeReadByte();
+ value |= (UInt32(b) << (8 * i));
+ }
+ return value;
+}
+
+bool CInArchive::ReadBlock()
+{
+ _blockPos = 0;
+ _blockSize = SafeReadUInt16();
+ if (_blockSize == 0 || _blockSize > kMaxBlockSize)
+ return false;
+ SafeReadBytes(_block, _blockSize);
+ UInt32 crcFromFile = SafeReadUInt32();
+ if (!CCRC::VerifyDigest(crcFromFile, _block, _blockSize))
+ throw CInArchiveException(CInArchiveException::kCRCError);
+ return true;
+}
+
+bool CInArchive::ReadBlock2()
+{
+ Byte id[2];
+ ReadBytesAndTestSize(id, 2);
+ if (id[0] != NSignature::kSig0 || id[1] != NSignature::kSig1)
+ throw CInArchiveException(CInArchiveException::kIncorrectArchive);
+ return ReadBlock();
+}
+
+bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)
+{
+ _stream = inStream;
+ if(_stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition) != S_OK)
+ return false;
+ _position = _streamStartPosition;
+ if (!FindAndReadMarker(searchHeaderSizeLimit))
+ return false;
+ if (!ReadBlock2())
+ return false;
+ for (;;)
+ if (!ReadBlock())
+ break;
+ return true;
+}
+
+void CInArchive::Close()
+{
+ _stream.Release();
+}
+
+void CInArchive::ThrowIncorrectArchiveException()
+{
+ throw CInArchiveException(CInArchiveException::kIncorrectArchive);
+}
+
+Byte CInArchive::ReadByte()
+{
+ if (_blockPos >= _blockSize)
+ ThrowIncorrectArchiveException();
+ return _block[_blockPos++];
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt16(b) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt32(b) << (8 * i));
+ }
+ return value;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+ filled = false;
+ if (!ReadBlock2())
+ return S_OK;
+
+ Byte firstHeaderSize = ReadByte();
+ item.Version = ReadByte();
+ item.ExtractVersion = ReadByte();
+ item.HostOS = ReadByte();
+ item.Flags = ReadByte();
+ item.Method = ReadByte();
+ item.FileType = ReadByte();
+ ReadByte(); // Reserved
+ item.ModifiedTime = ReadUInt32();
+ item.PackSize = ReadUInt32();
+ item.Size = ReadUInt32();
+ item.FileCRC = ReadUInt32();
+ ReadUInt16(); // FilespecPositionInFilename
+ item.FileAccessMode = ReadUInt16();
+ ReadByte(); // FirstChapter
+ ReadByte(); // LastChapter
+
+ /*
+ UInt32 extraData;
+ if ((header.Flags & NFileHeader::NFlags::kExtFile) != 0)
+ extraData = GetUInt32FromMemLE(_block + pos);
+ */
+ _blockPos = firstHeaderSize;
+
+ for (; _blockPos < _blockSize;)
+ item.Name += (char)ReadByte();
+
+ for (;;)
+ if (!ReadBlock())
+ break;
+
+ item.DataPosition = _position;
+
+ filled = true;
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Arj/ArjIn.h b/CPP/7zip/Archive/Arj/ArjIn.h
new file mode 100755
index 00000000..b73d7dba
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/ArjIn.h
@@ -0,0 +1,75 @@
+// Archive/ArjIn.h
+
+#ifndef __ARCHIVE_ARJIN_H
+#define __ARCHIVE_ARJIN_H
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+
+#include "ArjItem.h"
+
+namespace NArchive {
+namespace NArj {
+
+class CInArchiveException
+{
+public:
+ enum CCauseType
+ {
+ kUnexpectedEndOfArchive = 0,
+ kCRCError,
+ kIncorrectArchive,
+ kReadStreamError,
+ kSeekStreamError
+ }
+ Cause;
+ CInArchiveException(CCauseType cause): Cause(cause) {};
+};
+
+class CProgressVirt
+{
+public:
+ STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
+};
+
+class CInArchive
+{
+ CMyComPtr<IInStream> _stream;
+ UInt64 _streamStartPosition;
+ UInt64 _position;
+ UInt16 _blockSize;
+ Byte _block[kMaxBlockSize];
+ UInt32 _blockPos;
+
+
+ bool FindAndReadMarker(const UInt64 *searchHeaderSizeLimit);
+
+ bool ReadBlock();
+ bool ReadBlock2();
+
+ Byte ReadByte();
+ UInt16 ReadUInt16();
+ UInt32 ReadUInt32();
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 *processedSize);
+ bool ReadBytesAndTestSize(void *data, UInt32 size);
+ void SafeReadBytes(void *data, UInt32 size);
+ Byte SafeReadByte();
+ UInt16 SafeReadUInt16();
+ UInt32 SafeReadUInt32();
+
+ void IncreasePositionValue(UInt64 addValue);
+ void ThrowIncorrectArchiveException();
+
+public:
+ HRESULT GetNextItem(bool &filled, CItemEx &item);
+
+ bool Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
+ void Close();
+
+ void IncreaseRealPosition(UInt64 addValue);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Arj/ArjItem.h b/CPP/7zip/Archive/Arj/ArjItem.h
new file mode 100755
index 00000000..d48fe38d
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/ArjItem.h
@@ -0,0 +1,75 @@
+// Archive/ArjItem.h
+
+#ifndef __ARCHIVE_ARJ_ITEM_H
+#define __ARCHIVE_ARJ_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "ArjHeader.h"
+
+namespace NArchive {
+namespace NArj {
+
+struct CVersion
+{
+ Byte Version;
+ Byte HostOS;
+};
+
+inline bool operator==(const CVersion &v1, const CVersion &v2)
+ { return (v1.Version == v2.Version) && (v1.HostOS == v2.HostOS); }
+inline bool operator!=(const CVersion &v1, const CVersion &v2)
+ { return !(v1 == v2); }
+
+class CItem
+{
+public:
+ Byte Version;
+ Byte ExtractVersion;
+ Byte HostOS;
+ Byte Flags;
+ Byte Method;
+ Byte FileType;
+ UInt32 ModifiedTime;
+ UInt32 PackSize;
+ UInt32 Size;
+ UInt32 FileCRC;
+
+ // UInt16 FilespecPositionInFilename;
+ UInt16 FileAccessMode;
+ // Byte FirstChapter;
+ // Byte LastChapter;
+
+ AString Name;
+
+ bool IsEncrypted() const { return (Flags & NFileHeader::NFlags::kGarbled) != 0; }
+ bool IsDirectory() const { return (FileType == NFileHeader::NFileType::kDirectory); }
+ UInt32 GetWinAttributes() const
+ {
+ UInt32 winAtrributes;
+ switch(HostOS)
+ {
+ case NFileHeader::NHostOS::kMSDOS:
+ case NFileHeader::NHostOS::kWIN95:
+ winAtrributes = FileAccessMode;
+ break;
+ default:
+ winAtrributes = 0;
+ }
+ if (IsDirectory())
+ winAtrributes |= FILE_ATTRIBUTE_DIRECTORY;
+ return winAtrributes;
+ }
+};
+
+class CItemEx: public CItem
+{
+public:
+ UInt64 DataPosition;
+};
+
+}}
+
+#endif
+
+
diff --git a/CPP/7zip/Archive/Arj/DllExports.cpp b/CPP/7zip/Archive/Arj/DllExports.cpp
new file mode 100755
index 00000000..d32ca2d6
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/DllExports.cpp
@@ -0,0 +1,72 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "ArjHandler.h"
+
+// {23170F69-40C1-278A-1000-000110040000}
+DEFINE_GUID(CLSID_CArjHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x04, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CArjHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NArj::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Arj";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CArjHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"arj";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const unsigned char sig[] = { 0x60, 0xEA };
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 2)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Arj/StdAfx.cpp b/CPP/7zip/Archive/Arj/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Arj/StdAfx.h b/CPP/7zip/Archive/Arj/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/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/Arj/arj.ico b/CPP/7zip/Archive/Arj/arj.ico
new file mode 100755
index 00000000..c0f8b141
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/arj.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Arj/makefile b/CPP/7zip/Archive/Arj/makefile
new file mode 100755
index 00000000..2609998b
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/makefile
@@ -0,0 +1,66 @@
+PROG = arj.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+ARJ_OBJS = \
+ $O\DllExports.obj \
+ $O\ArjHandler.obj \
+ $O\ArjIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\CRC.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\InBuffer.obj \
+ $O\LimitedStreams.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+ $O\OutStreamWithCRC.obj \
+
+COMPRESS_ARJ_OBJS = \
+ $O\ArjDecoder1.obj \
+ $O\ArjDecoder2.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(ARJ_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_ARJ_OBJS) \
+ $O\CopyCoder.obj \
+ $O\LZOutWindow.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(ARJ_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)
+$(COMPRESS_ARJ_OBJS): ../../Compress/Arj/$(*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/Arj/resource.rc b/CPP/7zip/Archive/Arj/resource.rc
new file mode 100755
index 00000000..5158e405
--- /dev/null
+++ b/CPP/7zip/Archive/Arj/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Arj Plugin", "arj")
+
+101 ICON "arj.ico"
diff --git a/CPP/7zip/Archive/BZip2/BZip2.dsp b/CPP/7zip/Archive/BZip2/BZip2.dsp
new file mode 100755
index 00000000..1d14aedb
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2.dsp
@@ -0,0 +1,281 @@
+# Microsoft Developer Studio Project File - Name="BZip2" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=BZip2 - 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 "BZip2.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 "BZip2.mak" CFG="BZip2 - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "BZip2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "BZip2 - 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)" == "BZip2 - 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 "BZIP2_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BZIP2_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 0x419 /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\bz2.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "BZip2 - 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 "BZIP2_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 "BZIP2_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 0x419 /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\bz2.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "BZip2 - Win32 Release"
+# Name "BZip2 - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Archive.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\BZip2.ico
+# 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"StdAfx.h"
+# 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\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.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
+# 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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compression"
+
+# 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 "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\DummyOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DummyOutStream.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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\BZip2Handler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BZip2Handler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BZip2HandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BZip2Item.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\BZip2Update.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\BZip2Update.h
+# End Source File
+# End Group
+# Begin Group "7zip common"
+
+# PROP Default_Filter ""
+# 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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\bz2.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/BZip2/BZip2.dsw b/CPP/7zip/Archive/BZip2/BZip2.dsw
new file mode 100755
index 00000000..697e5095
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "BZip2"=.\BZip2.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/BZip2/BZip2Handler.cpp b/CPP/7zip/Archive/BZip2/BZip2Handler.cpp
new file mode 100755
index 00000000..169b2597
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2Handler.cpp
@@ -0,0 +1,287 @@
+// BZip2Handler.cpp
+
+#include "StdAfx.h"
+
+#include "BZip2Handler.h"
+
+#include "Common/Defs.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/StreamUtils.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+#include "Common/ComTry.h"
+
+#include "../Common/DummyOutStream.h"
+
+#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);
+#include "../Common/CoderLoader.h"
+extern CSysString GetBZip2CodecPath();
+#endif
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NBZip2 {
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ // { NULL, kpidIsFolder, VT_BOOL},
+ // { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ if (index != 0)
+ return E_INVALIDARG;
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidPackedSize:
+ propVariant = _item.PackSize;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ try
+ {
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));
+ const int kSignatureSize = 3;
+ Byte buffer[kSignatureSize];
+ UInt32 processedSize;
+ RINOK(ReadStream(stream, buffer, kSignatureSize, &processedSize));
+ if (processedSize != kSignatureSize)
+ return S_FALSE;
+ if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
+ return S_FALSE;
+
+ UInt64 endPosition;
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
+ _item.PackSize = endPosition - _streamStartPosition;
+
+ _stream = stream;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _stream.Release();
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (!allFilesMode)
+ {
+ if (numItems == 0)
+ return S_OK;
+ if (numItems != 1)
+ return E_INVALIDARG;
+ if (indices[0] != 0)
+ return E_INVALIDARG;
+ }
+
+ bool testMode = (testModeSpec != 0);
+
+ extractCallback->SetTotal(_item.PackSize);
+
+ UInt64 currentTotalPacked = 0, currentTotalUnPacked = 0;
+
+ RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+
+ RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+
+ if(!testMode && !realOutStream)
+ return S_OK;
+
+
+ extractCallback->PrepareOperation(askMode);
+
+ #ifndef COMPRESS_BZIP2
+ CCoderLibrary lib;
+ #endif
+ CMyComPtr<ICompressCoder> decoder;
+ #ifdef COMPRESS_BZIP2
+ decoder = new NCompress::NBZip2::CDecoder;
+ #else
+ HRESULT loadResult = lib.LoadAndCreateCoder(
+ GetBZip2CodecPath(),
+ CLSID_CCompressBZip2Decoder, &decoder);
+ if (loadResult != S_OK)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ return S_OK;
+ }
+ #endif
+
+ #ifdef COMPRESS_MT
+ {
+ CMyComPtr<ICompressSetCoderMt> setCoderMt;
+ decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ if (setCoderMt)
+ {
+ RINOK(setCoderMt->SetNumberOfThreads(_numThreads));
+ }
+ }
+ #endif
+
+ CDummyOutStream *outStreamSpec = new CDummyOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->Init(realOutStream);
+
+ realOutStream.Release();
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, true);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+
+ RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
+
+
+ HRESULT result = S_OK;
+
+ bool firstItem = true;
+ for (;;)
+ {
+ localCompressProgressSpec->Init(progress,
+ &currentTotalPacked,
+ &currentTotalUnPacked);
+
+ const int kSignatureSize = 3;
+ Byte buffer[kSignatureSize];
+ UInt32 processedSize;
+ RINOK(ReadStream(_stream, buffer, kSignatureSize, &processedSize));
+ if (processedSize < kSignatureSize)
+ {
+ if (firstItem)
+ return E_FAIL;
+ break;
+ }
+ if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h')
+ {
+ if (firstItem)
+ return E_FAIL;
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
+ return S_OK;
+ }
+ firstItem = false;
+
+ UInt64 dataStartPos;
+ RINOK(_stream->Seek((UInt64)(Int64)(-3), STREAM_SEEK_CUR, &dataStartPos));
+
+ result = decoder->Code(_stream, outStream, NULL, NULL, compressProgress);
+
+ if (result != S_OK)
+ break;
+
+ CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
+ decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize,
+ &getInStreamProcessedSize);
+ if (!getInStreamProcessedSize)
+ break;
+
+ UInt64 packSize;
+ RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize));
+ UInt64 pos;
+ RINOK(_stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos));
+ currentTotalPacked = pos - _streamStartPosition;
+ }
+ outStream.Release();
+
+ int retResult;
+ if (result == S_OK)
+ retResult = NArchive::NExtract::NOperationResult::kOK;
+ else if (result == S_FALSE)
+ retResult = NArchive::NExtract::NOperationResult::kDataError;
+ else
+ return result;
+
+ RINOK(extractCallback->SetOperationResult(retResult));
+
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/BZip2/BZip2Handler.h b/CPP/7zip/Archive/BZip2/BZip2Handler.h
new file mode 100755
index 00000000..7977334e
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2Handler.h
@@ -0,0 +1,83 @@
+// BZip2/Handler.h
+
+#ifndef __BZIP2_HANDLER_H
+#define __BZIP2_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "BZip2Item.h"
+
+#ifdef COMPRESS_MT
+#include "../../../Windows/System.h"
+#endif
+
+namespace NArchive {
+namespace NBZip2 {
+
+class CHandler:
+ public IInArchive,
+ public IOutArchive,
+ public ISetProperties,
+ public CMyUnknownImp
+{
+ CMyComPtr<IInStream> _stream;
+ NArchive::NBZip2::CItem _item;
+ UInt64 _streamStartPosition;
+
+ UInt32 _level;
+ UInt32 _dicSize;
+ UInt32 _numPasses;
+ #ifdef COMPRESS_MT
+ UInt32 _numThreads;
+ #endif
+ void InitMethodProperties()
+ {
+ _level = 5;
+ _dicSize =
+ _numPasses = 0xFFFFFFFF;
+ #ifdef COMPRESS_MT
+ _numThreads = NWindows::NSystem::GetNumberOfProcessors();;
+ #endif
+ }
+
+public:
+ MY_UNKNOWN_IMP3(
+ IInArchive,
+ IOutArchive,
+ ISetProperties
+ )
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+ // IOutArchiveHandler
+
+ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback);
+ STDMETHOD(GetFileTimeType)(UInt32 *type);
+
+ // ISetProperties
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties);
+
+ CHandler() { InitMethodProperties(); }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp b/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp
new file mode 100755
index 00000000..b5fc72a9
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2HandlerOut.cpp
@@ -0,0 +1,156 @@
+// BZip2HandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "BZip2Handler.h"
+#include "BZip2Update.h"
+
+#include "Common/Defs.h"
+#include "Common/String.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/ParseProperties.h"
+
+using namespace NWindows;
+
+static const UInt32 kNumPassesX1 = 1;
+static const UInt32 kNumPassesX7 = 2;
+static const UInt32 kNumPassesX9 = 7;
+
+static const UInt32 kDicSizeX1 = 100000;
+static const UInt32 kDicSizeX3 = 500000;
+static const UInt32 kDicSizeX5 = 900000;
+
+namespace NArchive {
+namespace NBZip2 {
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kUnix;
+ return S_OK;
+}
+
+static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ if (numItems != 1)
+ return E_INVALIDARG;
+
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(0,
+ &newData, &newProperties, &indexInArchive));
+
+ if (IntToBool(newProperties))
+ {
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(0, kpidIsFolder, &propVariant));
+ if (propVariant.vt == VT_BOOL)
+ {
+ if (propVariant.boolVal != VARIANT_FALSE)
+ return E_INVALIDARG;
+ }
+ else if (propVariant.vt != VT_EMPTY)
+ return E_INVALIDARG;
+ }
+ }
+
+ if (IntToBool(newData))
+ {
+ UInt64 size;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(0, kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = propVariant.uhVal.QuadPart;
+ }
+
+ UInt32 dicSize = _dicSize;
+ if (dicSize == 0xFFFFFFFF)
+ dicSize = (_level >= 5 ? kDicSizeX5 :
+ (_level >= 3 ? kDicSizeX3 :
+ kDicSizeX1));
+
+ UInt32 numPasses = _numPasses;
+ if (numPasses == 0xFFFFFFFF)
+ numPasses = (_level >= 9 ? kNumPassesX9 :
+ (_level >= 7 ? kNumPassesX7 :
+ kNumPassesX1));
+
+ return UpdateArchive(size, outStream, 0, dicSize, numPasses,
+ #ifdef COMPRESS_MT
+ _numThreads,
+ #endif
+ updateCallback);
+ }
+ if (indexInArchive != 0)
+ return E_INVALIDARG;
+ RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL));
+ return CopyStreams(_stream, outStream);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ InitMethodProperties();
+ #ifdef COMPRESS_MT
+ const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
+ _numThreads = numProcessors;
+ #endif
+
+ 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] == 'X')
+ {
+ UInt32 level = 9;
+ RINOK(ParsePropValue(name.Mid(1), prop, level));
+ _level = level;
+ continue;
+ }
+ if (name[0] == 'D')
+ {
+ UInt32 dicSize = kDicSizeX5;
+ RINOK(ParsePropDictionaryValue(name.Mid(1), prop, dicSize));
+ _dicSize = dicSize;
+ continue;
+ }
+ if (name.Left(4) == L"PASS")
+ {
+ UInt32 num = kNumPassesX9;
+ RINOK(ParsePropValue(name.Mid(4), prop, num));
+ _numPasses = num;
+ continue;
+ }
+ if (name.Left(2) == L"MT")
+ {
+ #ifdef COMPRESS_MT
+ RINOK(ParseMtProp(name.Mid(2), prop, numProcessors, _numThreads));
+ #endif
+ continue;
+ }
+ return E_INVALIDARG;
+ }
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/BZip2/BZip2Item.h b/CPP/7zip/Archive/BZip2/BZip2Item.h
new file mode 100755
index 00000000..d7508ab9
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2Item.h
@@ -0,0 +1,20 @@
+// Archive/BZip2Item.h
+
+#ifndef __ARCHIVE_BZIP2_ITEM_H
+#define __ARCHIVE_BZIP2_ITEM_H
+
+namespace NArchive {
+namespace NBZip2 {
+
+struct CItem
+{
+ UInt64 PackSize;
+ UInt64 UnPackSize;
+};
+
+}}
+
+#endif
+
+
+
diff --git a/CPP/7zip/Archive/BZip2/BZip2Update.cpp b/CPP/7zip/Archive/BZip2/BZip2Update.cpp
new file mode 100755
index 00000000..d9bdf963
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2Update.cpp
@@ -0,0 +1,84 @@
+// BZip2Update.cpp
+
+#include "StdAfx.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "Windows/PropVariant.h"
+
+#include "BZip2Update.h"
+
+#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);
+#include "../Common/CoderLoader.h"
+extern CSysString GetBZip2CodecPath();
+#endif
+
+namespace NArchive {
+namespace NBZip2 {
+
+HRESULT UpdateArchive(UInt64 unpackSize,
+ ISequentialOutStream *outStream,
+ int indexInClient,
+ UInt32 dictionary,
+ UInt32 numPasses,
+ #ifdef COMPRESS_MT
+ UInt32 numThreads,
+ #endif
+ IArchiveUpdateCallback *updateCallback)
+{
+ RINOK(updateCallback->SetTotal(unpackSize));
+ UInt64 complexity = 0;
+ RINOK(updateCallback->SetCompleted(&complexity));
+
+ CMyComPtr<ISequentialInStream> fileInStream;
+
+ RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
+ localProgressSpec->Init(updateCallback, true);
+
+ #ifndef COMPRESS_BZIP2
+ CCoderLibrary lib;
+ #endif
+ CMyComPtr<ICompressCoder> encoder;
+ #ifdef COMPRESS_BZIP2
+ encoder = new NCompress::NBZip2::CEncoder;
+ #else
+ RINOK(lib.LoadAndCreateCoder(GetBZip2CodecPath(),
+ CLSID_CCompressBZip2Encoder, &encoder));
+ #endif
+
+ CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+ encoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties);
+ if (setCoderProperties)
+ {
+ NWindows::NCOM::CPropVariant properties[] =
+ {
+ dictionary,
+ numPasses
+ #ifdef COMPRESS_MT
+ , numThreads
+ #endif
+ };
+ PROPID propIDs[] =
+ {
+ NCoderPropID::kDictionarySize,
+ NCoderPropID::kNumPasses
+ #ifdef COMPRESS_MT
+ , NCoderPropID::kNumThreads
+ #endif
+ };
+ RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, sizeof(propIDs) / sizeof(propIDs[0])));
+ }
+
+ RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, localProgress));
+
+ return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
+}
+
+}}
diff --git a/CPP/7zip/Archive/BZip2/BZip2Update.h b/CPP/7zip/Archive/BZip2/BZip2Update.h
new file mode 100755
index 00000000..ce20e323
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/BZip2Update.h
@@ -0,0 +1,24 @@
+// BZip2Update.h
+
+#ifndef __BZIP2_UPDATE_H
+#define __BZIP2_UPDATE_H
+
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace NBZip2 {
+
+HRESULT UpdateArchive(
+ UInt64 unpackSize,
+ ISequentialOutStream *outStream,
+ int indexInClient,
+ UInt32 dictionary,
+ UInt32 numPasses,
+ #ifdef COMPRESS_MT
+ UInt32 numThreads,
+ #endif
+ IArchiveUpdateCallback *updateCallback);
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/BZip2/DllExports.cpp b/CPP/7zip/Archive/BZip2/DllExports.cpp
new file mode 100755
index 00000000..5a861318
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/DllExports.cpp
@@ -0,0 +1,127 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "BZip2Handler.h"
+#include "../../ICoder.h"
+
+// {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-278A-1000-000110020000}
+DEFINE_GUID(CLSID_CBZip2Handler,
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x02, 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
+
+#ifndef COMPRESS_BZIP2
+#include "../Common/CodecsPath.h"
+CSysString GetBZip2CodecPath()
+{
+ return GetCodecsFolderPrefix() + TEXT("BZip2.dll");
+}
+#endif
+
+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_CBZip2Handler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ int needOut = *interfaceID == IID_IOutArchive;
+ if (needIn || needOut)
+ {
+ NArchive::NBZip2::CHandler *temp = new NArchive::NBZip2::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"BZip2";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CBZip2Handler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"bz2 bzip2 tbz2 tbz";
+ break;
+ case NArchive::kAddExtension:
+ propVariant = L"* * .tar .tar";
+ break;
+ case NArchive::kUpdate:
+ propVariant = true;
+ break;
+ case NArchive::kKeepName:
+ propVariant = true;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const char sig[] = { 'B', 'Z', 'h' };
+ if ((value->bstrVal = ::SysAllocStringByteLen(sig, 3)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/BZip2/StdAfx.cpp b/CPP/7zip/Archive/BZip2/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/BZip2/StdAfx.h b/CPP/7zip/Archive/BZip2/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/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/BZip2/bz2.ico b/CPP/7zip/Archive/BZip2/bz2.ico
new file mode 100755
index 00000000..614e3540
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/bz2.ico
Binary files differ
diff --git a/CPP/7zip/Archive/BZip2/makefile b/CPP/7zip/Archive/BZip2/makefile
new file mode 100755
index 00000000..20f20bdb
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/makefile
@@ -0,0 +1,55 @@
+PROG = bz2.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../ -DCOMPRESS_MT
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+BZ2_OBJS = \
+ $O\BZip2Handler.obj \
+ $O\BZip2HandlerOut.obj \
+ $O\BZip2Update.obj \
+ $O\DllExports.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\CodecsPath.obj \
+ $O\DummyOutStream.obj \
+ $O\ParseProperties.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(BZ2_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(BZ2_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/BZip2/resource.rc b/CPP/7zip/Archive/BZip2/resource.rc
new file mode 100755
index 00000000..2d4f27e3
--- /dev/null
+++ b/CPP/7zip/Archive/BZip2/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("BZip2 Plugin", "bz2")
+
+101 ICON "bz2.ico"
diff --git a/CPP/7zip/Archive/Cab/Cab.dsp b/CPP/7zip/Archive/Cab/Cab.dsp
new file mode 100755
index 00000000..565661f6
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/Cab.dsp
@@ -0,0 +1,395 @@
+# Microsoft Developer Studio Project File - Name="Cab" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Cab - 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 "Cab.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 "Cab.mak" CFG="Cab - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Cab - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Cab - 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)" == "Cab - 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 "CAB_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /FAs /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 0x419 /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\cab.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Cab - 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 "CAB_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CAB_EXPORTS" /FAcs /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 0x419 /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\cab.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Cab - Win32 Release"
+# Name "Cab - 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\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\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\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\CabBlockInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabBlockInStream.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CabItem.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\LSBFDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\LSBFDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\MSBFDecoder.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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# 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
+# Begin Group "Lzx"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\Lzx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\Lzx86Converter.cpp
+
+!IF "$(CFG)" == "Cab - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\Lzx86Converter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\LzxDecoder.cpp
+
+!IF "$(CFG)" == "Cab - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\LzxDecoder.h
+# End Source File
+# End Group
+# Begin Group "Deflate"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Deflate\DeflateConst.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Deflate\DeflateDecoder.cpp
+
+!IF "$(CFG)" == "Cab - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Cab - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Deflate\DeflateDecoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Deflate\DeflateExtConst.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 "Quantum"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Quantum\QuantumDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Quantum\QuantumDecoder.h
+# End Source File
+# End Group
+# Begin Group "Huffman"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Huffman\HuffmanDecoder.h
+# End Source File
+# End Group
+# End Group
+# Begin Source File
+
+SOURCE=.\cab.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Cab/Cab.dsw b/CPP/7zip/Archive/Cab/Cab.dsw
new file mode 100755
index 00000000..470cb1b3
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/Cab.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Cab"=.\Cab.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.cpp b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
new file mode 100755
index 00000000..b775c105
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.cpp
@@ -0,0 +1,194 @@
+// CabBlockInStream.cpp
+
+#include "StdAfx.h"
+
+#include "Common/Alloc.h"
+#include "Common/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "CabBlockInStream.h"
+
+namespace NArchive {
+namespace NCab {
+
+static const UInt32 kBlockSize = (1 << 16);
+
+bool CCabBlockInStream::Create()
+{
+ if (!_buffer)
+ _buffer = (Byte *)::MyAlloc(kBlockSize);
+ return (_buffer != 0);
+}
+
+CCabBlockInStream::~CCabBlockInStream()
+{
+ MyFree(_buffer);
+}
+
+class CCheckSum2
+{
+ UInt32 m_Value;
+ int m_Pos;
+ Byte m_Hist[4];
+public:
+ CCheckSum2(): m_Value(0){};
+ void Init() { m_Value = 0; m_Pos = 0; }
+ void Update(const void *data, UInt32 size);
+ void FinishDataUpdate()
+ {
+ for (int i = 0; i < m_Pos; i++)
+ m_Value ^= ((UInt32)(m_Hist[i])) << (8 * (m_Pos - i - 1));
+ }
+ void UpdateUInt32(UInt32 v) { m_Value ^= v; }
+ UInt32 GetResult() const { return m_Value; }
+};
+
+void CCheckSum2::Update(const void *data, UInt32 size)
+{
+ UInt32 checkSum = m_Value;
+ const Byte *dataPointer = (const Byte *)data;
+
+ while (size != 0 && m_Pos != 0)
+ {
+ m_Hist[m_Pos] = *dataPointer++;
+ m_Pos = (m_Pos + 1) & 3;
+ size--;
+ if (m_Pos == 0)
+ for (int i = 0; i < 4; i++)
+ checkSum ^= ((UInt32)m_Hist[i]) << (8 * i);
+ }
+
+ int numWords = size / 4;
+
+ while (numWords-- != 0)
+ {
+ UInt32 temp = *dataPointer++;
+ temp |= ((UInt32)(*dataPointer++)) << 8;
+ temp |= ((UInt32)(*dataPointer++)) << 16;
+ temp |= ((UInt32)(*dataPointer++)) << 24;
+ checkSum ^= temp;
+ }
+ m_Value = checkSum;
+
+ size &= 3;
+
+ while (size != 0)
+ {
+ m_Hist[m_Pos] = *dataPointer++;
+ m_Pos = (m_Pos + 1) & 3;
+ size--;
+ }
+}
+
+static const UInt32 kDataBlockHeaderSize = 8;
+
+class CTempCabInBuffer2
+{
+public:
+ Byte Buffer[kDataBlockHeaderSize];
+ UInt32 Pos;
+ Byte ReadByte()
+ {
+ return Buffer[Pos++];
+ }
+ UInt32 ReadUInt32()
+ {
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ value |= (((UInt32)ReadByte()) << (8 * i));
+ return value;
+ }
+ UInt16 ReadUInt16()
+ {
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ value |= (((UInt16)ReadByte()) << (8 * i));
+ return value;
+ }
+};
+
+HRESULT CCabBlockInStream::PreRead(UInt32 &packSize, UInt32 &unpackSize)
+{
+ CTempCabInBuffer2 inBuffer;
+ inBuffer.Pos = 0;
+ UInt32 processedSizeLoc;
+ RINOK(ReadStream(_stream, inBuffer.Buffer, kDataBlockHeaderSize, &processedSizeLoc))
+ if (processedSizeLoc != kDataBlockHeaderSize)
+ return S_FALSE; // bad block
+
+ UInt32 checkSum = inBuffer.ReadUInt32();
+ packSize = inBuffer.ReadUInt16();
+ unpackSize = inBuffer.ReadUInt16();
+ if (ReservedSize != 0)
+ {
+ RINOK(ReadStream(_stream, _buffer, ReservedSize, &processedSizeLoc));
+ if(ReservedSize != processedSizeLoc)
+ return S_FALSE; // bad block;
+ }
+ _pos = 0;
+ CCheckSum2 checkSumCalc;
+ checkSumCalc.Init();
+ UInt32 packSize2 = packSize;
+ if (MsZip && _size == 0)
+ {
+ if (packSize < 2)
+ return S_FALSE; // bad block;
+ Byte sig[2];
+ RINOK(ReadStream(_stream, sig, 2, &processedSizeLoc));
+ if(processedSizeLoc != 2)
+ return S_FALSE;
+ if (sig[0] != 0x43 || sig[1] != 0x4B)
+ return S_FALSE;
+ packSize2 -= 2;
+ checkSumCalc.Update(sig, 2);
+ }
+
+ if (kBlockSize - _size < packSize2)
+ return S_FALSE;
+
+ UInt32 curSize = packSize2;
+ if (curSize != 0)
+ {
+ RINOK(ReadStream(_stream, _buffer + _size, curSize, &processedSizeLoc));
+ checkSumCalc.Update(_buffer + _size, processedSizeLoc);
+ _size += processedSizeLoc;
+ if (processedSizeLoc != curSize)
+ return S_FALSE;
+ }
+ TotalPackSize = _size;
+
+ checkSumCalc.FinishDataUpdate();
+
+ bool dataError;
+ if (checkSum == 0)
+ dataError = false;
+ else
+ {
+ checkSumCalc.UpdateUInt32(packSize | (((UInt32)unpackSize) << 16));
+ dataError = (checkSumCalc.GetResult() != checkSum);
+ }
+ DataError |= dataError;
+ return dataError ? S_FALSE : S_OK;
+}
+
+STDMETHODIMP CCabBlockInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (processedSize != 0)
+ *processedSize = 0;
+ if (size == 0)
+ return S_OK;
+ if (_size != 0)
+ {
+ size = MyMin(_size, size);
+ memmove(data, _buffer + _pos, size);
+ _pos += size;
+ _size -= size;
+ if (processedSize != 0)
+ *processedSize = size;
+ return S_OK;
+ }
+ return S_OK; // no blocks data
+}
+
+}}
diff --git a/CPP/7zip/Archive/Cab/CabBlockInStream.h b/CPP/7zip/Archive/Cab/CabBlockInStream.h
new file mode 100755
index 00000000..46e15222
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabBlockInStream.h
@@ -0,0 +1,56 @@
+// CabBlockInStream.cpp
+
+#ifndef __CABBLOCKINSTREAM_H
+#define __CABBLOCKINSTREAM_H
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NCab {
+
+class CCabBlockInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CMyComPtr<ISequentialInStream> _stream;
+ Byte *_buffer;
+ UInt32 _pos;
+ UInt32 _size;
+ int _align;
+
+public:
+ UInt32 TotalPackSize;
+ UInt32 ReservedSize;
+ bool DataError;
+ bool MsZip;
+
+ CCabBlockInStream(): _buffer(0), ReservedSize(0), MsZip(false), DataError(false), _align(0), TotalPackSize(0) {}
+ ~CCabBlockInStream();
+ bool Create();
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+
+ void InitForNewFolder()
+ {
+ _align = 0;
+ TotalPackSize = 0;
+ }
+
+ void InitForNewBlock()
+ {
+ _size = 0;
+ _align = (_align + (int)TotalPackSize) & 1;
+ }
+
+ int GetAlign() const { return _align; }
+
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+ HRESULT PreRead(UInt32 &packSize, UInt32 &unpackSize);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cab/CabHandler.cpp b/CPP/7zip/Archive/Cab/CabHandler.cpp
new file mode 100755
index 00000000..cac79b11
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabHandler.cpp
@@ -0,0 +1,812 @@
+// CabHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Defs.h"
+#include "Common/Alloc.h"
+#include "Common/UTFConvert.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "CabHandler.h"
+#include "CabBlockInStream.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Compress/Deflate/DeflateDecoder.h"
+#include "../../Compress/Lzx/LzxDecoder.h"
+#include "../../Compress/Quantum/QuantumDecoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NCab {
+
+// #define _CAB_DETAILS
+
+#ifdef _CAB_DETAILS
+enum
+{
+ kpidBlockReal = kpidUserDefined,
+ kpidOffset,
+ kpidVolume,
+};
+#endif
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ // { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ { NULL, kpidAttributes, VT_UI4},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidBlock, VT_I4}
+ #ifdef _CAB_DETAILS
+ ,
+ { L"BlockReal", kpidBlockReal, VT_UI4},
+ { L"Offset", kpidOffset, VT_UI4},
+ { L"Volume", kpidVolume, VT_UI4}
+ #endif
+};
+
+static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
+
+static const wchar_t *kMethods[] =
+{
+ L"None",
+ L"MSZip",
+ L"Quantum",
+ L"LZX"
+};
+
+static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
+static const wchar_t *kUnknownMethod = L"Unknown";
+
+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;
+ if (srcItem.lpwstrName == 0)
+ *name = 0;
+ else
+ *name = ::SysAllocString(srcItem.lpwstrName);
+ 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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+
+ const CMvItem &mvItem = m_Database.Items[index];
+ const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
+ int itemIndex = mvItem.ItemIndex;
+ const CItem &item = db.Items[itemIndex];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ UString unicodeName;
+ if (item.IsNameUTF())
+ ConvertUTF8ToUnicode(item.Name, unicodeName);
+ else
+ unicodeName = MultiByteToUnicodeString(item.Name, CP_ACP);
+ propVariant = (const wchar_t *)NItemName::WinNameToOSName(unicodeName);
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = item.Size;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME localFileTime, utcFileTime;
+ if (NTime::DosTimeToFileTime(item.Time, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ propVariant = utcFileTime;
+ break;
+ }
+ case kpidAttributes:
+ propVariant = item.GetWinAttributes();
+ break;
+
+ case kpidMethod:
+ {
+ UInt32 realFolderIndex = item.GetFolderIndex(db.Folders.Size());
+ const CFolder &folder = db.Folders[realFolderIndex];
+ int methodIndex = folder.GetCompressionMethod();
+ UString method = (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
+ if (methodIndex == NHeader::NCompressionMethodMajor::kLZX ||
+ methodIndex == NHeader::NCompressionMethodMajor::kQuantum)
+ {
+ method += L":";
+ wchar_t temp[32];
+ ConvertUInt64ToString(folder.CompressionTypeMinor, temp);
+ method += temp;
+ }
+ propVariant = method;
+ break;
+ }
+ case kpidBlock:
+ propVariant = (Int32)m_Database.GetFolderIndex(&mvItem);
+ break;
+
+ #ifdef _CAB_DETAILS
+
+ case kpidBlockReal:
+ propVariant = UInt32(item.FolderIndex);
+ break;
+ case kpidOffset:
+ propVariant = (UInt32)item.Offset;
+ break;
+ case kpidVolume:
+ propVariant = (UInt32)mvItem.VolumeIndex;
+ break;
+
+ #endif
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+class CPropgressImp: public CProgressVirt
+{
+ CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
+public:
+ STDMETHOD(SetTotal)(const UInt64 *numFiles);
+ STDMETHOD(SetCompleted)(const UInt64 *numFiles);
+ void Init(IArchiveOpenCallback *openArchiveCallback)
+ { m_OpenArchiveCallback = openArchiveCallback; }
+};
+
+STDMETHODIMP CPropgressImp::SetTotal(const UInt64 *numFiles)
+{
+ if (m_OpenArchiveCallback)
+ return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
+ return S_OK;
+}
+
+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
+ Close();
+ HRESULT res = S_FALSE;
+ CInArchive archive;
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ {
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
+ openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
+ }
+
+ CMyComPtr<IInStream> nextStream = inStream;
+ bool prevChecked = false;
+ UInt64 numItems = 0;
+ try
+ {
+ while(nextStream != 0)
+ {
+ CDatabaseEx db;
+ db.Stream = nextStream;
+ res = archive.Open(maxCheckStartPosition, db);
+ if (res == S_OK)
+ {
+ if (!m_Database.Volumes.IsEmpty())
+ {
+ const CDatabaseEx &dbPrev = m_Database.Volumes[prevChecked ? m_Database.Volumes.Size() - 1 : 0];
+ if (dbPrev.ArchiveInfo.SetID != db.ArchiveInfo.SetID ||
+ dbPrev.ArchiveInfo.CabinetNumber + (prevChecked ? 1: - 1) !=
+ db.ArchiveInfo.CabinetNumber)
+ res = S_FALSE;
+ }
+ }
+ if (res == S_OK)
+ m_Database.Volumes.Insert(prevChecked ? m_Database.Volumes.Size() : 0, db);
+ else if (res != S_FALSE)
+ return res;
+ else
+ {
+ if (m_Database.Volumes.IsEmpty())
+ return S_FALSE;
+ if (prevChecked)
+ break;
+ prevChecked = true;
+ }
+
+ numItems += db.Items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numItems, NULL));
+
+ nextStream = 0;
+ for (;;)
+ {
+ const COtherArchive *otherArchive = 0;
+ if (!prevChecked)
+ {
+ const CInArchiveInfo &ai = m_Database.Volumes.Front().ArchiveInfo;
+ if (ai.IsTherePrev())
+ otherArchive = &ai.PreviousArchive;
+ else
+ prevChecked = true;
+ }
+ if (otherArchive == 0)
+ {
+ const CInArchiveInfo &ai = m_Database.Volumes.Back().ArchiveInfo;
+ if (ai.IsThereNext())
+ otherArchive = &ai.NextArchive;
+ }
+ if (!otherArchive)
+ break;
+ const UString fullName = MultiByteToUnicodeString(otherArchive->FileName, CP_ACP);
+ HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
+ if (result == S_OK)
+ break;
+ if (result != S_FALSE)
+ return result;
+ if (prevChecked)
+ break;
+ prevChecked = true;
+ }
+ }
+ if (res == S_OK)
+ {
+ m_Database.FillSortAndShrink();
+ if (!m_Database.Check())
+ res = S_FALSE;
+ }
+ }
+ catch(...)
+ {
+ res = S_FALSE;
+ }
+ if (res != S_OK)
+ {
+ Close();
+ return res;
+ }
+ COM_TRY_END
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ m_Database.Clear();
+ return S_OK;
+}
+
+class CCabFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+ const CMvDatabaseEx *m_Database;
+ const CRecordVector<bool> *m_ExtractStatuses;
+ int m_StartIndex;
+ int m_CurrentIndex;
+ CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
+ bool m_TestMode;
+
+ CMyComPtr<ISequentialOutStream> m_RealOutStream;
+
+ bool m_IsOk;
+ bool m_FileIsOpen;
+ UInt64 m_RemainFileSize;
+ UInt64 m_FolderSize;
+ UInt64 m_PosInFolder;
+
+ HRESULT OpenFile();
+ HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
+public:
+ HRESULT WriteEmptyFiles();
+
+ void Init(
+ const CMvDatabaseEx *database,
+ const CRecordVector<bool> *extractStatuses,
+ int startIndex,
+ UInt64 folderSize,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode);
+ HRESULT FlushCorrupted();
+ HRESULT Unsupported();
+
+ UInt64 GetRemain() const { return m_FolderSize - m_PosInFolder; }
+ UInt64 GetPosInFolder() const { return m_PosInFolder; }
+};
+
+void CCabFolderOutStream::Init(
+ const CMvDatabaseEx *database,
+ const CRecordVector<bool> *extractStatuses,
+ int startIndex,
+ UInt64 folderSize,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode)
+{
+ m_Database = database;
+ m_ExtractStatuses = extractStatuses;
+ m_StartIndex = startIndex;
+ m_FolderSize = folderSize;
+
+ m_ExtractCallback = extractCallback;
+ m_TestMode = testMode;
+
+ m_CurrentIndex = 0;
+ m_PosInFolder = 0;
+ m_FileIsOpen = false;
+ m_IsOk = true;
+}
+
+HRESULT CCabFolderOutStream::OpenFile()
+{
+ Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+ RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));
+ if (!m_RealOutStream && !m_TestMode)
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+ return m_ExtractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CCabFolderOutStream::WriteEmptyFiles()
+{
+ if (m_FileIsOpen)
+ return S_OK;
+ for(;m_CurrentIndex < m_ExtractStatuses->Size(); m_CurrentIndex++)
+ {
+ const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
+ const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
+ UInt64 fileSize = item.Size;
+ if (fileSize != 0)
+ return S_OK;
+ HRESULT result = OpenFile();
+ m_RealOutStream.Release();
+ RINOK(result);
+ RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ return S_OK;
+}
+
+// This is Write function
+HRESULT CCabFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
+{
+ UInt32 realProcessed = 0;
+ if (processedSize != NULL)
+ *processedSize = 0;
+ while(size != 0)
+ {
+ if (m_FileIsOpen)
+ {
+ UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));
+ HRESULT res = S_OK;
+ if (numBytesToWrite > 0)
+ {
+ if (!isOK)
+ m_IsOk = false;
+ if (m_RealOutStream)
+ {
+ UInt32 processedSizeLocal = 0;
+ res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
+ numBytesToWrite = processedSizeLocal;
+ }
+ }
+ realProcessed += numBytesToWrite;
+ if (processedSize != NULL)
+ *processedSize = realProcessed;
+ data = (const void *)((const Byte *)data + numBytesToWrite);
+ size -= numBytesToWrite;
+ m_RemainFileSize -= numBytesToWrite;
+ m_PosInFolder += numBytesToWrite;
+ if (res != S_OK)
+ return res;
+ if (m_RemainFileSize == 0)
+ {
+ m_RealOutStream.Release();
+ RINOK(m_ExtractCallback->SetOperationResult(
+ m_IsOk ?
+ NArchive::NExtract::NOperationResult::kOK:
+ NArchive::NExtract::NOperationResult::kDataError));
+ m_FileIsOpen = false;
+ }
+ if (realProcessed > 0)
+ break; // with this break this function works as Write-Part
+ }
+ else
+ {
+ if (m_CurrentIndex >= m_ExtractStatuses->Size())
+ return E_FAIL;
+
+ const CMvItem &mvItem = m_Database->Items[m_StartIndex + m_CurrentIndex];
+ const CItem &item = m_Database->Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
+
+ m_RemainFileSize = item.Size;
+
+ UInt32 fileOffset = item.Offset;
+ if (fileOffset < m_PosInFolder)
+ return E_FAIL;
+ if (fileOffset > m_PosInFolder)
+ {
+ UInt32 numBytesToWrite = (UInt32)MyMin((UInt64)fileOffset - m_PosInFolder, UInt64(size));
+ realProcessed += numBytesToWrite;
+ if (processedSize != NULL)
+ *processedSize = realProcessed;
+ data = (const void *)((const Byte *)data + numBytesToWrite);
+ size -= numBytesToWrite;
+ m_PosInFolder += numBytesToWrite;
+ }
+ if (fileOffset == m_PosInFolder)
+ {
+ RINOK(OpenFile());
+ m_FileIsOpen = true;
+ m_CurrentIndex++;
+ m_IsOk = true;
+ }
+ }
+ }
+ return WriteEmptyFiles();
+}
+
+STDMETHODIMP CCabFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ return Write2(data, size, processedSize, true);
+}
+
+HRESULT CCabFolderOutStream::FlushCorrupted()
+{
+ const UInt32 kBufferSize = (1 << 10);
+ Byte buffer[kBufferSize];
+ for (int i = 0; i < kBufferSize; i++)
+ buffer[i] = 0;
+ for (;;)
+ {
+ UInt64 remain = GetRemain();
+ if (remain == 0)
+ return S_OK;
+ UInt32 size = (UInt32)MyMin(remain, (UInt64)kBufferSize);
+ UInt32 processedSizeLocal = 0;
+ RINOK(Write2(buffer, size, &processedSizeLocal, false));
+ }
+}
+
+HRESULT CCabFolderOutStream::Unsupported()
+{
+ while(m_CurrentIndex < m_ExtractStatuses->Size())
+ {
+ HRESULT result = OpenFile();
+ if (result != S_FALSE && result != S_OK)
+ return result;
+ m_RealOutStream.Release();
+ RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ m_CurrentIndex++;
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == (UInt32)(-1));
+ if (allFilesMode)
+ numItems = m_Database.Items.Size();
+ if(numItems == 0)
+ return S_OK;
+ bool testMode = (_aTestMode != 0);
+ UInt64 totalUnPacked = 0;
+
+ UInt32 i;
+ int lastFolder = -2;
+ UInt64 lastFolderSize = 0;
+ for(i = 0; i < numItems; i++)
+ {
+ int index = allFilesMode ? i : indices[i];
+ const CMvItem &mvItem = m_Database.Items[index];
+ const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
+ if (item.IsDirectory())
+ continue;
+ int folderIndex = m_Database.GetFolderIndex(&mvItem);
+ if (folderIndex != lastFolder)
+ totalUnPacked += lastFolderSize;
+ lastFolder = folderIndex;
+ lastFolderSize = item.GetEndOffset();
+ }
+ totalUnPacked += lastFolderSize;
+
+ extractCallback->SetTotal(totalUnPacked);
+
+ totalUnPacked = 0;
+
+ NCompress::CCopyCoder *copyCoderSpec = NULL;
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ NCompress::NDeflate::NDecoder::CCOMCoder *deflateDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> deflateDecoder;
+
+ NCompress::NLzx::CDecoder *lzxDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> lzxDecoder;
+
+ NCompress::NQuantum::CDecoder *quantumDecoderSpec = NULL;
+ CMyComPtr<ICompressCoder> quantumDecoder;
+
+ CCabBlockInStream *cabBlockInStreamSpec = new CCabBlockInStream();
+ CMyComPtr<ISequentialInStream> cabBlockInStream = cabBlockInStreamSpec;
+ if (!cabBlockInStreamSpec->Create())
+ return E_OUTOFMEMORY;
+
+ CRecordVector<bool> extractStatuses;
+ for(i = 0; i < numItems;)
+ {
+ int index = allFilesMode ? i : indices[i];
+
+ const CMvItem &mvItem = m_Database.Items[index];
+ const CDatabaseEx &db = m_Database.Volumes[mvItem.VolumeIndex];
+ int itemIndex = mvItem.ItemIndex;
+ const CItem &item = db.Items[itemIndex];
+
+ i++;
+ if (item.IsDirectory())
+ {
+ Int32 askMode= testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ RINOK(extractCallback->PrepareOperation(askMode));
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+ int folderIndex = m_Database.GetFolderIndex(&mvItem);
+ if (folderIndex < 0)
+ {
+ // If we need previous archive
+ Int32 askMode= testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ RINOK(extractCallback->PrepareOperation(askMode));
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ int startIndex2 = m_Database.FolderStartFileIndex[folderIndex];
+ int startIndex = startIndex2;
+ extractStatuses.Clear();
+ for (; startIndex < index; startIndex++)
+ extractStatuses.Add(false);
+ extractStatuses.Add(true);
+ startIndex++;
+ UInt64 curUnpack = item.GetEndOffset();
+ for(;i < numItems; i++)
+ {
+ int indexNext = allFilesMode ? i : indices[i];
+ const CMvItem &mvItem = m_Database.Items[indexNext];
+ const CItem &item = m_Database.Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
+ if (item.IsDirectory())
+ continue;
+ int newFolderIndex = m_Database.GetFolderIndex(&mvItem);
+
+ if (newFolderIndex != folderIndex)
+ break;
+ for (; startIndex < indexNext; startIndex++)
+ extractStatuses.Add(false);
+ extractStatuses.Add(true);
+ startIndex++;
+ curUnpack = item.GetEndOffset();
+ }
+
+ RINOK(extractCallback->SetCompleted(&totalUnPacked));
+
+ CCabFolderOutStream *cabFolderOutStream = new CCabFolderOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(cabFolderOutStream);
+
+ const CFolder &folder = db.Folders[item.GetFolderIndex(db.Folders.Size())];
+
+ cabFolderOutStream->Init(&m_Database, &extractStatuses, startIndex2,
+ curUnpack, extractCallback, testMode);
+
+ cabBlockInStreamSpec->MsZip = false;
+ switch(folder.GetCompressionMethod())
+ {
+ case NHeader::NCompressionMethodMajor::kNone:
+ if(copyCoderSpec == NULL)
+ {
+ copyCoderSpec = new NCompress::CCopyCoder;
+ copyCoder = copyCoderSpec;
+ }
+ break;
+ case NHeader::NCompressionMethodMajor::kMSZip:
+ if(deflateDecoderSpec == NULL)
+ {
+ deflateDecoderSpec = new NCompress::NDeflate::NDecoder::CCOMCoder;
+ deflateDecoder = deflateDecoderSpec;
+ }
+ cabBlockInStreamSpec->MsZip = true;
+ break;
+ case NHeader::NCompressionMethodMajor::kLZX:
+ if(lzxDecoderSpec == NULL)
+ {
+ lzxDecoderSpec = new NCompress::NLzx::CDecoder;
+ lzxDecoder = lzxDecoderSpec;
+ }
+ RINOK(lzxDecoderSpec->SetParams(folder.CompressionTypeMinor));
+ break;
+ case NHeader::NCompressionMethodMajor::kQuantum:
+ if(quantumDecoderSpec == NULL)
+ {
+ quantumDecoderSpec = new NCompress::NQuantum::CDecoder;
+ quantumDecoder = quantumDecoderSpec;
+ }
+ quantumDecoderSpec->SetParams(folder.CompressionTypeMinor);
+ break;
+ default:
+ {
+ RINOK(cabFolderOutStream->Unsupported());
+ totalUnPacked += curUnpack;
+ continue;
+ }
+ }
+
+ cabBlockInStreamSpec->InitForNewFolder();
+
+ HRESULT res = S_OK;
+
+ {
+ int volIndex = mvItem.VolumeIndex;
+ int locFolderIndex = item.GetFolderIndex(db.Folders.Size());
+ bool keepHistory = false;
+ bool keepInputBuffer = false;
+ for (UInt32 f = 0; cabFolderOutStream->GetRemain() != 0;)
+ {
+ if (volIndex >= m_Database.Volumes.Size())
+ {
+ res = S_FALSE;
+ break;
+ }
+
+ const CDatabaseEx &db = m_Database.Volumes[volIndex];
+ const CFolder &folder = db.Folders[locFolderIndex];
+ if (f == 0)
+ {
+ cabBlockInStreamSpec->SetStream(db.Stream);
+ cabBlockInStreamSpec->ReservedSize = db.ArchiveInfo.GetDataBlockReserveSize();
+ RINOK(db.Stream->Seek(db.StartPosition + folder.DataStart, STREAM_SEEK_SET, NULL));
+ }
+ if (f == folder.NumDataBlocks)
+ {
+ volIndex++;
+ locFolderIndex = 0;
+ f = 0;
+ continue;
+ }
+ f++;
+
+ cabBlockInStreamSpec->DataError = false;
+
+ if (!keepInputBuffer)
+ cabBlockInStreamSpec->InitForNewBlock();
+
+ UInt32 packSize, unpackSize;
+ res = cabBlockInStreamSpec->PreRead(packSize, unpackSize);
+ if (res == S_FALSE)
+ break;
+ RINOK(res);
+ keepInputBuffer = (unpackSize == 0);
+ if (keepInputBuffer)
+ continue;
+
+
+ UInt64 totalUnPacked2 = totalUnPacked + cabFolderOutStream->GetPosInFolder();
+ RINOK(extractCallback->SetCompleted(&totalUnPacked2));
+ UInt64 unpackRemain = cabFolderOutStream->GetRemain();
+
+ const UInt32 kBlockSizeMax = (1 << 15);
+ if (unpackRemain > kBlockSizeMax)
+ unpackRemain = kBlockSizeMax;
+ if (unpackRemain > unpackSize)
+ unpackRemain = unpackSize;
+
+ switch(folder.GetCompressionMethod())
+ {
+ case NHeader::NCompressionMethodMajor::kNone:
+ res = copyCoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
+ break;
+ case NHeader::NCompressionMethodMajor::kMSZip:
+ deflateDecoderSpec->SetKeepHistory(keepHistory);
+ res = deflateDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
+ break;
+ case NHeader::NCompressionMethodMajor::kLZX:
+ lzxDecoderSpec->SetKeepHistory(keepHistory, cabBlockInStreamSpec->GetAlign());
+ res = lzxDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
+ break;
+ case NHeader::NCompressionMethodMajor::kQuantum:
+ quantumDecoderSpec->SetKeepHistory(keepHistory);
+ res = quantumDecoder->Code(cabBlockInStream, outStream, NULL, &unpackRemain, NULL);
+ break;
+ }
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ RINOK(res);
+ break;
+ }
+ keepHistory = true;
+ }
+ if (res == S_OK)
+ {
+ RINOK(cabFolderOutStream->WriteEmptyFiles());
+ }
+ }
+ if (res != S_OK || cabFolderOutStream->GetRemain() != 0)
+ {
+ RINOK(cabFolderOutStream->FlushCorrupted());
+ }
+ totalUnPacked += curUnpack;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = m_Database.Items.Size();
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Cab/CabHandler.h b/CPP/7zip/Archive/Cab/CabHandler.h
new file mode 100755
index 00000000..245586b6
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabHandler.h
@@ -0,0 +1,45 @@
+// CabHandler.h
+
+#ifndef __CAB_HANDLER_H
+#define __CAB_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "CabIn.h"
+
+namespace NArchive {
+namespace NCab {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+private:
+ CMvDatabaseEx m_Database;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cab/CabHeader.cpp b/CPP/7zip/Archive/Cab/CabHeader.cpp
new file mode 100755
index 00000000..37533dff
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabHeader.cpp
@@ -0,0 +1,19 @@
+// Archive/Cab/Header.h
+
+#include "StdAfx.h"
+
+#include "CabHeader.h"
+
+namespace NArchive{
+namespace NCab{
+namespace NHeader{
+
+namespace NArchive {
+
+UInt32 kSignature = 0x4643534d + 1;
+static class CSignatureInitializer
+{ public: CSignatureInitializer() { kSignature--; }} g_SignatureInitializer;
+
+}
+
+}}}
diff --git a/CPP/7zip/Archive/Cab/CabHeader.h b/CPP/7zip/Archive/Cab/CabHeader.h
new file mode 100755
index 00000000..5c122743
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabHeader.h
@@ -0,0 +1,42 @@
+// Archive/Cab/Header.h
+
+#ifndef __ARCHIVE_CAB_HEADER_H
+#define __ARCHIVE_CAB_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NCab {
+namespace NHeader{
+
+namespace NArchive
+{
+ extern UInt32 kSignature;
+ namespace NFlags
+ {
+ const int kPrevCabinet = 0x0001;
+ const int kNextCabinet = 0x0002;
+ const int kReservePresent = 0x0004;
+ }
+}
+
+namespace NCompressionMethodMajor
+{
+ const Byte kNone = 0;
+ const Byte kMSZip = 1;
+ const Byte kQuantum = 2;
+ const Byte kLZX = 3;
+}
+
+const int kFileNameIsUTFAttributeMask = 0x80;
+
+namespace NFolderIndex
+{
+ const int kContinuedFromPrev = 0xFFFD;
+ const int kContinuedToNext = 0xFFFE;
+ const int kContinuedPrevAndNext = 0xFFFF;
+}
+
+}}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cab/CabIn.cpp b/CPP/7zip/Archive/Cab/CabIn.cpp
new file mode 100755
index 00000000..ae774f19
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabIn.cpp
@@ -0,0 +1,343 @@
+// Archive/CabIn.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/MyCom.h"
+#include "CabIn.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive{
+namespace NCab{
+
+/*
+static HRESULT ReadBytes(IInStream *inStream, void *data, UInt32 size)
+{
+ UInt32 realProcessedSize;
+ RINOK(ReadStream(inStream, data, size, &realProcessedSize));
+ if(realProcessedSize != size)
+ return S_FALSE;
+ return S_OK;
+}
+
+static HRESULT SafeRead(IInStream *inStream, void *data, UInt32 size)
+{
+ UInt32 realProcessedSize;
+ RINOK(ReadStream(inStream, data, size, &realProcessedSize));
+ if(realProcessedSize != size)
+ throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
+ return S_OK;
+}
+
+static void SafeInByteRead(::CInBuffer &inBuffer, void *data, UInt32 size)
+{
+ UInt32 realProcessedSize;
+ inBuffer.ReadBytes(data, size, realProcessedSize);
+ if(realProcessedSize != size)
+ throw CInArchiveException(CInArchiveException::kUnexpectedEndOfArchive);
+}
+*/
+
+Byte CInArchive::ReadByte()
+{
+ Byte b;
+ if (!inBuffer.ReadByte(b))
+ throw CInArchiveException(CInArchiveException::kUnsupported);
+ return b;
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt16(b) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt32(b) << (8 * i));
+ }
+ return value;
+}
+
+AString CInArchive::SafeReadName()
+{
+ AString name;
+ for (;;)
+ {
+ Byte b = ReadByte();
+ if (b == 0)
+ return name;
+ name += (char)b;
+ }
+}
+
+void CInArchive::ReadOtherArchive(COtherArchive &oa)
+{
+ oa.FileName = SafeReadName();
+ oa.DiskName = SafeReadName();
+}
+
+void CInArchive::Skeep(size_t size)
+{
+ while (size-- != 0)
+ ReadByte();
+}
+
+HRESULT CInArchive::Open2(IInStream *inStream,
+ const UInt64 *searchHeaderSizeLimit,
+ CDatabase &database)
+{
+ database.Clear();
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &database.StartPosition));
+
+ {
+ if (!inBuffer.Create(1 << 17))
+ return E_OUTOFMEMORY;
+ inBuffer.SetStream(inStream);
+ inBuffer.Init();
+ UInt64 value = 0;
+ const int kSignatureSize = 8;
+ UInt64 kSignature64 = NHeader::NArchive::kSignature;
+ for (;;)
+ {
+ Byte b;
+ if (!inBuffer.ReadByte(b))
+ return S_FALSE;
+ value >>= 8;
+ value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);
+ if (inBuffer.GetProcessedSize() >= kSignatureSize)
+ {
+ if (value == kSignature64)
+ break;
+ if (searchHeaderSizeLimit != NULL)
+ if (inBuffer.GetProcessedSize() > (*searchHeaderSizeLimit))
+ return S_FALSE;
+ }
+ }
+ database.StartPosition += inBuffer.GetProcessedSize() - kSignatureSize;
+ }
+
+ CInArchiveInfo &archiveInfo = database.ArchiveInfo;
+
+ archiveInfo.Size = ReadUInt32(); // size of this cabinet file in bytes
+ if (ReadUInt32() != 0)
+ return S_FALSE;
+ archiveInfo.FileHeadersOffset = ReadUInt32(); // offset of the first CFFILE entry
+ if (ReadUInt32() != 0)
+ return S_FALSE;
+
+ archiveInfo.VersionMinor = ReadByte(); // cabinet file format version, minor
+ archiveInfo.VersionMajor = ReadByte(); // cabinet file format version, major
+ archiveInfo.NumFolders = ReadUInt16(); // number of CFFOLDER entries in this cabinet
+ archiveInfo.NumFiles = ReadUInt16(); // number of CFFILE entries in this cabinet
+ archiveInfo.Flags = ReadUInt16(); // number of CFFILE entries in this cabinet
+ archiveInfo.SetID = ReadUInt16(); // must be the same for all cabinets in a set
+ archiveInfo.CabinetNumber = ReadUInt16(); // number of this cabinet file in a set
+
+ if (archiveInfo.ReserveBlockPresent())
+ {
+ archiveInfo.PerCabinetAreaSize = ReadUInt16(); // (optional) size of per-cabinet reserved area
+ archiveInfo.PerFolderAreaSize = ReadByte(); // (optional) size of per-folder reserved area
+ archiveInfo.PerDataBlockAreaSize = ReadByte(); // (optional) size of per-datablock reserved area
+
+ Skeep(archiveInfo.PerCabinetAreaSize);
+ }
+
+ {
+ if (archiveInfo.IsTherePrev())
+ ReadOtherArchive(archiveInfo.PreviousArchive);
+ if (archiveInfo.IsThereNext())
+ ReadOtherArchive(archiveInfo.NextArchive);
+ }
+
+ int i;
+ for(i = 0; i < archiveInfo.NumFolders; i++)
+ {
+ CFolder folder;
+
+ folder.DataStart = ReadUInt32();
+ folder.NumDataBlocks = ReadUInt16();
+ folder.CompressionTypeMajor = ReadByte();
+ folder.CompressionTypeMinor = ReadByte();
+
+ Skeep(archiveInfo.PerFolderAreaSize);
+ database.Folders.Add(folder);
+ }
+
+ RINOK(inStream->Seek(database.StartPosition + archiveInfo.FileHeadersOffset, STREAM_SEEK_SET, NULL));
+
+ inBuffer.SetStream(inStream);
+ inBuffer.Init();
+ for(i = 0; i < archiveInfo.NumFiles; i++)
+ {
+ CItem item;
+ item.Size = ReadUInt32();
+ item.Offset = ReadUInt32();
+ item.FolderIndex = ReadUInt16();
+ UInt16 pureDate = ReadUInt16();
+ UInt16 pureTime = ReadUInt16();
+ item.Time = ((UInt32(pureDate) << 16)) | pureTime;
+ item.Attributes = ReadUInt16();
+ item.Name = SafeReadName();
+ int folderIndex = item.GetFolderIndex(database.Folders.Size());
+ if (folderIndex >= database.Folders.Size())
+ return S_FALSE;
+ database.Items.Add(item);
+ }
+ return S_OK;
+}
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+HRESULT CInArchive::Open(
+ const UInt64 *searchHeaderSizeLimit,
+ CDatabaseEx &database)
+{
+ return Open2(database.Stream, searchHeaderSizeLimit, database);
+}
+
+
+static int CompareMvItems2(const CMvItem *p1, const CMvItem *p2)
+{
+ RINOZ(MyCompare(p1->VolumeIndex, p2->VolumeIndex));
+ return MyCompare(p1->ItemIndex, p2->ItemIndex);
+}
+
+static int CompareMvItems(const CMvItem *p1, const CMvItem *p2, void *param)
+{
+ const CMvDatabaseEx &mvDb = *(const CMvDatabaseEx *)param;
+ const CDatabaseEx &db1 = mvDb.Volumes[p1->VolumeIndex];
+ const CDatabaseEx &db2 = mvDb.Volumes[p2->VolumeIndex];
+ const CItem &item1 = db1.Items[p1->ItemIndex];
+ const CItem &item2 = db2.Items[p2->ItemIndex];;
+ bool isDir1 = item1.IsDirectory();
+ bool isDir2 = item2.IsDirectory();
+ if (isDir1 && !isDir2)
+ return -1;
+ if (isDir2 && !isDir1)
+ return 1;
+ int f1 = mvDb.GetFolderIndex(p1);
+ int f2 = mvDb.GetFolderIndex(p2);
+ RINOZ(MyCompare(f1, f2));
+ RINOZ(MyCompare(item1.Offset, item2.Offset));
+ RINOZ(MyCompare(item1.Size, item2.Size));
+ return CompareMvItems2(p1, p2);
+}
+
+bool CMvDatabaseEx::AreItemsEqual(int i1, int i2)
+{
+ const CMvItem *p1 = &Items[i1];
+ const CMvItem *p2 = &Items[i2];
+ const CDatabaseEx &db1 = Volumes[p1->VolumeIndex];
+ const CDatabaseEx &db2 = Volumes[p2->VolumeIndex];
+ const CItem &item1 = db1.Items[p1->ItemIndex];
+ const CItem &item2 = db2.Items[p2->ItemIndex];;
+ int f1 = GetFolderIndex(p1);
+ int f2 = GetFolderIndex(p2);
+ if (f1 != f2)
+ return false;
+ if (item1.Offset != item2.Offset)
+ return false;
+ if (item1.Size != item2.Size)
+ return false;
+
+ return true;
+}
+
+void CMvDatabaseEx::FillSortAndShrink()
+{
+ Items.Clear();
+ StartFolderOfVol.Clear();
+ FolderStartFileIndex.Clear();
+ int offset = 0;
+ for (int v = 0; v < Volumes.Size(); v++)
+ {
+ const CDatabaseEx &db = Volumes[v];
+ int curOffset = offset;
+ if (db.IsTherePrevFolder())
+ curOffset--;
+ StartFolderOfVol.Add(curOffset);
+ offset += db.GetNumberOfNewFolders();
+
+ CMvItem mvItem;
+ mvItem.VolumeIndex = v;
+ for (int i = 0 ; i < db.Items.Size(); i++)
+ {
+ mvItem.ItemIndex = i;
+ Items.Add(mvItem);
+ }
+ }
+
+ Items.Sort(CompareMvItems, (void *)this);
+ int j = 1;
+ int i;
+ for (i = 1; i < Items.Size(); i++)
+ if (!AreItemsEqual(i, i -1))
+ Items[j++] = Items[i];
+ Items.DeleteFrom(j);
+
+ for (i = 0; i < Items.Size(); i++)
+ {
+ const CMvItem &mvItem = Items[i];
+ int folderIndex = GetFolderIndex(&mvItem);
+ if (folderIndex >= FolderStartFileIndex.Size())
+ FolderStartFileIndex.Add(i);
+ }
+}
+
+bool CMvDatabaseEx::Check()
+{
+ for (int v = 1; v < Volumes.Size(); v++)
+ {
+ const CDatabaseEx &db1 = Volumes[v];
+ if (db1.IsTherePrevFolder())
+ {
+ const CDatabaseEx &db0 = Volumes[v - 1];
+ if (db0.Folders.IsEmpty() || db1.Folders.IsEmpty())
+ return false;
+ const CFolder &f0 = db0.Folders.Back();
+ const CFolder &f1 = db1.Folders.Front();
+ if (f0.CompressionTypeMajor != f1.CompressionTypeMajor ||
+ f0.CompressionTypeMinor != f1.CompressionTypeMinor)
+ return false;
+ }
+ }
+ UInt64 maxPos = 0;
+ int prevFolder = -2;
+ for(int i = 0; i < Items.Size(); i++)
+ {
+ const CMvItem &mvItem = Items[i];
+ int fIndex = GetFolderIndex(&mvItem);
+ if (fIndex >= FolderStartFileIndex.Size())
+ return false;
+ const CItem &item = Volumes[mvItem.VolumeIndex].Items[mvItem.ItemIndex];
+ if (item.IsDirectory())
+ continue;
+ int folderIndex = GetFolderIndex(&mvItem);
+ if (folderIndex != prevFolder)
+ {
+ prevFolder = folderIndex;
+ maxPos = 0;
+ continue;
+ }
+ if (item.Offset < maxPos)
+ return false;
+ maxPos = item.GetEndOffset();
+ if (maxPos < item.Offset)
+ return false;
+ }
+ return true;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Cab/CabIn.h b/CPP/7zip/Archive/Cab/CabIn.h
new file mode 100755
index 00000000..aa3008f1
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabIn.h
@@ -0,0 +1,166 @@
+// Archive/CabIn.h
+
+#ifndef __ARCHIVE_CAB_IN_H
+#define __ARCHIVE_CAB_IN_H
+
+#include "../../IStream.h"
+#include "../../Common/InBuffer.h"
+#include "CabHeader.h"
+#include "CabItem.h"
+
+namespace NArchive {
+namespace NCab {
+
+class CInArchiveException
+{
+public:
+ enum CCauseType
+ {
+ kUnexpectedEndOfArchive = 0,
+ kIncorrectArchive,
+ kUnsupported,
+ } Cause;
+ CInArchiveException(CCauseType cause) : Cause(cause) {}
+};
+
+struct COtherArchive
+{
+ AString FileName;
+ AString DiskName;
+};
+
+struct CArchiveInfo
+{
+ Byte VersionMinor; /* cabinet file format version, minor */
+ Byte VersionMajor; /* cabinet file format version, major */
+ UInt16 NumFolders; /* number of CFFOLDER entries in this cabinet */
+ UInt16 NumFiles; /* number of CFFILE entries in this cabinet */
+ UInt16 Flags; /* cabinet file option indicators */
+ UInt16 SetID; /* must be the same for all cabinets in a set */
+ UInt16 CabinetNumber; /* number of this cabinet file in a set */
+
+ bool ReserveBlockPresent() const { return (Flags & NHeader::NArchive::NFlags::kReservePresent) != 0; }
+
+ bool IsTherePrev() const { return (Flags & NHeader::NArchive::NFlags::kPrevCabinet) != 0; }
+ bool IsThereNext() const { return (Flags & NHeader::NArchive::NFlags::kNextCabinet) != 0; }
+
+ UInt16 PerCabinetAreaSize; // (optional) size of per-cabinet reserved area
+ Byte PerFolderAreaSize; // (optional) size of per-folder reserved area
+ Byte PerDataBlockAreaSize; // (optional) size of per-datablock reserved area
+
+ Byte GetDataBlockReserveSize() const { return (Byte)(ReserveBlockPresent() ? PerDataBlockAreaSize : 0); }
+
+ COtherArchive PreviousArchive;
+ COtherArchive NextArchive;
+
+ CArchiveInfo()
+ {
+ Clear();
+ }
+
+ void Clear()
+ {
+ PerCabinetAreaSize = 0;
+ PerFolderAreaSize = 0;
+ PerDataBlockAreaSize = 0;
+ }
+};
+
+struct CInArchiveInfo: public CArchiveInfo
+{
+ UInt32 Size; /* size of this cabinet file in bytes */
+ UInt32 FileHeadersOffset; // offset of the first CFFILE entry
+};
+
+
+class CDatabase
+{
+public:
+ UInt64 StartPosition;
+ CInArchiveInfo ArchiveInfo;
+ CObjectVector<CFolder> Folders;
+ CObjectVector<CItem> Items;
+ void Clear()
+ {
+ ArchiveInfo.Clear();
+ Folders.Clear();
+ Items.Clear();
+ }
+ bool IsTherePrevFolder() const
+ {
+ for (int i = 0; i < Items.Size(); i++)
+ if (Items[i].ContinuedFromPrev())
+ return true;
+ return false;
+ }
+ int GetNumberOfNewFolders() const
+ {
+ int res = Folders.Size();
+ if (IsTherePrevFolder())
+ res--;
+ return res;
+ }
+ UInt32 GetFileOffset(int index) const { return Items[index].Offset; }
+ UInt32 GetFileSize(int index) const { return Items[index].Size; }
+};
+
+class CDatabaseEx: public CDatabase
+{
+public:
+ CMyComPtr<IInStream> Stream;
+};
+
+struct CMvItem
+{
+ int VolumeIndex;
+ int ItemIndex;
+};
+
+class CMvDatabaseEx
+{
+ bool AreItemsEqual(int i1, int i2);
+public:
+ CObjectVector<CDatabaseEx> Volumes;
+ CRecordVector<CMvItem> Items;
+ CRecordVector<int> StartFolderOfVol;
+ CRecordVector<int> FolderStartFileIndex;
+ int GetFolderIndex(const CMvItem *mvi) const
+ {
+ const CDatabaseEx &db = Volumes[mvi->VolumeIndex];
+ return StartFolderOfVol[mvi->VolumeIndex] +
+ db.Items[mvi->ItemIndex].GetFolderIndex(db.Folders.Size());
+ }
+ void Clear()
+ {
+ Volumes.Clear();
+ Items.Clear();
+ StartFolderOfVol.Clear();
+ FolderStartFileIndex.Clear();
+ }
+ void FillSortAndShrink();
+ bool Check();
+};
+
+class CInArchive
+{
+ CInBuffer inBuffer;
+
+ Byte ReadByte();
+ UInt16 ReadUInt16();
+ UInt32 ReadUInt32();
+ AString SafeReadName();
+ void Skeep(size_t size);
+ void ReadOtherArchive(COtherArchive &oa);
+
+ HRESULT Open2(IInStream *inStream,
+ const UInt64 *searchHeaderSizeLimit,
+ CDatabase &database);
+public:
+ HRESULT Open(
+ const UInt64 *searchHeaderSizeLimit,
+ CDatabaseEx &database);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cab/CabItem.h b/CPP/7zip/Archive/Cab/CabItem.h
new file mode 100755
index 00000000..21327eca
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/CabItem.h
@@ -0,0 +1,62 @@
+// Archive/CabItem.h
+
+#ifndef __ARCHIVE_CAB_ITEM_H
+#define __ARCHIVE_CAB_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "CabHeader.h"
+
+namespace NArchive {
+namespace NCab {
+
+struct CFolder
+{
+ UInt32 DataStart; // offset of the first CFDATA block in this folder
+ UInt16 NumDataBlocks; // number of CFDATA blocks in this folder
+ Byte CompressionTypeMajor;
+ Byte CompressionTypeMinor;
+ Byte GetCompressionMethod() const { return (Byte)(CompressionTypeMajor & 0xF); }
+};
+
+class CItem
+{
+public:
+ AString Name;
+ UInt32 Offset;
+ UInt32 Size;
+ UInt32 Time;
+ UInt16 FolderIndex;
+ UInt16 Flags;
+ UInt16 Attributes;
+ UInt64 GetEndOffset() const { return (UInt64)Offset + Size; }
+ UInt32 GetWinAttributes() const { return (Attributes & ~NHeader::kFileNameIsUTFAttributeMask); }
+ bool IsNameUTF() const { return (Attributes & NHeader::kFileNameIsUTFAttributeMask) != 0; }
+ bool IsDirectory() const { return (Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0; }
+
+ bool ContinuedFromPrev() const
+ {
+ return
+ (FolderIndex == NHeader::NFolderIndex::kContinuedFromPrev) ||
+ (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
+ }
+ bool ContinuedToNext() const
+ {
+ return
+ (FolderIndex == NHeader::NFolderIndex::kContinuedToNext) ||
+ (FolderIndex == NHeader::NFolderIndex::kContinuedPrevAndNext);
+ }
+
+ int GetFolderIndex(int numFolders) const
+ {
+ if (ContinuedFromPrev())
+ return 0;
+ if (ContinuedToNext())
+ return (numFolders - 1);
+ return FolderIndex;
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cab/DllExports.cpp b/CPP/7zip/Archive/Cab/DllExports.cpp
new file mode 100755
index 00000000..fa17f10b
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/DllExports.cpp
@@ -0,0 +1,72 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "CabHandler.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278A-1000-000110080000}
+DEFINE_GUID(CLSID_CCabHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x08, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE, DWORD, LPVOID)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CCabHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NCab::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Cab";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CCabHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"cab";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const char sig[] = { 0x4D, 0x53, 0x43, 0x46 };
+ 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/Cab/StdAfx.cpp b/CPP/7zip/Archive/Cab/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Cab/StdAfx.h b/CPP/7zip/Archive/Cab/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/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/Cab/cab.ico b/CPP/7zip/Archive/Cab/cab.ico
new file mode 100755
index 00000000..cc2007fc
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/cab.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Cab/makefile b/CPP/7zip/Archive/Cab/makefile
new file mode 100755
index 00000000..672afed3
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/makefile
@@ -0,0 +1,70 @@
+PROG = cab.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+CAB_OBJS = \
+ $O\DllExports.obj \
+ $O\CabBlockInStream.obj \
+ $O\CabHandler.obj \
+ $O\CabHeader.obj \
+ $O\CabIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\UTFConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\InBuffer.obj \
+ $O\LSBFDecoder.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+COMPRESS_LZX_OBJS = \
+ $O\LzxDecoder.obj \
+ $O\Lzx86Converter.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(CAB_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(COMPRESS_LZX_OBJS) \
+ $O\DeflateDecoder.obj \
+ $O\QuantumDecoder.obj \
+ $O\LZOutWindow.obj \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(CAB_OBJS): $(*B).cpp
+ $(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$(COMPRESS_LZX_OBJS): ../../Compress/Lzx/$(*B).cpp
+ $(COMPL_O2)
+$O\DeflateDecoder.obj: ../../Compress/Deflate/$(*B).cpp
+ $(COMPL_O2)
+$O\QuantumDecoder.obj: ../../Compress/Quantum/$(*B).cpp
+ $(COMPL)
+$O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
+
diff --git a/CPP/7zip/Archive/Cab/resource.rc b/CPP/7zip/Archive/Cab/resource.rc
new file mode 100755
index 00000000..fa0792bd
--- /dev/null
+++ b/CPP/7zip/Archive/Cab/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Cab Plugin", "cab")
+
+101 ICON "cab.ico"
diff --git a/CPP/7zip/Archive/Chm/Chm.dsp b/CPP/7zip/Archive/Chm/Chm.dsp
new file mode 100755
index 00000000..7e0b7c66
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/Chm.dsp
@@ -0,0 +1,337 @@
+# Microsoft Developer Studio Project File - Name="Chm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Chm - 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 "Chm.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 "Chm.mak" CFG="Chm - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Chm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Chm - 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)" == "Chm - 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 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /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 0x419 /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\chm.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Chm - 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 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CHM_EXPORTS" /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 0x419 /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\chm.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Chm - Win32 Release"
+# Name "Chm - 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"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ChmHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChmHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChmHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChmHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChmIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ChmIn.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\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.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\Buffer.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\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\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# 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
+# Begin Group "Lzx"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\Lzx.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\Lzx86Converter.cpp
+
+!IF "$(CFG)" == "Chm - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Chm - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\Lzx86Converter.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\LzxDecoder.cpp
+
+!IF "$(CFG)" == "Chm - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Chm - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzx\LzxDecoder.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Copy\CopyCoder.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Chm/Chm.dsw b/CPP/7zip/Archive/Chm/Chm.dsw
new file mode 100755
index 00000000..58cb09b2
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/Chm.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Chm"=.\Chm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.cpp b/CPP/7zip/Archive/Chm/ChmHandler.cpp
new file mode 100755
index 00000000..6b37c73e
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/ChmHandler.cpp
@@ -0,0 +1,731 @@
+// Chm/Handler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Defs.h"
+#include "Common/UTFConvert.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/StreamUtils.h"
+#include "../../Common/ProgressUtils.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Compress/Lzx/LzxDecoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+#include "ChmHandler.h"
+
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NChm {
+
+// #define _CHM_DETAILS
+
+#ifdef _CHM_DETAILS
+
+enum
+{
+ kpidSection = kpidUserDefined,
+ kpidOffset
+};
+
+#endif
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ // { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidBlock, VT_UI4}
+
+ #ifdef _CHM_DETAILS
+ ,
+ { L"Section", kpidSection, VT_UI4},
+ { L"Offset", kpidOffset, VT_UI4}
+ #endif
+};
+
+static const int kNumProperties = sizeof(kProperties) / sizeof(kProperties[0]);
+
+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;
+ if (srcItem.lpwstrName == 0)
+ *name = 0;
+ else
+ *name = ::SysAllocString(srcItem.lpwstrName);
+ 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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ if (m_Database.NewFormat)
+ {
+ switch(propID)
+ {
+ case kpidSize:
+ propVariant = (UInt64)m_Database.NewFormatString.Length();
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ }
+ int entryIndex;
+ if (m_Database.LowLevel)
+ entryIndex = index;
+ else
+ entryIndex = m_Database.Indices[index];
+ const CItem &item = m_Database.Items[entryIndex];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ UString us;
+ if (ConvertUTF8ToUnicode(item.Name, us))
+ {
+ if (!m_Database.LowLevel)
+ {
+ if (us.Length() > 1)
+ if (us[0] == L'/')
+ us.Delete(0);
+ }
+ propVariant = NItemName::GetOSName2(us);
+ }
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = item.Size;
+ break;
+ case kpidMethod:
+ {
+ if (!item.IsDirectory())
+ if (item.Section == 0)
+ propVariant = L"Copy";
+ else if (item.Section < m_Database.Sections.Size())
+ propVariant = m_Database.Sections[(int)item.Section].GetMethodName();
+ break;
+ }
+ case kpidBlock:
+ if (m_Database.LowLevel)
+ propVariant = item.Section;
+ else if (item.Section != 0)
+ propVariant = m_Database.GetFolder(index);
+ break;
+
+ #ifdef _CHM_DETAILS
+
+ case kpidSection:
+ propVariant = (UInt32)item.Section;
+ break;
+ case kpidOffset:
+ propVariant = (UInt32)item.Offset;
+ break;
+
+ #endif
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+class CPropgressImp: public CProgressVirt
+{
+ CMyComPtr<IArchiveOpenCallback> m_OpenArchiveCallback;
+public:
+ STDMETHOD(SetTotal)(const UInt64 *numFiles);
+ STDMETHOD(SetCompleted)(const UInt64 *numFiles);
+ void Init(IArchiveOpenCallback *openArchiveCallback)
+ { m_OpenArchiveCallback = openArchiveCallback; }
+};
+
+STDMETHODIMP CPropgressImp::SetTotal(const UInt64 *numFiles)
+{
+ if (m_OpenArchiveCallback)
+ return m_OpenArchiveCallback->SetCompleted(numFiles, NULL);
+ return S_OK;
+}
+
+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
+ m_Stream.Release();
+ try
+ {
+ CInArchive archive;
+ CPropgressImp progressImp;
+ progressImp.Init(openArchiveCallback);
+ RINOK(archive.Open(inStream, maxCheckStartPosition, m_Database));
+ /*
+ if (m_Database.LowLevel)
+ return S_FALSE;
+ */
+ m_Stream = inStream;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ m_Database.Clear();
+ m_Stream.Release();
+ return S_OK;
+}
+
+class CChmFolderOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ HRESULT Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK);
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+
+ UInt64 m_FolderSize;
+ UInt64 m_PosInFolder;
+ UInt64 m_PosInSection;
+ const CRecordVector<bool> *m_ExtractStatuses;
+ int m_StartIndex;
+ int m_CurrentIndex;
+ int m_NumFiles;
+
+private:
+ const CFilesDatabase *m_Database;
+ CMyComPtr<IArchiveExtractCallback> m_ExtractCallback;
+ bool m_TestMode;
+
+ bool m_IsOk;
+ bool m_FileIsOpen;
+ UInt64 m_RemainFileSize;
+ CMyComPtr<ISequentialOutStream> m_RealOutStream;
+
+ HRESULT OpenFile();
+ HRESULT WriteEmptyFiles();
+public:
+ void Init(
+ const CFilesDatabase *database,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode);
+ HRESULT FlushCorrupted();
+};
+
+void CChmFolderOutStream::Init(
+ const CFilesDatabase *database,
+ IArchiveExtractCallback *extractCallback,
+ bool testMode)
+{
+ m_Database = database;
+ m_ExtractCallback = extractCallback;
+ m_TestMode = testMode;
+
+ m_CurrentIndex = 0;
+ m_FileIsOpen = false;
+}
+
+HRESULT CChmFolderOutStream::OpenFile()
+{
+ Int32 askMode = (*m_ExtractStatuses)[m_CurrentIndex] ? (m_TestMode ?
+ NExtract::NAskMode::kTest :
+ NExtract::NAskMode::kExtract) :
+ NExtract::NAskMode::kSkip;
+ m_RealOutStream.Release();
+ RINOK(m_ExtractCallback->GetStream(m_StartIndex + m_CurrentIndex, &m_RealOutStream, askMode));
+ if (!m_RealOutStream && !m_TestMode)
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+ return m_ExtractCallback->PrepareOperation(askMode);
+}
+
+HRESULT CChmFolderOutStream::WriteEmptyFiles()
+{
+ if (m_FileIsOpen)
+ return S_OK;
+ for(;m_CurrentIndex < m_NumFiles; m_CurrentIndex++)
+ {
+ UInt64 fileSize = m_Database->GetFileSize(m_StartIndex + m_CurrentIndex);
+ if (fileSize != 0)
+ return S_OK;
+ HRESULT result = OpenFile();
+ m_RealOutStream.Release();
+ RINOK(result);
+ RINOK(m_ExtractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ return S_OK;
+}
+
+// This is WritePart function
+HRESULT CChmFolderOutStream::Write2(const void *data, UInt32 size, UInt32 *processedSize, bool isOK)
+{
+ UInt32 realProcessed = 0;
+ if (processedSize != NULL)
+ *processedSize = 0;
+ while(size != 0)
+ {
+ if (m_FileIsOpen)
+ {
+ UInt32 numBytesToWrite = (UInt32)MyMin(m_RemainFileSize, (UInt64)(size));
+ HRESULT res = S_OK;
+ if (numBytesToWrite > 0)
+ {
+ if (!isOK)
+ m_IsOk = false;
+ if (m_RealOutStream)
+ {
+ UInt32 processedSizeLocal = 0;
+ res = m_RealOutStream->Write((const Byte *)data, numBytesToWrite, &processedSizeLocal);
+ numBytesToWrite = processedSizeLocal;
+ }
+ }
+ realProcessed += numBytesToWrite;
+ if (processedSize != NULL)
+ *processedSize = realProcessed;
+ data = (const void *)((const Byte *)data + numBytesToWrite);
+ size -= numBytesToWrite;
+ m_RemainFileSize -= numBytesToWrite;
+ m_PosInSection += numBytesToWrite;
+ m_PosInFolder += numBytesToWrite;
+ if (res != S_OK)
+ return res;
+ if (m_RemainFileSize == 0)
+ {
+ m_RealOutStream.Release();
+ RINOK(m_ExtractCallback->SetOperationResult(
+ m_IsOk ?
+ NArchive::NExtract::NOperationResult::kOK:
+ NArchive::NExtract::NOperationResult::kDataError));
+ m_FileIsOpen = false;
+ }
+ if (realProcessed > 0)
+ break; // with this break this function works as write part
+ }
+ else
+ {
+ if (m_CurrentIndex >= m_NumFiles)
+ return E_FAIL;
+ int fullIndex = m_StartIndex + m_CurrentIndex;
+ m_RemainFileSize = m_Database->GetFileSize(fullIndex);
+ UInt64 fileOffset = m_Database->GetFileOffset(fullIndex);
+ if (fileOffset < m_PosInSection)
+ return E_FAIL;
+ if (fileOffset > m_PosInSection)
+ {
+ UInt32 numBytesToWrite = (UInt32)MyMin(fileOffset - m_PosInSection, UInt64(size));
+ realProcessed += numBytesToWrite;
+ if (processedSize != NULL)
+ *processedSize = realProcessed;
+ data = (const void *)((const Byte *)data + numBytesToWrite);
+ size -= numBytesToWrite;
+ m_PosInSection += numBytesToWrite;
+ m_PosInFolder += numBytesToWrite;
+ }
+ if (fileOffset == m_PosInSection)
+ {
+ RINOK(OpenFile());
+ m_FileIsOpen = true;
+ m_CurrentIndex++;
+ m_IsOk = true;
+ }
+ }
+ }
+ return WriteEmptyFiles();
+}
+
+STDMETHODIMP CChmFolderOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ return Write2(data, size, processedSize, true);
+}
+
+HRESULT CChmFolderOutStream::FlushCorrupted()
+{
+ const UInt32 kBufferSize = (1 << 10);
+ Byte buffer[kBufferSize];
+ for (int i = 0; i < kBufferSize; i++)
+ buffer[i] = 0;
+ while(m_PosInFolder < m_FolderSize)
+ {
+ UInt32 size = (UInt32)MyMin(m_FolderSize - m_PosInFolder, (UInt64)kBufferSize);
+ UInt32 processedSizeLocal = 0;
+ RINOK(Write2(buffer, size, &processedSizeLocal, false));
+ }
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == UInt32(-1));
+
+ if (allFilesMode)
+ numItems = m_Database.NewFormat ? 1:
+ (m_Database.LowLevel ?
+ m_Database.Items.Size():
+ m_Database.Indices.Size());
+ if(numItems == 0)
+ return S_OK;
+ bool testMode = (_aTestMode != 0);
+
+ UInt64 currentTotalSize = 0;
+
+ CMyComPtr<ICompressCoder> copyCoder;
+ UInt32 i;
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+
+ if (m_Database.LowLevel)
+ {
+ UInt64 currentItemSize = 0;
+ UInt64 totalSize = 0;
+ if (m_Database.NewFormat)
+ totalSize = m_Database.NewFormatString.Length();
+ else
+ for(i = 0; i < numItems; i++)
+ totalSize += m_Database.Items[allFilesMode ? i : indices[i]].Size;
+ extractCallback->SetTotal(totalSize);
+
+ for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ if (m_Database.NewFormat)
+ {
+ if (index != 0)
+ return E_FAIL;
+ if(!testMode && (!realOutStream))
+ continue;
+ if (!testMode)
+ {
+ UInt32 size = m_Database.NewFormatString.Length();
+ RINOK(WriteStream(realOutStream, (const char *)m_Database.NewFormatString, size, 0));
+ }
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+ const CItem &item = m_Database.Items[index];
+
+ currentItemSize = item.Size;
+
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ if (item.Section != 0)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
+ streamSpec->SetStream(m_Stream);
+ streamSpec->Init(item.Size);
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress, &currentTotalSize, &currentTotalSize);
+
+ if(!copyCoder)
+ copyCoder = new NCompress::CCopyCoder;
+ RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress));
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ return S_OK;
+ }
+
+ UInt64 lastFolderIndex = ((UInt64)0 - 1);
+ for(i = 0; i < numItems; i++)
+ {
+ UInt32 index = allFilesMode ? i : indices[i];
+ int entryIndex = m_Database.Indices[index];
+ const CItem &item = m_Database.Items[entryIndex];
+ UInt64 sectionIndex = item.Section;
+ if (item.IsDirectory() || item.Size == 0)
+ continue;
+ if (sectionIndex == 0)
+ {
+ currentTotalSize += item.Size;
+ continue;
+ }
+ const CSectionInfo &section = m_Database.Sections[(int)item.Section];
+ if (section.IsLzx())
+ {
+ const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
+ UInt64 folderIndex = m_Database.GetFolder(index);
+ if (lastFolderIndex == folderIndex)
+ folderIndex++;
+ lastFolderIndex = m_Database.GetLastFolder(index);
+ for (; folderIndex <= lastFolderIndex; folderIndex++)
+ currentTotalSize += lzxInfo.GetFolderSize();
+ }
+ }
+
+ RINOK(extractCallback->SetTotal(currentTotalSize));
+
+ NCompress::NLzx::CDecoder *lzxDecoderSpec = 0;
+ CMyComPtr<ICompressCoder> lzxDecoder;
+ CChmFolderOutStream *chmFolderOutStream = 0;
+ CMyComPtr<ISequentialOutStream> outStream;
+
+ currentTotalSize = 0;
+
+ CRecordVector<bool> extractStatuses;
+ for(i = 0; i < numItems;)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ UInt32 index = allFilesMode ? i : indices[i];
+ i++;
+ int entryIndex = m_Database.Indices[index];
+ const CItem &item = m_Database.Items[entryIndex];
+ UInt64 sectionIndex = item.Section;
+ Int32 askMode= testMode ?
+ NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ if (item.IsDirectory())
+ {
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ RINOK(extractCallback->PrepareOperation(askMode));
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress, NULL, &currentTotalSize);
+
+ if (item.Size == 0 || sectionIndex == 0)
+ {
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ if (!testMode && item.Size != 0)
+ {
+ RINOK(m_Stream->Seek(m_Database.ContentOffset + item.Offset, STREAM_SEEK_SET, NULL));
+ streamSpec->SetStream(m_Stream);
+ streamSpec->Init(item.Size);
+ if(!copyCoder)
+ copyCoder = new NCompress::CCopyCoder;
+ RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress));
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ currentTotalSize += item.Size;
+ continue;
+ }
+
+ const CSectionInfo &section = m_Database.Sections[(int)sectionIndex];
+
+ if (!section.IsLzx())
+ {
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+
+ const CLzxInfo &lzxInfo = section.Methods[0].LzxInfo;
+
+ if (chmFolderOutStream == 0)
+ {
+ chmFolderOutStream = new CChmFolderOutStream;
+ outStream = chmFolderOutStream;
+ }
+
+ chmFolderOutStream->Init(&m_Database, extractCallback, testMode);
+
+ if(lzxDecoderSpec == NULL)
+ {
+ lzxDecoderSpec = new NCompress::NLzx::CDecoder;
+ lzxDecoder = lzxDecoderSpec;
+ }
+
+ UInt64 folderIndex = m_Database.GetFolder(index);
+
+ UInt64 compressedPos = m_Database.ContentOffset + section.Offset;
+ UInt32 numDictBits = lzxInfo.GetNumDictBits();
+ RINOK(lzxDecoderSpec->SetParams(numDictBits));
+
+ const CItem *lastItem = &item;
+ extractStatuses.Clear();
+ extractStatuses.Add(true);
+
+ for (;; folderIndex++)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+
+ UInt64 startPos = lzxInfo.GetFolderPos(folderIndex);
+ UInt64 finishPos = lastItem->Offset + lastItem->Size;
+ UInt64 limitFolderIndex = lzxInfo.GetFolder(finishPos);
+
+ lastFolderIndex = m_Database.GetLastFolder(index);
+ UInt64 folderSize = lzxInfo.GetFolderSize();
+ UInt64 unPackSize = folderSize;
+ if (extractStatuses.IsEmpty())
+ chmFolderOutStream->m_StartIndex = index + 1;
+ else
+ chmFolderOutStream->m_StartIndex = index;
+ if (limitFolderIndex == folderIndex)
+ {
+ for(; i < numItems; i++)
+ {
+ UInt32 nextIndex = allFilesMode ? i : indices[i];
+ int entryIndex = m_Database.Indices[nextIndex];
+ const CItem &nextItem = m_Database.Items[entryIndex];
+ if (nextItem.Section != sectionIndex)
+ break;
+ UInt64 nextFolderIndex = m_Database.GetFolder(nextIndex);
+ if (nextFolderIndex != folderIndex)
+ break;
+ for (index++; index < nextIndex; index++)
+ extractStatuses.Add(false);
+ extractStatuses.Add(true);
+ index = nextIndex;
+ lastItem = &nextItem;
+ if (nextItem.Size != 0)
+ finishPos = nextItem.Offset + nextItem.Size;
+ lastFolderIndex = m_Database.GetLastFolder(index);
+ }
+ }
+ unPackSize = MyMin(finishPos - startPos, unPackSize);
+
+ chmFolderOutStream->m_FolderSize = folderSize;
+ chmFolderOutStream->m_PosInFolder = 0;
+ chmFolderOutStream->m_PosInSection = startPos;
+ chmFolderOutStream->m_ExtractStatuses = &extractStatuses;
+ chmFolderOutStream->m_NumFiles = extractStatuses.Size();
+ chmFolderOutStream->m_CurrentIndex = 0;
+ try
+ {
+ UInt64 startBlock = lzxInfo.GetBlockIndexFromFolderIndex(folderIndex);
+ const CResetTable &rt = lzxInfo.ResetTable;
+ UInt32 numBlocks = (UInt32)rt.GetNumBlocks(unPackSize);
+ for (UInt32 b = 0; b < numBlocks; b++)
+ {
+ UInt64 completedSize = currentTotalSize + chmFolderOutStream->m_PosInSection - startPos;
+ RINOK(extractCallback->SetCompleted(&completedSize));
+ UInt64 bCur = startBlock + b;
+ if (bCur >= rt.ResetOffsets.Size())
+ return E_FAIL;
+ UInt64 startOffset = rt.ResetOffsets[(int)startBlock];
+ UInt64 offset = rt.ResetOffsets[(int)bCur];
+ UInt64 compressedSize;
+ rt.GetCompressedSizeOfBlock(bCur, compressedSize);
+ UInt64 rem = finishPos - chmFolderOutStream->m_PosInSection;
+ if (rem > rt.BlockSize)
+ rem = rt.BlockSize;
+ // const UInt64 *offsets = (const UInt64 *)&rt.ResetOffsets.Front();
+ RINOK(m_Stream->Seek(compressedPos + offset, STREAM_SEEK_SET, NULL));
+ streamSpec->SetStream(m_Stream);
+ streamSpec->Init(compressedSize);
+ lzxDecoderSpec->SetKeepHistory(b > 0, (int)((offset - startOffset) & 1));
+ RINOK(lzxDecoder->Code(inStream, outStream, NULL, &rem, NULL));
+ }
+ }
+ catch(...)
+ {
+ RINOK(chmFolderOutStream->FlushCorrupted());
+ }
+ currentTotalSize += folderSize;
+ if (folderIndex == lastFolderIndex)
+ break;
+ extractStatuses.Clear();
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = m_Database.NewFormat ? 1:
+ (m_Database.LowLevel ?
+ m_Database.Items.Size():
+ m_Database.Indices.Size());
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Chm/ChmHandler.h b/CPP/7zip/Archive/Chm/ChmHandler.h
new file mode 100755
index 00000000..dd0692ba
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/ChmHandler.h
@@ -0,0 +1,46 @@
+// ChmHandler.h
+
+#ifndef __ARCHIVE_CHM_HANDLER_H
+#define __ARCHIVE_CHM_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "ChmIn.h"
+
+namespace NArchive {
+namespace NChm {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+private:
+ CFilesDatabase m_Database;
+ CMyComPtr<IInStream> m_Stream;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Chm/ChmHeader.cpp b/CPP/7zip/Archive/Chm/ChmHeader.cpp
new file mode 100755
index 00000000..4d485b6c
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/ChmHeader.cpp
@@ -0,0 +1,24 @@
+// Archive/Chm/Header.h
+
+#include "StdAfx.h"
+
+#include "ChmHeader.h"
+
+namespace NArchive{
+namespace NChm{
+namespace NHeader{
+
+UInt32 kItsfSignature = 0x46535449 + 1;
+UInt32 kItolSignature = 0x4C4F5449 + 1;
+static class CSignatureInitializer
+{
+public:
+ CSignatureInitializer()
+ {
+ kItsfSignature--;
+ kItolSignature--;
+ }
+}g_SignatureInitializer;
+
+
+}}}
diff --git a/CPP/7zip/Archive/Chm/ChmHeader.h b/CPP/7zip/Archive/Chm/ChmHeader.h
new file mode 100755
index 00000000..9f1bd42b
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/ChmHeader.h
@@ -0,0 +1,28 @@
+// Archive/Chm/Header.h
+
+#ifndef __ARCHIVE_CHM_HEADER_H
+#define __ARCHIVE_CHM_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NChm {
+namespace NHeader{
+
+const UInt32 kItspSignature = 0x50535449;
+const UInt32 kPmglSignature = 0x4C474D50;
+const UInt32 kLzxcSignature = 0x43585A4C;
+
+const UInt32 kIfcmSignature = 0x4D434649;
+const UInt32 kAollSignature = 0x4C4C4F41;
+const UInt32 kCaolSignature = 0x4C4F4143;
+
+extern UInt32 kItsfSignature;
+
+extern UInt32 kItolSignature;
+const UInt32 kItlsSignature = 0x534C5449;
+UInt64 inline GetHxsSignature() { return ((UInt64)kItlsSignature << 32) | kItolSignature; }
+
+}}}
+
+#endif
diff --git a/CPP/7zip/Archive/Chm/ChmIn.cpp b/CPP/7zip/Archive/Chm/ChmIn.cpp
new file mode 100755
index 00000000..8c56ec91
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/ChmIn.cpp
@@ -0,0 +1,925 @@
+// Archive/ChmIn.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/MyCom.h"
+#include "Common/UTFConvert.h"
+#include "Common/IntToString.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/LimitedStreams.h"
+#include "ChmIn.h"
+
+namespace NArchive{
+namespace NChm{
+
+// define CHM_LOW, if you want to see low level items
+// #define CHM_LOW
+
+static const GUID kChmLzxGuid =
+ { 0x7FC28940, 0x9D31, 0x11D0, 0x9B, 0x27, 0x00, 0xA0, 0xC9, 0x1E, 0x9C, 0x7C };
+static const GUID kHelp2LzxGuid =
+ { 0x0A9007C6, 0x4076, 0x11D3, 0x87, 0x89, 0x00, 0x00, 0xF8, 0x10, 0x57, 0x54 };
+static const GUID kDesGuid =
+ { 0x67F6E4A2, 0x60BF, 0x11D3, 0x85, 0x40, 0x00, 0xC0, 0x4F, 0x58, 0xC3, 0xCF };
+
+static bool AreGuidsEqual(REFGUID g1, REFGUID g2)
+{
+ if (g1.Data1 != g2.Data1 ||
+ g1.Data2 != g2.Data2 ||
+ g1.Data3 != g2.Data3)
+ return false;
+ for (int i = 0; i < 8; i++)
+ if (g1.Data4[i] != g2.Data4[i])
+ return false;
+ return true;
+}
+
+static char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+static void PrintByte(Byte b, AString &s)
+{
+ s += GetHex(b >> 4);
+ s += GetHex(b & 0xF);
+}
+
+static void PrintUInt16(UInt16 v, AString &s)
+{
+ PrintByte((Byte)(v >> 8), s);
+ PrintByte((Byte)v, s);
+}
+
+static void PrintUInt32(UInt32 v, AString &s)
+{
+ PrintUInt16((UInt16)(v >> 16), s);
+ PrintUInt16((UInt16)v, s);
+}
+
+AString CMethodInfo::GetGuidString() const
+{
+ AString s;
+ s += '{';
+ PrintUInt32(Guid.Data1, s);
+ s += '-';
+ PrintUInt16(Guid.Data2, s);
+ s += '-';
+ PrintUInt16(Guid.Data3, s);
+ s += '-';
+ PrintByte(Guid.Data4[0], s);
+ PrintByte(Guid.Data4[1], s);
+ s += '-';
+ for (int i = 2; i < 8; i++)
+ PrintByte(Guid.Data4[i], s);
+ s += '}';
+ return s;
+}
+
+bool CMethodInfo::IsLzx() const
+{
+ if (AreGuidsEqual(Guid, kChmLzxGuid))
+ return true;
+ return AreGuidsEqual(Guid, kHelp2LzxGuid);
+}
+
+bool CMethodInfo::IsDes() const
+{
+ return AreGuidsEqual(Guid, kDesGuid);
+}
+
+UString CMethodInfo::GetName() const
+{
+ UString s;
+ if (IsLzx())
+ {
+ s = L"LZX:";
+ UInt32 numDictBits = LzxInfo.GetNumDictBits();
+ wchar_t temp[32];
+ ConvertUInt64ToString(numDictBits, temp);
+ s += temp;
+ }
+ else
+ {
+ AString s2;
+ if (IsDes())
+ s2 = "DES";
+ else
+ {
+ s2 = GetGuidString();
+ if (ControlData.GetCapacity() > 0)
+ {
+ s2 += ":";
+ for (size_t i = 0; i < ControlData.GetCapacity(); i++)
+ PrintByte(ControlData[i], s2);
+ }
+ }
+ ConvertUTF8ToUnicode(s2, s);
+ }
+ return s;
+}
+
+bool CSectionInfo::IsLzx() const
+{
+ if (Methods.Size() != 1)
+ return false;
+ return Methods[0].IsLzx();
+}
+
+UString CSectionInfo::GetMethodName() const
+{
+ UString s;
+ if (!IsLzx())
+ {
+ UString temp;
+ if (ConvertUTF8ToUnicode(Name, temp))
+ s += temp;
+ s += L": ";
+ }
+ for (int i = 0; i < Methods.Size(); i++)
+ {
+ if (i != 0)
+ s += L" ";
+ s += Methods[i].GetName();
+ }
+ return s;
+}
+
+Byte CInArchive::ReadByte()
+{
+ Byte b;
+ if (!_inBuffer.ReadByte(b))
+ throw 1;
+ return b;
+}
+
+void CInArchive::Skeep(size_t size)
+{
+ while (size-- != 0)
+ ReadByte();
+}
+
+void CInArchive::ReadBytes(Byte *data, UInt32 size)
+{
+ for (UInt32 i = 0; i < size; i++)
+ data[i] = ReadByte();
+}
+
+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;
+}
+
+UInt64 CInArchive::ReadEncInt()
+{
+ UInt64 val = 0;;
+ for (int i = 0; i < 10; i++)
+ {
+ Byte b = ReadByte();
+ val |= (b & 0x7F);
+ if (b < 0x80)
+ return val;
+ val <<= 7;
+ }
+ throw 1;
+}
+
+void CInArchive::ReadGUID(GUID &g)
+{
+ g.Data1 = ReadUInt32();
+ g.Data2 = ReadUInt16();
+ g.Data3 = ReadUInt16();
+ ReadBytes(g.Data4, 8);
+}
+
+void CInArchive::ReadString(int size, AString &s)
+{
+ s.Empty();
+ while(size-- != 0)
+ {
+ char c = (char)ReadByte();
+ if (c == 0)
+ {
+ Skeep(size);
+ return;
+ }
+ s += c;
+ }
+}
+
+void CInArchive::ReadUString(int size, UString &s)
+{
+ s.Empty();
+ while(size-- != 0)
+ {
+ wchar_t c = ReadUInt16();
+ if (c == 0)
+ {
+ Skeep(2 * size);
+ return;
+ }
+ s += c;
+ }
+}
+
+HRESULT CInArchive::ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size)
+{
+ RINOK(inStream->Seek(pos, STREAM_SEEK_SET, NULL));
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> limitedStream(streamSpec);
+ streamSpec->SetStream(inStream);
+ streamSpec->Init(size);
+ _inBuffer.SetStream(limitedStream);
+ _inBuffer.Init();
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadDirEntry(CDatabase &database)
+{
+ CItem item;
+ UInt64 nameLength = ReadEncInt();
+ if (nameLength == 0 || nameLength >= 0x10000000)
+ return S_FALSE;
+ ReadString((int)nameLength, item.Name);
+ item.Section = ReadEncInt();
+ item.Offset = ReadEncInt();
+ item.Size = ReadEncInt();
+ database.Items.Add(item);
+ return S_OK;
+}
+
+HRESULT CInArchive::OpenChm(IInStream *inStream, CDatabase &database)
+{
+ UInt32 headerSize = ReadUInt32();
+ if (headerSize != 0x60)
+ return S_FALSE;
+ UInt32 unknown1 = ReadUInt32();
+ if (unknown1 != 0 && unknown1 != 1) // it's 0 in one .sll file
+ return S_FALSE;
+ /* UInt32 timeStamp = */ ReadUInt32();
+ // Considered as a big-endian DWORD, it appears to contain seconds (MSB) and
+ // fractional seconds (second byte).
+ // The third and fourth bytes may contain even more fractional bits.
+ // The 4 least significant bits in the last byte are constant.
+ /* UInt32 lang = */ ReadUInt32();
+ GUID g;
+ ReadGUID(g); // {7C01FD10-7BAA-11D0-9E0C-00A0-C922-E6EC}
+ ReadGUID(g); // {7C01FD11-7BAA-11D0-9E0C-00A0-C922-E6EC}
+ const int kNumSections = 2;
+ UInt64 sectionOffsets[kNumSections];
+ UInt64 sectionSizes[kNumSections];
+ int i;
+ for (i = 0; i < kNumSections; i++)
+ {
+ sectionOffsets[i] = ReadUInt64();
+ sectionSizes[i] = ReadUInt64();
+ }
+ // if (chmVersion == 3)
+ database.ContentOffset = ReadUInt64();
+ /*
+ else
+ database.ContentOffset = _startPosition + 0x58
+ */
+
+ /*
+ // Section 0
+ ReadChunk(inStream, sectionOffsets[0], sectionSizes[0]);
+ if (sectionSizes[0] != 0x18)
+ return S_FALSE;
+ ReadUInt32(); // unknown: 01FE
+ ReadUInt32(); // unknown: 0
+ UInt64 fileSize = ReadUInt64();
+ ReadUInt32(); // unknown: 0
+ ReadUInt32(); // unknown: 0
+ */
+
+ // Section 1: The Directory Listing
+ ReadChunk(inStream, sectionOffsets[1], sectionSizes[1]);
+ if (ReadUInt32() != NHeader::kItspSignature)
+ return S_FALSE;
+ if (ReadUInt32() != 1) // version
+ return S_FALSE;
+ /* UInt32 dirHeaderSize = */ ReadUInt32();
+ ReadUInt32(); // 0x0A (unknown)
+ UInt32 dirChunkSize = ReadUInt32(); // $1000
+ if (dirChunkSize < 32)
+ return S_FALSE;
+ /* UInt32 density = */ ReadUInt32(); // "Density" of quickref section, usually 2.
+ /* UInt32 depth = */ ReadUInt32(); // Depth of the index tree: 1 there is no index,
+ // 2 if there is one level of PMGI chunks.
+
+ /* UInt32 chunkNumber = */ ReadUInt32(); // Chunk number of root index chunk, -1 if there is none
+ // (though at least one file has 0 despite there being no
+ // index chunk, probably a bug.)
+ /* UInt32 firstPmglChunkNumber = */ ReadUInt32(); // Chunk number of first PMGL (listing) chunk
+ /* UInt32 lastPmglChunkNumber = */ ReadUInt32(); // Chunk number of last PMGL (listing) chunk
+ ReadUInt32(); // -1 (unknown)
+ UInt32 numDirChunks = ReadUInt32(); // Number of directory chunks (total)
+ /* UInt32 windowsLangId = */ ReadUInt32();
+ ReadGUID(g); // {5D02926A-212E-11D0-9DF9-00A0C922E6EC}
+ ReadUInt32(); // 0x54 (This is the length again)
+ ReadUInt32(); // -1 (unknown)
+ ReadUInt32(); // -1 (unknown)
+ ReadUInt32(); // -1 (unknown)
+
+ for (UInt32 ci = 0; ci < numDirChunks; ci++)
+ {
+ UInt64 chunkPos = _inBuffer.GetProcessedSize();
+ if (ReadUInt32() == NHeader::kPmglSignature)
+ {
+ // The quickref area is written backwards from the end of the chunk.
+ // One quickref entry exists for every n entries in the file, where n
+ // is calculated as 1 + (1 << quickref density). So for density = 2, n = 5.
+
+ UInt32 quickrefLength = ReadUInt32(); // Length of free space and/or quickref area at end of directory chunk
+ if (quickrefLength > dirChunkSize || quickrefLength < 2)
+ return S_FALSE;
+ ReadUInt32(); // Always 0
+ ReadUInt32(); // Chunk number of previous listing chunk when reading
+ // directory in sequence (-1 if this is the first listing chunk)
+ ReadUInt32(); // Chunk number of next listing chunk when reading
+ // directory in sequence (-1 if this is the last listing chunk)
+ int numItems = 0;
+ for (;;)
+ {
+ UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
+ UInt32 offsetLimit = dirChunkSize - quickrefLength;
+ if (offset > offsetLimit)
+ return S_FALSE;
+ if (offset == offsetLimit)
+ break;
+ RINOK(ReadDirEntry(database));
+ numItems++;
+ }
+ Skeep(quickrefLength - 2);
+ if (ReadUInt16() != numItems)
+ return S_FALSE;
+ }
+ else
+ Skeep(dirChunkSize - 4);
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::OpenHelp2(IInStream *inStream, CDatabase &database)
+{
+ if (ReadUInt32() != 1) // version
+ return S_FALSE;
+ if (ReadUInt32() != 0x28) // Location of header section table
+ return S_FALSE;
+ UInt32 numHeaderSections = ReadUInt32();
+ const int kNumHeaderSectionsMax = 5;
+ if (numHeaderSections != kNumHeaderSectionsMax)
+ return S_FALSE;
+ ReadUInt32(); // Length of post-header table
+ GUID g;
+ ReadGUID(g); // {0A9007C1-4076-11D3-8789-0000F8105754}
+
+ // header section table
+ UInt64 sectionOffsets[kNumHeaderSectionsMax];
+ UInt64 sectionSizes[kNumHeaderSectionsMax];
+ UInt32 i;
+ for (i = 0; i < numHeaderSections; i++)
+ {
+ sectionOffsets[i] = ReadUInt64();
+ sectionSizes[i] = ReadUInt64();
+ }
+
+ // Post-Header
+ ReadUInt32(); // 2
+ ReadUInt32(); // 0x98: offset to CAOL from beginning of post-header)
+ // ----- Directory information
+ ReadUInt64(); // Chunk number of top-level AOLI chunk in directory, or -1
+ ReadUInt64(); // Chunk number of first AOLL chunk in directory
+ ReadUInt64(); // Chunk number of last AOLL chunk in directory
+ ReadUInt64(); // 0 (unknown)
+ ReadUInt32(); // $2000 (Directory chunk size of directory)
+ ReadUInt32(); // Quickref density for main directory, usually 2
+ ReadUInt32(); // 0 (unknown)
+ ReadUInt32(); // Depth of main directory index tree
+ // 1 there is no index, 2 if there is one level of AOLI chunks.
+ ReadUInt64(); // 0 (unknown)
+ UInt64 numDirEntries = ReadUInt64(); // Number of directory entries
+ // ----- Directory Index Information
+ ReadUInt64(); // -1 (unknown, probably chunk number of top-level AOLI in directory index)
+ ReadUInt64(); // Chunk number of first AOLL chunk in directory index
+ ReadUInt64(); // Chunk number of last AOLL chunk in directory index
+ ReadUInt64(); // 0 (unknown)
+ ReadUInt32(); // $200 (Directory chunk size of directory index)
+ ReadUInt32(); // Quickref density for directory index, usually 2
+ ReadUInt32(); // 0 (unknown)
+ ReadUInt32(); // Depth of directory index index tree.
+ ReadUInt64(); // Possibly flags -- sometimes 1, sometimes 0.
+ ReadUInt64(); // Number of directory index entries (same as number of AOLL
+ // chunks in main directory)
+
+ // (The obvious guess for the following two fields, which recur in a number
+ // of places, is they are maximum sizes for the directory and directory index.
+ // However, I have seen no direct evidence that this is the case.)
+
+ ReadUInt32(); // $100000 (Same as field following chunk size in directory)
+ ReadUInt32(); // $20000 (Same as field following chunk size in directory index)
+
+ ReadUInt64(); // 0 (unknown)
+ if (ReadUInt32() != NHeader::kCaolSignature)
+ return S_FALSE;
+ if (ReadUInt32() != 2) // (Most likely a version number)
+ return S_FALSE;
+ UInt32 caolLength = ReadUInt32(); // $50 (Length of the CAOL section, which includes the ITSF section)
+ if (caolLength >= 0x2C)
+ {
+ /* UInt32 c7 = */ ReadUInt16(); // Unknown. Remains the same when identical files are built.
+ // Does not appear to be a checksum. Many files have
+ // 'HH' (HTML Help?) here, indicating this may be a compiler ID
+ // field. But at least one ITOL/ITLS compiler does not set this
+ // field to a constant value.
+ ReadUInt16(); // 0 (Unknown. Possibly part of 00A4 field)
+ ReadUInt32(); // Unknown. Two values have been seen -- $43ED, and 0.
+ ReadUInt32(); // $2000 (Directory chunk size of directory)
+ ReadUInt32(); // $200 (Directory chunk size of directory index)
+ ReadUInt32(); // $100000 (Same as field following chunk size in directory)
+ ReadUInt32(); // $20000 (Same as field following chunk size in directory index)
+ ReadUInt32(); // 0 (unknown)
+ ReadUInt32(); // 0 (Unknown)
+ if (caolLength == 0x2C)
+ {
+ database.ContentOffset = 0;
+ database.NewFormat = true;
+ }
+ else if (caolLength == 0x50)
+ {
+ ReadUInt32(); // 0 (Unknown)
+ if (ReadUInt32() != NHeader::kItsfSignature)
+ return S_FALSE;
+ if (ReadUInt32() != 4) // $4 (Version number -- CHM uses 3)
+ return S_FALSE;
+ if (ReadUInt32() != 0x20) // $20 (length of ITSF)
+ return S_FALSE;
+ UInt32 unknown = ReadUInt32();
+ if (unknown != 0 && unknown != 1) // = 0 for some HxW files, 1 in other cases;
+ return S_FALSE;
+ database.ContentOffset = _startPosition + ReadUInt64();
+ /* UInt32 timeStamp = */ ReadUInt32();
+ // A timestamp of some sort.
+ // Considered as a big-endian DWORD, it appears to contain
+ // seconds (MSB) and fractional seconds (second byte).
+ // The third and fourth bytes may contain even more fractional
+ // bits. The 4 least significant bits in the last byte are constant.
+ /* UInt32 lang = */ ReadUInt32(); // BE?
+ }
+ else
+ return S_FALSE;
+ }
+
+ /*
+ // Section 0
+ ReadChunk(inStream, _startPosition + sectionOffsets[0], sectionSizes[0]);
+ if (sectionSizes[0] != 0x18)
+ return S_FALSE;
+ ReadUInt32(); // unknown: 01FE
+ ReadUInt32(); // unknown: 0
+ UInt64 fileSize = ReadUInt64();
+ ReadUInt32(); // unknown: 0
+ ReadUInt32(); // unknown: 0
+ */
+
+ // Section 1: The Directory Listing
+ ReadChunk(inStream, _startPosition + sectionOffsets[1], sectionSizes[1]);
+ if (ReadUInt32() != NHeader::kIfcmSignature)
+ return S_FALSE;
+ if (ReadUInt32() != 1) // (probably a version number)
+ return S_FALSE;
+ UInt32 dirChunkSize = ReadUInt32(); // $2000
+ if (dirChunkSize < 64)
+ return S_FALSE;
+ ReadUInt32(); // $100000 (unknown)
+ ReadUInt32(); // -1 (unknown)
+ ReadUInt32(); // -1 (unknown)
+ UInt32 numDirChunks = ReadUInt32();
+ ReadUInt32(); // 0 (unknown, probably high word of above)
+
+ for (UInt32 ci = 0; ci < numDirChunks; ci++)
+ {
+ UInt64 chunkPos = _inBuffer.GetProcessedSize();
+ if (ReadUInt32() == NHeader::kAollSignature)
+ {
+ UInt32 quickrefLength = ReadUInt32(); // Length of quickref area at end of directory chunk
+ if (quickrefLength > dirChunkSize || quickrefLength < 2)
+ return S_FALSE;
+ ReadUInt64(); // Directory chunk number
+ // This must match physical position in file, that is
+ // the chunk size times the chunk number must be the
+ // offset from the end of the directory header.
+ ReadUInt64(); // Chunk number of previous listing chunk when reading
+ // directory in sequence (-1 if first listing chunk)
+ ReadUInt64(); // Chunk number of next listing chunk when reading
+ // directory in sequence (-1 if last listing chunk)
+ ReadUInt64(); // Number of first listing entry in this chunk
+ ReadUInt32(); // 1 (unknown -- other values have also been seen here)
+ ReadUInt32(); // 0 (unknown)
+
+ int numItems = 0;
+ for (;;)
+ {
+ UInt64 offset = _inBuffer.GetProcessedSize() - chunkPos;
+ UInt32 offsetLimit = dirChunkSize - quickrefLength;
+ if (offset > offsetLimit)
+ return S_FALSE;
+ if (offset == offsetLimit)
+ break;
+ if (database.NewFormat)
+ {
+ UInt16 nameLength = ReadUInt16();
+ if (nameLength == 0)
+ return S_FALSE;
+ UString name;
+ ReadUString((int)nameLength, name);
+ AString s;
+ ConvertUnicodeToUTF8(name, s);
+ Byte b = ReadByte();
+ s += ' ';
+ PrintByte(b, s);
+ s += ' ';
+ UInt64 len = ReadEncInt();
+ // then number of items ?
+ // then length ?
+ // then some data (binary encoding?)
+ while (len-- != 0)
+ {
+ b = ReadByte();
+ PrintByte(b, s);
+ }
+ database.NewFormatString += s;
+ database.NewFormatString += "\r\n";
+ }
+ else
+ {
+ RINOK(ReadDirEntry(database));
+ }
+ numItems++;
+ }
+ Skeep(quickrefLength - 2);
+ if (ReadUInt16() != numItems)
+ return S_FALSE;
+ if (numItems > numDirEntries)
+ return S_FALSE;
+ numDirEntries -= numItems;
+ }
+ else
+ Skeep(dirChunkSize - 4);
+ }
+ return numDirEntries == 0 ? S_OK : S_FALSE;
+}
+
+HRESULT CInArchive::DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name)
+{
+ int index = database.FindItem(name);
+ if (index < 0)
+ return S_FALSE;
+ const CItem &item = database.Items[index];
+ _chunkSize = item.Size;
+ return ReadChunk(inStream, database.ContentOffset + item.Offset, item.Size);
+}
+
+
+#define DATA_SPACE "::DataSpace/"
+static const char *kNameList = DATA_SPACE "NameList";
+static const char *kStorage = DATA_SPACE "Storage/";
+static const char *kContent = "Content";
+static const char *kControlData = "ControlData";
+static const char *kSpanInfo = "SpanInfo";
+static const char *kTransform = "Transform/";
+static const char *kResetTable = "/InstanceData/ResetTable";
+static const char *kTransformList = "List";
+
+static AString GetSectionPrefix(const AString &name)
+{
+ return AString(kStorage) + name + AString("/");
+}
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareFiles(const int *p1, const int *p2, void *param)
+{
+ const CObjectVector<CItem> &items = *(const CObjectVector<CItem> *)param;
+ const CItem &item1 = items[*p1];
+ const CItem &item2 = items[*p2];
+ bool isDir1 = item1.IsDirectory();
+ bool isDir2 = item2.IsDirectory();
+ if (isDir1 && !isDir2)
+ return -1;
+ if (isDir2)
+ {
+ if (isDir1)
+ return MyCompare(*p1, *p2);
+ return 1;
+ }
+ RINOZ(MyCompare(item1.Section, item2.Section));
+ RINOZ(MyCompare(item1.Offset, item2.Offset));
+ RINOZ(MyCompare(item1.Size, item2.Size));
+ return MyCompare(*p1, *p2);
+}
+
+void CFilesDatabase::SetIndices()
+{
+ for (int i = 0; i < Items.Size(); i++)
+ {
+ const CItem &item = Items[i];
+ if (item.IsUserItem() && item.Name.Length() != 1)
+ Indices.Add(i);
+ }
+}
+
+void CFilesDatabase::Sort()
+{
+ Indices.Sort(CompareFiles, (void *)&Items);
+}
+
+bool CFilesDatabase::Check()
+{
+ UInt64 maxPos = 0;
+ UInt64 prevSection = 0;
+ for(int i = 0; i < Indices.Size(); i++)
+ {
+ const CItem &item = Items[Indices[i]];
+ if (item.Section == 0 || item.IsDirectory())
+ continue;
+ if (item.Section != prevSection)
+ {
+ prevSection = item.Section;
+ maxPos = 0;
+ continue;
+ }
+ if (item.Offset < maxPos)
+ return false;
+ maxPos = item.Offset + item.Size;
+ if (maxPos < item.Offset)
+ return false;
+ }
+ return true;
+}
+
+HRESULT CInArchive::OpenHighLevel(IInStream *inStream, CFilesDatabase &database)
+{
+ {
+ // The NameList file
+ RINOK(DecompressStream(inStream, database, kNameList));
+ /* UInt16 length = */ ReadUInt16();
+ UInt16 numSections = ReadUInt16();
+ for (int i = 0; i < numSections; i++)
+ {
+ CSectionInfo section;
+ UInt16 nameLength = ReadUInt16();
+ UString name;
+ ReadUString(nameLength, name);
+ if (ReadUInt16() != 0)
+ return S_FALSE;
+ if (!ConvertUnicodeToUTF8(name, section.Name))
+ return S_FALSE;
+ database.Sections.Add(section);
+ }
+ }
+
+ int i;
+ for (i = 1; i < database.Sections.Size(); i++)
+ {
+ CSectionInfo &section = database.Sections[i];
+ AString sectionPrefix = GetSectionPrefix(section.Name);
+ {
+ // Content
+ int index = database.FindItem(sectionPrefix + kContent);
+ if (index < 0)
+ return S_FALSE;
+ const CItem &item = database.Items[index];
+ section.Offset = item.Offset;
+ section.CompressedSize = item.Size;
+ }
+ AString transformPrefix = sectionPrefix + kTransform;
+ if (database.Help2Format)
+ {
+ // Transform List
+ RINOK(DecompressStream(inStream, database, transformPrefix + kTransformList));
+ if ((_chunkSize & 0xF) != 0)
+ return S_FALSE;
+ int numGuids = (int)(_chunkSize / 0x10);
+ if (numGuids < 1)
+ return S_FALSE;
+ for (int i = 0; i < numGuids; i++)
+ {
+ CMethodInfo method;
+ ReadGUID(method.Guid);
+ section.Methods.Add(method);
+ }
+ }
+ else
+ {
+ CMethodInfo method;
+ method.Guid = kChmLzxGuid;
+ section.Methods.Add(method);
+ }
+
+ {
+ // Control Data
+ RINOK(DecompressStream(inStream, database, sectionPrefix + kControlData));
+ for (int mi = 0; mi < section.Methods.Size(); mi++)
+ {
+ CMethodInfo &method = section.Methods[mi];
+ UInt32 numDWORDS = ReadUInt32();
+ if (method.IsLzx())
+ {
+ if (numDWORDS < 5)
+ return S_FALSE;
+ if (ReadUInt32() != NHeader::kLzxcSignature)
+ return S_FALSE;
+ CLzxInfo &li = method.LzxInfo;
+ li.Version = ReadUInt32();
+ if (li.Version != 2 && li.Version != 3)
+ return S_FALSE;
+ li.ResetInterval = ReadUInt32();
+ li.WindowSize = ReadUInt32();
+ li.CacheSize = ReadUInt32();
+ if (li.ResetInterval != 2 && li.ResetInterval != 4)
+ return S_FALSE;
+ if (li.WindowSize != 2 && li.WindowSize != 4)
+ return S_FALSE;
+ numDWORDS -= 5;
+ while (numDWORDS-- != 0)
+ ReadUInt32();
+ }
+ else
+ {
+ UInt32 numBytes = numDWORDS * 4;
+ method.ControlData.SetCapacity(numBytes);
+ ReadBytes(method.ControlData, numBytes);
+ }
+ }
+ }
+
+ {
+ // SpanInfo
+ RINOK(DecompressStream(inStream, database, sectionPrefix + kSpanInfo));
+ section.UncompressedSize = ReadUInt64();
+ }
+
+ // read ResetTable for LZX
+ for (int mi = 0; mi < section.Methods.Size(); mi++)
+ {
+ CMethodInfo &method = section.Methods[mi];
+ if (method.IsLzx())
+ {
+ // ResetTable;
+ RINOK(DecompressStream(inStream, database, transformPrefix +
+ method.GetGuidString() + kResetTable));
+ CResetTable &rt = method.LzxInfo.ResetTable;
+ if (_chunkSize < 4)
+ {
+ if (_chunkSize != 0)
+ return S_FALSE;
+ // ResetTable is empty in .chw files
+ if (section.UncompressedSize != 0)
+ return S_FALSE;
+ rt.UncompressedSize = 0;
+ rt.CompressedSize = 0;
+ rt.BlockSize = 0;
+ }
+ else
+ {
+ UInt32 ver = ReadUInt32(); // 2 unknown (possibly a version number)
+ if (ver != 2 && ver != 3)
+ return S_FALSE;
+ UInt32 numEntries = ReadUInt32();
+ if (ReadUInt32() != 8) // Size of table entry (bytes)
+ return S_FALSE;
+ if (ReadUInt32() != 0x28) // Length of table header
+ return S_FALSE;
+ rt.UncompressedSize = ReadUInt64();
+ rt.CompressedSize = ReadUInt64();
+ rt.BlockSize = ReadUInt64(); // 0x8000 block size for locations below
+ if (rt.BlockSize != 0x8000)
+ return S_FALSE;
+ rt.ResetOffsets.Reserve(numEntries);
+ for (UInt32 i = 0; i < numEntries; i++)
+ rt.ResetOffsets.Add(ReadUInt64());
+ }
+ }
+ }
+ }
+
+ database.SetIndices();
+ database.Sort();
+ return database.Check() ? S_OK : S_FALSE;
+}
+
+HRESULT CInArchive::Open2(IInStream *inStream,
+ const UInt64 *searchHeaderSizeLimit,
+ CFilesDatabase &database)
+{
+ database.Clear();
+
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &_startPosition));
+
+ database.Help2Format = false;
+ const UInt32 chmVersion = 3;
+ {
+ if (!_inBuffer.Create(1 << 14))
+ return E_OUTOFMEMORY;
+ _inBuffer.SetStream(inStream);
+ _inBuffer.Init();
+ UInt64 value = 0;
+ const int kSignatureSize = 8;
+ UInt64 hxsSignature = NHeader::GetHxsSignature();
+ UInt64 chmSignature = ((UInt64)chmVersion << 32)| NHeader::kItsfSignature;
+ for (;;)
+ {
+ Byte b;
+ if (!_inBuffer.ReadByte(b))
+ return S_FALSE;
+ value >>= 8;
+ value |= ((UInt64)b) << ((kSignatureSize - 1) * 8);
+ if (_inBuffer.GetProcessedSize() >= kSignatureSize)
+ {
+ if (value == chmSignature)
+ break;
+ if (value == hxsSignature)
+ {
+ database.Help2Format = true;
+ break;
+ }
+ if (searchHeaderSizeLimit != NULL)
+ if (_inBuffer.GetProcessedSize() > (*searchHeaderSizeLimit))
+ return S_FALSE;
+ }
+ }
+ _startPosition += _inBuffer.GetProcessedSize() - kSignatureSize;
+ }
+
+ if (database.Help2Format)
+ {
+ RINOK(OpenHelp2(inStream, database));
+ if (database.NewFormat)
+ return S_OK;
+ }
+ else
+ {
+ RINOK(OpenChm(inStream, database));
+ }
+
+ #ifndef CHM_LOW
+ try
+ {
+ HRESULT res = OpenHighLevel(inStream, database);
+ if (res == S_FALSE)
+ {
+ database.HighLevelClear();
+ return S_OK;
+ }
+ RINOK(res);
+ database.LowLevel = false;
+ }
+ catch(...)
+ {
+ return S_OK;
+ }
+ #endif
+ return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream,
+ const UInt64 *searchHeaderSizeLimit,
+ CFilesDatabase &database)
+{
+ try
+ {
+ HRESULT res = Open2(inStream, searchHeaderSizeLimit, database);
+ _inBuffer.ReleaseStream();
+ return res;
+ }
+ catch(...)
+ {
+ _inBuffer.ReleaseStream();
+ throw;
+ }
+}
+
+}}
diff --git a/CPP/7zip/Archive/Chm/ChmIn.h b/CPP/7zip/Archive/Chm/ChmIn.h
new file mode 100755
index 00000000..ebf3c4be
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/ChmIn.h
@@ -0,0 +1,242 @@
+// Archive/ChmIn.h
+
+#ifndef __ARCHIVE_CHM_IN_H
+#define __ARCHIVE_CHM_IN_H
+
+#include "Common/String.h"
+#include "Common/Buffer.h"
+#include "../../IStream.h"
+#include "../../Common/InBuffer.h"
+#include "ChmHeader.h"
+
+namespace NArchive {
+namespace NChm {
+
+struct CItem
+{
+ UInt64 Section;
+ UInt64 Offset;
+ UInt64 Size;
+ AString Name;
+
+ bool IsFormatRelatedItem() const
+ {
+ if (Name.Length() < 2)
+ return false;
+ return Name[0] == ':' && Name[1] == ':';
+ }
+
+ bool IsUserItem() const
+ {
+ if (Name.Length() < 2)
+ return false;
+ return Name[0] == '/';
+ }
+
+ bool IsDirectory() const
+ {
+ if (Name.Length() == 0)
+ return false;
+ return (Name[Name.Length() - 1] == '/');
+ }
+};
+
+struct CDatabase
+{
+ UInt64 ContentOffset;
+ CObjectVector<CItem> Items;
+ AString NewFormatString;
+ bool Help2Format;
+ bool NewFormat;
+
+ int FindItem(const AString &name) const
+ {
+ for (int i = 0; i < Items.Size(); i++)
+ if (Items[i].Name == name)
+ return i;
+ return -1;
+ }
+
+ void Clear()
+ {
+ NewFormat = false;
+ NewFormatString.Empty();
+ Help2Format = false;
+ Items.Clear();
+ }
+};
+
+struct CResetTable
+{
+ UInt64 UncompressedSize;
+ UInt64 CompressedSize;
+ UInt64 BlockSize;
+ CRecordVector<UInt64> ResetOffsets;
+ bool GetCompressedSizeOfBlocks(UInt64 blockIndex, UInt32 numBlocks, UInt64 &size) const
+ {
+ if (blockIndex >= ResetOffsets.Size())
+ return false;
+ UInt64 startPos = ResetOffsets[(int)blockIndex];
+ if (blockIndex + numBlocks >= ResetOffsets.Size())
+ size = CompressedSize - startPos;
+ else
+ size = ResetOffsets[(int)(blockIndex + numBlocks)] - startPos;
+ return true;
+ }
+ bool GetCompressedSizeOfBlock(UInt64 blockIndex, UInt64 &size) const
+ {
+ return GetCompressedSizeOfBlocks(blockIndex, 1, size);
+ }
+ UInt64 GetNumBlocks(UInt64 size) const
+ {
+ return (size + BlockSize - 1) / BlockSize;
+ }
+};
+
+struct CLzxInfo
+{
+ UInt32 Version;
+ UInt32 ResetInterval;
+ UInt32 WindowSize;
+ UInt32 CacheSize;
+ CResetTable ResetTable;
+
+ UInt32 GetNumDictBits() const
+ {
+ if (Version == 2 || Version == 3)
+ {
+ for (int i = 0; i <= 31; i++)
+ if (((UInt32)1 << i) >= WindowSize)
+ return 15 + i;
+ }
+ return 0;
+ }
+
+ UInt64 GetFolderSize() const { return ResetTable.BlockSize * ResetInterval; };
+ UInt64 GetFolder(UInt64 offset) const { return offset / GetFolderSize(); };
+ UInt64 GetFolderPos(UInt64 folderIndex) const { return folderIndex * GetFolderSize(); };
+ UInt64 GetBlockIndexFromFolderIndex(UInt64 folderIndex) const { return folderIndex * ResetInterval; };
+ bool GetOffsetOfFolder(UInt64 folderIndex, UInt64 &offset) const
+ {
+ UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
+ if (blockIndex >= ResetTable.ResetOffsets.Size())
+ return false;
+ offset = ResetTable.ResetOffsets[(int)blockIndex];
+ return true;
+ }
+ bool GetCompressedSizeOfFolder(UInt64 folderIndex, UInt64 &size) const
+ {
+ UInt64 blockIndex = GetBlockIndexFromFolderIndex(folderIndex);
+ return ResetTable.GetCompressedSizeOfBlocks(blockIndex, ResetInterval, size);
+ }
+};
+
+struct CMethodInfo
+{
+ GUID Guid;
+ CByteBuffer ControlData;
+ CLzxInfo LzxInfo;
+ bool IsLzx() const;
+ bool IsDes() const;
+ AString GetGuidString() const;
+ UString GetName() const;
+};
+
+struct CSectionInfo
+{
+ UInt64 Offset;
+ UInt64 CompressedSize;
+ UInt64 UncompressedSize;
+
+ AString Name;
+ CObjectVector<CMethodInfo> Methods;
+
+ bool IsLzx() const;
+ UString GetMethodName() const;
+};
+
+class CFilesDatabase: public CDatabase
+{
+public:
+ bool LowLevel;
+ CRecordVector<int> Indices;
+ CObjectVector<CSectionInfo> Sections;
+
+ UInt64 GetFileSize(int fileIndex) const { return Items[Indices[fileIndex]].Size; }
+ UInt64 GetFileOffset(int fileIndex) const { return Items[Indices[fileIndex]].Offset; }
+
+ UInt64 GetFolder(int fileIndex) const
+ {
+ const CItem &item = Items[Indices[fileIndex]];
+ const CSectionInfo &section = Sections[(int)item.Section];
+ if (section.IsLzx())
+ return section.Methods[0].LzxInfo.GetFolder(item.Offset);
+ return 0;
+ }
+
+ UInt64 GetLastFolder(int fileIndex) const
+ {
+ const CItem &item = Items[Indices[fileIndex]];
+ const CSectionInfo &section = Sections[(int)item.Section];
+ if (section.IsLzx())
+ return section.Methods[0].LzxInfo.GetFolder(item.Offset + item.Size - 1);
+ return 0;
+ }
+
+ void HighLevelClear()
+ {
+ LowLevel = true;
+ Indices.Clear();
+ Sections.Clear();
+ }
+
+ void Clear()
+ {
+ CDatabase::Clear();
+ HighLevelClear();
+ }
+ void SetIndices();
+ void Sort();
+ bool Check();
+};
+
+class CProgressVirt
+{
+public:
+ STDMETHOD(SetTotal)(const UInt64 *numFiles) PURE;
+ STDMETHOD(SetCompleted)(const UInt64 *numFiles) PURE;
+};
+
+class CInArchive
+{
+ UInt64 _startPosition;
+ ::CInBuffer _inBuffer;
+ UInt64 _chunkSize;
+
+ Byte ReadByte();
+ void ReadBytes(Byte *data, UInt32 size);
+ void Skeep(size_t size);
+ UInt16 ReadUInt16();
+ UInt32 ReadUInt32();
+ UInt64 ReadUInt64();
+ UInt64 ReadEncInt();
+ void ReadString(int size, AString &s);
+ void ReadUString(int size, UString &s);
+ void ReadGUID(GUID &g);
+
+ HRESULT ReadChunk(IInStream *inStream, UInt64 pos, UInt64 size);
+
+ HRESULT ReadDirEntry(CDatabase &database);
+ HRESULT DecompressStream(IInStream *inStream, const CDatabase &database, const AString &name);
+
+public:
+ HRESULT OpenChm(IInStream *inStream, CDatabase &database);
+ HRESULT OpenHelp2(IInStream *inStream, CDatabase &database);
+ HRESULT OpenHighLevel(IInStream *inStream, CFilesDatabase &database);
+ HRESULT Open2(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
+ HRESULT Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit, CFilesDatabase &database);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Chm/DllExports.cpp b/CPP/7zip/Archive/Chm/DllExports.cpp
new file mode 100755
index 00000000..ad822094
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/DllExports.cpp
@@ -0,0 +1,77 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "ChmHandler.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278A-1000-000110E90000}
+DEFINE_GUID(CLSID_CChmHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE9, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CChmHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NChm::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Chm";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CChmHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"chm chi chq chw hxs hxi hxr hxq hxw lit";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const char sig[] = { 'I', 'T', 'S', 'F' };
+ if ((value->bstrVal = ::SysAllocStringByteLen(sig, 4)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kAssociate:
+ {
+ propVariant = false;
+ break;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Chm/StdAfx.cpp b/CPP/7zip/Archive/Chm/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Chm/StdAfx.h b/CPP/7zip/Archive/Chm/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/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/Chm/makefile b/CPP/7zip/Archive/Chm/makefile
new file mode 100755
index 00000000..4adce2f5
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/makefile
@@ -0,0 +1,68 @@
+PROG = chm.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+CHM_OBJS = \
+ $O\DllExports.obj \
+ $O\ChmHandler.obj \
+ $O\ChmHeader.obj \
+ $O\ChmIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\UTFConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\InBuffer.obj \
+ $O\LimitedStreams.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+COMPRESS_LZX_OBJS = \
+ $O\LzxDecoder.obj \
+ $O\Lzx86Converter.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(CHM_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_LZX_OBJS) \
+ $O\LZOutWindow.obj \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(CHM_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)
+$(COMPRESS_LZX_OBJS): ../../Compress/Lzx/$(*B).cpp
+ $(COMPL_O2)
+$O\LZOutWindow.obj: ../../Compress/LZ/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
+
diff --git a/CPP/7zip/Archive/Chm/resource.rc b/CPP/7zip/Archive/Chm/resource.rc
new file mode 100755
index 00000000..fc93ae4f
--- /dev/null
+++ b/CPP/7zip/Archive/Chm/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Chm Plugin", "chm")
diff --git a/CPP/7zip/Archive/Common/CodecsPath.cpp b/CPP/7zip/Archive/Common/CodecsPath.cpp
new file mode 100755
index 00000000..7ee89875
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CodecsPath.cpp
@@ -0,0 +1,34 @@
+// CodecsPath.cpp
+
+#include "StdAfx.h"
+#include "../../../Common/String.h"
+
+extern HINSTANCE g_hInstance;
+
+static CSysString GetLibraryPath()
+{
+ TCHAR fullPath[MAX_PATH + 1];
+ ::GetModuleFileName(g_hInstance, fullPath, MAX_PATH);
+ return fullPath;
+}
+
+static CSysString GetLibraryFolderPrefix()
+{
+ CSysString path = GetLibraryPath();
+ int pos = path.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+ return path.Left(pos + 1);
+}
+
+CSysString GetBaseFolderPrefix()
+{
+ CSysString libPrefix = GetLibraryFolderPrefix();
+ CSysString temp = libPrefix;
+ temp.Delete(temp.Length() - 1);
+ int pos = temp.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
+ return temp.Left(pos + 1);
+}
+
+CSysString GetCodecsFolderPrefix()
+{
+ return GetBaseFolderPrefix() + (CSysString)(TEXT("Codecs")) + (CSysString)(TEXT(STRING_PATH_SEPARATOR));
+}
diff --git a/CPP/7zip/Archive/Common/CodecsPath.h b/CPP/7zip/Archive/Common/CodecsPath.h
new file mode 100755
index 00000000..11145a03
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CodecsPath.h
@@ -0,0 +1,12 @@
+// CodecsPath.h
+
+#ifndef __CODECSPATH_H
+#define __CODECSPATH_H
+
+#include "../../../Common/String.h"
+
+CSysString GetBaseFolderPrefix();
+CSysString GetCodecsFolderPrefix();
+
+#endif
+
diff --git a/CPP/7zip/Archive/Common/CoderLoader.cpp b/CPP/7zip/Archive/Common/CoderLoader.cpp
new file mode 100755
index 00000000..bf54f6e0
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderLoader.cpp
@@ -0,0 +1,31 @@
+// CoderLoader.cpp
+
+#include "StdAfx.h"
+
+#include "CoderLoader.h"
+#include "FilterCoder.h"
+
+HRESULT CCoderLibrary::CreateCoderSpec(REFGUID clsID, ICompressCoder **coder)
+{
+ HRESULT result = CreateObject(clsID, IID_ICompressCoder, (void **)coder);
+ if (result == S_OK || result != E_NOINTERFACE)
+ return result;
+ CMyComPtr<ICompressFilter> filter;
+ RINOK(CreateObject(clsID, IID_ICompressFilter, (void **)&filter));
+ CFilterCoder *filterCoderSpec = new CFilterCoder;
+ CMyComPtr<ICompressCoder> filterCoder = filterCoderSpec;
+ filterCoderSpec->Filter = filter;
+ *coder = filterCoder.Detach();
+ return S_OK;
+}
+
+
+HRESULT CCoderLibrary::LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
+{
+ CCoderLibrary libTemp;
+ if (!libTemp.Load(filePath))
+ return GetLastError();
+ RINOK(libTemp.CreateCoderSpec(clsID, coder));
+ Attach(libTemp.Detach());
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Common/CoderLoader.h b/CPP/7zip/Archive/Common/CoderLoader.h
new file mode 100755
index 00000000..02322d8c
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderLoader.h
@@ -0,0 +1,147 @@
+// CoderLoader.h
+
+#ifndef __CODERLOADER_H
+#define __CODERLOADER_H
+
+#include "../../../Common/String.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Windows/DLL.h"
+#include "../../ICoder.h"
+
+typedef UInt32 (WINAPI * CreateObjectPointer)(
+ const GUID *clsID,
+ const GUID *interfaceID,
+ void **outObject);
+
+class CCoderLibrary: public NWindows::NDLL::CLibrary
+{
+public:
+ HRESULT CreateObject(REFGUID clsID, REFGUID iid, void **obj)
+ {
+ CreateObjectPointer createObject = (CreateObjectPointer)
+ GetProcAddress("CreateObject");
+ if (createObject == NULL)
+ return GetLastError();
+ return createObject(&clsID, &iid, obj);
+ }
+
+ HRESULT CreateFilter(REFGUID clsID, ICompressFilter **filter)
+ {
+ return CreateObject(clsID, IID_ICompressFilter, (void **)filter);
+ }
+
+ HRESULT CreateCoder(REFGUID clsID, ICompressCoder **coder)
+ {
+ return CreateObject(clsID, IID_ICompressCoder, (void **)coder);
+ }
+
+ HRESULT CreateCoderSpec(REFGUID clsID, ICompressCoder **coder);
+
+ HRESULT LoadAndCreateFilter(LPCTSTR filePath, REFGUID clsID, ICompressFilter **filter)
+ {
+ CCoderLibrary libTemp;
+ if (!libTemp.Load(filePath))
+ return GetLastError();
+ RINOK(libTemp.CreateFilter(clsID, filter));
+ Attach(libTemp.Detach());
+ return S_OK;
+ }
+
+
+ HRESULT LoadAndCreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
+ {
+ CCoderLibrary libTemp;
+ if (!libTemp.Load(filePath))
+ return GetLastError();
+ RINOK(libTemp.CreateCoder(clsID, coder));
+ Attach(libTemp.Detach());
+ return S_OK;
+ }
+
+ HRESULT LoadAndCreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder);
+ HRESULT CreateCoder2(REFGUID clsID, ICompressCoder2 **coder)
+ {
+ CreateObjectPointer createObject = (CreateObjectPointer)
+ GetProcAddress("CreateObject");
+ if (createObject == NULL)
+ return GetLastError();
+ return createObject(&clsID, &IID_ICompressCoder2, (void **)coder);
+ }
+ HRESULT LoadAndCreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder)
+ {
+ CCoderLibrary libTemp;
+ if (!libTemp.Load(filePath))
+ return GetLastError();
+ RINOK(libTemp.CreateCoder2(clsID, coder));
+ Attach(libTemp.Detach());
+ return S_OK;
+ }
+};
+
+
+class CCoderLibraries
+{
+ struct CPathToLibraryPair
+ {
+ CSysString Path;
+ CCoderLibrary Libary;
+ };
+ CObjectVector<CPathToLibraryPair> Pairs;
+public:
+ int FindPath(LPCTSTR filePath)
+ {
+ for (int i = 0; i < Pairs.Size(); i++)
+ if (Pairs[i].Path.CompareNoCase(filePath) == 0)
+ return i;
+ return -1;
+ }
+
+ HRESULT CreateCoder(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
+ {
+ int index = FindPath(filePath);
+ if (index < 0)
+ {
+ CPathToLibraryPair pair;
+ RINOK(pair.Libary.LoadAndCreateCoder(filePath, clsID, coder));
+ pair.Path = filePath;
+ Pairs.Add(pair);
+ pair.Libary.Detach();
+ return S_OK;
+ }
+ return Pairs[index].Libary.CreateCoder(clsID, coder);
+ }
+
+ HRESULT CreateCoderSpec(LPCTSTR filePath, REFGUID clsID, ICompressCoder **coder)
+ {
+ int index = FindPath(filePath);
+ if (index < 0)
+ {
+ CPathToLibraryPair pair;
+ RINOK(pair.Libary.LoadAndCreateCoderSpec(filePath, clsID, coder));
+ pair.Path = filePath;
+ Pairs.Add(pair);
+ pair.Libary.Detach();
+ return S_OK;
+ }
+ return Pairs[index].Libary.CreateCoderSpec(clsID, coder);
+ }
+
+ HRESULT CreateCoder2(LPCTSTR filePath, REFGUID clsID, ICompressCoder2 **coder)
+ {
+ int index = FindPath(filePath);
+ if (index < 0)
+ {
+ CPathToLibraryPair pair;
+ RINOK(pair.Libary.LoadAndCreateCoder2(filePath, clsID, coder));
+ pair.Path = filePath;
+ Pairs.Add(pair);
+ pair.Libary.Detach();
+ return S_OK;
+ }
+ return Pairs[index].Libary.CreateCoder2(clsID, coder);
+ }
+};
+
+
+#endif
+
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp
new file mode 100755
index 00000000..8f46e985
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp
@@ -0,0 +1,121 @@
+// CoderMixer2.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2.h"
+
+namespace NCoderMixer2 {
+
+CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo):
+ _srcBindInfo(srcBindInfo)
+{
+ srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams);
+
+ UInt32 j;
+ for (j = 0; j < NumSrcInStreams; j++)
+ {
+ _srcInToDestOutMap.Add(0);
+ DestOutToSrcInMap.Add(0);
+ }
+ for (j = 0; j < _numSrcOutStreams; j++)
+ {
+ _srcOutToDestInMap.Add(0);
+ _destInToSrcOutMap.Add(0);
+ }
+
+ UInt32 destInOffset = 0;
+ UInt32 destOutOffset = 0;
+ UInt32 srcInOffset = NumSrcInStreams;
+ UInt32 srcOutOffset = _numSrcOutStreams;
+
+ for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--)
+ {
+ const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i];
+
+ srcInOffset -= srcCoderInfo.NumInStreams;
+ srcOutOffset -= srcCoderInfo.NumOutStreams;
+
+ UInt32 j;
+ for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++)
+ {
+ UInt32 index = srcInOffset + j;
+ _srcInToDestOutMap[index] = destOutOffset;
+ DestOutToSrcInMap[destOutOffset] = index;
+ }
+ for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++)
+ {
+ UInt32 index = srcOutOffset + j;
+ _srcOutToDestInMap[index] = destInOffset;
+ _destInToSrcOutMap[destInOffset] = index;
+ }
+ }
+}
+
+void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo)
+{
+ destBindInfo.Coders.Clear();
+ destBindInfo.BindPairs.Clear();
+ destBindInfo.InStreams.Clear();
+ destBindInfo.OutStreams.Clear();
+
+ int i;
+ for (i = _srcBindInfo.Coders.Size() - 1; i >= 0; i--)
+ {
+ const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i];
+ CCoderStreamsInfo destCoderInfo;
+ destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams;
+ destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams;
+ destBindInfo.Coders.Add(destCoderInfo);
+ }
+ for (i = _srcBindInfo.BindPairs.Size() - 1; i >= 0; i--)
+ {
+ const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i];
+ CBindPair destBindPair;
+ destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex];
+ destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex];
+ destBindInfo.BindPairs.Add(destBindPair);
+ }
+ for (i = 0; i < _srcBindInfo.InStreams.Size(); i++)
+ destBindInfo.OutStreams.Add(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]);
+ for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++)
+ destBindInfo.InStreams.Add(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]);
+}
+
+CCoderInfo::CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
+ NumInStreams(numInStreams),
+ NumOutStreams(numOutStreams)
+{
+ InSizes.Reserve(NumInStreams);
+ InSizePointers.Reserve(NumInStreams);
+ OutSizePointers.Reserve(NumOutStreams);
+ OutSizePointers.Reserve(NumOutStreams);
+}
+
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
+ CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+{
+ sizes.Clear();
+ sizePointers.Clear();
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ if (srcSizes == 0 || srcSizes[i] == NULL)
+ {
+ sizes.Add(0);
+ sizePointers.Add(NULL);
+ }
+ else
+ {
+ sizes.Add(*srcSizes[i]);
+ sizePointers.Add(&sizes.Back());
+ }
+ }
+}
+
+void CCoderInfo::SetCoderInfo(const UInt64 **inSizes,
+ const UInt64 **outSizes)
+{
+ SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
+ SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+}
+
+}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h
new file mode 100755
index 00000000..78a3f280
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2.h
@@ -0,0 +1,168 @@
+// CoderMixer2.h
+
+#ifndef __CODER_MIXER2_H
+#define __CODER_MIXER2_H
+
+#include "../../../Common/Vector.h"
+#include "../../../Common/Types.h"
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
+namespace NCoderMixer2 {
+
+struct CBindPair
+{
+ UInt32 InIndex;
+ UInt32 OutIndex;
+};
+
+struct CCoderStreamsInfo
+{
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+};
+
+struct CBindInfo
+{
+ CRecordVector<CCoderStreamsInfo> Coders;
+ CRecordVector<CBindPair> BindPairs;
+ CRecordVector<UInt32> InStreams;
+ CRecordVector<UInt32> OutStreams;
+
+ void Clear()
+ {
+ Coders.Clear();
+ BindPairs.Clear();
+ InStreams.Clear();
+ OutStreams.Clear();
+ }
+
+ /*
+ UInt32 GetCoderStartOutStream(UInt32 coderIndex) const
+ {
+ UInt32 numOutStreams = 0;
+ for (UInt32 i = 0; i < coderIndex; i++)
+ numOutStreams += Coders[i].NumOutStreams;
+ return numOutStreams;
+ }
+ */
+
+
+ void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const
+ {
+ numInStreams = 0;
+ numOutStreams = 0;
+ for (int i = 0; i < Coders.Size(); i++)
+ {
+ const CCoderStreamsInfo &coderStreamsInfo = Coders[i];
+ numInStreams += coderStreamsInfo.NumInStreams;
+ numOutStreams += coderStreamsInfo.NumOutStreams;
+ }
+ }
+
+ int FindBinderForInStream(UInt32 inStream) const
+ {
+ for (int i = 0; i < BindPairs.Size(); i++)
+ if (BindPairs[i].InIndex == inStream)
+ return i;
+ return -1;
+ }
+ int FindBinderForOutStream(UInt32 outStream) const
+ {
+ for (int i = 0; i < BindPairs.Size(); i++)
+ if (BindPairs[i].OutIndex == outStream)
+ return i;
+ return -1;
+ }
+
+ UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const
+ {
+ UInt32 streamIndex = 0;
+ for (UInt32 i = 0; i < coderIndex; i++)
+ streamIndex += Coders[i].NumInStreams;
+ return streamIndex;
+ }
+
+ UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const
+ {
+ UInt32 streamIndex = 0;
+ for (UInt32 i = 0; i < coderIndex; i++)
+ streamIndex += Coders[i].NumOutStreams;
+ return streamIndex;
+ }
+
+
+ void FindInStream(UInt32 streamIndex, UInt32 &coderIndex,
+ UInt32 &coderStreamIndex) const
+ {
+ for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
+ {
+ UInt32 curSize = Coders[coderIndex].NumInStreams;
+ if (streamIndex < curSize)
+ {
+ coderStreamIndex = streamIndex;
+ return;
+ }
+ streamIndex -= curSize;
+ }
+ throw 1;
+ }
+ void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex,
+ UInt32 &coderStreamIndex) const
+ {
+ for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++)
+ {
+ UInt32 curSize = Coders[coderIndex].NumOutStreams;
+ if (streamIndex < curSize)
+ {
+ coderStreamIndex = streamIndex;
+ return;
+ }
+ streamIndex -= curSize;
+ }
+ throw 1;
+ }
+};
+
+class CBindReverseConverter
+{
+ UInt32 _numSrcOutStreams;
+ NCoderMixer2::CBindInfo _srcBindInfo;
+ CRecordVector<UInt32> _srcInToDestOutMap;
+ CRecordVector<UInt32> _srcOutToDestInMap;
+ CRecordVector<UInt32> _destInToSrcOutMap;
+public:
+ UInt32 NumSrcInStreams;
+ CRecordVector<UInt32> DestOutToSrcInMap;
+
+ CBindReverseConverter(const NCoderMixer2::CBindInfo &srcBindInfo);
+ void CreateReverseBindInfo(NCoderMixer2::CBindInfo &destBindInfo);
+};
+
+struct CCoderInfo
+{
+ CMyComPtr<ICompressCoder> Coder;
+ CMyComPtr<ICompressCoder2> Coder2;
+ UInt32 NumInStreams;
+ UInt32 NumOutStreams;
+
+ CRecordVector<UInt64> InSizes;
+ CRecordVector<UInt64> OutSizes;
+ CRecordVector<const UInt64 *> InSizePointers;
+ CRecordVector<const UInt64 *> OutSizePointers;
+
+ CCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
+ void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes);
+};
+
+class CCoderMixer2
+{
+public:
+ virtual void SetBindInfo(const CBindInfo &bindInfo) = 0;
+ virtual void ReInit() = 0;
+ virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0;
+};
+
+}
+#endif
+
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
new file mode 100755
index 00000000..9d7944b1
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp
@@ -0,0 +1,359 @@
+// CoderMixer2MT.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2MT.h"
+#include "CrossThreadProgress.h"
+
+using namespace NWindows;
+using namespace NSynchronization;
+
+namespace NCoderMixer2 {
+
+CThreadCoderInfo::CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams):
+ ExitEvent(NULL),
+ CompressEvent(NULL),
+ CompressionCompletedEvent(NULL),
+ CCoderInfo(numInStreams, numOutStreams)
+{
+ InStreams.Reserve(NumInStreams);
+ InStreamPointers.Reserve(NumInStreams);
+ OutStreams.Reserve(NumOutStreams);
+ OutStreamPointers.Reserve(NumOutStreams);
+}
+
+void CThreadCoderInfo::CreateEvents()
+{
+ CompressEvent = new CAutoResetEvent(false);
+ CompressionCompletedEvent = new CAutoResetEvent(false);
+}
+
+CThreadCoderInfo::~CThreadCoderInfo()
+{
+ if (CompressEvent != NULL)
+ delete CompressEvent;
+ if (CompressionCompletedEvent != NULL)
+ delete CompressionCompletedEvent;
+}
+
+class CCoderInfoFlusher2
+{
+ CThreadCoderInfo *m_CoderInfo;
+public:
+ CCoderInfoFlusher2(CThreadCoderInfo *coderInfo): m_CoderInfo(coderInfo) {}
+ ~CCoderInfoFlusher2()
+ {
+ int i;
+ for (i = 0; i < m_CoderInfo->InStreams.Size(); i++)
+ m_CoderInfo->InStreams[i].Release();
+ for (i = 0; i < m_CoderInfo->OutStreams.Size(); i++)
+ m_CoderInfo->OutStreams[i].Release();
+ m_CoderInfo->CompressionCompletedEvent->Set();
+ }
+};
+
+bool CThreadCoderInfo::WaitAndCode()
+{
+ HANDLE events[2] = { ExitEvent, *CompressEvent };
+ DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ if (waitResult == WAIT_OBJECT_0 + 0)
+ return false;
+
+ {
+ InStreamPointers.Clear();
+ OutStreamPointers.Clear();
+ UInt32 i;
+ for (i = 0; i < NumInStreams; i++)
+ {
+ if (InSizePointers[i] != NULL)
+ InSizePointers[i] = &InSizes[i];
+ InStreamPointers.Add(InStreams[i]);
+ }
+ for (i = 0; i < NumOutStreams; i++)
+ {
+ if (OutSizePointers[i] != NULL)
+ OutSizePointers[i] = &OutSizes[i];
+ OutStreamPointers.Add(OutStreams[i]);
+ }
+ CCoderInfoFlusher2 coderInfoFlusher(this);
+ if (Coder)
+ Result = Coder->Code(InStreamPointers[0],
+ OutStreamPointers[0],
+ InSizePointers[0],
+ OutSizePointers[0],
+ Progress);
+ else
+ Result = Coder2->Code(&InStreamPointers.Front(),
+ &InSizePointers.Front(),
+ NumInStreams,
+ &OutStreamPointers.Front(),
+ &OutSizePointers.Front(),
+ NumOutStreams,
+ Progress);
+ }
+ return true;
+}
+
+static void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes,
+ CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems)
+{
+ sizes.Clear();
+ sizePointers.Clear();
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ if (srcSizes == 0 || srcSizes[i] == NULL)
+ {
+ sizes.Add(0);
+ sizePointers.Add(NULL);
+ }
+ else
+ {
+ sizes.Add(*srcSizes[i]);
+ sizePointers.Add(&sizes.Back());
+ }
+ }
+}
+
+
+void CThreadCoderInfo::SetCoderInfo(const UInt64 **inSizes,
+ const UInt64 **outSizes, ICompressProgressInfo *progress)
+{
+ Progress = progress;
+ SetSizes(inSizes, InSizes, InSizePointers, NumInStreams);
+ SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams);
+}
+
+static DWORD WINAPI CoderThread(void *threadCoderInfo)
+{
+ for (;;)
+ {
+ if (!((CThreadCoderInfo *)threadCoderInfo)->WaitAndCode())
+ return 0;
+ }
+}
+
+//////////////////////////////////////
+// CCoderMixer2MT
+
+static DWORD WINAPI MainCoderThread(void *threadCoderInfo)
+{
+ for (;;)
+ {
+ if (!((CCoderMixer2MT *)threadCoderInfo)->MyCode())
+ return 0;
+ }
+}
+
+CCoderMixer2MT::CCoderMixer2MT()
+{
+ if (!_mainThread.Create(MainCoderThread, this))
+ throw 271825;
+}
+
+CCoderMixer2MT::~CCoderMixer2MT()
+{
+ _exitEvent.Set();
+ _mainThread.Wait();
+ for(int i = 0; i < _threads.Size(); i++)
+ {
+ _threads[i].Wait();
+ _threads[i].Close();
+ }
+}
+
+void CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo)
+{
+ _bindInfo = bindInfo;
+ _streamBinders.Clear();
+ for(int i = 0; i < _bindInfo.BindPairs.Size(); i++)
+ {
+ _streamBinders.Add(CStreamBinder());
+ _streamBinders.Back().CreateEvents();
+ }
+}
+
+void CCoderMixer2MT::AddCoderCommon()
+{
+ int index = _coderInfoVector.Size();
+ const CCoderStreamsInfo &CoderStreamsInfo = _bindInfo.Coders[index];
+
+ CThreadCoderInfo threadCoderInfo(CoderStreamsInfo.NumInStreams,
+ CoderStreamsInfo.NumOutStreams);
+ _coderInfoVector.Add(threadCoderInfo);
+ _coderInfoVector.Back().CreateEvents();
+ _coderInfoVector.Back().ExitEvent = _exitEvent;
+ _compressingCompletedEvents.Add(*_coderInfoVector.Back().CompressionCompletedEvent);
+
+ NWindows::CThread newThread;
+ _threads.Add(newThread);
+ if (!_threads.Back().Create(CoderThread, &_coderInfoVector.Back()))
+ throw 271824;
+}
+
+void CCoderMixer2MT::AddCoder(ICompressCoder *coder)
+{
+ AddCoderCommon();
+ _coderInfoVector.Back().Coder = coder;
+}
+
+void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder)
+{
+ AddCoderCommon();
+ _coderInfoVector.Back().Coder2 = coder;
+}
+
+/*
+void CCoderMixer2MT::FinishAddingCoders()
+{
+ for(int i = 0; i < _coderInfoVector.Size(); i++)
+ {
+ DWORD id;
+ HANDLE newThread = ::CreateThread(NULL, 0, CoderThread,
+ &_coderInfoVector[i], 0, &id);
+ if (newThread == 0)
+ throw 271824;
+ _threads.Add(newThread);
+ }
+}
+*/
+
+void CCoderMixer2MT::ReInit()
+{
+ for(int i = 0; i < _streamBinders.Size(); i++)
+ _streamBinders[i].ReInit();
+}
+
+
+STDMETHODIMP CCoderMixer2MT::Init(ISequentialInStream **inStreams,
+ ISequentialOutStream **outStreams)
+{
+ if (_coderInfoVector.Size() != _bindInfo.Coders.Size())
+ throw 0;
+ int i;
+ for(i = 0; i < _coderInfoVector.Size(); i++)
+ {
+ CThreadCoderInfo &coderInfo = _coderInfoVector[i];
+ const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i];
+ coderInfo.InStreams.Clear();
+ UInt32 j;
+ for(j = 0; j < coderStreamsInfo.NumInStreams; j++)
+ coderInfo.InStreams.Add(NULL);
+ coderInfo.OutStreams.Clear();
+ for(j = 0; j < coderStreamsInfo.NumOutStreams; j++)
+ coderInfo.OutStreams.Add(NULL);
+ }
+
+ for(i = 0; i < _bindInfo.BindPairs.Size(); i++)
+ {
+ const CBindPair &bindPair = _bindInfo.BindPairs[i];
+ UInt32 inCoderIndex, inCoderStreamIndex;
+ UInt32 outCoderIndex, outCoderStreamIndex;
+ _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex);
+ _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex);
+
+ _streamBinders[i].CreateStreams(
+ &_coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex],
+ &_coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex]);
+ }
+
+ for(i = 0; i < _bindInfo.InStreams.Size(); i++)
+ {
+ UInt32 inCoderIndex, inCoderStreamIndex;
+ _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex);
+ _coderInfoVector[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i];
+ }
+
+ for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
+ {
+ UInt32 outCoderIndex, outCoderStreamIndex;
+ _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex);
+ _coderInfoVector[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i];
+ }
+ return S_OK;
+}
+
+
+bool CCoderMixer2MT::MyCode()
+{
+ HANDLE events[2] = { _exitEvent, _startCompressingEvent };
+ DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ if (waitResult == WAIT_OBJECT_0 + 0)
+ return false;
+
+ for(int i = 0; i < _coderInfoVector.Size(); i++)
+ _coderInfoVector[i].CompressEvent->Set();
+ /* DWORD result = */ ::WaitForMultipleObjects(_compressingCompletedEvents.Size(),
+ &_compressingCompletedEvents.Front(), TRUE, INFINITE);
+
+ _compressingFinishedEvent.Set();
+
+ return true;
+}
+
+
+STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams,
+ const UInt64 ** /* inSizes */,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 ** /* outSizes */,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
+ numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
+ return E_INVALIDARG;
+
+ Init(inStreams, outStreams);
+
+ _compressingFinishedEvent.Reset(); // ?
+
+ CCrossThreadProgress *progressSpec = new CCrossThreadProgress;
+ CMyComPtr<ICompressProgressInfo> crossProgress = progressSpec;
+ progressSpec->Init();
+ _coderInfoVector[_progressCoderIndex].Progress = crossProgress;
+
+ _startCompressingEvent.Set();
+
+
+ for (;;)
+ {
+ HANDLE events[2] = {_compressingFinishedEvent, progressSpec->ProgressEvent };
+ DWORD waitResult = ::WaitForMultipleObjects(2, events, FALSE, INFINITE);
+ if (waitResult == WAIT_OBJECT_0 + 0)
+ break;
+ if (progress != NULL)
+ progressSpec->Result = progress->SetRatioInfo(progressSpec->InSize,
+ progressSpec->OutSize);
+ else
+ progressSpec->Result = S_OK;
+ progressSpec->WaitEvent.Set();
+ }
+
+ int i;
+ for(i = 0; i < _coderInfoVector.Size(); i++)
+ {
+ HRESULT result = _coderInfoVector[i].Result;
+ if (result == S_FALSE)
+ return result;
+ }
+ for(i = 0; i < _coderInfoVector.Size(); i++)
+ {
+ HRESULT result = _coderInfoVector[i].Result;
+ if (result != S_OK && result != E_FAIL)
+ return result;
+ }
+ for(i = 0; i < _coderInfoVector.Size(); i++)
+ {
+ HRESULT result = _coderInfoVector[i].Result;
+ if (result != S_OK)
+ return result;
+ }
+ return S_OK;
+}
+
+UInt64 CCoderMixer2MT::GetWriteProcessedSize(UInt32 binderIndex) const
+{
+ return _streamBinders[binderIndex].ProcessedSize;
+}
+
+}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h
new file mode 100755
index 00000000..78d752de
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h
@@ -0,0 +1,121 @@
+// CoderMixer2MT.h
+
+#ifndef __CODER_MIXER2_MT_H
+#define __CODER_MIXER2_MT_H
+
+#include "CoderMixer2.h"
+#include "../../../Common/MyCom.h"
+#include "../../../Windows/Thread.h"
+#include "../../Common/StreamBinder.h"
+
+namespace NCoderMixer2 {
+
+// CreateEvents();
+// {
+// SetCoderInfo()
+// Init Streams
+// set CompressEvent()
+// wait CompressionCompletedEvent
+// }
+
+struct CThreadCoderInfo: public CCoderInfo
+{
+ NWindows::NSynchronization::CAutoResetEvent *CompressEvent;
+ HANDLE ExitEvent;
+ NWindows::NSynchronization::CAutoResetEvent *CompressionCompletedEvent;
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > InStreams;
+ CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams;
+ CRecordVector<ISequentialInStream *> InStreamPointers;
+ CRecordVector<ISequentialOutStream *> OutStreamPointers;
+
+ CMyComPtr<ICompressProgressInfo> Progress; // CMyComPtr
+ HRESULT Result;
+
+ CThreadCoderInfo(UInt32 numInStreams, UInt32 numOutStreams);
+ void SetCoderInfo(const UInt64 **inSizes,
+ const UInt64 **outSizes, ICompressProgressInfo *progress);
+ ~CThreadCoderInfo();
+ bool WaitAndCode();
+ void CreateEvents();
+};
+
+
+// SetBindInfo()
+// for each coder
+// {
+// AddCoder[2]()
+// }
+//
+// for each file
+// {
+// ReInit()
+// for each coder
+// {
+// SetCoderInfo
+// }
+// SetProgressIndex(UInt32 coderIndex);
+// Code
+// }
+
+
+class CCoderMixer2MT:
+ public ICompressCoder2,
+ public CCoderMixer2,
+ public CMyUnknownImp
+{
+ MY_UNKNOWN_IMP
+
+public:
+ STDMETHOD(Init)(ISequentialInStream **inStreams,
+ ISequentialOutStream **outStreams);
+
+ STDMETHOD(Code)(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
+
+
+ CCoderMixer2MT();
+ ~CCoderMixer2MT();
+ void AddCoderCommon();
+ void AddCoder(ICompressCoder *coder);
+ void AddCoder2(ICompressCoder2 *coder);
+
+ void ReInit();
+ void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
+ { _coderInfoVector[coderIndex].SetCoderInfo(inSizes, outSizes, NULL); }
+ void SetProgressCoderIndex(UInt32 coderIndex)
+ { _progressCoderIndex = coderIndex; }
+
+
+ UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
+
+
+ bool MyCode();
+
+private:
+ CBindInfo _bindInfo;
+ CObjectVector<CStreamBinder> _streamBinders;
+ CObjectVector<CThreadCoderInfo> _coderInfoVector;
+ CRecordVector<NWindows::CThread> _threads;
+ NWindows::CThread _mainThread;
+
+ NWindows::NSynchronization::CAutoResetEvent _startCompressingEvent;
+ CRecordVector<HANDLE> _compressingCompletedEvents;
+ NWindows::NSynchronization::CAutoResetEvent _compressingFinishedEvent;
+
+ NWindows::NSynchronization::CManualResetEvent _exitEvent;
+ UInt32 _progressCoderIndex;
+
+public:
+ void SetBindInfo(const CBindInfo &bindInfo);
+
+};
+
+}
+#endif
+
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
new file mode 100755
index 00000000..c01b776d
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp
@@ -0,0 +1,238 @@
+// CoderMixer2ST.cpp
+
+#include "StdAfx.h"
+
+#include "CoderMixer2ST.h"
+
+namespace NCoderMixer2 {
+
+CCoderMixer2ST::CCoderMixer2ST() {}
+
+CCoderMixer2ST::~CCoderMixer2ST(){ }
+
+void CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo)
+{
+ _bindInfo = bindInfo;
+}
+
+void CCoderMixer2ST::AddCoderCommon(bool isMain)
+{
+ const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()];
+ _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain));
+}
+
+void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain)
+{
+ AddCoderCommon(isMain);
+ _coders.Back().Coder = coder;
+}
+
+void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain)
+{
+ AddCoderCommon(isMain);
+ _coders.Back().Coder2 = coder;
+}
+
+void CCoderMixer2ST::ReInit() { }
+
+HRESULT CCoderMixer2ST::GetInStream(
+ ISequentialInStream **inStreams, const UInt64 **inSizes,
+ UInt32 streamIndex, ISequentialInStream **inStreamRes)
+{
+ CMyComPtr<ISequentialInStream> seqInStream;
+ int i;
+ for(i = 0; i < _bindInfo.InStreams.Size(); i++)
+ if (_bindInfo.InStreams[i] == streamIndex)
+ {
+ seqInStream = inStreams[i];
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+ }
+ int binderIndex = _bindInfo.FindBinderForInStream(streamIndex);
+ if (binderIndex < 0)
+ return E_INVALIDARG;
+
+ UInt32 coderIndex, coderStreamIndex;
+ _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex,
+ coderIndex, coderStreamIndex);
+
+ CCoderInfo &coder = _coders[coderIndex];
+ if (!coder.Coder)
+ return E_NOTIMPL;
+ coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream);
+ if (!seqInStream)
+ return E_NOTIMPL;
+
+ UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex);
+
+ CMyComPtr<ICompressSetInStream> setInStream;
+ if (!coder.Coder)
+ return E_NOTIMPL;
+ coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream);
+ if (!setInStream)
+ return E_NOTIMPL;
+
+ if (coder.NumInStreams > 1)
+ return E_NOTIMPL;
+ for (i = 0; i < (int)coder.NumInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream2;
+ RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2));
+ RINOK(setInStream->SetInStream(seqInStream2));
+ }
+ *inStreamRes = seqInStream.Detach();
+ return S_OK;
+}
+
+HRESULT CCoderMixer2ST::GetOutStream(
+ ISequentialOutStream **outStreams, const UInt64 **outSizes,
+ UInt32 streamIndex, ISequentialOutStream **outStreamRes)
+{
+ CMyComPtr<ISequentialOutStream> seqOutStream;
+ int i;
+ for(i = 0; i < _bindInfo.OutStreams.Size(); i++)
+ if (_bindInfo.OutStreams[i] == streamIndex)
+ {
+ seqOutStream = outStreams[i];
+ *outStreamRes = seqOutStream.Detach();
+ return S_OK;
+ }
+ int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex);
+ if (binderIndex < 0)
+ return E_INVALIDARG;
+
+ UInt32 coderIndex, coderStreamIndex;
+ _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex,
+ coderIndex, coderStreamIndex);
+
+ CCoderInfo &coder = _coders[coderIndex];
+ if (!coder.Coder)
+ return E_NOTIMPL;
+ coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream);
+ if (!seqOutStream)
+ return E_NOTIMPL;
+
+ UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
+
+ CMyComPtr<ICompressSetOutStream> setOutStream;
+ if (!coder.Coder)
+ return E_NOTIMPL;
+ coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream);
+ if (!setOutStream)
+ return E_NOTIMPL;
+
+ if (coder.NumOutStreams > 1)
+ return E_NOTIMPL;
+ for (i = 0; i < (int)coder.NumOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream2;
+ RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2));
+ RINOK(setOutStream->SetOutStream(seqOutStream2));
+ }
+ *outStreamRes = seqOutStream.Detach();
+ return S_OK;
+}
+
+
+STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress)
+{
+ if (numInStreams != (UInt32)_bindInfo.InStreams.Size() ||
+ numOutStreams != (UInt32)_bindInfo.OutStreams.Size())
+ return E_INVALIDARG;
+
+ // Find main coder
+ int _mainCoderIndex = -1;
+ int i;
+ for (i = 0; i < _coders.Size(); i++)
+ if (_coders[i].IsMain)
+ {
+ _mainCoderIndex = i;
+ break;
+ }
+ if (_mainCoderIndex < 0)
+ for (i = 0; i < _coders.Size(); i++)
+ if (_coders[i].NumInStreams > 1)
+ {
+ if (_mainCoderIndex >= 0)
+ return E_NOTIMPL;
+ _mainCoderIndex = i;
+ }
+ if (_mainCoderIndex < 0)
+ _mainCoderIndex = 0;
+
+ // _mainCoderIndex = 0;
+ // _mainCoderIndex = _coders.Size() - 1;
+ CCoderInfo &mainCoder = _coders[_mainCoderIndex];
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams;
+ CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams;
+ UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex);
+ UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex);
+ for (i = 0; i < (int)mainCoder.NumInStreams; i++)
+ {
+ CMyComPtr<ISequentialInStream> seqInStream;
+ RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream));
+ seqInStreams.Add(seqInStream);
+ }
+ for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
+ {
+ CMyComPtr<ISequentialOutStream> seqOutStream;
+ RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream));
+ seqOutStreams.Add(seqOutStream);
+ }
+ CRecordVector< ISequentialInStream * > seqInStreamsSpec;
+ CRecordVector< ISequentialOutStream * > seqOutStreamsSpec;
+ for (i = 0; i < (int)mainCoder.NumInStreams; i++)
+ seqInStreamsSpec.Add(seqInStreams[i]);
+ for (i = 0; i < (int)mainCoder.NumOutStreams; i++)
+ seqOutStreamsSpec.Add(seqOutStreams[i]);
+
+ for (i = 0; i < _coders.Size(); i++)
+ {
+ if (i == _mainCoderIndex)
+ continue;
+ CCoderInfo &coder = _coders[i];
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+ if (setOutStreamSize)
+ {
+ RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0]));
+ }
+ }
+ if (mainCoder.Coder)
+ {
+ RINOK(mainCoder.Coder->Code(
+ seqInStreamsSpec[0], seqOutStreamsSpec[0],
+ mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0],
+ progress));
+ }
+ else
+ {
+ RINOK(mainCoder.Coder2->Code(
+ &seqInStreamsSpec.Front(),
+ &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams,
+ &seqOutStreamsSpec.Front(),
+ &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams,
+ progress));
+ }
+ CMyComPtr<IOutStreamFlush> flush;
+ seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush);
+ if (flush)
+ return flush->Flush();
+ return S_OK;
+}
+
+/*
+UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const
+{
+ return _streamBinders[binderIndex].ProcessedSize;
+}
+*/
+
+}
diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h
new file mode 100755
index 00000000..3144918b
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h
@@ -0,0 +1,88 @@
+// CoderMixer2ST.h
+
+#ifndef __CODER_MIXER2_ST_H
+#define __CODER_MIXER2_ST_H
+
+#include "CoderMixer2.h"
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+
+namespace NCoderMixer2 {
+
+// SetBindInfo()
+// for each coder
+// {
+// AddCoder[2]()
+// }
+//
+// for each file
+// {
+// ReInit()
+// for each coder
+// {
+// SetCoderInfo
+// }
+// SetProgressIndex(UInt32 coderIndex);
+// Code
+// }
+
+struct CSTCoderInfo: public CCoderInfo
+{
+ bool IsMain;
+ CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain):
+ CCoderInfo(numInStreams, numOutStreams),IsMain(isMain) {}
+};
+
+class CCoderMixer2ST:
+ public ICompressCoder2,
+ public CCoderMixer2,
+ public CMyUnknownImp
+{
+ MY_UNKNOWN_IMP
+
+ HRESULT GetInStream(
+ ISequentialInStream **inStreams, const UInt64 **inSizes,
+ UInt32 streamIndex, ISequentialInStream **inStreamRes);
+ HRESULT GetOutStream(
+ ISequentialOutStream **outStreams, const UInt64 **outSizes,
+ UInt32 streamIndex, ISequentialOutStream **outStreamRes);
+public:
+ STDMETHOD(Code)(ISequentialInStream **inStreams,
+ const UInt64 **inSizes,
+ UInt32 numInStreams,
+ ISequentialOutStream **outStreams,
+ const UInt64 **outSizes,
+ UInt32 numOutStreams,
+ ICompressProgressInfo *progress);
+
+ CCoderMixer2ST();
+ ~CCoderMixer2ST();
+ void AddCoderCommon(bool isMain);
+ void AddCoder(ICompressCoder *coder, bool isMain);
+ void AddCoder2(ICompressCoder2 *coder, bool isMain);
+
+ void ReInit();
+ void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes)
+ {
+ { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); }
+ }
+
+ void SetProgressCoderIndex(UInt32 /*coderIndex*/)
+ {
+ // _progressCoderIndex = coderIndex;
+ }
+
+ // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const;
+
+private:
+ CBindInfo _bindInfo;
+ CObjectVector<CSTCoderInfo> _coders;
+ int _mainCoderIndex;
+public:
+ void SetBindInfo(const CBindInfo &bindInfo);
+
+};
+
+}
+#endif
+
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.cpp b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
new file mode 100755
index 00000000..a974b54c
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CrossThreadProgress.cpp
@@ -0,0 +1,15 @@
+// CrossThreadProgress.cpp
+
+#include "StdAfx.h"
+
+#include "CrossThreadProgress.h"
+
+STDMETHODIMP CCrossThreadProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
+{
+ InSize = inSize;
+ OutSize = outSize;
+ ProgressEvent.Set();
+ WaitEvent.Lock();
+ return Result;
+}
+
diff --git a/CPP/7zip/Archive/Common/CrossThreadProgress.h b/CPP/7zip/Archive/Common/CrossThreadProgress.h
new file mode 100755
index 00000000..5dd339dc
--- /dev/null
+++ b/CPP/7zip/Archive/Common/CrossThreadProgress.h
@@ -0,0 +1,31 @@
+// CrossThreadProgress.h
+
+#ifndef __CROSSTHREADPROGRESS_H
+#define __CROSSTHREADPROGRESS_H
+
+#include "../../ICoder.h"
+#include "../../../Windows/Synchronization.h"
+#include "../../../Common/MyCom.h"
+
+class CCrossThreadProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
+{
+public:
+ const UInt64 *InSize;
+ const UInt64 *OutSize;
+ HRESULT Result;
+ NWindows::NSynchronization::CAutoResetEvent ProgressEvent;
+ NWindows::NSynchronization::CAutoResetEvent WaitEvent;
+ void Init()
+ {
+ ProgressEvent.Reset();
+ WaitEvent.Reset();
+ }
+
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+#endif
diff --git a/CPP/7zip/Archive/Common/DummyOutStream.cpp b/CPP/7zip/Archive/Common/DummyOutStream.cpp
new file mode 100755
index 00000000..b1d49913
--- /dev/null
+++ b/CPP/7zip/Archive/Common/DummyOutStream.cpp
@@ -0,0 +1,20 @@
+// DummyOutStream.cpp
+
+#include "StdAfx.h"
+
+#include "DummyOutStream.h"
+
+void CDummyOutStream::Init(ISequentialOutStream *outStream)
+{
+ m_Stream = outStream;
+}
+
+STDMETHODIMP CDummyOutStream::Write(const void *data,
+ UInt32 size, UInt32 *processedSize)
+{
+ if(m_Stream)
+ return m_Stream->Write(data, size, processedSize);
+ if(processedSize != NULL)
+ *processedSize = size;
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Common/DummyOutStream.h b/CPP/7zip/Archive/Common/DummyOutStream.h
new file mode 100755
index 00000000..51690787
--- /dev/null
+++ b/CPP/7zip/Archive/Common/DummyOutStream.h
@@ -0,0 +1,23 @@
+// DummyOutStream.h
+
+#ifndef __DUMMYOUTSTREAM_H
+#define __DUMMYOUTSTREAM_H
+
+#include "../../IStream.h"
+#include "Common/MyCom.h"
+
+class CDummyOutStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialOutStream> m_Stream;
+public:
+ void Init(ISequentialOutStream *outStream);
+};
+
+#endif
diff --git a/CPP/7zip/Archive/Common/FilterCoder.cpp b/CPP/7zip/Archive/Common/FilterCoder.cpp
new file mode 100755
index 00000000..5e104c84
--- /dev/null
+++ b/CPP/7zip/Archive/Common/FilterCoder.cpp
@@ -0,0 +1,243 @@
+// FilterCoder.cpp
+
+#include "StdAfx.h"
+
+#include "FilterCoder.h"
+#include "../../../Common/Alloc.h"
+#include "../../../Common/Defs.h"
+#include "../../Common/StreamUtils.h"
+
+static const int kBufferSize = 1 << 17;
+
+CFilterCoder::CFilterCoder()
+{
+ _buffer = (Byte *)::MidAlloc(kBufferSize);
+}
+
+CFilterCoder::~CFilterCoder()
+{
+ ::MidFree(_buffer);
+}
+
+HRESULT CFilterCoder::WriteWithLimit(ISequentialOutStream *outStream, UInt32 size)
+{
+ if (_outSizeIsDefined)
+ {
+ UInt64 remSize = _outSize - _nowPos64;
+ if (size > remSize)
+ size = (UInt32)remSize;
+ }
+ UInt32 processedSize = 0;
+ RINOK(WriteStream(outStream, _buffer, size, &processedSize));
+ if (size != processedSize)
+ return E_FAIL;
+ _nowPos64 += processedSize;
+ return S_OK;
+}
+
+
+STDMETHODIMP CFilterCoder::Code(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, const UInt64 * /* inSize */, const UInt64 *outSize,
+ ICompressProgressInfo *progress)
+{
+ RINOK(Init());
+ UInt32 bufferPos = 0;
+ _outSizeIsDefined = (outSize != 0);
+ if (_outSizeIsDefined)
+ _outSize = *outSize;
+
+ while(NeedMore())
+ {
+ UInt32 processedSize;
+
+ // Change it: It can be optimized using ReadPart
+ RINOK(ReadStream(inStream, _buffer + bufferPos, kBufferSize - bufferPos, &processedSize));
+
+ UInt32 endPos = bufferPos + processedSize;
+
+ bufferPos = Filter->Filter(_buffer, endPos);
+ if (bufferPos > endPos)
+ {
+ for (; endPos< bufferPos; endPos++)
+ _buffer[endPos] = 0;
+ bufferPos = Filter->Filter(_buffer, endPos);
+ }
+
+ if (bufferPos == 0)
+ {
+ if (endPos > 0)
+ return WriteWithLimit(outStream, endPos);
+ return S_OK;
+ }
+ RINOK(WriteWithLimit(outStream, bufferPos));
+ if (progress != NULL)
+ {
+ RINOK(progress->SetRatioInfo(&_nowPos64, &_nowPos64));
+ }
+ UInt32 i = 0;
+ while(bufferPos < endPos)
+ _buffer[i++] = _buffer[bufferPos++];
+ bufferPos = i;
+ }
+ return S_OK;
+}
+
+// #ifdef _ST_MODE
+STDMETHODIMP CFilterCoder::SetOutStream(ISequentialOutStream *outStream)
+{
+ _bufferPos = 0;
+ _outStream = outStream;
+ return Init();
+}
+
+STDMETHODIMP CFilterCoder::ReleaseOutStream()
+{
+ _outStream.Release();
+ return S_OK;
+};
+
+
+STDMETHODIMP CFilterCoder::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 processedSizeTotal = 0;
+ while(size > 0)
+ {
+ UInt32 sizeMax = kBufferSize - _bufferPos;
+ UInt32 sizeTemp = size;
+ if (sizeTemp > sizeMax)
+ sizeTemp = sizeMax;
+ memmove(_buffer + _bufferPos, data, sizeTemp);
+ size -= sizeTemp;
+ processedSizeTotal += sizeTemp;
+ data = (const Byte *)data + sizeTemp;
+ UInt32 endPos = _bufferPos + sizeTemp;
+ _bufferPos = Filter->Filter(_buffer, endPos);
+ if (_bufferPos == 0)
+ {
+ _bufferPos = endPos;
+ break;
+ }
+ if (_bufferPos > endPos)
+ {
+ if (size != 0)
+ return E_FAIL;
+ break;
+ }
+ RINOK(WriteWithLimit(_outStream, _bufferPos));
+ UInt32 i = 0;
+ while(_bufferPos < endPos)
+ _buffer[i++] = _buffer[_bufferPos++];
+ _bufferPos = i;
+ }
+ if (processedSize != NULL)
+ *processedSize = processedSizeTotal;
+ return S_OK;
+}
+
+STDMETHODIMP CFilterCoder::Flush()
+{
+ if (_bufferPos != 0)
+ {
+ UInt32 endPos = Filter->Filter(_buffer, _bufferPos);
+ if (endPos > _bufferPos)
+ {
+ for (; _bufferPos < endPos; _bufferPos++)
+ _buffer[_bufferPos] = 0;
+ if (Filter->Filter(_buffer, endPos) != endPos)
+ return E_FAIL;
+ }
+ UInt32 processedSize;
+ RINOK(WriteStream(_outStream, _buffer, _bufferPos, &processedSize));
+ if (_bufferPos != processedSize)
+ return E_FAIL;
+ _bufferPos = 0;
+ }
+ CMyComPtr<IOutStreamFlush> flush;
+ _outStream.QueryInterface(IID_IOutStreamFlush, &flush);
+ if (flush)
+ return flush->Flush();
+ return S_OK;
+}
+
+
+STDMETHODIMP CFilterCoder::SetInStream(ISequentialInStream *inStream)
+{
+ _convertedPosBegin = _convertedPosEnd = _bufferPos = 0;
+ _inStream = inStream;
+ return Init();
+}
+
+STDMETHODIMP CFilterCoder::ReleaseInStream()
+{
+ _inStream.Release();
+ return S_OK;
+};
+
+STDMETHODIMP CFilterCoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 processedSizeTotal = 0;
+ while(size > 0)
+ {
+ if (_convertedPosBegin != _convertedPosEnd)
+ {
+ UInt32 sizeTemp = MyMin(size, _convertedPosEnd - _convertedPosBegin);
+ memmove(data, _buffer + _convertedPosBegin, sizeTemp);
+ _convertedPosBegin += sizeTemp;
+ data = (void *)((Byte *)data + sizeTemp);
+ size -= sizeTemp;
+ processedSizeTotal += sizeTemp;
+ break;
+ }
+ int i;
+ for (i = 0; _convertedPosEnd + i < _bufferPos; i++)
+ _buffer[i] = _buffer[i + _convertedPosEnd];
+ _bufferPos = i;
+ _convertedPosBegin = _convertedPosEnd = 0;
+ UInt32 processedSizeTemp;
+ UInt32 size0 = kBufferSize - _bufferPos;
+ // Optimize it:
+ RINOK(ReadStream(_inStream, _buffer + _bufferPos, size0, &processedSizeTemp));
+ _bufferPos = _bufferPos + processedSizeTemp;
+ _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
+ if (_convertedPosEnd == 0)
+ {
+ if (_bufferPos == 0)
+ break;
+ else
+ {
+ _convertedPosEnd = _bufferPos; // check it
+ continue;
+ }
+ }
+ if (_convertedPosEnd > _bufferPos)
+ {
+ for (; _bufferPos < _convertedPosEnd; _bufferPos++)
+ _buffer[_bufferPos] = 0;
+ _convertedPosEnd = Filter->Filter(_buffer, _bufferPos);
+ }
+ }
+ if (processedSize != NULL)
+ *processedSize = processedSizeTotal;
+ return S_OK;
+}
+
+// #endif // _ST_MODE
+
+#ifndef _NO_CRYPTO
+STDMETHODIMP CFilterCoder::CryptoSetPassword(const Byte *data, UInt32 size)
+{
+ return _setPassword->CryptoSetPassword(data, size);
+}
+#endif
+
+#ifndef EXTRACT_ONLY
+STDMETHODIMP CFilterCoder::WriteCoderProperties(ISequentialOutStream *outStream)
+{
+ return _writeCoderProperties->WriteCoderProperties(outStream);
+}
+#endif
+
+STDMETHODIMP CFilterCoder::SetDecoderProperties2(const Byte *data, UInt32 size)
+{
+ return _setDecoderProperties->SetDecoderProperties2(data, size);
+}
diff --git a/CPP/7zip/Archive/Common/FilterCoder.h b/CPP/7zip/Archive/Common/FilterCoder.h
new file mode 100755
index 00000000..45618172
--- /dev/null
+++ b/CPP/7zip/Archive/Common/FilterCoder.h
@@ -0,0 +1,130 @@
+// FilterCoder.h
+
+#ifndef __FILTERCODER_H
+#define __FILTERCODER_H
+
+#include "../../../Common/MyCom.h"
+#include "../../ICoder.h"
+#include "../../IPassword.h"
+
+#define MY_QUERYINTERFACE_ENTRY_AG(i, sub0, sub) if (iid == IID_ ## i) \
+{ if (!sub) RINOK(sub0->QueryInterface(IID_ ## i, (void **)&sub)) \
+*outObject = (void *)(i *)this; AddRef(); return S_OK; }
+
+class CFilterCoder:
+ public ICompressCoder,
+ // #ifdef _ST_MODE
+ public ICompressSetInStream,
+ public ISequentialInStream,
+ public ICompressSetOutStream,
+ public ISequentialOutStream,
+ public IOutStreamFlush,
+ // #endif
+
+ #ifndef _NO_CRYPTO
+ public ICryptoSetPassword,
+ #endif
+ #ifndef EXTRACT_ONLY
+ public ICompressWriteCoderProperties,
+ #endif
+ public ICompressSetDecoderProperties2,
+ public CMyUnknownImp
+{
+protected:
+ Byte *_buffer;
+ // #ifdef _ST_MODE
+ CMyComPtr<ISequentialInStream> _inStream;
+ CMyComPtr<ISequentialOutStream> _outStream;
+ UInt32 _bufferPos;
+ UInt32 _convertedPosBegin;
+ UInt32 _convertedPosEnd;
+ // #endif
+ bool _outSizeIsDefined;
+ UInt64 _outSize;
+ UInt64 _nowPos64;
+
+ HRESULT Init()
+ {
+ _nowPos64 = 0;
+ _outSizeIsDefined = false;
+ return Filter->Init();
+ }
+
+ CMyComPtr<ICryptoSetPassword> _setPassword;
+ #ifndef EXTRACT_ONLY
+ CMyComPtr<ICompressWriteCoderProperties> _writeCoderProperties;
+ #endif
+ CMyComPtr<ICompressSetDecoderProperties2> _setDecoderProperties;
+public:
+ CMyComPtr<ICompressFilter> Filter;
+
+ CFilterCoder();
+ ~CFilterCoder();
+ HRESULT WriteWithLimit(ISequentialOutStream *outStream, UInt32 size);
+ bool NeedMore() const
+ { return (!_outSizeIsDefined || (_nowPos64 < _outSize)); }
+
+public:
+ MY_QUERYINTERFACE_BEGIN
+ MY_QUERYINTERFACE_ENTRY(ICompressCoder)
+ // #ifdef _ST_MODE
+ MY_QUERYINTERFACE_ENTRY(ICompressSetInStream)
+ MY_QUERYINTERFACE_ENTRY(ISequentialInStream)
+
+ MY_QUERYINTERFACE_ENTRY(ICompressSetOutStream)
+ MY_QUERYINTERFACE_ENTRY(ISequentialOutStream)
+ MY_QUERYINTERFACE_ENTRY(IOutStreamFlush)
+ // #endif
+
+ #ifndef _NO_CRYPTO
+ MY_QUERYINTERFACE_ENTRY_AG(ICryptoSetPassword, Filter, _setPassword)
+ #endif
+
+ #ifndef EXTRACT_ONLY
+ MY_QUERYINTERFACE_ENTRY_AG(ICompressWriteCoderProperties, Filter, _writeCoderProperties)
+ #endif
+
+ MY_QUERYINTERFACE_ENTRY_AG(ICompressSetDecoderProperties2, Filter, _setDecoderProperties)
+ MY_QUERYINTERFACE_END
+ MY_ADDREF_RELEASE
+ STDMETHOD(Code)(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, const UInt64 *inSize, const UInt64 *outSize,
+ ICompressProgressInfo *progress);
+ // #ifdef _ST_MODE
+ STDMETHOD(ReleaseInStream)();
+ STDMETHOD(SetInStream)(ISequentialInStream *inStream);
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); \
+ STDMETHOD(SetOutStream)(ISequentialOutStream *outStream);
+ STDMETHOD(ReleaseOutStream)();
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Flush)();
+ // #endif
+
+ #ifndef _NO_CRYPTO
+ STDMETHOD(CryptoSetPassword)(const Byte *data, UInt32 size);
+ #endif
+ #ifndef EXTRACT_ONLY
+ STDMETHOD(WriteCoderProperties)(ISequentialOutStream *outStream);
+ #endif
+ STDMETHOD(SetDecoderProperties2)(const Byte *data, UInt32 size);
+};
+
+// #ifdef _ST_MODE
+class CInStreamReleaser
+{
+public:
+ CFilterCoder *FilterCoder;
+ CInStreamReleaser(): FilterCoder(0) {}
+ ~CInStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseInStream(); }
+};
+
+class COutStreamReleaser
+{
+public:
+ CFilterCoder *FilterCoder;
+ COutStreamReleaser(): FilterCoder(0) {}
+ ~COutStreamReleaser() { if (FilterCoder) FilterCoder->ReleaseOutStream(); }
+};
+// #endif
+
+#endif
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.cpp b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
new file mode 100755
index 00000000..74dff7e1
--- /dev/null
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.cpp
@@ -0,0 +1,41 @@
+// InStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "InStreamWithCRC.h"
+
+STDMETHODIMP CSequentialInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ _size += realProcessedSize;
+ if (size > 0 && realProcessedSize == 0)
+ _wasFinished = true;
+ _crc.Update(data, realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+STDMETHODIMP CInStreamWithCRC::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = _stream->Read(data, size, &realProcessedSize);
+ if (size > 0 && realProcessedSize == 0)
+ _wasFinished = true;
+ _size += realProcessedSize;
+ _crc.Update(data, realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+STDMETHODIMP CInStreamWithCRC::Seek(Int64 offset,
+ UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if (seekOrigin != STREAM_SEEK_SET || offset != 0)
+ return E_FAIL;
+ _size = 0;
+ _crc.Init();
+ return _stream->Seek(offset, seekOrigin, newPosition);
+}
diff --git a/CPP/7zip/Archive/Common/InStreamWithCRC.h b/CPP/7zip/Archive/Common/InStreamWithCRC.h
new file mode 100755
index 00000000..770a1437
--- /dev/null
+++ b/CPP/7zip/Archive/Common/InStreamWithCRC.h
@@ -0,0 +1,65 @@
+// InStreamWithCRC.h
+
+#ifndef __INSTREAMWITHCRC_H
+#define __INSTREAMWITHCRC_H
+
+#include "../../../Common/CRC.h"
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+
+class CSequentialInStreamWithCRC:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialInStream> _stream;
+ UInt64 _size;
+ CCRC _crc;
+ bool _wasFinished;
+public:
+ void SetStream(ISequentialInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ _crc.Init();
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt32 GetCRC() const { return _crc.GetDigest(); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+class CInStreamWithCRC:
+ public IInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+private:
+ CMyComPtr<IInStream> _stream;
+ UInt64 _size;
+ CCRC _crc;
+ bool _wasFinished;
+public:
+ void SetStream(IInStream *stream) { _stream = stream; }
+ void Init()
+ {
+ _size = 0;
+ _wasFinished = false;
+ _crc.Init();
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt32 GetCRC() const { return _crc.GetDigest(); }
+ UInt64 GetSize() const { return _size; }
+ bool WasFinished() const { return _wasFinished; }
+};
+
+#endif
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.cpp b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
new file mode 100755
index 00000000..f7c3fcd9
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.cpp
@@ -0,0 +1,59 @@
+// Archive/Common/ItemNameUtils.cpp
+
+#include "StdAfx.h"
+
+#include "ItemNameUtils.h"
+
+namespace NArchive {
+namespace NItemName {
+
+static const wchar_t kOSDirDelimiter = WCHAR_PATH_SEPARATOR;
+static const wchar_t kDirDelimiter = L'/';
+
+UString MakeLegalName(const UString &name)
+{
+ UString zipName = name;
+ zipName.Replace(kOSDirDelimiter, kDirDelimiter);
+ return zipName;
+}
+
+UString GetOSName(const UString &name)
+{
+ UString newName = name;
+ newName.Replace(kDirDelimiter, kOSDirDelimiter);
+ return newName;
+}
+
+UString GetOSName2(const UString &name)
+{
+ if (name.IsEmpty())
+ return UString();
+ UString newName = GetOSName(name);
+ if (newName[newName.Length() - 1] == kOSDirDelimiter)
+ newName.Delete(newName.Length() - 1);
+ return newName;
+}
+
+bool HasTailSlash(const AString &name, UINT codePage)
+{
+ if (name.IsEmpty())
+ return false;
+ LPCSTR prev =
+ #ifdef _WIN32
+ CharPrevExA((WORD)codePage, name, &name[name.Length()], 0);
+ #else
+ (LPCSTR)(name) + (name.Length() - 1);
+ #endif
+ return (*prev == '/');
+}
+
+#ifndef _WIN32
+UString WinNameToOSName(const UString &name)
+{
+ UString newName = name;
+ newName.Replace(L'\\', kOSDirDelimiter);
+ return newName;
+}
+#endif
+
+}}
diff --git a/CPP/7zip/Archive/Common/ItemNameUtils.h b/CPP/7zip/Archive/Common/ItemNameUtils.h
new file mode 100755
index 00000000..63a01563
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ItemNameUtils.h
@@ -0,0 +1,24 @@
+// Archive/Common/ItemNameUtils.h
+
+#ifndef __ARCHIVE_ITEMNAMEUTILS_H
+#define __ARCHIVE_ITEMNAMEUTILS_H
+
+#include "../../../Common/String.h"
+
+namespace NArchive {
+namespace NItemName {
+
+ UString MakeLegalName(const UString &name);
+ UString GetOSName(const UString &name);
+ UString GetOSName2(const UString &name);
+ bool HasTailSlash(const AString &name, UINT codePage);
+
+ #ifdef _WIN32
+ inline UString WinNameToOSName(const UString &name) { return name; }
+ #else
+ UString WinNameToOSName(const UString &name);
+ #endif
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Common/MultiStream.cpp b/CPP/7zip/Archive/Common/MultiStream.cpp
new file mode 100755
index 00000000..a8cb333e
--- /dev/null
+++ b/CPP/7zip/Archive/Common/MultiStream.cpp
@@ -0,0 +1,201 @@
+// MultiStream.cpp
+
+#include "StdAfx.h"
+
+#include "MultiStream.h"
+
+STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if(processedSize != NULL)
+ *processedSize = 0;
+ while(_streamIndex < Streams.Size() && size > 0)
+ {
+ CSubStreamInfo &s = Streams[_streamIndex];
+ if (_pos == s.Size)
+ {
+ _streamIndex++;
+ _pos = 0;
+ continue;
+ }
+ RINOK(s.Stream->Seek(s.Pos + _pos, STREAM_SEEK_SET, 0));
+ UInt32 sizeToRead = UInt32(MyMin((UInt64)size, s.Size - _pos));
+ UInt32 realProcessed;
+ HRESULT result = s.Stream->Read(data, sizeToRead, &realProcessed);
+ data = (void *)((Byte *)data + realProcessed);
+ size -= realProcessed;
+ if(processedSize != NULL)
+ *processedSize += realProcessed;
+ _pos += realProcessed;
+ _seekPos += realProcessed;
+ RINOK(result);
+ break;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin,
+ UInt64 *newPosition)
+{
+ UInt64 newPos;
+ switch(seekOrigin)
+ {
+ case STREAM_SEEK_SET:
+ newPos = offset;
+ break;
+ case STREAM_SEEK_CUR:
+ newPos = _seekPos + offset;
+ break;
+ case STREAM_SEEK_END:
+ newPos = _totalLength + offset;
+ break;
+ default:
+ return STG_E_INVALIDFUNCTION;
+ }
+ _seekPos = 0;
+ for (_streamIndex = 0; _streamIndex < Streams.Size(); _streamIndex++)
+ {
+ UInt64 size = Streams[_streamIndex].Size;
+ if (newPos < _seekPos + size)
+ {
+ _pos = newPos - _seekPos;
+ _seekPos += _pos;
+ if (newPosition != 0)
+ *newPosition = newPos;
+ return S_OK;
+ }
+ _seekPos += size;
+ }
+ if (newPos == _seekPos)
+ {
+ if (newPosition != 0)
+ *newPosition = newPos;
+ return S_OK;
+ }
+ return E_FAIL;
+}
+
+
+/*
+class COutVolumeStream:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+ int _volIndex;
+ UInt64 _volSize;
+ UInt64 _curPos;
+ CMyComPtr<ISequentialOutStream> _volumeStream;
+ COutArchive _archive;
+ CCRC _crc;
+
+public:
+ MY_UNKNOWN_IMP
+
+ CFileItem _file;
+ CUpdateOptions _options;
+ CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ void Init(IArchiveUpdateCallback2 *volumeCallback,
+ const UString &name)
+ {
+ _file.Name = name;
+ _file.IsStartPosDefined = true;
+ _file.StartPos = 0;
+
+ VolumeCallback = volumeCallback;
+ _volIndex = 0;
+ _volSize = 0;
+ }
+
+ HRESULT Flush();
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+};
+
+HRESULT COutVolumeStream::Flush()
+{
+ if (_volumeStream)
+ {
+ _file.UnPackSize = _curPos;
+ _file.FileCRC = _crc.GetDigest();
+ RINOK(WriteVolumeHeader(_archive, _file, _options));
+ _archive.Close();
+ _volumeStream.Release();
+ _file.StartPos += _file.UnPackSize;
+ }
+ return S_OK;
+}
+*/
+
+/*
+STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ if(processedSize != NULL)
+ *processedSize = 0;
+ while(size > 0)
+ {
+ if (_streamIndex >= Streams.Size())
+ {
+ CSubStreamInfo subStream;
+ RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
+ RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
+ subStream.Pos = 0;
+ Streams.Add(subStream);
+ continue;
+ }
+ CSubStreamInfo &subStream = Streams[_streamIndex];
+ if (_offsetPos >= subStream.Size)
+ {
+ _offsetPos -= subStream.Size;
+ _streamIndex++;
+ continue;
+ }
+ if (_offsetPos != subStream.Pos)
+ {
+ CMyComPtr<IOutStream> outStream;
+ RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
+ RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
+ subStream.Pos = _offsetPos;
+ }
+
+ UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
+ UInt32 realProcessed;
+ RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
+ data = (void *)((Byte *)data + realProcessed);
+ size -= realProcessed;
+ subStream.Pos += realProcessed;
+ _offsetPos += realProcessed;
+ _absPos += realProcessed;
+ if (_absPos > _length)
+ _length = _absPos;
+ if(processedSize != NULL)
+ *processedSize += realProcessed;
+ if (subStream.Pos == subStream.Size)
+ {
+ _streamIndex++;
+ _offsetPos = 0;
+ }
+ if (realProcessed != curSize && realProcessed == 0)
+ return E_FAIL;
+ }
+ return S_OK;
+}
+
+STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
+{
+ if(seekOrigin >= 3)
+ return STG_E_INVALIDFUNCTION;
+ switch(seekOrigin)
+ {
+ case STREAM_SEEK_SET:
+ _absPos = offset;
+ break;
+ case STREAM_SEEK_CUR:
+ _absPos += offset;
+ break;
+ case STREAM_SEEK_END:
+ _absPos = _length + offset;
+ break;
+ }
+ _offsetPos = _absPos;
+ _streamIndex = 0;
+ return S_OK;
+}
+*/
diff --git a/CPP/7zip/Archive/Common/MultiStream.h b/CPP/7zip/Archive/Common/MultiStream.h
new file mode 100755
index 00000000..5a7cc687
--- /dev/null
+++ b/CPP/7zip/Archive/Common/MultiStream.h
@@ -0,0 +1,76 @@
+// MultiStream.h
+
+#ifndef __MULTISTREAM_H
+#define __MULTISTREAM_H
+
+#include "../../../Common/MyCom.h"
+#include "../../../Common/Vector.h"
+#include "../../Archive/IArchive.h"
+
+class CMultiStream:
+ public IInStream,
+ public CMyUnknownImp
+{
+ int _streamIndex;
+ UInt64 _pos;
+ UInt64 _seekPos;
+ UInt64 _totalLength;
+public:
+ struct CSubStreamInfo
+ {
+ CMyComPtr<IInStream> Stream;
+ UInt64 Pos;
+ UInt64 Size;
+ };
+ CObjectVector<CSubStreamInfo> Streams;
+ void Init()
+ {
+ _streamIndex = 0;
+ _pos = 0;
+ _seekPos = 0;
+ _totalLength = 0;
+ for (int i = 0; i < Streams.Size(); i++)
+ _totalLength += Streams[i].Size;
+ }
+
+ MY_UNKNOWN_IMP1(IInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+
+/*
+class COutMultiStream:
+ public IOutStream,
+ public CMyUnknownImp
+{
+ int _streamIndex; // required stream
+ UInt64 _offsetPos; // offset from start of _streamIndex index
+ UInt64 _absPos;
+ UInt64 _length;
+
+ struct CSubStreamInfo
+ {
+ CMyComPtr<ISequentialOutStream> Stream;
+ UInt64 Size;
+ UInt64 Pos;
+ };
+ CObjectVector<CSubStreamInfo> Streams;
+public:
+ CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
+ void Init()
+ {
+ _streamIndex = 0;
+ _offsetPos = 0;
+ _absPos = 0;
+ _length = 0;
+ }
+
+ MY_UNKNOWN_IMP1(IOutStream)
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+ STDMETHOD(Seek)(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition);
+};
+*/
+
+#endif
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
new file mode 100755
index 00000000..7ac3f123
--- /dev/null
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.cpp
@@ -0,0 +1,24 @@
+// OutStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "OutStreamWithCRC.h"
+
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result;
+ if(!_stream)
+ {
+ realProcessedSize = size;
+ result = S_OK;
+ }
+ else
+ result = _stream->Write(data, size, &realProcessedSize);
+ if (_calculateCrc)
+ _crc.Update(data, realProcessedSize);
+ _size += realProcessedSize;
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return result;
+}
diff --git a/CPP/7zip/Archive/Common/OutStreamWithCRC.h b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
new file mode 100755
index 00000000..0feb542b
--- /dev/null
+++ b/CPP/7zip/Archive/Common/OutStreamWithCRC.h
@@ -0,0 +1,37 @@
+// OutStreamWithCRC.h
+
+#ifndef __OUTSTREAMWITHCRC_H
+#define __OUTSTREAMWITHCRC_H
+
+#include "../../../Common/CRC.h"
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+
+class COutStreamWithCRC:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CMyComPtr<ISequentialOutStream> _stream;
+ UInt64 _size;
+ CCRC _crc;
+ bool _calculateCrc;
+public:
+ void SetStream(ISequentialOutStream *stream) { _stream = stream; }
+ void Init(bool calculateCrc = true)
+ {
+ _size = 0;
+ _calculateCrc = calculateCrc;
+ _crc.Init();
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt64 GetSize() const { return _size; }
+ UInt32 GetCRC() const { return _crc.GetDigest(); }
+ void InitCRC() { _crc.Init(); }
+};
+
+#endif
diff --git a/CPP/7zip/Archive/Common/ParseProperties.cpp b/CPP/7zip/Archive/Common/ParseProperties.cpp
new file mode 100755
index 00000000..9866d900
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ParseProperties.cpp
@@ -0,0 +1,171 @@
+// ParseProperties.cpp
+
+#include "StdAfx.h"
+
+#include "ParseProperties.h"
+
+#include "Common/StringToInt.h"
+#include "Common/MyCom.h"
+
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+ if (prop.vt == VT_UI4)
+ {
+ if (!name.IsEmpty())
+ return E_INVALIDARG;
+ resValue = prop.ulVal;
+ }
+ else if (prop.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;
+ resValue = (UInt32)v;
+ }
+ }
+ else
+ return E_INVALIDARG;
+ return S_OK;
+}
+
+static const int kLogarithmicSizeLimit = 32;
+static const wchar_t kByteSymbol = L'B';
+static const wchar_t kKiloByteSymbol = L'K';
+static const wchar_t kMegaByteSymbol = L'M';
+
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
+{
+ UString srcString = srcStringSpec;
+ srcString.MakeUpper();
+
+ const wchar_t *start = srcString;
+ const wchar_t *end;
+ UInt64 number = ConvertStringToUInt64(start, &end);
+ int numDigits = (int)(end - start);
+ if (numDigits == 0 || srcString.Length() > numDigits + 1)
+ return E_INVALIDARG;
+ if (srcString.Length() == numDigits)
+ {
+ if (number >= kLogarithmicSizeLimit)
+ return E_INVALIDARG;
+ dicSize = (UInt32)1 << (int)number;
+ return S_OK;
+ }
+ switch (srcString[numDigits])
+ {
+ case kByteSymbol:
+ if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
+ return E_INVALIDARG;
+ dicSize = (UInt32)number;
+ break;
+ case kKiloByteSymbol:
+ if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
+ return E_INVALIDARG;
+ dicSize = (UInt32)(number << 10);
+ break;
+ case kMegaByteSymbol:
+ if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
+ return E_INVALIDARG;
+ dicSize = (UInt32)(number << 20);
+ break;
+ default:
+ return E_INVALIDARG;
+ }
+ return S_OK;
+}
+
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
+{
+ if (name.IsEmpty())
+ {
+ if (prop.vt == VT_UI4)
+ {
+ UInt32 logDicSize = prop.ulVal;
+ if (logDicSize >= 32)
+ return E_INVALIDARG;
+ resValue = (UInt32)1 << logDicSize;
+ return S_OK;
+ }
+ if (prop.vt == VT_BSTR)
+ return ParsePropDictionaryValue(prop.bstrVal, resValue);
+ return E_INVALIDARG;
+ }
+ return ParsePropDictionaryValue(name, resValue);
+}
+
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
+{
+ switch(value.vt)
+ {
+ case VT_EMPTY:
+ dest = true;
+ break;
+ /*
+ case VT_UI4:
+ dest = (value.ulVal != 0);
+ break;
+ */
+ case VT_BSTR:
+ {
+ UString valueString = value.bstrVal;
+ valueString.MakeUpper();
+ if (valueString.Compare(L"ON") == 0)
+ dest = true;
+ else if (valueString.Compare(L"OFF") == 0)
+ dest = false;
+ else
+ return E_INVALIDARG;
+ break;
+ }
+ default:
+ return E_INVALIDARG;
+ }
+ return S_OK;
+}
+
+int ParseStringToUInt32(const UString &srcString, UInt32 &number)
+{
+ const wchar_t *start = srcString;
+ const wchar_t *end;
+ UInt64 number64 = ConvertStringToUInt64(start, &end);
+ if (number64 > 0xFFFFFFFF)
+ {
+ number = 0;
+ return 0;
+ }
+ number = (UInt32)number64;
+ return (int)(end - start);
+}
+
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
+{
+ if (name.IsEmpty())
+ {
+ switch(prop.vt)
+ {
+ case VT_UI4:
+ numThreads = prop.ulVal;
+ break;
+ default:
+ {
+ bool val;
+ RINOK(SetBoolProperty(val, prop));
+ numThreads = (val ? defaultNumThreads : 1);
+ break;
+ }
+ }
+ }
+ else
+ {
+ UInt32 number;
+ int index = ParseStringToUInt32(name, number);
+ if (index != name.Length())
+ return E_INVALIDARG;
+ numThreads = number;
+ }
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Common/ParseProperties.h b/CPP/7zip/Archive/Common/ParseProperties.h
new file mode 100755
index 00000000..e6db316b
--- /dev/null
+++ b/CPP/7zip/Archive/Common/ParseProperties.h
@@ -0,0 +1,17 @@
+// ParseProperties.h
+
+#ifndef __PARSEPROPERTIES_H
+#define __PARSEPROPERTIES_H
+
+#include "Common/String.h"
+#include "Common/Types.h"
+
+HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize);
+HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
+
+HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value);
+int ParseStringToUInt32(const UString &srcString, UInt32 &number);
+HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads);
+
+#endif
diff --git a/CPP/7zip/Archive/Common/StdAfx.h b/CPP/7zip/Archive/Common/StdAfx.h
new file mode 100755
index 00000000..2e4be10b
--- /dev/null
+++ b/CPP/7zip/Archive/Common/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/Archive/Cpio/CpioHandler.cpp b/CPP/7zip/Archive/Cpio/CpioHandler.cpp
new file mode 100755
index 00000000..601afbd6
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioHandler.cpp
@@ -0,0 +1,289 @@
+// Archive/cpio/Handler.cpp
+
+#include "StdAfx.h"
+
+#include "CpioHandler.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/Time.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common//LimitedStreams.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../Common/ItemNameUtils.h"
+#include "CpioIn.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NCpio {
+
+enum // PropID
+{
+ kpidinode = kpidUserDefined,
+ kpidiChkSum
+};
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ // { NULL, kpidUser, VT_BSTR},
+ // { NULL, kpidGroup, VT_BSTR},
+ // { L"inode", kpidinode, VT_UI4}
+ // { L"CheckSum", kpidiChkSum, VT_UI4}
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ // try
+ {
+ CInArchive archive;
+
+ if(archive.Open(inStream) != S_OK)
+ return S_FALSE;
+
+ m_Items.Clear();
+
+ if (openArchiveCallback != NULL)
+ {
+ RINOK(openArchiveCallback->SetTotal(NULL, NULL));
+ UInt64 numFiles = m_Items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+
+ for (;;)
+ {
+ CItemEx itemInfo;
+ bool filled;
+ HRESULT result = archive.GetNextItem(filled, itemInfo);
+ if (result == S_FALSE)
+ return S_FALSE;
+ if (result != S_OK)
+ return S_FALSE;
+ if (!filled)
+ break;
+ m_Items.Add(itemInfo);
+ archive.SkeepDataRecords(itemInfo.Size, itemInfo.Align);
+ if (openArchiveCallback != NULL)
+ {
+ UInt64 numFiles = m_Items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ if (m_Items.Size() == 0)
+ return S_FALSE;
+
+ m_InStream = inStream;
+ }
+ /*
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ */
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ m_Items.Clear();
+ m_InStream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = m_Items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ const CItemEx &item = m_Items[index];
+
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = (const wchar_t *)NItemName::GetOSName(
+ MultiByteToUnicodeString(item.Name, CP_OEMCP));
+ break;
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ propVariant = item.Size;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME utcFileTime;
+ if (item.ModificationTime != 0)
+ NTime::UnixTimeToFileTime(item.ModificationTime, utcFileTime);
+ else
+ {
+ utcFileTime.dwLowDateTime = 0;
+ utcFileTime.dwHighDateTime = 0;
+ }
+ propVariant = utcFileTime;
+ break;
+ }
+ case kpidinode:
+ propVariant = item.inode;
+ break;
+ /*
+ case kpidiChkSum:
+ propVariant = item.ChkSum;
+ break;
+ */
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = m_Items.Size();
+ if(numItems == 0)
+ return S_OK;
+ bool testMode = (_aTestMode != 0);
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ totalSize += m_Items[allFilesMode ? i : indices[i]].Size;
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+ UInt64 currentItemSize;
+
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ const CItemEx &itemInfo = m_Items[index];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ currentItemSize = itemInfo.Size;
+
+ if(itemInfo.IsDirectory())
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+ if(!testMode && (!realOutStream))
+ {
+ continue;
+ }
+ RINOK(extractCallback->PrepareOperation(askMode));
+ {
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ RINOK(m_InStream->Seek(itemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL));
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(m_InStream);
+ streamSpec->Init(itemInfo.Size);
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress,
+ &currentTotalSize, &currentTotalSize);
+
+ if(copyCoder == NULL)
+ {
+ copyCoder = new NCompress::CCopyCoder;
+ }
+ try
+ {
+ RINOK(copyCoder->Code(inStream, realOutStream,
+ NULL, NULL, compressProgress));
+ }
+ catch(...)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Cpio/CpioHandler.h b/CPP/7zip/Archive/Cpio/CpioHandler.h
new file mode 100755
index 00000000..39702541
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioHandler.h
@@ -0,0 +1,47 @@
+// Archive/cpio/Handler.h
+
+#ifndef __ARCHIVE_CPIO_HANDLER_H
+#define __ARCHIVE_CPIO_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "CpioItem.h"
+
+namespace NArchive {
+namespace NCpio {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+private:
+ CObjectVector<CItemEx> m_Items;
+ CMyComPtr<IInStream> m_InStream;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cpio/CpioHeader.cpp b/CPP/7zip/Archive/Cpio/CpioHeader.cpp
new file mode 100755
index 00000000..9e4d99cb
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioHeader.cpp
@@ -0,0 +1,23 @@
+// Archive/cpio/Header.h
+
+#include "StdAfx.h"
+
+#include "CpioHeader.h"
+
+namespace NArchive {
+namespace NCpio {
+namespace NFileHeader {
+
+ namespace NMagic
+ {
+ extern const char *kMagic1 = "070701";
+ extern const char *kMagic2 = "070702";
+ extern const char *kMagic3 = "070707";
+ extern const char *kEndName = "TRAILER!!!";
+
+ const Byte kMagicForRecord2[2] = { 0xC7, 0x71 };
+ // unsigned short kMagicForRecord2BE = 0xC771;
+ }
+
+}}}
+
diff --git a/CPP/7zip/Archive/Cpio/CpioHeader.h b/CPP/7zip/Archive/Cpio/CpioHeader.h
new file mode 100755
index 00000000..40a0014a
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioHeader.h
@@ -0,0 +1,70 @@
+// Archive/cpio/Header.h
+
+#ifndef __ARCHIVE_CPIO_HEADER_H
+#define __ARCHIVE_CPIO_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NCpio {
+
+namespace NFileHeader
+{
+ namespace NMagic
+ {
+ extern const char *kMagic1;
+ extern const char *kMagic2;
+ extern const char *kMagic3;
+ extern const char *kEndName;
+ extern const Byte kMagicForRecord2[2];
+ }
+
+ const UInt32 kRecord2Size = 26;
+ /*
+ struct CRecord2
+ {
+ unsigned short c_magic;
+ short c_dev;
+ unsigned short c_ino;
+ unsigned short c_mode;
+ unsigned short c_uid;
+ unsigned short c_gid;
+ unsigned short c_nlink;
+ short c_rdev;
+ unsigned short c_mtimes[2];
+ unsigned short c_namesize;
+ unsigned short c_filesizes[2];
+ };
+ */
+
+ const UInt32 kRecordSize = 110;
+ /*
+ struct CRecord
+ {
+ char Magic[6]; // "070701" for "new" portable format, "070702" for CRC format
+ char inode[8];
+ char Mode[8];
+ char UID[8];
+ char GID[8];
+ char nlink[8];
+ char mtime[8];
+ char Size[8]; // must be 0 for FIFOs and directories
+ char DevMajor[8];
+ char DevMinor[8];
+ char RDevMajor[8]; //only valid for chr and blk special files
+ char RDevMinor[8]; //only valid for chr and blk special files
+ char NameSize[8]; // count includes terminating NUL in pathname
+ char ChkSum[8]; // 0 for "new" portable format; for CRC format the sum of all the bytes in the file
+ bool CheckMagic() const
+ { return memcmp(Magic, NMagic::kMagic1, 6) == 0 ||
+ memcmp(Magic, NMagic::kMagic2, 6) == 0; };
+ };
+ */
+
+ const UInt32 kOctRecordSize = 76;
+
+}
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cpio/CpioIn.cpp b/CPP/7zip/Archive/Cpio/CpioIn.cpp
new file mode 100755
index 00000000..91399362
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioIn.cpp
@@ -0,0 +1,271 @@
+// Archive/cpioIn.cpp
+
+#include "StdAfx.h"
+
+#include "CpioIn.h"
+
+#include "Common/StringToInt.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "CpioHeader.h"
+
+namespace NArchive {
+namespace NCpio {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ RINOK(ReadStream(m_Stream, data, size, &processedSize));
+ m_Position += processedSize;
+ return S_OK;
+}
+
+Byte CInArchive::ReadByte()
+{
+ if (_blockPos >= _blockSize)
+ throw "Incorrect cpio archive";
+ return _block[_blockPos++];
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt16(b) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt32(b) << (8 * i));
+ }
+ return value;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+ m_Stream = inStream;
+ return S_OK;
+}
+
+bool CInArchive::ReadNumber(UInt32 &resultValue)
+{
+ resultValue = 0;
+ for (int i = 0; i < 8; i++)
+ {
+ char c = char(ReadByte());
+ int d;
+ if (c >= '0' && c <= '9')
+ d = c - '0';
+ else if (c >= 'A' && c <= 'F')
+ d = 10 + c - 'A';
+ else if (c >= 'a' && c <= 'f')
+ d = 10 + c - 'a';
+ else
+ return false;
+ resultValue *= 0x10;
+ resultValue += d;
+ }
+ return true;
+}
+
+static bool OctalToNumber(const char *s, UInt64 &res)
+{
+ const char *end;
+ res = ConvertOctStringToUInt64(s, &end);
+ return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *s, UInt32 &res)
+{
+ UInt64 res64;
+ if (!OctalToNumber(s, res64))
+ return false;
+ res = (UInt32)res64;
+ return (res64 <= 0xFFFFFFFF);
+}
+
+bool CInArchive::ReadOctNumber(int size, UInt32 &resultValue)
+{
+ char sz[32 + 4];
+ int i;
+ for (i = 0; i < size && i < 32; i++)
+ sz[i] = (char)ReadByte();
+ sz[i] = 0;
+ return OctalToNumber32(sz, resultValue);
+}
+
+#define GetFromHex(y) { if (!ReadNumber(y)) return S_FALSE; }
+#define GetFromOct6(y) { if (!ReadOctNumber(6, y)) return S_FALSE; }
+#define GetFromOct11(y) { if (!ReadOctNumber(11, y)) return S_FALSE; }
+
+static unsigned short ConvertValue(unsigned short value, bool convert)
+{
+ if (!convert)
+ return value;
+ return (unsigned short)((((unsigned short)(value & 0xFF)) << 8) | (value >> 8));
+}
+
+static UInt32 GetAlignedSize(UInt32 size, UInt32 align)
+{
+ while ((size & (align - 1)) != 0)
+ size++;
+ return size;
+}
+
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+ filled = false;
+
+ UInt32 processedSize;
+ item.HeaderPosition = m_Position;
+
+ _blockSize = kMaxBlockSize;
+ RINOK(ReadBytes(_block, 2, processedSize));
+ if (processedSize != 2)
+ return S_FALSE;
+ _blockPos = 0;
+
+ UInt32 nameSize;
+
+ bool oldBE =
+ _block[0] == NFileHeader::NMagic::kMagicForRecord2[1] &&
+ _block[1] == NFileHeader::NMagic::kMagicForRecord2[0];
+
+ bool binMode = (_block[0] == NFileHeader::NMagic::kMagicForRecord2[0] &&
+ _block[1] == NFileHeader::NMagic::kMagicForRecord2[1]) ||
+ oldBE;
+
+ if (binMode)
+ {
+ RINOK(ReadBytes(_block + 2, NFileHeader::kRecord2Size - 2, processedSize));
+ if (processedSize != NFileHeader::kRecord2Size - 2)
+ return S_FALSE;
+ item.Align = 2;
+ _blockPos = 2;
+ item.DevMajor = 0;
+ item.DevMinor = ConvertValue(ReadUInt16(), oldBE);
+ item.inode = ConvertValue(ReadUInt16(), oldBE);
+ item.Mode = ConvertValue(ReadUInt16(), oldBE);
+ item.UID = ConvertValue(ReadUInt16(), oldBE);
+ item.GID = ConvertValue(ReadUInt16(), oldBE);
+ item.NumLinks = ConvertValue(ReadUInt16(), oldBE);
+ item.RDevMajor =0;
+ item.RDevMinor = ConvertValue(ReadUInt16(), oldBE);
+ UInt16 timeHigh = ConvertValue(ReadUInt16(), oldBE);
+ UInt16 timeLow = ConvertValue(ReadUInt16(), oldBE);
+ item.ModificationTime = (UInt32(timeHigh) << 16) + timeLow;
+ nameSize = ConvertValue(ReadUInt16(), oldBE);
+ UInt16 sizeHigh = ConvertValue(ReadUInt16(), oldBE);
+ UInt16 sizeLow = ConvertValue(ReadUInt16(), oldBE);
+ item.Size = (UInt32(sizeHigh) << 16) + sizeLow;
+
+ item.ChkSum = 0;
+ item.HeaderSize = GetAlignedSize(
+ nameSize + NFileHeader::kRecord2Size, item.Align);
+ nameSize = item.HeaderSize - NFileHeader::kRecord2Size;
+ }
+ else
+ {
+ RINOK(ReadBytes(_block + 2, 4, processedSize));
+ if (processedSize != 4)
+ return S_FALSE;
+
+ bool magicOK =
+ memcmp(_block, NFileHeader::NMagic::kMagic1, 6) == 0 ||
+ memcmp(_block, NFileHeader::NMagic::kMagic2, 6) == 0;
+ _blockPos = 6;
+ if (magicOK)
+ {
+ RINOK(ReadBytes(_block + 6, NFileHeader::kRecordSize - 6, processedSize));
+ if (processedSize != NFileHeader::kRecordSize - 6)
+ return S_FALSE;
+ item.Align = 4;
+
+ GetFromHex(item.inode);
+ GetFromHex(item.Mode);
+ GetFromHex(item.UID);
+ GetFromHex(item.GID);
+ GetFromHex(item.NumLinks);
+ UInt32 modificationTime;
+ GetFromHex(modificationTime);
+ item.ModificationTime = modificationTime;
+ GetFromHex(item.Size);
+ GetFromHex(item.DevMajor);
+ GetFromHex(item.DevMinor);
+ GetFromHex(item.RDevMajor);
+ GetFromHex(item.RDevMinor);
+ GetFromHex(nameSize);
+ GetFromHex(item.ChkSum);
+ item.HeaderSize = GetAlignedSize(
+ nameSize + NFileHeader::kRecordSize, item.Align);
+ nameSize = item.HeaderSize - NFileHeader::kRecordSize;
+ }
+ else
+ {
+ if (!memcmp(_block, NFileHeader::NMagic::kMagic3, 6) == 0)
+ return S_FALSE;
+ RINOK(ReadBytes(_block + 6, NFileHeader::kOctRecordSize - 6, processedSize));
+ if (processedSize != NFileHeader::kOctRecordSize - 6)
+ return S_FALSE;
+ item.Align = 1;
+ item.DevMajor = 0;
+ GetFromOct6(item.DevMinor);
+ GetFromOct6(item.inode);
+ GetFromOct6(item.Mode);
+ GetFromOct6(item.UID);
+ GetFromOct6(item.GID);
+ GetFromOct6(item.NumLinks);
+ item.RDevMajor = 0;
+ GetFromOct6(item.RDevMinor);
+ UInt32 modificationTime;
+ GetFromOct11(modificationTime);
+ item.ModificationTime = modificationTime;
+ GetFromOct6(nameSize);
+ GetFromOct11(item.Size); // ?????
+ item.HeaderSize = GetAlignedSize(
+ nameSize + NFileHeader::kOctRecordSize, item.Align);
+ nameSize = item.HeaderSize - NFileHeader::kOctRecordSize;
+ }
+ }
+ if (nameSize == 0 || nameSize >= (1 << 27))
+ return E_FAIL;
+ RINOK(ReadBytes(item.Name.GetBuffer(nameSize),
+ nameSize, processedSize));
+ if (processedSize != nameSize)
+ return E_FAIL;
+ item.Name.ReleaseBuffer();
+ if (strcmp(item.Name, NFileHeader::NMagic::kEndName) == 0)
+ return S_OK;
+ filled = true;
+ return S_OK;
+}
+
+HRESULT CInArchive::Skeep(UInt64 numBytes)
+{
+ UInt64 newPostion;
+ RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+ m_Position += numBytes;
+ if (m_Position != newPostion)
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT CInArchive::SkeepDataRecords(UInt64 dataSize, UInt32 align)
+{
+ while ((dataSize & (align - 1)) != 0)
+ dataSize++;
+ return Skeep(dataSize);
+}
+
+}}
diff --git a/CPP/7zip/Archive/Cpio/CpioIn.h b/CPP/7zip/Archive/Cpio/CpioIn.h
new file mode 100755
index 00000000..19e3da10
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioIn.h
@@ -0,0 +1,41 @@
+// CpioIn.h
+
+#ifndef __ARCHIVE_CPIO_IN_H
+#define __ARCHIVE_CPIO_IN_H
+
+#include "Common/MyCom.h"
+#include "Common/Types.h"
+#include "../../IStream.h"
+#include "CpioItem.h"
+
+namespace NArchive {
+namespace NCpio {
+
+const UInt32 kMaxBlockSize = NFileHeader::kRecordSize;
+
+class CInArchive
+{
+ CMyComPtr<IInStream> m_Stream;
+ UInt64 m_Position;
+
+ UInt16 _blockSize;
+ Byte _block[kMaxBlockSize];
+ UInt32 _blockPos;
+ Byte ReadByte();
+ UInt16 ReadUInt16();
+ UInt32 ReadUInt32();
+
+ bool ReadNumber(UInt32 &resultValue);
+ bool ReadOctNumber(int size, UInt32 &resultValue);
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+public:
+ HRESULT Open(IInStream *inStream);
+ HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
+ HRESULT Skeep(UInt64 numBytes);
+ HRESULT SkeepDataRecords(UInt64 dataSize, UInt32 align);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cpio/CpioItem.h b/CPP/7zip/Archive/Cpio/CpioItem.h
new file mode 100755
index 00000000..0eb2a0b4
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/CpioItem.h
@@ -0,0 +1,55 @@
+// Archive/cpio/ItemInfo.h
+
+#ifndef __ARCHIVE_CPIO_ITEMINFO_H
+#define __ARCHIVE_CPIO_ITEMINFO_H
+
+#include <sys/stat.h>
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "CpioHeader.h"
+
+namespace NArchive {
+namespace NCpio {
+
+struct CItem
+{
+ AString Name;
+ UInt32 inode;
+ UInt32 Mode;
+ UInt32 UID;
+ UInt32 GID;
+ UInt32 Size;
+ UInt32 ModificationTime;
+
+ // char LinkFlag;
+ // AString LinkName; ?????
+ char Magic[8];
+ UInt32 NumLinks;
+ UInt32 DevMajor;
+ UInt32 DevMinor;
+ UInt32 RDevMajor;
+ UInt32 RDevMinor;
+ UInt32 ChkSum;
+
+ UInt32 Align;
+
+ bool IsDirectory() const
+#ifdef _WIN32
+ { return (Mode & _S_IFMT) == _S_IFDIR; }
+#else
+ { return (Mode & S_IFMT) == S_IFDIR; }
+#endif
+};
+
+class CItemEx: public CItem
+{
+public:
+ UInt64 HeaderPosition;
+ UInt32 HeaderSize;
+ UInt64 GetDataPosition() const { return HeaderPosition + HeaderSize; };
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Cpio/DllExports.cpp b/CPP/7zip/Archive/Cpio/DllExports.cpp
new file mode 100755
index 00000000..8eb38bfd
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/DllExports.cpp
@@ -0,0 +1,65 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "CpioHandler.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278A-1000-000110ED0000}
+DEFINE_GUID(CLSID_CCpioHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xED, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CCpioHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NCpio::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Cpio";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CCpioHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"cpio";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Cpio/StdAfx.cpp b/CPP/7zip/Archive/Cpio/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Cpio/StdAfx.h b/CPP/7zip/Archive/Cpio/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/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/Cpio/cpio.dsp b/CPP/7zip/Archive/Cpio/cpio.dsp
new file mode 100755
index 00000000..f30c3e63
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/cpio.dsp
@@ -0,0 +1,265 @@
+# Microsoft Developer Studio Project File - Name="cpio" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=cpio - 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 "cpio.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 "cpio.mak" CFG="cpio - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "cpio - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "cpio - 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)" == "cpio - 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 "CPIO_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CPIO_EXPORTS" /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 0x419 /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\cpio.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "cpio - 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 "CPIO_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CPIO_EXPORTS" /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 0x419 /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\cpio.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "cpio - Win32 Release"
+# Name "cpio - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Archive.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\cpio.ico
+# 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"StdAfx.h"
+# 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\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# 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 "Compress"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\CpioHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CpioHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CpioHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CpioHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CpioIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\CpioIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\CpioItem.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.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\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.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
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Cpio/cpio.dsw b/CPP/7zip/Archive/Cpio/cpio.dsw
new file mode 100755
index 00000000..b1b6d98f
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/cpio.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "cpio"=.\cpio.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Cpio/cpio.ico b/CPP/7zip/Archive/Cpio/cpio.ico
new file mode 100755
index 00000000..9abaabc7
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/cpio.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Cpio/makefile b/CPP/7zip/Archive/Cpio/makefile
new file mode 100755
index 00000000..d7760281
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/makefile
@@ -0,0 +1,55 @@
+PROG = cpio.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+CPIO_OBJS = \
+ $O\DllExports.obj \
+ $O\CpioHandler.obj \
+ $O\CpioHeader.obj \
+ $O\CpioIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\LimitedStreams.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(CPIO_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_CPIO_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(CPIO_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Cpio/resource.rc b/CPP/7zip/Archive/Cpio/resource.rc
new file mode 100755
index 00000000..d5456e5a
--- /dev/null
+++ b/CPP/7zip/Archive/Cpio/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Cpio Plugin", "cpio")
+
+101 ICON "cpio.ico"
diff --git a/CPP/7zip/Archive/Deb/Deb.dsp b/CPP/7zip/Archive/Deb/Deb.dsp
new file mode 100755
index 00000000..56689305
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/Deb.dsp
@@ -0,0 +1,269 @@
+# Microsoft Developer Studio Project File - Name="Deb" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Deb - 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 "Deb.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 "Deb.mak" CFG="Deb - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Deb - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Deb - 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)" == "Deb - 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 "DEB_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEB_EXPORTS" /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 0x419 /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\deb.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Deb - 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 "DEB_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "DEB_EXPORTS" /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 0x419 /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\deb.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Deb - Win32 Release"
+# Name "Deb - Win32 Debug"
+# Begin Group "Spec"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Archive.def
+# End Source File
+# Begin Source File
+
+SOURCE=.\Deb.ico
+# 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"StdAfx.h"
+# 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\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\DebHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DebHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DebHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DebHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DebIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\DebIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\DebItem.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.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\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.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
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Deb/Deb.dsw b/CPP/7zip/Archive/Deb/Deb.dsw
new file mode 100755
index 00000000..c7169534
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/Deb.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Deb"=.\Deb.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Deb/DebHandler.cpp b/CPP/7zip/Archive/Deb/DebHandler.cpp
new file mode 100755
index 00000000..8728cec8
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebHandler.cpp
@@ -0,0 +1,255 @@
+// DebHandler.cpp
+
+#include "StdAfx.h"
+
+#include "DebHandler.h"
+#include "DebIn.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/Time.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NDeb {
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ // { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME}
+};
+
+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_INVALIDARG;
+}
+
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ {
+ CInArchive archive;
+ if(archive.Open(stream) != S_OK)
+ return S_FALSE;
+ _items.Clear();
+
+ if (openArchiveCallback != NULL)
+ {
+ RINOK(openArchiveCallback->SetTotal(NULL, NULL));
+ UInt64 numFiles = _items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+
+ for (;;)
+ {
+ CItemEx itemInfo;
+ bool filled;
+ HRESULT result = archive.GetNextItem(filled, itemInfo);
+ if (result == S_FALSE)
+ return S_FALSE;
+ if (result != S_OK)
+ return S_FALSE;
+ if (!filled)
+ break;
+ _items.Add(itemInfo);
+ archive.SkeepData(itemInfo.Size);
+ if (openArchiveCallback != NULL)
+ {
+ UInt64 numFiles = _items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ _inStream = stream;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _inStream.Release();
+ _items.Clear();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ const CItemEx &item = _items[index];
+
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = (const wchar_t *)NItemName::GetOSName2(
+ MultiByteToUnicodeString(item.Name, CP_OEMCP));
+ break;
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ propVariant = item.Size;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME utcFileTime;
+ if (item.ModificationTime != 0)
+ NTime::UnixTimeToFileTime(item.ModificationTime, utcFileTime);
+ else
+ {
+ utcFileTime.dwLowDateTime = 0;
+ utcFileTime.dwHighDateTime = 0;
+ }
+ propVariant = utcFileTime;
+ break;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = _items.Size();
+ if(numItems == 0)
+ return S_OK;
+ bool testMode = (_aTestMode != 0);
+ UInt64 totalSize = 0;
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ totalSize += _items[allFilesMode ? i : indices[i]].Size;
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+ UInt64 currentItemSize;
+
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ const CItemEx &itemInfo = _items[index];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ currentItemSize = itemInfo.Size;
+
+ if(!testMode && (!realOutStream))
+ {
+ continue;
+ }
+ RINOK(extractCallback->PrepareOperation(askMode));
+ {
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ RINOK(_inStream->Seek(itemInfo.GetDataPosition(), STREAM_SEEK_SET, NULL));
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_inStream);
+ streamSpec->Init(itemInfo.Size);
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress,
+ &currentTotalSize, &currentTotalSize);
+
+ if(copyCoder == NULL)
+ {
+ copyCoder = new NCompress::CCopyCoder;
+ }
+ try
+ {
+ RINOK(copyCoder->Code(inStream, realOutStream,
+ NULL, NULL, compressProgress));
+ }
+ catch(...)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Deb/DebHandler.h b/CPP/7zip/Archive/Deb/DebHandler.h
new file mode 100755
index 00000000..47de0224
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebHandler.h
@@ -0,0 +1,47 @@
+// DebHandler.h
+
+#ifndef __DEB_HANDLER_H
+#define __DEB_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "DebItem.h"
+
+namespace NArchive {
+namespace NDeb {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+private:
+ CObjectVector<CItemEx> _items;
+ CMyComPtr<IInStream> _inStream;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Deb/DebHeader.cpp b/CPP/7zip/Archive/Deb/DebHeader.cpp
new file mode 100755
index 00000000..dce00e1b
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebHeader.cpp
@@ -0,0 +1,13 @@
+// Archive/Deb/Header.h
+
+#include "StdAfx.h"
+
+#include "DebHeader.h"
+
+namespace NArchive {
+namespace NDeb {
+namespace NHeader {
+
+const char *kSignature = "!<arch>\n";
+
+}}}
diff --git a/CPP/7zip/Archive/Deb/DebHeader.h b/CPP/7zip/Archive/Deb/DebHeader.h
new file mode 100755
index 00000000..c2884000
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebHeader.h
@@ -0,0 +1,38 @@
+// Archive/Deb/Header.h
+
+#ifndef __ARCHIVE_DEB_HEADER_H
+#define __ARCHIVE_DEB_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NDeb {
+
+namespace NHeader
+{
+ const int kSignatureLen = 8;
+ extern const char *kSignature;
+ const int kNameSize = 16;
+ const int kTimeSize = 12;
+ const int kModeSize = 8;
+ const int kSizeSize = 10;
+
+ /*
+ struct CHeader
+ {
+ char Name[kNameSize];
+ char ModificationTime[kTimeSize];
+ char Number0[6];
+ char Number1[6];
+ char Mode[kModeSize];
+ char Size[kSizeSize];
+ char Quote;
+ char NewLine;
+ };
+ */
+ const int kHeaderSize = kNameSize + kTimeSize + 6 + 6 + kModeSize + kSizeSize + 1 + 1;
+}
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Deb/DebIn.cpp b/CPP/7zip/Archive/Deb/DebIn.cpp
new file mode 100755
index 00000000..c2221d12
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebIn.cpp
@@ -0,0 +1,165 @@
+// Archive/DebIn.cpp
+
+#include "StdAfx.h"
+
+#include "DebIn.h"
+#include "DebHeader.h"
+
+#include "Common/StringToInt.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NDeb {
+
+using namespace NHeader;
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ RINOK(ReadStream(m_Stream, data, size, &processedSize));
+ m_Position += processedSize;
+ return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+ char signature[kSignatureLen];
+ UInt32 processedSize;
+ RINOK(ReadStream(inStream, signature, kSignatureLen, &processedSize));
+ m_Position += processedSize;
+ if (processedSize != kSignatureLen)
+ return S_FALSE;
+ if (memcmp(signature, kSignature, kSignatureLen) != 0)
+ return S_FALSE;
+ m_Stream = inStream;
+ 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;
+ }
+}
+
+static bool OctalToNumber(const char *s, int size, UInt64 &res)
+{
+ char sz[32];
+ MyStrNCpy(sz, s, size);
+ sz[size] = 0;
+ const char *end;
+ int i;
+ for (i = 0; sz[i] == ' '; i++);
+ res = ConvertOctStringToUInt64(sz + i, &end);
+ return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *s, int size, UInt32 &res)
+{
+ UInt64 res64;
+ if (!OctalToNumber(s, size, res64))
+ return false;
+ res = (UInt32)res64;
+ return (res64 <= 0xFFFFFFFF);
+}
+
+static bool DecimalToNumber(const char *s, int size, UInt64 &res)
+{
+ char sz[32];
+ MyStrNCpy(sz, s, size);
+ sz[size] = 0;
+ const char *end;
+ int i;
+ for (i = 0; sz[i] == ' '; i++);
+ res = ConvertStringToUInt64(sz + i, &end);
+ return (*end == ' ' || *end == 0);
+}
+
+static bool DecimalToNumber32(const char *s, int size, UInt32 &res)
+{
+ UInt64 res64;
+ if (!DecimalToNumber(s, size, res64))
+ return false;
+ res = (UInt32)res64;
+ return (res64 <= 0xFFFFFFFF);
+}
+
+#define RIF(x) { if (!(x)) return S_FALSE; }
+
+
+HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
+{
+ filled = false;
+
+ char header[NHeader::kHeaderSize];
+ const char *cur = header;
+
+ UInt32 processedSize;
+ item.HeaderPosition = m_Position;
+ RINOK(ReadBytes(header, sizeof(header), processedSize));
+ if (processedSize < sizeof(header))
+ return S_OK;
+
+ char tempString[kNameSize + 1];
+ MyStrNCpy(tempString, cur, kNameSize);
+ cur += kNameSize;
+ tempString[kNameSize] = '\0';
+ item.Name = tempString;
+ item.Name.Trim();
+
+ for (int i = 0; i < item.Name.Length(); i++)
+ if (((Byte)item.Name[i]) < 0x20)
+ return S_FALSE;
+
+ RIF(DecimalToNumber32(cur, kTimeSize, item.ModificationTime));
+ cur += kTimeSize;
+
+ cur += 6 + 6;
+
+ RIF(OctalToNumber32(cur, kModeSize, item.Mode));
+ cur += kModeSize;
+
+ RIF(DecimalToNumber(cur, kSizeSize, item.Size));
+ cur += kSizeSize;
+
+ filled = true;
+ return S_OK;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+ for (;;)
+ {
+ RINOK(GetNextItemReal(filled, item));
+ if (!filled)
+ return S_OK;
+ if (item.Name.CompareNoCase("debian-binary") != 0)
+ return S_OK;
+ if (item.Size != 4)
+ return S_OK;
+ SkeepData(item.Size);
+ }
+}
+
+HRESULT CInArchive::Skeep(UInt64 numBytes)
+{
+ UInt64 newPostion;
+ RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+ m_Position += numBytes;
+ if (m_Position != newPostion)
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT CInArchive::SkeepData(UInt64 dataSize)
+{
+ return Skeep((dataSize + 1) & (~((UInt64)0x1)));
+}
+
+}}
diff --git a/CPP/7zip/Archive/Deb/DebIn.h b/CPP/7zip/Archive/Deb/DebIn.h
new file mode 100755
index 00000000..c1b72b6e
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebIn.h
@@ -0,0 +1,29 @@
+// Archive/DebIn.h
+
+#ifndef __ARCHIVE_DEB_IN_H
+#define __ARCHIVE_DEB_IN_H
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+#include "DebItem.h"
+
+namespace NArchive {
+namespace NDeb {
+
+class CInArchive
+{
+ CMyComPtr<IInStream> m_Stream;
+ UInt64 m_Position;
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+ HRESULT GetNextItemReal(bool &filled, CItemEx &itemInfo);
+ HRESULT Skeep(UInt64 numBytes);
+public:
+ HRESULT Open(IInStream *inStream);
+ HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
+ HRESULT SkeepData(UInt64 dataSize);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Deb/DebItem.h b/CPP/7zip/Archive/Deb/DebItem.h
new file mode 100755
index 00000000..f587f3f5
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DebItem.h
@@ -0,0 +1,32 @@
+// Archive/Deb/ItemInfo.h
+
+#ifndef __ARCHIVE_DEB_ITEMINFO_H
+#define __ARCHIVE_DEB_ITEMINFO_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "DebHeader.h"
+
+namespace NArchive {
+namespace NDeb {
+
+class CItem
+{
+public:
+ AString Name;
+ UInt64 Size;
+ UInt32 ModificationTime;
+ UInt32 Mode;
+};
+
+class CItemEx: public CItem
+{
+public:
+ UInt64 HeaderPosition;
+ UInt64 GetDataPosition() const { return HeaderPosition + NHeader::kHeaderSize; };
+ // UInt64 GetFullSize() const { return NFileHeader::kRecordSize + Size; };
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Deb/DllExports.cpp b/CPP/7zip/Archive/Deb/DllExports.cpp
new file mode 100755
index 00000000..fe320531
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/DllExports.cpp
@@ -0,0 +1,73 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "DebHandler.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278A-1000-000110EC0000}
+DEFINE_GUID(CLSID_CDebHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEC, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /*lpReserved*/)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CDebHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NDeb::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Deb";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CDebHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"deb";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)NArchive::NDeb::NHeader::kSignature,
+ NArchive::NDeb::NHeader::kSignatureLen)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Deb/StdAfx.cpp b/CPP/7zip/Archive/Deb/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Deb/StdAfx.h b/CPP/7zip/Archive/Deb/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/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/Deb/deb.ico b/CPP/7zip/Archive/Deb/deb.ico
new file mode 100755
index 00000000..97a08654
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/deb.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Deb/makefile b/CPP/7zip/Archive/Deb/makefile
new file mode 100755
index 00000000..a74f33de
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/makefile
@@ -0,0 +1,54 @@
+PROG = deb.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+DEB_OBJS = \
+ $O\DllExports.obj \
+ $O\DebHandler.obj \
+ $O\DebHeader.obj \
+ $O\DebIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\LimitedStreams.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(DEB_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(DEB_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Deb/resource.rc b/CPP/7zip/Archive/Deb/resource.rc
new file mode 100755
index 00000000..a80edced
--- /dev/null
+++ b/CPP/7zip/Archive/Deb/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Deb Plugin", "deb")
+
+101 ICON "deb.ico"
diff --git a/CPP/7zip/Archive/GZip/DllExports.cpp b/CPP/7zip/Archive/GZip/DllExports.cpp
new file mode 100755
index 00000000..3bddcfb9
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/DllExports.cpp
@@ -0,0 +1,125 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "GZipHandler.h"
+
+// {23170F69-40C1-278A-1000-000110EF0000}
+DEFINE_GUID(CLSID_CGZipHandler,
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEF, 0x00, 0x00);
+
+// {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);
+
+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
+
+#ifndef COMPRESS_DEFLATE
+#include "../Common/CodecsPath.h"
+CSysString GetDeflateCodecPath()
+{
+ return GetCodecsFolderPrefix() + TEXT("Deflate.dll");
+}
+#endif
+
+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_CGZipHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ int needOut = *interfaceID == IID_IOutArchive;
+ if (needIn || needOut)
+ {
+ NArchive::NGZip::CHandler *temp = new NArchive::NGZip::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"GZip";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CGZipHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"gz gzip tgz tpz";
+ break;
+ case NArchive::kAddExtension:
+ propVariant = L"* * .tar .tar";
+ break;
+ case NArchive::kUpdate:
+ propVariant = true;
+ break;
+ case NArchive::kKeepName:
+ propVariant = true;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const unsigned char sig[] = { 0x1F, 0x8B };
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 2)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/GZip/GZip.dsp b/CPP/7zip/Archive/GZip/GZip.dsp
new file mode 100755
index 00000000..3af06b46
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZip.dsp
@@ -0,0 +1,321 @@
+# Microsoft Developer Studio Project File - Name="GZip" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=GZip - 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 "GZip.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 "GZip.mak" CFG="GZip - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "GZip - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "GZip - 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)" == "GZip - 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 "GZIP_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GZIP_EXPORTS" /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 0x419 /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\gz.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "GZip - 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 "GZIP_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "GZIP_EXPORTS" /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 0x419 /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\gz.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "GZip - Win32 Release"
+# Name "GZip - 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=.\GZip.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# 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\CRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\CRC.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\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
+# 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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compression"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\GZipHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipHandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipUpdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\GZipUpdate.h
+# End Source File
+# End Group
+# Begin Group "7zip Common"
+
+# PROP Default_Filter ""
+# 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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.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\InStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\InStreamWithCRC.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 Source File
+
+SOURCE=.\gz.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/GZip/GZip.dsw b/CPP/7zip/Archive/GZip/GZip.dsw
new file mode 100755
index 00000000..5ff50d2c
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZip.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "GZip"=.\GZip.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/GZip/GZipHandler.cpp b/CPP/7zip/Archive/GZip/GZipHandler.cpp
new file mode 100755
index 00000000..ff592324
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipHandler.cpp
@@ -0,0 +1,361 @@
+// GZipHandler.cpp
+
+#include "StdAfx.h"
+
+#include "GZipHandler.h"
+
+#include "Common/Defs.h"
+#include "Common/CRC.h"
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../ICoder.h"
+#include "../../Common/ProgressUtils.h"
+#include "../Common/OutStreamWithCRC.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);
+#include "../Common/CoderLoader.h"
+extern CSysString GetDeflateCodecPath();
+#endif
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NGZip {
+
+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
+{
+ kpidExtraIsPresent = kpidUserDefined,
+ kpidExtraFlags,
+ kpidIsText
+};
+*/
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ // { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ // { NULL, kpidCommented, VT_BOOL},
+ // { NULL, kpidMethod, VT_UI1},
+ { NULL, kpidHostOS, VT_BSTR},
+
+ { NULL, kpidCRC, VT_UI4}
+ // { L"Extra", kpidExtraIsPresent, VT_BOOL}
+ // { L"Extra flags", kpidExtraFlags, VT_UI1},
+ // { L"Is Text", kpidIsText, VT_BOOL},
+};
+
+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)
+{
+ const STATPROPSTG &prop = kProperties[index];
+ *propID = prop.propid;
+ *varType = prop.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 = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case kpidPath:
+ if (m_Item.NameIsPresent())
+ propVariant = MultiByteToUnicodeString(m_Item.Name, CP_ACP);
+ break;
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME utcTime;
+ if (m_Item.Time != 0)
+ {
+ NTime::UnixTimeToFileTime((UInt32)m_Item.Time, utcTime);
+ propVariant = utcTime;
+ }
+ else
+ {
+ // utcTime.dwLowDateTime = utcTime.dwHighDateTime = 0;
+ // propVariant = utcTime;
+ }
+ break;
+ }
+ case kpidSize:
+ propVariant = UInt64(m_Item.UnPackSize32);
+ break;
+ case kpidPackedSize:
+ propVariant = m_PackSize;
+ break;
+ case kpidCommented:
+ propVariant = m_Item.CommentIsPresent();
+ break;
+ case kpidHostOS:
+ propVariant = (m_Item.HostOS < kNumHostOSes) ?
+ kHostOS[m_Item.HostOS] : kUnknownOS;
+ break;
+ case kpidMethod:
+ propVariant = m_Item.CompressionMethod;
+ break;
+ case kpidCRC:
+ propVariant = m_Item.FileCRC;
+ break;
+ /*
+ case kpidExtraFlags:
+ propVariant = m_Item.ExtraFlags;
+ break;
+ case kpidIsText:
+ propVariant = m_Item.IsText();
+ break;
+ case kpidExtraIsPresent:
+ propVariant = m_Item.ExtraFieldIsPresent();
+ break;
+ */
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ try
+ {
+ CInArchive archive;
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition));
+ RINOK(archive.ReadHeader(inStream, m_Item));
+ m_DataOffset = archive.GetOffset();
+ UInt64 newPosition;
+ RINOK(inStream->Seek(-8, STREAM_SEEK_END, &newPosition));
+ m_PackSize = newPosition - (m_StreamStartPosition + m_DataOffset);
+ if (archive.ReadPostHeader(inStream, m_Item) != S_OK)
+ return S_FALSE;
+ m_Stream = inStream;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ m_Stream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (!allFilesMode)
+ {
+ if (numItems == 0)
+ return S_OK;
+ if (numItems != 1)
+ return E_INVALIDARG;
+ if (indices[0] != 0)
+ return E_INVALIDARG;
+ }
+
+ bool testMode = (_aTestMode != 0);
+
+ extractCallback->SetTotal(m_PackSize);
+
+ UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
+
+ RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+
+ RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+
+ if(!testMode && !realOutStream)
+ return S_OK;
+
+ extractCallback->PrepareOperation(askMode);
+
+ COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->SetStream(realOutStream);
+ outStreamSpec->Init();
+ realOutStream.Release();
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, true);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+
+ #ifndef COMPRESS_DEFLATE
+ CCoderLibrary lib;
+ #endif
+ CMyComPtr<ICompressCoder> deflateDecoder;
+ bool firstItem = true;
+ RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL));
+ for (;;)
+ {
+ localCompressProgressSpec->Init(progress,
+ &currentTotalPacked,
+ &currentTotalUnPacked);
+
+ CInArchive archive;
+ CItem item;
+ HRESULT result = archive.ReadHeader(m_Stream, item);
+ if (result != S_OK)
+ {
+ if (firstItem)
+ return E_FAIL;
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
+ return S_OK;
+ }
+ firstItem = false;
+
+ UInt64 dataStartPos;
+ RINOK(m_Stream->Seek(0, STREAM_SEEK_CUR, &dataStartPos));
+
+ outStreamSpec->InitCRC();
+
+ switch(item.CompressionMethod)
+ {
+ case NFileHeader::NCompressionMethod::kDeflate:
+ {
+ if(!deflateDecoder)
+ {
+ #ifdef COMPRESS_DEFLATE
+ deflateDecoder = new NCompress::NDeflate::NDecoder::CCOMCoder;
+ #else
+ RINOK(lib.LoadAndCreateCoder(GetDeflateCodecPath(),
+ CLSID_CCompressDeflateDecoder, &deflateDecoder));
+ #endif
+ }
+ try
+ {
+ HRESULT result = deflateDecoder->Code(m_Stream, outStream, NULL, NULL, compressProgress);
+ if (result == S_FALSE)
+ throw "data error";
+ if (result != S_OK)
+ return result;
+ }
+ catch(...)
+ {
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kDataError));
+ return S_OK;
+ }
+ break;
+ }
+ default:
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(
+ NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ return S_OK;
+ }
+ CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize;
+ RINOK(deflateDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize,
+ &getInStreamProcessedSize));
+ UInt64 packSize;
+ RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize));
+ UInt64 pos;
+ RINOK(m_Stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos));
+
+ currentTotalPacked = pos - m_StreamStartPosition;
+
+ CItem postItem;
+ if (archive.ReadPostHeader(m_Stream, postItem) != S_OK)
+ return E_FAIL;
+ if((outStreamSpec->GetCRC() != postItem.FileCRC))
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kCRCError))
+ break;
+ }
+ }
+ COM_TRY_END
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/GZip/GZipHandler.h b/CPP/7zip/Archive/GZip/GZipHandler.h
new file mode 100755
index 00000000..9af7e4a4
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipHandler.h
@@ -0,0 +1,79 @@
+// GZip/Handler.h
+
+#ifndef __GZIP_HANDLER_H
+#define __GZIP_HANDLER_H
+
+#include "Common/MyCom.h"
+
+#include "../IArchive.h"
+
+#include "GZipIn.h"
+#include "GZipUpdate.h"
+
+namespace NArchive {
+namespace NGZip {
+
+class CHandler:
+ public IInArchive,
+ public IOutArchive,
+ public ISetProperties,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP3(
+ IInArchive,
+ IOutArchive,
+ ISetProperties)
+
+ STDMETHOD(Open)(IInStream *inStream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+public:
+ CHandler() { InitMethodProperties(); }
+
+private:
+ NArchive::NGZip::CItem m_Item;
+ UInt64 m_StreamStartPosition;
+ UInt64 m_DataOffset;
+ UInt64 m_PackSize;
+ CMyComPtr<IInStream> m_Stream;
+ CCompressionMethodMode m_Method;
+ UInt32 m_Level;
+
+ void InitMethodProperties()
+ {
+ m_Method.NumMatchFinderCyclesDefined = false;
+ m_Level = m_Method.NumPasses = m_Method.NumFastBytes = m_Method.NumMatchFinderCycles = 0xFFFFFFFF;
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp b/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp
new file mode 100755
index 00000000..cc896016
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipHandlerOut.cpp
@@ -0,0 +1,200 @@
+// Archive/GZip/OutHandler.cpp
+
+#include "StdAfx.h"
+
+#include "GZipHandler.h"
+#include "GZipUpdate.h"
+
+#include "Common/StringConvert.h"
+#include "Common/StringToInt.h"
+
+#include "Windows/Time.h"
+#include "Windows/FileFind.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../Common/ParseProperties.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NGZip {
+
+static const UInt32 kNumPassesX1 = 1;
+static const UInt32 kNumPassesX7 = 3;
+static const UInt32 kNumPassesX9 = 10;
+
+static const UInt32 kNumFastBytesX1 = 32;
+static const UInt32 kNumFastBytesX7 = 64;
+static const UInt32 kNumFastBytesX9 = 128;
+
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *timeType)
+{
+ *timeType = NFileTimeType::kUnix;
+ return S_OK;
+}
+
+static HRESULT CopyStreams(ISequentialInStream *inStream, ISequentialOutStream *outStream)
+{
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+ return copyCoder->Code(inStream, outStream, NULL, NULL, NULL);
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ if (numItems != 1)
+ return E_INVALIDARG;
+
+ UInt64 size;
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ UInt32 itemIndex = 0;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProperties, &indexInArchive));
+
+ CItem newItem = m_Item;
+ newItem.ExtraFlags = 0;
+ newItem.Flags = 0;
+ if (IntToBool(newProperties))
+ {
+ UInt32 attributes;
+ FILETIME utcTime;
+ UString name;
+ bool isDirectory;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(itemIndex, kpidAttributes, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ attributes = 0;
+ else if (propVariant.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ attributes = propVariant.ulVal;
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(itemIndex, kpidLastWriteTime, &propVariant));
+ if (propVariant.vt != VT_FILETIME)
+ return E_INVALIDARG;
+ utcTime = propVariant.filetime;
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(itemIndex, 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(itemIndex, kpidIsFolder, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ isDirectory = false;
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ isDirectory = (propVariant.boolVal != VARIANT_FALSE);
+ }
+ if (isDirectory || NFile::NFind::NAttributes::IsDirectory(attributes))
+ return E_INVALIDARG;
+ if(!FileTimeToUnixTime(utcTime, newItem.Time))
+ return E_INVALIDARG;
+ newItem.Name = UnicodeStringToMultiByte(name, CP_ACP);
+ int dirDelimiterPos = newItem.Name.ReverseFind(CHAR_PATH_SEPARATOR);
+ if (dirDelimiterPos >= 0)
+ newItem.Name = newItem.Name.Mid(dirDelimiterPos + 1);
+
+ newItem.SetNameIsPresentFlag(!newItem.Name.IsEmpty());
+ }
+
+ if (IntToBool(newData))
+ {
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(itemIndex, kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = propVariant.uhVal.QuadPart;
+ }
+ newItem.UnPackSize32 = (UInt32)size;
+
+ UInt32 level = m_Level;
+ if (level == 0xFFFFFFFF)
+ level = 5;
+ if (m_Method.NumPasses == 0xFFFFFFFF)
+ m_Method.NumPasses = (level >= 9 ? kNumPassesX9 :
+ (level >= 7 ? kNumPassesX7 :
+ kNumPassesX1));
+ if (m_Method.NumFastBytes == 0xFFFFFFFF)
+ m_Method.NumFastBytes = (level >= 9 ? kNumFastBytesX9 :
+ (level >= 7 ? kNumFastBytesX7 :
+ kNumFastBytesX1));
+
+ return UpdateArchive(m_Stream, size, outStream, newItem, m_Method, itemIndex, updateCallback);
+ }
+
+ if (indexInArchive != 0)
+ return E_INVALIDARG;
+
+ if (IntToBool(newProperties))
+ {
+ COutArchive outArchive;
+ outArchive.Create(outStream);
+ outArchive.WriteHeader(newItem);
+ RINOK(m_Stream->Seek(m_StreamStartPosition + m_DataOffset, STREAM_SEEK_SET, NULL));
+ }
+ else
+ {
+ RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL));
+ }
+ return CopyStreams(m_Stream, outStream);
+}
+
+STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
+{
+ InitMethodProperties();
+ for (int i = 0; i < numProperties; i++)
+ {
+ UString name = names[i];
+ name.MakeUpper();
+ const PROPVARIANT &prop = values[i];
+ if (name[0] == L'X')
+ {
+ UInt32 level = 9;
+ RINOK(ParsePropValue(name.Mid(1), prop, level));
+ m_Level = level;
+ }
+ else if (name.Left(4) == L"PASS")
+ {
+ UInt32 num = kNumPassesX9;
+ RINOK(ParsePropValue(name.Mid(4), prop, num));
+ m_Method.NumPasses = num;
+ }
+ else if (name.Left(2) == L"FB")
+ {
+ UInt32 num = kNumFastBytesX9;
+ RINOK(ParsePropValue(name.Mid(2), prop, num));
+ m_Method.NumFastBytes = num;
+ }
+ else if (name.Left(2) == L"MC")
+ {
+ UInt32 num = 0xFFFFFFFF;
+ RINOK(ParsePropValue(name.Mid(2), prop, num));
+ m_Method.NumMatchFinderCycles = num;
+ m_Method.NumMatchFinderCyclesDefined = true;
+ }
+ else
+ return E_INVALIDARG;
+ }
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/GZip/GZipHeader.cpp b/CPP/7zip/Archive/GZip/GZipHeader.cpp
new file mode 100755
index 00000000..5e697fa9
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipHeader.cpp
@@ -0,0 +1,20 @@
+// Archive/GZip/Header.h
+
+#include "StdAfx.h"
+
+#include "GZipHeader.h"
+
+namespace NArchive {
+namespace NGZip {
+
+extern UInt16 kSignature = 0x8B1F + 1;
+
+static class CMarkersInitializer
+{
+public:
+ CMarkersInitializer()
+ { kSignature--; }
+} g_MarkerInitializer;
+
+}}
+
diff --git a/CPP/7zip/Archive/GZip/GZipHeader.h b/CPP/7zip/Archive/GZip/GZipHeader.h
new file mode 100755
index 00000000..e83548eb
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipHeader.h
@@ -0,0 +1,85 @@
+// Archive/GZip/Header.h
+
+#ifndef __ARCHIVE_GZIP_HEADER_H
+#define __ARCHIVE_GZIP_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NGZip {
+
+extern UInt16 kSignature;
+static const UInt32 kSignatureSize = 2;
+
+namespace NFileHeader
+{
+ /*
+ struct CBlock
+ {
+ UInt16 Id;
+ Byte CompressionMethod;
+ Byte Flags;
+ UInt32 Time;
+ Byte ExtraFlags;
+ Byte HostOS;
+ };
+ */
+
+ namespace NFlags
+ {
+ const int kDataIsText = 1 << 0;
+ const int kHeaderCRCIsPresent = 1 << 1;
+ const int kExtraIsPresent = 1 << 2;
+ const int kNameIsPresent = 1 << 3;
+ const int kComentIsPresent = 1 << 4;
+ }
+
+ namespace NExtraFlags
+ {
+ enum EEnum
+ {
+ kMaximum = 2,
+ kFastest = 4
+ };
+ }
+
+ namespace NCompressionMethod
+ {
+ const Byte kDeflate = 8;
+ }
+
+ 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,
+
+ kUnknown = 255
+ };
+ const int kNumHostSystems = 19;
+ }
+}
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/GZip/GZipIn.cpp b/CPP/7zip/Archive/GZip/GZipIn.cpp
new file mode 100755
index 00000000..2b16d369
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipIn.cpp
@@ -0,0 +1,121 @@
+// Archive/GZipIn.cpp
+
+#include "StdAfx.h"
+
+#include "GZipIn.h"
+
+#include "Common/Defs.h"
+#include "Common/MyCom.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NGZip {
+
+HRESULT CInArchive::ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size)
+{
+ UInt32 realProcessedSize;
+ RINOK(ReadStream(inStream, data, size, &realProcessedSize));
+ m_Position += realProcessedSize;
+ if(realProcessedSize != size)
+ return S_FALSE;
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadByte(ISequentialInStream *inStream, Byte &value)
+{
+ return ReadBytes(inStream, &value, 1);
+}
+
+HRESULT CInArchive::ReadUInt16(ISequentialInStream *inStream, UInt16 &value)
+{
+ value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ Byte b;
+ RINOK(ReadByte(inStream, b));
+ value |= (UInt16(b) << (8 * i));
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadUInt32(ISequentialInStream *inStream, UInt32 &value)
+{
+ value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b;
+ RINOK(ReadByte(inStream, b));
+ value |= (UInt32(b) << (8 * i));
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, CCRC &crc)
+{
+ resString.Empty();
+ for (;;)
+ {
+ Byte c;
+ RINOK(ReadByte(inStream, c));
+ crc.UpdateByte(c);
+ if (c == 0)
+ return S_OK;
+ resString += char(c);
+ }
+}
+
+HRESULT CInArchive::ReadHeader(ISequentialInStream *inStream, CItem &item)
+{
+ item.Clear();
+ m_Position = 0;
+
+ UInt16 signature;
+ RINOK(ReadUInt16(inStream, signature));
+ if (signature != kSignature)
+ return S_FALSE;
+ RINOK(ReadByte(inStream, item.CompressionMethod));
+ RINOK(ReadByte(inStream, item.Flags));
+ RINOK(ReadUInt32(inStream, item.Time));
+ RINOK(ReadByte(inStream, item.ExtraFlags));
+ RINOK(ReadByte(inStream, item.HostOS));
+
+ CCRC crc;
+ crc.Update(&signature, 2);
+ crc.UpdateByte(item.CompressionMethod);
+ crc.UpdateByte(item.Flags);
+ crc.UpdateUInt32(item.Time);
+ crc.UpdateByte(item.ExtraFlags);
+ crc.UpdateByte(item.HostOS);
+
+ if (item.ExtraFieldIsPresent())
+ {
+ UInt16 extraSize;
+ RINOK(ReadUInt16(inStream, extraSize));
+ crc.UpdateUInt16(extraSize);
+ item.Extra.SetCapacity(extraSize);
+ RINOK(ReadBytes(inStream, item.Extra, extraSize));
+ crc.Update(item.Extra, extraSize);
+ }
+ if (item.NameIsPresent())
+ RINOK(ReadZeroTerminatedString(inStream, item.Name, crc));
+ if (item.CommentIsPresent())
+ RINOK(ReadZeroTerminatedString(inStream, item.Comment, crc));
+ if (item.HeaderCRCIsPresent())
+ {
+ UInt16 headerCRC;
+ RINOK(ReadUInt16(inStream, headerCRC));
+ if ((UInt16)crc.GetDigest() != headerCRC)
+ return S_FALSE;
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::ReadPostHeader(ISequentialInStream *inStream, CItem &item)
+{
+ RINOK(ReadUInt32(inStream, item.FileCRC));
+ return ReadUInt32(inStream, item.UnPackSize32);
+}
+
+}}
diff --git a/CPP/7zip/Archive/GZip/GZipIn.h b/CPP/7zip/Archive/GZip/GZipIn.h
new file mode 100755
index 00000000..998470e0
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipIn.h
@@ -0,0 +1,31 @@
+// Archive/GZipIn.h
+
+#ifndef __ARCHIVE_GZIP_IN_H
+#define __ARCHIVE_GZIP_IN_H
+
+#include "GZipHeader.h"
+#include "GZipItem.h"
+#include "Common/CRC.h"
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NGZip {
+
+class CInArchive
+{
+ UInt64 m_Position;
+
+ HRESULT ReadBytes(ISequentialInStream *inStream, void *data, UInt32 size);
+ HRESULT ReadZeroTerminatedString(ISequentialInStream *inStream, AString &resString, CCRC &crc);
+ HRESULT ReadByte(ISequentialInStream *inStream, Byte &value);
+ HRESULT ReadUInt16(ISequentialInStream *inStream, UInt16 &value);
+ HRESULT ReadUInt32(ISequentialInStream *inStream, UInt32 &value);
+public:
+ HRESULT ReadHeader(ISequentialInStream *inStream, CItem &item);
+ HRESULT ReadPostHeader(ISequentialInStream *inStream, CItem &item);
+ UInt64 GetOffset() const { return m_Position; }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/GZip/GZipItem.h b/CPP/7zip/Archive/GZip/GZipItem.h
new file mode 100755
index 00000000..7006dfb3
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipItem.h
@@ -0,0 +1,59 @@
+// Archive/GZipItem.h
+
+#ifndef __ARCHIVE_GZIP_ITEM_H
+#define __ARCHIVE_GZIP_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "Common/Buffer.h"
+
+namespace NArchive {
+namespace NGZip {
+
+class CItem
+{
+private:
+ bool TestFlag(Byte flag) const { return ((Flags & flag) != 0); }
+public:
+ Byte CompressionMethod;
+ Byte Flags;
+ UInt32 Time;
+ Byte ExtraFlags;
+ Byte HostOS;
+ UInt32 FileCRC;
+ UInt32 UnPackSize32;
+
+ AString Name;
+ AString Comment;
+ CByteBuffer Extra;
+
+ bool IsText() const
+ { return TestFlag(NFileHeader::NFlags::kDataIsText); }
+ bool HeaderCRCIsPresent() const
+ { return TestFlag(NFileHeader::NFlags::kHeaderCRCIsPresent); }
+ bool ExtraFieldIsPresent() const
+ { return TestFlag(NFileHeader::NFlags::kExtraIsPresent); }
+ bool NameIsPresent() const
+ { return TestFlag(NFileHeader::NFlags::kNameIsPresent); }
+ bool CommentIsPresent() const
+ { return TestFlag(NFileHeader::NFlags::kComentIsPresent); }
+
+ void SetNameIsPresentFlag(bool nameIsPresent)
+ {
+ if (nameIsPresent)
+ Flags |= NFileHeader::NFlags::kNameIsPresent;
+ else
+ Flags &= (~NFileHeader::NFlags::kNameIsPresent);
+ }
+
+ void Clear()
+ {
+ Name.Empty();
+ Comment.Empty();;
+ Extra.SetCapacity(0);
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/GZip/GZipOut.cpp b/CPP/7zip/Archive/GZip/GZipOut.cpp
new file mode 100755
index 00000000..afa8a931
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipOut.cpp
@@ -0,0 +1,69 @@
+// Archive/GZipOut.cpp
+
+#include "StdAfx.h"
+
+#include "GZipOut.h"
+#include "Common/CRC.h"
+#include "Windows/Defs.h"
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NGZip {
+
+HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)
+{
+ UInt32 processedSize;
+ RINOK(WriteStream(m_Stream, buffer, size, &processedSize));
+ if(processedSize != size)
+ return E_FAIL;
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteByte(Byte value)
+{
+ return WriteBytes(&value, 1);
+}
+
+HRESULT COutArchive::WriteUInt16(UInt16 value)
+{
+ for (int i = 0; i < 2; i++)
+ {
+ RINOK(WriteByte((Byte)value));
+ value >>= 8;
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteUInt32(UInt32 value)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ RINOK(WriteByte((Byte)value));
+ value >>= 8;
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WriteHeader(const CItem &item)
+{
+ RINOK(WriteUInt16(kSignature));
+ RINOK(WriteByte(item.CompressionMethod));
+ RINOK(WriteByte((Byte)(item.Flags & NFileHeader::NFlags::kNameIsPresent)));
+ RINOK(WriteUInt32(item.Time));
+ RINOK(WriteByte(item.ExtraFlags));
+ RINOK(WriteByte(item.HostOS));
+ if (item.NameIsPresent())
+ {
+ RINOK(WriteBytes((const char *)item.Name, item.Name.Length()));
+ RINOK(WriteByte(0));
+ }
+ return S_OK;
+}
+
+HRESULT COutArchive::WritePostHeader(const CItem &item)
+{
+ RINOK(WriteUInt32(item.FileCRC));
+ return WriteUInt32(item.UnPackSize32);
+}
+
+}}
diff --git a/CPP/7zip/Archive/GZip/GZipOut.h b/CPP/7zip/Archive/GZip/GZipOut.h
new file mode 100755
index 00000000..a2ba2ebf
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipOut.h
@@ -0,0 +1,29 @@
+// Archive/GZipOut.h
+
+#ifndef __ARCHIVE_GZIP_OUT_H
+#define __ARCHIVE_GZIP_OUT_H
+
+#include "Common/MyCom.h"
+#include "GZipHeader.h"
+#include "GZipItem.h"
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NGZip {
+
+class COutArchive
+{
+ CMyComPtr<ISequentialOutStream> m_Stream;
+ HRESULT WriteBytes(const void *buffer, UInt32 size);
+ HRESULT WriteByte(Byte value);
+ HRESULT WriteUInt16(UInt16 value);
+ HRESULT WriteUInt32(UInt32 value);
+public:
+ void Create(ISequentialOutStream *outStream) { m_Stream = outStream; }
+ HRESULT WriteHeader(const CItem &item);
+ HRESULT WritePostHeader(const CItem &item);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/GZip/GZipUpdate.cpp b/CPP/7zip/Archive/GZip/GZipUpdate.cpp
new file mode 100755
index 00000000..45e6e985
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipUpdate.cpp
@@ -0,0 +1,120 @@
+// GZipUpdate.cpp
+
+#include "StdAfx.h"
+
+#include "GZipUpdate.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+
+#include "Windows/Defs.h"
+#include "Windows/PropVariant.h"
+
+#include "../../ICoder.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/InStreamWithCRC.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);
+#include "../Common/CoderLoader.h"
+extern CSysString GetDeflateCodecPath();
+#endif
+
+namespace NArchive {
+namespace NGZip {
+
+static const Byte kHostOS = NFileHeader::NHostOS::kFAT;
+
+HRESULT UpdateArchive(IInStream * /* inStream */,
+ UInt64 unpackSize,
+ ISequentialOutStream *outStream,
+ const CItem &newItem,
+ const CCompressionMethodMode &compressionMethod,
+ int indexInClient,
+ IArchiveUpdateCallback *updateCallback)
+{
+ UInt64 complexity = 0;
+
+ complexity += unpackSize;
+
+ RINOK(updateCallback->SetTotal(complexity));
+
+ #ifndef COMPRESS_DEFLATE
+ CCoderLibrary lib;
+ #endif
+ CMyComPtr<ICompressCoder> deflateEncoder;
+
+ complexity = 0;
+ RINOK(updateCallback->SetCompleted(&complexity));
+
+ CMyComPtr<ISequentialInStream> fileInStream;
+
+ RINOK(updateCallback->GetStream(indexInClient, &fileInStream));
+
+ CSequentialInStreamWithCRC *inStreamSpec = new CSequentialInStreamWithCRC;
+ CMyComPtr<ISequentialInStream> crcStream(inStreamSpec);
+ inStreamSpec->SetStream(fileInStream);
+ inStreamSpec->Init();
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
+ localProgressSpec->Init(updateCallback, true);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+
+ COutArchive outArchive;
+ outArchive.Create(outStream);
+
+ CItem item = newItem;
+ item.CompressionMethod = NFileHeader::NCompressionMethod::kDeflate;
+ item.ExtraFlags = 0;
+ item.HostOS = kHostOS;
+
+ RINOK(outArchive.WriteHeader(item));
+
+ localCompressProgressSpec->Init(localProgress, &complexity, NULL);
+
+ {
+ #ifdef COMPRESS_DEFLATE
+ deflateEncoder = new NCompress::NDeflate::NEncoder::CCOMCoder;
+ #else
+ RINOK(lib.LoadAndCreateCoder(GetDeflateCodecPath(),
+ CLSID_CCompressDeflateEncoder, &deflateEncoder));
+ #endif
+
+ NWindows::NCOM::CPropVariant properties[] =
+ {
+ compressionMethod.NumPasses,
+ compressionMethod.NumFastBytes,
+ compressionMethod.NumMatchFinderCycles
+ };
+ PROPID propIDs[] =
+ {
+ NCoderPropID::kNumPasses,
+ NCoderPropID::kNumFastBytes,
+ NCoderPropID::kMatchFinderCycles
+ };
+ int numProps = sizeof(propIDs) / sizeof(propIDs[0]);
+ if (!compressionMethod.NumMatchFinderCyclesDefined)
+ numProps--;
+ CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
+ RINOK(deflateEncoder.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));
+ RINOK(setCoderProperties->SetCoderProperties(propIDs, properties, numProps));
+ }
+ RINOK(deflateEncoder->Code(crcStream, outStream, NULL, NULL, compressProgress));
+
+ item.FileCRC = inStreamSpec->GetCRC();
+ item.UnPackSize32 = (UInt32)inStreamSpec->GetSize();
+ RINOK(outArchive.WritePostHeader(item));
+ return updateCallback->SetOperationResult(NArchive::NUpdate::NOperationResult::kOK);
+}
+
+}}
diff --git a/CPP/7zip/Archive/GZip/GZipUpdate.h b/CPP/7zip/Archive/GZip/GZipUpdate.h
new file mode 100755
index 00000000..c06e8a4c
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/GZipUpdate.h
@@ -0,0 +1,32 @@
+// GZip/Update.h
+
+#ifndef __GZIP_UPDATE_H
+#define __GZIP_UPDATE_H
+
+#include "../IArchive.h"
+
+#include "GZipOut.h"
+#include "GZipItem.h"
+
+namespace NArchive {
+namespace NGZip {
+
+struct CCompressionMethodMode
+{
+ UInt32 NumPasses;
+ UInt32 NumFastBytes;
+ bool NumMatchFinderCyclesDefined;
+ UInt32 NumMatchFinderCycles;
+};
+
+HRESULT UpdateArchive(IInStream *inStream,
+ UInt64 unpackSize,
+ ISequentialOutStream *outStream,
+ const CItem &newItem,
+ const CCompressionMethodMode &compressionMethod,
+ int indexInClient,
+ IArchiveUpdateCallback *updateCallback);
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/GZip/StdAfx.cpp b/CPP/7zip/Archive/GZip/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/GZip/StdAfx.h b/CPP/7zip/Archive/GZip/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/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/GZip/gz.ico b/CPP/7zip/Archive/GZip/gz.ico
new file mode 100755
index 00000000..f50d8c08
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/gz.ico
Binary files differ
diff --git a/CPP/7zip/Archive/GZip/makefile b/CPP/7zip/Archive/GZip/makefile
new file mode 100755
index 00000000..abc3f1e4
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/makefile
@@ -0,0 +1,60 @@
+PROG = gz.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+GZ_OBJS = \
+ $O\GZipHandler.obj \
+ $O\GZipHandlerOut.obj \
+ $O\GZipHeader.obj \
+ $O\GZipIn.obj \
+ $O\GZipOut.obj \
+ $O\GZipUpdate.obj \
+ $O\DllExports.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\CRC.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\CodecsPath.obj \
+ $O\InStreamWithCRC.obj \
+ $O\OutStreamWithCRC.obj \
+ $O\ParseProperties.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(GZ_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(GZ_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/GZip/resource.rc b/CPP/7zip/Archive/GZip/resource.rc
new file mode 100755
index 00000000..29fb4825
--- /dev/null
+++ b/CPP/7zip/Archive/GZip/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("GZip Plugin", "gz")
+
+101 ICON "gz.ico"
diff --git a/CPP/7zip/Archive/IArchive.h b/CPP/7zip/Archive/IArchive.h
new file mode 100755
index 00000000..d6cbe804
--- /dev/null
+++ b/CPP/7zip/Archive/IArchive.h
@@ -0,0 +1,173 @@
+// IArchive.h
+
+#ifndef __IARCHIVE_H
+#define __IARCHIVE_H
+
+#include "../IStream.h"
+#include "../IProgress.h"
+#include "../PropID.h"
+
+// MIDL_INTERFACE("23170F69-40C1-278A-0000-000600xx0000")
+#define ARCHIVE_INTERFACE_SUB(i, base, x) \
+DEFINE_GUID(IID_ ## i, \
+0x23170F69, 0x40C1, 0x278A, 0x00, 0x00, 0x00, 0x06, 0x00, x, 0x00, 0x00); \
+struct i: public base
+
+#define ARCHIVE_INTERFACE(i, x) ARCHIVE_INTERFACE_SUB(i, IUnknown, x)
+
+namespace NFileTimeType
+{
+ enum EEnum
+ {
+ kWindows,
+ kUnix,
+ kDOS
+ };
+}
+
+namespace NArchive
+{
+ enum
+ {
+ kName = 0,
+ kClassID,
+ kExtension,
+ kAddExtension,
+ kUpdate,
+ kKeepName,
+ kStartSignature,
+ kFinishSignature,
+ kAssociate
+ };
+
+ namespace NExtract
+ {
+ namespace NAskMode
+ {
+ enum
+ {
+ kExtract = 0,
+ kTest,
+ kSkip,
+ };
+ }
+ namespace NOperationResult
+ {
+ enum
+ {
+ kOK = 0,
+ kUnSupportedMethod,
+ kDataError,
+ kCRCError,
+ };
+ }
+ }
+ namespace NUpdate
+ {
+ namespace NOperationResult
+ {
+ enum
+ {
+ kOK = 0,
+ kError,
+ };
+ }
+ }
+}
+
+ARCHIVE_INTERFACE(IArchiveOpenCallback, 0x10)
+{
+ STDMETHOD(SetTotal)(const UInt64 *files, const UInt64 *bytes) PURE;
+ STDMETHOD(SetCompleted)(const UInt64 *files, const UInt64 *bytes) PURE;
+};
+
+
+ARCHIVE_INTERFACE_SUB(IArchiveExtractCallback, IProgress, 0x20)
+{
+ STDMETHOD(GetStream)(UInt32 index, ISequentialOutStream **outStream,
+ Int32 askExtractMode) PURE;
+ // GetStream OUT: S_OK - OK, S_FALSE - skeep this file
+ STDMETHOD(PrepareOperation)(Int32 askExtractMode) PURE;
+ STDMETHOD(SetOperationResult)(Int32 resultEOperationResult) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IArchiveOpenVolumeCallback, 0x30)
+{
+ STDMETHOD(GetProperty)(PROPID propID, PROPVARIANT *value) PURE;
+ STDMETHOD(GetStream)(const wchar_t *name, IInStream **inStream) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IInArchiveGetStream, 0x40)
+{
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IArchiveOpenSetSubArchiveName, 0x50)
+{
+ STDMETHOD(SetSubArchiveName)(const wchar_t *name) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IInArchive, 0x60)
+{
+ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback) PURE;
+ STDMETHOD(Close)() PURE;
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems) PURE;
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback) PURE;
+ // indices must be sorted
+ // numItems = 0xFFFFFFFF means all files
+ // testMode != 0 means "test files operation"
+
+ STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value) PURE;
+
+ STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties) PURE;
+ STDMETHOD(GetPropertyInfo)(UInt32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
+
+ STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties) PURE;
+ STDMETHOD(GetArchivePropertyInfo)(UInt32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType) PURE;
+};
+
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback, IProgress, 0x80)
+{
+ STDMETHOD(GetUpdateItemInfo)(UInt32 index,
+ Int32 *newData, // 1 - new data, 0 - old data
+ Int32 *newProperties, // 1 - new properties, 0 - old properties
+ UInt32 *indexInArchive // -1 if there is no in archive, or if doesn't matter
+ ) PURE;
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value) PURE;
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **inStream) PURE;
+ STDMETHOD(SetOperationResult)(Int32 operationResult) PURE;
+};
+
+
+ARCHIVE_INTERFACE_SUB(IArchiveUpdateCallback2, IArchiveUpdateCallback, 0x82)
+{
+ STDMETHOD(GetVolumeSize)(UInt32 index, UInt64 *size) PURE;
+ STDMETHOD(GetVolumeStream)(UInt32 index, ISequentialOutStream **volumeStream) PURE;
+};
+
+
+ARCHIVE_INTERFACE(IOutArchive, 0xA0)
+{
+ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback) PURE;
+ STDMETHOD(GetFileTimeType)(UInt32 *type) PURE;
+};
+
+
+ARCHIVE_INTERFACE(ISetProperties, 0x03)
+{
+ STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) PURE;
+};
+
+
+#endif
diff --git a/CPP/7zip/Archive/Iso/DllExports.cpp b/CPP/7zip/Archive/Iso/DllExports.cpp
new file mode 100755
index 00000000..f746eea1
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/DllExports.cpp
@@ -0,0 +1,88 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "IsoHandler.h"
+
+// {23170F69-40C1-278A-1000-000110E70000}
+DEFINE_GUID(CLSID_CIsoHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xE7, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CIsoHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ // int needOut = *interfaceID == IID_IOutArchive;
+ if (needIn /*|| needOut */)
+ {
+ NArchive::NIso::CHandler *temp = new NArchive::NIso::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"Iso";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CIsoHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"iso";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const unsigned char sig[] = { 'C', 'D', '0', '0', '1', 0x1 };
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 7)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Iso/Iso.dsp b/CPP/7zip/Archive/Iso/Iso.dsp
new file mode 100755
index 00000000..a204e9cd
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/Iso.dsp
@@ -0,0 +1,273 @@
+# Microsoft Developer Studio Project File - Name="Iso" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Iso - 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 "Iso.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 "Iso.mak" CFG="Iso - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Iso - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Iso - 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)" == "Iso - 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 "TAR_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /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 0x419 /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\Iso.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Iso - 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 "TAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /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 0x419 /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\Iso.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Iso - Win32 Release"
+# Name "Iso - 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=.\Iso.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# 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\Buffer.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\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\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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\IsoHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\IsoHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\IsoHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\IsoHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\IsoIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\IsoIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\IsoItem.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.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\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.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
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Iso/Iso.dsw b/CPP/7zip/Archive/Iso/Iso.dsw
new file mode 100755
index 00000000..27728dd2
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/Iso.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Iso"=.\Iso.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Iso/Iso.ico b/CPP/7zip/Archive/Iso/Iso.ico
new file mode 100755
index 00000000..2538e408
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/Iso.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.cpp b/CPP/7zip/Archive/Iso/IsoHandler.cpp
new file mode 100755
index 00000000..1831e913
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoHandler.cpp
@@ -0,0 +1,301 @@
+// Iso/Handler.cpp
+
+#include "StdAfx.h"
+
+#include "IsoHandler.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/Time.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NIso {
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME}
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ Close();
+ // try
+ {
+ if(_archive.Open(stream) != S_OK)
+ return S_FALSE;
+ _inStream = stream;
+ }
+ // catch(...) { return S_FALSE; }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _archive.Clear();
+ _inStream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _archive.Refs.Size() + _archive.BootEntries.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ if (index >= (UInt32)_archive.Refs.Size())
+ {
+ index -= _archive.Refs.Size();
+ const CBootInitialEntry &be = _archive.BootEntries[index];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ // wchar_t name[32];
+ // ConvertUInt64ToString(index + 1, name);
+ UString s = L"[BOOT]" WSTRING_PATH_SEPARATOR;
+ // s += name;
+ // s += L"-";
+ s += be.GetName();
+ propVariant = (const wchar_t *)s;
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ {
+ propVariant = (UInt64)_archive.GetBootItemSize(index);
+ break;
+ }
+ }
+ }
+ else
+ {
+ const CRef &ref = _archive.Refs[index];
+ const CDir &item = ref.Dir->_subItems[ref.Index];
+ switch(propID)
+ {
+ case kpidPath:
+ if (item.FileId.GetCapacity() >= 0)
+ {
+ UString s;
+ if (_archive.IsJoliet())
+ s = item.GetPathU();
+ else
+ s = MultiByteToUnicodeString(item.GetPath(_archive.IsSusp, _archive.SuspSkipSize), CP_OEMCP);
+
+ int pos = s.ReverseFind(L';');
+ if (pos >= 0 && pos == s.Length() - 2)
+ if (s[s.Length() - 1] == L'1')
+ s = s.Left(pos);
+ if (!s.IsEmpty())
+ if (s[s.Length() - 1] == L'.')
+ s = s.Left(s.Length() - 1);
+ propVariant = (const wchar_t *)NItemName::GetOSName2(s);
+ }
+ break;
+ case kpidIsFolder:
+ propVariant = item.IsDir();
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ if (!item.IsDir())
+ propVariant = (UInt64)item.DataLength;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME utcFileTime;
+ if (item.DateTime.GetFileTime(utcFileTime))
+ propVariant = utcFileTime;
+ /*
+ else
+ {
+ utcFileTime.dwLowDateTime = 0;
+ utcFileTime.dwHighDateTime = 0;
+ }
+ */
+ break;
+ }
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool testMode = (_aTestMode != 0);
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = _archive.Refs.Size();
+ UInt64 totalSize = 0;
+ if(numItems == 0)
+ return S_OK;
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ {
+ UInt32 index = (allFilesMode ? i : indices[i]);
+ if (index < (UInt32)_archive.Refs.Size())
+ {
+ const CRef &ref = _archive.Refs[index];
+ const CDir &item = ref.Dir->_subItems[ref.Index];
+ totalSize += item.DataLength;
+ }
+ else
+ {
+ totalSize += _archive.GetBootItemSize(index - _archive.Refs.Size());
+ }
+ }
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+ UInt64 currentItemSize;
+
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ currentItemSize = 0;
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract;
+ UInt32 index = allFilesMode ? i : indices[i];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ UInt64 blockIndex;
+ if (index < (UInt32)_archive.Refs.Size())
+ {
+ const CRef &ref = _archive.Refs[index];
+ const CDir &item = ref.Dir->_subItems[ref.Index];
+ if(item.IsDir())
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+ currentItemSize = item.DataLength;
+ blockIndex = item.ExtentLocation;
+ }
+ else
+ {
+ int bootIndex = index - _archive.Refs.Size();
+ const CBootInitialEntry &be = _archive.BootEntries[bootIndex];
+ currentItemSize = _archive.GetBootItemSize(bootIndex);
+ blockIndex = be.LoadRBA;
+ }
+
+ if(!testMode && (!realOutStream))
+ continue;
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+ {
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ RINOK(_inStream->Seek(blockIndex * _archive.BlockSize, STREAM_SEEK_SET, NULL));
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_inStream);
+ streamSpec->Init(currentItemSize);
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress, &currentTotalSize, &currentTotalSize);
+
+ Int32 res = NArchive::NExtract::NOperationResult::kOK;
+ if(!copyCoder)
+ {
+ copyCoder = new NCompress::CCopyCoder;
+ }
+ try
+ {
+ RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, compressProgress));
+ }
+ catch(...)
+ {
+ res = NArchive::NExtract::NOperationResult::kDataError;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(res));
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Iso/IsoHandler.h b/CPP/7zip/Archive/Iso/IsoHandler.h
new file mode 100755
index 00000000..e545d2a7
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoHandler.h
@@ -0,0 +1,59 @@
+// Tar/Handler.h
+
+#ifndef __ISO_HANDLER_H
+#define __ISO_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "IsoItem.h"
+#include "IsoIn.h"
+
+namespace NArchive {
+namespace NIso {
+
+class CHandler:
+ public IInArchive,
+ // public IOutArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(
+ IInArchive
+ // IOutArchive
+ )
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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 *type);
+ */
+
+private:
+ CMyComPtr<IInStream> _inStream;
+ CInArchive _archive;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.cpp b/CPP/7zip/Archive/Iso/IsoHeader.cpp
new file mode 100755
index 00000000..9555e49b
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoHeader.cpp
@@ -0,0 +1,21 @@
+// Archive/Iso/Header.h
+
+#include "StdAfx.h"
+
+#include "IsoHeader.h"
+
+namespace NArchive {
+namespace NIso {
+
+const char *kElToritoSpec = "EL TORITO SPECIFICATION\0\0\0\0\0\0\0\0\0";
+
+const wchar_t *kMediaTypes[5] =
+{
+ L"NoEmulation",
+ L"1.2M",
+ L"1.44M",
+ L"2.88M",
+ L"HardDisk"
+};
+
+}}
diff --git a/CPP/7zip/Archive/Iso/IsoHeader.h b/CPP/7zip/Archive/Iso/IsoHeader.h
new file mode 100755
index 00000000..9702d70a
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoHeader.h
@@ -0,0 +1,61 @@
+// Archive/IsoHeader.h
+
+#ifndef __ARCHIVE_ISO_HEADER_H
+#define __ARCHIVE_ISO_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NIso {
+
+namespace NVolDescType
+{
+ const Byte kBootRecord = 0;
+ const Byte kPrimaryVol = 1;
+ const Byte kSupplementaryVol = 2;
+ const Byte kVolParttition = 3;
+ const Byte kTerminator = 255;
+}
+
+const Byte kVersion = 1;
+
+namespace NFileFlags
+{
+ const Byte kDirectory = 1 << 1;
+}
+
+extern const char *kElToritoSpec;
+
+const UInt32 kStartPos = 0x8000;
+
+namespace NBootEntryId
+{
+ const Byte kValidationEntry = 1;
+ const Byte kInitialEntryNotBootable = 0;
+ const Byte kInitialEntryBootable = 0x88;
+}
+
+namespace NBootPlatformId
+{
+ const Byte kX86 = 0;
+ const Byte kPowerPC = 1;
+ const Byte kMac = 2;
+}
+
+const BYTE kBootMediaTypeMask = 0xF;
+
+namespace NBootMediaType
+{
+ const Byte kNoEmulation = 0;
+ const Byte k1d2Floppy = 1;
+ const Byte k1d44Floppy = 2;
+ const Byte k2d88Floppy = 3;
+ const Byte kHardDisk = 4;
+}
+
+const int kNumBootMediaTypes = 5;
+extern const wchar_t *kMediaTypes[];
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Iso/IsoIn.cpp b/CPP/7zip/Archive/Iso/IsoIn.cpp
new file mode 100755
index 00000000..213b3014
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoIn.cpp
@@ -0,0 +1,438 @@
+// Archive/IsoIn.cpp
+
+#include "StdAfx.h"
+
+#include "IsoIn.h"
+#include "IsoHeader.h"
+
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NIso {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ return ReadStream(_stream, data, size, &processedSize);
+}
+
+Byte CInArchive::ReadByte()
+{
+ if (m_BufferPos >= BlockSize)
+ m_BufferPos = 0;
+ if (m_BufferPos == 0)
+ {
+ UInt32 processedSize;
+ if (ReadBytes(m_Buffer, BlockSize, processedSize) != S_OK)
+ throw 1;
+ if (processedSize != BlockSize)
+ throw 1;
+ }
+ Byte b = m_Buffer[m_BufferPos++];
+ _position++;
+ return b;
+}
+
+void CInArchive::ReadBytes(Byte *data, UInt32 size)
+{
+ for (UInt32 i = 0; i < size; i++)
+ data[i] = ReadByte();
+}
+
+void CInArchive::Skeep(size_t size)
+{
+ while (size-- != 0)
+ ReadByte();
+}
+
+void CInArchive::SkeepZeros(size_t size)
+{
+ while (size-- != 0)
+ {
+ Byte b = ReadByte();
+ if (b != 0)
+ throw 1;
+ }
+}
+
+UInt16 CInArchive::ReadUInt16Spec()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ value |= ((UInt16)(ReadByte()) << (8 * i));
+ return value;
+}
+
+
+UInt16 CInArchive::ReadUInt16()
+{
+ Byte b[4];
+ ReadBytes(b, 4);
+ UInt32 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ if (b[i] != b[3 - i])
+ throw 1;
+ value |= ((UInt16)(b[i]) << (8 * i));
+ }
+ return (UInt16)value;
+}
+
+UInt32 CInArchive::ReadUInt32Le()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ value |= ((UInt32)(ReadByte()) << (8 * i));
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32Be()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ value <<= 8;
+ value |= ReadByte();
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ Byte b[8];
+ ReadBytes(b, 8);
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ if (b[i] != b[7 - i])
+ throw 1;
+ value |= ((UInt32)(b[i]) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadDigits(int numDigits)
+{
+ UInt32 res = 0;
+ for (int i = 0; i < numDigits; i++)
+ {
+ Byte b = ReadByte();
+ if (b < '0' || b > '9')
+ {
+ if (b == 0) // it's bug in some CD's
+ b = '0';
+ else
+ throw 1;
+ }
+ UInt32 d = (UInt32)(b - '0');
+ res *= 10;
+ res += d;
+ }
+ return res;
+}
+
+void CInArchive::ReadDateTime(CDateTime &d)
+{
+ d.Year = (UInt16)ReadDigits(4);
+ d.Month = (Byte)ReadDigits(2);
+ d.Day = (Byte)ReadDigits(2);
+ d.Hour = (Byte)ReadDigits(2);
+ d.Minute = (Byte)ReadDigits(2);
+ d.Second = (Byte)ReadDigits(2);
+ d.Hundredths = (Byte)ReadDigits(2);
+ d.GmtOffset = (signed char)ReadByte();
+}
+
+void CInArchive::ReadBootRecordDescriptor(CBootRecordDescriptor &d)
+{
+ ReadBytes(d.BootSystemId, sizeof(d.BootSystemId));
+ ReadBytes(d.BootId, sizeof(d.BootId));
+ ReadBytes(d.BootSystemUse, sizeof(d.BootSystemUse));
+}
+
+void CInArchive::ReadRecordingDateTime(CRecordingDateTime &t)
+{
+ t.Year = ReadByte();
+ t.Month = ReadByte();
+ t.Day = ReadByte();
+ t.Hour = ReadByte();
+ t.Minute = ReadByte();
+ t.Second = ReadByte();
+ t.GmtOffset = (signed char)ReadByte();
+}
+
+void CInArchive::ReadDirRecord2(CDirRecord &r, Byte len)
+{
+ r.ExtendedAttributeRecordLen = ReadByte();
+ if (r.ExtendedAttributeRecordLen != 0)
+ throw 1;
+ r.ExtentLocation = ReadUInt32();
+ r.DataLength = ReadUInt32();
+ ReadRecordingDateTime(r.DateTime);
+ r.FileFlags = ReadByte();
+ r.FileUnitSize = ReadByte();
+ r.InterleaveGapSize = ReadByte();
+ r.VolSequenceNumber = ReadUInt16();
+ Byte idLen = ReadByte();
+ r.FileId.SetCapacity(idLen);
+ ReadBytes((Byte *)r.FileId, idLen);
+ int padSize = 1 - (idLen & 1);
+
+ // SkeepZeros(1 - (idLen & 1));
+ Skeep(1 - (idLen & 1)); // it's bug in some cd's. Must be zeros
+
+ int curPos = 33 + idLen + padSize;
+ if (curPos > len)
+ throw 1;
+ int rem = len - curPos;
+ r.SystemUse.SetCapacity(rem);
+ ReadBytes((Byte *)r.SystemUse, rem);
+}
+
+void CInArchive::ReadDirRecord(CDirRecord &r)
+{
+ Byte len = ReadByte();
+ ReadDirRecord2(r, len);
+}
+
+void CInArchive::ReadVolumeDescriptor(CVolumeDescriptor &d)
+{
+ d.VolFlags = ReadByte();
+ ReadBytes(d.SystemId, sizeof(d.SystemId));
+ ReadBytes(d.VolumeId, sizeof(d.VolumeId));
+ SkeepZeros(8);
+ d.VolumeSpaceSize = ReadUInt32();
+ ReadBytes(d.EscapeSequence, sizeof(d.EscapeSequence));
+ d.VolumeSetSize = ReadUInt16();
+ d.VolumeSequenceNumber = ReadUInt16();
+ d.LogicalBlockSize = ReadUInt16();
+ d.PathTableSize = ReadUInt32();
+ d.LPathTableLocation = ReadUInt32Le();
+ d.LOptionalPathTableLocation = ReadUInt32Le();
+ d.MPathTableLocation = ReadUInt32Be();
+ d.MOptionalPathTableLocation = ReadUInt32Be();
+ ReadDirRecord(d.RootDirRecord);
+ ReadBytes(d.VolumeSetId, sizeof(d.VolumeSetId));
+ ReadBytes(d.PublisherId, sizeof(d.PublisherId));
+ ReadBytes(d.DataPreparerId, sizeof(d.DataPreparerId));
+ ReadBytes(d.ApplicationId, sizeof(d.ApplicationId));
+ ReadBytes(d.CopyrightFileId, sizeof(d.CopyrightFileId));
+ ReadBytes(d.AbstractFileId, sizeof(d.AbstractFileId));
+ ReadBytes(d.BibFileId, sizeof(d.BibFileId));
+ ReadDateTime(d.CreationTime);
+ ReadDateTime(d.ModificationTime);
+ ReadDateTime(d.ExpirationTime);
+ ReadDateTime(d.EffectiveTime);
+ d.FileStructureVersion = ReadByte(); // = 1
+ SkeepZeros(1);
+ ReadBytes(d.ApplicationUse, sizeof(d.ApplicationUse));
+ SkeepZeros(653);
+}
+
+static inline bool CheckDescriptorSignature(const Byte *sig)
+{
+ return sig[0] == 'C' &&
+ sig[1] == 'D' &&
+ sig[2] == '0' &&
+ sig[3] == '0' &&
+ sig[4] == '1';
+}
+
+void CInArchive::SeekToBlock(UInt32 blockIndex)
+{
+ if (_stream->Seek((UInt64)blockIndex * VolDescs[MainVolDescIndex].LogicalBlockSize, STREAM_SEEK_SET, &_position) != S_OK)
+ throw 1;
+ m_BufferPos = 0;
+}
+
+void CInArchive::ReadDir(CDir &d, int level)
+{
+ if (!d.IsDir())
+ return;
+ SeekToBlock(d.ExtentLocation);
+ UInt64 startPos = _position;
+
+ bool firstItem = true;
+ for (;;)
+ {
+ UInt64 offset = _position - startPos;
+ if (offset >= d.DataLength)
+ break;
+ Byte len = ReadByte();
+ if (len == 0)
+ continue;
+ CDir subItem;
+ ReadDirRecord2(subItem, len);
+ if (firstItem && level == 0)
+ IsSusp = subItem.CheckSusp(SuspSkipSize);
+
+ if (!subItem.IsSystemItem())
+ d._subItems.Add(subItem);
+
+ firstItem = false;
+ }
+ for (int i = 0; i < d._subItems.Size(); i++)
+ ReadDir(d._subItems[i], level + 1);
+}
+
+void CInArchive::CreateRefs(CDir &d)
+{
+ if (!d.IsDir())
+ return;
+ for (int i = 0; i < d._subItems.Size(); i++)
+ {
+ CRef ref;
+ CDir &subItem = d._subItems[i];
+ subItem.Parent = &d;
+ ref.Dir = &d;
+ ref.Index = i;
+ Refs.Add(ref);
+ CreateRefs(subItem);
+ }
+}
+
+void CInArchive::ReadBootInfo()
+{
+ if (!_bootIsDefined)
+ return;
+ if (memcmp(_bootDesc.BootSystemId, kElToritoSpec, sizeof(_bootDesc.BootSystemId)) != 0)
+ return;
+
+ const Byte *p = (const Byte *)_bootDesc.BootSystemUse;
+ UInt32 blockIndex = p[0] | ((UInt32)p[1] << 8) | ((UInt32)p[2] << 16) | ((UInt32)p[3] << 24);
+ SeekToBlock(blockIndex);
+ Byte b = ReadByte();
+ if (b != NBootEntryId::kValidationEntry)
+ return;
+ {
+ CBootValidationEntry e;
+ e.PlatformId = ReadByte();
+ if (ReadUInt16Spec() != 0)
+ throw 1;
+ ReadBytes(e.Id, sizeof(e.Id));
+ /* UInt16 checkSum = */ ReadUInt16Spec();
+ if (ReadByte() != 0x55)
+ throw 1;
+ if (ReadByte() != 0xAA)
+ throw 1;
+ }
+ b = ReadByte();
+ if (b == NBootEntryId::kInitialEntryBootable || b == NBootEntryId::kInitialEntryNotBootable)
+ {
+ CBootInitialEntry e;
+ e.Bootable = (b == NBootEntryId::kInitialEntryBootable);
+ e.BootMediaType = ReadByte();
+ e.LoadSegment = ReadUInt16Spec();
+ e.SystemType = ReadByte();
+ if (ReadByte() != 0)
+ throw 1;
+ e.SectorCount = ReadUInt16Spec();
+ e.LoadRBA = ReadUInt32Le();
+ if (ReadByte() != 0)
+ throw 1;
+ BootEntries.Add(e);
+ }
+ else
+ return;
+}
+
+HRESULT CInArchive::Open2()
+{
+ Clear();
+ RINOK(_stream->Seek(kStartPos, STREAM_SEEK_CUR, &_position));
+
+ bool primVolDescDefined = false;
+ m_BufferPos = 0;
+ BlockSize = kBlockSize;
+ VolDescs.Add(CVolumeDescriptor());
+ for (;;)
+ {
+ Byte sig[6];
+ ReadBytes(sig, 6);
+ if (!CheckDescriptorSignature(sig + 1))
+ return S_FALSE;
+ // version = 2 for ISO 9660:1999?
+ Byte ver = ReadByte();
+ if (ver > 2)
+ throw S_FALSE;
+
+ if (sig[0] == NVolDescType::kTerminator)
+ break;
+ switch(sig[0])
+ {
+ case NVolDescType::kBootRecord:
+ {
+ _bootIsDefined = true;
+ ReadBootRecordDescriptor(_bootDesc);
+ break;
+ }
+ case NVolDescType::kPrimaryVol:
+ {
+ if (primVolDescDefined)
+ return S_FALSE;
+ primVolDescDefined = true;
+ CVolumeDescriptor &volDesc = VolDescs[0];
+ ReadVolumeDescriptor(volDesc);
+ // some burners write "Joliet" Escape Sequence to primary volume
+ memset(volDesc.EscapeSequence, 0, sizeof(volDesc.EscapeSequence));
+ break;
+ }
+ case NVolDescType::kSupplementaryVol:
+ {
+ CVolumeDescriptor sd;
+ ReadVolumeDescriptor(sd);
+ VolDescs.Add(sd);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ MainVolDescIndex = 0;
+ if (!primVolDescDefined)
+ return S_FALSE;
+ for (int i = VolDescs.Size() - 1; i >= 0; i--)
+ {
+ if (VolDescs[i].IsJoliet())
+ {
+ MainVolDescIndex = i;
+ break;
+ }
+ }
+ // MainVolDescIndex = 0; // to read primary volume
+ if (VolDescs[MainVolDescIndex].LogicalBlockSize != kBlockSize)
+ return S_FALSE;
+ (CDirRecord &)_rootDir = VolDescs[MainVolDescIndex].RootDirRecord;
+ ReadDir(_rootDir, 0);
+ CreateRefs(_rootDir);
+ ReadBootInfo();
+ return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ _stream = inStream;
+ UInt64 pos;
+ RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &pos));
+ RINOK(_stream->Seek(0, STREAM_SEEK_END, &_archiveSize));
+ RINOK(_stream->Seek(pos, STREAM_SEEK_SET, &_position));
+ HRESULT res = S_FALSE;
+ try { res = Open2(); }
+ catch(...) { Clear(); res = S_FALSE; }
+ _stream.Release();
+ return res;
+}
+
+void CInArchive::Clear()
+{
+ Refs.Clear();
+ _rootDir.Clear();
+ VolDescs.Clear();
+ _bootIsDefined = false;
+ BootEntries.Clear();
+ SuspSkipSize = 0;
+ IsSusp = false;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Iso/IsoIn.h b/CPP/7zip/Archive/Iso/IsoIn.h
new file mode 100755
index 00000000..ab850bd9
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoIn.h
@@ -0,0 +1,301 @@
+// Archive/IsoIn.h
+
+#ifndef __ARCHIVE_ISO_IN_H
+#define __ARCHIVE_ISO_IN_H
+
+#include "Common/MyCom.h"
+#include "Common/IntToString.h"
+
+#include "../../IStream.h"
+
+#include "IsoItem.h"
+#include "IsoHeader.h"
+
+namespace NArchive {
+namespace NIso {
+
+struct CDir: public CDirRecord
+{
+ CDir *Parent;
+ CObjectVector<CDir> _subItems;
+
+ void Clear()
+ {
+ Parent = 0;
+ _subItems.Clear();
+ }
+
+ int GetLength(bool checkSusp, int skipSize) const
+ {
+ int len = GetLengthCur(checkSusp, skipSize);
+ if (Parent != 0)
+ if (Parent->Parent != 0)
+ len += 1 + Parent->GetLength(checkSusp, skipSize);
+ return len;
+ }
+
+ int GetLengthU() const
+ {
+ int len = (int)(FileId.GetCapacity() / 2);
+ if (Parent != 0)
+ if (Parent->Parent != 0)
+ len += 1 + Parent->GetLengthU();
+ return len;
+ }
+
+ AString GetPath(bool checkSusp, int skipSize) const
+ {
+ AString s;
+ int len = GetLength(checkSusp, skipSize);
+ char *p = s.GetBuffer(len + 1);
+ p += len;
+ *p = 0;
+ const CDir *cur = this;
+ for (;;)
+ {
+ int curLen = cur->GetLengthCur(checkSusp, skipSize);
+ p -= curLen;
+ memmove(p, (const char *)(const Byte *)cur->GetNameCur(checkSusp, skipSize), curLen);
+ cur = cur->Parent;
+ if (cur == 0)
+ break;
+ if (cur->Parent == 0)
+ break;
+ p--;
+ *p = CHAR_PATH_SEPARATOR;
+ }
+ s.ReleaseBuffer();
+ return s;
+ }
+
+ UString GetPathU() const
+ {
+ UString s;
+ int len = GetLengthU();
+ wchar_t *p = s.GetBuffer(len + 1);
+ p += len;
+ *p = 0;
+ const CDir *cur = this;
+ for (;;)
+ {
+ int curLen = (int)(cur->FileId.GetCapacity() / 2);
+ p -= curLen;
+ for (int i = 0; i < curLen; i++)
+ {
+ Byte b0 = ((const Byte *)cur->FileId)[i * 2];
+ Byte b1 = ((const Byte *)cur->FileId)[i * 2 + 1];
+ p[i] = (wchar_t)(((wchar_t)b0 << 8) | b1);
+ }
+ cur = cur->Parent;
+ if (cur == 0)
+ break;
+ if (cur->Parent == 0)
+ break;
+ p--;
+ *p = WCHAR_PATH_SEPARATOR;
+ }
+ s.ReleaseBuffer();
+ return s;
+ }
+};
+
+struct CDateTime
+{
+ UInt16 Year;
+ Byte Month;
+ Byte Day;
+ Byte Hour;
+ Byte Minute;
+ Byte Second;
+ Byte Hundredths;
+ signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
+ bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
+ Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
+};
+
+struct CBootRecordDescriptor
+{
+ Byte BootSystemId[32]; // a-characters
+ Byte BootId[32]; // a-characters
+ Byte BootSystemUse[1977];
+};
+
+struct CBootValidationEntry
+{
+ Byte PlatformId;
+ Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM.
+};
+
+struct CBootInitialEntry
+{
+ bool Bootable;
+ Byte BootMediaType;
+ UInt16 LoadSegment;
+ /* This is the load segment for the initial boot image. If this
+ value is 0 the system will use the traditional segment of 7C0. If this value
+ is non-zero the system will use the specified segment. This applies to x86
+ architectures only. For "flat" model architectures (such as Motorola) this
+ is the address divided by 10. */
+ Byte SystemType; // This must be a copy of byte 5 (System Type) from the
+ // Partition Table found in the boot image.
+ UInt16 SectorCount; // This is the number of virtual/emulated sectors the system
+ // will store at Load Segment during the initial boot procedure.
+ UInt32 LoadRBA; // This is the start address of the virtual disk. CD’s use
+ // Relative/Logical block addressing.
+
+ UInt64 GetSize() const
+ {
+ // if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
+ return SectorCount * 512;
+ }
+
+ UString GetName() const
+ {
+ UString s;
+ if (Bootable)
+ s += L"Bootable";
+ else
+ s += L"NotBootable";
+ s += L"_";
+ if (BootMediaType >= kNumBootMediaTypes)
+ {
+ wchar_t name[32];
+ ConvertUInt64ToString(BootMediaType, name);
+ s += name;
+ }
+ else
+ s += kMediaTypes[BootMediaType];
+ s += L".img";
+ return s;
+ }
+};
+
+struct CVolumeDescriptor
+{
+ Byte VolFlags;
+ Byte SystemId[32]; // a-characters. An identification of a system
+ // which can recognize and act upon the content of the Logical
+ // Sectors with logical Sector Numbers 0 to 15 of the volume.
+ Byte VolumeId[32]; // d-characters. An identification of the volume.
+ UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded
+ Byte EscapeSequence[32];
+ UInt16 VolumeSetSize;
+ UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member.
+ UInt16 LogicalBlockSize;
+ UInt32 PathTableSize;
+ UInt32 LPathTableLocation;
+ UInt32 LOptionalPathTableLocation;
+ UInt32 MPathTableLocation;
+ UInt32 MOptionalPathTableLocation;
+ CDirRecord RootDirRecord;
+ Byte VolumeSetId[128];
+ Byte PublisherId[128];
+ Byte DataPreparerId[128];
+ Byte ApplicationId[128];
+ Byte CopyrightFileId[37];
+ Byte AbstractFileId[37];
+ Byte BibFileId[37];
+ CDateTime CreationTime;
+ CDateTime ModificationTime;
+ CDateTime ExpirationTime;
+ CDateTime EffectiveTime;
+ Byte FileStructureVersion; // = 1;
+ Byte ApplicationUse[512];
+
+ bool IsJoliet() const
+ {
+ if ((VolFlags & 1) != 0)
+ return false;
+ Byte b = EscapeSequence[2];
+ return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&
+ (b == 0x40 || b == 0x43 || b == 0x45));
+ }
+};
+
+struct CRef
+{
+ CDir *Dir;
+ UInt32 Index;
+};
+
+const UInt32 kBlockSize = 1 << 11;
+
+class CInArchive
+{
+ CMyComPtr<IInStream> _stream;
+ UInt64 _position;
+
+ Byte m_Buffer[kBlockSize];
+ UInt32 m_BufferPos;
+
+ CDir _rootDir;
+ bool _bootIsDefined;
+ CBootRecordDescriptor _bootDesc;
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+ void Skeep(size_t size);
+ void SkeepZeros(size_t size);
+ Byte ReadByte();
+ void ReadBytes(Byte *data, UInt32 size);
+ UInt16 ReadUInt16Spec();
+ UInt16 ReadUInt16();
+ UInt32 ReadUInt32Le();
+ UInt32 ReadUInt32Be();
+ UInt32 ReadUInt32();
+ UInt64 ReadUInt64();
+ UInt32 ReadDigits(int numDigits);
+ void ReadDateTime(CDateTime &d);
+ void ReadRecordingDateTime(CRecordingDateTime &t);
+ void ReadDirRecord2(CDirRecord &r, Byte len);
+ void ReadDirRecord(CDirRecord &r);
+
+ void ReadBootRecordDescriptor(CBootRecordDescriptor &d);
+ void ReadVolumeDescriptor(CVolumeDescriptor &d);
+
+ void SeekToBlock(UInt32 blockIndex);
+ void ReadDir(CDir &d, int level);
+ void CreateRefs(CDir &d);
+
+ void ReadBootInfo();
+ HRESULT Open2();
+public:
+ HRESULT Open(IInStream *inStream);
+ void Clear();
+
+ UInt64 _archiveSize;
+
+ CRecordVector<CRef> Refs;
+ CObjectVector<CVolumeDescriptor> VolDescs;
+ int MainVolDescIndex;
+ UInt32 BlockSize;
+ CObjectVector<CBootInitialEntry> BootEntries;
+
+
+ bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }
+
+ UInt64 GetBootItemSize(int index) const
+ {
+ const CBootInitialEntry &be = BootEntries[index];
+ UInt64 size = be.GetSize();
+ if (be.BootMediaType == NBootMediaType::k1d2Floppy)
+ size = (1200 << 10);
+ else if (be.BootMediaType == NBootMediaType::k1d44Floppy)
+ size = (1440 << 10);
+ else if (be.BootMediaType == NBootMediaType::k2d88Floppy)
+ size = (2880 << 10);
+ UInt64 startPos = be.LoadRBA * BlockSize;
+ if (startPos < _archiveSize)
+ {
+ if (_archiveSize - startPos < size)
+ size = _archiveSize - startPos;
+ }
+ return size;
+ }
+
+ bool IsSusp;
+ int SuspSkipSize;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Iso/IsoItem.h b/CPP/7zip/Archive/Iso/IsoItem.h
new file mode 100755
index 00000000..14024d8d
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/IsoItem.h
@@ -0,0 +1,145 @@
+// Archive/IsoItem.h
+
+#ifndef __ARCHIVE_ISO_ITEM_H
+#define __ARCHIVE_ISO_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "Common/Buffer.h"
+
+#include "IsoHeader.h"
+
+namespace NArchive {
+namespace NIso {
+
+struct CRecordingDateTime
+{
+ Byte Year;
+ Byte Month;
+ Byte Day;
+ Byte Hour;
+ Byte Minute;
+ Byte Second;
+ signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
+
+ bool GetFileTime(FILETIME &ft) const
+ {
+ SYSTEMTIME st;
+ st.wYear = (WORD)(Year + 1900);
+ st.wMonth = Month;
+ st.wDayOfWeek = 0; // check it
+ st.wDay = Day;
+ st.wHour = Hour;
+ st.wMinute = Minute;
+ st.wSecond = Second;
+ st.wMilliseconds = 0;
+ if (!SystemTimeToFileTime(&st, &ft))
+ return false;
+ UInt64 value = (((UInt64)ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
+ value += (UInt64)((Int64)(int)GmtOffset * 15 * 60);
+ ft.dwLowDateTime = (DWORD)value;
+ ft.dwHighDateTime = DWORD(value >> 32);
+ return true;
+ }
+};
+
+struct CDirRecord
+{
+ Byte ExtendedAttributeRecordLen;
+ UInt32 ExtentLocation;
+ UInt32 DataLength;
+ CRecordingDateTime DateTime;
+ Byte FileFlags;
+ Byte FileUnitSize;
+ Byte InterleaveGapSize;
+ UInt16 VolSequenceNumber;
+ CByteBuffer FileId;
+ CByteBuffer SystemUse;
+
+ bool IsDir() const { return (FileFlags & NFileFlags::kDirectory) != 0; }
+ bool IsSystemItem() const
+ {
+ if (FileId.GetCapacity() != 1)
+ return false;
+ Byte b = *(const Byte *)FileId;
+ return (b == 0 || b == 1);
+ }
+
+ const Byte* FindSuspName(int skipSize, int &lenRes) const
+ {
+ lenRes = 0;
+ const Byte *p = (const Byte *)SystemUse + skipSize;
+ int length = (int)(SystemUse.GetCapacity() - skipSize);
+ while (length >= 5)
+ {
+ int len = p[2];
+ if (p[0] == 'N' && p[1] == 'M' && p[3] == 1)
+ {
+ lenRes = len - 5;
+ return p + 5;
+ }
+ p += len;
+ length -= len;
+ }
+ return 0;
+ }
+
+ int GetLengthCur(bool checkSusp, int skipSize) const
+ {
+ if (checkSusp)
+ {
+ int len;
+ const Byte *res = FindSuspName(skipSize, len);
+ if (res != 0)
+ return len;
+ }
+ return (int)FileId.GetCapacity();
+ }
+
+ const Byte* GetNameCur(bool checkSusp, int skipSize) const
+ {
+ if (checkSusp)
+ {
+ int len;
+ const Byte *res = FindSuspName(skipSize, len);
+ if (res != 0)
+ return res;
+ }
+ return (const Byte *)FileId;
+ }
+
+
+ bool CheckSusp(const Byte *p, int &startPos) const
+ {
+ if (p[0] == 'S' &&
+ p[1] == 'P' &&
+ p[2] == 0x7 &&
+ p[3] == 0x1 &&
+ p[4] == 0xBE &&
+ p[5] == 0xEF)
+ {
+ startPos = p[6];
+ return true;
+ }
+ return false;
+ }
+
+ bool CheckSusp(int &startPos) const
+ {
+ const Byte *p = (const Byte *)SystemUse;
+ int length = (int)SystemUse.GetCapacity();
+ const int kMinLen = 7;
+ if (length < kMinLen)
+ return false;
+ if (CheckSusp(p, startPos))
+ return true;
+ const int kOffset2 = 14;
+ if (length < kOffset2 + kMinLen)
+ return false;
+ return CheckSusp(p + kOffset2, startPos);
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Iso/StdAfx.cpp b/CPP/7zip/Archive/Iso/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Iso/StdAfx.h b/CPP/7zip/Archive/Iso/StdAfx.h
new file mode 100755
index 00000000..2e4be10b
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/Archive/Iso/makefile b/CPP/7zip/Archive/Iso/makefile
new file mode 100755
index 00000000..100a3cd0
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/makefile
@@ -0,0 +1,55 @@
+PROG = iso.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+TAR_OBJS = \
+ $O\DllExports.obj \
+ $O\IsoHandler.obj \
+ $O\IsoHeader.obj \
+ $O\IsoIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\LimitedStreams.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(TAR_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_TAR_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(TAR_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Iso/resource.rc b/CPP/7zip/Archive/Iso/resource.rc
new file mode 100755
index 00000000..86929b0e
--- /dev/null
+++ b/CPP/7zip/Archive/Iso/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Iso Plugin", "iso")
+
+101 ICON "iso.ico"
diff --git a/CPP/7zip/Archive/Lzh/DllExports.cpp b/CPP/7zip/Archive/Lzh/DllExports.cpp
new file mode 100755
index 00000000..c2b30945
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/DllExports.cpp
@@ -0,0 +1,72 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "LzhHandler.h"
+
+// {23170F69-40C1-278A-1000-000110060000}
+DEFINE_GUID(CLSID_CLzhHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x06, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CLzhHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NLzh::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Lzh";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CLzhHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"lzh lha";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const unsigned char sig[] = { '-', 'l' };
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 2)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Lzh/Lzh.def b/CPP/7zip/Archive/Lzh/Lzh.def
new file mode 100755
index 00000000..e240b3f2
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/Lzh.def
@@ -0,0 +1,7 @@
+; Arj.def
+
+LIBRARY Arj.dll
+
+EXPORTS
+ CreateObject PRIVATE
+ GetHandlerProperty PRIVATE
diff --git a/CPP/7zip/Archive/Lzh/Lzh.dsp b/CPP/7zip/Archive/Lzh/Lzh.dsp
new file mode 100755
index 00000000..ad00699c
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/Lzh.dsp
@@ -0,0 +1,333 @@
+# Microsoft Developer Studio Project File - Name="Lzh" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Lzh - 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 "lzh.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 "lzh.mak" CFG="Lzh - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Lzh - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Lzh - 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)" == "Lzh - 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 "ARJ_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARJ_EXPORTS" /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 0x419 /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\lzh.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Lzh - 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 "ARJ_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ARJ_EXPORTS" /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 0x419 /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\lzh.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Lzh - Win32 Release"
+# Name "Lzh - 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\Buffer.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\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\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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\LzhCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhCRC.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhOutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\LzhOutStreamWithCRC.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# PROP Default_Filter ""
+# Begin Group "Codecs"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzh\LzhDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Lzh\LzhDecoder.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
+# 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 "Huffman"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Huffman\HuffmanDecoder.h
+# End Source File
+# End Group
+# 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\MSBFDecoder.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\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.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 "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\lzh.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Lzh/Lzh.dsw b/CPP/7zip/Archive/Lzh/Lzh.dsw
new file mode 100755
index 00000000..41ab2218
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/Lzh.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "lzh"=.\lzh.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Lzh/LzhCRC.cpp b/CPP/7zip/Archive/Lzh/LzhCRC.cpp
new file mode 100755
index 00000000..ca1235bb
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhCRC.cpp
@@ -0,0 +1,43 @@
+// LzhCRC.cpp
+
+#include "StdAfx.h"
+
+#include "LzhCRC.h"
+
+namespace NArchive {
+namespace NLzh {
+
+static const UInt16 kCRCPoly = 0xA001;
+
+UInt16 CCRC::Table[256];
+
+void CCRC::InitTable()
+{
+ for (UInt32 i = 0; i < 256; i++)
+ {
+ UInt32 r = i;
+ for (int j = 0; j < 8; j++)
+ if (r & 1)
+ r = (r >> 1) ^ kCRCPoly;
+ else
+ r >>= 1;
+ CCRC::Table[i] = (UInt16)r;
+ }
+}
+
+class CCRCTableInit
+{
+public:
+ CCRCTableInit() { CCRC::InitTable(); }
+} g_CRCTableInit;
+
+void CCRC::Update(const void *data, size_t size)
+{
+ UInt16 v = _value;
+ const Byte *p = (const Byte *)data;
+ for (; size > 0; size--, p++)
+ v = (UInt16)(Table[((Byte)(v)) ^ *p] ^ (v >> 8));
+ _value = v;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Lzh/LzhCRC.h b/CPP/7zip/Archive/Lzh/LzhCRC.h
new file mode 100755
index 00000000..e49d649c
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhCRC.h
@@ -0,0 +1,27 @@
+// LzhCRC.h
+
+#ifndef __LZH_CRC_H
+#define __LZH_CRC_H
+
+#include <stddef.h>
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NLzh {
+
+class CCRC
+{
+ UInt16 _value;
+public:
+ static UInt16 Table[256];
+ static void InitTable();
+
+ CCRC(): _value(0){};
+ void Init() { _value = 0; }
+ void Update(const void *data, size_t size);
+ UInt16 GetDigest() const { return _value; }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Lzh/LzhHandler.cpp b/CPP/7zip/Archive/Lzh/LzhHandler.cpp
new file mode 100755
index 00000000..03af11d1
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhHandler.cpp
@@ -0,0 +1,464 @@
+// LzhHandler.cpp
+
+#include "StdAfx.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+
+#include "Windows/Time.h"
+#include "Windows/PropVariant.h"
+
+#include "LzhHandler.h"
+#include "LzhOutStreamWithCRC.h"
+
+#include "../../ICoder.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../../Compress/Lzh/LzhDecoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NLzh{
+
+struct COsPair
+{
+ Byte Id;
+ const wchar_t *Name;
+};
+
+COsPair g_OsPairs[] =
+{
+ { 'M', L"MS-DOS" },
+ { '2', L"OS/2" },
+ { '9', L"OS9" },
+ { 'K', L"OS/68K" },
+ { '3', L"OS/386" },
+ { 'H', L"HUMAN" },
+ { 'U', L"UNIX" },
+ { 'C', L"CP/M" },
+ { 'F', L"FLEX" },
+ { 'm', L"Mac" },
+ { 'R', L"Runser" },
+ { 'T', L"TownsOS" },
+ { 'X', L"XOSK" },
+ { 'w', L"Windows95" },
+ { 'W', L"WindowsNT" },
+ { 0, L"MS-DOS" },
+ { 'J', L"Java VM" }
+};
+
+const wchar_t *kUnknownOS = L"Unknown";
+
+const int kNumHostOSes = sizeof(g_OsPairs) / sizeof(g_OsPairs[0]);
+
+static const wchar_t *GetOS(Byte osId)
+{
+ for (int i = 0; i < kNumHostOSes; i++)
+ if (g_OsPairs[i].Id == osId)
+ return g_OsPairs[i].Name;
+ return kUnknownOS;
+};
+
+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, kpidCommented, VT_BOOL},
+
+ { NULL, kpidCRC, VT_UI4},
+
+ { NULL, kpidMethod, VT_UI1},
+ { NULL, kpidHostOS, VT_BSTR}
+
+};
+
+
+CHandler::CHandler()
+{}
+
+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 = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ const CItemEx &item = _items[index];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP));
+ if (!s.IsEmpty())
+ {
+ if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR)
+ s.Delete(s.Length() - 1);
+ propVariant = s;
+ }
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = item.Size;
+ break;
+ case kpidPackedSize:
+ propVariant = item.PackSize;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME utcFileTime;
+ UInt32 unixTime;
+ if (item.GetUnixTime(unixTime))
+ {
+ NTime::UnixTimeToFileTime(unixTime, utcFileTime);
+ }
+ else
+ {
+ FILETIME localFileTime;
+ if (DosTimeToFileTime(item.ModifiedTime, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ propVariant = utcFileTime;
+ break;
+ }
+ /*
+ case kpidAttributes:
+ propVariant = (UInt32)item.Attributes;
+ break;
+ case kpidCommented:
+ propVariant = item.IsCommented();
+ break;
+ */
+ case kpidCRC:
+ propVariant = (UInt32)item.CRC;
+ break;
+ case kpidMethod:
+ {
+ wchar_t method2[kMethodIdSize + 1];
+ method2[kMethodIdSize] = 0;
+ for (int i = 0; i < kMethodIdSize; i++)
+ method2[i] = item.Method[i];
+ propVariant = method2;
+ break;
+ }
+ case kpidHostOS:
+ propVariant = GetOS(item.OsId);
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+class CPropgressImp: public CProgressVirt
+{
+public:
+ CMyComPtr<IArchiveOpenCallback> Callback;
+ STDMETHOD(SetCompleted)(const UInt64 *numFiles);
+};
+
+STDMETHODIMP CPropgressImp::SetCompleted(const UInt64 *numFiles)
+{
+ if (Callback)
+ return Callback->SetCompleted(numFiles, NULL);
+ return S_OK;
+}
+*/
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback)
+{
+ COM_TRY_BEGIN
+ try
+ {
+ _items.Clear();
+ CInArchive archive;
+ RINOK(archive.Open(inStream));
+ if (callback != NULL)
+ {
+ RINOK(callback->SetTotal(NULL, NULL));
+ UInt64 numFiles = _items.Size();
+ RINOK(callback->SetCompleted(&numFiles, NULL));
+ }
+ for (;;)
+ {
+ CItemEx itemInfo;
+ bool filled;
+ HRESULT result = archive.GetNextItem(filled, itemInfo);
+ if (result == S_FALSE)
+ return S_FALSE;
+ if (result != S_OK)
+ return S_FALSE;
+ if (!filled)
+ break;
+ _items.Add(itemInfo);
+ archive.Skeep(itemInfo.PackSize);
+ if (callback != NULL)
+ {
+ UInt64 numFiles = _items.Size();
+ RINOK(callback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ if (_items.IsEmpty())
+ return S_FALSE;
+
+ _stream = inStream;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ COM_TRY_END
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _items.Clear();
+ _stream.Release();
+ return S_OK;
+}
+
+
+
+//////////////////////////////////////
+// CHandler::DecompressItems
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool testMode = (testModeSpec != 0);
+ UInt64 totalUnPacked = 0, totalPacked = 0;
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = _items.Size();
+ if(numItems == 0)
+ return S_OK;
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ {
+ const CItemEx &itemInfo = _items[allFilesMode ? i : indices[i]];
+ totalUnPacked += itemInfo.Size;
+ totalPacked += itemInfo.PackSize;
+ }
+ extractCallback->SetTotal(totalUnPacked);
+
+ UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0;
+ UInt64 currentItemUnPacked, currentItemPacked;
+
+ NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0;
+ CMyComPtr<ICompressCoder> lzhDecoder;
+ CMyComPtr<ICompressCoder> lzh1Decoder;
+ CMyComPtr<ICompressCoder> arj2Decoder;
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ 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 &itemInfo = _items[index];
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ if(itemInfo.IsDirectory())
+ {
+ // if (!testMode)
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ continue;
+ }
+
+ if (!testMode && (!realOutStream))
+ continue;
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+ currentItemUnPacked = itemInfo.Size;
+ currentItemPacked = itemInfo.PackSize;
+
+ {
+ COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->Init(realOutStream);
+ realOutStream.Release();
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+
+ UInt64 pos;
+ _stream->Seek(itemInfo.DataPosition, STREAM_SEEK_SET, &pos);
+
+ streamSpec->SetStream(_stream);
+ streamSpec->Init(itemInfo.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);
+
+ HRESULT result;
+
+ if (itemInfo.IsCopyMethod())
+ {
+ if(!copyCoder)
+ copyCoder = new NCompress::CCopyCoder;
+ try
+ {
+ result = copyCoder->Code(inStream, outStream, NULL, NULL, 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;
+ }
+ }
+ else if (itemInfo.IsLh4GroupMethod())
+ {
+ if(!lzhDecoder)
+ {
+ lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder;
+ lzhDecoder = lzhDecoderSpec;
+ }
+ try
+ {
+ lzhDecoderSpec->SetDictionary(itemInfo.GetNumDictBits());
+ result = lzhDecoder->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;
+ }
+ }
+ /*
+ else if (itemInfo.IsLh1GroupMethod())
+ {
+ if(!lzh1Decoder)
+ {
+ lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder;
+ lzh1Decoder = lzh1DecoderSpec;
+ }
+ try
+ {
+ lzh1DecoderSpec->SetDictionary(itemInfo.GetNumDictBits());
+ result = lzh1Decoder->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;
+ }
+ }
+ */
+ else
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+
+ bool crcOK = (outStreamSpec->GetCRC() == itemInfo.CRC);
+ outStream.Release();
+ if(crcOK)
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK))
+ else
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kCRCError))
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+
+}}
diff --git a/CPP/7zip/Archive/Lzh/LzhHandler.h b/CPP/7zip/Archive/Lzh/LzhHandler.h
new file mode 100755
index 00000000..2dc89494
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhHandler.h
@@ -0,0 +1,47 @@
+// LzhHandler.h
+
+#ifndef __LZH_HANDLER_H
+#define __LZH_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+#include "LzhIn.h"
+
+namespace NArchive {
+namespace NLzh {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *inStream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *callback);
+ 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);
+
+ CHandler();
+private:
+ CObjectVector<CItemEx> _items;
+ CMyComPtr<IInStream> _stream;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Lzh/LzhHeader.h b/CPP/7zip/Archive/Lzh/LzhHeader.h
new file mode 100755
index 00000000..845b9a21
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhHeader.h
@@ -0,0 +1,19 @@
+// Archive/Lzh/Header.h
+
+#ifndef __ARCHIVE_LZH_HEADER_H
+#define __ARCHIVE_LZH_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NLzh {
+
+const int kMethodIdSize = 5;
+
+const Byte kExtIdFileName = 0x01;
+const Byte kExtIdDirName = 0x02;
+const Byte kExtIdUnixTime = 0x54;
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Lzh/LzhIn.cpp b/CPP/7zip/Archive/Lzh/LzhIn.cpp
new file mode 100755
index 00000000..42ef50e4
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhIn.cpp
@@ -0,0 +1,171 @@
+// Archive/arj/InEngine.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/Buffer.h"
+#include "Common/CRC.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "LzhIn.h"
+
+namespace NArchive {
+namespace NLzh {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ RINOK(ReadStream(m_Stream, data, size, &processedSize));
+ m_Position += processedSize;
+ return S_OK;
+}
+
+HRESULT CInArchive::CheckReadBytes(void *data, UInt32 size)
+{
+ UInt32 processedSize;
+ RINOK(ReadBytes(data, size, processedSize));
+ return (processedSize == size) ? S_OK: S_FALSE;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+ m_Stream = inStream;
+ return S_OK;
+}
+
+static const Byte *ReadUInt32(const Byte *p, UInt32 &v)
+{
+ v = 0;
+ for (int i = 0; i < 4; i++)
+ v |= ((UInt32)(*p++) << (i * 8));
+ return p;
+}
+
+static const Byte *ReadUInt16(const Byte *p, UInt16 &v)
+{
+ v = 0;
+ for (int i = 0; i < 2; i++)
+ v |= ((UInt16)(*p++) << (i * 8));
+ return p;
+}
+
+static const Byte *ReadString(const Byte *p, size_t size, AString &s)
+{
+ s.Empty();
+ for (size_t i = 0; i < size; i++)
+ {
+ char c = p[i];
+ if (c == 0)
+ break;
+ s += c;
+ }
+ return p + size;
+}
+
+static Byte CalcSum(const Byte *data, size_t size)
+{
+ Byte sum = 0;
+ for (size_t i = 0; i < size; i++)
+ sum = (Byte)(sum + data[i]);
+ return sum;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+ filled = false;
+
+ UInt32 processedSize;
+ Byte startHeader[2];
+ RINOK(ReadBytes(startHeader, 2, processedSize))
+ if (processedSize == 0)
+ return S_OK;
+ if (processedSize == 1)
+ return (startHeader[0] == 0) ? S_OK: S_FALSE;
+ if (startHeader[0] == 0 && startHeader[1] == 0)
+ return S_OK;
+
+ Byte header[256];
+ const UInt32 kBasicPartSize = 22;
+ RINOK(ReadBytes(header, kBasicPartSize, processedSize));
+ if (processedSize != kBasicPartSize)
+ return (startHeader[0] == 0) ? S_OK: S_FALSE;
+
+ const Byte *p = header;
+ memmove(item.Method, p, kMethodIdSize);
+ if (!item.IsValidMethod())
+ return S_OK;
+ p += kMethodIdSize;
+ p = ReadUInt32(p, item.PackSize);
+ p = ReadUInt32(p, item.Size);
+ p = ReadUInt32(p, item.ModifiedTime);
+ item.Attributes = *p++;
+ item.Level = *p++;
+ if (item.Level > 2)
+ return S_FALSE;
+ UInt32 headerSize;
+ if (item.Level < 2)
+ {
+ headerSize = startHeader[0];
+ if (headerSize < kBasicPartSize)
+ return S_FALSE;
+ UInt32 remain = headerSize - kBasicPartSize;
+ RINOK(CheckReadBytes(header + kBasicPartSize, remain));
+ if (startHeader[1] != CalcSum(header, headerSize))
+ return S_FALSE;
+ size_t nameLength = *p++;
+ if ((p - header) + nameLength + 2 > headerSize)
+ return S_FALSE;
+ p = ReadString(p, nameLength, item.Name);
+ }
+ else
+ headerSize = startHeader[0] | ((UInt32)startHeader[1] << 8);
+ p = ReadUInt16(p, item.CRC);
+ if (item.Level != 0)
+ {
+ if (item.Level == 2)
+ {
+ RINOK(CheckReadBytes(header + kBasicPartSize, 2));
+ }
+ if ((size_t)(p - header) + 3 > headerSize)
+ return S_FALSE;
+ item.OsId = *p++;
+ UInt16 nextSize;
+ p = ReadUInt16(p, nextSize);
+ while (nextSize != 0)
+ {
+ if (nextSize < 3)
+ return S_FALSE;
+ if (item.Level == 1)
+ {
+ if (item.PackSize < nextSize)
+ return S_FALSE;
+ item.PackSize -= nextSize;
+ }
+ CExtension ext;
+ RINOK(CheckReadBytes(&ext.Type, 1))
+ nextSize -= 3;
+ ext.Data.SetCapacity(nextSize);
+ RINOK(CheckReadBytes((Byte *)ext.Data, nextSize))
+ item.Extensions.Add(ext);
+ Byte hdr2[2];
+ RINOK(CheckReadBytes(hdr2, 2));
+ ReadUInt16(hdr2, nextSize);
+ }
+ }
+ item.DataPosition = m_Position;
+ filled = true;
+ return S_OK;
+}
+
+HRESULT CInArchive::Skeep(UInt64 numBytes)
+{
+ UInt64 newPostion;
+ RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+ m_Position += numBytes;
+ if (m_Position != newPostion)
+ return E_FAIL;
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Lzh/LzhIn.h b/CPP/7zip/Archive/Lzh/LzhIn.h
new file mode 100755
index 00000000..344a133f
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhIn.h
@@ -0,0 +1,29 @@
+// Archive/LzhIn.h
+
+#ifndef __ARCHIVE_LZHIN_H
+#define __ARCHIVE_LZHIN_H
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+
+#include "LzhItem.h"
+
+namespace NArchive {
+namespace NLzh {
+
+class CInArchive
+{
+ CMyComPtr<IInStream> m_Stream;
+ UInt64 m_Position;
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+ HRESULT CheckReadBytes(void *data, UInt32 size);
+public:
+ HRESULT Open(IInStream *inStream);
+ HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
+ HRESULT Skeep(UInt64 numBytes);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Lzh/LzhItem.h b/CPP/7zip/Archive/Lzh/LzhItem.h
new file mode 100755
index 00000000..66d4ed75
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhItem.h
@@ -0,0 +1,172 @@
+// Archive/LzhItem.h
+
+#ifndef __ARCHIVE_LZH_ITEM_H
+#define __ARCHIVE_LZH_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+#include "Common/Buffer.h"
+#include "LzhHeader.h"
+
+namespace NArchive {
+namespace NLzh {
+
+struct CExtension
+{
+ Byte Type;
+ CByteBuffer Data;
+ AString GetString() const
+ {
+ AString s;
+ for (size_t i = 0; i < Data.GetCapacity(); i++)
+ {
+ char c = (char)Data[i];
+ if (c == 0)
+ break;
+ s += c;
+ }
+ return s;
+ }
+};
+
+struct CItem
+{
+public:
+ AString Name;
+ Byte Method[kMethodIdSize];
+ UInt32 PackSize;
+ UInt32 Size;
+ UInt32 ModifiedTime;
+ Byte Attributes;
+ Byte Level;
+ UInt16 CRC;
+ Byte OsId;
+ CObjectVector<CExtension> Extensions;
+
+ bool IsValidMethod() const { return (Method[0] == '-' && Method[1] == 'l' && Method[4] == '-'); }
+ bool IsLhMethod() const {return (IsValidMethod() && Method[2] == 'h'); }
+ bool IsDirectory() const {return (IsLhMethod() && Method[3] == 'd'); }
+
+ bool IsCopyMethod() const
+ {
+ return (IsLhMethod() && Method[3] == '0') ||
+ (IsValidMethod() && Method[2] == 'z' && Method[3] == '4');
+ }
+
+ bool IsLh1GroupMethod() const
+ {
+ if (!IsLhMethod())
+ return false;
+ switch(Method[3])
+ {
+ case '1':
+ return true;
+ }
+ return false;
+ }
+
+ bool IsLh4GroupMethod() const
+ {
+ if (!IsLhMethod())
+ return false;
+ switch(Method[3])
+ {
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ return true;
+ }
+ return false;
+ }
+
+ int GetNumDictBits() const
+ {
+ if (!IsLhMethod())
+ return 0;
+ switch(Method[3])
+ {
+ case '1':
+ return 12;
+ case '2':
+ return 13;
+ case '3':
+ return 13;
+ case '4':
+ return 12;
+ case '5':
+ return 13;
+ case '6':
+ return 15;
+ case '7':
+ return 16;
+ }
+ return 0;
+ }
+
+ int FindExt(Byte type) const
+ {
+ for (int i = 0; i < Extensions.Size(); i++)
+ if (Extensions[i].Type == type)
+ return i;
+ return -1;
+ }
+ bool GetUnixTime(UInt32 &value) const
+ {
+ int index = FindExt(kExtIdUnixTime);
+ if (index < 0)
+ {
+ if (Level == 2)
+ {
+ value = ModifiedTime;
+ return true;
+ }
+ return false;
+ }
+ const Byte *data = (const Byte *)(Extensions[index].Data);
+ value = data[0] |
+ ((UInt32)data[1] << 8) |
+ ((UInt32)data[2] << 16) |
+ ((UInt32)data[3] << 24);
+ return true;
+ }
+
+ AString GetDirName() const
+ {
+ int index = FindExt(kExtIdDirName);
+ if (index < 0)
+ return AString();
+ return Extensions[index].GetString();
+ }
+
+ AString GetFileName() const
+ {
+ int index = FindExt(kExtIdFileName);
+ if (index < 0)
+ return Name;
+ return Extensions[index].GetString();
+ }
+
+ AString GetName() const
+ {
+ AString dirName = GetDirName();
+ dirName.Replace((char)(unsigned char)0xFF, '\\');
+ if (!dirName.IsEmpty())
+ {
+ char c = dirName[dirName.Length() - 1];
+ if (c != '\\')
+ dirName += '\\';
+ }
+ return dirName + GetFileName();
+ }
+};
+
+class CItemEx: public CItem
+{
+public:
+ UInt64 DataPosition;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp
new file mode 100755
index 00000000..2281a884
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.cpp
@@ -0,0 +1,27 @@
+// LzhOutStreamWithCRC.cpp
+
+#include "StdAfx.h"
+
+#include "LzhOutStreamWithCRC.h"
+
+namespace NArchive {
+namespace NLzh {
+
+STDMETHODIMP COutStreamWithCRC::Write(const void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result;
+ if(!_stream)
+ {
+ realProcessedSize = size;
+ result = S_OK;
+ }
+ else
+ result = _stream->Write(data, size, &realProcessedSize);
+ _crc.Update(data, realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ return result;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h
new file mode 100755
index 00000000..31b536b7
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/LzhOutStreamWithCRC.h
@@ -0,0 +1,38 @@
+// LzhOutStreamWithCRC.h
+
+#ifndef __LZHOUTSTREAMWITHCRC_H
+#define __LZHOUTSTREAMWITHCRC_H
+
+#include "LzhCRC.h"
+#include "../../../Common/MyCom.h"
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NLzh {
+
+class COutStreamWithCRC:
+ public ISequentialOutStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
+private:
+ CCRC _crc;
+ CMyComPtr<ISequentialOutStream> _stream;
+public:
+ void Init(ISequentialOutStream *stream)
+ {
+ _stream = stream;
+ _crc.Init();
+ }
+ void ReleaseStream() { _stream.Release(); }
+ UInt32 GetCRC() const { return _crc.GetDigest(); }
+ void InitCRC() { _crc.Init(); }
+
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Lzh/StdAfx.cpp b/CPP/7zip/Archive/Lzh/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Lzh/StdAfx.h b/CPP/7zip/Archive/Lzh/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/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/Lzh/lzh.ico b/CPP/7zip/Archive/Lzh/lzh.ico
new file mode 100755
index 00000000..84dab49c
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/lzh.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Lzh/makefile b/CPP/7zip/Archive/Lzh/makefile
new file mode 100755
index 00000000..6f8fd2a0
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/makefile
@@ -0,0 +1,65 @@
+PROG = lzh.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+LZH_OBJS = \
+ $O\DllExports.obj \
+ $O\LzhCRC.obj \
+ $O\LzhHandler.obj \
+ $O\LzhIn.obj \
+ $O\LzhOutStreamWithCRC.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\InBuffer.obj \
+ $O\LimitedStreams.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+COMPRESS_LZH_OBJS = \
+ $O\LzhDecoder.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(LZH_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_LZH_OBJS) \
+ $O\CopyCoder.obj \
+ $O\LZOutWindow.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(LZH_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)
+$(COMPRESS_LZH_OBJS): ../../Compress/Lzh/$(*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/Lzh/resource.rc b/CPP/7zip/Archive/Lzh/resource.rc
new file mode 100755
index 00000000..2870e520
--- /dev/null
+++ b/CPP/7zip/Archive/Lzh/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Lzh Plugin", "lzh")
+
+101 ICON "lzh.ico"
diff --git a/CPP/7zip/Archive/Nsis/DllExports.cpp b/CPP/7zip/Archive/Nsis/DllExports.cpp
new file mode 100755
index 00000000..f10f56ea
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/DllExports.cpp
@@ -0,0 +1,110 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "NsisHandler.h"
+
+// {23170F69-40C1-278A-1000-000110090000}
+DEFINE_GUID(CLSID_CNsisHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x09, 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
+
+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_CNsisHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ // int needOut = *interfaceID == IID_IOutArchive;
+ if (needIn /*|| needOut */)
+ {
+ NArchive::NNsis::CHandler *temp = new NArchive::NNsis::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"Nsis";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CNsisHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"exe";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)NArchive::NNsis::kSignature,
+ NArchive::NNsis::kSignatureSize)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kAssociate:
+ {
+ propVariant = false;
+ break;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Nsis/Nsis.dsp b/CPP/7zip/Archive/Nsis/Nsis.dsp
new file mode 100755
index 00000000..45ce0386
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/Nsis.dsp
@@ -0,0 +1,337 @@
+# Microsoft Developer Studio Project File - Name="Nsis" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Nsis - 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 "Nsis.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 "Nsis.mak" CFG="Nsis - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Nsis - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Nsis - 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)" == "Nsis - 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 "TAR_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /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 0x419 /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\nsis.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Nsis - 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 "TAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /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 0x419 /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\nsis.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Nsis - Win32 Release"
+# Name "Nsis - 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=.\Nsis.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\resource.rc
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# 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\Buffer.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\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\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
+# End Group
+# Begin Group "Compress"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\NsisDecode.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NsisDecode.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\NsisHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NsisHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\NsisIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\NsisIn.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\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.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\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 "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
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Nsis/Nsis.dsw b/CPP/7zip/Archive/Nsis/Nsis.dsw
new file mode 100755
index 00000000..d3df6d27
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/Nsis.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Nsis"=.\Nsis.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.cpp b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
new file mode 100755
index 00000000..d49b2312
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.cpp
@@ -0,0 +1,150 @@
+// NsisDecode.cpp
+
+#include "StdAfx.h"
+
+#include "NsisDecode.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "../7z/7zMethods.h"
+
+namespace NArchive {
+namespace NNsis {
+
+static const N7z::CMethodID k_Copy = { { 0x0 }, 1 };
+static const N7z::CMethodID k_Deflate = { { 0x4, 0x9, 0x1 }, 3 };
+static const N7z::CMethodID k_BZip2 = { { 0x4, 0x9, 0x2 }, 3 };
+static const N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };
+static const N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };
+
+CDecoder::CDecoder()
+{
+ N7z::LoadMethodMap();
+}
+
+HRESULT CDecoder::Init(IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter)
+{
+ useFilter = false;
+ CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
+
+ if (_decoderInStream)
+ if (method != _method)
+ Release();
+ _method = method;
+ if (!_codecInStream)
+ {
+ const NArchive::N7z::CMethodID *methodID = 0;
+ switch (method)
+ {
+ case NMethodType::kCopy:
+ methodID = &k_Copy;
+ break;
+ case NMethodType::kDeflate:
+ methodID = &k_Deflate;
+ break;
+ case NMethodType::kBZip2:
+ methodID = &k_BZip2;
+ break;
+ case NMethodType::kLZMA:
+ methodID = &k_LZMA;
+ break;
+ default:
+ return E_NOTIMPL;
+ }
+ N7z::CMethodInfo methodInfo;
+ if (!N7z::GetMethodInfo(*methodID, methodInfo))
+ return E_NOTIMPL;
+ CMyComPtr<ICompressCoder> coder;
+ RINOK(_libraries.CreateCoder(methodInfo.FilePath, methodInfo.Decoder, &coder));
+ coder.QueryInterface(IID_ISequentialInStream, &_codecInStream);
+ if (!_codecInStream)
+ return E_NOTIMPL;
+ }
+
+ if (thereIsFilterFlag)
+ {
+ UInt32 processedSize;
+ BYTE flag;
+ RINOK(inStream->Read(&flag, 1, &processedSize));
+ if (processedSize != 1)
+ return E_FAIL;
+ if (flag > 1)
+ return E_NOTIMPL;
+ useFilter = (flag != 0);
+ }
+
+ if (useFilter)
+ {
+ if (!_filterInStream)
+ {
+ N7z::CMethodInfo methodInfo;
+ if (!N7z::GetMethodInfo(k_BCJ_X86, methodInfo))
+ return E_NOTIMPL;
+ CMyComPtr<ICompressCoder> coder;
+ RINOK(_libraries.CreateCoderSpec(methodInfo.FilePath, methodInfo.Decoder, &coder));
+ coder.QueryInterface(IID_ISequentialInStream, &_filterInStream);
+ if (!_filterInStream)
+ return E_NOTIMPL;
+ }
+ CMyComPtr<ICompressSetInStream> setInStream;
+ _filterInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
+ if (!setInStream)
+ return E_NOTIMPL;
+ RINOK(setInStream->SetInStream(_codecInStream));
+ _decoderInStream = _filterInStream;
+ }
+ else
+ _decoderInStream = _codecInStream;
+
+ if (method == NMethodType::kLZMA)
+ {
+ CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
+ _codecInStream.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ if (setDecoderProperties)
+ {
+ static const UInt32 kPropertiesSize = 5;
+ BYTE properties[kPropertiesSize];
+ UInt32 processedSize;
+ RINOK(inStream->Read(properties, kPropertiesSize, &processedSize));
+ if (processedSize != kPropertiesSize)
+ return E_FAIL;
+ RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)properties, kPropertiesSize));
+ }
+ }
+
+ {
+ CMyComPtr<ICompressSetInStream> setInStream;
+ _codecInStream.QueryInterface(IID_ICompressSetInStream, &setInStream);
+ if (!setInStream)
+ return E_NOTIMPL;
+ RINOK(setInStream->SetInStream(inStream));
+ }
+
+ {
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ _codecInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+ if (!setOutStreamSize)
+ return E_NOTIMPL;
+ RINOK(setOutStreamSize->SetOutStreamSize(NULL));
+ }
+
+ if (useFilter)
+ {
+ /*
+ CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize;
+ _filterInStream.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize);
+ if (!setOutStreamSize)
+ return E_NOTIMPL;
+ RINOK(setOutStreamSize->SetOutStreamSize(NULL));
+ */
+ }
+
+ return S_OK;
+}
+
+HRESULT CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ return ReadStream(_decoderInStream, data, size, processedSize);;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Nsis/NsisDecode.h b/CPP/7zip/Archive/Nsis/NsisDecode.h
new file mode 100755
index 00000000..1bec178f
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/NsisDecode.h
@@ -0,0 +1,47 @@
+// NsisDecode.h
+
+#ifndef __NSIS_DECODE_H
+#define __NSIS_DECODE_H
+
+#include "../../IStream.h"
+
+#include "../Common/CoderLoader.h"
+
+namespace NArchive {
+namespace NNsis {
+
+namespace NMethodType
+{
+ enum EEnum
+ {
+ kCopy,
+ kDeflate,
+ kBZip2,
+ kLZMA
+ };
+}
+
+class CDecoder
+{
+ NMethodType::EEnum _method;
+ CCoderLibraries _libraries;
+
+ CMyComPtr<ISequentialInStream> _filterInStream;
+ CMyComPtr<ISequentialInStream> _codecInStream;
+ CMyComPtr<ISequentialInStream> _decoderInStream;
+
+public:
+ CDecoder();
+ void Release()
+ {
+ _filterInStream.Release();
+ _codecInStream.Release();
+ _decoderInStream.Release();
+ }
+ HRESULT Init(IInStream *inStream, NMethodType::EEnum method, bool thereIsFilterFlag, bool &useFilter);
+ HRESULT Read(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.cpp b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
new file mode 100755
index 00000000..0d840479
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.cpp
@@ -0,0 +1,484 @@
+// NSisHandler.cpp
+
+#include "StdAfx.h"
+
+#include "NsisHandler.h"
+
+#include "Common/StringConvert.h"
+#include "Common/IntToString.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NNsis {
+
+static const wchar_t *kBcjMethod = L"BCJ";
+static const wchar_t *kUnknownMethod = L"Unknown";
+
+static const wchar_t *kMethods[] =
+{
+ L"Copy",
+ L"Deflate",
+ L"BZip2",
+ L"LZMA"
+};
+
+static const int kNumMethods = sizeof(kMethods) / sizeof(kMethods[0]);
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ { NULL, kpidMethod, VT_BSTR},
+ { NULL, kpidSolid, VT_BOOL}
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 * maxCheckStartPosition, IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ Close();
+ {
+ if(_archive.Open(stream, maxCheckStartPosition) != S_OK)
+ return S_FALSE;
+ _inStream = stream;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _archive.Clear();
+ _archive.Release();
+ _inStream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _archive.Items.Size()
+ #ifdef NSIS_SCRIPT
+ + 1
+ #endif
+ ;
+ return S_OK;
+}
+
+static UString ConvertUInt32ToString(UInt32 value)
+{
+ wchar_t buffer[32];
+ ConvertUInt64ToString(value, buffer);
+ return buffer;
+}
+
+static UString GetStringForSizeValue(UInt32 value)
+{
+ for (int i = 31; i >= 0; i--)
+ if ((UInt32(1) << i) == value)
+ return ConvertUInt32ToString(i);
+ UString result;
+ if (value % (1 << 20) == 0)
+ {
+ result += ConvertUInt32ToString(value >> 20);
+ result += L"m";
+ }
+ else if (value % (1 << 10) == 0)
+ {
+ result += ConvertUInt32ToString(value >> 10);
+ result += L"k";
+ }
+ else
+ {
+ result += ConvertUInt32ToString(value);
+ result += L"b";
+ }
+ return result;
+}
+
+bool CHandler::GetUncompressedSize(int index, UInt32 &size)
+{
+ size = 0;
+ const CItem &item = _archive.Items[index];
+ if (item.SizeIsDefined)
+ size = item.Size;
+ else if (_archive.IsSolid && item.EstimatedSizeIsDefined)
+ size = item.EstimatedSize;
+ else
+ return false;
+ return true;
+}
+
+bool CHandler::GetCompressedSize(int index, UInt32 &size)
+{
+ size = 0;
+ const CItem &item = _archive.Items[index];
+ if (item.CompressedSizeIsDefined)
+ size = item.CompressedSize;
+ else
+ {
+ if (_archive.IsSolid)
+ {
+ if (index == 0)
+ size = _archive.FirstHeader.GetDataSize();
+ else
+ return false;
+ }
+ else
+ {
+ if (!item.IsCompressed)
+ size = item.Size;
+ else
+ return false;
+ }
+ }
+ return true;
+}
+
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ #ifdef NSIS_SCRIPT
+ if (index >= (UInt32)_archive.Items.Size())
+ {
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = L"[NSIS].nsi";
+ break;
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ propVariant = (UInt64)_archive.Script.Length();
+ break;
+ case kpidSolid:
+ propVariant = false;
+ break;
+ }
+ }
+ else
+ #endif
+ {
+ const CItem &item = _archive.Items[index];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ const UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetReducedName(), CP_ACP));
+ propVariant = (const wchar_t *)s;
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidSize:
+ {
+ UInt32 size;
+ if (GetUncompressedSize(index, size))
+ propVariant = (UInt64)size;
+ break;
+ }
+ case kpidPackedSize:
+ {
+ UInt32 size;
+ if (GetCompressedSize(index, size))
+ propVariant = (UInt64)size;
+ break;
+ }
+ case kpidLastWriteTime:
+ {
+ if (item.DateTime.dwHighDateTime > 0x01000000 &&
+ item.DateTime.dwHighDateTime < 0xFF000000)
+ propVariant = item.DateTime;
+ break;
+ }
+ case kpidMethod:
+ {
+ NMethodType::EEnum methodIndex = _archive.Method;
+ UString method;
+ if (_archive.IsSolid && _archive.UseFilter || !_archive.IsSolid && item.UseFilter)
+ {
+ method += kBcjMethod;
+ method += L" ";
+ }
+ method += (methodIndex < kNumMethods) ? kMethods[methodIndex] : kUnknownMethod;
+ if (methodIndex == NMethodType::kLZMA)
+ {
+ method += L":";
+ method += GetStringForSizeValue(_archive.IsSolid ? _archive.DictionarySize: item.DictionarySize);
+ }
+ propVariant = method;
+ break;
+ }
+ case kpidSolid:
+ propVariant = _archive.IsSolid;
+ break;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool testMode = (_aTestMode != 0);
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ GetNumberOfItems(&numItems);
+ if(numItems == 0)
+ return S_OK;
+ UInt64 totalSize = 0;
+
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ {
+ UInt32 index = (allFilesMode ? i : indices[i]);
+ #ifdef NSIS_SCRIPT
+ if (index >= (UInt32)_archive.Items.Size())
+ totalSize += _archive.Script.Length();
+ else
+ #endif
+ {
+ UInt32 size;
+ if (_archive.IsSolid)
+ {
+ GetUncompressedSize(index, size);
+ UInt64 pos = _archive.GetPosOfSolidItem(index);
+ if (pos > totalSize)
+ totalSize = pos + size;
+ }
+ else
+ {
+ GetCompressedSize(index, size);
+ totalSize += size;
+ }
+ }
+ }
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+ UInt32 currentItemSize = 0;
+
+ UInt64 streamPos = 0;
+ if (_archive.IsSolid)
+ {
+ RINOK(_inStream->Seek(_archive.StreamOffset, STREAM_SEEK_SET, NULL));
+ bool useFilter;
+ RINOK(_archive.Decoder.Init(_inStream, _archive.Method, _archive.FilterFlag, useFilter));
+ }
+
+ bool dataError = false;
+ for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ currentItemSize = 0;
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest : NArchive::NExtract::NAskMode::kExtract;
+ UInt32 index = allFilesMode ? i : indices[i];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ #ifdef NSIS_SCRIPT
+ if (index >= (UInt32)_archive.Items.Size())
+ {
+ currentItemSize = _archive.Script.Length();
+ if(!testMode && (!realOutStream))
+ continue;
+ RINOK(extractCallback->PrepareOperation(askMode));
+ if (!testMode)
+ RINOK(realOutStream->Write((const char *)_archive.Script, (UInt32)_archive.Script.Length(), NULL));
+ }
+ else
+ #endif
+ {
+ const CItem &item = _archive.Items[index];
+
+ if (_archive.IsSolid)
+ GetUncompressedSize(index, currentItemSize);
+ else
+ GetCompressedSize(index, currentItemSize);
+
+ if(!testMode && (!realOutStream))
+ continue;
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ if (!dataError)
+ {
+ bool needDecompress = false;
+ bool sizeIsKnown = false;
+ UInt32 fullSize = 0;
+
+ const UInt32 kBufferLength = 1 << 11;
+ Byte buffer[kBufferLength];
+
+ if (_archive.IsSolid)
+ {
+ UInt64 pos = _archive.GetPosOfSolidItem(index);
+ while(streamPos < pos)
+ {
+ UInt32 curSize = (UInt32)MyMin(pos - streamPos, (UInt64)kBufferLength);
+ UInt32 processedSize;
+ HRESULT res = _archive.Decoder.Read(buffer, curSize, &processedSize);
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ dataError = true;
+ break;
+ }
+ if (processedSize == 0)
+ {
+ dataError = true;
+ break;
+ }
+ streamPos += processedSize;
+ }
+ if (streamPos == pos)
+ {
+ UInt32 processedSize;
+ RINOK(_archive.Decoder.Read(buffer, 4, &processedSize));
+ if (processedSize != 4)
+ return E_FAIL;
+ streamPos += processedSize;
+ fullSize = GetUInt32FromMemLE(buffer);
+ sizeIsKnown = true;
+ needDecompress = true;
+ }
+ }
+ else
+ {
+ RINOK(_inStream->Seek(_archive.GetPosOfNonSolidItem(index) + 4, STREAM_SEEK_SET, NULL));
+ if (item.IsCompressed)
+ {
+ needDecompress = true;
+ bool useFilter;
+ RINOK(_archive.Decoder.Init(_inStream, _archive.Method, _archive.FilterFlag, useFilter));
+ fullSize = GetUInt32FromMemLE(buffer);
+ }
+ else
+ fullSize = item.Size;
+ }
+ if (!dataError)
+ {
+ if (needDecompress)
+ {
+ UInt64 offset = 0;
+ while(!sizeIsKnown || fullSize > 0)
+ {
+ UInt32 curSize = kBufferLength;
+ if (sizeIsKnown && curSize > fullSize)
+ curSize = fullSize;
+ UInt32 processedSize;
+ HRESULT res = _archive.Decoder.Read(buffer, curSize, &processedSize);
+ if (res != S_OK)
+ {
+ if (res != S_FALSE)
+ return res;
+ dataError = true;
+ break;
+ }
+ if (processedSize == 0)
+ {
+ if (sizeIsKnown)
+ dataError = true;
+ break;
+ }
+
+ fullSize -= processedSize;
+ streamPos += processedSize;
+ offset += processedSize;
+
+ UInt64 completed;
+ if (_archive.IsSolid)
+ completed = streamPos;
+ else
+ completed = currentTotalSize + offset;
+ RINOK(extractCallback->SetCompleted(&completed));
+ if (!testMode)
+ RINOK(realOutStream->Write(buffer, processedSize, NULL));
+ }
+ }
+ else
+ {
+ while(fullSize > 0)
+ {
+ UInt32 curSize = MyMin(fullSize, kBufferLength);
+ UInt32 processedSize;
+ RINOK(_inStream->Read(buffer, curSize, &processedSize));
+ if (processedSize == 0)
+ {
+ dataError = true;
+ break;
+ }
+ fullSize -= processedSize;
+ streamPos += processedSize;
+ if (!testMode)
+ RINOK(realOutStream->Write(buffer, processedSize, 0));
+ }
+ }
+ }
+ }
+ }
+ if (!testMode)
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(dataError ?
+ NArchive::NExtract::NOperationResult::kDataError :
+ NArchive::NExtract::NOperationResult::kOK));
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Nsis/NsisHandler.h b/CPP/7zip/Archive/Nsis/NsisHandler.h
new file mode 100755
index 00000000..1ff8b776
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/NsisHandler.h
@@ -0,0 +1,41 @@
+// NSisHandler.h
+
+#ifndef __NSIS_HANDLER_H
+#define __NSIS_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "NsisIn.h"
+
+namespace NArchive {
+namespace NNsis {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+ CMyComPtr<IInStream> _inStream;
+ CInArchive _archive;
+
+ bool GetUncompressedSize(int index, UInt32 &size);
+ bool GetCompressedSize(int index, UInt32 &size);
+
+public:
+ MY_UNKNOWN_IMP1(IInArchive)
+
+ STDMETHOD(Open)(IInStream *stream, const UInt64 *maxCheckStartPosition, IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback);
+ 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);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.cpp b/CPP/7zip/Archive/Nsis/NsisIn.cpp
new file mode 100755
index 00000000..0db6ccfd
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/NsisIn.cpp
@@ -0,0 +1,1169 @@
+// Archive/NsisIn.cpp
+
+#include "StdAfx.h"
+
+#include "NsisIn.h"
+#include "NsisDecode.h"
+
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "Common/IntToString.h"
+
+namespace NArchive {
+namespace NNsis {
+
+Byte kSignature[kSignatureSize] = { 0xEF + 1, 0xBE, 0xAD, 0xDE,
+0x4E, 0x75, 0x6C, 0x6C, 0x73, 0x6F, 0x66, 0x74, 0x49, 0x6E, 0x73, 0x74};
+
+class SignatureInitializer
+{
+public:
+ SignatureInitializer() { kSignature[0]--; };
+} g_SignatureInitializer;
+
+static const char *kCrLf = "\x0D\x0A";
+
+UInt32 GetUInt32FromMemLE(const Byte *p)
+{
+ return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
+}
+
+Byte CInArchive::ReadByte()
+{
+ if (_posInData >= _size)
+ throw 1;
+ return _data[_posInData++];
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ value |= ((UInt32)(ReadByte()) << (8 * i));
+ return value;
+}
+
+void CInArchive::ReadBlockHeader(CBlockHeader &bh)
+{
+ bh.Offset = ReadUInt32();
+ bh.Num = ReadUInt32();
+}
+
+#define RINOZ(x) { int __tt = (x); if (__tt != 0) return __tt; }
+
+static int CompareItems(void *const *p1, void *const *p2, void * /* param */)
+{
+ RINOZ(MyCompare(
+ (**(const CItem **)p1).Pos,
+ (**(const CItem **)p2).Pos));
+ return 0;
+}
+
+AString CInArchive::ReadString(UInt32 pos)
+{
+ AString s;
+ UInt32 offset = GetOffset() + _stringsPos + pos;
+ for (;;)
+ {
+ if (offset >= _size)
+ throw 1;
+ char c = _data[offset++];
+ if (c == 0)
+ break;
+ s += c;
+ }
+ return s;
+}
+
+/*
+static AString ParsePrefix(const AString &prefix)
+{
+ AString res = prefix;
+ if (prefix.Length() >= 3)
+ {
+ if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x95 && (Byte)prefix[2] == 0x80)
+ res = "$INSTDIR" + prefix.Mid(3);
+ else if ((Byte)prefix[0] == 0xFD && (Byte)prefix[1] == 0x96 && (Byte)prefix[2] == 0x80)
+ res = "$OUTDIR" + prefix.Mid(3);
+ }
+ return res;
+}
+*/
+
+#define SYSREGKEY "Software\\Microsoft\\Windows\\CurrentVersion"
+
+/*
+# define CSIDL_PROGRAMS 0x2
+# define CSIDL_PRINTERS 0x4
+# define CSIDL_PERSONAL 0x5
+# define CSIDL_FAVORITES 0x6
+# define CSIDL_STARTUP 0x7
+# define CSIDL_RECENT 0x8
+# define CSIDL_SENDTO 0x9
+# define CSIDL_STARTMENU 0xB
+# define CSIDL_MYMUSIC 0xD
+# define CSIDL_MYVIDEO 0xE
+
+# define CSIDL_DESKTOPDIRECTORY 0x10
+# define CSIDL_NETHOOD 0x13
+# define CSIDL_FONTS 0x14
+# define CSIDL_TEMPLATES 0x15
+# define CSIDL_COMMON_STARTMENU 0x16
+# define CSIDL_COMMON_PROGRAMS 0x17
+# define CSIDL_COMMON_STARTUP 0x18
+# define CSIDL_COMMON_DESKTOPDIRECTORY 0x19
+# define CSIDL_APPDATA 0x1A
+# define CSIDL_PRINTHOOD 0x1B
+# define CSIDL_LOCAL_APPDATA 0x1C
+# define CSIDL_ALTSTARTUP 0x1D
+# define CSIDL_COMMON_ALTSTARTUP 0x1E
+# define CSIDL_COMMON_FAVORITES 0x1F
+
+# define CSIDL_INTERNET_CACHE 0x20
+# define CSIDL_COOKIES 0x21
+# define CSIDL_HISTORY 0x22
+# define CSIDL_COMMON_APPDATA 0x23
+# define CSIDL_WINDOWS 0x24
+# define CSIDL_SYSTEM 0x25
+# define CSIDL_PROGRAM_FILES 0x26
+# define CSIDL_MYPICTURES 0x27
+# define CSIDL_PROFILE 0x28
+# define CSIDL_PROGRAM_FILES_COMMON 0x2B
+# define CSIDL_COMMON_TEMPLATES 0x2D
+# define CSIDL_COMMON_DOCUMENTS 0x2E
+# define CSIDL_COMMON_ADMINTOOLS 0x2F
+
+# define CSIDL_ADMINTOOLS 0x30
+# define CSIDL_COMMON_MUSIC 0x35
+# define CSIDL_COMMON_PICTURES 0x36
+# define CSIDL_COMMON_VIDEO 0x37
+# define CSIDL_RESOURCES 0x38
+# define CSIDL_RESOURCES_LOCALIZED 0x39
+# define CSIDL_CDBURN_AREA 0x3B
+*/
+
+struct CCommandPair
+{
+ int NumParams;
+ const char *Name;
+};
+
+enum
+{
+ // 0
+ EW_INVALID_OPCODE, // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction
+ // does nothing, which is easily ignored but means something is wrong.
+ EW_RET, // return from function call
+ EW_NOP, // Nop/Jump, do nothing: 1, [?new address+1:advance one]
+ EW_ABORT, // Abort: 1 [status]
+ EW_QUIT, // Quit: 0
+ EW_CALL, // Call: 1 [new address+1]
+ EW_UPDATETEXT, // Update status text: 2 [update str, ui_st_updateflag=?ui_st_updateflag:this]
+ EW_SLEEP, // Sleep: 1 [sleep time in milliseconds]
+ EW_BRINGTOFRONT, // BringToFront: 0
+ EW_CHDETAILSVIEW, // SetDetailsView: 2 [listaction,buttonaction]
+
+ // 10
+ EW_SETFILEATTRIBUTES, // SetFileAttributes: 2 [filename, attributes]
+ EW_CREATEDIR, // Create directory: 2, [path, ?update$INSTDIR]
+ EW_IFFILEEXISTS, // IfFileExists: 3, [file name, jump amount if exists, jump amount if not exists]
+ EW_SETFLAG, // Sets a flag: 2 [id, data]
+ EW_IFFLAG, // If a flag: 4 [on, off, id, new value mask]
+ EW_GETFLAG, // Gets a flag: 2 [output, id]
+ EW_RENAME, // Rename: 3 [old, new, rebootok]
+ EW_GETFULLPATHNAME, // GetFullPathName: 2 [output, input, ?lfn:sfn]
+ EW_SEARCHPATH, // SearchPath: 2 [output, filename]
+ EW_GETTEMPFILENAME, // GetTempFileName: 2 [output, base_dir]
+
+ // 20
+ EW_EXTRACTFILE, // File to extract: 6 [overwriteflag, output filename, compressed filedata, filedatetimelow, filedatetimehigh, allow ignore]
+ // overwriteflag: 0x1 = no. 0x0=force, 0x2=try, 0x3=if date is newer
+ EW_DELETEFILE, // Delete File: 2, [filename, rebootok]
+ EW_MESSAGEBOX, // MessageBox: 5,[MB_flags,text,retv1:retv2,moveonretv1:moveonretv2]
+ EW_RMDIR, // RMDir: 2 [path, recursiveflag]
+ EW_STRLEN, // StrLen: 2 [output, input]
+ EW_ASSIGNVAR, // Assign: 4 [variable (0-9) to assign, string to assign, maxlen, startpos]
+ EW_STRCMP, // StrCmp: 5 [str1, str2, jump_if_equal, jump_if_not_equal, case-sensitive?]
+ EW_READENVSTR, // ReadEnvStr/ExpandEnvStrings: 3 [output, string_with_env_variables, IsRead]
+ EW_INTCMP, // IntCmp: 6 [val1, val2, equal, val1<val2, val1>val2, unsigned?]
+ EW_INTOP, // IntOp: 4 [output, input1, input2, op] where op: 0=add, 1=sub, 2=mul, 3=div, 4=bor, 5=band, 6=bxor, 7=bnot input1, 8=lnot input1, 9=lor, 10=land], 11=1%2
+
+ // 30
+ EW_INTFMT, // IntFmt: [output, format, input]
+ EW_PUSHPOP, // Push/Pop/Exchange: 3 [variable/string, ?pop:push, ?exch]
+ EW_FINDWINDOW, // FindWindow: 5, [outputvar, window class,window name, window_parent, window_after]
+ EW_SENDMESSAGE, // SendMessage: 6 [output, hwnd, msg, wparam, lparam, [wparamstring?1:0 | lparamstring?2:0 | timeout<<2]
+ EW_ISWINDOW, // IsWindow: 3 [hwnd, jump_if_window, jump_if_notwindow]
+ EW_GETDLGITEM, // GetDlgItem: 3: [outputvar, dialog, item_id]
+ EW_SETCTLCOLORS, // SerCtlColors: 3: [hwnd, pointer to struct colors]
+ EW_SETBRANDINGIMAGE, // SetBrandingImage: 1: [Bitmap file]
+ EW_CREATEFONT, // CreateFont: 5: [handle output, face name, height, weight, flags]
+ EW_SHOWWINDOW, // ShowWindow: 2: [hwnd, show state]
+
+ // 40
+ EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]
+ EW_EXECUTE, // Execute program: 3,[complete command line,waitflag,>=0?output errorcode]
+ EW_GETFILETIME, // GetFileTime; 3 [file highout lowout]
+ EW_GETDLLVERSION, // GetDLLVersion: 3 [file highout lowout]
+ EW_REGISTERDLL, // Register DLL: 3,[DLL file name, string ptr of function to call, text to put in display (<0 if none/pass parms), 1 - no unload, 0 - unload]
+ EW_CREATESHORTCUT, // Make Shortcut: 5, [link file, target file, parameters, icon file, iconindex|show mode<<8|hotkey<<16]
+ EW_COPYFILES, // CopyFiles: 3 [source mask, destination location, flags]
+ EW_REBOOT, // Reboot: 0
+ EW_WRITEINI, // Write INI String: 4, [Section, Name, Value, INI File]
+ EW_READINISTR, // ReadINIStr: 4 [output, section, name, ini_file]
+
+ // 50
+ EW_DELREG, // DeleteRegValue/DeleteRegKey: 4, [root key(int), KeyName, ValueName, delkeyonlyifempty]. ValueName is -1 if delete key
+ EW_WRITEREG, // Write Registry value: 5, [RootKey(int),KeyName,ItemName,ItemData,typelen]
+ // typelen=1 for str, 2 for dword, 3 for binary, 0 for expanded str
+ EW_READREGSTR, // ReadRegStr: 5 [output, rootkey(int), keyname, itemname, ==1?int::str]
+ EW_REGENUM, // RegEnum: 5 [output, rootkey, keyname, index, ?key:value]
+ EW_FCLOSE, // FileClose: 1 [handle]
+ EW_FOPEN, // FileOpen: 4 [name, openmode, createmode, outputhandle]
+ EW_FPUTS, // FileWrite: 3 [handle, string, ?int:string]
+ EW_FGETS, // FileRead: 4 [handle, output, maxlen, ?getchar:gets]
+ EW_FSEEK, // FileSeek: 4 [handle, offset, mode, >=0?positionoutput]
+ EW_FINDCLOSE, // FindClose: 1 [handle]
+
+ // 60
+ EW_FINDNEXT, // FindNext: 2 [output, handle]
+ EW_FINDFIRST, // FindFirst: 2 [filespec, output, handleoutput]
+ EW_WRITEUNINSTALLER, // WriteUninstaller: 3 [name, offset, icon_size]
+ EW_LOG, // LogText: 2 [0, text] / LogSet: [1, logstate]
+ EW_SECTIONSET, // SectionSetText: 3: [idx, 0, text]
+ // SectionGetText: 3: [idx, 1, output]
+ // SectionSetFlags: 3: [idx, 2, flags]
+ // SectionGetFlags: 3: [idx, 3, output]
+ EW_INSTTYPESET, // InstTypeSetFlags: 3: [idx, 0, flags]
+ // InstTypeGetFlags: 3: [idx, 1, output]
+ // instructions not actually implemented in exehead, but used in compiler.
+ EW_GETLABELADDR, // both of these get converted to EW_ASSIGNVAR
+ EW_GETFUNCTIONADDR,
+
+ EW_LOCKWINDOW
+};
+
+static CCommandPair kCommandPairs[] =
+{
+ { 0, "Invalid" },
+ { 0, "Return" },
+ { 1, "Goto" },
+ { 0, "Abort" },
+ { 0, "Quit" },
+ { 1, "Call" },
+ { 2, "UpdateSatusText" },
+ { 1, "Sleep" },
+ { 0, "BringToFront" },
+ { 2, "SetDetailsView" },
+
+ { 2, "SetFileAttributes" },
+ { 2, "SetOutPath" },
+ { 3, "IfFileExists" },
+ { 2, "SetFlag" },
+ { 4, "IfFlag" },
+ { 2, "GetFlag" },
+ { 3, "Rename" },
+ { 2, "GetFullPathName" },
+ { 2, "SearchPath" },
+ { 2, "GetTempFileName" },
+
+ { 6, "File" },
+ { 2, "Delete" },
+ { 5, "MessageBox" },
+ { 2, "RMDir" },
+ { 2, "Assign" },
+ { 4, "StrCpy" },
+ { 5, "StrCmp" },
+ { 3, "ReadEnvStr" },
+ { 6, "IntCmp" },
+ { 4, "IntOp" },
+
+ { 3, "IntFmt" },
+ { 3, "PushPop" },
+ { 5, "FindWindow" },
+ { 6, "SendMessage" },
+ { 3, "IsWindow" },
+ { 3, "GetDlgItem" },
+ { 3, "SerCtlColors" },
+ { 1, "SetBrandingImage" },
+ { 5, "CreateFont" },
+ { 2, "ShowWindow" },
+
+ { 4, "ShellExecute" },
+ { 3, "Execute" },
+ { 3, "GetFileTime" },
+ { 3, "GetDLLVersion" },
+ { 3, "RegisterDLL" },
+ { 5, "CreateShortCut" },
+ { 3, "CopyFiles" },
+ { 0, "Reboot" },
+ { 4, "WriteINIStr" },
+ { 4, "ReadINIStr" },
+
+ { 4, "DelReg" },
+ { 5, "WriteReg" },
+ { 5, "ReadRegStr" },
+ { 5, "RegEnum" },
+ { 1, "FileClose" },
+ { 4, "FileOpen" },
+ { 3, "FileWrite" },
+ { 4, "FileRead" },
+ { 4, "FileSeek" },
+ { 1, "FindClose" },
+
+ { 2, "FindNext" },
+ { 2, "FindFirst" },
+ { 3, "WriteUninstaller" },
+ { 2, "LogText" },
+ { 3, "Section?etText" },
+ { 3, "InstType?etFlags" },
+ { 6, "GetLabelAddr" },
+ { 2, "GetFunctionAddress" },
+ { 6, "LockWindow" }
+};
+
+
+static const char *kShellStrings[] =
+{
+ "",
+ "",
+
+ "SMPROGRAMS",
+ "",
+ "PRINTERS",
+ "DOCUMENTS",
+ "FAVORITES",
+ "SMSTARTUP",
+ "RECENT",
+ "SENDTO",
+ "",
+ "STARTMENU",
+ "",
+ "MUSIC",
+ "VIDEO",
+ "",
+
+ "DESKTOP",
+ "",
+ "",
+ "NETHOOD",
+ "FONTS",
+ "TEMPLATES",
+ "COMMONSTARTMENU",
+ "COMMONFILES",
+ "COMMON_STARTUP",
+ "COMMON_DESKTOPDIRECTORY",
+ "QUICKLAUNCH",
+ "PRINTHOOD",
+ "LOCALAPPDATA",
+ "ALTSTARTUP",
+ "ALTSTARTUP",
+ "FAVORITES",
+
+ "INTERNET_CACHE",
+ "COOKIES",
+ "HISTORY",
+ "APPDATA",
+ "WINDIR",
+ "SYSDIR",
+ "PROGRAMFILES",
+ "PICTURES",
+ "PROFILE",
+ "",
+ "",
+ "COMMONFILES",
+ "",
+ "TEMPLATES",
+ "DOCUMENTS",
+ "ADMINTOOLS",
+
+ "ADMINTOOLS",
+ "",
+ "",
+ "",
+ "",
+ "MUSIC",
+ "PICTURES",
+ "VIDEO",
+ "RESOURCES",
+ "RESOURCES_LOCALIZED",
+ "",
+ "CDBURN_AREA"
+};
+
+static const int kNumShellStrings = sizeof(kShellStrings) / sizeof(kShellStrings[0]);
+
+/*
+# define CMDLINE 20 // everything before here doesn't have trailing slash removal
+# define INSTDIR 21
+# define OUTDIR 22
+# define EXEDIR 23
+# define LANGUAGE 24
+# define TEMP 25
+# define PLUGINSDIR 26
+# define HWNDPARENT 27
+# define _CLICK 28
+# define _OUTDIR 29
+*/
+
+static const char *kVarStrings[] =
+{
+ "CMDLINE",
+ "INSTDIR",
+ "OUTDIR",
+ "EXEDIR",
+ "LANGUAGE",
+ "TEMP",
+ "PLUGINSDIR",
+ "HWNDPARENT",
+ "_CLICK",
+ "_OUTDIR"
+};
+
+static const int kNumVarStrings = sizeof(kVarStrings) / sizeof(kVarStrings[0]);
+
+
+static AString UIntToString(UInt32 v)
+{
+ char sz[32];
+ ConvertUInt64ToString(v, sz);
+ return sz;
+}
+
+static AString IntToString(Int32 v)
+{
+ char sz[32];
+ ConvertInt64ToString(v, sz);
+ return sz;
+}
+
+static AString GetVar(UInt32 index)
+{
+ AString res = "$";
+ if (index < 10)
+ res += UIntToString(index);
+ else if (index < 20)
+ {
+ res += "R";
+ res += UIntToString(index - 10);
+ }
+ else if (index < 20 + kNumVarStrings)
+ res += kVarStrings[index - 20];
+ else
+ {
+ res += "[";
+ res += UIntToString(index);
+ res += "]";
+ }
+ return res;
+}
+
+// $0..$9, $INSTDIR, etc are encoded as ASCII bytes starting from this value.
+#define NS_SKIP_CODE 252
+#define NS_VAR_CODE 253
+#define NS_SHELL_CODE 254
+#define NS_LANG_CODE 255
+#define NS_CODES_START NS_SKIP_CODE
+
+// Based on Dave Laundon's simplified process_string
+AString GetNsisString(const AString &s)
+{
+ AString res;
+ for (int i = 0; i < s.Length();)
+ {
+ unsigned char nVarIdx = s[i++];
+ if (nVarIdx > NS_CODES_START && i + 2 <= s.Length())
+ {
+ int nData = s[i++] & 0x7F;
+ unsigned char c1 = s[i++];
+ nData |= (((int)(c1 & 0x7F)) << 7);
+
+ if (nVarIdx == NS_SHELL_CODE)
+ {
+ UInt32 index = c1;
+ bool needPrint = true;
+ res += "$";
+ if (index < kNumShellStrings)
+ {
+ const char *sz = kShellStrings[index];
+ if (sz[0] != 0)
+ {
+ res += sz;
+ needPrint = false;
+ }
+ }
+ if (needPrint)
+ {
+ res += "SHELL[";
+ res += UIntToString(index);
+ res += "]";
+ }
+ }
+ else if (nVarIdx == NS_VAR_CODE)
+ res += GetVar(nData);
+ else if (nVarIdx == NS_LANG_CODE)
+ res += "NS_LANG_CODE";
+ }
+ else if (nVarIdx == NS_SKIP_CODE)
+ {
+ if (i < s.Length())
+ res += s[i++];
+ }
+ else // Normal char
+ res += (char)nVarIdx;
+ }
+ return res;
+}
+
+AString CInArchive::ReadString2(UInt32 pos)
+{
+ return GetNsisString(ReadString(pos));
+}
+
+#define DEL_DIR 1
+#define DEL_RECURSE 2
+#define DEL_REBOOT 4
+// #define DEL_SIMPLE 8
+
+static const int kNumEntryParams = 6;
+
+struct CEntry
+{
+ UInt32 Which;
+ UInt32 Params[kNumEntryParams];
+ AString GetParamsString(int numParams);
+ CEntry()
+ {
+ Which = 0;
+ for (UInt32 j = 0; j < kNumEntryParams; j++)
+ Params[j] = 0;
+ }
+};
+
+AString CEntry::GetParamsString(int numParams)
+{
+ AString s;
+ for (int i = 0; i < numParams; i++)
+ {
+ s += " ";
+ UInt32 v = Params[i];
+ if (v > 0xFFF00000)
+ s += IntToString((Int32)Params[i]);
+ else
+ s += UIntToString(Params[i]);
+ }
+ return s;
+}
+
+HRESULT CInArchive::ReadEntries(const CBlockHeader &bh)
+{
+ _posInData = bh.Offset + GetOffset();
+ AString prefix;
+ for (UInt32 i = 0; i < bh.Num; i++)
+ {
+ CEntry e;
+ e.Which = ReadUInt32();
+ for (UInt32 j = 0; j < kNumEntryParams; j++)
+ e.Params[j] = ReadUInt32();
+ #ifdef NSIS_SCRIPT
+ if (e.Which != EW_PUSHPOP && e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+ {
+ const CCommandPair &pair = kCommandPairs[e.Which];
+ Script += pair.Name;
+ }
+ #endif
+
+ switch (e.Which)
+ {
+ case EW_CREATEDIR:
+ {
+ prefix.Empty();
+ prefix = ReadString2(e.Params[0]);
+ #ifdef NSIS_SCRIPT
+ Script += " ";
+ Script += prefix;
+ #endif
+ break;
+ }
+
+ case EW_EXTRACTFILE:
+ {
+ CItem item;
+ item.Prefix = prefix;
+ /* UInt32 overwriteFlag = e.Params[0]; */
+ item.Name = ReadString2(e.Params[1]);
+ item.Pos = e.Params[2];
+ item.DateTime.dwLowDateTime = e.Params[3];
+ item.DateTime.dwHighDateTime = e.Params[4];
+ /* UInt32 allowIgnore = e.Params[5]; */
+ if (Items.Size() > 0)
+ {
+ /*
+ if (item.Pos == Items.Back().Pos)
+ continue;
+ */
+ }
+ Items.Add(item);
+ #ifdef NSIS_SCRIPT
+ Script += " ";
+ Script += item.Name;
+ #endif
+ break;
+ }
+
+
+ #ifdef NSIS_SCRIPT
+ case EW_UPDATETEXT:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += UIntToString(e.Params[1]);
+ break;
+ }
+ case EW_SETFILEATTRIBUTES:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += UIntToString(e.Params[1]);
+ break;
+ }
+ case EW_IFFILEEXISTS:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += UIntToString(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+ case EW_RENAME:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+ case EW_GETFULLPATHNAME:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+ case EW_SEARCHPATH:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ break;
+ }
+ case EW_GETTEMPFILENAME:
+ {
+ AString s;
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ break;
+ }
+
+ case EW_DELETEFILE:
+ {
+ UInt64 flag = e.Params[1];
+ if (flag != 0)
+ {
+ Script += " ";
+ if (flag == DEL_REBOOT)
+ Script += "/REBOOTOK";
+ else
+ Script += UIntToString(e.Params[1]);
+ }
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ break;
+ }
+ case EW_RMDIR:
+ {
+ UInt64 flag = e.Params[1];
+ if (flag != 0)
+ {
+ if ((flag & DEL_REBOOT) != 0)
+ Script += " /REBOOTOK";
+ if ((flag & DEL_RECURSE) != 0)
+ Script += " /r";
+ }
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ break;
+ }
+ case EW_ASSIGNVAR:
+ {
+ Script += " ";
+ Script += GetVar(e.Params[0]);;
+ Script += " \"";
+ AString maxLen, startOffset;
+ Script += ReadString2(e.Params[1]);
+ Script += "\"";
+ if (e.Params[2] != 0)
+ maxLen = ReadString(e.Params[2]);
+ if (e.Params[3] != 0)
+ startOffset = ReadString(e.Params[3]);
+ if (!maxLen.IsEmpty() || !startOffset.IsEmpty())
+ {
+ Script += " ";
+ if (maxLen.IsEmpty())
+ Script += "\"\"";
+ else
+ Script += maxLen;
+ if (!startOffset.IsEmpty())
+ {
+ Script += " ";
+ Script += startOffset;
+ }
+ }
+ break;
+ }
+ case EW_STRCMP:
+ {
+ Script += " ";
+
+ Script += " \"";
+ Script += ReadString2(e.Params[0]);
+ Script += "\"";
+
+ Script += " \"";
+ Script += ReadString2(e.Params[1]);
+ Script += "\"";
+
+ for (int j = 2; j < 5; j++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[j]);
+ }
+ break;
+ }
+
+ case EW_PUSHPOP:
+ {
+ int isPop = (e.Params[1] != 0);
+ if (isPop)
+ {
+ Script += "Pop";
+ Script += " ";
+ Script += GetVar(e.Params[0]);;
+ }
+ else
+ {
+ int isExch = (e.Params[2] != 0);
+ if (isExch)
+ {
+ Script += "Exch";
+ }
+ else
+ {
+ Script += "Push";
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ }
+ }
+ break;
+ }
+
+ /*
+ case EW_SENDMESSAGE:
+ {
+ Script += " ";
+ Script += IntToString(e.Params[0]);
+ Script += " ";
+ Script += GetVar(e.Params[1]);
+ Script += " ";
+ Script += ReadString2(e.Params[2]);
+ Script += " ";
+ Script += UIntToString(e.Params[3]);
+ Script += " ";
+ Script += IntToString(e.Params[4]);
+ Script += " ";
+ Script += UIntToString(e.Params[5]);
+ break;
+ }
+ */
+
+ case EW_REGISTERDLL:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ Script += " ";
+ Script += ReadString2(e.Params[1]);
+ Script += " ";
+ Script += UIntToString(e.Params[2]);
+ break;
+ }
+
+ case EW_CREATESHORTCUT:
+ {
+ AString s;
+
+ Script += " ";
+ Script += " \"";
+ Script += ReadString2(e.Params[0]);
+ Script += " \"";
+
+ Script += " ";
+ Script += " \"";
+ Script += ReadString2(e.Params[1]);
+ Script += " \"";
+
+ for (int j = 2; j < 5; j++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[j]);
+ }
+ break;
+ }
+
+ /*
+ case EW_DELREG:
+ {
+ AString keyName, valueName;
+ keyName = ReadString2(e.Params[1]);
+ bool isValue = (e.Params[2] != -1);
+ if (isValue)
+ {
+ valueName = ReadString2(e.Params[2]);
+ Script += "Key";
+ }
+ else
+ Script += "Value";
+ Script += " ";
+ Script += UIntToString(e.Params[0]);
+ Script += " ";
+ Script += keyName;
+ if (isValue)
+ {
+ Script += " ";
+ Script += valueName;
+ }
+ Script += " ";
+ Script += UIntToString(e.Params[3]);
+ break;
+ }
+ */
+
+ case EW_WRITEUNINSTALLER:
+ {
+ Script += " ";
+ Script += ReadString2(e.Params[0]);
+ for (int j = 1; j < 3; j++)
+ {
+ Script += " ";
+ Script += UIntToString(e.Params[j]);
+ }
+ break;
+ }
+
+ default:
+ {
+ int numParams = kNumEntryParams;
+ if (e.Which < sizeof(kCommandPairs) / sizeof(kCommandPairs[0]))
+ {
+ const CCommandPair &pair = kCommandPairs[e.Which];
+ // Script += pair.Name;
+ numParams = pair.NumParams;
+ }
+ else
+ {
+ Script += "Unknown";
+ Script += UIntToString(e.Which);
+ }
+ Script += e.GetParamsString(numParams);
+ }
+ #endif
+ }
+ #ifdef NSIS_SCRIPT
+ Script += kCrLf;
+ #endif
+ }
+
+ {
+ Items.Sort(CompareItems, 0);
+ int i;
+ for (i = 0; i + 1 < Items.Size();)
+ {
+ if (Items[i].Pos == Items[i + 1].Pos)
+ Items.Delete(i + 1);
+ else
+ i++;
+ }
+ for (i = 0; i + 1 < Items.Size(); i++)
+ {
+ CItem &item = Items[i];
+ item.EstimatedSizeIsDefined = true;
+ item.EstimatedSize = Items[i + 1].Pos - item.Pos - 4;
+ }
+ if (!IsSolid)
+ {
+ for (i = 0; i < Items.Size(); i++)
+ {
+ CItem &item = Items[i];
+ RINOK(_stream->Seek(GetPosOfNonSolidItem(i), STREAM_SEEK_SET, NULL));
+ const UInt32 kSigSize = 4 + 1 + 5;
+ BYTE sig[kSigSize];
+ UInt32 processedSize;
+ RINOK(ReadStream(_stream, sig, kSigSize, &processedSize));
+ if (processedSize < 4)
+ return S_FALSE;
+ UInt32 size = GetUInt32FromMemLE(sig);
+ if ((size & 0x80000000) != 0)
+ {
+ item.IsCompressed = true;
+ // is compressed;
+ size &= ~0x80000000;
+ if (Method == NMethodType::kLZMA)
+ {
+ if (processedSize < 9)
+ return S_FALSE;
+ if (FilterFlag)
+ item.UseFilter = (sig[4] != 0);
+ item.DictionarySize = GetUInt32FromMemLE(sig + 5 + (FilterFlag ? 1 : 0));
+ }
+ }
+ else
+ {
+ item.IsCompressed = false;
+ item.Size = size;
+ item.SizeIsDefined = true;
+ }
+ item.CompressedSize = size;
+ item.CompressedSizeIsDefined = true;
+ }
+ }
+ }
+ return S_OK;
+}
+
+HRESULT CInArchive::Parse()
+{
+ // UInt32 offset = ReadUInt32();
+ // ???? offset == FirstHeader.HeaderLength
+ /* UInt32 ehFlags = */ ReadUInt32();
+ CBlockHeader bhPages, bhSections, bhEntries, bhStrings, bhLangTables, bhCtlColors, bhData;
+ // CBlockHeader bgFont;
+ ReadBlockHeader(bhPages);
+ ReadBlockHeader(bhSections);
+ ReadBlockHeader(bhEntries);
+ ReadBlockHeader(bhStrings);
+ ReadBlockHeader(bhLangTables);
+ ReadBlockHeader(bhCtlColors);
+ // ReadBlockHeader(bgFont);
+ ReadBlockHeader(bhData);
+
+ _stringsPos = bhStrings.Offset;
+
+ return ReadEntries(bhEntries);
+}
+
+static bool IsLZMA(const Byte *p, UInt32 &dictionary)
+{
+ dictionary = GetUInt32FromMemLE(p + 1);
+ return (p[0] == 0x5D && p[1] == 0x00 && p[2] == 0x00 && p[5] == 0x00);
+}
+
+static bool IsLZMA(const Byte *p, UInt32 &dictionary, bool &thereIsFlag)
+{
+ if (IsLZMA(p, dictionary))
+ {
+ thereIsFlag = false;
+ return true;
+ }
+ if (IsLZMA(p + 1, dictionary))
+ {
+ thereIsFlag = true;
+ return true;
+ }
+ return false;
+}
+
+HRESULT CInArchive::Open2()
+{
+ RINOK(_stream->Seek(0, STREAM_SEEK_CUR, &StreamOffset));
+
+ const UInt32 kSigSize = 4 + 1 + 5 + 1; // size, flag, lzma props, lzma first byte
+ BYTE sig[kSigSize];
+ UInt32 processedSize;
+ RINOK(ReadStream(_stream, sig, kSigSize, &processedSize));
+ if (processedSize != kSigSize)
+ return S_FALSE;
+ UInt64 position;
+ RINOK(_stream->Seek(StreamOffset, STREAM_SEEK_SET, &position));
+
+ _headerIsCompressed = true;
+ IsSolid = true;
+ FilterFlag = false;
+
+ UInt32 compressedHeaderSize = GetUInt32FromMemLE(sig);
+
+ if (compressedHeaderSize == FirstHeader.HeaderLength)
+ {
+ _headerIsCompressed = false;
+ IsSolid = false;
+ Method = NMethodType::kCopy;
+ }
+ else if (IsLZMA(sig, DictionarySize, FilterFlag))
+ {
+ Method = NMethodType::kLZMA;
+ }
+ else if (IsLZMA(sig + 4, DictionarySize, FilterFlag))
+ {
+ IsSolid = false;
+ Method = NMethodType::kLZMA;
+ }
+ else if (sig[3] == 0x80)
+ {
+ IsSolid = false;
+ Method = NMethodType::kDeflate;
+ }
+ else
+ {
+ Method = NMethodType::kDeflate;
+ }
+
+ _posInData = 0;
+ if (!IsSolid)
+ {
+ _headerIsCompressed = ((compressedHeaderSize & 0x80000000) != 0);
+ if (_headerIsCompressed)
+ compressedHeaderSize &= ~0x80000000;
+ _nonSolidStartOffset = compressedHeaderSize;
+ RINOK(_stream->Seek(StreamOffset + 4, STREAM_SEEK_SET, NULL));
+ }
+ UInt32 unpackSize = FirstHeader.HeaderLength;
+ if (_headerIsCompressed)
+ {
+ // unpackSize = (1 << 23);
+ _data.SetCapacity(unpackSize);
+ RINOK(Decoder.Init(_stream, Method, FilterFlag, UseFilter));
+ UInt32 processedSize;
+ RINOK(Decoder.Read(_data, unpackSize, &processedSize));
+ if (processedSize != unpackSize)
+ return S_FALSE;
+ _size = (size_t)processedSize;
+ if (IsSolid)
+ {
+ UInt32 size2 = ReadUInt32();
+ if (size2 < _size)
+ _size = size2;
+ }
+ }
+ else
+ {
+ _data.SetCapacity(unpackSize);
+ _size = (size_t)unpackSize;
+ RINOK(ReadStream(_stream, (Byte *)_data, unpackSize, &processedSize));
+ if (processedSize != unpackSize)
+ return S_FALSE;
+ }
+ return Parse();
+}
+
+/*
+NsisExe =
+{
+ ExeStub
+ Archive // must start from 512 * N
+ #ifndef NSIS_CONFIG_CRC_ANAL
+ {
+ Some additional data
+ }
+}
+
+Archive
+{
+ FirstHeader
+ Data
+ #ifdef NSIS_CONFIG_CRC_SUPPORT && FirstHeader.ThereIsCrc()
+ {
+ CRC
+ }
+}
+
+FirstHeader
+{
+ UInt32 Flags;
+ Byte Signature[16];
+ // points to the header+sections+entries+stringtable in the datablock
+ UInt32 HeaderLength;
+ UInt32 ArchiveSize;
+}
+*/
+
+HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *maxCheckStartPosition)
+{
+ Clear();
+ UInt64 pos;
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &pos));
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &_archiveSize));
+ UInt64 position;
+ RINOK(inStream->Seek(pos, STREAM_SEEK_SET, &position));
+ UInt64 maxSize = (maxCheckStartPosition != 0) ? *maxCheckStartPosition : (1 << 20);
+ const UInt32 kStep = 512;
+ const UInt32 kStartHeaderSize = 4 * 7;
+ Byte buffer[kStep];
+ bool found = false;
+
+ UInt64 headerPosition = 0;
+ while (position <= maxSize)
+ {
+ UInt32 processedSize;
+ RINOK(ReadStream(inStream, buffer, kStartHeaderSize, &processedSize));
+ if (processedSize != kStartHeaderSize)
+ return S_FALSE;
+ headerPosition = position;
+ position += processedSize;
+ if(memcmp(buffer + 4, kSignature, kSignatureSize) == 0)
+ {
+ found = true;
+ break;
+ }
+ const UInt32 kRem = kStep - kStartHeaderSize;
+ RINOK(ReadStream(inStream, buffer + kStartHeaderSize, kRem, &processedSize));
+ if (processedSize != kRem)
+ return S_FALSE;
+ position += processedSize;
+ }
+ if (!found)
+ return S_FALSE;
+ FirstHeader.Flags = GetUInt32FromMemLE(buffer);
+ FirstHeader.HeaderLength = GetUInt32FromMemLE(buffer + kSignatureSize + 4);
+ FirstHeader.ArchiveSize = GetUInt32FromMemLE(buffer + kSignatureSize + 8);
+ if (_archiveSize - headerPosition < FirstHeader.ArchiveSize)
+ return S_FALSE;
+
+ _stream = inStream;
+ HRESULT res = S_FALSE;
+ try { res = Open2(); }
+ catch(...) { Clear(); res = S_FALSE; }
+ _stream.Release();
+ return res;
+}
+
+void CInArchive::Clear()
+{
+ #ifdef NSIS_SCRIPT
+ Script.Empty();
+ #endif
+ Items.Clear();
+}
+
+}}
diff --git a/CPP/7zip/Archive/Nsis/NsisIn.h b/CPP/7zip/Archive/Nsis/NsisIn.h
new file mode 100755
index 00000000..d75a9e6e
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/NsisIn.h
@@ -0,0 +1,166 @@
+// Archive/NsisIn.h
+
+#ifndef __ARCHIVE_NSIS_IN_H
+#define __ARCHIVE_NSIS_IN_H
+
+#include "Common/MyCom.h"
+#include "Common/IntToString.h"
+#include "Common/Buffer.h"
+
+#include "../../IStream.h"
+
+#include "NsisDecode.h"
+
+// #define NSIS_SCRIPT
+
+namespace NArchive {
+namespace NNsis {
+
+const int kSignatureSize = 16;
+extern Byte kSignature[kSignatureSize];
+
+const UInt32 kFlagsMask = 0xF;
+namespace NFlags
+{
+ const UInt32 kUninstall = 1;
+ const UInt32 kSilent = 2;
+ const UInt32 kNoCrc = 4;
+ const UInt32 kForceCrc = 8;
+}
+
+struct CFirstHeader
+{
+ UInt32 Flags;
+ UInt32 HeaderLength;
+
+ UInt32 ArchiveSize;
+
+ bool ThereIsCrc() const
+ {
+ if ((Flags & NFlags::kForceCrc ) != 0)
+ return true;
+ return ((Flags & NFlags::kNoCrc) == 0);
+ }
+
+ UInt32 GetDataSize() const { return ArchiveSize - (ThereIsCrc() ? 4 : 0); }
+};
+
+
+struct CBlockHeader
+{
+ UInt32 Offset;
+ UInt32 Num;
+};
+
+struct CItem
+{
+ AString Prefix;
+ AString Name;
+ UInt32 Pos;
+ bool SizeIsDefined;
+ bool CompressedSizeIsDefined;
+ bool EstimatedSizeIsDefined;
+ UInt32 Size;
+ UInt32 CompressedSize;
+ UInt32 EstimatedSize;
+ FILETIME DateTime;
+ UInt32 DictionarySize;
+ bool IsCompressed;
+ bool UseFilter;
+ CItem(): UseFilter(false), SizeIsDefined(false), EstimatedSizeIsDefined(false),
+ IsCompressed(true), CompressedSizeIsDefined(false), Size(0) {}
+
+ bool IsINSTDIR() const
+ {
+ if (Prefix.Length() < 3)
+ return false;
+ return true;
+ }
+
+ AString GetReducedName() const
+ {
+ AString prefix = Prefix;
+ if (prefix.Length() > 0)
+ if (prefix[prefix.Length() - 1] != '\\')
+ prefix += '\\';
+ AString s2 = prefix + Name;
+ const int len = 9;
+ if (s2.Left(len).CompareNoCase("$INSTDIR\\") == 0)
+ s2 = s2.Mid(len);
+ return s2;
+ }
+
+};
+
+class CInArchive
+{
+ UInt64 _archiveSize;
+ CMyComPtr<IInStream> _stream;
+
+ Byte ReadByte();
+ UInt32 ReadUInt32();
+ HRESULT Open2();
+ void ReadBlockHeader(CBlockHeader &bh);
+ AString ReadString(UInt32 pos);
+ AString ReadString2(UInt32 pos);
+ HRESULT ReadEntries(const CBlockHeader &bh);
+ HRESULT Parse();
+
+ CByteBuffer _data;
+ UInt64 _size;
+
+ size_t _posInData;
+
+ UInt32 _stringsPos;
+
+
+ bool _headerIsCompressed;
+ UInt32 _nonSolidStartOffset;
+public:
+ HRESULT Open(IInStream *inStream, const UInt64 *maxCheckStartPosition);
+ void Clear();
+
+ UInt64 StreamOffset;
+ CDecoder Decoder;
+ CObjectVector<CItem> Items;
+ bool IsSolid;
+ CFirstHeader FirstHeader;
+ NMethodType::EEnum Method;
+ bool UseFilter;
+ UInt32 DictionarySize;
+ bool FilterFlag;
+
+ #ifdef NSIS_SCRIPT
+ AString Script;
+ #endif
+ UInt32 GetOffset() const { return IsSolid ? 4 : 0; }
+ UInt64 GetDataPos(int index)
+ {
+ const CItem &item = Items[index];
+ return GetOffset() + FirstHeader.HeaderLength + item.Pos;
+ }
+
+ UInt64 GetPosOfSolidItem(int index) const
+ {
+ const CItem &item = Items[index];
+ return 4 + FirstHeader.HeaderLength + item.Pos;
+ }
+
+ UInt64 GetPosOfNonSolidItem(int index) const
+ {
+ const CItem &item = Items[index];
+ return StreamOffset + _nonSolidStartOffset + 4 + item.Pos;
+ }
+
+ void Release()
+ {
+ Decoder.Release();
+ }
+
+};
+
+UInt32 GetUInt32FromMemLE(const Byte *p);
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Nsis/StdAfx.cpp b/CPP/7zip/Archive/Nsis/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Nsis/StdAfx.h b/CPP/7zip/Archive/Nsis/StdAfx.h
new file mode 100755
index 00000000..2e4be10b
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/Archive/Nsis/makefile b/CPP/7zip/Archive/Nsis/makefile
new file mode 100755
index 00000000..69fcf523
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/makefile
@@ -0,0 +1,67 @@
+PROG = nsis.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+TAR_OBJS = \
+ $O\DllExports.obj \
+ $O\NsisDecode.obj \
+ $O\NsisHandler.obj \
+ $O\NsisIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\FileFind.obj \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\LimitedStreams.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\CodecsPath.obj \
+ $O\CoderLoader.obj \
+ $O\ItemNameUtils.obj \
+ $O\FilterCoder.obj \
+
+7Z_OBJS = \
+ $O\7zMethodID.obj \
+ $O\7zMethods.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(TAR_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(7Z_OBJS) \
+ $(COMPRESS_TAR_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(TAR_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Nsis/resource.rc b/CPP/7zip/Archive/Nsis/resource.rc
new file mode 100755
index 00000000..487eb4ee
--- /dev/null
+++ b/CPP/7zip/Archive/Nsis/resource.rc
@@ -0,0 +1,3 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Nsis Plugin", "nsis")
diff --git a/CPP/7zip/Archive/RPM/DllExports.cpp b/CPP/7zip/Archive/RPM/DllExports.cpp
new file mode 100755
index 00000000..ed21e64f
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/DllExports.cpp
@@ -0,0 +1,68 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "RpmHandler.h"
+
+// {23170F69-40C1-278A-1000-000110EB0000}
+DEFINE_GUID(CLSID_CRpmHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEB, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CRpmHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NRpm::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Rpm";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CRpmHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"rpm";
+ break;
+ case NArchive::kAddExtension:
+ propVariant = L".cpio.gz";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/RPM/Rpm.dsp b/CPP/7zip/Archive/RPM/Rpm.dsp
new file mode 100755
index 00000000..085fe137
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/Rpm.dsp
@@ -0,0 +1,205 @@
+# Microsoft Developer Studio Project File - Name="Rpm" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Rpm - 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 "Rpm.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 "Rpm.mak" CFG="Rpm - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Rpm - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Rpm - 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)" == "Rpm - 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 "RPM_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "../../../" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RPM_EXPORTS" /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\rpm.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Rpm - 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 "RPM_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "../../../" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RPM_EXPORTS" /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\rpm.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Rpm - Win32 Release"
+# Name "Rpm - 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=.\Rpm.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "7-zip Common"
+
+# PROP Default_Filter ""
+# 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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# 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 "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\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\RpmHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RpmHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RpmHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RpmIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RpmIn.h
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/RPM/Rpm.dsw b/CPP/7zip/Archive/RPM/Rpm.dsw
new file mode 100755
index 00000000..a67232ed
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/Rpm.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Rpm"=.\Rpm.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/RPM/RpmHandler.cpp b/CPP/7zip/Archive/RPM/RpmHandler.cpp
new file mode 100755
index 00000000..b1a5bf7d
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/RpmHandler.cpp
@@ -0,0 +1,194 @@
+// RPM/Handler.cpp
+
+#include "StdAfx.h"
+
+#include "RpmHandler.h"
+#include "RpmIn.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamObjects.h"
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NRpm {
+
+STATPROPSTG kProperties[] =
+{
+// { NULL, kpidPath, VT_BSTR},
+// { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8}
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *inStream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ try
+ {
+ if(OpenArchive(inStream) != S_OK)
+ return S_FALSE;
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Pos));
+ m_InStream = inStream;
+ UInt64 endPosition;
+ RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPosition));
+ m_Size = endPosition - m_Pos;
+ return S_OK;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ m_InStream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+
+ switch(propID)
+ {
+ /*
+ case kpidPath:
+ propVariant = (const wchar_t *)L"a.cpio.gz";
+ break;
+ */
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ propVariant = m_Size;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = 1;
+ if(numItems == 0)
+ return S_OK;
+ if(numItems != 1)
+ return E_FAIL;
+ if (indices[0] != 0)
+ return E_FAIL;
+
+ bool testMode = (_aTestMode != 0);
+
+ UInt64 currentTotalSize = 0;
+ RINOK(extractCallback->SetTotal(m_Size));
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ Int32 index = 0;
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ if(!testMode && (!realOutStream))
+ return S_OK;
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ return S_OK;
+ }
+
+ RINOK(m_InStream->Seek(m_Pos, STREAM_SEEK_SET, NULL));
+
+ CMyComPtr<ICompressCoder> copyCoder = new NCompress::CCopyCoder;
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ try
+ {
+ RINOK(copyCoder->Code(m_InStream, realOutStream, NULL, NULL, progress));
+ }
+ catch(...)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ return S_OK;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/RPM/RpmHandler.h b/CPP/7zip/Archive/RPM/RpmHandler.h
new file mode 100755
index 00000000..484c6c54
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/RpmHandler.h
@@ -0,0 +1,46 @@
+// RPM/Handler.h
+
+#ifndef __RPM_HANDLER_H
+#define __RPM_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace NRpm {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+private:
+ CMyComPtr<IInStream> m_InStream;
+ UInt64 m_Pos;
+ UInt64 m_Size;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/RPM/RpmHeader.h b/CPP/7zip/Archive/RPM/RpmHeader.h
new file mode 100755
index 00000000..d76963bd
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/RpmHeader.h
@@ -0,0 +1,63 @@
+// Archive/RpmHeader.h
+
+#ifndef __ARCHIVE_RPM_HEADER_H
+#define __ARCHIVE_RPM_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NRpm {
+
+/* Reference: lib/signature.h of rpm package */
+#define RPMSIG_NONE 0 /* Do not change! */
+/* The following types are no longer generated */
+#define RPMSIG_PGP262_1024 1 /* No longer generated */ /* 256 byte */
+/* These are the new-style signatures. They are Header structures. */
+/* Inside them we can put any number of any type of signature we like. */
+
+#define RPMSIG_HEADERSIG 5 /* New Header style signature */
+
+const UInt32 kLeadSize = 96;
+struct CLead
+{
+ unsigned char Magic[4];
+ unsigned char Major; // not supported ver1, only support 2,3 and lator
+ unsigned char Minor;
+ UInt16 Type;
+ UInt16 ArchNum;
+ char Name[66];
+ UInt16 OSNum;
+ UInt16 SignatureType;
+ char Reserved[16]; // pad to 96 bytes -- 8 byte aligned
+ bool MagicCheck() const
+ { return Magic[0] == 0xed && Magic[1] == 0xab && Magic[2] == 0xee && Magic[3] == 0xdb; };
+};
+
+const UInt32 kEntryInfoSize = 16;
+/*
+struct CEntryInfo
+{
+ int Tag;
+ int Type;
+ int Offset; // Offset from beginning of data segment, only defined on disk
+ int Count;
+};
+*/
+
+// case: SignatureType == RPMSIG_HEADERSIG
+const UInt32 kCSigHeaderSigSize = 16;
+struct CSigHeaderSig
+{
+ unsigned char Magic[4];
+ UInt32 Reserved;
+ UInt32 IndexLen; // count of index entries
+ UInt32 DataLen; // number of bytes
+ bool MagicCheck()
+ { return Magic[0] == 0x8e && Magic[1] == 0xad && Magic[2] == 0xe8 && Magic[3] == 0x01; };
+ UInt32 GetLostHeaderLen()
+ { return IndexLen * kEntryInfoSize + DataLen; };
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/RPM/RpmIn.cpp b/CPP/7zip/Archive/RPM/RpmIn.cpp
new file mode 100755
index 00000000..c1600894
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/RpmIn.cpp
@@ -0,0 +1,112 @@
+// Archive/RpmIn.cpp
+
+#include "StdAfx.h"
+
+#include "RpmIn.h"
+
+#include "RpmHeader.h"
+
+#include "Windows/Defs.h"
+#include "Common/MyCom.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NRpm {
+
+static UInt16 GetUInt16(const char *data)
+{
+ return (UInt16)((Byte)data[1] | (((UInt16)(Byte)data[0]) << 8));
+}
+
+static UInt32 GetUInt32(const char *data)
+{
+ return
+ ((UInt32)(Byte)data[3]) |
+ (((UInt32)(Byte)data[2]) << 8) |
+ (((UInt32)(Byte)data[1]) << 16) |
+ (((UInt32)(Byte)data[0]) << 24);
+}
+
+static HRESULT RedSigHeaderSig(IInStream *inStream, CSigHeaderSig &h)
+{
+ char dat[kCSigHeaderSigSize];
+ char *cur = dat;
+ UInt32 processedSize;
+ RINOK(ReadStream(inStream, dat, kCSigHeaderSigSize, &processedSize));
+ if (kCSigHeaderSigSize != processedSize)
+ return S_FALSE;
+ memmove(h.Magic, cur, 4);
+ cur += 4;
+ cur += 4;
+ h.IndexLen = GetUInt32(cur);
+ cur += 4;
+ h.DataLen = GetUInt32(cur);
+ return S_OK;
+}
+
+HRESULT OpenArchive(IInStream *inStream)
+{
+ UInt64 pos;
+ char leadData[kLeadSize];
+ char *cur = leadData;
+ CLead lead;
+ UInt32 processedSize;
+ RINOK(ReadStream(inStream, leadData, kLeadSize, &processedSize));
+ if (kLeadSize != processedSize)
+ return S_FALSE;
+ memmove(lead.Magic, cur, 4);
+ cur += 4;
+ lead.Major = *cur++;
+ lead.Minor = *cur++;
+ lead.Type = GetUInt16(cur);
+ cur += 2;
+ lead.ArchNum = GetUInt16(cur);
+ cur += 2;
+ memmove(lead.Name, cur, sizeof(lead.Name));
+ cur += sizeof(lead.Name);
+ lead.OSNum = GetUInt16(cur);
+ cur += 2;
+ lead.SignatureType = GetUInt16(cur);
+ cur += 2;
+
+ if (!lead.MagicCheck() || lead.Major < 3)
+ return S_FALSE;
+
+ CSigHeaderSig sigHeader, header;
+ if(lead.SignatureType == RPMSIG_NONE)
+ {
+ ;
+ }
+ else if(lead.SignatureType == RPMSIG_PGP262_1024)
+ {
+ UInt64 pos;
+ RINOK(inStream->Seek(256, STREAM_SEEK_CUR, &pos));
+ }
+ else if(lead.SignatureType == RPMSIG_HEADERSIG)
+ {
+ RINOK(RedSigHeaderSig(inStream, sigHeader));
+ if(!sigHeader.MagicCheck())
+ return S_FALSE;
+ UInt32 len = sigHeader.GetLostHeaderLen();
+ RINOK(inStream->Seek(len, STREAM_SEEK_CUR, &pos));
+ if((pos % 8) != 0)
+ {
+ RINOK(inStream->Seek((pos / 8 + 1) * 8 - pos,
+ STREAM_SEEK_CUR, &pos));
+ }
+ }
+ else
+ return S_FALSE;
+
+ RINOK(RedSigHeaderSig(inStream, header));
+ if(!header.MagicCheck())
+ return S_FALSE;
+ int headerLen = header.GetLostHeaderLen();
+ if(headerLen == -1)
+ return S_FALSE;
+ RINOK(inStream->Seek(headerLen, STREAM_SEEK_CUR, &pos));
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/RPM/RpmIn.h b/CPP/7zip/Archive/RPM/RpmIn.h
new file mode 100755
index 00000000..ec798cb8
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/RpmIn.h
@@ -0,0 +1,15 @@
+// Archive/RpmIn.h
+
+#ifndef __ARCHIVE_RPM_IN_H
+#define __ARCHIVE_RPM_IN_H
+
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NRpm {
+
+HRESULT OpenArchive(IInStream *inStream);
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/RPM/StdAfx.cpp b/CPP/7zip/Archive/RPM/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/RPM/StdAfx.h b/CPP/7zip/Archive/RPM/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/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/RPM/makefile b/CPP/7zip/Archive/RPM/makefile
new file mode 100755
index 00000000..afda1289
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/makefile
@@ -0,0 +1,42 @@
+PROG = rpm.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib
+
+RPM_OBJS = \
+ $O\DllExports.obj \
+ $O\RpmHandler.obj \
+ $O\RpmIn.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(RPM_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(RPM_OBJS): $(*B).cpp
+ $(COMPL)
+$(COMMON_OBJS): ../../../Common/$(*B).cpp
+ $(COMPL)
+$(WIN_OBJS): ../../../Windows/$(*B).cpp
+ $(COMPL)
+$(7ZIP_COMMON_OBJS): ../../Common/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/RPM/resource.rc b/CPP/7zip/Archive/RPM/resource.rc
new file mode 100755
index 00000000..926f09aa
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Rpm Plugin", "rpm")
+
+101 ICON "rpm.ico"
diff --git a/CPP/7zip/Archive/RPM/rpm.ico b/CPP/7zip/Archive/RPM/rpm.ico
new file mode 100755
index 00000000..cdeb8d1b
--- /dev/null
+++ b/CPP/7zip/Archive/RPM/rpm.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Rar/DllExports.cpp b/CPP/7zip/Archive/Rar/DllExports.cpp
new file mode 100755
index 00000000..921bffb2
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/DllExports.cpp
@@ -0,0 +1,142 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "../../IPassword.h"
+#include "../Common/CodecsPath.h"
+
+// {23170F69-40C1-278B-0601-010000000000}
+DEFINE_GUID(CLSID_CCrypto_AES128_Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x06, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+#include "RarHandler.h"
+
+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);
+}
+
+
+// {23170F69-40C1-278B-0403-010000000000}
+DEFINE_GUID(CLSID_CCompressRar15Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+// {23170F69-40C1-278B-0403-020000000000}
+DEFINE_GUID(CLSID_CCompressRar20Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+// {23170F69-40C1-278B-0403-030000000000}
+DEFINE_GUID(CLSID_CCompressRar29Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+/*
+// {23170F69-40C1-278B-06F1-0302000000000}
+DEFINE_GUID(CLSID_CCryptoRar20Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00);
+
+// {23170F69-40C1-278B-06F1-0303000000000}
+DEFINE_GUID(CLSID_CCryptoRar29Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00);
+*/
+
+// {23170F69-40C1-278A-1000-000110030000}
+DEFINE_GUID(CLSID_CRarHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x03, 0x00, 0x00);
+
+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_CRarHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ if (needIn)
+ {
+ NArchive::NRar::CHandler *temp = new NArchive::NRar::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"Rar";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CRarHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"rar";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)NArchive::NRar::NHeader::kMarker,
+ NArchive::NRar::NHeader::kMarkerSize)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Rar/Rar.dsp b/CPP/7zip/Archive/Rar/Rar.dsp
new file mode 100755
index 00000000..739024da
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/Rar.dsp
@@ -0,0 +1,459 @@
+# Microsoft Developer Studio Project File - Name="Rar" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Rar - 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 "Rar.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 "Rar.mak" CFG="Rar - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Rar - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Rar - 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)" == "Rar - 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 "RAR_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RAR_EXPORTS" /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 0x419 /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\rar.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Rar - 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 "RAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "RAR_EXPORTS" /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 0x419 /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\rar.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Rar - Win32 Release"
+# Name "Rar - 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"StdAfx.h"
+# 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\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\DynamicBuffer.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\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\Types.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\UTFConvert.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 "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\FilterCoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\FilterCoder.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\IArchiveHandler.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\OutStreamWithCRC.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\OutStreamWithCRC.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\Handle.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 "Compress"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\RarHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarItem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarVolumeInStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\RarVolumeInStream.h
+# End Source File
+# End Group
+# Begin Group "Crypto"
+
+# PROP Default_Filter ""
+# Begin Group "Rar29"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Crypto\RarAES\RarAES.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\RarAES\RarAES.h
+# End Source File
+# End Group
+# Begin Group "Rar20"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Crypto\Rar20\Rar20Cipher.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\Rar20\Rar20Cipher.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\Rar20\Rar20Crypto.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\Rar20\Rar20Crypto.h
+# End Source File
+# End Group
+# Begin Group "Hash"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Crypto\Hash\Sha1.cpp
+
+!IF "$(CFG)" == "Rar - Win32 Release"
+
+# ADD CPP /O2
+# SUBTRACT CPP /YX /Yc /Yu
+
+!ELSEIF "$(CFG)" == "Rar - Win32 Debug"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Crypto\Hash\Sha1.h
+# End Source File
+# End Group
+# End Group
+# Begin Group "7-zip 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\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 "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 Source File
+
+SOURCE=.\Rar.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Rar/Rar.dsw b/CPP/7zip/Archive/Rar/Rar.dsw
new file mode 100755
index 00000000..3dab87aa
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/Rar.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Rar"=.\Rar.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Rar/RarHandler.cpp b/CPP/7zip/Archive/Rar/RarHandler.cpp
new file mode 100755
index 00000000..3389f0e2
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarHandler.cpp
@@ -0,0 +1,941 @@
+// RarHandler.cpp
+
+#include "StdAfx.h"
+
+#include "RarHandler.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+#include "Common/IntToString.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../../IPassword.h"
+
+#include "../../Common//ProgressUtils.h"
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../../Crypto/Rar20/Rar20Cipher.h"
+#include "../../Crypto/RarAES/RarAES.h"
+
+#include "../Common/OutStreamWithCRC.h"
+#include "../Common/CoderLoader.h"
+#include "../Common/CodecsPath.h"
+#include "../Common/FilterCoder.h"
+#include "../Common/ItemNameUtils.h"
+
+#include "../7z/7zMethods.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+// {23170F69-40C1-278B-0403-010000000000}
+DEFINE_GUID(CLSID_CCompressRar15Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+// {23170F69-40C1-278B-0403-020000000000}
+DEFINE_GUID(CLSID_CCompressRar20Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+// {23170F69-40C1-278B-0403-030000000000}
+DEFINE_GUID(CLSID_CCompressRar29Decoder,
+0x23170F69, 0x40C1, 0x278B, 0x04, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00);
+
+
+namespace NArchive {
+namespace NRar {
+
+static const wchar_t *kHostOS[] =
+{
+ L"MS DOS",
+ L"OS/2",
+ L"Win32",
+ L"Unix",
+ L"Mac OS",
+ L"BeOS"
+};
+
+static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]);
+
+static const wchar_t *kUnknownOS = L"Unknown";
+
+enum // PropID
+{
+ kpidUnPackVersion = kpidUserDefined
+};
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ { NULL, kpidCreationTime, VT_FILETIME},
+ { NULL, kpidLastAccessTime, VT_FILETIME},
+ { NULL, kpidAttributes, VT_UI4},
+
+
+ { NULL, kpidEncrypted, VT_BOOL},
+ { NULL, kpidSolid, VT_BOOL},
+ { NULL, kpidCommented, VT_BOOL},
+ { NULL, kpidSplitBefore, VT_BOOL},
+ { NULL, kpidSplitAfter, VT_BOOL},
+ { NULL, kpidCRC, VT_UI4},
+ { NULL, kpidHostOS, VT_BSTR},
+ { NULL, kpidMethod, VT_BSTR}
+ // { NULL, kpidDictionarySize, VT_UI4},
+ // { L"UnPack Version", kpidUnPackVersion, VT_UI1}
+};
+
+STATPROPSTG kArchiveProperties[] =
+{
+ { NULL, kpidSolid, VT_BOOL},
+ { NULL, kpidCommented, VT_BOOL},
+};
+
+UInt64 CHandler::GetPackSize(int refIndex) const
+{
+ const CRefItem &refItem = _refItems[refIndex];
+ UInt64 totalPackSize = 0;
+ for (int i = 0; i < refItem.NumItems; i++)
+ totalPackSize += _items[refItem.ItemIndex + i].PackSize;
+ return totalPackSize;
+}
+
+STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case kpidSolid:
+ propVariant = _archiveInfo.IsSolid();
+ break;
+ case kpidCommented:
+ propVariant = _archiveInfo.IsCommented();
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+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 = sizeof(kArchiveProperties) / sizeof(kArchiveProperties[0]);
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetArchivePropertyInfo(UInt32 index,
+ BSTR *name, PROPID *propID, VARTYPE *varType)
+{
+ if(index >= sizeof(kArchiveProperties) / sizeof(kArchiveProperties[0]))
+ return E_INVALIDARG;
+ const STATPROPSTG &srcItem = kArchiveProperties[index];
+ *propID = srcItem.propid;
+ *varType = srcItem.vt;
+ *name = 0;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _refItems.Size();
+ return S_OK;
+}
+
+static bool RarTimeToFileTime(const CRarTime &rarTime, FILETIME &result)
+{
+ if (!DosTimeToFileTime(rarTime.DosTime, result))
+ return false;
+ UInt64 value = (((UInt64)result.dwHighDateTime) << 32) + result.dwLowDateTime;
+ value += (UInt64)rarTime.LowSecond * 10000000;
+ value += ((UInt64)rarTime.SubTime[2] << 16) +
+ ((UInt64)rarTime.SubTime[1] << 8) +
+ ((UInt64)rarTime.SubTime[0]);
+ result.dwLowDateTime = (DWORD)value;
+ result.dwHighDateTime = DWORD(value >> 32);
+ return true;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ const CRefItem &refItem = _refItems[index];
+ const CItemEx &item = _items[refItem.ItemIndex];
+ switch(propID)
+ {
+ case kpidPath:
+ {
+ UString u;
+ if (item.HasUnicodeName() && !item.UnicodeName.IsEmpty())
+ u = item.UnicodeName;
+ else
+ u = MultiByteToUnicodeString(item.Name, CP_OEMCP);
+ propVariant = (const wchar_t *)NItemName::WinNameToOSName(u);
+ break;
+ }
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ propVariant = item.UnPackSize;
+ break;
+ case kpidPackedSize:
+ {
+ propVariant = GetPackSize(index);
+ break;
+ }
+ case kpidLastWriteTime:
+ {
+ FILETIME localFileTime, utcFileTime;
+ if (RarTimeToFileTime(item.LastWriteTime, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ propVariant = utcFileTime;
+ break;
+ }
+ case kpidCreationTime:
+ {
+ if (item.IsCreationTimeDefined)
+ {
+ FILETIME localFileTime, utcFileTime;
+ if (RarTimeToFileTime(item.CreationTime, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ propVariant = utcFileTime;
+ }
+ break;
+ }
+ case kpidLastAccessTime:
+ {
+ if (item.IsLastAccessTimeDefined)
+ {
+ FILETIME localFileTime, utcFileTime;
+ if (RarTimeToFileTime(item.LastAccessTime, localFileTime))
+ {
+ if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime))
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ }
+ else
+ utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0;
+ propVariant = utcFileTime;
+ }
+ break;
+ }
+ case kpidAttributes:
+ propVariant = item.GetWinAttributes();
+ break;
+ case kpidEncrypted:
+ propVariant = item.IsEncrypted();
+ break;
+ case kpidSolid:
+ propVariant = IsSolid(index);
+ break;
+ case kpidCommented:
+ propVariant = item.IsCommented();
+ break;
+ case kpidSplitBefore:
+ propVariant = item.IsSplitBefore();
+ break;
+ case kpidSplitAfter:
+ propVariant = _items[refItem.ItemIndex + refItem.NumItems - 1].IsSplitAfter();
+ break;
+ /*
+ case kpidDictionarySize:
+ if (!item.IsDirectory())
+ propVariant = UInt32(0x10000 << item.GetDictSize());
+ break;
+ */
+ case kpidCRC:
+ {
+ const CItemEx &lastItem =
+ _items[refItem.ItemIndex + refItem.NumItems - 1];
+ if (lastItem.IsSplitAfter())
+ propVariant = item.FileCRC;
+ else
+ propVariant = lastItem.FileCRC;
+ break;
+ }
+ case kpidUnPackVersion:
+ propVariant = item.UnPackVersion;
+ break;
+ case kpidMethod:
+ {
+ UString method;
+ if (item.Method >= Byte('0') && item.Method <= Byte('5'))
+ {
+ method = L"m";
+ wchar_t temp[32];
+ ConvertUInt64ToString(item.Method - Byte('0'), temp);
+ method += temp;
+ if (!item.IsDirectory())
+ {
+ method += L":";
+ ConvertUInt64ToString(16 + item.GetDictSize(), temp);
+ method += temp;
+ }
+ }
+ else
+ {
+ wchar_t temp[32];
+ ConvertUInt64ToString(item.Method, temp);
+ method += temp;
+ }
+ propVariant = method;
+ break;
+ }
+ case kpidHostOS:
+ propVariant = (item.HostOS < kNumHostOSes) ?
+ (kHostOS[item.HostOS]) : kUnknownOS;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+class CVolumeName
+{
+ bool _first;
+ bool _newStyle;
+ UString _unchangedPart;
+ UString _changedPart;
+ UString _afterPart;
+public:
+ CVolumeName(): _newStyle(true) {};
+
+ bool InitName(const UString &name, bool newStyle)
+ {
+ _first = true;
+ _newStyle = newStyle;
+ int dotPos = name.ReverseFind('.');
+ UString basePart = name;
+ if (dotPos >= 0)
+ {
+ UString ext = name.Mid(dotPos + 1);
+ if (ext.CompareNoCase(L"RAR")==0 ||
+ ext.CompareNoCase(L"EXE") == 0)
+ {
+ _afterPart = L".rar";
+ basePart = name.Left(dotPos);
+ }
+ }
+
+ if (!_newStyle)
+ {
+ _afterPart.Empty();
+ _unchangedPart = basePart + UString(L".");
+ _changedPart = L"r00";
+ return true;;
+ }
+
+ int numLetters = 1;
+ if (basePart.Right(numLetters) == L"1")
+ {
+ while (numLetters < basePart.Length())
+ {
+ if (basePart[basePart.Length() - numLetters - 1] != '0')
+ break;
+ numLetters++;
+ }
+ }
+ else
+ return false;
+ _unchangedPart = basePart.Left(basePart.Length() - numLetters);
+ _changedPart = basePart.Right(numLetters);
+ return true;
+ }
+
+ UString GetNextName()
+ {
+ UString newName;
+ if (_newStyle || !_first)
+ {
+ int i;
+ int numLetters = _changedPart.Length();
+ for (i = numLetters - 1; i >= 0; i--)
+ {
+ wchar_t c = _changedPart[i];
+ if (c == L'9')
+ {
+ c = L'0';
+ newName = c + newName;
+ if (i == 0)
+ newName = UString(L'1') + newName;
+ continue;
+ }
+ c++;
+ newName = UString(c) + newName;
+ i--;
+ for (; i >= 0; i--)
+ newName = _changedPart[i] + newName;
+ break;
+ }
+ _changedPart = newName;
+ }
+ _first = false;
+ return _unchangedPart + _changedPart + _afterPart;
+ }
+};
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ try
+ {
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ CMyComPtr<ICryptoGetTextPassword> getTextPassword;
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
+
+ CVolumeName seqName;
+
+ if (openArchiveCallback != NULL)
+ {
+ openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
+ RINOK(openArchiveCallback->SetTotal(NULL, NULL));
+ UInt64 numFiles = _items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ openArchiveCallbackWrap.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword);
+ }
+
+ for (;;)
+ {
+ CMyComPtr<IInStream> inStream;
+ if (!_archives.IsEmpty())
+ {
+ if (!openVolumeCallback)
+ break;
+
+ if(_archives.Size() == 1)
+ {
+ if (!_archiveInfo.IsVolume())
+ break;
+ UString baseName;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant));
+ if (propVariant.vt != VT_BSTR)
+ break;
+ baseName = propVariant.bstrVal;
+ }
+ seqName.InitName(baseName, _archiveInfo.HaveNewVolumeName());
+ }
+
+ UString fullName = seqName.GetNextName();
+ HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!stream)
+ break;
+ }
+ else
+ inStream = stream;
+
+ NArchive::NRar::CInArchive archive;
+ if(!archive.Open(inStream, maxCheckStartPosition))
+ return S_FALSE;
+
+ if (_archives.IsEmpty())
+ archive.GetArchiveInfo(_archiveInfo);
+
+ CItemEx item;
+ for (;;)
+ {
+ HRESULT result = archive.GetNextItem(item, getTextPassword);
+ if (result == S_FALSE)
+ break;
+ RINOK(result);
+ if (item.IgnoreItem())
+ continue;
+
+ bool needAdd = true;
+ if (item.IsSplitBefore())
+ {
+ if (!_refItems.IsEmpty())
+ {
+ CRefItem &refItem = _refItems.Back();
+ refItem.NumItems++;
+ needAdd = false;
+ }
+ }
+ if (needAdd)
+ {
+ CRefItem refItem;
+ refItem.ItemIndex = _items.Size();
+ refItem.NumItems = 1;
+ refItem.VolumeIndex = _archives.Size();
+ _refItems.Add(refItem);
+ }
+ _items.Add(item);
+ if (openArchiveCallback != NULL)
+ {
+ UInt64 numFiles = _items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ _archives.Add(archive);
+ }
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ COM_TRY_BEGIN
+ _refItems.Clear();
+ _items.Clear();
+ _archives.Clear();
+ return S_OK;
+ COM_TRY_END
+}
+
+struct CMethodItem
+{
+ Byte RarUnPackVersion;
+ 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 censoredTotalUnPacked = 0,
+ // censoredTotalPacked = 0,
+ importantTotalUnPacked = 0;
+ // importantTotalPacked = 0;
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = _refItems.Size();
+ if(numItems == 0)
+ return S_OK;
+ int lastIndex = 0;
+ CRecordVector<int> importantIndexes;
+ CRecordVector<bool> extractStatuses;
+
+ for(UInt32 t = 0; t < numItems; t++)
+ {
+ int index = allFilesMode ? t : indices[t];
+ const CRefItem &refItem = _refItems[index];
+ const CItemEx &item = _items[refItem.ItemIndex];
+ censoredTotalUnPacked += item.UnPackSize;
+ // censoredTotalPacked += item.PackSize;
+ int j;
+ for(j = lastIndex; j <= index; j++)
+ // if(!_items[_refItems[j].ItemIndex].IsSolid())
+ if(!IsSolid(j))
+ lastIndex = j;
+ for(j = lastIndex; j <= index; j++)
+ {
+ const CRefItem &refItem = _refItems[j];
+ const CItemEx &item = _items[refItem.ItemIndex];
+
+ // const CItemEx &item = _items[j];
+
+ importantTotalUnPacked += item.UnPackSize;
+ // importantTotalPacked += item.PackSize;
+ importantIndexes.Add(j);
+ extractStatuses.Add(j == index);
+ }
+ lastIndex = index + 1;
+ }
+
+ extractCallback->SetTotal(importantTotalUnPacked);
+ UInt64 currentImportantTotalUnPacked = 0;
+ UInt64 currentImportantTotalPacked = 0;
+ UInt64 currentUnPackSize, currentPackSize;
+
+ /*
+ CSysString path = GetCodecsFolderPrefix() + TEXT("Rar29.dll");
+ TCHAR compressLibPath[MAX_PATH + 64];
+ if (!GetCompressFolderPrefix(compressLibPath))
+ return ::GetLastError();
+ lstrcat(compressLibPath, TEXT("Rar29.dll"));
+ */
+ N7z::LoadMethodMap();
+ CCoderLibraries libraries;
+ CObjectVector<CMethodItem> methodItems;
+
+ /*
+ CCoderLibrary compressLib;
+ CMyComPtr<ICompressCoder> decoder15;
+ CMyComPtr<ICompressCoder> decoder20;
+ CMyComPtr<ICompressCoder> decoder29;
+ */
+
+ NCompress::CCopyCoder *copyCoderSpec = NULL;
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ // CCoderMixer *mixerCoderSpec;
+ // CMyComPtr<ICompressCoder> mixerCoder;
+ // bool mixerCoderStoreMethod;
+ // int mixerCryptoVersion;
+
+ CFilterCoder *filterStreamSpec = new CFilterCoder;
+ CMyComPtr<ISequentialInStream> filterStream = filterStreamSpec;
+
+ NCrypto::NRar20::CDecoder *rar20CryptoDecoderSpec = NULL;
+ CMyComPtr<ICompressFilter> rar20CryptoDecoder;
+ NCrypto::NRar29::CDecoder *rar29CryptoDecoderSpec = NULL;
+ CMyComPtr<ICompressFilter> rar29CryptoDecoder;
+
+ CFolderInStream *folderInStreamSpec = NULL;
+ CMyComPtr<ISequentialInStream> folderInStream;
+
+ for(int i = 0; i < importantIndexes.Size(); i++,
+ currentImportantTotalUnPacked += currentUnPackSize,
+ currentImportantTotalPacked += currentPackSize)
+ {
+ RINOK(extractCallback->SetCompleted(
+ &currentImportantTotalUnPacked));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+
+ Int32 askMode;
+ if(extractStatuses[i])
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ else
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+
+ UInt32 index = importantIndexes[i];
+
+ const CRefItem &refItem = _refItems[index];
+ const CItemEx &item = _items[refItem.ItemIndex];
+
+ currentUnPackSize = item.UnPackSize;
+
+ currentPackSize = GetPackSize(index);
+
+ if(item.IgnoreItem())
+ continue;
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ if(item.IsDirectory())
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ bool mustBeProcessedAnywhere = false;
+ if(i < importantIndexes.Size() - 1)
+ {
+ // const CRefItem &nextRefItem = _refItems[importantIndexes[i + 1]];
+ // const CItemEx &nextItemInfo = _items[nextRefItem.ItemIndex];
+ // mustBeProcessedAnywhere = nextItemInfo.IsSolid();
+ mustBeProcessedAnywhere = IsSolid(importantIndexes[i + 1]);
+ }
+
+ if (!mustBeProcessedAnywhere && !testMode && !realOutStream)
+ continue;
+
+ if (!realOutStream && !testMode)
+ askMode = NArchive::NExtract::NAskMode::kSkip;
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+
+ COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->SetStream(realOutStream);
+ outStreamSpec->Init();
+ realOutStream.Release();
+
+ UInt64 packedPos = currentImportantTotalPacked;
+ UInt64 unpackedPos = currentImportantTotalUnPacked;
+
+ /*
+ for (int partIndex = 0; partIndex < 1; partIndex++)
+ {
+ CMyComPtr<ISequentialInStream> inStream;
+
+ // item redefinition
+ const CItemEx &item = _items[refItem.ItemIndex + partIndex];
+
+ NArchive::NRar::CInArchive &archive = _archives[refItem.VolumeIndex + partIndex];
+
+ inStream.Attach(archive.CreateLimitedStream(item.GetDataPosition(),
+ item.PackSize));
+ */
+ if (!folderInStream)
+ {
+ folderInStreamSpec = new CFolderInStream;
+ folderInStream = folderInStreamSpec;
+ }
+
+ folderInStreamSpec->Init(&_archives, &_items, refItem);
+
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress,
+ &packedPos,
+ &unpackedPos);
+
+ UInt64 packSize = currentPackSize;
+
+ // packedPos += item.PackSize;
+ // unpackedPos += 0;
+
+ CMyComPtr<ISequentialInStream> inStream;
+ if (item.IsEncrypted())
+ {
+ CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
+ if (item.UnPackVersion >= 29)
+ {
+ if (!rar29CryptoDecoder)
+ {
+ rar29CryptoDecoderSpec = new NCrypto::NRar29::CDecoder;
+ rar29CryptoDecoder = rar29CryptoDecoderSpec;
+ // RINOK(rar29CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar29Decoder));
+ }
+ rar29CryptoDecoderSpec->SetRar350Mode(item.UnPackVersion < 36);
+ CMyComPtr<ICompressSetDecoderProperties2> cryptoProperties;
+ RINOK(rar29CryptoDecoder.QueryInterface(IID_ICompressSetDecoderProperties2,
+ &cryptoProperties));
+ RINOK(cryptoProperties->SetDecoderProperties2(item.Salt, item.HasSalt() ? sizeof(item.Salt) : 0));
+ filterStreamSpec->Filter = rar29CryptoDecoder;
+ }
+ else if (item.UnPackVersion >= 20)
+ {
+ if (!rar20CryptoDecoder)
+ {
+ rar20CryptoDecoderSpec = new NCrypto::NRar20::CDecoder;
+ rar20CryptoDecoder = rar20CryptoDecoderSpec;
+ // RINOK(rar20CryptoDecoder.CoCreateInstance(CLSID_CCryptoRar20Decoder));
+ }
+ filterStreamSpec->Filter = rar20CryptoDecoder;
+ }
+ else
+ {
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ RINOK(filterStreamSpec->Filter.QueryInterface(IID_ICryptoSetPassword,
+ &cryptoSetPassword));
+
+ if (!getTextPassword)
+ extractCallback.QueryInterface(IID_ICryptoGetTextPassword,
+ &getTextPassword);
+ if (getTextPassword)
+ {
+ CMyComBSTR password;
+ RINOK(getTextPassword->CryptoGetTextPassword(&password));
+ if (item.UnPackVersion >= 29)
+ {
+ CByteBuffer buffer;
+ UString unicodePassword(password);
+ const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+ buffer.SetCapacity(sizeInBytes);
+ for (int i = 0; i < unicodePassword.Length(); i++)
+ {
+ wchar_t c = unicodePassword[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+ RINOK(cryptoSetPassword->CryptoSetPassword(
+ (const Byte *)buffer, sizeInBytes));
+ }
+ else
+ {
+ AString oemPassword = UnicodeStringToMultiByte(
+ (const wchar_t *)password, CP_OEMCP);
+ RINOK(cryptoSetPassword->CryptoSetPassword(
+ (const Byte *)(const char *)oemPassword, oemPassword.Length()));
+ }
+ }
+ else
+ {
+ RINOK(cryptoSetPassword->CryptoSetPassword(0, 0));
+ }
+ filterStreamSpec->SetInStream(folderInStream);
+ inStream = filterStream;
+ }
+ else
+ {
+ inStream = folderInStream;
+ }
+ CMyComPtr<ICompressCoder> commonCoder;
+ switch(item.Method)
+ {
+ case '0':
+ {
+ if(copyCoderSpec == NULL)
+ {
+ copyCoderSpec = new NCompress::CCopyCoder;
+ copyCoder = copyCoderSpec;
+ }
+ commonCoder = copyCoder;
+ break;
+ }
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ {
+ /*
+ if (item.UnPackVersion >= 29)
+ {
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ */
+ int m;
+ for (m = 0; m < methodItems.Size(); m++)
+ if (methodItems[m].RarUnPackVersion == item.UnPackVersion)
+ break;
+ if (m == methodItems.Size())
+ {
+ CMethodItem mi;
+ mi.RarUnPackVersion = item.UnPackVersion;
+ N7z::CMethodID methodID = { { 0x04, 0x03 } , 3 };
+
+ Byte myID;
+ if (item.UnPackVersion < 20)
+ myID = 1;
+ else if (item.UnPackVersion < 29)
+ myID = 2;
+ else
+ myID = 3;
+ methodID.ID[2] = myID;
+ 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));
+ m = methodItems.Add(mi);
+ }
+ CMyComPtr<ICompressCoder> decoder = methodItems[m].Coder;
+
+ CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
+ RINOK(decoder.QueryInterface(IID_ICompressSetDecoderProperties2,
+ &compressSetDecoderProperties));
+
+ Byte isSolid = (Byte)((IsSolid(index) || item.IsSplitBefore()) ? 1: 0);
+
+ RINOK(compressSetDecoderProperties->SetDecoderProperties2(&isSolid, 1));
+
+ commonCoder = decoder;
+ break;
+ }
+ default:
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kUnSupportedMethod));
+ continue;
+ }
+ HRESULT result = commonCoder->Code(inStream, outStream,
+ &packSize, &item.UnPackSize, compressProgress);
+ if (item.IsEncrypted())
+ filterStreamSpec->ReleaseInStream();
+ if (result == S_FALSE)
+ {
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ if (result != S_OK)
+ return result;
+
+ /*
+ if (refItem.NumItems == 1 &&
+ !item.IsSplitBefore() && !item.IsSplitAfter())
+ */
+ {
+ const CItemEx &lastItem = _items[refItem.ItemIndex + refItem.NumItems - 1];
+ bool crcOK = outStreamSpec->GetCRC() == lastItem.FileCRC;
+ outStream.Release();
+ RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK:
+ NArchive::NExtract::NOperationResult::kCRCError));
+ }
+ /*
+ else
+ {
+ bool crcOK = true;
+ for (int partIndex = 0; partIndex < refItem.NumItems; partIndex++)
+ {
+ const CItemEx &item = _items[refItem.ItemIndex + partIndex];
+ if (item.FileCRC != folderInStreamSpec->CRCs[partIndex])
+ {
+ crcOK = false;
+ break;
+ }
+ }
+ RINOK(extractCallback->SetOperationResult(crcOK ? NArchive::NExtract::NOperationResult::kOK:
+ NArchive::NExtract::NOperationResult::kCRCError));
+ }
+ */
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+/*
+STDMETHODIMP CHandler::ExtractAllItems(Int32 testMode,
+ IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ CRecordVector<UInt32> indices;
+ indices.Reserve(_refItems.Size());
+ for(int i = 0; i < _refItems.Size(); i++)
+ indices.Add(i);
+ return Extract(&indices.Front(), _refItems.Size(), testMode, extractCallback);
+ COM_TRY_END
+}
+*/
+
+}}
diff --git a/CPP/7zip/Archive/Rar/RarHandler.h b/CPP/7zip/Archive/Rar/RarHandler.h
new file mode 100755
index 00000000..ea13e01e
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarHandler.h
@@ -0,0 +1,63 @@
+// Rar/Handler.h
+
+#ifndef __RAR_HANDLER_H
+#define __RAR_HANDLER_H
+
+#include "../IArchive.h"
+#include "RarIn.h"
+#include "RarVolumeInStream.h"
+
+namespace NArchive {
+namespace NRar {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ 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);
+
+private:
+ CRecordVector<CRefItem> _refItems;
+ CObjectVector<CItemEx> _items;
+ CObjectVector<CInArchive> _archives;
+ NArchive::NRar::CInArchiveInfo _archiveInfo;
+
+ UInt64 GetPackSize(int refIndex) const;
+ // NArchive::NRar::CInArchive _archive;
+
+ bool IsSolid(int refIndex)
+ {
+ const CItemEx &item = _items[_refItems[refIndex].ItemIndex];
+ if (item.UnPackVersion < 20)
+ {
+ if (_archiveInfo.IsSolid())
+ return (refIndex > 0);
+ return false;
+ }
+ return item.IsSolid();
+ }
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Rar/RarHeader.cpp b/CPP/7zip/Archive/Rar/RarHeader.cpp
new file mode 100755
index 00000000..94481e02
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarHeader.cpp
@@ -0,0 +1,21 @@
+// Archive/Rar/Headers.cpp
+
+#include "StdAfx.h"
+
+#include "RarHeader.h"
+
+namespace NArchive{
+namespace NRar{
+namespace NHeader{
+
+Byte kMarker[kMarkerSize] = {0x52 + 1, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00};
+
+class CMarkerInitializer
+{
+public:
+ CMarkerInitializer() { kMarker[0]--; };
+};
+
+static CMarkerInitializer markerInitializer;
+
+}}}
diff --git a/CPP/7zip/Archive/Rar/RarHeader.h b/CPP/7zip/Archive/Rar/RarHeader.h
new file mode 100755
index 00000000..832a21c0
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarHeader.h
@@ -0,0 +1,224 @@
+// Archive/RarHeader.h
+
+#ifndef __ARCHIVE_RAR_HEADER_H
+#define __ARCHIVE_RAR_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive{
+namespace NRar{
+namespace NHeader{
+
+const int kMarkerSize = 7;
+extern Byte kMarker[kMarkerSize];
+
+const int kArchiveSolid = 0x1;
+
+namespace NBlockType
+{
+ enum EBlockType
+ {
+ kMarker = 0x72,
+ kArchiveHeader = 0x73,
+ kFileHeader = 0x74,
+ kCommentHeader = 0x75,
+ kOldAuthenticity = 0x76,
+ kSubBlock = 0x77,
+ kRecoveryRecord = 0x78,
+ kAuthenticity = 0x79,
+
+ kEndOfArchive = 0x7B // Is not safe
+ };
+}
+
+namespace NArchive
+{
+ const UInt16 kVolume = 1;
+ const UInt16 kComment = 2;
+ const UInt16 kLock = 4;
+ const UInt16 kSolid = 8;
+ const UInt16 kNewVolName = 0x10; // ('volname.partN.rar')
+ const UInt16 kAuthenticity = 0x20;
+ const UInt16 kRecovery = 0x40;
+ const UInt16 kBlockEncryption = 0x80;
+ const UInt16 kFirstVolume = 0x100; // (set only by RAR 3.0 and later)
+ const UInt16 kEncryptVer = 0x200; // RAR 3.6 there is EncryptVer Byte in End of MainHeader
+
+ const int kHeaderSizeMin = 7;
+
+ struct CBlock
+ {
+ UInt16 CRC;
+ Byte Type;
+ UInt16 Flags;
+ UInt16 Size;
+ UInt16 Reserved1;
+ UInt32 Reserved2;
+ // UInt16 GetRealCRC() const;
+ };
+
+ const int kArchiveHeaderSize = 13;
+
+ const int kBlockHeadersAreEncrypted = 0x80;
+
+ struct CHeader360: public CBlock
+ {
+ Byte EncryptVersion;
+ bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
+ bool IsThereEncryptVer() const { return (Flags & NHeader::NArchive::kEncryptVer) != 0; }
+ bool IsEncryptOld() const { return (!IsThereEncryptVer() || EncryptVersion < 36); }
+ UInt32 GetBaseSize() const { return kArchiveHeaderSize + (IsEncryptOld() ? 0 : 1); }
+ };
+}
+
+namespace NFile
+{
+ const int kSplitBefore = 1 << 0;
+ const int kSplitAfter = 1 << 1;
+ const int kEncrypted = 1 << 2;
+ const int kComment = 1 << 3;
+ const int kSolid = 1 << 4;
+
+ const int kDictBitStart = 5;
+ const int kNumDictBits = 3;
+ const int kDictMask = (1 << kNumDictBits) - 1;
+ const int kDictDirectoryValue = 0x7;
+
+ const int kSize64Bits = 1 << 8;
+ const int kUnicodeName = 1 << 9;
+ const int kSalt = 1 << 10;
+ const int kOldVersion = 1 << 11;
+ const int kExtTime = 1 << 12;
+ // const int kExtFlags = 1 << 13;
+ // const int kSkipIfUnknown = 1 << 14;
+
+ const int kLongBlock = 1 << 15;
+
+ /*
+ struct CBlock
+ {
+ // UInt16 HeadCRC;
+ // Byte Type;
+ // UInt16 Flags;
+ // UInt16 HeadSize;
+ UInt32 PackSize;
+ UInt32 UnPackSize;
+ Byte HostOS;
+ UInt32 FileCRC;
+ UInt32 Time;
+ Byte UnPackVersion;
+ Byte Method;
+ UInt16 NameSize;
+ UInt32 Attributes;
+ };
+ */
+
+ /*
+ struct CBlock32
+ {
+ UInt16 HeadCRC;
+ Byte Type;
+ UInt16 Flags;
+ UInt16 HeadSize;
+ UInt32 PackSize;
+ UInt32 UnPackSize;
+ Byte HostOS;
+ UInt32 FileCRC;
+ UInt32 Time;
+ Byte UnPackVersion;
+ Byte Method;
+ UInt16 NameSize;
+ UInt32 Attributes;
+ UInt16 GetRealCRC(const void *aName, UInt32 aNameSize,
+ bool anExtraDataDefined = false, Byte *anExtraData = 0) const;
+ };
+ struct CBlock64
+ {
+ UInt16 HeadCRC;
+ Byte Type;
+ UInt16 Flags;
+ UInt16 HeadSize;
+ UInt32 PackSizeLow;
+ UInt32 UnPackSizeLow;
+ Byte HostOS;
+ UInt32 FileCRC;
+ UInt32 Time;
+ Byte UnPackVersion;
+ Byte Method;
+ UInt16 NameSize;
+ UInt32 Attributes;
+ UInt32 PackSizeHigh;
+ UInt32 UnPackSizeHigh;
+ UInt16 GetRealCRC(const void *aName, UInt32 aNameSize) const;
+ };
+ */
+
+ const int kLabelFileAttribute = 0x08;
+ const int kWinFileDirectoryAttributeMask = 0x10;
+
+ enum CHostOS
+ {
+ kHostMSDOS = 0,
+ kHostOS2 = 1,
+ kHostWin32 = 2,
+ kHostUnix = 3,
+ kHostMacOS = 4,
+ kHostBeOS = 5
+ };
+}
+
+namespace NBlock
+{
+ const UInt16 kLongBlock = 1 << 15;
+ struct CBlock
+ {
+ UInt16 CRC;
+ Byte Type;
+ UInt16 Flags;
+ UInt16 HeadSize;
+ // UInt32 DataSize;
+ };
+}
+
+/*
+struct CSubBlock
+{
+ UInt16 HeadCRC;
+ Byte HeadType;
+ UInt16 Flags;
+ UInt16 HeadSize;
+ UInt32 DataSize;
+ UInt16 SubType;
+ Byte Level; // Reserved : Must be 0
+};
+
+struct CCommentBlock
+{
+ UInt16 HeadCRC;
+ Byte HeadType;
+ UInt16 Flags;
+ UInt16 HeadSize;
+ UInt16 UnpSize;
+ Byte UnpVer;
+ Byte Method;
+ UInt16 CommCRC;
+};
+
+
+struct CProtectHeader
+{
+ UInt16 HeadCRC;
+ Byte HeadType;
+ UInt16 Flags;
+ UInt16 HeadSize;
+ UInt32 DataSize;
+ Byte Version;
+ UInt16 RecSectors;
+ UInt32 TotalBlocks;
+ Byte Mark[8];
+};
+*/
+
+}}}
+
+#endif
diff --git a/CPP/7zip/Archive/Rar/RarIn.cpp b/CPP/7zip/Archive/Rar/RarIn.cpp
new file mode 100755
index 00000000..9a88feb7
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarIn.cpp
@@ -0,0 +1,535 @@
+// Archive/RarIn.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/CRC.h"
+#include "Common/UTFConvert.h"
+
+#include "RarIn.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NRar {
+
+static const char kEndOfString = '\0';
+
+void CInArchive::ThrowExceptionWithCode(
+ CInArchiveException::CCauseType cause)
+{
+ throw CInArchiveException(cause);
+}
+
+bool CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)
+{
+ m_CryptoMode = false;
+ if(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition) != S_OK)
+ return false;
+ m_Position = m_StreamStartPosition;
+ m_Stream = inStream;
+ if (ReadMarkerAndArchiveHeader(searchHeaderSizeLimit))
+ return true;
+ m_Stream.Release();
+ return false;
+}
+
+void CInArchive::Close()
+{
+ m_Stream.Release();
+}
+
+
+static inline bool TestMarkerCandidate(const void *aTestBytes)
+{
+ for (UInt32 i = 0; i < NHeader::kMarkerSize; i++)
+ if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i])
+ return false;
+ return true;
+}
+
+bool CInArchive::FindAndReadMarker(const UInt64 *searchHeaderSizeLimit)
+{
+ // if (m_Length < NHeader::kMarkerSize)
+ // return false;
+ m_ArchiveStartPosition = 0;
+ m_Position = m_StreamStartPosition;
+ if(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL) != S_OK)
+ return false;
+
+ Byte marker[NHeader::kMarkerSize];
+ UInt32 processedSize;
+ ReadBytes(marker, NHeader::kMarkerSize, &processedSize);
+ if(processedSize != NHeader::kMarkerSize)
+ return false;
+ if (TestMarkerCandidate(marker))
+ return true;
+
+ CByteDynamicBuffer dynamicBuffer;
+ static const UInt32 kSearchMarkerBufferSize = 0x10000;
+ dynamicBuffer.EnsureCapacity(kSearchMarkerBufferSize);
+ Byte *buffer = dynamicBuffer;
+ UInt32 numBytesPrev = NHeader::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 < NHeader::kMarkerSize)
+ break;
+ UInt32 numTests = numBytesInBuffer - NHeader::kMarkerSize + 1;
+ for(UInt32 pos = 0; pos < numTests; pos++, curTestPos++)
+ {
+ if (TestMarkerCandidate(buffer + pos))
+ {
+ m_ArchiveStartPosition = curTestPos;
+ m_Position = curTestPos + NHeader::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);
+ }
+ return false;
+}
+
+void CInArchive::ThrowUnexpectedEndOfArchiveException()
+{
+ ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive);
+}
+
+bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
+{
+ if (m_CryptoMode)
+ {
+ const Byte *bufData = (const Byte *)m_DecryptedData;
+ UInt32 bufSize = m_DecryptedDataSize;
+ UInt32 i;
+ for (i = 0; i < size && m_CryptoPos < bufSize; i++)
+ ((Byte *)data)[i] = bufData[m_CryptoPos++];
+ return (i == size);
+ }
+ UInt32 processedSize;
+ ReadStream(m_Stream, data, size, &processedSize);
+ return (processedSize == size);
+}
+
+void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size)
+{
+ if(!ReadBytesAndTestSize(data,size))
+ ThrowUnexpectedEndOfArchiveException();
+}
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize;
+ HRESULT result = ReadStream(m_Stream, data, size, &realProcessedSize);
+ if(processedSize != NULL)
+ *processedSize = realProcessedSize;
+ AddToSeekValue(realProcessedSize);
+ return result;
+}
+
+bool CInArchive::ReadMarkerAndArchiveHeader(const UInt64 *searchHeaderSizeLimit)
+{
+ if (!FindAndReadMarker(searchHeaderSizeLimit))
+ return false;
+
+ Byte buf[NHeader::NArchive::kArchiveHeaderSize];
+ UInt32 processedSize;
+ ReadBytes(buf, sizeof(buf), &processedSize);
+ if (processedSize != sizeof(buf))
+ return false;
+ m_CurData = buf;
+ m_CurPos = 0;
+ m_PosLimit = sizeof(buf);
+
+ m_ArchiveHeader.CRC = ReadUInt16();
+ m_ArchiveHeader.Type = ReadByte();
+ m_ArchiveHeader.Flags = ReadUInt16();
+ m_ArchiveHeader.Size = ReadUInt16();
+ m_ArchiveHeader.Reserved1 = ReadUInt16();
+ m_ArchiveHeader.Reserved2 = ReadUInt32();
+ m_ArchiveHeader.EncryptVersion = 0;
+
+ CCRC crc;
+ crc.UpdateByte(m_ArchiveHeader.Type);
+ crc.UpdateUInt16(m_ArchiveHeader.Flags);
+ crc.UpdateUInt16(m_ArchiveHeader.Size);
+ crc.UpdateUInt16(m_ArchiveHeader.Reserved1);
+ crc.UpdateUInt32(m_ArchiveHeader.Reserved2);
+
+ if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize)
+ {
+ ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize);
+ if (processedSize != 1)
+ return false;
+ crc.UpdateByte(m_ArchiveHeader.EncryptVersion);
+ }
+
+ if(m_ArchiveHeader.CRC != (crc.GetDigest() & 0xFFFF))
+ ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError);
+ if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)
+ return false;
+ m_ArchiveCommentPosition = m_Position;
+ m_SeekOnArchiveComment = true;
+ return true;
+}
+
+void CInArchive::SkipArchiveComment()
+{
+ if (!m_SeekOnArchiveComment)
+ return;
+ AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize());
+ m_SeekOnArchiveComment = false;
+}
+
+void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
+{
+ archiveInfo.StartPosition = m_ArchiveStartPosition;
+ archiveInfo.Flags = m_ArchiveHeader.Flags;
+ archiveInfo.CommentPosition = m_ArchiveCommentPosition;
+ archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize);
+}
+
+static void DecodeUnicodeFileName(const char *name, const Byte *encName,
+ int encSize, wchar_t *unicodeName, int maxDecSize)
+{
+ int encPos = 0;
+ int decPos = 0;
+ int flagBits = 0;
+ Byte flags = 0;
+ Byte highByte = encName[encPos++];
+ while (encPos < encSize && decPos < maxDecSize)
+ {
+ if (flagBits == 0)
+ {
+ flags = encName[encPos++];
+ flagBits = 8;
+ }
+ switch(flags >> 6)
+ {
+ case 0:
+ unicodeName[decPos++] = encName[encPos++];
+ break;
+ case 1:
+ unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
+ break;
+ case 2:
+ unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
+ encPos += 2;
+ break;
+ case 3:
+ {
+ int length = encName[encPos++];
+ if (length & 0x80)
+ {
+ Byte correction = encName[encPos++];
+ for (length = (length & 0x7f) + 2;
+ length > 0 && decPos < maxDecSize; length--, decPos++)
+ unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
+ }
+ else
+ for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)
+ unicodeName[decPos] = name[decPos];
+ }
+ break;
+ }
+ flags <<= 2;
+ flagBits -= 2;
+ }
+ unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
+}
+
+void CInArchive::ReadName(CItemEx &item, int nameSize)
+{
+ item.UnicodeName.Empty();
+ if (nameSize > 0)
+ {
+ m_NameBuffer.EnsureCapacity(nameSize + 1);
+ char *buffer = (char *)m_NameBuffer;
+
+ for (int i = 0; i < nameSize; i++)
+ buffer[i] = ReadByte();
+
+ int mainLen;
+ for (mainLen = 0; mainLen < nameSize; mainLen++)
+ if (buffer[mainLen] == '\0')
+ break;
+ buffer[mainLen] = '\0';
+ item.Name = buffer;
+
+ if(item.HasUnicodeName())
+ {
+ if(mainLen < nameSize)
+ {
+ int unicodeNameSizeMax = MyMin(nameSize, (0x400));
+ _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);
+ DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,
+ nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);
+ item.UnicodeName = _unicodeNameBuffer;
+ }
+ else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
+ item.UnicodeName.Empty();
+ }
+ }
+ else
+ item.Name.Empty();
+}
+
+Byte CInArchive::ReadByte()
+{
+ if (m_CurPos >= m_PosLimit)
+ throw CInArchiveException(CInArchiveException::kIncorrectArchive);
+ return m_CurData[m_CurPos++];
+}
+
+UInt16 CInArchive::ReadUInt16()
+{
+ UInt16 value = 0;
+ for (int i = 0; i < 2; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt16(b) << (8 * i));
+ }
+ return value;
+}
+
+UInt32 CInArchive::ReadUInt32()
+{
+ UInt32 value = 0;
+ for (int i = 0; i < 4; i++)
+ {
+ Byte b = ReadByte();
+ value |= (UInt32(b) << (8 * i));
+ }
+ return value;
+}
+
+void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)
+{
+ rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
+ int numDigits = (mask & 3);
+ rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;
+ for (int i = 0; i < numDigits; i++)
+ rarTime.SubTime[3 - numDigits + i] = ReadByte();
+}
+
+void CInArchive::ReadHeaderReal(CItemEx &item)
+{
+ item.Flags = m_BlockHeader.Flags;
+ item.PackSize = ReadUInt32();
+ item.UnPackSize = ReadUInt32();
+ item.HostOS = ReadByte();
+ item.FileCRC = ReadUInt32();
+ item.LastWriteTime.DosTime = ReadUInt32();
+ item.UnPackVersion = ReadByte();
+ item.Method = ReadByte();
+ int nameSize = ReadUInt16();
+ item.Attributes = ReadUInt32();
+
+ item.LastWriteTime.LowSecond = 0;
+ item.LastWriteTime.SubTime[0] =
+ item.LastWriteTime.SubTime[1] =
+ item.LastWriteTime.SubTime[2] = 0;
+
+ if((item.Flags & NHeader::NFile::kSize64Bits) != 0)
+ {
+ item.PackSize |= ((UInt64)ReadUInt32() << 32);
+ item.UnPackSize |= ((UInt64)ReadUInt32() << 32);
+ }
+
+ ReadName(item, nameSize);
+
+ if (item.HasSalt())
+ for (int i = 0; i < sizeof(item.Salt); i++)
+ item.Salt[i] = ReadByte();
+
+ // some rar archives have HasExtTime flag without field.
+ if (m_CurPos < m_PosLimit && item.HasExtTime())
+ {
+ Byte accessMask = (Byte)(ReadByte() >> 4);
+ Byte b = ReadByte();
+ Byte modifMask = (Byte)(b >> 4);
+ Byte createMask = (Byte)(b & 0xF);
+ if ((modifMask & 8) != 0)
+ ReadTime(modifMask, item.LastWriteTime);
+ item.IsCreationTimeDefined = ((createMask & 8) != 0);
+ if (item.IsCreationTimeDefined)
+ {
+ item.CreationTime.DosTime = ReadUInt32();
+ ReadTime(createMask, item.CreationTime);
+ }
+ item.IsLastAccessTimeDefined = ((accessMask & 8) != 0);
+ if (item.IsLastAccessTimeDefined)
+ {
+ item.LastAccessTime.DosTime = ReadUInt32();
+ ReadTime(accessMask, item.LastAccessTime);
+ }
+ }
+
+ UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;
+
+ item.Position = m_Position;
+ item.MainPartSize = fileHeaderWithNameSize;
+ item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
+
+ if (m_CryptoMode)
+ item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
+ else
+ item.AlignSize = 0;
+ AddToSeekValue(m_BlockHeader.HeadSize);
+}
+
+void CInArchive::AddToSeekValue(UInt64 addValue)
+{
+ m_Position += addValue;
+}
+
+HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword)
+{
+ if (m_SeekOnArchiveComment)
+ SkipArchiveComment();
+ for (;;)
+ {
+ if(!SeekInArchive(m_Position))
+ return S_FALSE;
+ if (!m_CryptoMode && (m_ArchiveHeader.Flags &
+ NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
+ {
+ m_CryptoMode = false;
+ if (getTextPassword == 0)
+ return S_FALSE;
+ if(!SeekInArchive(m_Position))
+ return S_FALSE;
+ if (!m_RarAES)
+ {
+ m_RarAESSpec = new NCrypto::NRar29::CDecoder;
+ m_RarAES = m_RarAESSpec;
+ }
+ m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld());
+
+ // Salt
+ const UInt32 kSaltSize = 8;
+ Byte salt[kSaltSize];
+ if(!ReadBytesAndTestSize(salt, kSaltSize))
+ return false;
+ m_Position += kSaltSize;
+ RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
+ // Password
+ CMyComBSTR password;
+ RINOK(getTextPassword->CryptoGetTextPassword(&password))
+ UString unicodePassword(password);
+
+ CByteBuffer buffer;
+ const UInt32 sizeInBytes = unicodePassword.Length() * 2;
+ buffer.SetCapacity(sizeInBytes);
+ for (int i = 0; i < unicodePassword.Length(); i++)
+ {
+ wchar_t c = unicodePassword[i];
+ ((Byte *)buffer)[i * 2] = (Byte)c;
+ ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
+ }
+
+ RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+
+ const UInt32 kDecryptedBufferSize = (1 << 12);
+ if (m_DecryptedData.GetCapacity() == 0)
+ {
+ m_DecryptedData.SetCapacity(kDecryptedBufferSize);
+ }
+ RINOK(m_RarAES->Init());
+ RINOK(ReadStream(m_Stream, (Byte *)m_DecryptedData, kDecryptedBufferSize, &m_DecryptedDataSize));
+ m_DecryptedDataSize = m_RarAES->Filter((Byte *)m_DecryptedData, m_DecryptedDataSize);
+
+ m_CryptoMode = true;
+ m_CryptoPos = 0;
+ }
+
+ m_FileHeaderData.EnsureCapacity(7);
+ if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))
+ return S_FALSE;
+
+ m_CurData = (Byte *)m_FileHeaderData;
+ m_CurPos = 0;
+ m_PosLimit = 7;
+ m_BlockHeader.CRC = ReadUInt16();
+ m_BlockHeader.Type = ReadByte();
+ m_BlockHeader.Flags = ReadUInt16();
+ m_BlockHeader.HeadSize = ReadUInt16();
+
+ if (m_BlockHeader.HeadSize < 7)
+ ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);
+
+ if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)
+ return S_FALSE;
+
+ if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)
+ {
+ m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
+ m_CurData = (Byte *)m_FileHeaderData;
+ m_PosLimit = m_BlockHeader.HeadSize;
+ ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7);
+ ReadHeaderReal(item);
+ if ((CCRC::CalculateDigest(m_CurData + 2,
+ m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)
+ ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
+
+ FinishCryptoBlock();
+ m_CryptoMode = false;
+ SeekInArchive(m_Position); // Move Position to compressed Data;
+ AddToSeekValue(item.PackSize); // m_Position points to next header;
+ return S_OK;
+ }
+ if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 12))
+ return E_FAIL; // it's for bad passwords
+ if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
+ {
+ m_FileHeaderData.EnsureCapacity(7 + 4);
+ m_CurData = (Byte *)m_FileHeaderData;
+ ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it
+ m_PosLimit = 7 + 4;
+ UInt32 dataSize = ReadUInt32();
+ AddToSeekValue(dataSize);
+ if (m_CryptoMode && dataSize > (1 << 27))
+ return E_FAIL; // it's for bad passwords
+ m_CryptoPos = m_BlockHeader.HeadSize;
+ }
+ else
+ m_CryptoPos = 0;
+ AddToSeekValue(m_BlockHeader.HeadSize);
+ FinishCryptoBlock();
+ m_CryptoMode = false;
+ }
+}
+
+void CInArchive::DirectGetBytes(void *data, UInt32 size)
+{
+ ReadStream(m_Stream, data, size, NULL);
+}
+
+bool CInArchive::SeekInArchive(UInt64 position)
+{
+ UInt64 newPosition;
+ m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition);
+ return newPosition == position;
+}
+
+ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
+{
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ SeekInArchive(position);
+ streamSpec->SetStream(m_Stream);
+ streamSpec->Init(size);
+ return inStream.Detach();
+}
+
+}}
diff --git a/CPP/7zip/Archive/Rar/RarIn.h b/CPP/7zip/Archive/Rar/RarIn.h
new file mode 100755
index 00000000..22262a74
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarIn.h
@@ -0,0 +1,124 @@
+// RarIn.h
+
+#ifndef __ARCHIVE_RAR_IN_H
+#define __ARCHIVE_RAR_IN_H
+
+#include "Common/DynamicBuffer.h"
+#include "Common/Exception.h"
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+#include "../../ICoder.h"
+#include "../../Common/StreamObjects.h"
+#include "../../Crypto/RarAES/RarAES.h"
+#include "RarHeader.h"
+#include "RarItem.h"
+
+namespace NArchive {
+namespace NRar {
+
+class CInArchiveException
+{
+public:
+ enum CCauseType
+ {
+ kUnexpectedEndOfArchive = 0,
+ kArchiveHeaderCRCError,
+ kFileHeaderCRCError,
+ kIncorrectArchive,
+ }
+ Cause;
+ CInArchiveException(CCauseType cause) : Cause(cause) {}
+};
+
+class CInArchiveInfo
+{
+public:
+ UInt64 StartPosition;
+ WORD Flags;
+ UInt64 CommentPosition;
+ WORD CommentSize;
+ bool IsSolid() const { return (Flags & NHeader::NArchive::kSolid) != 0; }
+ bool IsCommented() const { return (Flags & NHeader::NArchive::kComment) != 0; }
+ bool IsVolume() const { return (Flags & NHeader::NArchive::kVolume) != 0; }
+ bool HaveNewVolumeName() const { return (Flags & NHeader::NArchive::kNewVolName) != 0; }
+ bool IsEncrypted() const { return (Flags & NHeader::NArchive::kBlockEncryption) != 0; }
+};
+
+class CInArchive
+{
+ CMyComPtr<IInStream> m_Stream;
+
+ UInt64 m_StreamStartPosition;
+ UInt64 m_Position;
+ UInt64 m_ArchiveStartPosition;
+
+ NHeader::NArchive::CHeader360 m_ArchiveHeader;
+ CDynamicBuffer<char> m_NameBuffer;
+ CDynamicBuffer<wchar_t> _unicodeNameBuffer;
+ bool m_SeekOnArchiveComment;
+ UInt64 m_ArchiveCommentPosition;
+
+ void ReadName(CItemEx &item, int nameSize);
+ void ReadHeaderReal(CItemEx &item);
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 *aProcessedSize);
+ bool ReadBytesAndTestSize(void *data, UInt32 size);
+ void ReadBytesAndTestResult(void *data, UInt32 size);
+
+ bool FindAndReadMarker(const UInt64 *searchHeaderSizeLimit);
+ void ThrowExceptionWithCode(CInArchiveException::CCauseType cause);
+ void ThrowUnexpectedEndOfArchiveException();
+
+ void AddToSeekValue(UInt64 addValue);
+
+protected:
+
+ CDynamicBuffer<Byte> m_FileHeaderData;
+
+ NHeader::NBlock::CBlock m_BlockHeader;
+
+ NCrypto::NRar29::CDecoder *m_RarAESSpec;
+ CMyComPtr<ICompressFilter> m_RarAES;
+
+ Byte *m_CurData; // it must point to start of Rar::Block
+ UInt32 m_CurPos;
+ UInt32 m_PosLimit;
+ Byte ReadByte();
+ UInt16 ReadUInt16();
+ UInt32 ReadUInt32();
+ void ReadTime(Byte mask, CRarTime &rarTime);
+
+ CBuffer<Byte> m_DecryptedData;
+ UInt32 m_DecryptedDataSize;
+
+ bool m_CryptoMode;
+ UInt32 m_CryptoPos;
+ void FinishCryptoBlock()
+ {
+ if (m_CryptoMode)
+ while ((m_CryptoPos & 0xF) != 0)
+ {
+ m_CryptoPos++;
+ m_Position++;
+ }
+ }
+
+ bool ReadMarkerAndArchiveHeader(const UInt64 *searchHeaderSizeLimit);
+public:
+ bool Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit);
+ void Close();
+ HRESULT GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword);
+
+ void SkipArchiveComment();
+
+ void GetArchiveInfo(CInArchiveInfo &archiveInfo) const;
+
+ void DirectGetBytes(void *data, UInt32 size);
+
+ bool SeekInArchive(UInt64 position);
+ ISequentialInStream *CreateLimitedStream(UInt64 position, UInt64 size);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Rar/RarItem.cpp b/CPP/7zip/Archive/Rar/RarItem.cpp
new file mode 100755
index 00000000..61a72557
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarItem.cpp
@@ -0,0 +1,118 @@
+// RarItem.cpp
+
+#include "StdAfx.h"
+
+#include "RarItem.h"
+#include "RarHeader.h"
+
+namespace NArchive{
+namespace NRar{
+
+bool CItem::IsEncrypted() const
+ { return (Flags & NHeader::NFile::kEncrypted) != 0; }
+bool CItem::IsSolid() const
+ { return (Flags & NHeader::NFile::kSolid) != 0; }
+bool CItem::IsCommented() const
+ { return (Flags & NHeader::NFile::kComment) != 0; }
+bool CItem::IsSplitBefore() const
+ { return (Flags & NHeader::NFile::kSplitBefore) != 0; }
+bool CItem::IsSplitAfter() const
+ { return (Flags & NHeader::NFile::kSplitAfter) != 0; }
+bool CItem::HasSalt() const
+ { return (Flags & NHeader::NFile::kSalt) != 0; }
+bool CItem::HasExtTime() const
+ { return (Flags & NHeader::NFile::kExtTime) != 0; }
+bool CItem::HasUnicodeName() const
+ { return (Flags & NHeader::NFile::kUnicodeName) != 0; }
+bool CItem::IsOldVersion() const
+ { return (Flags & NHeader::NFile::kOldVersion) != 0; }
+
+bool CItem::IgnoreItem() const
+{
+ switch(HostOS)
+ {
+ case NHeader::NFile::kHostMSDOS:
+ case NHeader::NFile::kHostOS2:
+ case NHeader::NFile::kHostWin32:
+ return ((Attributes & NHeader::NFile::kLabelFileAttribute) != 0);
+ }
+ return false;
+}
+
+UInt32 CItem::GetDictSize() const
+{ return (Flags >> NHeader::NFile::kDictBitStart) & NHeader::NFile::kDictMask; }
+
+bool CItem::IsDirectory() const
+{
+ if (GetDictSize() == NHeader::NFile::kDictDirectoryValue)
+ return true;
+ switch(HostOS)
+ {
+ case NHeader::NFile::kHostMSDOS:
+ case NHeader::NFile::kHostOS2:
+ case NHeader::NFile::kHostWin32:
+ if ((Attributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
+ return true;
+ }
+ return false;
+}
+
+UInt32 CItem::GetWinAttributes() const
+{
+ UInt32 winAttributes;
+ switch(HostOS)
+ {
+ case NHeader::NFile::kHostMSDOS:
+ case NHeader::NFile::kHostOS2:
+ case NHeader::NFile::kHostWin32:
+ winAttributes = Attributes;
+ break;
+ default:
+ winAttributes = 0; // must be converted from unix value;;
+ }
+ if (IsDirectory()) // test it;
+ winAttributes |= NHeader::NFile::kWinFileDirectoryAttributeMask;
+ return winAttributes;
+}
+
+void CItem::ClearFlags()
+{ Flags = 0; }
+
+void CItem::SetFlagBits(int startBitNumber, int numBits, int value)
+{
+ UInt16 mask = (UInt16)(((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::SetDictSize(UInt32 size)
+{
+ SetFlagBits(NHeader::NFile::kDictBitStart, NHeader::NFile::kNumDictBits, (size & NHeader::NFile::kDictMask));
+}
+
+void CItem::SetAsDirectory(bool directory)
+{
+ if (directory)
+ SetDictSize(NHeader::NFile::kDictDirectoryValue);
+}
+
+void CItem::SetEncrypted(bool encrypted)
+ { SetBitMask(NHeader::NFile::kEncrypted, encrypted); }
+void CItem::SetSolid(bool solid)
+ { SetBitMask(NHeader::NFile::kSolid, solid); }
+void CItem::SetCommented(bool commented)
+ { SetBitMask(NHeader::NFile::kComment, commented); }
+void CItem::SetSplitBefore(bool splitBefore)
+ { SetBitMask(NHeader::NFile::kSplitBefore, splitBefore); }
+void CItem::SetSplitAfter(bool splitAfter)
+ { SetBitMask(NHeader::NFile::kSplitAfter, splitAfter); }
+
+}}
diff --git a/CPP/7zip/Archive/Rar/RarItem.h b/CPP/7zip/Archive/Rar/RarItem.h
new file mode 100755
index 00000000..85050a42
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarItem.h
@@ -0,0 +1,91 @@
+// RarItem.h
+
+#ifndef __ARCHIVE_RAR_ITEM_H
+#define __ARCHIVE_RAR_ITEM_H
+
+#include "Common/Types.h"
+#include "Common/String.h"
+
+namespace NArchive{
+namespace NRar{
+
+struct CRarTime
+{
+ UInt32 DosTime;
+ Byte LowSecond;
+ Byte SubTime[3];
+};
+
+class CItem
+{
+public:
+ UInt16 Flags;
+ UInt64 PackSize;
+ UInt64 UnPackSize;
+ Byte HostOS;
+ UInt32 FileCRC;
+
+ CRarTime CreationTime;
+ CRarTime LastWriteTime;
+ CRarTime LastAccessTime;
+ bool IsCreationTimeDefined;
+ // bool IsLastWriteTimeDefined;
+ bool IsLastAccessTimeDefined;
+
+ Byte UnPackVersion;
+ Byte Method;
+ UInt32 Attributes;
+ AString Name;
+ UString UnicodeName;
+
+ Byte Salt[8];
+
+ bool IsEncrypted() const;
+ bool IsSolid() const;
+ bool IsCommented() const;
+ bool IsSplitBefore() const;
+ bool IsSplitAfter() const;
+ bool HasSalt() const;
+ bool HasExtTime() const;
+
+ bool HasUnicodeName() const;
+ bool IsOldVersion() const;
+
+ UInt32 GetDictSize() const;
+ bool IsDirectory() const;
+ bool IgnoreItem() const;
+ UInt32 GetWinAttributes() const;
+
+ CItem(): IsCreationTimeDefined(false), IsLastAccessTimeDefined(false) {}
+private:
+ void SetFlagBits(int startBitNumber, int numBits, int value);
+ void SetBitMask(int bitMask, bool enable);
+public:
+ void ClearFlags();
+ void SetDictSize(UInt32 size);
+ void SetAsDirectory(bool directory);
+ void SetEncrypted(bool encrypted);
+ void SetSolid(bool solid);
+ void SetCommented(bool commented);
+ void SetSplitBefore(bool splitBefore);
+ void SetSplitAfter(bool splitAfter);
+};
+
+class CItemEx: public CItem
+{
+public:
+ UInt64 Position;
+ UInt16 MainPartSize;
+ UInt16 CommentSize;
+ UInt16 AlignSize;
+ UInt64 GetFullSize() const { return MainPartSize + CommentSize + AlignSize + PackSize; };
+ // DWORD GetHeaderWithCommentSize() const { return MainPartSize + CommentSize; };
+ UInt64 GetCommentPosition() const { return Position + MainPartSize; };
+ UInt64 GetDataPosition() const { return GetCommentPosition() + CommentSize + AlignSize; };
+};
+
+}}
+
+#endif
+
+
diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp
new file mode 100755
index 00000000..32078e6d
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarVolumeInStream.cpp
@@ -0,0 +1,79 @@
+// RarVolumeInStream.cpp
+
+#include "StdAfx.h"
+
+#include "RarVolumeInStream.h"
+
+#include "Windows/Defs.h"
+#include "Common/Defs.h"
+
+namespace NArchive {
+namespace NRar {
+
+void CFolderInStream::Init(
+ CObjectVector<CInArchive> *archives,
+ const CObjectVector<CItemEx> *items,
+ const CRefItem &refItem)
+{
+ _archives = archives;
+ _items = items;
+ _refItem = refItem;
+ _curIndex = 0;
+ CRCs.Clear();
+ _fileIsOpen = false;
+}
+
+HRESULT CFolderInStream::OpenStream()
+{
+ while (_curIndex < _refItem.NumItems)
+ {
+ const CItemEx &item = (*_items)[_refItem.ItemIndex + _curIndex];
+ _stream.Attach((*_archives)[_refItem.VolumeIndex + _curIndex].
+ CreateLimitedStream(item.GetDataPosition(), item.PackSize));
+ _curIndex++;
+ _fileIsOpen = true;
+ _crc.Init();
+ return S_OK;
+ }
+ return S_OK;
+}
+
+HRESULT CFolderInStream::CloseStream()
+{
+ CRCs.Add(_crc.GetDigest());
+ _stream.Release();
+ _fileIsOpen = false;
+ return S_OK;
+}
+
+STDMETHODIMP CFolderInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ UInt32 realProcessedSize = 0;
+ while ((_curIndex < _refItem.NumItems || _fileIsOpen) && size > 0)
+ {
+ if (_fileIsOpen)
+ {
+ UInt32 localProcessedSize;
+ RINOK(_stream->Read(
+ ((Byte *)data) + realProcessedSize, size, &localProcessedSize));
+ _crc.Update(((Byte *)data) + realProcessedSize, localProcessedSize);
+ if (localProcessedSize == 0)
+ {
+ RINOK(CloseStream());
+ continue;
+ }
+ realProcessedSize += localProcessedSize;
+ size -= localProcessedSize;
+ break;
+ }
+ else
+ {
+ RINOK(OpenStream());
+ }
+ }
+ if (processedSize != 0)
+ *processedSize = realProcessedSize;
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Rar/RarVolumeInStream.h b/CPP/7zip/Archive/Rar/RarVolumeInStream.h
new file mode 100755
index 00000000..4c9a9e96
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/RarVolumeInStream.h
@@ -0,0 +1,50 @@
+// RarVolumeInStream.h
+
+#ifndef __RAR_VOLUME_IN_STREAM_H
+#define __RAR_VOLUME_IN_STREAM_H
+
+#include "../../IStream.h"
+#include "Common/CRC.h"
+#include "RarIn.h"
+
+namespace NArchive {
+namespace NRar {
+
+struct CRefItem
+{
+ int VolumeIndex;
+ int ItemIndex;
+ int NumItems;
+};
+
+class CFolderInStream:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+
+private:
+ CObjectVector<CInArchive> *_archives;
+ const CObjectVector<CItemEx> *_items;
+ CRefItem _refItem;
+ int _curIndex;
+ CCRC _crc;
+ bool _fileIsOpen;
+ CMyComPtr<ISequentialInStream> _stream;
+
+ HRESULT OpenStream();
+ HRESULT CloseStream();
+public:
+ void Init(CObjectVector<CInArchive> *archives,
+ const CObjectVector<CItemEx> *items,
+ const CRefItem &refItem);
+
+ CRecordVector<UInt32> CRCs;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Rar/StdAfx.cpp b/CPP/7zip/Archive/Rar/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Rar/StdAfx.h b/CPP/7zip/Archive/Rar/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/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/Rar/makefile b/CPP/7zip/Archive/Rar/makefile
new file mode 100755
index 00000000..678dd412
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/makefile
@@ -0,0 +1,90 @@
+PROG = rar.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+RAR_OBJS = \
+ $O\DllExports.obj \
+ $O\RarHandler.obj \
+ $O\RarHeader.obj \
+ $O\RarIn.obj \
+ $O\RarItem.obj \
+ $O\RarVolumeInStream.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\CRC.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\UTFConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\DLL.obj \
+ $O\FileFind.obj \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\LimitedStreams.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamObjects.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\CodecsPath.obj \
+ $O\FilterCoder.obj \
+ $O\InStreamWithCRC.obj \
+ $O\OutStreamWithCRC.obj \
+
+7Z_OBJS = \
+ $O\7zMethodID.obj \
+ $O\7zMethods.obj \
+
+CRYPTO_HASH_OBJS = \
+ $O\Sha1.obj \
+
+CRYPTO_RAR20_OBJS = \
+ $O\Rar20Cipher.obj \
+ $O\Rar20Crypto.obj \
+
+CRYPTO_RARAES_OBJS = \
+ $O\RarAES.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(RAR_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(7Z_OBJS) \
+ $(CRYPTO_HASH_OBJS) \
+ $(CRYPTO_RAR20_OBJS) \
+ $(CRYPTO_RARAES_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(RAR_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_RAR20_OBJS): ../../Crypto/Rar20/$(*B).cpp
+ $(COMPL)
+$(CRYPTO_RARAES_OBJS): ../../Crypto/RarAES/$(*B).cpp
+ $(COMPL)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Rar/rar.ico b/CPP/7zip/Archive/Rar/rar.ico
new file mode 100755
index 00000000..2918d294
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/rar.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Rar/resource.rc b/CPP/7zip/Archive/Rar/resource.rc
new file mode 100755
index 00000000..94b4198b
--- /dev/null
+++ b/CPP/7zip/Archive/Rar/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Rar Plugin", "rar")
+
+101 ICON "rar.ico"
diff --git a/CPP/7zip/Archive/Split/DllExports.cpp b/CPP/7zip/Archive/Split/DllExports.cpp
new file mode 100755
index 00000000..e28f64ce
--- /dev/null
+++ b/CPP/7zip/Archive/Split/DllExports.cpp
@@ -0,0 +1,65 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "SplitHandler.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278A-1000-000110EA0000}
+DEFINE_GUID(CLSID_CSplitHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEA, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CSplitHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ if (*interfaceID != IID_IInArchive)
+ return E_NOINTERFACE;
+ CMyComPtr<IInArchive> inArchive = (IInArchive *)new NArchive::NSplit::CHandler;
+ *outObject = inArchive.Detach();
+ COM_TRY_END
+ return S_OK;
+}
+
+STDAPI GetHandlerProperty(PROPID propID, PROPVARIANT *value)
+{
+ NWindows::NCOM::CPropVariant propVariant;
+ switch(propID)
+ {
+ case NArchive::kName:
+ propVariant = L"Split";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CSplitHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"001";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = true;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Split/Split.dsp b/CPP/7zip/Archive/Split/Split.dsp
new file mode 100755
index 00000000..d6229d98
--- /dev/null
+++ b/CPP/7zip/Archive/Split/Split.dsp
@@ -0,0 +1,237 @@
+# Microsoft Developer Studio Project File - Name="Split" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Split - 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 "Split.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 "Split.mak" CFG="Split - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Split - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Split - 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)" == "Split - 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 "SPLIT_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPLIT_EXPORTS" /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 0x419 /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\split.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Split - 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 "SPLIT_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SPLIT_EXPORTS" /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 0x419 /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\split.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Split - Win32 Release"
+# Name "Split - 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=.\Split.ico
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.cpp
+# ADD CPP /Yc"StdAfx.h"
+# 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\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.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\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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# 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 "7zip Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\MultiStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\MultiStream.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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Group "Interface"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\IArchive.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\SplitHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\SplitHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\SplitHandlerOut.cpp
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Split/Split.dsw b/CPP/7zip/Archive/Split/Split.dsw
new file mode 100755
index 00000000..988ca30a
--- /dev/null
+++ b/CPP/7zip/Archive/Split/Split.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Split"=.\Split.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Split/Split.ico b/CPP/7zip/Archive/Split/Split.ico
new file mode 100755
index 00000000..5cb93e84
--- /dev/null
+++ b/CPP/7zip/Archive/Split/Split.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Split/SplitHandler.cpp b/CPP/7zip/Archive/Split/SplitHandler.cpp
new file mode 100755
index 00000000..e919154f
--- /dev/null
+++ b/CPP/7zip/Archive/Split/SplitHandler.cpp
@@ -0,0 +1,415 @@
+// Tar/Handler.cpp
+
+#include "StdAfx.h"
+
+#include "SplitHandler.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/Time.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Compress/Copy/CopyCoder.h"
+#include "../Common/ItemNameUtils.h"
+#include "../Common/MultiStream.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NSplit {
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+// { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+};
+
+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_INVALIDARG;
+}
+
+class CSeqName
+{
+public:
+ UString _unchangedPart;
+ UString _changedPart;
+ bool _splitStyle;
+ UString GetNextName()
+ {
+ UString newName;
+ if (_splitStyle)
+ {
+ int i;
+ int numLetters = _changedPart.Length();
+ for (i = numLetters - 1; i >= 0; i--)
+ {
+ wchar_t c = _changedPart[i];
+ if (c == 'z')
+ {
+ c = 'a';
+ newName = c + newName;
+ continue;
+ }
+ else if (c == 'Z')
+ {
+ c = 'A';
+ newName = c + newName;
+ continue;
+ }
+ c++;
+ if ((c == 'z' || c == 'Z') && i == 0)
+ {
+ _unchangedPart += c;
+ wchar_t newChar = (c == 'z') ? L'a' : L'A';
+ newName.Empty();
+ numLetters++;
+ for (int k = 0; k < numLetters; k++)
+ newName += newChar;
+ break;
+ }
+ newName = c + newName;
+ i--;
+ for (; i >= 0; i--)
+ newName = _changedPart[i] + newName;
+ break;
+ }
+ }
+ else
+ {
+ int i;
+ int numLetters = _changedPart.Length();
+ for (i = numLetters - 1; i >= 0; i--)
+ {
+ wchar_t c = _changedPart[i];
+ if (c == L'9')
+ {
+ c = L'0';
+ newName = c + newName;
+ if (i == 0)
+ newName = UString(L'1') + newName;
+ continue;
+ }
+ c++;
+ newName = c + newName;
+ i--;
+ for (; i >= 0; i--)
+ newName = _changedPart[i] + newName;
+ break;
+ }
+ }
+ _changedPart = newName;
+ return _unchangedPart + _changedPart;
+ }
+};
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ Close();
+ if (openArchiveCallback == 0)
+ return S_FALSE;
+ // try
+ {
+ CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
+ CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback;
+ if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback,
+ &openVolumeCallback) != S_OK)
+ return S_FALSE;
+
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(openVolumeCallback->GetProperty(kpidName, &propVariant));
+ if (propVariant.vt != VT_BSTR)
+ return S_FALSE;
+ _name = propVariant.bstrVal;
+ }
+
+ int dotPos = _name.ReverseFind('.');
+ UString prefix, ext;
+ if (dotPos >= 0)
+ {
+ prefix = _name.Left(dotPos + 1);
+ ext = _name.Mid(dotPos + 1);
+ }
+ else
+ ext = _name;
+ UString extBig = ext;
+ extBig.MakeUpper();
+
+ CSeqName seqName;
+
+ int numLetters = 2;
+ bool splitStyle = false;
+ if (extBig.Right(2) == L"AA")
+ {
+ splitStyle = true;
+ while (numLetters < extBig.Length())
+ {
+ if (extBig[extBig.Length() - numLetters - 1] != 'A')
+ break;
+ numLetters++;
+ }
+ }
+ else if (ext.Right(2) == L"01")
+ {
+ while (numLetters < extBig.Length())
+ {
+ if (extBig[extBig.Length() - numLetters - 1] != '0')
+ break;
+ numLetters++;
+ }
+ if (numLetters != ext.Length())
+ return S_FALSE;
+ }
+ else
+ return S_FALSE;
+
+ _streams.Add(stream);
+
+ seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters);
+ seqName._changedPart = ext.Right(numLetters);
+ seqName._splitStyle = splitStyle;
+
+ if (prefix.Length() < 1)
+ _subName = L"file";
+ else
+ _subName = prefix.Left(prefix.Length() - 1);
+
+ _totalSize = 0;
+ UInt64 size;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(openVolumeCallback->GetProperty(kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = propVariant.uhVal.QuadPart;
+ }
+ _totalSize += size;
+ _sizes.Add(size);
+
+ if (openArchiveCallback != NULL)
+ {
+ RINOK(openArchiveCallback->SetTotal(NULL, NULL));
+ UInt64 numFiles = _streams.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+
+ for (;;)
+ {
+ UString fullName = seqName.GetNextName();
+ CMyComPtr<IInStream> nextStream;
+ HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream);
+ if (result == S_FALSE)
+ break;
+ if (result != S_OK)
+ return result;
+ if (!stream)
+ break;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(openVolumeCallback->GetProperty(kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ size = propVariant.uhVal.QuadPart;
+ }
+ _totalSize += size;
+ _sizes.Add(size);
+ _streams.Add(nextStream);
+ if (openArchiveCallback != NULL)
+ {
+ UInt64 numFiles = _streams.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ }
+ /*
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ */
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _sizes.Clear();
+ _streams.Clear();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _streams.IsEmpty() ? 0 : 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = _subName;
+ break;
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ propVariant = _totalSize;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback)
+{
+ COM_TRY_BEGIN
+
+ if (numItems != UInt32(-1))
+ {
+ if (numItems != 1)
+ return E_INVALIDARG;
+ if (indices[0] != 0)
+ return E_INVALIDARG;
+ }
+ bool testMode = (_aTestMode != 0);
+ CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback;
+ extractCallback->SetTotal(_totalSize);
+
+ /*
+ CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback;
+ if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK)
+ return E_FAIL;
+ */
+
+ UInt64 currentTotalSize = 0;
+ UInt64 currentItemSize;
+
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ Int32 index = 0;
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ RINOK(extractCallback->PrepareOperation(askMode));
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ return S_OK;
+ }
+ // currentItemSize = itemInfo.Size;
+
+ if(!testMode && (!realOutStream))
+ {
+ return S_OK;
+ }
+
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+
+ for(int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize)
+ {
+ // CMyComPtr<ISequentialInStream> inStream;
+ // RINOK(volumeExtractCallback->GetInStream(_names[i], &inStream));
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress,
+ &currentTotalSize, &currentTotalSize);
+ IInStream *inStream = _streams[i];
+ RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL));
+ try
+ {
+ RINOK(copyCoder->Code(inStream, realOutStream,
+ NULL, NULL, compressProgress));
+ }
+ catch(...)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ return S_OK;;
+ }
+ currentItemSize = copyCoderSpec->TotalSize;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
+{
+ if (index != 0)
+ return E_INVALIDARG;
+ *stream = 0;
+ CMultiStream *streamSpec = new CMultiStream;
+ CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
+ for (int i = 0; i < _streams.Size(); i++)
+ {
+ CMultiStream::CSubStreamInfo subStreamInfo;
+ subStreamInfo.Stream = _streams[i];
+ subStreamInfo.Pos = 0;
+ subStreamInfo.Size = _sizes[i];
+ streamSpec->Streams.Add(subStreamInfo);
+ }
+ streamSpec->Init();
+ *stream = streamTemp.Detach();
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Split/SplitHandler.h b/CPP/7zip/Archive/Split/SplitHandler.h
new file mode 100755
index 00000000..8b3fcb70
--- /dev/null
+++ b/CPP/7zip/Archive/Split/SplitHandler.h
@@ -0,0 +1,62 @@
+// Split/Handler.h
+
+#ifndef __SPLIT_HANDLER_H
+#define __SPLIT_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "Common/String.h"
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace NSplit {
+
+class CHandler:
+ public IInArchive,
+ public IInArchiveGetStream,
+ // public IOutArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP1(IInArchiveGetStream)
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+ STDMETHOD(GetStream)(UInt32 index, ISequentialInStream **stream);
+
+ // IOutArchiveHandler
+ /*
+ STDMETHOD(UpdateItems)(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback);
+
+ STDMETHOD(GetFileTimeType)(UInt32 *type);
+ */
+
+private:
+ UString _subName;
+ UString _name;
+ CObjectVector<CMyComPtr<IInStream> > _streams;
+ CRecordVector<UInt64> _sizes;
+
+ UInt64 _totalSize;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Split/SplitHandlerOut.cpp b/CPP/7zip/Archive/Split/SplitHandlerOut.cpp
new file mode 100755
index 00000000..ea86c281
--- /dev/null
+++ b/CPP/7zip/Archive/Split/SplitHandlerOut.cpp
@@ -0,0 +1,102 @@
+// Split/OutHandler.cpp
+
+#include "StdAfx.h"
+
+#include "SplitHandler.h"
+#include "../../../Windows/PropVariant.h"
+#include "../../../Common/ComTry.h"
+#include "../../../Common/StringToInt.h"
+
+using namespace NWindows;
+
+namespace NArchive {
+namespace NSplit {
+
+/*
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kWindows;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+
+ if (numItems != 1)
+ return E_INVALIDARG;
+
+ UInt64 volumeSize = 0;
+
+ CMyComPtr<IArchiveUpdateCallback2> callback2;
+ updateCallback->QueryInterface(IID_IArchiveUpdateCallback2,
+ (void **)&callback2);
+
+ RINOK(callback2->GetVolumeSize(0, &volumeSize));
+
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+
+ UInt32 fileIndex = 0;
+ RINOK(updateCallback->GetUpdateItemInfo(fileIndex,
+ &newData, &newProperties, &indexInArchive));
+
+ if (newProperties != 0)
+ {
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(fileIndex, kpidIsFolder, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ {
+ }
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ {
+ if (propVariant.boolVal != VARIANT_FALSE)
+ return E_INVALIDARG;
+ }
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(fileIndex, kpidIsAnti, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ {
+ }
+ else if (propVariant.vt != VT_BOOL)
+ return E_INVALIDARG;
+ else
+ {
+ if (propVariant.boolVal != VARIANT_FALSE)
+ return E_INVALIDARG;
+ }
+ }
+ }
+ UInt64 newSize;
+ bool thereIsCopyData = false;
+ if (newData != 0)
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(fileIndex, kpidSize, &propVariant));
+ if (propVariant.vt != VT_UI8)
+ return E_INVALIDARG;
+ newSize = propVariant.uhVal.QuadPart;
+ }
+ else
+ thereIsCopyData = true;
+
+ UInt64 pos = 0;
+ while(pos < newSize)
+ {
+
+ }
+ return S_OK;
+ COM_TRY_END
+}
+*/
+
+}}
diff --git a/CPP/7zip/Archive/Split/StdAfx.cpp b/CPP/7zip/Archive/Split/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Split/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Split/StdAfx.h b/CPP/7zip/Archive/Split/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Split/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/Split/makefile b/CPP/7zip/Archive/Split/makefile
new file mode 100755
index 00000000..650c750b
--- /dev/null
+++ b/CPP/7zip/Archive/Split/makefile
@@ -0,0 +1,51 @@
+PROG = split.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+SPLIT_OBJS = \
+ $O\DllExports.obj \
+ $O\SplitHandler.obj \
+ $O\SplitHandlerOut.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\MultiStream.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(SPLIT_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(SPLIT_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Split/resource.rc b/CPP/7zip/Archive/Split/resource.rc
new file mode 100755
index 00000000..3e301754
--- /dev/null
+++ b/CPP/7zip/Archive/Split/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Split Plugin", "split")
+
+101 ICON "Split.ico"
diff --git a/CPP/7zip/Archive/Tar/DllExports.cpp b/CPP/7zip/Archive/Tar/DllExports.cpp
new file mode 100755
index 00000000..afa2fd24
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/DllExports.cpp
@@ -0,0 +1,86 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "../../ICoder.h"
+#include "TarHandler.h"
+
+// {23170F69-40C1-278A-1000-000110EE0000}
+DEFINE_GUID(CLSID_CTarHandler,
+ 0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0xEE, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CTarHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ int needOut = *interfaceID == IID_IOutArchive;
+ if (needIn || needOut)
+ {
+ NArchive::NTar::CHandler *temp = new NArchive::NTar::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"Tar";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CTarHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"tar";
+ break;
+ case NArchive::kUpdate:
+ propVariant = true;
+ break;
+ case NArchive::kKeepName:
+ propVariant = false;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const unsigned char sig[] = { 'u', 's', 't', 'a', 'r' };
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 5)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Tar/StdAfx.cpp b/CPP/7zip/Archive/Tar/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Tar/StdAfx.h b/CPP/7zip/Archive/Tar/StdAfx.h
new file mode 100755
index 00000000..2e4be10b
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/StdAfx.h
@@ -0,0 +1,9 @@
+// StdAfx.h
+
+#ifndef __STDAFX_H
+#define __STDAFX_H
+
+#include "../../../Common/MyWindows.h"
+#include "../../../Common/NewHandler.h"
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/Tar.dsp b/CPP/7zip/Archive/Tar/Tar.dsp
new file mode 100755
index 00000000..c01e7383
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/Tar.dsp
@@ -0,0 +1,297 @@
+# Microsoft Developer Studio Project File - Name="Tar" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Tar - 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 "Tar.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 "Tar.mak" CFG="Tar - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Tar - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Tar - 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)" == "Tar - 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 "TAR_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /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 0x419 /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\tar.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Tar - 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 "TAR_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "TAR_EXPORTS" /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 0x419 /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\tar.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Tar - Win32 Release"
+# Name "Tar - 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"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Tar.ico
+# 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\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\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\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compress"
+
+# 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 "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\TarHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarHandlerOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarHeader.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarHeader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarIn.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarIn.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarItem.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarOut.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarOut.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarUpdate.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\TarUpdate.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\ItemNameUtils.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\ProgressUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\ProgressUtils.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
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Tar/Tar.dsw b/CPP/7zip/Archive/Tar/Tar.dsw
new file mode 100755
index 00000000..318cce1c
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/Tar.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Tar"=.\Tar.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Tar/TarHandler.cpp b/CPP/7zip/Archive/Tar/TarHandler.cpp
new file mode 100755
index 00000000..9c2cd006
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarHandler.cpp
@@ -0,0 +1,282 @@
+// Tar/Handler.cpp
+
+#include "StdAfx.h"
+
+#include "TarHandler.h"
+#include "TarIn.h"
+
+#include "Common/Defs.h"
+#include "Common/StringConvert.h"
+#include "Common/NewHandler.h"
+#include "Common/ComTry.h"
+
+#include "Windows/Time.h"
+#include "Windows/PropVariant.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Common/LimitedStreams.h"
+#include "../../Compress/Copy/CopyCoder.h"
+
+#include "../Common/ItemNameUtils.h"
+
+using namespace NWindows;
+using namespace NTime;
+
+namespace NArchive {
+namespace NTar {
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidIsFolder, VT_BOOL},
+ { NULL, kpidSize, VT_UI8},
+ { NULL, kpidPackedSize, VT_UI8},
+ { NULL, kpidLastWriteTime, VT_FILETIME},
+ { NULL, kpidUser, VT_BSTR},
+ { NULL, kpidGroup, VT_BSTR},
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback *openArchiveCallback)
+{
+ COM_TRY_BEGIN
+ // try
+ {
+ CInArchive archive;
+
+ if(archive.Open(stream) != S_OK)
+ return S_FALSE;
+
+ _items.Clear();
+
+ if (openArchiveCallback != NULL)
+ {
+ RINOK(openArchiveCallback->SetTotal(NULL, NULL));
+ UInt64 numFiles = _items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+
+ for (;;)
+ {
+ CItemEx item;
+ bool filled;
+ HRESULT result = archive.GetNextItem(filled, item);
+ if (result == S_FALSE)
+ return S_FALSE;
+ if (result != S_OK)
+ return S_FALSE;
+ if (!filled)
+ break;
+ _items.Add(item);
+ archive.SkeepDataRecords(item.Size);
+ if (openArchiveCallback != NULL)
+ {
+ UInt64 numFiles = _items.Size();
+ RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL));
+ }
+ }
+ if (_items.Size() == 0)
+ return S_FALSE;
+
+ _inStream = stream;
+ }
+ /*
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ */
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _items.Clear();
+ _inStream.Release();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = _items.Size();
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ const NArchive::NTar::CItemEx &item = _items[index];
+
+ switch(propID)
+ {
+ case kpidPath:
+ propVariant = (const wchar_t *)NItemName::GetOSName2(
+ MultiByteToUnicodeString(item.Name, CP_OEMCP));
+ break;
+ case kpidIsFolder:
+ propVariant = item.IsDirectory();
+ break;
+ case kpidSize:
+ case kpidPackedSize:
+ propVariant = (UInt64)item.Size;
+ break;
+ case kpidLastWriteTime:
+ {
+ FILETIME utcFileTime;
+ if (item.ModificationTime != 0)
+ NTime::UnixTimeToFileTime((UInt32)item.ModificationTime, utcFileTime);
+ else
+ {
+ utcFileTime.dwLowDateTime = 0;
+ utcFileTime.dwHighDateTime = 0;
+ }
+ propVariant = utcFileTime;
+ break;
+ }
+ case kpidUser:
+ propVariant = (const wchar_t *)
+ MultiByteToUnicodeString(item.UserName, CP_OEMCP);
+ break;
+ case kpidGroup:
+ propVariant = (const wchar_t *)
+ MultiByteToUnicodeString(item.GroupName, CP_OEMCP);
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool testMode = (_aTestMode != 0);
+ bool allFilesMode = (numItems == UInt32(-1));
+ if (allFilesMode)
+ numItems = _items.Size();
+ UInt64 totalSize = 0;
+ if(numItems == 0)
+ return S_OK;
+ UInt32 i;
+ for(i = 0; i < numItems; i++)
+ totalSize += _items[allFilesMode ? i : indices[i]].Size;
+ extractCallback->SetTotal(totalSize);
+
+ UInt64 currentTotalSize = 0;
+ UInt64 currentItemSize;
+
+ CMyComPtr<ICompressCoder> copyCoder;
+
+ for(i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
+ {
+ RINOK(extractCallback->SetCompleted(&currentTotalSize));
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+ Int32 index = allFilesMode ? i : indices[i];
+ const CItemEx &item = _items[index];
+
+ RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
+
+ currentItemSize = item.Size;
+
+ if(item.IsDirectory())
+ {
+ RINOK(extractCallback->PrepareOperation(askMode));
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+ if(!testMode && (!realOutStream))
+ {
+ continue;
+ }
+ RINOK(extractCallback->PrepareOperation(askMode));
+ {
+ if (testMode)
+ {
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ continue;
+ }
+
+ RINOK(_inStream->Seek(item.GetDataPosition(), STREAM_SEEK_SET, NULL));
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<ISequentialInStream> inStream(streamSpec);
+ streamSpec->SetStream(_inStream);
+ streamSpec->Init(item.Size);
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, false);
+
+
+ CLocalCompressProgressInfo *localCompressProgressSpec =
+ new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+ localCompressProgressSpec->Init(progress,
+ &currentTotalSize, &currentTotalSize);
+
+ if(!copyCoder)
+ {
+ copyCoder = new NCompress::CCopyCoder;
+ }
+ try
+ {
+ RINOK(copyCoder->Code(inStream, realOutStream,
+ NULL, NULL, compressProgress));
+ }
+ catch(...)
+ {
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kDataError));
+ continue;
+ }
+ realOutStream.Release();
+ RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
+ }
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Tar/TarHandler.h b/CPP/7zip/Archive/Tar/TarHandler.h
new file mode 100755
index 00000000..7b6e3a40
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarHandler.h
@@ -0,0 +1,56 @@
+// Tar/Handler.h
+
+#ifndef __TAR_HANDLER_H
+#define __TAR_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+#include "TarItem.h"
+
+namespace NArchive {
+namespace NTar {
+
+class CHandler:
+ public IInArchive,
+ public IOutArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP2(
+ IInArchive,
+ IOutArchive
+ )
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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 *type);
+
+private:
+ CObjectVector<CItemEx> _items;
+ CMyComPtr<IInStream> _inStream;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/TarHandlerOut.cpp b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
new file mode 100755
index 00000000..110833fb
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarHandlerOut.cpp
@@ -0,0 +1,126 @@
+// Tar/HandlerOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/StringConvert.h"
+#include "Common/ComTry.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Time.h"
+
+#include "../Common/ItemNameUtils.h"
+
+#include "TarHandler.h"
+#include "TarUpdate.h"
+
+using namespace NWindows;
+using namespace NCOM;
+using namespace NTime;
+
+namespace NArchive {
+namespace NTar {
+
+STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type)
+{
+ *type = NFileTimeType::kUnix;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COM_TRY_BEGIN
+ CObjectVector<CUpdateItemInfo> updateItems;
+ for(UInt32 i = 0; i < numItems; i++)
+ {
+ CUpdateItemInfo updateItem;
+ Int32 newData;
+ Int32 newProperties;
+ UInt32 indexInArchive;
+ if (!updateCallback)
+ return E_FAIL;
+ RINOK(updateCallback->GetUpdateItemInfo(i,
+ &newData, &newProperties, &indexInArchive));
+ updateItem.NewProperties = IntToBool(newProperties);
+ updateItem.NewData = IntToBool(newData);
+ updateItem.IndexInArchive = indexInArchive;
+ updateItem.IndexInClient = i;
+
+ if (IntToBool(newProperties))
+ {
+ FILETIME utcTime;
+ UString name;
+ bool isDirectoryStatusDefined;
+ UInt32 attributes;
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));
+ if (propVariant.vt == VT_EMPTY)
+ attributes = 0;
+ else if (propVariant.vt != VT_UI4)
+ return E_INVALIDARG;
+ else
+ attributes = propVariant.ulVal;
+ }
+ {
+ NCOM::CPropVariant propVariant;
+ RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant));
+ if (propVariant.vt != VT_FILETIME)
+ return E_INVALIDARG;
+ utcTime = 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;
+ }
+ }
+ updateItem.Name = UnicodeStringToMultiByte(
+ NItemName::MakeLegalName(name), CP_OEMCP);
+ if (!isDirectoryStatusDefined)
+ updateItem.IsDirectory = ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0);
+ if (updateItem.IsDirectory)
+ updateItem.Name += '/';
+
+ if(!FileTimeToUnixTime(utcTime, updateItem.Time))
+ {
+ updateItem.Time = 0;
+ // return E_INVALIDARG;
+ }
+ }
+ 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);
+ }
+ return UpdateArchive(_inStream, outStream, _items, updateItems, updateCallback);
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Tar/TarHeader.cpp b/CPP/7zip/Archive/Tar/TarHeader.cpp
new file mode 100755
index 00000000..35f0d0cf
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarHeader.cpp
@@ -0,0 +1,25 @@
+// Archive/Tar/Header.h
+
+#include "StdAfx.h"
+
+#include "TarHeader.h"
+
+namespace NArchive {
+namespace NTar {
+namespace NFileHeader {
+
+ // The checksum field is filled with this while the checksum is computed.
+ const char *kCheckSumBlanks = " "; // 8 blanks, no null
+
+ const char *kLongLink = "././@LongLink";
+ const char *kLongLink2 = "@LongLink";
+
+ // The magic field is filled with this if uname and gname are valid.
+ namespace NMagic
+ {
+ const char *kUsTar = "ustar"; // 5 chars
+ const char *kGNUTar = "GNUtar "; // 7 chars and a null
+ const char *kEmpty = "\0\0\0\0\0\0\0\0"; // 7 chars and a null
+ }
+
+}}}
diff --git a/CPP/7zip/Archive/Tar/TarHeader.h b/CPP/7zip/Archive/Tar/TarHeader.h
new file mode 100755
index 00000000..0ab31e52
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarHeader.h
@@ -0,0 +1,99 @@
+// Archive/Tar/Header.h
+
+#ifndef __ARCHIVE_TAR_HEADER_H
+#define __ARCHIVE_TAR_HEADER_H
+
+#include "Common/Types.h"
+
+namespace NArchive {
+namespace NTar {
+
+namespace NFileHeader
+{
+ const int kRecordSize = 512;
+ const int kNameSize = 100;
+ const int kUserNameSize = 32;
+ const int kGroupNameSize = 32;
+ const int kPrefixSize = 155;
+
+ /*
+ struct CHeader
+ {
+ char Name[kNameSize];
+ char Mode[8];
+ char UID[8];
+ char GID[8];
+ char Size[12];
+ char ModificationTime[12];
+ char CheckSum[8];
+ char LinkFlag;
+ char LinkName[kNameSize];
+ char Magic[8];
+ char UserName[kUserNameSize];
+ char GroupName[kGroupNameSize];
+ char DeviceMajor[8];
+ char DeviceMinor[8];
+ char Prefix[155];
+ };
+ union CRecord
+ {
+ CHeader Header;
+ Byte Padding[kRecordSize];
+ };
+ */
+
+ namespace NMode
+ {
+ const int kSetUID = 04000; // Set UID on execution
+ const int kSetGID = 02000; // Set GID on execution
+ const int kSaveText = 01000; // Save text (sticky bit)
+ }
+
+ namespace NFilePermissions
+ {
+ const int kUserRead = 00400; // read by owner
+ const int kUserWrite = 00200; // write by owner
+ const int kUserExecute = 00100; // execute/search by owner
+ const int kGroupRead = 00040; // read by group
+ const int kGroupWrite = 00020; // write by group
+ const int kGroupExecute = 00010; // execute/search by group
+ const int kOtherRead = 00004; // read by other
+ const int kOtherWrite = 00002; // write by other
+ const int kOtherExecute = 00001; // execute/search by other
+ }
+
+
+ // The linkflag defines the type of file
+ namespace NLinkFlag
+ {
+ const char kOldNormal = '\0'; // Normal disk file, Unix compatible
+ const char kNormal = '0'; // Normal disk file
+ const char kLink = '1'; // Link to previously dumped file
+ const char kSymbolicLink = '2'; // Symbolic link
+ const char kCharacter = '3'; // Character special file
+ const char kBlock = '4'; // Block special file
+ const char kDirectory = '5'; // Directory
+ const char kFIFO = '6'; // FIFO special file
+ const char kContiguous = '7'; // Contiguous file
+ }
+ // Further link types may be defined later.
+
+ // The checksum field is filled with this while the checksum is computed.
+ extern const char *kCheckSumBlanks;// = " "; // 8 blanks, no null
+
+ extern const char *kLongLink; // = "././@LongLink";
+ extern const char *kLongLink2; // = "@LongLink";
+
+ // The magic field is filled with this if uname and gname are valid.
+ namespace NMagic
+ {
+ extern const char *kUsTar; // = "ustar"; // 5 chars
+ extern const char *kGNUTar; // = "GNUtar "; // 7 chars and a null
+ extern const char *kEmpty; // = "GNUtar "; // 7 chars and a null
+ }
+
+}
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
new file mode 100755
index 00000000..86afc482
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -0,0 +1,248 @@
+// Archive/TarIn.cpp
+
+#include "StdAfx.h"
+
+#include "TarIn.h"
+#include "TarHeader.h"
+
+#include "Common/StringToInt.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NTar {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ RINOK(ReadStream(m_Stream, data, size, &processedSize));
+ m_Position += processedSize;
+ return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+ m_Stream = inStream;
+ 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;
+ }
+}
+
+static bool OctalToNumber(const char *srcString, int size, UInt64 &res)
+{
+ char sz[32];
+ MyStrNCpy(sz, srcString, size);
+ sz[size] = 0;
+ const char *end;
+ int i;
+ for (i = 0; sz[i] == ' '; i++);
+ res = ConvertOctStringToUInt64(sz + i, &end);
+ return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *srcString, int size, UInt32 &res)
+{
+ UInt64 res64;
+ if (!OctalToNumber(srcString, size, res64))
+ return false;
+ res = (UInt32)res64;
+ return (res64 <= 0xFFFFFFFF);
+}
+
+#define RIF(x) { if (!(x)) return S_FALSE; }
+
+static bool IsRecordLast(const char *record)
+{
+ for (int i = 0; i < NFileHeader::kRecordSize; i++)
+ if (record[i] != 0)
+ return false;
+ return true;
+}
+
+static void ReadString(const char *s, int size, AString &result)
+{
+ if (size > NFileHeader::kRecordSize)
+ size = NFileHeader::kNameSize;
+ char tempString[NFileHeader::kRecordSize + 1];
+ MyStrNCpy(tempString, s, size);
+ tempString[size] = '\0';
+ result = tempString;
+}
+
+static char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
+{
+ item.LongLinkSize = 0;
+ // NFileHeader::CRecord record;
+ char record[NFileHeader::kRecordSize];
+ char *cur = record;
+
+ filled = false;
+
+ UInt32 processedSize;
+ item.HeaderPosition = m_Position;
+ RINOK(ReadBytes(record, NFileHeader::kRecordSize, processedSize));
+ if (processedSize == 0 ||
+ (processedSize == NFileHeader::kRecordSize && IsRecordLast(record)))
+ return S_OK;
+ if (processedSize < NFileHeader::kRecordSize)
+ return S_FALSE;
+
+ // NFileHeader::CHeader &header = record.Header;
+
+ AString name;
+ ReadString(cur, NFileHeader::kNameSize, name);
+ cur += NFileHeader::kNameSize;
+
+ item.Name.Empty();
+ int i;
+ for (i = 0; i < name.Length(); i++)
+ {
+ char c = name[i];
+ if (((Byte)c) < 0x08)
+ {
+ return S_FALSE;
+ }
+ if (((Byte)c) < 0x20)
+ {
+ item.Name += '[';
+ item.Name += GetHex((Byte)(((Byte)c) >> 4));
+ item.Name += GetHex((Byte)(((Byte)c) & 0xF));
+ item.Name += ']';
+ }
+ else
+ item.Name += c;
+ }
+
+ RIF(OctalToNumber32(cur, 8, item.Mode));
+ cur += 8;
+
+ if (!OctalToNumber32(cur, 8, item.UID))
+ item.UID = 0;
+ cur += 8;
+
+ if (!OctalToNumber32(cur, 8, item.GID))
+ item.GID = 0;
+ cur += 8;
+
+ RIF(OctalToNumber(cur, 12, item.Size));
+ cur += 12;
+
+ RIF(OctalToNumber32(cur, 12, item.ModificationTime));
+ cur += 12;
+
+ UInt32 checkSum;
+ RIF(OctalToNumber32(cur, 8, checkSum));
+ memmove(cur, NFileHeader::kCheckSumBlanks, 8);
+ cur += 8;
+
+ item.LinkFlag = *cur++;
+
+ ReadString(cur, NFileHeader::kNameSize, item.LinkName);
+ cur += NFileHeader::kNameSize;
+
+ memmove(item.Magic, cur, 8);
+ cur += 8;
+
+ ReadString(cur, NFileHeader::kUserNameSize, item.UserName);
+ cur += NFileHeader::kUserNameSize;
+ ReadString(cur, NFileHeader::kUserNameSize, item.GroupName);
+ cur += NFileHeader::kUserNameSize;
+
+ item.DeviceMajorDefined = (cur[0] != 0);
+ RIF(OctalToNumber32(cur, 8, item.DeviceMajor));
+ cur += 8;
+
+ item.DeviceMinorDefined = (cur[0] != 0);
+ RIF(OctalToNumber32(cur, 8, item.DeviceMinor));
+ cur += 8;
+
+ AString prefix;
+ ReadString(cur, NFileHeader::kPrefixSize, prefix);
+ cur += NFileHeader::kPrefixSize;
+ if (!prefix.IsEmpty() && item.IsMagic())
+ item.Name = prefix + AString('/') + item.Name;
+
+ if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
+ item.Size = 0;
+
+
+ UInt32 checkSumReal = 0;
+ for(i = 0; i < NFileHeader::kRecordSize; i++)
+ checkSumReal += Byte(record[i]);
+
+ if (checkSumReal != checkSum)
+ return S_FALSE;
+
+ filled = true;
+ return S_OK;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+ RINOK(GetNextItemReal(filled, item));
+ if (!filled)
+ return S_OK;
+ // GNUtar extension
+ if (item.LinkFlag == 'L')
+ {
+ if (item.Name.Compare(NFileHeader::kLongLink) != 0)
+ if (item.Name.Compare(NFileHeader::kLongLink2) != 0)
+ return S_FALSE;
+ UInt64 headerPosition = item.HeaderPosition;
+
+ UInt32 processedSize;
+ AString fullName;
+ char *buffer = fullName.GetBuffer((UInt32)item.Size + 1);
+ RINOK(ReadBytes(buffer, (UInt32)item.Size, processedSize));
+ buffer[item.Size] = '\0';
+ fullName.ReleaseBuffer();
+ if (processedSize != item.Size)
+ return S_FALSE;
+ RINOK(Skeep((0 - item.Size) & 0x1FF));
+ RINOK(GetNextItemReal(filled, item));
+ item.Name = fullName;
+ item.LongLinkSize = item.HeaderPosition - headerPosition;
+ item.HeaderPosition = headerPosition;
+ }
+ else if (item.LinkFlag == 'g' || item.LinkFlag == 'x')
+ {
+ // pax Extended Header
+ return S_OK;
+ }
+ else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
+ return S_FALSE;
+ return S_OK;
+}
+
+HRESULT CInArchive::Skeep(UInt64 numBytes)
+{
+ UInt64 newPostion;
+ RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+ m_Position += numBytes;
+ if (m_Position != newPostion)
+ return E_FAIL;
+ return S_OK;
+}
+
+
+HRESULT CInArchive::SkeepDataRecords(UInt64 dataSize)
+{
+ return Skeep((dataSize + 0x1FF) & (~((UInt64)0x1FF)));
+}
+
+}}
diff --git a/CPP/7zip/Archive/Tar/TarIn.h b/CPP/7zip/Archive/Tar/TarIn.h
new file mode 100755
index 00000000..28781375
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarIn.h
@@ -0,0 +1,30 @@
+// Archive/TarIn.h
+
+#ifndef __ARCHIVE_TAR_IN_H
+#define __ARCHIVE_TAR_IN_H
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+
+#include "TarItem.h"
+
+namespace NArchive {
+namespace NTar {
+
+class CInArchive
+{
+ CMyComPtr<IInStream> m_Stream;
+ UInt64 m_Position;
+
+ HRESULT ReadBytes(void *data, UInt32 size, UInt32 &processedSize);
+public:
+ HRESULT Open(IInStream *inStream);
+ HRESULT GetNextItemReal(bool &filled, CItemEx &itemInfo);
+ HRESULT GetNextItem(bool &filled, CItemEx &itemInfo);
+ HRESULT Skeep(UInt64 numBytes);
+ HRESULT SkeepDataRecords(UInt64 dataSize);
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/TarItem.h b/CPP/7zip/Archive/Tar/TarItem.h
new file mode 100755
index 00000000..71fff7ba
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarItem.h
@@ -0,0 +1,69 @@
+// Archive/Tar/Item.h
+
+#ifndef __ARCHIVE_TAR_ITEM_H
+#define __ARCHIVE_TAR_ITEM_H
+
+#include <time.h>
+
+#include "Common/Types.h"
+#include "Common/String.h"
+
+#include "../Common/ItemNameUtils.h"
+#include "TarHeader.h"
+
+namespace NArchive {
+namespace NTar {
+
+class CItem
+{
+public:
+ AString Name;
+ UInt32 Mode;
+ UInt32 UID;
+ UInt32 GID;
+ UInt64 Size;
+ UInt32 ModificationTime;
+ char LinkFlag;
+ AString LinkName;
+ char Magic[8];
+ AString UserName;
+ AString GroupName;
+
+ bool DeviceMajorDefined;
+ UInt32 DeviceMajor;
+ bool DeviceMinorDefined;
+ UInt32 DeviceMinor;
+
+ bool IsDirectory() const
+ {
+ if (LinkFlag == NFileHeader::NLinkFlag::kDirectory)
+ return true;
+ if (LinkFlag == NFileHeader::NLinkFlag::kOldNormal ||
+ LinkFlag == NFileHeader::NLinkFlag::kNormal)
+ {
+ return NItemName::HasTailSlash(Name, CP_OEMCP);
+ }
+ return false;
+ }
+
+ bool IsMagic() const
+ {
+ for (int i = 0; i < 5; i++)
+ if (Magic[i] != NFileHeader::NMagic::kUsTar[i])
+ return false;
+ return true;
+ }
+};
+
+class CItemEx: public CItem
+{
+public:
+ UInt64 HeaderPosition;
+ UInt64 LongLinkSize;
+ UInt64 GetDataPosition() const { return HeaderPosition + LongLinkSize + NFileHeader::kRecordSize; };
+ UInt64 GetFullSize() const { return LongLinkSize + NFileHeader::kRecordSize + Size; };
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp
new file mode 100755
index 00000000..e278edda
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarOut.cpp
@@ -0,0 +1,191 @@
+// Archive/TarOut.cpp
+
+#include "StdAfx.h"
+
+#include "TarOut.h"
+#include "TarHeader.h"
+
+#include "Common/IntToString.h"
+#include "Windows/Defs.h"
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NTar {
+
+HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)
+{
+ UInt32 processedSize;
+ RINOK(WriteStream(m_Stream, buffer, size, &processedSize));
+ if(processedSize != size)
+ return E_FAIL;
+ return S_OK;
+}
+
+void COutArchive::Create(ISequentialOutStream *outStream)
+{
+ m_Stream = outStream;
+}
+
+static AString MakeOctalString(UInt64 value)
+{
+ char s[32];
+ ConvertUInt64ToString(value, s, 8);
+ return AString(s) + ' ';
+}
+
+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;
+ }
+}
+
+static bool MakeOctalString8(char *s, UInt32 value)
+{
+ AString tempString = MakeOctalString(value);
+
+ const int kMaxSize = 8;
+ if (tempString.Length() >= kMaxSize)
+ return false;
+ int numSpaces = kMaxSize - (tempString.Length() + 1);
+ for(int i = 0; i < numSpaces; i++)
+ s[i] = ' ';
+ MyStringCopy(s + numSpaces, (const char *)tempString);
+ return true;
+}
+
+static bool MakeOctalString12(char *s, UInt64 value)
+{
+ AString tempString = MakeOctalString(value);
+ const int kMaxSize = 12;
+ if (tempString.Length() > kMaxSize)
+ return false;
+ int numSpaces = kMaxSize - tempString.Length();
+ for(int i = 0; i < numSpaces; i++)
+ s[i] = ' ';
+ memmove(s + numSpaces, (const char *)tempString, tempString.Length());
+ return true;
+}
+
+static bool CopyString(char *dest, const AString &src, int maxSize)
+{
+ if (src.Length() >= maxSize)
+ return false;
+ MyStringCopy(dest, (const char *)src);
+ return true;
+}
+
+#define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; }
+
+HRESULT COutArchive::WriteHeaderReal(const CItem &item)
+{
+ char record[NFileHeader::kRecordSize];
+ char *cur = record;
+ int i;
+ for (i = 0; i < NFileHeader::kRecordSize; i++)
+ record[i] = 0;
+
+ // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize));
+ if (item.Name.Length() > NFileHeader::kNameSize)
+ return E_FAIL;
+ MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
+ cur += NFileHeader::kNameSize;
+
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode));
+ cur += 8;
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID));
+ cur += 8;
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID));
+ cur += 8;
+
+ RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.Size));
+ cur += 12;
+ RETURN_IF_NOT_TRUE(MakeOctalString12(cur, item.ModificationTime));
+ cur += 12;
+
+ memmove(cur, NFileHeader::kCheckSumBlanks, 8);
+ cur += 8;
+
+ *cur++ = item.LinkFlag;
+
+ RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize));
+ cur += NFileHeader::kNameSize;
+
+ memmove(cur, item.Magic, 8);
+ cur += 8;
+
+ RETURN_IF_NOT_TRUE(CopyString(cur, item.UserName, NFileHeader::kUserNameSize));
+ cur += NFileHeader::kUserNameSize;
+ RETURN_IF_NOT_TRUE(CopyString(cur, item.GroupName, NFileHeader::kGroupNameSize));
+ cur += NFileHeader::kUserNameSize;
+
+
+ if (item.DeviceMajorDefined)
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor));
+ cur += 8;
+
+ if (item.DeviceMinorDefined)
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor));
+ cur += 8;
+
+
+ UInt32 checkSumReal = 0;
+ for(i = 0; i < NFileHeader::kRecordSize; i++)
+ checkSumReal += Byte(record[i]);
+
+ RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
+
+ return WriteBytes(record, NFileHeader::kRecordSize);
+}
+
+HRESULT COutArchive::WriteHeader(const CItem &item)
+{
+ int nameSize = item.Name.Length();
+ if (nameSize < NFileHeader::kNameSize)
+ return WriteHeaderReal(item);
+
+ CItem modifiedItem = item;
+ int nameStreamSize = nameSize + 1;
+ modifiedItem.Size = nameStreamSize;
+ modifiedItem.LinkFlag = 'L';
+ modifiedItem.Name = NFileHeader::kLongLink;
+ modifiedItem.LinkName.Empty();
+ RINOK(WriteHeaderReal(modifiedItem));
+ RINOK(WriteBytes(item.Name, nameStreamSize));
+ RINOK(FillDataResidual(nameStreamSize));
+
+ modifiedItem = item;
+ modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1);
+ return WriteHeaderReal(modifiedItem);
+}
+
+HRESULT COutArchive::FillDataResidual(UInt64 dataSize)
+{
+ UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1));
+ if (lastRecordSize == 0)
+ return S_OK;
+ UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize;
+ Byte residualBytes[NFileHeader::kRecordSize];
+ for (UInt32 i = 0; i < residualSize; i++)
+ residualBytes[i] = 0;
+ return WriteBytes(residualBytes, residualSize);
+}
+
+HRESULT COutArchive::WriteFinishHeader()
+{
+ Byte record[NFileHeader::kRecordSize];
+ int i;
+ for (i = 0; i < NFileHeader::kRecordSize; i++)
+ record[i] = 0;
+ for (i = 0; i < 2; i++)
+ {
+ RINOK(WriteBytes(record, NFileHeader::kRecordSize));
+ }
+ return S_OK;
+}
+
+}}
diff --git a/CPP/7zip/Archive/Tar/TarOut.h b/CPP/7zip/Archive/Tar/TarOut.h
new file mode 100755
index 00000000..ef837869
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarOut.h
@@ -0,0 +1,28 @@
+// Archive/TarOut.h
+
+#ifndef __ARCHIVE_TAR_OUT_H
+#define __ARCHIVE_TAR_OUT_H
+
+#include "TarItem.h"
+
+#include "Common/MyCom.h"
+#include "../../IStream.h"
+
+namespace NArchive {
+namespace NTar {
+
+class COutArchive
+{
+ CMyComPtr<ISequentialOutStream> m_Stream;
+ HRESULT WriteBytes(const void *buffer, UInt32 size);
+public:
+ void Create(ISequentialOutStream *outStream);
+ HRESULT WriteHeaderReal(const CItem &item);
+ HRESULT WriteHeader(const CItem &item);
+ HRESULT FillDataResidual(UInt64 dataSize);
+ HRESULT WriteFinishHeader();
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.cpp b/CPP/7zip/Archive/Tar/TarUpdate.cpp
new file mode 100755
index 00000000..9a6f64e2
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarUpdate.cpp
@@ -0,0 +1,162 @@
+// TarUpdate.cpp
+
+#include "StdAfx.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 "TarOut.h"
+#include "TarUpdate.h"
+
+static const UInt64 kOneItemComplexity = 512;
+
+namespace NArchive {
+namespace NTar {
+
+static HRESULT CopyBlock(ISequentialInStream *inStream,
+ ISequentialOutStream *outStream, ICompressProgressInfo *progress,
+ UInt64 *totalSize = NULL)
+{
+ NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder;
+ CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
+ HRESULT result = copyCoder->Code(inStream, outStream, NULL, NULL, progress);
+ if (totalSize != NULL)
+ *totalSize = copyCoderSpec->TotalSize;
+ return result;
+}
+
+HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
+ const CObjectVector<NArchive::NTar::CItemEx> &inputItems,
+ const CObjectVector<CUpdateItemInfo> &updateItems,
+ IArchiveUpdateCallback *updateCallback)
+{
+ COutArchive outArchive;
+ outArchive.Create(outStream);
+
+ UInt64 complexity = 0;
+
+ int i;
+ for(i = 0; i < updateItems.Size(); i++)
+ {
+ const CUpdateItemInfo &updateItem = updateItems[i];
+ if (updateItem.NewData)
+ complexity += updateItem.Size;
+ else
+ complexity += inputItems[updateItem.IndexInArchive].GetFullSize();
+ complexity += kOneItemComplexity;
+ }
+
+ RINOK(updateCallback->SetTotal(complexity));
+
+ complexity = 0;
+
+ for(i = 0; i < updateItems.Size(); i++)
+ {
+ RINOK(updateCallback->SetCompleted(&complexity));
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> localProgress = localProgressSpec;
+ localProgressSpec->Init(updateCallback, true);
+
+ CLocalCompressProgressInfo *localCompressProgressSpec = new CLocalCompressProgressInfo;
+ CMyComPtr<ICompressProgressInfo> compressProgress = localCompressProgressSpec;
+
+ localCompressProgressSpec->Init(localProgress, &complexity, NULL);
+
+ const CUpdateItemInfo &updateItem = updateItems[i];
+ CItem item;
+ if (updateItem.NewProperties)
+ {
+ item.Mode = 0777;
+ item.Name = (updateItem.Name);
+ if (updateItem.IsDirectory)
+ {
+ item.LinkFlag = NFileHeader::NLinkFlag::kDirectory;
+ item.Size = 0;
+ }
+ else
+ {
+ item.LinkFlag = NFileHeader::NLinkFlag::kNormal;
+ item.Size = updateItem.Size;
+ }
+ item.ModificationTime = updateItem.Time;
+ item.DeviceMajorDefined = false;
+ item.DeviceMinorDefined = false;
+ item.UID = 0;
+ item.GID = 0;
+ memmove(item.Magic, NFileHeader::NMagic::kEmpty, 8);
+ }
+ else
+ {
+ const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive];
+ item = existItemInfo;
+ }
+ if (updateItem.NewData)
+ {
+ item.Size = updateItem.Size;
+ if (item.Size == UInt64(Int64(-1)))
+ return E_INVALIDARG;
+ }
+ else
+ {
+ const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive];
+ item.Size = existItemInfo.Size;
+ }
+
+ if (updateItem.NewData)
+ {
+ CMyComPtr<ISequentialInStream> fileInStream;
+ HRESULT res = updateCallback->GetStream(updateItem.IndexInClient, &fileInStream);
+ if (res != S_FALSE)
+ {
+ RINOK(res);
+ RINOK(outArchive.WriteHeader(item));
+ if (!updateItem.IsDirectory)
+ {
+ UInt64 totalSize;
+ RINOK(CopyBlock(fileInStream, outStream, compressProgress, &totalSize));
+ if (totalSize != item.Size)
+ return E_FAIL;
+ RINOK(outArchive.FillDataResidual(item.Size));
+ }
+ }
+ complexity += updateItem.Size;
+ RINOK(updateCallback->SetOperationResult(
+ NArchive::NUpdate::NOperationResult::kOK));
+ }
+ else
+ {
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ CMyComPtr<CLimitedSequentialInStream> inStreamLimited(streamSpec);
+ const CItemEx &existItemInfo = inputItems[updateItem.IndexInArchive];
+ if (updateItem.NewProperties)
+ {
+ RINOK(outArchive.WriteHeader(item));
+ RINOK(inStream->Seek(existItemInfo.GetDataPosition(),
+ STREAM_SEEK_SET, NULL));
+ streamSpec->SetStream(inStream);
+ streamSpec->Init(existItemInfo.Size);
+ }
+ else
+ {
+ RINOK(inStream->Seek(existItemInfo.HeaderPosition,
+ STREAM_SEEK_SET, NULL));
+ streamSpec->SetStream(inStream);
+ streamSpec->Init(existItemInfo.GetFullSize());
+ }
+ RINOK(CopyBlock(inStreamLimited, outStream, compressProgress));
+ RINOK(outArchive.FillDataResidual(existItemInfo.Size));
+ complexity += existItemInfo.GetFullSize();
+ }
+ complexity += kOneItemComplexity;
+ }
+ return outArchive.WriteFinishHeader();
+}
+
+}}
+
diff --git a/CPP/7zip/Archive/Tar/TarUpdate.h b/CPP/7zip/Archive/Tar/TarUpdate.h
new file mode 100755
index 00000000..92f5cebb
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarUpdate.h
@@ -0,0 +1,36 @@
+// Tar/Update.h
+
+#ifndef __TAR_UPDATE_H
+#define __TAR_UPDATE_H
+
+#include "Common/Vector.h"
+#include "Common/Types.h"
+#include "Common/String.h"
+
+#include "../IArchive.h"
+#include "TarItem.h"
+
+namespace NArchive {
+namespace NTar {
+
+struct CUpdateItemInfo
+{
+ bool NewData;
+ bool NewProperties;
+ int IndexInArchive;
+ int IndexInClient;
+
+ UInt32 Time;
+ UInt64 Size;
+ AString Name;
+ bool IsDirectory;
+};
+
+HRESULT UpdateArchive(IInStream *inStream, ISequentialOutStream *outStream,
+ const CObjectVector<CItemEx> &inputItems,
+ const CObjectVector<CUpdateItemInfo> &updateItems,
+ IArchiveUpdateCallback *updateCallback);
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Tar/makefile b/CPP/7zip/Archive/Tar/makefile
new file mode 100755
index 00000000..f892c303
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/makefile
@@ -0,0 +1,59 @@
+PROG = tar.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib user32.lib
+
+TAR_OBJS = \
+ $O\DllExports.obj \
+ $O\TarHandler.obj \
+ $O\TarHandlerOut.obj \
+ $O\TarHeader.obj \
+ $O\TarIn.obj \
+ $O\TarOut.obj \
+ $O\TarUpdate.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\IntToString.obj \
+ $O\NewHandler.obj \
+ $O\String.obj \
+ $O\StringConvert.obj \
+ $O\StringToInt.obj \
+ $O\Vector.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\LimitedStreams.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\ItemNameUtils.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(TAR_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_TAR_OBJS) \
+ $O\CopyCoder.obj \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(TAR_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)
+$O\CopyCoder.obj: ../../Compress/Copy/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Tar/resource.rc b/CPP/7zip/Archive/Tar/resource.rc
new file mode 100755
index 00000000..3d37f440
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Tar Plugin", "tar")
+
+101 ICON "tar.ico"
diff --git a/CPP/7zip/Archive/Tar/tar.ico b/CPP/7zip/Archive/Tar/tar.ico
new file mode 100755
index 00000000..6835885b
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/tar.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Z/DllExports.cpp b/CPP/7zip/Archive/Z/DllExports.cpp
new file mode 100755
index 00000000..b8df85f4
--- /dev/null
+++ b/CPP/7zip/Archive/Z/DllExports.cpp
@@ -0,0 +1,91 @@
+// DLLExports.cpp
+
+#include "StdAfx.h"
+
+#include "Common/MyInitGuid.h"
+#include "Common/ComTry.h"
+#include "Windows/PropVariant.h"
+#include "ZHandler.h"
+#include "../../ICoder.h"
+
+// {23170F69-40C1-278A-1000-000110050000}
+DEFINE_GUID(CLSID_CZHandler,
+0x23170F69, 0x40C1, 0x278A, 0x10, 0x00, 0x00, 0x01, 0x10, 0x05, 0x00, 0x00);
+
+extern "C"
+BOOL WINAPI DllMain(HINSTANCE /* hInstance */, DWORD /* dwReason */, LPVOID /* lpReserved */)
+{
+ return TRUE;
+}
+
+STDAPI CreateObject(
+ const GUID *classID,
+ const GUID *interfaceID,
+ void **outObject)
+{
+ COM_TRY_BEGIN
+ *outObject = 0;
+ if (*classID != CLSID_CZHandler)
+ return CLASS_E_CLASSNOTAVAILABLE;
+ int needIn = *interfaceID == IID_IInArchive;
+ int needOut = *interfaceID == IID_IOutArchive;
+ if (needIn || needOut)
+ {
+ NArchive::NZ::CHandler *temp = new NArchive::NZ::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"Z";
+ break;
+ case NArchive::kClassID:
+ {
+ if ((value->bstrVal = ::SysAllocStringByteLen(
+ (const char *)&CLSID_CZHandler, sizeof(GUID))) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+ case NArchive::kExtension:
+ propVariant = L"z taz";
+ break;
+ case NArchive::kAddExtension:
+ propVariant = L"* .tar";
+ break;
+ case NArchive::kUpdate:
+ propVariant = false;
+ break;
+ case NArchive::kKeepName:
+ propVariant = true;
+ break;
+ case NArchive::kStartSignature:
+ {
+ const unsigned char sig[] = { 0x1F, 0x9D };
+ if ((value->bstrVal = ::SysAllocStringByteLen((const char *)sig, 2)) != 0)
+ value->vt = VT_BSTR;
+ return S_OK;
+ }
+
+ }
+ propVariant.Detach(value);
+ return S_OK;
+}
diff --git a/CPP/7zip/Archive/Z/StdAfx.cpp b/CPP/7zip/Archive/Z/StdAfx.cpp
new file mode 100755
index 00000000..d0feea85
--- /dev/null
+++ b/CPP/7zip/Archive/Z/StdAfx.cpp
@@ -0,0 +1,3 @@
+// StdAfx.cpp
+
+#include "StdAfx.h"
diff --git a/CPP/7zip/Archive/Z/StdAfx.h b/CPP/7zip/Archive/Z/StdAfx.h
new file mode 100755
index 00000000..e7fb6986
--- /dev/null
+++ b/CPP/7zip/Archive/Z/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/Z/Z.dsp b/CPP/7zip/Archive/Z/Z.dsp
new file mode 100755
index 00000000..e1f72522
--- /dev/null
+++ b/CPP/7zip/Archive/Z/Z.dsp
@@ -0,0 +1,237 @@
+# Microsoft Developer Studio Project File - Name="Z" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=Z - 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 "Z.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 "Z.mak" CFG="Z - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "Z - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "Z - 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)" == "Z - 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 "BZIP2_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /Gz /MD /W3 /GX /O1 /I "..\..\..\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BZIP2_EXPORTS" /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 0x419 /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\z.dll" /opt:NOWIN98
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "Z - 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 "BZIP2_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /Gz /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "BZIP2_EXPORTS" /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 0x419 /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\z.dll" /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "Z - Win32 Release"
+# Name "Z - 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"StdAfx.h"
+# End Source File
+# Begin Source File
+
+SOURCE=.\StdAfx.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\Z.ico
+# 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\NewHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\NewHandler.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Common\StringConvert.h
+# End Source File
+# End Group
+# Begin Group "Windows"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\..\Windows\PropVariant.h
+# End Source File
+# End Group
+# Begin Group "Compression"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\..\Compress\Z\ZDecoder.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Compress\Z\ZDecoder.h
+# End Source File
+# End Group
+# Begin Group "Archive Common"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=..\Common\DummyOutStream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\Common\DummyOutStream.h
+# End Source File
+# End Group
+# Begin Group "Engine"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ZHandler.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\ZHandler.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\OutBuffer.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\OutBuffer.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\StreamUtils.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\Common\StreamUtils.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\z.ico
+# End Source File
+# End Target
+# End Project
diff --git a/CPP/7zip/Archive/Z/Z.dsw b/CPP/7zip/Archive/Z/Z.dsw
new file mode 100755
index 00000000..1f67186a
--- /dev/null
+++ b/CPP/7zip/Archive/Z/Z.dsw
@@ -0,0 +1,29 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "Z"=.\Z.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/CPP/7zip/Archive/Z/Z.ico b/CPP/7zip/Archive/Z/Z.ico
new file mode 100755
index 00000000..2db53583
--- /dev/null
+++ b/CPP/7zip/Archive/Z/Z.ico
Binary files differ
diff --git a/CPP/7zip/Archive/Z/ZHandler.cpp b/CPP/7zip/Archive/Z/ZHandler.cpp
new file mode 100755
index 00000000..33887690
--- /dev/null
+++ b/CPP/7zip/Archive/Z/ZHandler.cpp
@@ -0,0 +1,202 @@
+// ZHandler.cpp
+
+#include "StdAfx.h"
+
+#include "ZHandler.h"
+
+#include "Common/Defs.h"
+
+#include "../../Common/ProgressUtils.h"
+#include "../../Compress/Z/ZDecoder.h"
+#include "../../Common/StreamUtils.h"
+
+#include "Windows/PropVariant.h"
+#include "Windows/Defs.h"
+#include "Common/ComTry.h"
+
+#include "../Common/DummyOutStream.h"
+
+namespace NArchive {
+namespace NZ {
+
+STATPROPSTG kProperties[] =
+{
+ { NULL, kpidPath, VT_BSTR},
+ { NULL, kpidPackedSize, VT_UI8},
+};
+
+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_INVALIDARG;
+}
+
+STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
+{
+ *numItems = 1;
+ return S_OK;
+}
+
+STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
+{
+ COM_TRY_BEGIN
+ NWindows::NCOM::CPropVariant propVariant;
+ if (index != 0)
+ return E_INVALIDARG;
+ switch(propID)
+ {
+ case kpidIsFolder:
+ propVariant = false;
+ break;
+ case kpidPackedSize:
+ propVariant = _packSize;
+ break;
+ }
+ propVariant.Detach(value);
+ return S_OK;
+ COM_TRY_END
+}
+
+static const int kSignatureSize = 3;
+
+STDMETHODIMP CHandler::Open(IInStream *stream,
+ const UInt64 * /* maxCheckStartPosition */,
+ IArchiveOpenCallback * /* openArchiveCallback */)
+{
+ COM_TRY_BEGIN
+ try
+ {
+ RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition));
+ Byte buffer[kSignatureSize];
+ UInt32 processedSize;
+ RINOK(ReadStream(stream, buffer, kSignatureSize, &processedSize));
+ if (processedSize != kSignatureSize)
+ return S_FALSE;
+ if (buffer[0] != 0x1F || buffer[1] != 0x9D)
+ return S_FALSE;
+ _properties = buffer[2];
+
+ UInt64 endPosition;
+ RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition));
+ _packSize = endPosition - _streamStartPosition - kSignatureSize;
+
+ _stream = stream;
+ }
+ catch(...)
+ {
+ return S_FALSE;
+ }
+ return S_OK;
+ COM_TRY_END
+}
+
+STDMETHODIMP CHandler::Close()
+{
+ _stream.Release();
+ return S_OK;
+}
+
+
+STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
+ Int32 testModeSpec, IArchiveExtractCallback *extractCallback)
+{
+ COM_TRY_BEGIN
+ bool allFilesMode = (numItems == (UInt32)(-1));
+ if (!allFilesMode)
+ {
+ if (numItems == 0)
+ return S_OK;
+ if (numItems != 1)
+ return E_INVALIDARG;
+ if (indices[0] != 0)
+ return E_INVALIDARG;
+ }
+
+ bool testMode = (testModeSpec != 0);
+
+ extractCallback->SetTotal(_packSize);
+
+ UInt64 currentTotalPacked = 0;
+
+ RINOK(extractCallback->SetCompleted(&currentTotalPacked));
+
+ CMyComPtr<ISequentialOutStream> realOutStream;
+ Int32 askMode;
+ askMode = testMode ? NArchive::NExtract::NAskMode::kTest :
+ NArchive::NExtract::NAskMode::kExtract;
+
+ RINOK(extractCallback->GetStream(0, &realOutStream, askMode));
+
+ if(!testMode && !realOutStream)
+ return S_OK;
+
+ extractCallback->PrepareOperation(askMode);
+
+ CDummyOutStream *outStreamSpec = new CDummyOutStream;
+ CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
+ outStreamSpec->Init(realOutStream);
+
+ realOutStream.Release();
+
+ CLocalProgress *localProgressSpec = new CLocalProgress;
+ CMyComPtr<ICompressProgressInfo> progress = localProgressSpec;
+ localProgressSpec->Init(extractCallback, true);
+
+ RINOK(_stream->Seek(_streamStartPosition + kSignatureSize, STREAM_SEEK_SET, NULL));
+
+ CMyComPtr<ICompressCoder> decoder;
+ NCompress::NZ::CDecoder *decoderSpec = new NCompress::NZ::CDecoder;
+ decoder = decoderSpec;
+
+ HRESULT result = decoderSpec->SetDecoderProperties2(&_properties, 1);
+
+ int opResult;
+ if (result != S_OK)
+ opResult = NArchive::NExtract::NOperationResult::kUnSupportedMethod;
+ else
+ {
+ result = decoder->Code(_stream, outStream, NULL, NULL, progress);
+ outStream.Release();
+ if (result == S_FALSE)
+ opResult = NArchive::NExtract::NOperationResult::kDataError;
+ else if (result == S_OK)
+ opResult = NArchive::NExtract::NOperationResult::kOK;
+ else
+ return result;
+ }
+ RINOK(extractCallback->SetOperationResult(opResult));
+ return S_OK;
+ COM_TRY_END
+}
+
+}}
diff --git a/CPP/7zip/Archive/Z/ZHandler.h b/CPP/7zip/Archive/Z/ZHandler.h
new file mode 100755
index 00000000..7abba29f
--- /dev/null
+++ b/CPP/7zip/Archive/Z/ZHandler.h
@@ -0,0 +1,47 @@
+// ZHandler.h
+
+#ifndef __Z_HANDLER_H
+#define __Z_HANDLER_H
+
+#include "Common/MyCom.h"
+#include "../IArchive.h"
+
+namespace NArchive {
+namespace NZ {
+
+class CHandler:
+ public IInArchive,
+ public CMyUnknownImp
+{
+public:
+ MY_UNKNOWN_IMP
+
+ STDMETHOD(Open)(IInStream *stream,
+ const UInt64 *maxCheckStartPosition,
+ IArchiveOpenCallback *openArchiveCallback);
+ STDMETHOD(Close)();
+ STDMETHOD(GetNumberOfItems)(UInt32 *numItems);
+ STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value);
+ STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems,
+ Int32 testMode, IArchiveExtractCallback *extractCallback);
+
+ 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);
+
+private:
+ CMyComPtr<IInStream> _stream;
+ UInt64 _streamStartPosition;
+ UInt64 _packSize;
+ Byte _properties;
+};
+
+}}
+
+#endif
diff --git a/CPP/7zip/Archive/Z/makefile b/CPP/7zip/Archive/Z/makefile
new file mode 100755
index 00000000..aff4fc42
--- /dev/null
+++ b/CPP/7zip/Archive/Z/makefile
@@ -0,0 +1,52 @@
+PROG = z.dll
+DEF_FILE = ../Archive.def
+CFLAGS = $(CFLAGS) -I ../../../
+LIBS = $(LIBS) oleaut32.lib
+
+Z_OBJS = \
+ $O\DllExports.obj \
+ $O\ZHandler.obj \
+
+COMMON_OBJS = \
+ $O\Alloc.obj \
+ $O\NewHandler.obj \
+
+WIN_OBJS = \
+ $O\PropVariant.obj \
+
+7ZIP_COMMON_OBJS = \
+ $O\InBuffer.obj \
+ $O\OutBuffer.obj \
+ $O\ProgressUtils.obj \
+ $O\StreamUtils.obj \
+
+AR_COMMON_OBJS = \
+ $O\DummyOutStream.obj \
+
+COMPRESS_Z_OBJS = \
+ $O\ZDecoder.obj \
+
+OBJS = \
+ $O\StdAfx.obj \
+ $(Z_OBJS) \
+ $(COMMON_OBJS) \
+ $(WIN_OBJS) \
+ $(7ZIP_COMMON_OBJS) \
+ $(AR_COMMON_OBJS) \
+ $(COMPRESS_Z_OBJS) \
+ $O\resource.res
+
+!include "../../../Build.mak"
+
+$(Z_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)
+$(COMPRESS_Z_OBJS): ../../Compress/Z/$(*B).cpp
+ $(COMPL)
diff --git a/CPP/7zip/Archive/Z/resource.rc b/CPP/7zip/Archive/Z/resource.rc
new file mode 100755
index 00000000..05a81423
--- /dev/null
+++ b/CPP/7zip/Archive/Z/resource.rc
@@ -0,0 +1,5 @@
+#include "../../MyVersionInfo.rc"
+
+MY_VERSION_INFO_DLL("Z Plugin", "z")
+
+101 ICON "Z.ico"
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
diff --git a/CPP/7zip/Archive/makefile b/CPP/7zip/Archive/makefile
new file mode 100755
index 00000000..7512ad56
--- /dev/null
+++ b/CPP/7zip/Archive/makefile
@@ -0,0 +1,23 @@
+DIRS = \
+ 7z\~ \
+ Arj\~ \
+ BZip2\~ \
+ Cab\~ \
+ Chm\~ \
+ Cpio\~ \
+ Deb\~ \
+ GZip\~ \
+ Iso\~ \
+ Lzh\~ \
+ Nsis\~ \
+ Rar\~ \
+ RPM\~ \
+ Split\~ \
+ Tar\~ \
+ Z\~ \
+ Zip\~ \
+
+all: $(DIRS)
+
+$(DIRS):
+!include "../SubBuild.mak"