diff options
Diffstat (limited to 'CPP/7zip/Archive/SwfHandler.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/Archive/SwfHandler.cpp | 651 |
1 files changed, 468 insertions, 183 deletions
diff --git a/CPP/7zip/Archive/SwfHandler.cpp b/CPP/7zip/Archive/SwfHandler.cpp index d7d9537e..7cfea330 100755..100644 --- a/CPP/7zip/Archive/SwfHandler.cpp +++ b/CPP/7zip/Archive/SwfHandler.cpp @@ -4,19 +4,23 @@ #include "../../../C/CpuArch.h" -#include "Common/Buffer.h" -#include "Common/ComTry.h" -#include "Common/IntToString.h" -#include "Common/MyString.h" +#include "../../Common/ComTry.h" +#include "../../Common/IntToString.h" +#include "../../Common/MyBuffer.h" +#include "../../Common/MyString.h" -#include "Windows/PropVariant.h" +#include "../../Windows/PropVariant.h" #include "../Common/InBuffer.h" +#include "../Common/LimitedStreams.h" #include "../Common/ProgressUtils.h" #include "../Common/RegisterArc.h" +#include "../Common/StreamObjects.h" #include "../Common/StreamUtils.h" #include "../Compress/CopyCoder.h" +#include "../Compress/LzmaDecoder.h" +#include "../Compress/LzmaEncoder.h" #include "../Compress/ZlibDecoder.h" #include "../Compress/ZlibEncoder.h" @@ -26,33 +30,120 @@ using namespace NWindows; namespace NArchive { + +static const UInt32 kFileSizeMax = (UInt32)1 << 29; + namespace NSwfc { -static const UInt32 kHeaderSize = 8; +static const unsigned kHeaderBaseSize = 8; +static const unsigned kHeaderLzmaSize = 17; static const Byte SWF_UNCOMPRESSED = 'F'; -static const Byte SWF_COMPRESSED = 'C'; -static const Byte SWF_MIN_COMPRESSED_VER = 6; +static const Byte SWF_COMPRESSED_ZLIB = 'C'; +static const Byte SWF_COMPRESSED_LZMA = 'Z'; + +static const Byte SWF_MIN_COMPRESSED_ZLIB_VER = 6; +static const Byte SWF_MIN_COMPRESSED_LZMA_VER = 13; + +static const Byte kVerLim = 20; + +API_FUNC_static_IsArc IsArc_Swf(const Byte *p, size_t size) +{ + if (size < kHeaderBaseSize) + return k_IsArc_Res_NEED_MORE; + if (p[0] != SWF_UNCOMPRESSED || + p[1] != 'W' || + p[2] != 'S' || + p[3] >= kVerLim) + return k_IsArc_Res_NO; + UInt32 uncompressedSize = GetUi32(p + 4); + if (uncompressedSize > kFileSizeMax) + return k_IsArc_Res_NO; + return k_IsArc_Res_YES; +} + +API_FUNC_static_IsArc IsArc_Swfc(const Byte *p, size_t size) +{ + if (size < kHeaderBaseSize + 2 + 1) // 2 + 1 (for zlib check) + return k_IsArc_Res_NEED_MORE; + if ((p[0] != SWF_COMPRESSED_ZLIB && + p[0] != SWF_COMPRESSED_LZMA) || + p[1] != 'W' || + p[2] != 'S' || + p[3] >= kVerLim) + return k_IsArc_Res_NO; + UInt32 uncompressedSize = GetUi32(p + 4); + if (uncompressedSize > kFileSizeMax) + return k_IsArc_Res_NO; + + if (p[0] == SWF_COMPRESSED_ZLIB) + { + if (!NCompress::NZlib::IsZlib_3bytes(p + 8)) + return k_IsArc_Res_NO; + } + else + { + if (size < kHeaderLzmaSize + 2) + return k_IsArc_Res_NEED_MORE; + if (p[kHeaderLzmaSize] != 0 || + (p[kHeaderLzmaSize + 1] & 0x80) != 0) + return k_IsArc_Res_NO; + UInt32 lzmaPackSize = GetUi32(p + 8); + UInt32 lzmaProp = p[12]; + UInt32 lzmaDicSize = GetUi32(p + 13); + if (lzmaProp > 5 * 5 * 9 || + lzmaDicSize > ((UInt32)1 << 28) || + lzmaPackSize < 5 || + lzmaPackSize > ((UInt32)1 << 28)) + return k_IsArc_Res_NO; + } + + return k_IsArc_Res_YES; +} struct CItem { - Byte Buf[kHeaderSize]; + Byte Buf[kHeaderLzmaSize]; + unsigned HeaderSize; UInt32 GetSize() const { return GetUi32(Buf + 4); } - bool IsSwf(Byte c) const { return (Buf[0] == c && Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < 32); } - bool IsUncompressed() const { return IsSwf(SWF_UNCOMPRESSED); } - bool IsCompressed() const { return IsSwf(SWF_COMPRESSED); } + UInt32 GetLzmaPackSize() const { return GetUi32(Buf + 8); } + UInt32 GetLzmaDicSize() const { return GetUi32(Buf + 13); } - void MakeUncompressed() { Buf[0] = SWF_UNCOMPRESSED; } - void MakeCompressed() + bool IsSwf() const { return (Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < kVerLim); } + bool IsUncompressed() const { return Buf[0] == SWF_UNCOMPRESSED; } + bool IsZlib() const { return Buf[0] == SWF_COMPRESSED_ZLIB; } + bool IsLzma() const { return Buf[0] == SWF_COMPRESSED_LZMA; } + + void MakeUncompressed() + { + Buf[0] = SWF_UNCOMPRESSED; + HeaderSize = kHeaderBaseSize; + } + void MakeZlib() + { + Buf[0] = SWF_COMPRESSED_ZLIB; + if (Buf[3] < SWF_MIN_COMPRESSED_ZLIB_VER) + Buf[3] = SWF_MIN_COMPRESSED_ZLIB_VER; + } + void MakeLzma(UInt32 packSize) { - Buf[0] = SWF_COMPRESSED; - if (Buf[3] < SWF_MIN_COMPRESSED_VER) - Buf[3] = SWF_MIN_COMPRESSED_VER; + Buf[0] = SWF_COMPRESSED_LZMA; + if (Buf[3] < SWF_MIN_COMPRESSED_LZMA_VER) + Buf[3] = SWF_MIN_COMPRESSED_LZMA_VER; + SetUi32(Buf + 8, packSize); + HeaderSize = kHeaderLzmaSize; } - HRESULT ReadHeader(ISequentialInStream *stream) { return ReadStream_FALSE(stream, Buf, kHeaderSize); } - HRESULT WriteHeader(ISequentialOutStream *stream) { return WriteStream(stream, Buf, kHeaderSize); } + HRESULT ReadHeader(ISequentialInStream *stream) + { + HeaderSize = kHeaderBaseSize; + return ReadStream_FALSE(stream, Buf, kHeaderBaseSize); + } + HRESULT WriteHeader(ISequentialOutStream *stream) + { + return WriteStream(stream, Buf, HeaderSize); + } }; class CHandler: @@ -69,19 +160,22 @@ class CHandler: CMyComPtr<IInStream> _stream; CSingleMethodProps _props; + bool _lzmaMode; public: + CHandler(): _lzmaMode(false) {} MY_UNKNOWN_IMP4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties) INTERFACE_IInArchive(;) INTERFACE_IOutArchive(;) STDMETHOD(OpenSeq)(ISequentialInStream *stream); - STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, Int32 numProps); + STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidSize, VT_UI8}, - { NULL, kpidPackSize, VT_UI8} + kpidSize, + kpidPackSize, + kpidMethod }; IMP_IInArchive_Props @@ -90,9 +184,10 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: if (_packSizeDefined) prop = _packSize; break; + case kpidPhySize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break; + case kpidIsNotArcType: prop = true; break; } prop.Detach(value); return S_OK; @@ -104,13 +199,48 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) return S_OK; } +static void DicSizeToString(char *s, UInt32 val) +{ + char c = 0; + unsigned i; + for (i = 0; i <= 31; i++) + if (((UInt32)1 << i) == val) + { + val = i; + break; + } + if (i == 32) + { + c = 'b'; + if ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; } + else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; } + } + ::ConvertUInt32ToString(val, s); + int pos = MyStringLen(s); + s[pos++] = c; + s[pos] = 0; +} + STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; - switch(propID) + switch (propID) { case kpidSize: prop = (UInt64)_item.GetSize(); break; - case kpidPackSize: if (_packSizeDefined) prop = _packSize; break; + case kpidPackSize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break; + case kpidMethod: + { + char s[32]; + if (_item.IsZlib()) + MyStringCopy(s, "zlib"); + else + { + MyStringCopy(s, "LZMA:"); + DicSizeToString(s + 5, _item.GetLzmaDicSize()); + } + prop = s; + break; + } } prop.Detach(value); return S_OK; @@ -126,30 +256,63 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) { Close(); - HRESULT res = _item.ReadHeader(stream); - if (res == S_OK) - if (_item.IsCompressed()) - _seqStream = stream; - else - res = S_FALSE; - return res; + RINOK(_item.ReadHeader(stream)); + if (!_item.IsSwf()) + return S_FALSE; + if (_item.IsLzma()) + { + RINOK(ReadStream_FALSE(stream, _item.Buf + kHeaderBaseSize, kHeaderLzmaSize - kHeaderBaseSize)); + _item.HeaderSize = kHeaderLzmaSize; + _packSize = _item.GetLzmaPackSize(); + _packSizeDefined = true; + } + else if (!_item.IsZlib()) + return S_FALSE; + if (_item.GetSize() < _item.HeaderSize) + return S_FALSE; + _seqStream = stream; + return S_OK; } STDMETHODIMP CHandler::Close() { + _packSize = 0; _packSizeDefined = false; _seqStream.Release(); _stream.Release(); return S_OK; } +class CCompressProgressInfoImp: + public ICompressProgressInfo, + public CMyUnknownImp +{ + CMyComPtr<IArchiveOpenCallback> Callback; +public: + UInt64 Offset; + MY_UNKNOWN_IMP1(ICompressProgressInfo) + STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize); + void Init(IArchiveOpenCallback *callback) { Callback = callback; } +}; + +STDMETHODIMP CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + if (Callback) + { + UInt64 files = 0; + UInt64 value = Offset + *inSize; + return Callback->SetCompleted(&files, &value); + } + return S_OK; +} + STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN if (numItems == 0) return S_OK; - if (numItems != (UInt32)-1 && (numItems != 1 || indices[0] != 0)) + if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0)) return E_INVALIDARG; extractCallback->SetTotal(_item.GetSize()); @@ -163,9 +326,6 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, extractCallback->PrepareOperation(askMode); - NCompress::NZlib::CDecoder *_decoderSpec = new NCompress::NZlib::CDecoder; - CMyComPtr<ICompressCoder> _decoder = _decoderSpec; - CDummyOutStream *outStreamSpec = new CDummyOutStream; CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); outStreamSpec->SetStream(realOutStream); @@ -176,24 +336,73 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(extractCallback, false); - lps->InSize = kHeaderSize; + lps->InSize = _item.HeaderSize; lps->OutSize = outStreamSpec->GetSize(); RINOK(lps->SetCur()); CItem item = _item; item.MakeUncompressed(); - RINOK(item.WriteHeader(outStream)); if (_stream) - RINOK(_stream->Seek(kHeaderSize, STREAM_SEEK_SET, NULL)); - HRESULT result = _decoderSpec->Code(_seqStream, outStream, NULL, NULL, progress); + RINOK(_stream->Seek(_item.HeaderSize, STREAM_SEEK_SET, NULL)); + NCompress::NZlib::CDecoder *_decoderZlibSpec = NULL; + NCompress::NLzma::CDecoder *_decoderLzmaSpec = NULL; + CMyComPtr<ICompressCoder> _decoder; + + CMyComPtr<ISequentialInStream> inStream2; + + UInt64 unpackSize = _item.GetSize() - (UInt32)8; + if (_item.IsZlib()) + { + _decoderZlibSpec = new NCompress::NZlib::CDecoder; + _decoder = _decoderZlibSpec; + inStream2 = _seqStream; + } + else + { + /* Some .swf files with lzma contain additional 8 bytes at the end + in uncompressed stream. + What does that data mean ??? + We don't decompress these additional 8 bytes */ + + // unpackSize = _item.GetSize(); + // SetUi32(item.Buf + 4, (UInt32)(unpackSize + 8)); + CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream; + inStream2 = limitedStreamSpec; + limitedStreamSpec->SetStream(_seqStream); + limitedStreamSpec->Init(_item.GetLzmaPackSize()); + + _decoderLzmaSpec = new NCompress::NLzma::CDecoder; + _decoder = _decoderLzmaSpec; + // _decoderLzmaSpec->FinishStream = true; + + Byte props[5]; + memcpy(props, _item.Buf + 12, 5); + UInt32 dicSize = _item.GetLzmaDicSize(); + if (dicSize > (UInt32)unpackSize) + { + dicSize = (UInt32)unpackSize; + SetUi32(props + 1, dicSize); + } + RINOK(_decoderLzmaSpec->SetDecoderProperties2(props, 5)); + } + RINOK(item.WriteHeader(outStream)); + HRESULT result = _decoder->Code(inStream2, outStream, NULL, &unpackSize, progress); Int32 opRes = NExtract::NOperationResult::kDataError; if (result == S_OK) { - if (_item.GetSize() == outStreamSpec->GetSize()) + if (item.GetSize() == outStreamSpec->GetSize()) { - _packSizeDefined = true; - _packSize = _decoderSpec->GetInputProcessedSize() + kHeaderSize; - opRes = NExtract::NOperationResult::kOK; + if (_item.IsZlib()) + { + _packSizeDefined = true; + _packSize = _decoderZlibSpec->GetInputProcessedSize(); + opRes = NExtract::NOperationResult::kOK; + } + else + { + // if (_decoderLzmaSpec->GetInputProcessedSize() == _packSize) + opRes = NExtract::NOperationResult::kOK; + } } } else if (result != S_FALSE) @@ -204,8 +413,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static HRESULT UpdateArchive(ISequentialOutStream *outStream, - UInt64 size, const CSingleMethodProps &props, +static HRESULT UpdateArchive(ISequentialOutStream *outStream, UInt64 size, + bool lzmaMode, const CSingleMethodProps &props, IArchiveUpdateCallback *updateCallback) { UInt64 complexity = 0; @@ -215,27 +424,73 @@ static HRESULT UpdateArchive(ISequentialOutStream *outStream, CMyComPtr<ISequentialInStream> fileInStream; RINOK(updateCallback->GetStream(0, &fileInStream)); + /* + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + realOutStream.Release(); + */ + CItem item; HRESULT res = item.ReadHeader(fileInStream); if (res == S_FALSE) return E_INVALIDARG; RINOK(res); - if (!item.IsUncompressed() || size != item.GetSize()) + if (!item.IsSwf() || !item.IsUncompressed() || size != item.GetSize()) return E_INVALIDARG; - item.MakeCompressed(); - item.WriteHeader(outStream); + NCompress::NZlib::CEncoder *encoderZlibSpec = NULL; + NCompress::NLzma::CEncoder *encoderLzmaSpec = NULL; + CMyComPtr<ICompressCoder> encoder; + CMyComPtr<IOutStream> outSeekStream; + if (lzmaMode) + { + outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream); + if (!outSeekStream) + return E_NOTIMPL; + encoderLzmaSpec = new NCompress::NLzma::CEncoder; + encoder = encoderLzmaSpec; + RINOK(props.SetCoderProps(encoderLzmaSpec, &size)); + item.MakeLzma((UInt32)0xFFFFFFFF); + CBufPtrSeqOutStream *propStreamSpec = new CBufPtrSeqOutStream; + CMyComPtr<ISequentialOutStream> propStream = propStreamSpec; + propStreamSpec->Init(item.Buf + 12, 5); + RINOK(encoderLzmaSpec->WriteCoderProperties(propStream)); + } + else + { + encoderZlibSpec = new NCompress::NZlib::CEncoder; + encoder = encoderZlibSpec; + encoderZlibSpec->Create(); + RINOK(props.SetCoderProps(encoderZlibSpec->DeflateEncoderSpec, NULL)); + item.MakeZlib(); + } + RINOK(item.WriteHeader(outStream)); CLocalProgress *lps = new CLocalProgress; CMyComPtr<ICompressProgressInfo> progress = lps; lps->Init(updateCallback, true); - NCompress::NZlib::CEncoder *encoderSpec = new NCompress::NZlib::CEncoder; - CMyComPtr<ICompressCoder> encoder = encoderSpec; - encoderSpec->Create(); - RINOK(props.SetCoderProps(encoderSpec->DeflateEncoderSpec, NULL)); RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, progress)); - if (encoderSpec->GetInputProcessedSize() + kHeaderSize != size) + UInt64 inputProcessed; + if (lzmaMode) + { + UInt64 curPos = 0; + RINOK(outSeekStream->Seek(0, STREAM_SEEK_CUR, &curPos)); + UInt64 packSize = curPos - kHeaderLzmaSize; + if (packSize > (UInt32)0xFFFFFFFF) + return E_INVALIDARG; + item.MakeLzma((UInt32)packSize); + RINOK(outSeekStream->Seek(0, STREAM_SEEK_SET, NULL)); + item.WriteHeader(outStream); + inputProcessed = encoderLzmaSpec->GetInputProcessedSize(); + } + else + { + inputProcessed = encoderZlibSpec->GetInputProcessedSize(); + } + if (inputProcessed + kHeaderBaseSize != size) return E_INVALIDARG; return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK); } @@ -283,7 +538,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return E_INVALIDARG; size = prop.uhVal.QuadPart; } - return UpdateArchive(outStream, size, _props, updateCallback); + return UpdateArchive(outStream, size, _lzmaMode, _props, updateCallback); } if (indexInArchive != 0) @@ -301,20 +556,37 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numIt return NCompress::CopyStream(_seqStream, outStream, NULL); } -STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProps) +STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) { - return _props.SetProperties(names, values, numProps); + _lzmaMode = false; + RINOK(_props.SetProperties(names, values, numProps)); + UString m = _props.MethodName; + m.MakeLower_Ascii(); + if (m.IsEqualTo("lzma")) + { + return E_NOTIMPL; + // _lzmaMode = true; + } + else if (m.IsEqualTo("deflate") || m.IsEmpty()) + _lzmaMode = false; + else + return E_INVALIDARG; + return S_OK; } -static IInArchive *CreateArc() { return new CHandler; } -#ifndef EXTRACT_ONLY -static IOutArchive *CreateArcOut() { return new CHandler; } -#else -#define CreateArcOut 0 -#endif +IMP_CreateArcIn +IMP_CreateArcOut static CArcInfo g_ArcInfo = - { L"SWFc", L"swf", L"~.swf", 0xD8, { 'C', 'W', 'S' }, 3, true, CreateArc, CreateArcOut }; + { "SWFc", "swf", "~.swf", 0xD8, + 2 + 3 + 3, + { + 3, 'C', 'W', 'S', + 3, 'Z', 'W', 'S', + }, + 0, + NArcInfoFlags::kMultiSignature, + REF_CreateArc_Pair, IsArc_Swfc }; REGISTER_ARC(Swfc) @@ -322,8 +594,7 @@ REGISTER_ARC(Swfc) namespace NSwf { -static const UInt32 kFileSizeMax = (UInt32)1 << 30; -static const int kNumTagsMax = (UInt32)1 << 23; +static const unsigned kNumTagsMax = 1 << 23; struct CTag { @@ -338,7 +609,7 @@ class CHandler: { CObjectVector<CTag> _tags; NSwfc::CItem _item; - UInt64 _packSize; + UInt64 _phySize; HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback); HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback); @@ -349,11 +620,11 @@ public: STDMETHOD(OpenSeq)(ISequentialInStream *stream); }; -STATPROPSTG kProps[] = +static const Byte kProps[] = { - { NULL, kpidPath, VT_BSTR}, - { NULL, kpidSize, VT_UI8}, - { NULL, kpidComment, VT_BSTR} + kpidPath, + kpidSize, + kpidComment, }; IMP_IInArchive_Props @@ -362,9 +633,10 @@ IMP_IInArchive_ArcProps_NO_Table STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) { NCOM::CPropVariant prop; - switch(propID) + switch (propID) { - case kpidPhySize: prop = _packSize; break; + case kpidPhySize: prop = _phySize; break; + case kpidIsNotArcType: prop = true; break; } prop.Detach(value); return S_OK; @@ -379,105 +651,105 @@ STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) static const char *g_TagDesc[92] = { - "End", - "ShowFrame", - "DefineShape", - NULL, - "PlaceObject", - "RemoveObject", - "DefineBits", - "DefineButton", - "JPEGTables", - "SetBackgroundColor", - "DefineFont", - "DefineText", - "DoAction", - "DefineFontInfo", - "DefineSound", - "StartSound", - NULL, - "DefineButtonSound", - "SoundStreamHead", - "SoundStreamBlock", - "DefineBitsLossless", - "DefineBitsJPEG2", - "DefineShape2", - "DefineButtonCxform", - "Protect", - NULL, - "PlaceObject2", - NULL, - "RemoveObject2", - NULL, - NULL, - NULL, - "DefineShape3", - "DefineText2", - "DefineButton2", - "DefineBitsJPEG3", - "DefineBitsLossless2", - "DefineEditText", - NULL, - "DefineSprite", - NULL, - "41", - NULL, - "FrameLabel", - NULL, - "SoundStreamHead2", - "DefineMorphShape", - NULL, - "DefineFont2", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "ExportAssets", - "ImportAssets", - "EnableDebugger", - "DoInitAction", - "DefineVideoStream", - "VideoFrame", - "DefineFontInfo2", - NULL, - "EnableDebugger2", - "ScriptLimits", - "SetTabIndex", - NULL, - NULL, - "FileAttributes", - "PlaceObject3", - "ImportAssets2", - NULL, - "DefineFontAlignZones", - "CSMTextSettings", - "DefineFont3", - "SymbolClass", - "Metadata", - "DefineScalingGrid", - NULL, - NULL, - NULL, - "DoABC", - "DefineShape4", - "DefineMorphShape2", - NULL, - "DefineSceneAndFrameLabelData", - "DefineBinaryData", - "DefineFontName", - "StartSound2", - "DefineBitsJPEG4", - "DefineFont4" + "End" + , "ShowFrame" + , "DefineShape" + , NULL + , "PlaceObject" + , "RemoveObject" + , "DefineBits" + , "DefineButton" + , "JPEGTables" + , "SetBackgroundColor" + , "DefineFont" + , "DefineText" + , "DoAction" + , "DefineFontInfo" + , "DefineSound" + , "StartSound" + , NULL + , "DefineButtonSound" + , "SoundStreamHead" + , "SoundStreamBlock" + , "DefineBitsLossless" + , "DefineBitsJPEG2" + , "DefineShape2" + , "DefineButtonCxform" + , "Protect" + , NULL + , "PlaceObject2" + , NULL + , "RemoveObject2" + , NULL + , NULL + , NULL + , "DefineShape3" + , "DefineText2" + , "DefineButton2" + , "DefineBitsJPEG3" + , "DefineBitsLossless2" + , "DefineEditText" + , NULL + , "DefineSprite" + , NULL + , "41" + , NULL + , "FrameLabel" + , NULL + , "SoundStreamHead2" + , "DefineMorphShape" + , NULL + , "DefineFont2" + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , NULL + , "ExportAssets" + , "ImportAssets" + , "EnableDebugger" + , "DoInitAction" + , "DefineVideoStream" + , "VideoFrame" + , "DefineFontInfo2" + , NULL + , "EnableDebugger2" + , "ScriptLimits" + , "SetTabIndex" + , NULL + , NULL + , "FileAttributes" + , "PlaceObject3" + , "ImportAssets2" + , NULL + , "DefineFontAlignZones" + , "CSMTextSettings" + , "DefineFont3" + , "SymbolClass" + , "Metadata" + , "DefineScalingGrid" + , NULL + , NULL + , NULL + , "DoABC" + , "DefineShape4" + , "DefineMorphShape2" + , NULL + , "DefineSceneAndFrameLabelData" + , "DefineBinaryData" + , "DefineFontName" + , "StartSound2" + , "DefineBitsJPEG4" + , "DefineFont4" }; STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { NWindows::NCOM::CPropVariant prop; const CTag &tag = _tags[index]; - switch(propID) + switch (propID) { case kpidPath: { @@ -491,9 +763,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val } case kpidSize: case kpidPackSize: - prop = (UInt64)tag.Buf.GetCapacity(); break; + prop = (UInt64)tag.Buf.Size(); break; case kpidComment: - if (tag.Type < sizeof(g_TagDesc) / sizeof(g_TagDesc[0])) + if (tag.Type < ARRAY_SIZE(g_TagDesc)) { const char *s = g_TagDesc[tag.Type]; if (s != NULL) @@ -579,8 +851,12 @@ UInt32 CBitReader::ReadBits(unsigned numBits) HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback) { RINOK(_item.ReadHeader(stream)) - if (!_item.IsUncompressed()) + if (!_item.IsSwf() || !_item.IsUncompressed()) + return S_FALSE; + UInt32 uncompressedSize = _item.GetSize(); + if (uncompressedSize > kFileSizeMax) return S_FALSE; + CInBuffer s; if (!s.Create(1 << 20)) @@ -610,13 +886,12 @@ HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *ca length = Read32(s); if (type == 0) break; - UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderSize + length; - if (offset > kFileSizeMax || _tags.Size() >= kNumTagsMax) + UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderBaseSize + length; + if (offset > uncompressedSize || _tags.Size() >= kNumTagsMax) return S_FALSE; - _tags.Add(CTag()); - CTag &tag = _tags.Back(); + CTag &tag = _tags.AddNew(); tag.Type = type; - tag.Buf.SetCapacity(length); + tag.Buf.Alloc(length); if (s.ReadBytes(tag.Buf, length) != length) return S_FALSE; if (callback && offset >= offsetPrev + (1 << 20)) @@ -626,7 +901,12 @@ HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *ca offsetPrev = offset; } } - _packSize = s.GetProcessedSize() + NSwfc::kHeaderSize; + _phySize = s.GetProcessedSize() + NSwfc::kHeaderBaseSize; + if (_phySize != uncompressedSize) + { + // do we need to support files extracted from SFW-LZMA with additional 8 bytes? + return S_FALSE; + } return S_OK; } @@ -645,6 +925,7 @@ STDMETHODIMP CHandler::OpenSeq(ISequentialInStream *stream) STDMETHODIMP CHandler::Close() { + _phySize = 0; return S_OK; } @@ -652,7 +933,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, Int32 testMode, IArchiveExtractCallback *extractCallback) { COM_TRY_BEGIN - bool allFilesMode = (numItems == (UInt32)-1); + bool allFilesMode = (numItems == (UInt32)(Int32)-1); if (allFilesMode) numItems = _tags.Size(); if (numItems == 0) @@ -660,7 +941,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, UInt64 totalSize = 0; UInt32 i; for (i = 0; i < numItems; i++) - totalSize += _tags[allFilesMode ? i : indices[i]].Buf.GetCapacity(); + totalSize += _tags[allFilesMode ? i : indices[i]].Buf.Size(); extractCallback->SetTotal(totalSize); CLocalProgress *lps = new CLocalProgress; @@ -678,7 +959,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, NExtract::NAskMode::kExtract; UInt32 index = allFilesMode ? i : indices[i]; const CByteBuffer &buf = _tags[index].Buf; - totalSize += buf.GetCapacity(); + totalSize += buf.Size(); CMyComPtr<ISequentialOutStream> outStream; RINOK(extractCallback->GetStream(index, &outStream, askMode)); @@ -687,7 +968,7 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, RINOK(extractCallback->PrepareOperation(askMode)); if (outStream) - RINOK(WriteStream(outStream, buf, buf.GetCapacity())); + RINOK(WriteStream(outStream, buf, buf.Size())); outStream.Release(); RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); } @@ -695,10 +976,14 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems, COM_TRY_END } -static IInArchive *CreateArc() { return new CHandler; } +IMP_CreateArcIn static CArcInfo g_ArcInfo = - { L"SWF", L"swf", 0, 0xD7, { 'F', 'W', 'S' }, 3, true, CreateArc, 0 }; + { "SWF", "swf", 0, 0xD7, + 3, { 'F', 'W', 'S' }, + 0, + NArcInfoFlags::kKeepName, + CreateArc, NULL, NSwfc::IsArc_Swf }; REGISTER_ARC(Swf) |