view 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
line wrap: on
line source
1 // 7zHandler.cpp
3 #include "StdAfx.h"
5 extern "C"
6 {
7 #include "../../../../C/CpuArch.h"
8 }
10 #include "../../../Common/ComTry.h"
11 #include "../../../Common/IntToString.h"
13 #ifdef COMPRESS_MT
14 #include "../../../Windows/System.h"
15 #endif
17 #include "../Common/ItemNameUtils.h"
19 #include "7zHandler.h"
20 #include "7zProperties.h"
22 #ifdef __7Z_SET_PROPERTIES
23 #ifdef EXTRACT_ONLY
24 #include "../Common/ParseProperties.h"
25 #endif
26 #endif
28 using namespace NWindows;
30 extern UString ConvertMethodIdToString(UInt64 id);
32 namespace NArchive {
33 namespace N7z {
35 CHandler::CHandler()
36 {
37 _crcSize = 4;
39 #ifndef _NO_CRYPTO
40 _passwordIsDefined = false;
41 #endif
43 #ifdef EXTRACT_ONLY
44 #ifdef COMPRESS_MT
45 _numThreads = NSystem::GetNumberOfProcessors();
46 #endif
47 #else
48 Init();
49 #endif
50 }
52 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
53 {
54 *numItems = _db.Files.Size();
55 return S_OK;
56 }
58 #ifdef _SFX
60 IMP_IInArchive_ArcProps_NO
62 STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
63 {
64 return E_NOTIMPL;
65 }
67 STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,
68 BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
69 {
70 return E_NOTIMPL;
71 }
74 #else
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 };
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 }
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 }
129 IMP_IInArchive_ArcProps
131 #endif
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 }
145 #ifndef _SFX
147 static UString ConvertUInt32ToString(UInt32 value)
148 {
149 wchar_t buffer[32];
150 ConvertUInt64ToString(value, buffer);
151 return buffer;
152 }
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 }
178 static const UInt64 k_Copy = 0x0;
179 static const UInt64 k_LZMA = 0x030101;
180 static const UInt64 k_PPMD = 0x030401;
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 }
194 #endif
196 static const UInt64 k_AES = 0x06F10701;
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 }
211 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
212 {
213 COM_TRY_BEGIN
214 NCOM::CPropVariant prop;
216 /*
217 const CRef2 &ref2 = _refs[index];
218 if (ref2.Refs.IsEmpty())
219 return E_FAIL;
220 const CRef &ref = ref2.Refs.Front();
221 */
223 const CFileItem &item = _db.Files[index];
224 UInt32 index2 = index;
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' ';
280 {
281 UString methodName;
282 bool methodIsKnown = FindMethod(
283 EXTERNAL_CODECS_VARS
284 coderInfo.MethodID, methodName);
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 }
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;
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 }
452 STDMETHODIMP CHandler::Close()
453 {
454 COM_TRY_BEGIN
455 _inStream.Release();
456 _db.Clear();
457 return S_OK;
458 COM_TRY_END
459 }
461 #ifdef __7Z_SET_PROPERTIES
462 #ifdef EXTRACT_ONLY
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
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 }
498 #endif
499 #endif
501 IMPL_ISetCompressCodecsInfo
503 }}