xref: /aosp_15_r20/external/lzma/CPP/7zip/Archive/SwfHandler.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // SwfHandler.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h"
6*f6dc9357SAndroid Build Coastguard Worker 
7*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/IntToString.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyBuffer.h"
10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyString.h"
11*f6dc9357SAndroid Build Coastguard Worker 
12*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h"
13*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariantUtils.h"
14*f6dc9357SAndroid Build Coastguard Worker 
15*f6dc9357SAndroid Build Coastguard Worker #include "../Common/InBuffer.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h"
17*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h"
18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h"
19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h"
20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h"
23*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/LzmaDecoder.h"
24*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/ZlibDecoder.h"
25*f6dc9357SAndroid Build Coastguard Worker 
26*f6dc9357SAndroid Build Coastguard Worker #include "Common/DummyOutStream.h"
27*f6dc9357SAndroid Build Coastguard Worker 
28*f6dc9357SAndroid Build Coastguard Worker // #define Z7_SWF_UPDATE
29*f6dc9357SAndroid Build Coastguard Worker 
30*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_SWF_UPDATE
31*f6dc9357SAndroid Build Coastguard Worker 
32*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/LzmaEncoder.h"
33*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/ZlibEncoder.h"
34*f6dc9357SAndroid Build Coastguard Worker 
35*f6dc9357SAndroid Build Coastguard Worker #include "Common/HandlerOut.h"
36*f6dc9357SAndroid Build Coastguard Worker 
37*f6dc9357SAndroid Build Coastguard Worker #endif
38*f6dc9357SAndroid Build Coastguard Worker 
39*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
40*f6dc9357SAndroid Build Coastguard Worker 
41*f6dc9357SAndroid Build Coastguard Worker namespace NArchive {
42*f6dc9357SAndroid Build Coastguard Worker 
43*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kFileSizeMax = (UInt32)1 << 29;
44*f6dc9357SAndroid Build Coastguard Worker 
45*f6dc9357SAndroid Build Coastguard Worker namespace NSwfc {
46*f6dc9357SAndroid Build Coastguard Worker 
47*f6dc9357SAndroid Build Coastguard Worker static const unsigned kHeaderBaseSize = 8;
48*f6dc9357SAndroid Build Coastguard Worker static const unsigned kHeaderLzmaSize = 17;
49*f6dc9357SAndroid Build Coastguard Worker 
50*f6dc9357SAndroid Build Coastguard Worker static const Byte SWF_UNCOMPRESSED = 'F';
51*f6dc9357SAndroid Build Coastguard Worker static const Byte SWF_COMPRESSED_ZLIB = 'C';
52*f6dc9357SAndroid Build Coastguard Worker static const Byte SWF_COMPRESSED_LZMA = 'Z';
53*f6dc9357SAndroid Build Coastguard Worker 
54*f6dc9357SAndroid Build Coastguard Worker static const Byte SWF_MIN_COMPRESSED_ZLIB_VER = 6;
55*f6dc9357SAndroid Build Coastguard Worker static const Byte SWF_MIN_COMPRESSED_LZMA_VER = 13;
56*f6dc9357SAndroid Build Coastguard Worker 
57*f6dc9357SAndroid Build Coastguard Worker static const Byte kVerLim = 64;
58*f6dc9357SAndroid Build Coastguard Worker 
IsArc_Swf(const Byte * p,size_t size)59*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Swf(const Byte *p, size_t size)
60*f6dc9357SAndroid Build Coastguard Worker {
61*f6dc9357SAndroid Build Coastguard Worker   if (size < kHeaderBaseSize)
62*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NEED_MORE;
63*f6dc9357SAndroid Build Coastguard Worker   if (p[0] != SWF_UNCOMPRESSED ||
64*f6dc9357SAndroid Build Coastguard Worker       p[1] != 'W' ||
65*f6dc9357SAndroid Build Coastguard Worker       p[2] != 'S' ||
66*f6dc9357SAndroid Build Coastguard Worker       p[3] >= kVerLim)
67*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NO;
68*f6dc9357SAndroid Build Coastguard Worker   UInt32 uncompressedSize = GetUi32(p + 4);
69*f6dc9357SAndroid Build Coastguard Worker   if (uncompressedSize > kFileSizeMax)
70*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NO;
71*f6dc9357SAndroid Build Coastguard Worker   return k_IsArc_Res_YES;
72*f6dc9357SAndroid Build Coastguard Worker }
73*f6dc9357SAndroid Build Coastguard Worker }
74*f6dc9357SAndroid Build Coastguard Worker 
IsArc_Swfc(const Byte * p,size_t size)75*f6dc9357SAndroid Build Coastguard Worker API_FUNC_static_IsArc IsArc_Swfc(const Byte *p, size_t size)
76*f6dc9357SAndroid Build Coastguard Worker {
77*f6dc9357SAndroid Build Coastguard Worker   if (size < kHeaderBaseSize + 2 + 1) // 2 + 1 (for zlib check)
78*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NEED_MORE;
79*f6dc9357SAndroid Build Coastguard Worker   if ((p[0] != SWF_COMPRESSED_ZLIB &&
80*f6dc9357SAndroid Build Coastguard Worker       p[0] != SWF_COMPRESSED_LZMA) ||
81*f6dc9357SAndroid Build Coastguard Worker       p[1] != 'W' ||
82*f6dc9357SAndroid Build Coastguard Worker       p[2] != 'S' ||
83*f6dc9357SAndroid Build Coastguard Worker       p[3] >= kVerLim)
84*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NO;
85*f6dc9357SAndroid Build Coastguard Worker   UInt32 uncompressedSize = GetUi32(p + 4);
86*f6dc9357SAndroid Build Coastguard Worker   if (uncompressedSize > kFileSizeMax)
87*f6dc9357SAndroid Build Coastguard Worker     return k_IsArc_Res_NO;
88*f6dc9357SAndroid Build Coastguard Worker 
89*f6dc9357SAndroid Build Coastguard Worker   if (p[0] == SWF_COMPRESSED_ZLIB)
90*f6dc9357SAndroid Build Coastguard Worker   {
91*f6dc9357SAndroid Build Coastguard Worker     if (!NCompress::NZlib::IsZlib_3bytes(p + 8))
92*f6dc9357SAndroid Build Coastguard Worker       return k_IsArc_Res_NO;
93*f6dc9357SAndroid Build Coastguard Worker   }
94*f6dc9357SAndroid Build Coastguard Worker   else
95*f6dc9357SAndroid Build Coastguard Worker   {
96*f6dc9357SAndroid Build Coastguard Worker     if (size < kHeaderLzmaSize + 2)
97*f6dc9357SAndroid Build Coastguard Worker       return k_IsArc_Res_NEED_MORE;
98*f6dc9357SAndroid Build Coastguard Worker     if (p[kHeaderLzmaSize] != 0 ||
99*f6dc9357SAndroid Build Coastguard Worker         (p[kHeaderLzmaSize + 1] & 0x80) != 0)
100*f6dc9357SAndroid Build Coastguard Worker       return k_IsArc_Res_NO;
101*f6dc9357SAndroid Build Coastguard Worker     UInt32 lzmaPackSize = GetUi32(p + 8);
102*f6dc9357SAndroid Build Coastguard Worker     UInt32 lzmaProp = p[12];
103*f6dc9357SAndroid Build Coastguard Worker     UInt32 lzmaDicSize = GetUi32(p + 13);
104*f6dc9357SAndroid Build Coastguard Worker     if (lzmaProp > 5 * 5 * 9 ||
105*f6dc9357SAndroid Build Coastguard Worker         lzmaDicSize > ((UInt32)1 << 28) ||
106*f6dc9357SAndroid Build Coastguard Worker         lzmaPackSize < 5 ||
107*f6dc9357SAndroid Build Coastguard Worker         lzmaPackSize > ((UInt32)1 << 28))
108*f6dc9357SAndroid Build Coastguard Worker       return k_IsArc_Res_NO;
109*f6dc9357SAndroid Build Coastguard Worker   }
110*f6dc9357SAndroid Build Coastguard Worker 
111*f6dc9357SAndroid Build Coastguard Worker   return k_IsArc_Res_YES;
112*f6dc9357SAndroid Build Coastguard Worker }
113*f6dc9357SAndroid Build Coastguard Worker }
114*f6dc9357SAndroid Build Coastguard Worker 
115*f6dc9357SAndroid Build Coastguard Worker struct CItem
116*f6dc9357SAndroid Build Coastguard Worker {
117*f6dc9357SAndroid Build Coastguard Worker   Byte Buf[kHeaderLzmaSize];
118*f6dc9357SAndroid Build Coastguard Worker   unsigned HeaderSize;
119*f6dc9357SAndroid Build Coastguard Worker 
GetSizeCItem120*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetSize() const { return GetUi32(Buf + 4); }
GetLzmaPackSizeCItem121*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetLzmaPackSize() const { return GetUi32(Buf + 8); }
GetLzmaDicSizeCItem122*f6dc9357SAndroid Build Coastguard Worker   UInt32 GetLzmaDicSize() const { return GetUi32(Buf + 13); }
123*f6dc9357SAndroid Build Coastguard Worker 
IsSwfCItem124*f6dc9357SAndroid Build Coastguard Worker   bool IsSwf() const { return (Buf[1] == 'W' && Buf[2] == 'S' && Buf[3] < kVerLim); }
IsUncompressedCItem125*f6dc9357SAndroid Build Coastguard Worker   bool IsUncompressed() const { return Buf[0] == SWF_UNCOMPRESSED; }
IsZlibCItem126*f6dc9357SAndroid Build Coastguard Worker   bool IsZlib() const { return Buf[0] == SWF_COMPRESSED_ZLIB; }
IsLzmaCItem127*f6dc9357SAndroid Build Coastguard Worker   bool IsLzma() const { return Buf[0] == SWF_COMPRESSED_LZMA; }
128*f6dc9357SAndroid Build Coastguard Worker 
MakeUncompressedCItem129*f6dc9357SAndroid Build Coastguard Worker   void MakeUncompressed()
130*f6dc9357SAndroid Build Coastguard Worker   {
131*f6dc9357SAndroid Build Coastguard Worker     Buf[0] = SWF_UNCOMPRESSED;
132*f6dc9357SAndroid Build Coastguard Worker     HeaderSize = kHeaderBaseSize;
133*f6dc9357SAndroid Build Coastguard Worker   }
MakeZlibCItem134*f6dc9357SAndroid Build Coastguard Worker   void MakeZlib()
135*f6dc9357SAndroid Build Coastguard Worker   {
136*f6dc9357SAndroid Build Coastguard Worker     Buf[0] = SWF_COMPRESSED_ZLIB;
137*f6dc9357SAndroid Build Coastguard Worker     if (Buf[3] < SWF_MIN_COMPRESSED_ZLIB_VER)
138*f6dc9357SAndroid Build Coastguard Worker       Buf[3] = SWF_MIN_COMPRESSED_ZLIB_VER;
139*f6dc9357SAndroid Build Coastguard Worker   }
MakeLzmaCItem140*f6dc9357SAndroid Build Coastguard Worker   void MakeLzma(UInt32 packSize)
141*f6dc9357SAndroid Build Coastguard Worker   {
142*f6dc9357SAndroid Build Coastguard Worker     Buf[0] = SWF_COMPRESSED_LZMA;
143*f6dc9357SAndroid Build Coastguard Worker     if (Buf[3] < SWF_MIN_COMPRESSED_LZMA_VER)
144*f6dc9357SAndroid Build Coastguard Worker       Buf[3] = SWF_MIN_COMPRESSED_LZMA_VER;
145*f6dc9357SAndroid Build Coastguard Worker     SetUi32(Buf + 8, packSize)
146*f6dc9357SAndroid Build Coastguard Worker     HeaderSize = kHeaderLzmaSize;
147*f6dc9357SAndroid Build Coastguard Worker   }
148*f6dc9357SAndroid Build Coastguard Worker 
ReadHeaderCItem149*f6dc9357SAndroid Build Coastguard Worker   HRESULT ReadHeader(ISequentialInStream *stream)
150*f6dc9357SAndroid Build Coastguard Worker   {
151*f6dc9357SAndroid Build Coastguard Worker     HeaderSize = kHeaderBaseSize;
152*f6dc9357SAndroid Build Coastguard Worker     return ReadStream_FALSE(stream, Buf, kHeaderBaseSize);
153*f6dc9357SAndroid Build Coastguard Worker   }
WriteHeaderCItem154*f6dc9357SAndroid Build Coastguard Worker   HRESULT WriteHeader(ISequentialOutStream *stream)
155*f6dc9357SAndroid Build Coastguard Worker   {
156*f6dc9357SAndroid Build Coastguard Worker     return WriteStream(stream, Buf, HeaderSize);
157*f6dc9357SAndroid Build Coastguard Worker   }
158*f6dc9357SAndroid Build Coastguard Worker };
159*f6dc9357SAndroid Build Coastguard Worker 
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker Z7_class_CHandler_final:
162*f6dc9357SAndroid Build Coastguard Worker   public IInArchive,
163*f6dc9357SAndroid Build Coastguard Worker   public IArchiveOpenSeq,
164*f6dc9357SAndroid Build Coastguard Worker  #ifdef Z7_SWF_UPDATE
165*f6dc9357SAndroid Build Coastguard Worker   public IOutArchive,
166*f6dc9357SAndroid Build Coastguard Worker   public ISetProperties,
167*f6dc9357SAndroid Build Coastguard Worker  #endif
168*f6dc9357SAndroid Build Coastguard Worker   public CMyUnknownImp
169*f6dc9357SAndroid Build Coastguard Worker {
170*f6dc9357SAndroid Build Coastguard Worker  #ifdef Z7_SWF_UPDATE
171*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACES_IMP_UNK_4(IInArchive, IArchiveOpenSeq, IOutArchive, ISetProperties)
172*f6dc9357SAndroid Build Coastguard Worker  #else
173*f6dc9357SAndroid Build Coastguard Worker   Z7_IFACES_IMP_UNK_2(IInArchive, IArchiveOpenSeq)
174*f6dc9357SAndroid Build Coastguard Worker  #endif
175*f6dc9357SAndroid Build Coastguard Worker 
176*f6dc9357SAndroid Build Coastguard Worker   CItem _item;
177*f6dc9357SAndroid Build Coastguard Worker   UInt64 _packSize;
178*f6dc9357SAndroid Build Coastguard Worker   bool _packSizeDefined;
179*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> _seqStream;
180*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IInStream> _stream;
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_SWF_UPDATE
183*f6dc9357SAndroid Build Coastguard Worker   CSingleMethodProps _props;
184*f6dc9357SAndroid Build Coastguard Worker   bool _lzmaMode;
185*f6dc9357SAndroid Build Coastguard Worker #endif
186*f6dc9357SAndroid Build Coastguard Worker 
187*f6dc9357SAndroid Build Coastguard Worker public:
188*f6dc9357SAndroid Build Coastguard Worker  #ifdef Z7_SWF_UPDATE
189*f6dc9357SAndroid Build Coastguard Worker   CHandler(): _lzmaMode(false) {}
190*f6dc9357SAndroid Build Coastguard Worker  #endif
191*f6dc9357SAndroid Build Coastguard Worker };
192*f6dc9357SAndroid Build Coastguard Worker 
193*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
194*f6dc9357SAndroid Build Coastguard Worker {
195*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
196*f6dc9357SAndroid Build Coastguard Worker   kpidPackSize,
197*f6dc9357SAndroid Build Coastguard Worker   kpidMethod
198*f6dc9357SAndroid Build Coastguard Worker };
199*f6dc9357SAndroid Build Coastguard Worker 
200*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
201*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_NO_Table
202*f6dc9357SAndroid Build Coastguard Worker 
203*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
204*f6dc9357SAndroid Build Coastguard Worker {
205*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
206*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
207*f6dc9357SAndroid Build Coastguard Worker   {
208*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break;
209*f6dc9357SAndroid Build Coastguard Worker     case kpidIsNotArcType: prop = true; break;
210*f6dc9357SAndroid Build Coastguard Worker   }
211*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
212*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
213*f6dc9357SAndroid Build Coastguard Worker }
214*f6dc9357SAndroid Build Coastguard Worker 
215*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
216*f6dc9357SAndroid Build Coastguard Worker {
217*f6dc9357SAndroid Build Coastguard Worker   *numItems = 1;
218*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
219*f6dc9357SAndroid Build Coastguard Worker }
220*f6dc9357SAndroid Build Coastguard Worker 
221*f6dc9357SAndroid Build Coastguard Worker static void DicSizeToString(char *s, UInt32 val)
222*f6dc9357SAndroid Build Coastguard Worker {
223*f6dc9357SAndroid Build Coastguard Worker   char c = 0;
224*f6dc9357SAndroid Build Coastguard Worker   unsigned i;
225*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < 32; i++)
226*f6dc9357SAndroid Build Coastguard Worker     if (((UInt32)1 << i) == val)
227*f6dc9357SAndroid Build Coastguard Worker     {
228*f6dc9357SAndroid Build Coastguard Worker       val = i;
229*f6dc9357SAndroid Build Coastguard Worker       break;
230*f6dc9357SAndroid Build Coastguard Worker     }
231*f6dc9357SAndroid Build Coastguard Worker   if (i == 32)
232*f6dc9357SAndroid Build Coastguard Worker   {
233*f6dc9357SAndroid Build Coastguard Worker     c = 'b';
234*f6dc9357SAndroid Build Coastguard Worker     if      ((val & ((1 << 20) - 1)) == 0) { val >>= 20; c = 'm'; }
235*f6dc9357SAndroid Build Coastguard Worker     else if ((val & ((1 << 10) - 1)) == 0) { val >>= 10; c = 'k'; }
236*f6dc9357SAndroid Build Coastguard Worker   }
237*f6dc9357SAndroid Build Coastguard Worker   ::ConvertUInt32ToString(val, s);
238*f6dc9357SAndroid Build Coastguard Worker   unsigned pos = MyStringLen(s);
239*f6dc9357SAndroid Build Coastguard Worker   s[pos++] = c;
240*f6dc9357SAndroid Build Coastguard Worker   s[pos] = 0;
241*f6dc9357SAndroid Build Coastguard Worker }
242*f6dc9357SAndroid Build Coastguard Worker 
243*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value))
244*f6dc9357SAndroid Build Coastguard Worker {
245*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
246*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
247*f6dc9357SAndroid Build Coastguard Worker   {
248*f6dc9357SAndroid Build Coastguard Worker     case kpidSize: prop = (UInt64)_item.GetSize(); break;
249*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize: if (_packSizeDefined) prop = _item.HeaderSize + _packSize; break;
250*f6dc9357SAndroid Build Coastguard Worker     case kpidMethod:
251*f6dc9357SAndroid Build Coastguard Worker     {
252*f6dc9357SAndroid Build Coastguard Worker       char s[32];
253*f6dc9357SAndroid Build Coastguard Worker       if (_item.IsZlib())
254*f6dc9357SAndroid Build Coastguard Worker         MyStringCopy(s, "zlib");
255*f6dc9357SAndroid Build Coastguard Worker       else
256*f6dc9357SAndroid Build Coastguard Worker       {
257*f6dc9357SAndroid Build Coastguard Worker         MyStringCopy(s, "LZMA:");
258*f6dc9357SAndroid Build Coastguard Worker         DicSizeToString(s + 5, _item.GetLzmaDicSize());
259*f6dc9357SAndroid Build Coastguard Worker       }
260*f6dc9357SAndroid Build Coastguard Worker       prop = s;
261*f6dc9357SAndroid Build Coastguard Worker       break;
262*f6dc9357SAndroid Build Coastguard Worker     }
263*f6dc9357SAndroid Build Coastguard Worker   }
264*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
265*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
266*f6dc9357SAndroid Build Coastguard Worker }
267*f6dc9357SAndroid Build Coastguard Worker 
268*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *))
269*f6dc9357SAndroid Build Coastguard Worker {
270*f6dc9357SAndroid Build Coastguard Worker   RINOK(OpenSeq(stream))
271*f6dc9357SAndroid Build Coastguard Worker   _stream = stream;
272*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
273*f6dc9357SAndroid Build Coastguard Worker }
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
276*f6dc9357SAndroid Build Coastguard Worker {
277*f6dc9357SAndroid Build Coastguard Worker   Close();
278*f6dc9357SAndroid Build Coastguard Worker   RINOK(_item.ReadHeader(stream))
279*f6dc9357SAndroid Build Coastguard Worker   if (!_item.IsSwf())
280*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
281*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsLzma())
282*f6dc9357SAndroid Build Coastguard Worker   {
283*f6dc9357SAndroid Build Coastguard Worker     RINOK(ReadStream_FALSE(stream, _item.Buf + kHeaderBaseSize, kHeaderLzmaSize - kHeaderBaseSize))
284*f6dc9357SAndroid Build Coastguard Worker     _item.HeaderSize = kHeaderLzmaSize;
285*f6dc9357SAndroid Build Coastguard Worker     _packSize = _item.GetLzmaPackSize();
286*f6dc9357SAndroid Build Coastguard Worker     _packSizeDefined = true;
287*f6dc9357SAndroid Build Coastguard Worker   }
288*f6dc9357SAndroid Build Coastguard Worker   else if (!_item.IsZlib())
289*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
290*f6dc9357SAndroid Build Coastguard Worker   if (_item.GetSize() < _item.HeaderSize)
291*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
292*f6dc9357SAndroid Build Coastguard Worker   _seqStream = stream;
293*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
294*f6dc9357SAndroid Build Coastguard Worker }
295*f6dc9357SAndroid Build Coastguard Worker 
296*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
297*f6dc9357SAndroid Build Coastguard Worker {
298*f6dc9357SAndroid Build Coastguard Worker   _packSize = 0;
299*f6dc9357SAndroid Build Coastguard Worker   _packSizeDefined = false;
300*f6dc9357SAndroid Build Coastguard Worker   _seqStream.Release();
301*f6dc9357SAndroid Build Coastguard Worker   _stream.Release();
302*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
303*f6dc9357SAndroid Build Coastguard Worker }
304*f6dc9357SAndroid Build Coastguard Worker 
305*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_COM_1(
306*f6dc9357SAndroid Build Coastguard Worker   CCompressProgressInfoImp,
307*f6dc9357SAndroid Build Coastguard Worker   ICompressProgressInfo
308*f6dc9357SAndroid Build Coastguard Worker )
309*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IArchiveOpenCallback> Callback;
310*f6dc9357SAndroid Build Coastguard Worker public:
311*f6dc9357SAndroid Build Coastguard Worker   UInt64 Offset;
312*f6dc9357SAndroid Build Coastguard Worker   void Init(IArchiveOpenCallback *callback) { Callback = callback; }
313*f6dc9357SAndroid Build Coastguard Worker };
314*f6dc9357SAndroid Build Coastguard Worker 
315*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CCompressProgressInfoImp::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
316*f6dc9357SAndroid Build Coastguard Worker {
317*f6dc9357SAndroid Build Coastguard Worker   if (Callback)
318*f6dc9357SAndroid Build Coastguard Worker   {
319*f6dc9357SAndroid Build Coastguard Worker     const UInt64 files = 0;
320*f6dc9357SAndroid Build Coastguard Worker     const UInt64 value = Offset + *inSize;
321*f6dc9357SAndroid Build Coastguard Worker     return Callback->SetCompleted(&files, &value);
322*f6dc9357SAndroid Build Coastguard Worker   }
323*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
324*f6dc9357SAndroid Build Coastguard Worker }
325*f6dc9357SAndroid Build Coastguard Worker 
326*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
327*f6dc9357SAndroid Build Coastguard Worker     Int32 testMode, IArchiveExtractCallback *extractCallback))
328*f6dc9357SAndroid Build Coastguard Worker {
329*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
330*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
331*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
332*f6dc9357SAndroid Build Coastguard Worker   if (numItems != (UInt32)(Int32)-1 && (numItems != 1 || indices[0] != 0))
333*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
334*f6dc9357SAndroid Build Coastguard Worker 
335*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->SetTotal(_item.GetSize()))
336*f6dc9357SAndroid Build Coastguard Worker   Int32 opRes;
337*f6dc9357SAndroid Build Coastguard Worker {
338*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> realOutStream;
339*f6dc9357SAndroid Build Coastguard Worker   const Int32 askMode = testMode ?
340*f6dc9357SAndroid Build Coastguard Worker       NExtract::NAskMode::kTest :
341*f6dc9357SAndroid Build Coastguard Worker       NExtract::NAskMode::kExtract;
342*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->GetStream(0, &realOutStream, askMode))
343*f6dc9357SAndroid Build Coastguard Worker   if (!testMode && !realOutStream)
344*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
345*f6dc9357SAndroid Build Coastguard Worker 
346*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->PrepareOperation(askMode))
347*f6dc9357SAndroid Build Coastguard Worker 
348*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ISequentialOutStream, CDummyOutStream> outStream;
349*f6dc9357SAndroid Build Coastguard Worker   outStream->SetStream(realOutStream);
350*f6dc9357SAndroid Build Coastguard Worker   outStream->Init();
351*f6dc9357SAndroid Build Coastguard Worker   // realOutStream.Release();
352*f6dc9357SAndroid Build Coastguard Worker 
353*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
354*f6dc9357SAndroid Build Coastguard Worker   lps->Init(extractCallback, false);
355*f6dc9357SAndroid Build Coastguard Worker 
356*f6dc9357SAndroid Build Coastguard Worker   lps->InSize = _item.HeaderSize;
357*f6dc9357SAndroid Build Coastguard Worker   lps->OutSize = outStream->GetSize();
358*f6dc9357SAndroid Build Coastguard Worker   RINOK(lps->SetCur())
359*f6dc9357SAndroid Build Coastguard Worker 
360*f6dc9357SAndroid Build Coastguard Worker   CItem item = _item;
361*f6dc9357SAndroid Build Coastguard Worker   item.MakeUncompressed();
362*f6dc9357SAndroid Build Coastguard Worker   if (_stream)
363*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekSet(_stream, _item.HeaderSize))
364*f6dc9357SAndroid Build Coastguard Worker   NCompress::NZlib::CDecoder *_decoderZlibSpec = NULL;
365*f6dc9357SAndroid Build Coastguard Worker   NCompress::NLzma::CDecoder *_decoderLzmaSpec = NULL;
366*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressCoder> _decoder;
367*f6dc9357SAndroid Build Coastguard Worker 
368*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> inStream2;
369*f6dc9357SAndroid Build Coastguard Worker 
370*f6dc9357SAndroid Build Coastguard Worker   const UInt64 unpackSize = _item.GetSize() - (UInt32)8;
371*f6dc9357SAndroid Build Coastguard Worker   if (_item.IsZlib())
372*f6dc9357SAndroid Build Coastguard Worker   {
373*f6dc9357SAndroid Build Coastguard Worker     _decoderZlibSpec = new NCompress::NZlib::CDecoder;
374*f6dc9357SAndroid Build Coastguard Worker     _decoder = _decoderZlibSpec;
375*f6dc9357SAndroid Build Coastguard Worker     inStream2 = _seqStream;
376*f6dc9357SAndroid Build Coastguard Worker   }
377*f6dc9357SAndroid Build Coastguard Worker   else
378*f6dc9357SAndroid Build Coastguard Worker   {
379*f6dc9357SAndroid Build Coastguard Worker     /* Some .swf files with lzma contain additional 8 bytes at the end
380*f6dc9357SAndroid Build Coastguard Worker        in uncompressed stream.
381*f6dc9357SAndroid Build Coastguard Worker        What does that data mean ???
382*f6dc9357SAndroid Build Coastguard Worker        We don't decompress these additional 8 bytes */
383*f6dc9357SAndroid Build Coastguard Worker 
384*f6dc9357SAndroid Build Coastguard Worker     // unpackSize = _item.GetSize();
385*f6dc9357SAndroid Build Coastguard Worker     // SetUi32(item.Buf + 4, (UInt32)(unpackSize + 8));
386*f6dc9357SAndroid Build Coastguard Worker     CLimitedSequentialInStream *limitedStreamSpec = new CLimitedSequentialInStream;
387*f6dc9357SAndroid Build Coastguard Worker     inStream2 = limitedStreamSpec;
388*f6dc9357SAndroid Build Coastguard Worker     limitedStreamSpec->SetStream(_seqStream);
389*f6dc9357SAndroid Build Coastguard Worker     limitedStreamSpec->Init(_item.GetLzmaPackSize());
390*f6dc9357SAndroid Build Coastguard Worker 
391*f6dc9357SAndroid Build Coastguard Worker     _decoderLzmaSpec = new NCompress::NLzma::CDecoder;
392*f6dc9357SAndroid Build Coastguard Worker     _decoder = _decoderLzmaSpec;
393*f6dc9357SAndroid Build Coastguard Worker     // _decoderLzmaSpec->FinishStream = true;
394*f6dc9357SAndroid Build Coastguard Worker 
395*f6dc9357SAndroid Build Coastguard Worker     Byte props[5];
396*f6dc9357SAndroid Build Coastguard Worker     memcpy(props, _item.Buf + 12, 5);
397*f6dc9357SAndroid Build Coastguard Worker     UInt32 dicSize = _item.GetLzmaDicSize();
398*f6dc9357SAndroid Build Coastguard Worker     if (dicSize > (UInt32)unpackSize)
399*f6dc9357SAndroid Build Coastguard Worker     {
400*f6dc9357SAndroid Build Coastguard Worker       dicSize = (UInt32)unpackSize;
401*f6dc9357SAndroid Build Coastguard Worker       SetUi32(props + 1, dicSize)
402*f6dc9357SAndroid Build Coastguard Worker     }
403*f6dc9357SAndroid Build Coastguard Worker     RINOK(_decoderLzmaSpec->SetDecoderProperties2(props, 5))
404*f6dc9357SAndroid Build Coastguard Worker   }
405*f6dc9357SAndroid Build Coastguard Worker   RINOK(item.WriteHeader(outStream))
406*f6dc9357SAndroid Build Coastguard Worker   const HRESULT result = _decoder->Code(inStream2, outStream, NULL, &unpackSize, lps);
407*f6dc9357SAndroid Build Coastguard Worker   opRes = NExtract::NOperationResult::kDataError;
408*f6dc9357SAndroid Build Coastguard Worker   if (result == S_OK)
409*f6dc9357SAndroid Build Coastguard Worker   {
410*f6dc9357SAndroid Build Coastguard Worker     if (item.GetSize() == outStream->GetSize())
411*f6dc9357SAndroid Build Coastguard Worker     {
412*f6dc9357SAndroid Build Coastguard Worker       if (_item.IsZlib())
413*f6dc9357SAndroid Build Coastguard Worker       {
414*f6dc9357SAndroid Build Coastguard Worker         _packSizeDefined = true;
415*f6dc9357SAndroid Build Coastguard Worker         _packSize = _decoderZlibSpec->GetInputProcessedSize();
416*f6dc9357SAndroid Build Coastguard Worker         opRes = NExtract::NOperationResult::kOK;
417*f6dc9357SAndroid Build Coastguard Worker       }
418*f6dc9357SAndroid Build Coastguard Worker       else
419*f6dc9357SAndroid Build Coastguard Worker       {
420*f6dc9357SAndroid Build Coastguard Worker         // if (_decoderLzmaSpec->GetInputProcessedSize() == _packSize)
421*f6dc9357SAndroid Build Coastguard Worker           opRes = NExtract::NOperationResult::kOK;
422*f6dc9357SAndroid Build Coastguard Worker       }
423*f6dc9357SAndroid Build Coastguard Worker     }
424*f6dc9357SAndroid Build Coastguard Worker   }
425*f6dc9357SAndroid Build Coastguard Worker   else if (result != S_FALSE)
426*f6dc9357SAndroid Build Coastguard Worker     return result;
427*f6dc9357SAndroid Build Coastguard Worker 
428*f6dc9357SAndroid Build Coastguard Worker   // outStream.Release();
429*f6dc9357SAndroid Build Coastguard Worker  }
430*f6dc9357SAndroid Build Coastguard Worker   return extractCallback->SetOperationResult(opRes);
431*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
432*f6dc9357SAndroid Build Coastguard Worker }
433*f6dc9357SAndroid Build Coastguard Worker 
434*f6dc9357SAndroid Build Coastguard Worker 
435*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_SWF_UPDATE
436*f6dc9357SAndroid Build Coastguard Worker 
437*f6dc9357SAndroid Build Coastguard Worker static HRESULT UpdateArchive(ISequentialOutStream *outStream, UInt64 size,
438*f6dc9357SAndroid Build Coastguard Worker     bool lzmaMode, const CSingleMethodProps &props,
439*f6dc9357SAndroid Build Coastguard Worker     IArchiveUpdateCallback *updateCallback)
440*f6dc9357SAndroid Build Coastguard Worker {
441*f6dc9357SAndroid Build Coastguard Worker   UInt64 complexity = 0;
442*f6dc9357SAndroid Build Coastguard Worker   RINOK(updateCallback->SetTotal(size))
443*f6dc9357SAndroid Build Coastguard Worker   RINOK(updateCallback->SetCompleted(&complexity))
444*f6dc9357SAndroid Build Coastguard Worker 
445*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialInStream> fileInStream;
446*f6dc9357SAndroid Build Coastguard Worker   RINOK(updateCallback->GetStream(0, &fileInStream))
447*f6dc9357SAndroid Build Coastguard Worker 
448*f6dc9357SAndroid Build Coastguard Worker   /*
449*f6dc9357SAndroid Build Coastguard Worker   CDummyOutStream *outStreamSpec = new CDummyOutStream;
450*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
451*f6dc9357SAndroid Build Coastguard Worker   outStreamSpec->SetStream(realOutStream);
452*f6dc9357SAndroid Build Coastguard Worker   outStreamSpec->Init();
453*f6dc9357SAndroid Build Coastguard Worker   realOutStream.Release();
454*f6dc9357SAndroid Build Coastguard Worker   */
455*f6dc9357SAndroid Build Coastguard Worker 
456*f6dc9357SAndroid Build Coastguard Worker   CItem item;
457*f6dc9357SAndroid Build Coastguard Worker   const HRESULT res = item.ReadHeader(fileInStream);
458*f6dc9357SAndroid Build Coastguard Worker   if (res == S_FALSE)
459*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
460*f6dc9357SAndroid Build Coastguard Worker   RINOK(res)
461*f6dc9357SAndroid Build Coastguard Worker   if (!item.IsSwf() || !item.IsUncompressed() || size != item.GetSize())
462*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
463*f6dc9357SAndroid Build Coastguard Worker 
464*f6dc9357SAndroid Build Coastguard Worker   NCompress::NZlib::CEncoder *encoderZlibSpec = NULL;
465*f6dc9357SAndroid Build Coastguard Worker   NCompress::NLzma::CEncoder *encoderLzmaSpec = NULL;
466*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressCoder> encoder;
467*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<IOutStream> outSeekStream;
468*f6dc9357SAndroid Build Coastguard Worker   if (lzmaMode)
469*f6dc9357SAndroid Build Coastguard Worker   {
470*f6dc9357SAndroid Build Coastguard Worker     outStream->QueryInterface(IID_IOutStream, (void **)&outSeekStream);
471*f6dc9357SAndroid Build Coastguard Worker     if (!outSeekStream)
472*f6dc9357SAndroid Build Coastguard Worker       return E_NOTIMPL;
473*f6dc9357SAndroid Build Coastguard Worker     encoderLzmaSpec = new NCompress::NLzma::CEncoder;
474*f6dc9357SAndroid Build Coastguard Worker     encoder = encoderLzmaSpec;
475*f6dc9357SAndroid Build Coastguard Worker     RINOK(props.SetCoderProps(encoderLzmaSpec, &size))
476*f6dc9357SAndroid Build Coastguard Worker     item.MakeLzma((UInt32)0xFFFFFFFF);
477*f6dc9357SAndroid Build Coastguard Worker     CBufPtrSeqOutStream *propStreamSpec = new CBufPtrSeqOutStream;
478*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialOutStream> propStream = propStreamSpec;
479*f6dc9357SAndroid Build Coastguard Worker     propStreamSpec->Init(item.Buf + 12, 5);
480*f6dc9357SAndroid Build Coastguard Worker     RINOK(encoderLzmaSpec->WriteCoderProperties(propStream))
481*f6dc9357SAndroid Build Coastguard Worker   }
482*f6dc9357SAndroid Build Coastguard Worker   else
483*f6dc9357SAndroid Build Coastguard Worker   {
484*f6dc9357SAndroid Build Coastguard Worker     encoderZlibSpec = new NCompress::NZlib::CEncoder;
485*f6dc9357SAndroid Build Coastguard Worker     encoder = encoderZlibSpec;
486*f6dc9357SAndroid Build Coastguard Worker     encoderZlibSpec->Create();
487*f6dc9357SAndroid Build Coastguard Worker     RINOK(props.SetCoderProps(encoderZlibSpec->DeflateEncoderSpec, NULL))
488*f6dc9357SAndroid Build Coastguard Worker     item.MakeZlib();
489*f6dc9357SAndroid Build Coastguard Worker   }
490*f6dc9357SAndroid Build Coastguard Worker   RINOK(item.WriteHeader(outStream))
491*f6dc9357SAndroid Build Coastguard Worker 
492*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps;
493*f6dc9357SAndroid Build Coastguard Worker   lps->Init(updateCallback, true);
494*f6dc9357SAndroid Build Coastguard Worker 
495*f6dc9357SAndroid Build Coastguard Worker   RINOK(encoder->Code(fileInStream, outStream, NULL, NULL, lps))
496*f6dc9357SAndroid Build Coastguard Worker   UInt64 inputProcessed;
497*f6dc9357SAndroid Build Coastguard Worker   if (lzmaMode)
498*f6dc9357SAndroid Build Coastguard Worker   {
499*f6dc9357SAndroid Build Coastguard Worker     UInt64 curPos = 0;
500*f6dc9357SAndroid Build Coastguard Worker     RINOK(outSeekStream->Seek(0, STREAM_SEEK_CUR, &curPos))
501*f6dc9357SAndroid Build Coastguard Worker     const UInt64 packSize = curPos - kHeaderLzmaSize;
502*f6dc9357SAndroid Build Coastguard Worker     if (packSize > (UInt32)0xFFFFFFFF)
503*f6dc9357SAndroid Build Coastguard Worker       return E_INVALIDARG;
504*f6dc9357SAndroid Build Coastguard Worker     item.MakeLzma((UInt32)packSize);
505*f6dc9357SAndroid Build Coastguard Worker     RINOK(outSeekStream->Seek(0, STREAM_SEEK_SET, NULL))
506*f6dc9357SAndroid Build Coastguard Worker     RINOK(item.WriteHeader(outStream))
507*f6dc9357SAndroid Build Coastguard Worker     inputProcessed = encoderLzmaSpec->GetInputProcessedSize();
508*f6dc9357SAndroid Build Coastguard Worker   }
509*f6dc9357SAndroid Build Coastguard Worker   else
510*f6dc9357SAndroid Build Coastguard Worker   {
511*f6dc9357SAndroid Build Coastguard Worker     inputProcessed = encoderZlibSpec->GetInputProcessedSize();
512*f6dc9357SAndroid Build Coastguard Worker   }
513*f6dc9357SAndroid Build Coastguard Worker   if (inputProcessed + kHeaderBaseSize != size)
514*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
515*f6dc9357SAndroid Build Coastguard Worker   return updateCallback->SetOperationResult(NUpdate::NOperationResult::kOK);
516*f6dc9357SAndroid Build Coastguard Worker }
517*f6dc9357SAndroid Build Coastguard Worker 
518*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetFileTimeType(UInt32 *timeType))
519*f6dc9357SAndroid Build Coastguard Worker {
520*f6dc9357SAndroid Build Coastguard Worker   *timeType = NFileTimeType::kUnix;
521*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
522*f6dc9357SAndroid Build Coastguard Worker }
523*f6dc9357SAndroid Build Coastguard Worker 
524*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems,
525*f6dc9357SAndroid Build Coastguard Worker     IArchiveUpdateCallback *updateCallback))
526*f6dc9357SAndroid Build Coastguard Worker {
527*f6dc9357SAndroid Build Coastguard Worker   if (numItems != 1)
528*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
529*f6dc9357SAndroid Build Coastguard Worker 
530*f6dc9357SAndroid Build Coastguard Worker   Int32 newData, newProps;
531*f6dc9357SAndroid Build Coastguard Worker   UInt32 indexInArchive;
532*f6dc9357SAndroid Build Coastguard Worker   if (!updateCallback)
533*f6dc9357SAndroid Build Coastguard Worker     return E_FAIL;
534*f6dc9357SAndroid Build Coastguard Worker   RINOK(updateCallback->GetUpdateItemInfo(0, &newData, &newProps, &indexInArchive))
535*f6dc9357SAndroid Build Coastguard Worker 
536*f6dc9357SAndroid Build Coastguard Worker   if (IntToBool(newProps))
537*f6dc9357SAndroid Build Coastguard Worker   {
538*f6dc9357SAndroid Build Coastguard Worker     {
539*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
540*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->GetProperty(0, kpidIsDir, &prop))
541*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt == VT_BOOL)
542*f6dc9357SAndroid Build Coastguard Worker       {
543*f6dc9357SAndroid Build Coastguard Worker         if (prop.boolVal != VARIANT_FALSE)
544*f6dc9357SAndroid Build Coastguard Worker           return E_INVALIDARG;
545*f6dc9357SAndroid Build Coastguard Worker       }
546*f6dc9357SAndroid Build Coastguard Worker       else if (prop.vt != VT_EMPTY)
547*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
548*f6dc9357SAndroid Build Coastguard Worker     }
549*f6dc9357SAndroid Build Coastguard Worker   }
550*f6dc9357SAndroid Build Coastguard Worker 
551*f6dc9357SAndroid Build Coastguard Worker   if (IntToBool(newData))
552*f6dc9357SAndroid Build Coastguard Worker   {
553*f6dc9357SAndroid Build Coastguard Worker     UInt64 size;
554*f6dc9357SAndroid Build Coastguard Worker     {
555*f6dc9357SAndroid Build Coastguard Worker       NCOM::CPropVariant prop;
556*f6dc9357SAndroid Build Coastguard Worker       RINOK(updateCallback->GetProperty(0, kpidSize, &prop))
557*f6dc9357SAndroid Build Coastguard Worker       if (prop.vt != VT_UI8)
558*f6dc9357SAndroid Build Coastguard Worker         return E_INVALIDARG;
559*f6dc9357SAndroid Build Coastguard Worker       size = prop.uhVal.QuadPart;
560*f6dc9357SAndroid Build Coastguard Worker     }
561*f6dc9357SAndroid Build Coastguard Worker     return UpdateArchive(outStream, size, _lzmaMode, _props, updateCallback);
562*f6dc9357SAndroid Build Coastguard Worker   }
563*f6dc9357SAndroid Build Coastguard Worker 
564*f6dc9357SAndroid Build Coastguard Worker   if (indexInArchive != 0)
565*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
566*f6dc9357SAndroid Build Coastguard Worker 
567*f6dc9357SAndroid Build Coastguard Worker   if (!_seqStream)
568*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
569*f6dc9357SAndroid Build Coastguard Worker 
570*f6dc9357SAndroid Build Coastguard Worker   if (_stream)
571*f6dc9357SAndroid Build Coastguard Worker   {
572*f6dc9357SAndroid Build Coastguard Worker     RINOK(InStream_SeekToBegin(_stream))
573*f6dc9357SAndroid Build Coastguard Worker   }
574*f6dc9357SAndroid Build Coastguard Worker   else
575*f6dc9357SAndroid Build Coastguard Worker     _item.WriteHeader(outStream);
576*f6dc9357SAndroid Build Coastguard Worker   return NCompress::CopyStream(_seqStream, outStream, NULL);
577*f6dc9357SAndroid Build Coastguard Worker }
578*f6dc9357SAndroid Build Coastguard Worker 
579*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps))
580*f6dc9357SAndroid Build Coastguard Worker {
581*f6dc9357SAndroid Build Coastguard Worker   _lzmaMode = false;
582*f6dc9357SAndroid Build Coastguard Worker   RINOK(_props.SetProperties(names, values, numProps))
583*f6dc9357SAndroid Build Coastguard Worker   const AString &m = _props.MethodName;
584*f6dc9357SAndroid Build Coastguard Worker   if (m.IsEqualTo_Ascii_NoCase("lzma"))
585*f6dc9357SAndroid Build Coastguard Worker   {
586*f6dc9357SAndroid Build Coastguard Worker     return E_NOTIMPL;
587*f6dc9357SAndroid Build Coastguard Worker     // _lzmaMode = true;
588*f6dc9357SAndroid Build Coastguard Worker   }
589*f6dc9357SAndroid Build Coastguard Worker   else if (m.IsEqualTo_Ascii_NoCase("Deflate") || m.IsEmpty())
590*f6dc9357SAndroid Build Coastguard Worker     _lzmaMode = false;
591*f6dc9357SAndroid Build Coastguard Worker   else
592*f6dc9357SAndroid Build Coastguard Worker     return E_INVALIDARG;
593*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
594*f6dc9357SAndroid Build Coastguard Worker }
595*f6dc9357SAndroid Build Coastguard Worker 
596*f6dc9357SAndroid Build Coastguard Worker #endif
597*f6dc9357SAndroid Build Coastguard Worker 
598*f6dc9357SAndroid Build Coastguard Worker 
599*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = {
600*f6dc9357SAndroid Build Coastguard Worker     3, 'C', 'W', 'S',
601*f6dc9357SAndroid Build Coastguard Worker     3, 'Z', 'W', 'S' };
602*f6dc9357SAndroid Build Coastguard Worker 
603*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
604*f6dc9357SAndroid Build Coastguard Worker   "SWFc", "swf", "~.swf", 0xD8,
605*f6dc9357SAndroid Build Coastguard Worker   k_Signature,
606*f6dc9357SAndroid Build Coastguard Worker   0,
607*f6dc9357SAndroid Build Coastguard Worker   NArcInfoFlags::kMultiSignature,
608*f6dc9357SAndroid Build Coastguard Worker   IsArc_Swfc)
609*f6dc9357SAndroid Build Coastguard Worker 
610*f6dc9357SAndroid Build Coastguard Worker }
611*f6dc9357SAndroid Build Coastguard Worker 
612*f6dc9357SAndroid Build Coastguard Worker namespace NSwf {
613*f6dc9357SAndroid Build Coastguard Worker 
614*f6dc9357SAndroid Build Coastguard Worker static const unsigned kNumTagsMax = 1 << 23;
615*f6dc9357SAndroid Build Coastguard Worker 
616*f6dc9357SAndroid Build Coastguard Worker struct CTag
617*f6dc9357SAndroid Build Coastguard Worker {
618*f6dc9357SAndroid Build Coastguard Worker   UInt32 Type;
619*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer Buf;
620*f6dc9357SAndroid Build Coastguard Worker };
621*f6dc9357SAndroid Build Coastguard Worker 
622*f6dc9357SAndroid Build Coastguard Worker 
623*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_1(
624*f6dc9357SAndroid Build Coastguard Worker   IArchiveOpenSeq
625*f6dc9357SAndroid Build Coastguard Worker )
626*f6dc9357SAndroid Build Coastguard Worker   CObjectVector<CTag> _tags;
627*f6dc9357SAndroid Build Coastguard Worker   NSwfc::CItem _item;
628*f6dc9357SAndroid Build Coastguard Worker   UInt64 _phySize;
629*f6dc9357SAndroid Build Coastguard Worker 
630*f6dc9357SAndroid Build Coastguard Worker   HRESULT OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback);
631*f6dc9357SAndroid Build Coastguard Worker   HRESULT OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback);
632*f6dc9357SAndroid Build Coastguard Worker };
633*f6dc9357SAndroid Build Coastguard Worker 
634*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] =
635*f6dc9357SAndroid Build Coastguard Worker {
636*f6dc9357SAndroid Build Coastguard Worker   kpidPath,
637*f6dc9357SAndroid Build Coastguard Worker   kpidSize,
638*f6dc9357SAndroid Build Coastguard Worker   kpidComment,
639*f6dc9357SAndroid Build Coastguard Worker };
640*f6dc9357SAndroid Build Coastguard Worker 
641*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props
642*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps_NO_Table
643*f6dc9357SAndroid Build Coastguard Worker 
644*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value))
645*f6dc9357SAndroid Build Coastguard Worker {
646*f6dc9357SAndroid Build Coastguard Worker   NCOM::CPropVariant prop;
647*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
648*f6dc9357SAndroid Build Coastguard Worker   {
649*f6dc9357SAndroid Build Coastguard Worker     case kpidPhySize: prop = _phySize; break;
650*f6dc9357SAndroid Build Coastguard Worker     case kpidIsNotArcType: prop = true; break;
651*f6dc9357SAndroid Build Coastguard Worker   }
652*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
653*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
654*f6dc9357SAndroid Build Coastguard Worker }
655*f6dc9357SAndroid Build Coastguard Worker 
656*f6dc9357SAndroid Build Coastguard Worker 
657*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems))
658*f6dc9357SAndroid Build Coastguard Worker {
659*f6dc9357SAndroid Build Coastguard Worker   *numItems = _tags.Size();
660*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
661*f6dc9357SAndroid Build Coastguard Worker }
662*f6dc9357SAndroid Build Coastguard Worker 
663*f6dc9357SAndroid Build Coastguard Worker static const char * const g_TagDesc[92] =
664*f6dc9357SAndroid Build Coastguard Worker {
665*f6dc9357SAndroid Build Coastguard Worker     "End"
666*f6dc9357SAndroid Build Coastguard Worker   , "ShowFrame"
667*f6dc9357SAndroid Build Coastguard Worker   , "DefineShape"
668*f6dc9357SAndroid Build Coastguard Worker   , NULL
669*f6dc9357SAndroid Build Coastguard Worker   , "PlaceObject"
670*f6dc9357SAndroid Build Coastguard Worker   , "RemoveObject"
671*f6dc9357SAndroid Build Coastguard Worker   , "DefineBits"
672*f6dc9357SAndroid Build Coastguard Worker   , "DefineButton"
673*f6dc9357SAndroid Build Coastguard Worker   , "JPEGTables"
674*f6dc9357SAndroid Build Coastguard Worker   , "SetBackgroundColor"
675*f6dc9357SAndroid Build Coastguard Worker   , "DefineFont"
676*f6dc9357SAndroid Build Coastguard Worker   , "DefineText"
677*f6dc9357SAndroid Build Coastguard Worker   , "DoAction"
678*f6dc9357SAndroid Build Coastguard Worker   , "DefineFontInfo"
679*f6dc9357SAndroid Build Coastguard Worker   , "DefineSound"
680*f6dc9357SAndroid Build Coastguard Worker   , "StartSound"
681*f6dc9357SAndroid Build Coastguard Worker   , NULL
682*f6dc9357SAndroid Build Coastguard Worker   , "DefineButtonSound"
683*f6dc9357SAndroid Build Coastguard Worker   , "SoundStreamHead"
684*f6dc9357SAndroid Build Coastguard Worker   , "SoundStreamBlock"
685*f6dc9357SAndroid Build Coastguard Worker   , "DefineBitsLossless"
686*f6dc9357SAndroid Build Coastguard Worker   , "DefineBitsJPEG2"
687*f6dc9357SAndroid Build Coastguard Worker   , "DefineShape2"
688*f6dc9357SAndroid Build Coastguard Worker   , "DefineButtonCxform"
689*f6dc9357SAndroid Build Coastguard Worker   , "Protect"
690*f6dc9357SAndroid Build Coastguard Worker   , NULL
691*f6dc9357SAndroid Build Coastguard Worker   , "PlaceObject2"
692*f6dc9357SAndroid Build Coastguard Worker   , NULL
693*f6dc9357SAndroid Build Coastguard Worker   , "RemoveObject2"
694*f6dc9357SAndroid Build Coastguard Worker   , NULL
695*f6dc9357SAndroid Build Coastguard Worker   , NULL
696*f6dc9357SAndroid Build Coastguard Worker   , NULL
697*f6dc9357SAndroid Build Coastguard Worker   , "DefineShape3"
698*f6dc9357SAndroid Build Coastguard Worker   , "DefineText2"
699*f6dc9357SAndroid Build Coastguard Worker   , "DefineButton2"
700*f6dc9357SAndroid Build Coastguard Worker   , "DefineBitsJPEG3"
701*f6dc9357SAndroid Build Coastguard Worker   , "DefineBitsLossless2"
702*f6dc9357SAndroid Build Coastguard Worker   , "DefineEditText"
703*f6dc9357SAndroid Build Coastguard Worker   , NULL
704*f6dc9357SAndroid Build Coastguard Worker   , "DefineSprite"
705*f6dc9357SAndroid Build Coastguard Worker   , NULL
706*f6dc9357SAndroid Build Coastguard Worker   , "41"
707*f6dc9357SAndroid Build Coastguard Worker   , NULL
708*f6dc9357SAndroid Build Coastguard Worker   , "FrameLabel"
709*f6dc9357SAndroid Build Coastguard Worker   , NULL
710*f6dc9357SAndroid Build Coastguard Worker   , "SoundStreamHead2"
711*f6dc9357SAndroid Build Coastguard Worker   , "DefineMorphShape"
712*f6dc9357SAndroid Build Coastguard Worker   , NULL
713*f6dc9357SAndroid Build Coastguard Worker   , "DefineFont2"
714*f6dc9357SAndroid Build Coastguard Worker   , NULL
715*f6dc9357SAndroid Build Coastguard Worker   , NULL
716*f6dc9357SAndroid Build Coastguard Worker   , NULL
717*f6dc9357SAndroid Build Coastguard Worker   , NULL
718*f6dc9357SAndroid Build Coastguard Worker   , NULL
719*f6dc9357SAndroid Build Coastguard Worker   , NULL
720*f6dc9357SAndroid Build Coastguard Worker   , NULL
721*f6dc9357SAndroid Build Coastguard Worker   , "ExportAssets"
722*f6dc9357SAndroid Build Coastguard Worker   , "ImportAssets"
723*f6dc9357SAndroid Build Coastguard Worker   , "EnableDebugger"
724*f6dc9357SAndroid Build Coastguard Worker   , "DoInitAction"
725*f6dc9357SAndroid Build Coastguard Worker   , "DefineVideoStream"
726*f6dc9357SAndroid Build Coastguard Worker   , "VideoFrame"
727*f6dc9357SAndroid Build Coastguard Worker   , "DefineFontInfo2"
728*f6dc9357SAndroid Build Coastguard Worker   , NULL
729*f6dc9357SAndroid Build Coastguard Worker   , "EnableDebugger2"
730*f6dc9357SAndroid Build Coastguard Worker   , "ScriptLimits"
731*f6dc9357SAndroid Build Coastguard Worker   , "SetTabIndex"
732*f6dc9357SAndroid Build Coastguard Worker   , NULL
733*f6dc9357SAndroid Build Coastguard Worker   , NULL
734*f6dc9357SAndroid Build Coastguard Worker   , "FileAttributes"
735*f6dc9357SAndroid Build Coastguard Worker   , "PlaceObject3"
736*f6dc9357SAndroid Build Coastguard Worker   , "ImportAssets2"
737*f6dc9357SAndroid Build Coastguard Worker   , NULL
738*f6dc9357SAndroid Build Coastguard Worker   , "DefineFontAlignZones"
739*f6dc9357SAndroid Build Coastguard Worker   , "CSMTextSettings"
740*f6dc9357SAndroid Build Coastguard Worker   , "DefineFont3"
741*f6dc9357SAndroid Build Coastguard Worker   , "SymbolClass"
742*f6dc9357SAndroid Build Coastguard Worker   , "Metadata"
743*f6dc9357SAndroid Build Coastguard Worker   , "DefineScalingGrid"
744*f6dc9357SAndroid Build Coastguard Worker   , NULL
745*f6dc9357SAndroid Build Coastguard Worker   , NULL
746*f6dc9357SAndroid Build Coastguard Worker   , NULL
747*f6dc9357SAndroid Build Coastguard Worker   , "DoABC"
748*f6dc9357SAndroid Build Coastguard Worker   , "DefineShape4"
749*f6dc9357SAndroid Build Coastguard Worker   , "DefineMorphShape2"
750*f6dc9357SAndroid Build Coastguard Worker   , NULL
751*f6dc9357SAndroid Build Coastguard Worker   , "DefineSceneAndFrameLabelData"
752*f6dc9357SAndroid Build Coastguard Worker   , "DefineBinaryData"
753*f6dc9357SAndroid Build Coastguard Worker   , "DefineFontName"
754*f6dc9357SAndroid Build Coastguard Worker   , "StartSound2"
755*f6dc9357SAndroid Build Coastguard Worker   , "DefineBitsJPEG4"
756*f6dc9357SAndroid Build Coastguard Worker   , "DefineFont4"
757*f6dc9357SAndroid Build Coastguard Worker };
758*f6dc9357SAndroid Build Coastguard Worker 
759*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value))
760*f6dc9357SAndroid Build Coastguard Worker {
761*f6dc9357SAndroid Build Coastguard Worker   NWindows::NCOM::CPropVariant prop;
762*f6dc9357SAndroid Build Coastguard Worker   const CTag &tag = _tags[index];
763*f6dc9357SAndroid Build Coastguard Worker   switch (propID)
764*f6dc9357SAndroid Build Coastguard Worker   {
765*f6dc9357SAndroid Build Coastguard Worker     case kpidPath:
766*f6dc9357SAndroid Build Coastguard Worker     {
767*f6dc9357SAndroid Build Coastguard Worker       char s[32];
768*f6dc9357SAndroid Build Coastguard Worker       ConvertUInt32ToString(index, s);
769*f6dc9357SAndroid Build Coastguard Worker       size_t i = strlen(s);
770*f6dc9357SAndroid Build Coastguard Worker       s[i++] = '.';
771*f6dc9357SAndroid Build Coastguard Worker       ConvertUInt32ToString(tag.Type, s + i);
772*f6dc9357SAndroid Build Coastguard Worker       prop = s;
773*f6dc9357SAndroid Build Coastguard Worker       break;
774*f6dc9357SAndroid Build Coastguard Worker     }
775*f6dc9357SAndroid Build Coastguard Worker     case kpidSize:
776*f6dc9357SAndroid Build Coastguard Worker     case kpidPackSize:
777*f6dc9357SAndroid Build Coastguard Worker       prop = (UInt64)tag.Buf.Size(); break;
778*f6dc9357SAndroid Build Coastguard Worker     case kpidComment:
779*f6dc9357SAndroid Build Coastguard Worker       TYPE_TO_PROP(g_TagDesc, tag.Type, prop);
780*f6dc9357SAndroid Build Coastguard Worker       break;
781*f6dc9357SAndroid Build Coastguard Worker   }
782*f6dc9357SAndroid Build Coastguard Worker   prop.Detach(value);
783*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
784*f6dc9357SAndroid Build Coastguard Worker }
785*f6dc9357SAndroid Build Coastguard Worker 
786*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallback *callback))
787*f6dc9357SAndroid Build Coastguard Worker {
788*f6dc9357SAndroid Build Coastguard Worker   return OpenSeq2(stream, callback);
789*f6dc9357SAndroid Build Coastguard Worker }
790*f6dc9357SAndroid Build Coastguard Worker 
791*f6dc9357SAndroid Build Coastguard Worker static UInt16 Read16(CInBuffer &stream)
792*f6dc9357SAndroid Build Coastguard Worker {
793*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = 0;
794*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 2; i++)
795*f6dc9357SAndroid Build Coastguard Worker   {
796*f6dc9357SAndroid Build Coastguard Worker     Byte b;
797*f6dc9357SAndroid Build Coastguard Worker     if (!stream.ReadByte(b))
798*f6dc9357SAndroid Build Coastguard Worker       throw 1;
799*f6dc9357SAndroid Build Coastguard Worker     res |= (UInt32)b << (i * 8);
800*f6dc9357SAndroid Build Coastguard Worker   }
801*f6dc9357SAndroid Build Coastguard Worker   return (UInt16)res;
802*f6dc9357SAndroid Build Coastguard Worker }
803*f6dc9357SAndroid Build Coastguard Worker 
804*f6dc9357SAndroid Build Coastguard Worker static UInt32 Read32(CInBuffer &stream)
805*f6dc9357SAndroid Build Coastguard Worker {
806*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = 0;
807*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0; i < 4; i++)
808*f6dc9357SAndroid Build Coastguard Worker   {
809*f6dc9357SAndroid Build Coastguard Worker     Byte b;
810*f6dc9357SAndroid Build Coastguard Worker     if (!stream.ReadByte(b))
811*f6dc9357SAndroid Build Coastguard Worker       throw 1;
812*f6dc9357SAndroid Build Coastguard Worker     res |= (UInt32)b << (i * 8);
813*f6dc9357SAndroid Build Coastguard Worker   }
814*f6dc9357SAndroid Build Coastguard Worker   return res;
815*f6dc9357SAndroid Build Coastguard Worker }
816*f6dc9357SAndroid Build Coastguard Worker 
817*f6dc9357SAndroid Build Coastguard Worker struct CBitReader
818*f6dc9357SAndroid Build Coastguard Worker {
819*f6dc9357SAndroid Build Coastguard Worker   CInBuffer *stream;
820*f6dc9357SAndroid Build Coastguard Worker   unsigned NumBits;
821*f6dc9357SAndroid Build Coastguard Worker   Byte Val;
822*f6dc9357SAndroid Build Coastguard Worker 
823*f6dc9357SAndroid Build Coastguard Worker   CBitReader(): NumBits(0), Val(0) {}
824*f6dc9357SAndroid Build Coastguard Worker 
825*f6dc9357SAndroid Build Coastguard Worker   UInt32 ReadBits(unsigned numBits);
826*f6dc9357SAndroid Build Coastguard Worker };
827*f6dc9357SAndroid Build Coastguard Worker 
828*f6dc9357SAndroid Build Coastguard Worker UInt32 CBitReader::ReadBits(unsigned numBits)
829*f6dc9357SAndroid Build Coastguard Worker {
830*f6dc9357SAndroid Build Coastguard Worker   UInt32 res = 0;
831*f6dc9357SAndroid Build Coastguard Worker   while (numBits > 0)
832*f6dc9357SAndroid Build Coastguard Worker   {
833*f6dc9357SAndroid Build Coastguard Worker     if (NumBits == 0)
834*f6dc9357SAndroid Build Coastguard Worker     {
835*f6dc9357SAndroid Build Coastguard Worker       Val = stream->ReadByte();
836*f6dc9357SAndroid Build Coastguard Worker       NumBits = 8;
837*f6dc9357SAndroid Build Coastguard Worker     }
838*f6dc9357SAndroid Build Coastguard Worker     if (numBits <= NumBits)
839*f6dc9357SAndroid Build Coastguard Worker     {
840*f6dc9357SAndroid Build Coastguard Worker       res <<= numBits;
841*f6dc9357SAndroid Build Coastguard Worker       NumBits -= numBits;
842*f6dc9357SAndroid Build Coastguard Worker       res |= (Val >> NumBits);
843*f6dc9357SAndroid Build Coastguard Worker       Val = (Byte)(Val & (((unsigned)1 << NumBits) - 1));
844*f6dc9357SAndroid Build Coastguard Worker       break;
845*f6dc9357SAndroid Build Coastguard Worker     }
846*f6dc9357SAndroid Build Coastguard Worker     else
847*f6dc9357SAndroid Build Coastguard Worker     {
848*f6dc9357SAndroid Build Coastguard Worker       res <<= NumBits;
849*f6dc9357SAndroid Build Coastguard Worker       res |= Val;
850*f6dc9357SAndroid Build Coastguard Worker       numBits -= NumBits;
851*f6dc9357SAndroid Build Coastguard Worker       NumBits = 0;
852*f6dc9357SAndroid Build Coastguard Worker     }
853*f6dc9357SAndroid Build Coastguard Worker   }
854*f6dc9357SAndroid Build Coastguard Worker   return res;
855*f6dc9357SAndroid Build Coastguard Worker }
856*f6dc9357SAndroid Build Coastguard Worker 
857*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::OpenSeq3(ISequentialInStream *stream, IArchiveOpenCallback *callback)
858*f6dc9357SAndroid Build Coastguard Worker {
859*f6dc9357SAndroid Build Coastguard Worker   RINOK(_item.ReadHeader(stream))
860*f6dc9357SAndroid Build Coastguard Worker   if (!_item.IsSwf() || !_item.IsUncompressed())
861*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
862*f6dc9357SAndroid Build Coastguard Worker   const UInt32 uncompressedSize = _item.GetSize();
863*f6dc9357SAndroid Build Coastguard Worker   if (uncompressedSize > kFileSizeMax)
864*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
865*f6dc9357SAndroid Build Coastguard Worker 
866*f6dc9357SAndroid Build Coastguard Worker 
867*f6dc9357SAndroid Build Coastguard Worker   CInBuffer s;
868*f6dc9357SAndroid Build Coastguard Worker   if (!s.Create(1 << 20))
869*f6dc9357SAndroid Build Coastguard Worker     return E_OUTOFMEMORY;
870*f6dc9357SAndroid Build Coastguard Worker   s.SetStream(stream);
871*f6dc9357SAndroid Build Coastguard Worker   s.Init();
872*f6dc9357SAndroid Build Coastguard Worker   {
873*f6dc9357SAndroid Build Coastguard Worker     CBitReader br;
874*f6dc9357SAndroid Build Coastguard Worker     br.stream = &s;
875*f6dc9357SAndroid Build Coastguard Worker     const unsigned numBits = br.ReadBits(5);
876*f6dc9357SAndroid Build Coastguard Worker     /* UInt32 xMin = */ br.ReadBits(numBits);
877*f6dc9357SAndroid Build Coastguard Worker     /* UInt32 xMax = */ br.ReadBits(numBits);
878*f6dc9357SAndroid Build Coastguard Worker     /* UInt32 yMin = */ br.ReadBits(numBits);
879*f6dc9357SAndroid Build Coastguard Worker     /* UInt32 yMax = */ br.ReadBits(numBits);
880*f6dc9357SAndroid Build Coastguard Worker   }
881*f6dc9357SAndroid Build Coastguard Worker   /* UInt32 frameDelay = */ Read16(s);
882*f6dc9357SAndroid Build Coastguard Worker   /* UInt32 numFrames =  */ Read16(s);
883*f6dc9357SAndroid Build Coastguard Worker 
884*f6dc9357SAndroid Build Coastguard Worker   _tags.Clear();
885*f6dc9357SAndroid Build Coastguard Worker   UInt64 offsetPrev = 0;
886*f6dc9357SAndroid Build Coastguard Worker   for (;;)
887*f6dc9357SAndroid Build Coastguard Worker   {
888*f6dc9357SAndroid Build Coastguard Worker     const UInt32 pair = Read16(s);
889*f6dc9357SAndroid Build Coastguard Worker     const UInt32 type = pair >> 6;
890*f6dc9357SAndroid Build Coastguard Worker     UInt32 length = pair & 0x3F;
891*f6dc9357SAndroid Build Coastguard Worker     if (length == 0x3F)
892*f6dc9357SAndroid Build Coastguard Worker       length = Read32(s);
893*f6dc9357SAndroid Build Coastguard Worker     if (type == 0)
894*f6dc9357SAndroid Build Coastguard Worker       break;
895*f6dc9357SAndroid Build Coastguard Worker     const UInt64 offset = s.GetProcessedSize() + NSwfc::kHeaderBaseSize + length;
896*f6dc9357SAndroid Build Coastguard Worker     if (offset > uncompressedSize || _tags.Size() >= kNumTagsMax)
897*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
898*f6dc9357SAndroid Build Coastguard Worker     CTag &tag = _tags.AddNew();
899*f6dc9357SAndroid Build Coastguard Worker     tag.Type = type;
900*f6dc9357SAndroid Build Coastguard Worker     tag.Buf.Alloc(length);
901*f6dc9357SAndroid Build Coastguard Worker     if (s.ReadBytes(tag.Buf, length) != length)
902*f6dc9357SAndroid Build Coastguard Worker       return S_FALSE;
903*f6dc9357SAndroid Build Coastguard Worker     if (callback && offset >= offsetPrev + (1 << 20))
904*f6dc9357SAndroid Build Coastguard Worker     {
905*f6dc9357SAndroid Build Coastguard Worker       const UInt64 numItems = _tags.Size();
906*f6dc9357SAndroid Build Coastguard Worker       RINOK(callback->SetCompleted(&numItems, &offset))
907*f6dc9357SAndroid Build Coastguard Worker       offsetPrev = offset;
908*f6dc9357SAndroid Build Coastguard Worker     }
909*f6dc9357SAndroid Build Coastguard Worker   }
910*f6dc9357SAndroid Build Coastguard Worker   _phySize = s.GetProcessedSize() + NSwfc::kHeaderBaseSize;
911*f6dc9357SAndroid Build Coastguard Worker   if (_phySize != uncompressedSize)
912*f6dc9357SAndroid Build Coastguard Worker   {
913*f6dc9357SAndroid Build Coastguard Worker     // do we need to support files extracted from SFW-LZMA with additional 8 bytes?
914*f6dc9357SAndroid Build Coastguard Worker     return S_FALSE;
915*f6dc9357SAndroid Build Coastguard Worker   }
916*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
917*f6dc9357SAndroid Build Coastguard Worker }
918*f6dc9357SAndroid Build Coastguard Worker 
919*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::OpenSeq2(ISequentialInStream *stream, IArchiveOpenCallback *callback)
920*f6dc9357SAndroid Build Coastguard Worker {
921*f6dc9357SAndroid Build Coastguard Worker   HRESULT res;
922*f6dc9357SAndroid Build Coastguard Worker   try { res = OpenSeq3(stream, callback); }
923*f6dc9357SAndroid Build Coastguard Worker   catch(...) { res = S_FALSE; }
924*f6dc9357SAndroid Build Coastguard Worker   return res;
925*f6dc9357SAndroid Build Coastguard Worker }
926*f6dc9357SAndroid Build Coastguard Worker 
927*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::OpenSeq(ISequentialInStream *stream))
928*f6dc9357SAndroid Build Coastguard Worker {
929*f6dc9357SAndroid Build Coastguard Worker   return OpenSeq2(stream, NULL);
930*f6dc9357SAndroid Build Coastguard Worker }
931*f6dc9357SAndroid Build Coastguard Worker 
932*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close())
933*f6dc9357SAndroid Build Coastguard Worker {
934*f6dc9357SAndroid Build Coastguard Worker   _phySize = 0;
935*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
936*f6dc9357SAndroid Build Coastguard Worker }
937*f6dc9357SAndroid Build Coastguard Worker 
938*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems,
939*f6dc9357SAndroid Build Coastguard Worker     Int32 testMode, IArchiveExtractCallback *extractCallback))
940*f6dc9357SAndroid Build Coastguard Worker {
941*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_BEGIN
942*f6dc9357SAndroid Build Coastguard Worker   const bool allFilesMode = (numItems == (UInt32)(Int32)-1);
943*f6dc9357SAndroid Build Coastguard Worker   if (allFilesMode)
944*f6dc9357SAndroid Build Coastguard Worker     numItems = _tags.Size();
945*f6dc9357SAndroid Build Coastguard Worker   if (numItems == 0)
946*f6dc9357SAndroid Build Coastguard Worker     return S_OK;
947*f6dc9357SAndroid Build Coastguard Worker   UInt64 totalSize = 0;
948*f6dc9357SAndroid Build Coastguard Worker   UInt32 i;
949*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
950*f6dc9357SAndroid Build Coastguard Worker     totalSize += _tags[allFilesMode ? i : indices[i]].Buf.Size();
951*f6dc9357SAndroid Build Coastguard Worker   RINOK(extractCallback->SetTotal(totalSize))
952*f6dc9357SAndroid Build Coastguard Worker 
953*f6dc9357SAndroid Build Coastguard Worker   CLocalProgress *lps = new CLocalProgress;
954*f6dc9357SAndroid Build Coastguard Worker   CMyComPtr<ICompressProgressInfo> progress = lps;
955*f6dc9357SAndroid Build Coastguard Worker   lps->Init(extractCallback, false);
956*f6dc9357SAndroid Build Coastguard Worker 
957*f6dc9357SAndroid Build Coastguard Worker   totalSize = 0;
958*f6dc9357SAndroid Build Coastguard Worker 
959*f6dc9357SAndroid Build Coastguard Worker   for (i = 0; i < numItems; i++)
960*f6dc9357SAndroid Build Coastguard Worker   {
961*f6dc9357SAndroid Build Coastguard Worker     lps->InSize = lps->OutSize = totalSize;
962*f6dc9357SAndroid Build Coastguard Worker     RINOK(lps->SetCur())
963*f6dc9357SAndroid Build Coastguard Worker     const Int32 askMode = testMode ?
964*f6dc9357SAndroid Build Coastguard Worker         NExtract::NAskMode::kTest :
965*f6dc9357SAndroid Build Coastguard Worker         NExtract::NAskMode::kExtract;
966*f6dc9357SAndroid Build Coastguard Worker     const UInt32 index = allFilesMode ? i : indices[i];
967*f6dc9357SAndroid Build Coastguard Worker     const CByteBuffer &buf = _tags[index].Buf;
968*f6dc9357SAndroid Build Coastguard Worker     totalSize += buf.Size();
969*f6dc9357SAndroid Build Coastguard Worker 
970*f6dc9357SAndroid Build Coastguard Worker     CMyComPtr<ISequentialOutStream> outStream;
971*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->GetStream(index, &outStream, askMode))
972*f6dc9357SAndroid Build Coastguard Worker     if (!testMode && !outStream)
973*f6dc9357SAndroid Build Coastguard Worker       continue;
974*f6dc9357SAndroid Build Coastguard Worker 
975*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->PrepareOperation(askMode))
976*f6dc9357SAndroid Build Coastguard Worker     if (outStream)
977*f6dc9357SAndroid Build Coastguard Worker       RINOK(WriteStream(outStream, buf, buf.Size()))
978*f6dc9357SAndroid Build Coastguard Worker     outStream.Release();
979*f6dc9357SAndroid Build Coastguard Worker     RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK))
980*f6dc9357SAndroid Build Coastguard Worker   }
981*f6dc9357SAndroid Build Coastguard Worker   return S_OK;
982*f6dc9357SAndroid Build Coastguard Worker   COM_TRY_END
983*f6dc9357SAndroid Build Coastguard Worker }
984*f6dc9357SAndroid Build Coastguard Worker 
985*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = { 'F', 'W', 'S' };
986*f6dc9357SAndroid Build Coastguard Worker 
987*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I(
988*f6dc9357SAndroid Build Coastguard Worker   "SWF", "swf", NULL, 0xD7,
989*f6dc9357SAndroid Build Coastguard Worker   k_Signature,
990*f6dc9357SAndroid Build Coastguard Worker   0,
991*f6dc9357SAndroid Build Coastguard Worker   NArcInfoFlags::kKeepName,
992*f6dc9357SAndroid Build Coastguard Worker   NSwfc::IsArc_Swf)
993*f6dc9357SAndroid Build Coastguard Worker 
994*f6dc9357SAndroid Build Coastguard Worker }}
995