Mercurial > vba-linux
diff src/win32/7zip/7z/CPP/7zip/Archive/Lzh/LzhHandler.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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/Lzh/LzhHandler.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,387 @@ 1.4 +// LzhHandler.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Common/ComTry.h" 1.9 +#include "Common/Defs.h" 1.10 +#include "Common/StringConvert.h" 1.11 + 1.12 +#include "Windows/PropVariant.h" 1.13 +#include "Windows/Time.h" 1.14 + 1.15 +#include "LzhHandler.h" 1.16 +#include "LzhOutStreamWithCRC.h" 1.17 + 1.18 +#include "../../ICoder.h" 1.19 + 1.20 +#include "../../Common/LimitedStreams.h" 1.21 +#include "../../Common/ProgressUtils.h" 1.22 + 1.23 +#include "../../Compress/CopyCoder.h" 1.24 +#include "../../Compress/LzhDecoder.h" 1.25 + 1.26 +#include "../Common/ItemNameUtils.h" 1.27 + 1.28 +using namespace NWindows; 1.29 +using namespace NTime; 1.30 + 1.31 +namespace NArchive { 1.32 +namespace NLzh{ 1.33 + 1.34 +struct COsPair 1.35 +{ 1.36 + Byte Id; 1.37 + const wchar_t *Name; 1.38 +}; 1.39 + 1.40 +COsPair g_OsPairs[] = 1.41 +{ 1.42 + { 'M', L"MS-DOS" }, 1.43 + { '2', L"OS/2" }, 1.44 + { '9', L"OS9" }, 1.45 + { 'K', L"OS/68K" }, 1.46 + { '3', L"OS/386" }, 1.47 + { 'H', L"HUMAN" }, 1.48 + { 'U', L"UNIX" }, 1.49 + { 'C', L"CP/M" }, 1.50 + { 'F', L"FLEX" }, 1.51 + { 'm', L"Mac" }, 1.52 + { 'R', L"Runser" }, 1.53 + { 'T', L"TownsOS" }, 1.54 + { 'X', L"XOSK" }, 1.55 + { 'w', L"Windows95" }, 1.56 + { 'W', L"WindowsNT" }, 1.57 + { 0, L"MS-DOS" }, 1.58 + { 'J', L"Java VM" } 1.59 +}; 1.60 + 1.61 +const wchar_t *kUnknownOS = L"Unknown"; 1.62 + 1.63 +const int kNumHostOSes = sizeof(g_OsPairs) / sizeof(g_OsPairs[0]); 1.64 + 1.65 +static const wchar_t *GetOS(Byte osId) 1.66 +{ 1.67 + for (int i = 0; i < kNumHostOSes; i++) 1.68 + if (g_OsPairs[i].Id == osId) 1.69 + return g_OsPairs[i].Name; 1.70 + return kUnknownOS; 1.71 +}; 1.72 + 1.73 +STATPROPSTG kProps[] = 1.74 +{ 1.75 + { NULL, kpidPath, VT_BSTR}, 1.76 + { NULL, kpidIsDir, VT_BOOL}, 1.77 + { NULL, kpidSize, VT_UI8}, 1.78 + { NULL, kpidPackSize, VT_UI8}, 1.79 + { NULL, kpidMTime, VT_FILETIME}, 1.80 + { NULL, kpidAttrib, VT_UI4}, 1.81 + 1.82 + // { NULL, kpidCommented, VT_BOOL}, 1.83 + 1.84 + { NULL, kpidCRC, VT_UI4}, 1.85 + 1.86 + { NULL, kpidMethod, VT_UI1}, 1.87 + { NULL, kpidHostOS, VT_BSTR} 1.88 + 1.89 +}; 1.90 + 1.91 +IMP_IInArchive_Props 1.92 +IMP_IInArchive_ArcProps_NO 1.93 + 1.94 +CHandler::CHandler() {} 1.95 + 1.96 +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) 1.97 +{ 1.98 + *numItems = _items.Size(); 1.99 + return S_OK; 1.100 +} 1.101 + 1.102 +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) 1.103 +{ 1.104 + COM_TRY_BEGIN 1.105 + NWindows::NCOM::CPropVariant prop; 1.106 + const CItemEx &item = _items[index]; 1.107 + switch(propID) 1.108 + { 1.109 + case kpidPath: 1.110 + { 1.111 + UString s = NItemName::WinNameToOSName(MultiByteToUnicodeString(item.GetName(), CP_OEMCP)); 1.112 + if (!s.IsEmpty()) 1.113 + { 1.114 + if (s[s.Length() - 1] == WCHAR_PATH_SEPARATOR) 1.115 + s.Delete(s.Length() - 1); 1.116 + prop = s; 1.117 + } 1.118 + break; 1.119 + } 1.120 + case kpidIsDir: prop = item.IsDir(); break; 1.121 + case kpidSize: prop = item.Size; break; 1.122 + case kpidPackSize: prop = item.PackSize; break; 1.123 + case kpidCRC: prop = (UInt32)item.CRC; break; 1.124 + case kpidHostOS: prop = GetOS(item.OsId); break; 1.125 + case kpidMTime: 1.126 + { 1.127 + FILETIME utcFileTime; 1.128 + UInt32 unixTime; 1.129 + if (item.GetUnixTime(unixTime)) 1.130 + NTime::UnixTimeToFileTime(unixTime, utcFileTime); 1.131 + else 1.132 + { 1.133 + FILETIME localFileTime; 1.134 + if (DosTimeToFileTime(item.ModifiedTime, localFileTime)) 1.135 + { 1.136 + if (!LocalFileTimeToFileTime(&localFileTime, &utcFileTime)) 1.137 + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; 1.138 + } 1.139 + else 1.140 + utcFileTime.dwHighDateTime = utcFileTime.dwLowDateTime = 0; 1.141 + } 1.142 + prop = utcFileTime; 1.143 + break; 1.144 + } 1.145 + /* 1.146 + case kpidAttrib: prop = (UInt32)item.Attributes; break; 1.147 + case kpidCommented: prop = item.IsCommented(); break; 1.148 + */ 1.149 + case kpidMethod: 1.150 + { 1.151 + wchar_t method2[kMethodIdSize + 1]; 1.152 + method2[kMethodIdSize] = 0; 1.153 + for (int i = 0; i < kMethodIdSize; i++) 1.154 + method2[i] = item.Method[i]; 1.155 + prop = method2; 1.156 + break; 1.157 + } 1.158 + } 1.159 + prop.Detach(value); 1.160 + return S_OK; 1.161 + COM_TRY_END 1.162 +} 1.163 + 1.164 +/* 1.165 +class CProgressImp: public CProgressVirt 1.166 +{ 1.167 +public: 1.168 + CMyComPtr<IArchiveOpenCallback> Callback; 1.169 + STDMETHOD(SetCompleted)(const UInt64 *numFiles); 1.170 +}; 1.171 + 1.172 +STDMETHODIMP CProgressImp::SetCompleted(const UInt64 *numFiles) 1.173 +{ 1.174 + if (Callback) 1.175 + return Callback->SetCompleted(numFiles, NULL); 1.176 + return S_OK; 1.177 +} 1.178 +*/ 1.179 + 1.180 +STDMETHODIMP CHandler::Open(IInStream *stream, 1.181 + const UInt64 * /* maxCheckStartPosition */, IArchiveOpenCallback *callback) 1.182 +{ 1.183 + COM_TRY_BEGIN 1.184 + try 1.185 + { 1.186 + _items.Clear(); 1.187 + CInArchive archive; 1.188 + 1.189 + UInt64 endPos = 0; 1.190 + bool needSetTotal = true; 1.191 + 1.192 + if (callback != NULL) 1.193 + { 1.194 + RINOK(stream->Seek(0, STREAM_SEEK_END, &endPos)); 1.195 + RINOK(stream->Seek(0, STREAM_SEEK_SET, NULL)); 1.196 + } 1.197 + 1.198 + RINOK(archive.Open(stream)); 1.199 + for (;;) 1.200 + { 1.201 + CItemEx item; 1.202 + bool filled; 1.203 + HRESULT result = archive.GetNextItem(filled, item); 1.204 + if (result == S_FALSE) 1.205 + return S_FALSE; 1.206 + if (result != S_OK) 1.207 + return S_FALSE; 1.208 + if (!filled) 1.209 + break; 1.210 + _items.Add(item); 1.211 + archive.Skeep(item.PackSize); 1.212 + if (callback != NULL) 1.213 + { 1.214 + if (needSetTotal) 1.215 + { 1.216 + RINOK(callback->SetTotal(NULL, &endPos)); 1.217 + needSetTotal = false; 1.218 + } 1.219 + if (_items.Size() % 100 == 0) 1.220 + { 1.221 + UInt64 numFiles = _items.Size(); 1.222 + UInt64 numBytes = item.DataPosition; 1.223 + RINOK(callback->SetCompleted(&numFiles, &numBytes)); 1.224 + } 1.225 + } 1.226 + } 1.227 + if (_items.IsEmpty()) 1.228 + return S_FALSE; 1.229 + 1.230 + _stream = stream; 1.231 + } 1.232 + catch(...) 1.233 + { 1.234 + return S_FALSE; 1.235 + } 1.236 + COM_TRY_END 1.237 + return S_OK; 1.238 +} 1.239 + 1.240 +STDMETHODIMP CHandler::Close() 1.241 +{ 1.242 + _items.Clear(); 1.243 + _stream.Release(); 1.244 + return S_OK; 1.245 +} 1.246 + 1.247 + 1.248 + 1.249 +////////////////////////////////////// 1.250 +// CHandler::DecompressItems 1.251 + 1.252 +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, 1.253 + Int32 testModeSpec, IArchiveExtractCallback *extractCallback) 1.254 +{ 1.255 + COM_TRY_BEGIN 1.256 + bool testMode = (testModeSpec != 0); 1.257 + UInt64 totalUnPacked = 0, totalPacked = 0; 1.258 + bool allFilesMode = (numItems == UInt32(-1)); 1.259 + if (allFilesMode) 1.260 + numItems = _items.Size(); 1.261 + if(numItems == 0) 1.262 + return S_OK; 1.263 + UInt32 i; 1.264 + for(i = 0; i < numItems; i++) 1.265 + { 1.266 + const CItemEx &item = _items[allFilesMode ? i : indices[i]]; 1.267 + totalUnPacked += item.Size; 1.268 + totalPacked += item.PackSize; 1.269 + } 1.270 + extractCallback->SetTotal(totalUnPacked); 1.271 + 1.272 + UInt64 currentTotalUnPacked = 0, currentTotalPacked = 0; 1.273 + UInt64 currentItemUnPacked, currentItemPacked; 1.274 + 1.275 + NCompress::NLzh::NDecoder::CCoder *lzhDecoderSpec = 0; 1.276 + CMyComPtr<ICompressCoder> lzhDecoder; 1.277 + CMyComPtr<ICompressCoder> lzh1Decoder; 1.278 + CMyComPtr<ICompressCoder> arj2Decoder; 1.279 + 1.280 + NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder(); 1.281 + CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; 1.282 + 1.283 + CLocalProgress *lps = new CLocalProgress; 1.284 + CMyComPtr<ICompressProgressInfo> progress = lps; 1.285 + lps->Init(extractCallback, false); 1.286 + 1.287 + CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream; 1.288 + CMyComPtr<ISequentialInStream> inStream(streamSpec); 1.289 + streamSpec->SetStream(_stream); 1.290 + 1.291 + for(i = 0; i < numItems; i++, currentTotalUnPacked += currentItemUnPacked, 1.292 + currentTotalPacked += currentItemPacked) 1.293 + { 1.294 + currentItemUnPacked = 0; 1.295 + currentItemPacked = 0; 1.296 + 1.297 + lps->InSize = currentTotalPacked; 1.298 + lps->OutSize = currentTotalUnPacked; 1.299 + RINOK(lps->SetCur()); 1.300 + 1.301 + CMyComPtr<ISequentialOutStream> realOutStream; 1.302 + Int32 askMode; 1.303 + askMode = testMode ? NExtract::NAskMode::kTest : 1.304 + NExtract::NAskMode::kExtract; 1.305 + Int32 index = allFilesMode ? i : indices[i]; 1.306 + const CItemEx &item = _items[index]; 1.307 + RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); 1.308 + 1.309 + if (item.IsDir()) 1.310 + { 1.311 + // if (!testMode) 1.312 + { 1.313 + RINOK(extractCallback->PrepareOperation(askMode)); 1.314 + RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)); 1.315 + } 1.316 + continue; 1.317 + } 1.318 + 1.319 + if (!testMode && (!realOutStream)) 1.320 + continue; 1.321 + 1.322 + RINOK(extractCallback->PrepareOperation(askMode)); 1.323 + currentItemUnPacked = item.Size; 1.324 + currentItemPacked = item.PackSize; 1.325 + 1.326 + { 1.327 + COutStreamWithCRC *outStreamSpec = new COutStreamWithCRC; 1.328 + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); 1.329 + outStreamSpec->Init(realOutStream); 1.330 + realOutStream.Release(); 1.331 + 1.332 + UInt64 pos; 1.333 + _stream->Seek(item.DataPosition, STREAM_SEEK_SET, &pos); 1.334 + 1.335 + streamSpec->Init(item.PackSize); 1.336 + 1.337 + HRESULT result = S_OK; 1.338 + Int32 opRes = NExtract::NOperationResult::kOK; 1.339 + 1.340 + if (item.IsCopyMethod()) 1.341 + { 1.342 + result = copyCoder->Code(inStream, outStream, NULL, NULL, progress); 1.343 + if (result == S_OK && copyCoderSpec->TotalSize != item.PackSize) 1.344 + result = S_FALSE; 1.345 + } 1.346 + else if (item.IsLh4GroupMethod()) 1.347 + { 1.348 + if (!lzhDecoder) 1.349 + { 1.350 + lzhDecoderSpec = new NCompress::NLzh::NDecoder::CCoder; 1.351 + lzhDecoder = lzhDecoderSpec; 1.352 + } 1.353 + lzhDecoderSpec->SetDictionary(item.GetNumDictBits()); 1.354 + result = lzhDecoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); 1.355 + } 1.356 + /* 1.357 + else if (item.IsLh1GroupMethod()) 1.358 + { 1.359 + if (!lzh1Decoder) 1.360 + { 1.361 + lzh1DecoderSpec = new NCompress::NLzh1::NDecoder::CCoder; 1.362 + lzh1Decoder = lzh1DecoderSpec; 1.363 + } 1.364 + lzh1DecoderSpec->SetDictionary(item.GetNumDictBits()); 1.365 + result = lzh1Decoder->Code(inStream, outStream, NULL, ¤tItemUnPacked, progress); 1.366 + } 1.367 + */ 1.368 + else 1.369 + opRes = NExtract::NOperationResult::kUnSupportedMethod; 1.370 + 1.371 + if (opRes == NExtract::NOperationResult::kOK) 1.372 + { 1.373 + if (result == S_FALSE) 1.374 + opRes = NExtract::NOperationResult::kDataError; 1.375 + else 1.376 + { 1.377 + RINOK(result); 1.378 + if (outStreamSpec->GetCRC() != item.CRC) 1.379 + opRes = NExtract::NOperationResult::kCRCError; 1.380 + } 1.381 + } 1.382 + outStream.Release(); 1.383 + RINOK(extractCallback->SetOperationResult(opRes)); 1.384 + } 1.385 + } 1.386 + return S_OK; 1.387 + COM_TRY_END 1.388 +} 1.389 + 1.390 +}}