Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/7z/7zHandler.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 // 7zHandler.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 extern "C" | |
6 { | |
7 #include "../../../../C/CpuArch.h" | |
8 } | |
9 | |
10 #include "../../../Common/ComTry.h" | |
11 #include "../../../Common/IntToString.h" | |
12 | |
13 #ifdef COMPRESS_MT | |
14 #include "../../../Windows/System.h" | |
15 #endif | |
16 | |
17 #include "../Common/ItemNameUtils.h" | |
18 | |
19 #include "7zHandler.h" | |
20 #include "7zProperties.h" | |
21 | |
22 #ifdef __7Z_SET_PROPERTIES | |
23 #ifdef EXTRACT_ONLY | |
24 #include "../Common/ParseProperties.h" | |
25 #endif | |
26 #endif | |
27 | |
28 using namespace NWindows; | |
29 | |
30 extern UString ConvertMethodIdToString(UInt64 id); | |
31 | |
32 namespace NArchive { | |
33 namespace N7z { | |
34 | |
35 CHandler::CHandler() | |
36 { | |
37 _crcSize = 4; | |
38 | |
39 #ifndef _NO_CRYPTO | |
40 _passwordIsDefined = false; | |
41 #endif | |
42 | |
43 #ifdef EXTRACT_ONLY | |
44 #ifdef COMPRESS_MT | |
45 _numThreads = NSystem::GetNumberOfProcessors(); | |
46 #endif | |
47 #else | |
48 Init(); | |
49 #endif | |
50 } | |
51 | |
52 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
53 { | |
54 *numItems = _db.Files.Size(); | |
55 return S_OK; | |
56 } | |
57 | |
58 #ifdef _SFX | |
59 | |
60 IMP_IInArchive_ArcProps_NO | |
61 | |
62 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */) | |
63 { | |
64 return E_NOTIMPL; | |
65 } | |
66 | |
67 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */, | |
68 BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */) | |
69 { | |
70 return E_NOTIMPL; | |
71 } | |
72 | |
73 | |
74 #else | |
75 | |
76 STATPROPSTG kArcProps[] = | |
77 { | |
78 { NULL, kpidMethod, VT_BSTR}, | |
79 { NULL, kpidSolid, VT_BOOL}, | |
80 { NULL, kpidNumBlocks, VT_UI4}, | |
81 { NULL, kpidPhySize, VT_UI8}, | |
82 { NULL, kpidHeadersSize, VT_UI8}, | |
83 { NULL, kpidOffset, VT_UI8} | |
84 }; | |
85 | |
86 STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value) | |
87 { | |
88 COM_TRY_BEGIN | |
89 NCOM::CPropVariant prop; | |
90 switch(propID) | |
91 { | |
92 case kpidMethod: | |
93 { | |
94 UString resString; | |
95 CRecordVector<UInt64> ids; | |
96 int i; | |
97 for (i = 0; i < _db.Folders.Size(); i++) | |
98 { | |
99 const CFolder &f = _db.Folders[i]; | |
100 for (int j = f.Coders.Size() - 1; j >= 0; j--) | |
101 ids.AddToUniqueSorted(f.Coders[j].MethodID); | |
102 } | |
103 | |
104 for (i = 0; i < ids.Size(); i++) | |
105 { | |
106 UInt64 id = ids[i]; | |
107 UString methodName; | |
108 /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName); | |
109 if (methodName.IsEmpty()) | |
110 methodName = ConvertMethodIdToString(id); | |
111 if (!resString.IsEmpty()) | |
112 resString += L' '; | |
113 resString += methodName; | |
114 } | |
115 prop = resString; | |
116 break; | |
117 } | |
118 case kpidSolid: prop = _db.IsSolid(); break; | |
119 case kpidNumBlocks: prop = (UInt32)_db.Folders.Size(); break; | |
120 case kpidHeadersSize: prop = _db.HeadersSize; break; | |
121 case kpidPhySize: prop = _db.PhySize; break; | |
122 case kpidOffset: if (_db.ArchiveInfo.StartPosition != 0) prop = _db.ArchiveInfo.StartPosition; break; | |
123 } | |
124 prop.Detach(value); | |
125 return S_OK; | |
126 COM_TRY_END | |
127 } | |
128 | |
129 IMP_IInArchive_ArcProps | |
130 | |
131 #endif | |
132 | |
133 static void SetPropFromUInt64Def(CUInt64DefVector &v, int index, NCOM::CPropVariant &prop) | |
134 { | |
135 UInt64 value; | |
136 if (v.GetItem(index, value)) | |
137 { | |
138 FILETIME ft; | |
139 ft.dwLowDateTime = (DWORD)value; | |
140 ft.dwHighDateTime = (DWORD)(value >> 32); | |
141 prop = ft; | |
142 } | |
143 } | |
144 | |
145 #ifndef _SFX | |
146 | |
147 static UString ConvertUInt32ToString(UInt32 value) | |
148 { | |
149 wchar_t buffer[32]; | |
150 ConvertUInt64ToString(value, buffer); | |
151 return buffer; | |
152 } | |
153 | |
154 static UString GetStringForSizeValue(UInt32 value) | |
155 { | |
156 for (int i = 31; i >= 0; i--) | |
157 if ((UInt32(1) << i) == value) | |
158 return ConvertUInt32ToString(i); | |
159 UString result; | |
160 if (value % (1 << 20) == 0) | |
161 { | |
162 result += ConvertUInt32ToString(value >> 20); | |
163 result += L"m"; | |
164 } | |
165 else if (value % (1 << 10) == 0) | |
166 { | |
167 result += ConvertUInt32ToString(value >> 10); | |
168 result += L"k"; | |
169 } | |
170 else | |
171 { | |
172 result += ConvertUInt32ToString(value); | |
173 result += L"b"; | |
174 } | |
175 return result; | |
176 } | |
177 | |
178 static const UInt64 k_Copy = 0x0; | |
179 static const UInt64 k_LZMA = 0x030101; | |
180 static const UInt64 k_PPMD = 0x030401; | |
181 | |
182 static wchar_t GetHex(Byte value) | |
183 { | |
184 return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10))); | |
185 } | |
186 static inline UString GetHex2(Byte value) | |
187 { | |
188 UString result; | |
189 result += GetHex((Byte)(value >> 4)); | |
190 result += GetHex((Byte)(value & 0xF)); | |
191 return result; | |
192 } | |
193 | |
194 #endif | |
195 | |
196 static const UInt64 k_AES = 0x06F10701; | |
197 | |
198 bool CHandler::IsEncrypted(UInt32 index2) const | |
199 { | |
200 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; | |
201 if (folderIndex != kNumNoIndex) | |
202 { | |
203 const CFolder &folderInfo = _db.Folders[folderIndex]; | |
204 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) | |
205 if (folderInfo.Coders[i].MethodID == k_AES) | |
206 return true; | |
207 } | |
208 return false; | |
209 } | |
210 | |
211 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | |
212 { | |
213 COM_TRY_BEGIN | |
214 NCOM::CPropVariant prop; | |
215 | |
216 /* | |
217 const CRef2 &ref2 = _refs[index]; | |
218 if (ref2.Refs.IsEmpty()) | |
219 return E_FAIL; | |
220 const CRef &ref = ref2.Refs.Front(); | |
221 */ | |
222 | |
223 const CFileItem &item = _db.Files[index]; | |
224 UInt32 index2 = index; | |
225 | |
226 switch(propID) | |
227 { | |
228 case kpidPath: | |
229 if (!item.Name.IsEmpty()) | |
230 prop = NItemName::GetOSName(item.Name); | |
231 break; | |
232 case kpidIsDir: prop = item.IsDir; break; | |
233 case kpidSize: | |
234 { | |
235 prop = item.Size; | |
236 // prop = ref2.Size; | |
237 break; | |
238 } | |
239 case kpidPackSize: | |
240 { | |
241 // prop = ref2.PackSize; | |
242 { | |
243 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; | |
244 if (folderIndex != kNumNoIndex) | |
245 { | |
246 if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2) | |
247 prop = _db.GetFolderFullPackSize(folderIndex); | |
248 /* | |
249 else | |
250 prop = (UInt64)0; | |
251 */ | |
252 } | |
253 else | |
254 prop = (UInt64)0; | |
255 } | |
256 break; | |
257 } | |
258 case kpidPosition: { UInt64 v; if (_db.StartPos.GetItem(index2, v)) prop = v; break; } | |
259 case kpidCTime: SetPropFromUInt64Def(_db.CTime, index2, prop); break; | |
260 case kpidATime: SetPropFromUInt64Def(_db.ATime, index2, prop); break; | |
261 case kpidMTime: SetPropFromUInt64Def(_db.MTime, index2, prop); break; | |
262 case kpidAttrib: if (item.AttribDefined) prop = item.Attrib; break; | |
263 case kpidCRC: if (item.CrcDefined) prop = item.Crc; break; | |
264 case kpidEncrypted: prop = IsEncrypted(index2); break; | |
265 case kpidIsAnti: prop = _db.IsItemAnti(index2); break; | |
266 #ifndef _SFX | |
267 case kpidMethod: | |
268 { | |
269 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; | |
270 if (folderIndex != kNumNoIndex) | |
271 { | |
272 const CFolder &folderInfo = _db.Folders[folderIndex]; | |
273 UString methodsString; | |
274 for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--) | |
275 { | |
276 const CCoderInfo &coderInfo = folderInfo.Coders[i]; | |
277 if (!methodsString.IsEmpty()) | |
278 methodsString += L' '; | |
279 | |
280 { | |
281 UString methodName; | |
282 bool methodIsKnown = FindMethod( | |
283 EXTERNAL_CODECS_VARS | |
284 coderInfo.MethodID, methodName); | |
285 | |
286 if (methodIsKnown) | |
287 { | |
288 methodsString += methodName; | |
289 if (coderInfo.MethodID == k_LZMA) | |
290 { | |
291 if (coderInfo.Props.GetCapacity() >= 5) | |
292 { | |
293 methodsString += L":"; | |
294 UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); | |
295 methodsString += GetStringForSizeValue(dicSize); | |
296 } | |
297 } | |
298 else if (coderInfo.MethodID == k_PPMD) | |
299 { | |
300 if (coderInfo.Props.GetCapacity() >= 5) | |
301 { | |
302 Byte order = *(const Byte *)coderInfo.Props; | |
303 methodsString += L":o"; | |
304 methodsString += ConvertUInt32ToString(order); | |
305 methodsString += L":mem"; | |
306 UInt32 dicSize = GetUi32((const Byte *)coderInfo.Props + 1); | |
307 methodsString += GetStringForSizeValue(dicSize); | |
308 } | |
309 } | |
310 else if (coderInfo.MethodID == k_AES) | |
311 { | |
312 if (coderInfo.Props.GetCapacity() >= 1) | |
313 { | |
314 methodsString += L":"; | |
315 const Byte *data = (const Byte *)coderInfo.Props; | |
316 Byte firstByte = *data++; | |
317 UInt32 numCyclesPower = firstByte & 0x3F; | |
318 methodsString += ConvertUInt32ToString(numCyclesPower); | |
319 /* | |
320 if ((firstByte & 0xC0) != 0) | |
321 { | |
322 methodsString += L":"; | |
323 return S_OK; | |
324 UInt32 saltSize = (firstByte >> 7) & 1; | |
325 UInt32 ivSize = (firstByte >> 6) & 1; | |
326 if (coderInfo.Props.GetCapacity() >= 2) | |
327 { | |
328 Byte secondByte = *data++; | |
329 saltSize += (secondByte >> 4); | |
330 ivSize += (secondByte & 0x0F); | |
331 } | |
332 } | |
333 */ | |
334 } | |
335 } | |
336 else | |
337 { | |
338 if (coderInfo.Props.GetCapacity() > 0) | |
339 { | |
340 methodsString += L":["; | |
341 for (size_t bi = 0; bi < coderInfo.Props.GetCapacity(); bi++) | |
342 { | |
343 if (bi > 5 && bi + 1 < coderInfo.Props.GetCapacity()) | |
344 { | |
345 methodsString += L".."; | |
346 break; | |
347 } | |
348 else | |
349 methodsString += GetHex2(coderInfo.Props[bi]); | |
350 } | |
351 methodsString += L"]"; | |
352 } | |
353 } | |
354 } | |
355 else | |
356 { | |
357 methodsString += ConvertMethodIdToString(coderInfo.MethodID); | |
358 } | |
359 } | |
360 } | |
361 prop = methodsString; | |
362 } | |
363 } | |
364 break; | |
365 case kpidBlock: | |
366 { | |
367 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; | |
368 if (folderIndex != kNumNoIndex) | |
369 prop = (UInt32)folderIndex; | |
370 } | |
371 break; | |
372 case kpidPackedSize0: | |
373 case kpidPackedSize1: | |
374 case kpidPackedSize2: | |
375 case kpidPackedSize3: | |
376 case kpidPackedSize4: | |
377 { | |
378 CNum folderIndex = _db.FileIndexToFolderIndexMap[index2]; | |
379 if (folderIndex != kNumNoIndex) | |
380 { | |
381 const CFolder &folderInfo = _db.Folders[folderIndex]; | |
382 if (_db.FolderStartFileIndex[folderIndex] == (CNum)index2 && | |
383 folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0)) | |
384 { | |
385 prop = _db.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0); | |
386 } | |
387 else | |
388 prop = (UInt64)0; | |
389 } | |
390 else | |
391 prop = (UInt64)0; | |
392 } | |
393 break; | |
394 #endif | |
395 } | |
396 prop.Detach(value); | |
397 return S_OK; | |
398 COM_TRY_END | |
399 } | |
400 | |
401 STDMETHODIMP CHandler::Open(IInStream *stream, | |
402 const UInt64 *maxCheckStartPosition, | |
403 IArchiveOpenCallback *openArchiveCallback) | |
404 { | |
405 COM_TRY_BEGIN | |
406 Close(); | |
407 #ifndef _SFX | |
408 _fileInfoPopIDs.Clear(); | |
409 #endif | |
410 try | |
411 { | |
412 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback; | |
413 | |
414 #ifndef _NO_CRYPTO | |
415 CMyComPtr<ICryptoGetTextPassword> getTextPassword; | |
416 if (openArchiveCallback) | |
417 { | |
418 openArchiveCallbackTemp.QueryInterface( | |
419 IID_ICryptoGetTextPassword, &getTextPassword); | |
420 } | |
421 #endif | |
422 CInArchive archive; | |
423 RINOK(archive.Open(stream, maxCheckStartPosition)); | |
424 #ifndef _NO_CRYPTO | |
425 _passwordIsDefined = false; | |
426 UString password; | |
427 #endif | |
428 HRESULT result = archive.ReadDatabase( | |
429 EXTERNAL_CODECS_VARS | |
430 _db | |
431 #ifndef _NO_CRYPTO | |
432 , getTextPassword, _passwordIsDefined | |
433 #endif | |
434 ); | |
435 RINOK(result); | |
436 _db.Fill(); | |
437 _inStream = stream; | |
438 } | |
439 catch(...) | |
440 { | |
441 Close(); | |
442 return S_FALSE; | |
443 } | |
444 // _inStream = stream; | |
445 #ifndef _SFX | |
446 FillPopIDs(); | |
447 #endif | |
448 return S_OK; | |
449 COM_TRY_END | |
450 } | |
451 | |
452 STDMETHODIMP CHandler::Close() | |
453 { | |
454 COM_TRY_BEGIN | |
455 _inStream.Release(); | |
456 _db.Clear(); | |
457 return S_OK; | |
458 COM_TRY_END | |
459 } | |
460 | |
461 #ifdef __7Z_SET_PROPERTIES | |
462 #ifdef EXTRACT_ONLY | |
463 | |
464 STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties) | |
465 { | |
466 COM_TRY_BEGIN | |
467 #ifdef COMPRESS_MT | |
468 const UInt32 numProcessors = NSystem::GetNumberOfProcessors(); | |
469 _numThreads = numProcessors; | |
470 #endif | |
471 | |
472 for (int i = 0; i < numProperties; i++) | |
473 { | |
474 UString name = names[i]; | |
475 name.MakeUpper(); | |
476 if (name.IsEmpty()) | |
477 return E_INVALIDARG; | |
478 const PROPVARIANT &value = values[i]; | |
479 UInt32 number; | |
480 int index = ParseStringToUInt32(name, number); | |
481 if (index == 0) | |
482 { | |
483 if(name.Left(2).CompareNoCase(L"MT") == 0) | |
484 { | |
485 #ifdef COMPRESS_MT | |
486 RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads)); | |
487 #endif | |
488 continue; | |
489 } | |
490 else | |
491 return E_INVALIDARG; | |
492 } | |
493 } | |
494 return S_OK; | |
495 COM_TRY_END | |
496 } | |
497 | |
498 #endif | |
499 #endif | |
500 | |
501 IMPL_ISetCompressCodecsInfo | |
502 | |
503 }} |