Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/GZip/GZipHandler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // GZipHandler.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "GZipHandler.h" | |
6 | |
7 #include "Common/Defs.h" | |
8 #include "Common/StringConvert.h" | |
9 #include "Common/ComTry.h" | |
10 #include "Windows/PropVariant.h" | |
11 #include "Windows/Time.h" | |
12 | |
13 #include "../../ICoder.h" | |
14 #include "../../Common/ProgressUtils.h" | |
15 #include "../../Common/CreateCoder.h" | |
16 #include "../Common/OutStreamWithCRC.h" | |
17 | |
18 using namespace NWindows; | |
19 | |
20 namespace NArchive { | |
21 namespace NGZip { | |
22 | |
23 static const CMethodId kMethodId_Deflate = 0x040108; | |
24 | |
25 const wchar_t *kHostOS[] = | |
26 { | |
27 L"FAT", | |
28 L"AMIGA", | |
29 L"VMS", | |
30 L"Unix", | |
31 L"VM_CMS", | |
32 L"Atari", // what if it's a minix filesystem? [cjh] | |
33 L"HPFS", // filesystem used by OS/2 (and NT 3.x) | |
34 L"Mac", | |
35 L"Z_System", | |
36 L"CPM", | |
37 L"TOPS20", // pkzip 2.50 NTFS | |
38 L"NTFS", // filesystem used by Windows NT | |
39 L"QDOS ", // SMS/QDOS | |
40 L"Acorn", // Archimedes Acorn RISC OS | |
41 L"VFAT", // filesystem used by Windows 95, NT | |
42 L"MVS", | |
43 L"BeOS", // hybrid POSIX/database filesystem | |
44 // BeBOX or PowerMac | |
45 L"Tandem", | |
46 L"THEOS" | |
47 }; | |
48 | |
49 static const int kNumHostOSes = sizeof(kHostOS) / sizeof(kHostOS[0]); | |
50 | |
51 static const wchar_t *kUnknownOS = L"Unknown"; | |
52 | |
53 /* | |
54 enum // PropID | |
55 { | |
56 kpidExtraIsPresent = kpidUserDefined, | |
57 kpidExtraFlags, | |
58 kpidIsText | |
59 }; | |
60 */ | |
61 | |
62 STATPROPSTG kProps[] = | |
63 { | |
64 { NULL, kpidPath, VT_BSTR}, | |
65 { NULL, kpidSize, VT_UI8}, | |
66 { NULL, kpidPackSize, VT_UI8}, | |
67 { NULL, kpidMTime, VT_FILETIME}, | |
68 // { NULL, kpidMethod, VT_UI1}, | |
69 { NULL, kpidHostOS, VT_BSTR}, | |
70 { NULL, kpidCRC, VT_UI4} | |
71 // { L"Extra", kpidExtraIsPresent, VT_BOOL} | |
72 // { L"Extra flags", kpidExtraFlags, VT_UI1}, | |
73 // { L"Is Text", kpidIsText, VT_BOOL}, | |
74 }; | |
75 | |
76 IMP_IInArchive_Props | |
77 IMP_IInArchive_ArcProps_NO | |
78 | |
79 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
80 { | |
81 *numItems = 1; | |
82 return S_OK; | |
83 } | |
84 | |
85 STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) | |
86 { | |
87 COM_TRY_BEGIN | |
88 NWindows::NCOM::CPropVariant prop; | |
89 switch(propID) | |
90 { | |
91 case kpidPath: | |
92 if (m_Item.NameIsPresent()) | |
93 prop = MultiByteToUnicodeString(m_Item.Name, CP_ACP); | |
94 break; | |
95 case kpidMTime: | |
96 { | |
97 FILETIME utcTime; | |
98 if (m_Item.Time != 0) | |
99 { | |
100 NTime::UnixTimeToFileTime((UInt32)m_Item.Time, utcTime); | |
101 prop = utcTime; | |
102 } | |
103 else | |
104 { | |
105 // utcTime.dwLowDateTime = utcTime.dwHighDateTime = 0; | |
106 // prop = utcTime; | |
107 } | |
108 break; | |
109 } | |
110 case kpidSize: prop = UInt64(m_Item.UnPackSize32); break; | |
111 case kpidPackSize: prop = m_PackSize; break; | |
112 case kpidCommented: prop = m_Item.CommentIsPresent(); break; | |
113 case kpidHostOS: | |
114 prop = (m_Item.HostOS < kNumHostOSes) ? | |
115 kHostOS[m_Item.HostOS] : kUnknownOS; | |
116 break; | |
117 case kpidMethod: prop = m_Item.CompressionMethod; break; | |
118 case kpidCRC: prop = m_Item.FileCRC; break; | |
119 /* | |
120 case kpidExtraFlags: prop = m_Item.ExtraFlags; break; | |
121 case kpidIsText: prop = m_Item.IsText(); break; | |
122 case kpidExtraIsPresent: prop = m_Item.ExtraFieldIsPresent(); break; | |
123 */ | |
124 } | |
125 prop.Detach(value); | |
126 return S_OK; | |
127 COM_TRY_END | |
128 } | |
129 | |
130 STDMETHODIMP CHandler::Open(IInStream *inStream, | |
131 const UInt64 * /* maxCheckStartPosition */, | |
132 IArchiveOpenCallback * /* openArchiveCallback */) | |
133 { | |
134 COM_TRY_BEGIN | |
135 try | |
136 { | |
137 CInArchive archive; | |
138 RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); | |
139 RINOK(archive.ReadHeader(inStream, m_Item)); | |
140 m_DataOffset = archive.GetOffset(); | |
141 UInt64 newPosition; | |
142 RINOK(inStream->Seek(-8, STREAM_SEEK_END, &newPosition)); | |
143 m_PackSize = newPosition - (m_StreamStartPosition + m_DataOffset); | |
144 if (archive.ReadPostHeader(inStream, m_Item) != S_OK) | |
145 return S_FALSE; | |
146 m_Stream = inStream; | |
147 } | |
148 catch(...) | |
149 { | |
150 return S_FALSE; | |
151 } | |
152 return S_OK; | |
153 COM_TRY_END | |
154 } | |
155 | |
156 STDMETHODIMP CHandler::Close() | |
157 { | |
158 m_Stream.Release(); | |
159 return S_OK; | |
160 } | |
161 | |
162 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
163 Int32 _aTestMode, IArchiveExtractCallback *extractCallback) | |
164 { | |
165 COM_TRY_BEGIN | |
166 bool allFilesMode = (numItems == UInt32(-1)); | |
167 if (!allFilesMode) | |
168 { | |
169 if (numItems == 0) | |
170 return S_OK; | |
171 if (numItems != 1) | |
172 return E_INVALIDARG; | |
173 if (indices[0] != 0) | |
174 return E_INVALIDARG; | |
175 } | |
176 | |
177 bool testMode = (_aTestMode != 0); | |
178 | |
179 extractCallback->SetTotal(m_PackSize); | |
180 | |
181 UInt64 currentTotalPacked = 0; | |
182 | |
183 RINOK(extractCallback->SetCompleted(¤tTotalPacked)); | |
184 CMyComPtr<ISequentialOutStream> realOutStream; | |
185 Int32 askMode; | |
186 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : | |
187 NArchive::NExtract::NAskMode::kExtract; | |
188 | |
189 RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); | |
190 | |
191 if(!testMode && !realOutStream) | |
192 return S_OK; | |
193 | |
194 extractCallback->PrepareOperation(askMode); | |
195 | |
196 COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; | |
197 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | |
198 outStreamSpec->SetStream(realOutStream); | |
199 outStreamSpec->Init(); | |
200 realOutStream.Release(); | |
201 | |
202 CLocalProgress *lps = new CLocalProgress; | |
203 CMyComPtr<ICompressProgressInfo> progress = lps; | |
204 lps->Init(extractCallback, true); | |
205 | |
206 CMyComPtr<ICompressCoder> deflateDecoder; | |
207 bool firstItem = true; | |
208 RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); | |
209 Int32 opRes; | |
210 for (;;) | |
211 { | |
212 lps->InSize = currentTotalPacked; | |
213 lps->OutSize = outStreamSpec->GetSize(); | |
214 | |
215 CInArchive archive; | |
216 CItem item; | |
217 HRESULT result = archive.ReadHeader(m_Stream, item); | |
218 if (result != S_OK) | |
219 { | |
220 if (firstItem) | |
221 return E_FAIL; | |
222 opRes = NArchive::NExtract::NOperationResult::kOK; | |
223 break; | |
224 } | |
225 firstItem = false; | |
226 | |
227 UInt64 dataStartPos; | |
228 RINOK(m_Stream->Seek(0, STREAM_SEEK_CUR, &dataStartPos)); | |
229 | |
230 outStreamSpec->InitCRC(); | |
231 | |
232 if (item.CompressionMethod != NFileHeader::NCompressionMethod::kDeflate) | |
233 { | |
234 opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; | |
235 break; | |
236 } | |
237 | |
238 if (!deflateDecoder) | |
239 { | |
240 RINOK(CreateCoder( | |
241 EXTERNAL_CODECS_VARS | |
242 kMethodId_Deflate, deflateDecoder, false)); | |
243 if (!deflateDecoder) | |
244 { | |
245 opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; | |
246 break; | |
247 } | |
248 } | |
249 result = deflateDecoder->Code(m_Stream, outStream, NULL, NULL, progress); | |
250 if (result != S_OK) | |
251 { | |
252 if (result != S_FALSE) | |
253 return result; | |
254 opRes = NArchive::NExtract::NOperationResult::kDataError; | |
255 break; | |
256 } | |
257 | |
258 CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; | |
259 RINOK(deflateDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, | |
260 &getInStreamProcessedSize)); | |
261 UInt64 packSize; | |
262 RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize)); | |
263 UInt64 pos; | |
264 RINOK(m_Stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos)); | |
265 | |
266 currentTotalPacked = pos - m_StreamStartPosition; | |
267 | |
268 CItem postItem; | |
269 if (archive.ReadPostHeader(m_Stream, postItem) != S_OK) | |
270 return E_FAIL; | |
271 if((outStreamSpec->GetCRC() != postItem.FileCRC)) | |
272 { | |
273 opRes = NArchive::NExtract::NOperationResult::kCRCError; | |
274 break; | |
275 } | |
276 } | |
277 outStream.Release(); | |
278 return extractCallback->SetOperationResult(opRes); | |
279 COM_TRY_END | |
280 } | |
281 | |
282 IMPL_ISetCompressCodecsInfo | |
283 | |
284 }} |