1*f6dc9357SAndroid Build Coastguard Worker // XarHandler.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/Sha256.h" 6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/Sha512.h" 7*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/ComTry.h" 10*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyLinux.h" 11*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/MyXml.h" 12*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/StringToInt.h" 13*f6dc9357SAndroid Build Coastguard Worker #include "../../Common/UTFConvert.h" 14*f6dc9357SAndroid Build Coastguard Worker 15*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/PropVariant.h" 16*f6dc9357SAndroid Build Coastguard Worker #include "../../Windows/TimeUtils.h" 17*f6dc9357SAndroid Build Coastguard Worker 18*f6dc9357SAndroid Build Coastguard Worker #include "../Common/LimitedStreams.h" 19*f6dc9357SAndroid Build Coastguard Worker #include "../Common/ProgressUtils.h" 20*f6dc9357SAndroid Build Coastguard Worker #include "../Common/RegisterArc.h" 21*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamObjects.h" 22*f6dc9357SAndroid Build Coastguard Worker #include "../Common/StreamUtils.h" 23*f6dc9357SAndroid Build Coastguard Worker 24*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/BZip2Decoder.h" 25*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/CopyCoder.h" 26*f6dc9357SAndroid Build Coastguard Worker #include "../Compress/ZlibDecoder.h" 27*f6dc9357SAndroid Build Coastguard Worker 28*f6dc9357SAndroid Build Coastguard Worker #include "Common/OutStreamWithSha1.h" 29*f6dc9357SAndroid Build Coastguard Worker 30*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows; 31*f6dc9357SAndroid Build Coastguard Worker 32*f6dc9357SAndroid Build Coastguard Worker #define XAR_SHOW_RAW 33*f6dc9357SAndroid Build Coastguard Worker 34*f6dc9357SAndroid Build Coastguard Worker #define Get16(p) GetBe16(p) 35*f6dc9357SAndroid Build Coastguard Worker #define Get32(p) GetBe32(p) 36*f6dc9357SAndroid Build Coastguard Worker #define Get64(p) GetBe64(p) 37*f6dc9357SAndroid Build Coastguard Worker 38*f6dc9357SAndroid Build Coastguard Worker namespace NArchive { 39*f6dc9357SAndroid Build Coastguard Worker namespace NXar { 40*f6dc9357SAndroid Build Coastguard Worker 41*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1( 42*f6dc9357SAndroid Build Coastguard Worker CInStreamWithSha256 43*f6dc9357SAndroid Build Coastguard Worker , ISequentialInStream 44*f6dc9357SAndroid Build Coastguard Worker ) 45*f6dc9357SAndroid Build Coastguard Worker bool _sha512Mode; 46*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialInStream> _stream; 47*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 _sha256; 48*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 _sha512; 49*f6dc9357SAndroid Build Coastguard Worker UInt64 _size; 50*f6dc9357SAndroid Build Coastguard Worker Sha256()51*f6dc9357SAndroid Build Coastguard Worker CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; } Sha512()52*f6dc9357SAndroid Build Coastguard Worker CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; } 53*f6dc9357SAndroid Build Coastguard Worker public: 54*f6dc9357SAndroid Build Coastguard Worker CInStreamWithSha256(): 55*f6dc9357SAndroid Build Coastguard Worker _sha256(sizeof(CSha256)), 56*f6dc9357SAndroid Build Coastguard Worker _sha512(sizeof(CSha512)) 57*f6dc9357SAndroid Build Coastguard Worker {} 58*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialInStream *stream) { _stream = stream; } 59*f6dc9357SAndroid Build Coastguard Worker void Init(bool sha512Mode) 60*f6dc9357SAndroid Build Coastguard Worker { 61*f6dc9357SAndroid Build Coastguard Worker _sha512Mode = sha512Mode; 62*f6dc9357SAndroid Build Coastguard Worker _size = 0; 63*f6dc9357SAndroid Build Coastguard Worker if (sha512Mode) 64*f6dc9357SAndroid Build Coastguard Worker Sha512_Init(Sha512(), SHA512_DIGEST_SIZE); 65*f6dc9357SAndroid Build Coastguard Worker else 66*f6dc9357SAndroid Build Coastguard Worker Sha256_Init(Sha256()); 67*f6dc9357SAndroid Build Coastguard Worker } 68*f6dc9357SAndroid Build Coastguard Worker void ReleaseStream() { _stream.Release(); } 69*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize() const { return _size; } 70*f6dc9357SAndroid Build Coastguard Worker void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); } 71*f6dc9357SAndroid Build Coastguard Worker void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); } 72*f6dc9357SAndroid Build Coastguard Worker }; 73*f6dc9357SAndroid Build Coastguard Worker 74*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CInStreamWithSha256::Read(void *data, UInt32 size, UInt32 *processedSize)) 75*f6dc9357SAndroid Build Coastguard Worker { 76*f6dc9357SAndroid Build Coastguard Worker UInt32 realProcessedSize; 77*f6dc9357SAndroid Build Coastguard Worker const HRESULT result = _stream->Read(data, size, &realProcessedSize); 78*f6dc9357SAndroid Build Coastguard Worker _size += realProcessedSize; 79*f6dc9357SAndroid Build Coastguard Worker if (_sha512Mode) 80*f6dc9357SAndroid Build Coastguard Worker Sha512_Update(Sha512(), (const Byte *)data, realProcessedSize); 81*f6dc9357SAndroid Build Coastguard Worker else 82*f6dc9357SAndroid Build Coastguard Worker Sha256_Update(Sha256(), (const Byte *)data, realProcessedSize); 83*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 84*f6dc9357SAndroid Build Coastguard Worker *processedSize = realProcessedSize; 85*f6dc9357SAndroid Build Coastguard Worker return result; 86*f6dc9357SAndroid Build Coastguard Worker } 87*f6dc9357SAndroid Build Coastguard Worker 88*f6dc9357SAndroid Build Coastguard Worker 89*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_NOQIB_1( 90*f6dc9357SAndroid Build Coastguard Worker COutStreamWithSha256 91*f6dc9357SAndroid Build Coastguard Worker , ISequentialOutStream 92*f6dc9357SAndroid Build Coastguard Worker ) 93*f6dc9357SAndroid Build Coastguard Worker bool _sha512Mode; 94*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> _stream; 95*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 _sha256; 96*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer1 _sha512; 97*f6dc9357SAndroid Build Coastguard Worker UInt64 _size; 98*f6dc9357SAndroid Build Coastguard Worker 99*f6dc9357SAndroid Build Coastguard Worker CSha256 *Sha256() { return (CSha256 *)(void *)(Byte *)_sha256; } 100*f6dc9357SAndroid Build Coastguard Worker CSha512 *Sha512() { return (CSha512 *)(void *)(Byte *)_sha512; } 101*f6dc9357SAndroid Build Coastguard Worker public: 102*f6dc9357SAndroid Build Coastguard Worker COutStreamWithSha256(): 103*f6dc9357SAndroid Build Coastguard Worker _sha256(sizeof(CSha256)), 104*f6dc9357SAndroid Build Coastguard Worker _sha512(sizeof(CSha512)) 105*f6dc9357SAndroid Build Coastguard Worker {} 106*f6dc9357SAndroid Build Coastguard Worker void SetStream(ISequentialOutStream *stream) { _stream = stream; } 107*f6dc9357SAndroid Build Coastguard Worker void ReleaseStream() { _stream.Release(); } 108*f6dc9357SAndroid Build Coastguard Worker void Init(bool sha512Mode) 109*f6dc9357SAndroid Build Coastguard Worker { 110*f6dc9357SAndroid Build Coastguard Worker _sha512Mode = sha512Mode; 111*f6dc9357SAndroid Build Coastguard Worker _size = 0; 112*f6dc9357SAndroid Build Coastguard Worker if (sha512Mode) 113*f6dc9357SAndroid Build Coastguard Worker Sha512_Init(Sha512(), SHA512_DIGEST_SIZE); 114*f6dc9357SAndroid Build Coastguard Worker else 115*f6dc9357SAndroid Build Coastguard Worker Sha256_Init(Sha256()); 116*f6dc9357SAndroid Build Coastguard Worker } 117*f6dc9357SAndroid Build Coastguard Worker UInt64 GetSize() const { return _size; } 118*f6dc9357SAndroid Build Coastguard Worker void Final256(Byte *digest) { Sha256_Final(Sha256(), digest); } 119*f6dc9357SAndroid Build Coastguard Worker void Final512(Byte *digest) { Sha512_Final(Sha512(), digest, SHA512_DIGEST_SIZE); } 120*f6dc9357SAndroid Build Coastguard Worker }; 121*f6dc9357SAndroid Build Coastguard Worker 122*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(COutStreamWithSha256::Write(const void *data, UInt32 size, UInt32 *processedSize)) 123*f6dc9357SAndroid Build Coastguard Worker { 124*f6dc9357SAndroid Build Coastguard Worker HRESULT result = S_OK; 125*f6dc9357SAndroid Build Coastguard Worker if (_stream) 126*f6dc9357SAndroid Build Coastguard Worker result = _stream->Write(data, size, &size); 127*f6dc9357SAndroid Build Coastguard Worker // if (_calculate) 128*f6dc9357SAndroid Build Coastguard Worker if (_sha512Mode) 129*f6dc9357SAndroid Build Coastguard Worker Sha512_Update(Sha512(), (const Byte *)data, size); 130*f6dc9357SAndroid Build Coastguard Worker else 131*f6dc9357SAndroid Build Coastguard Worker Sha256_Update(Sha256(), (const Byte *)data, size); 132*f6dc9357SAndroid Build Coastguard Worker _size += size; 133*f6dc9357SAndroid Build Coastguard Worker if (processedSize) 134*f6dc9357SAndroid Build Coastguard Worker *processedSize = size; 135*f6dc9357SAndroid Build Coastguard Worker return result; 136*f6dc9357SAndroid Build Coastguard Worker } 137*f6dc9357SAndroid Build Coastguard Worker 138*f6dc9357SAndroid Build Coastguard Worker // we limit supported xml sizes: 139*f6dc9357SAndroid Build Coastguard Worker // ((size_t)1 << (sizeof(size_t) / 2 + 28)) - (1u << 14); 140*f6dc9357SAndroid Build Coastguard Worker static const size_t kXmlSizeMax = ((size_t)1 << 30) - (1u << 14); 141*f6dc9357SAndroid Build Coastguard Worker static const size_t kXmlPackSizeMax = kXmlSizeMax; 142*f6dc9357SAndroid Build Coastguard Worker 143*f6dc9357SAndroid Build Coastguard Worker #define XAR_CKSUM_NONE 0 144*f6dc9357SAndroid Build Coastguard Worker #define XAR_CKSUM_SHA1 1 145*f6dc9357SAndroid Build Coastguard Worker #define XAR_CKSUM_MD5 2 146*f6dc9357SAndroid Build Coastguard Worker #define XAR_CKSUM_SHA256 3 147*f6dc9357SAndroid Build Coastguard Worker #define XAR_CKSUM_SHA512 4 148*f6dc9357SAndroid Build Coastguard Worker // #define XAR_CKSUM_OTHER 3 149*f6dc9357SAndroid Build Coastguard Worker // fork version of xar can use (3) as special case, 150*f6dc9357SAndroid Build Coastguard Worker // where name of hash is stored as string at the end of header 151*f6dc9357SAndroid Build Coastguard Worker // we do not support such hash still. 152*f6dc9357SAndroid Build Coastguard Worker 153*f6dc9357SAndroid Build Coastguard Worker static const char * const k_ChecksumNames[] = 154*f6dc9357SAndroid Build Coastguard Worker { 155*f6dc9357SAndroid Build Coastguard Worker "NONE" 156*f6dc9357SAndroid Build Coastguard Worker , "SHA1" 157*f6dc9357SAndroid Build Coastguard Worker , "MD5" 158*f6dc9357SAndroid Build Coastguard Worker , "SHA256" 159*f6dc9357SAndroid Build Coastguard Worker , "SHA512" 160*f6dc9357SAndroid Build Coastguard Worker }; 161*f6dc9357SAndroid Build Coastguard Worker 162*f6dc9357SAndroid Build Coastguard Worker static unsigned GetHashSize(int algo) 163*f6dc9357SAndroid Build Coastguard Worker { 164*f6dc9357SAndroid Build Coastguard Worker if (algo <= XAR_CKSUM_NONE || algo > XAR_CKSUM_SHA512) 165*f6dc9357SAndroid Build Coastguard Worker return 0; 166*f6dc9357SAndroid Build Coastguard Worker if (algo == XAR_CKSUM_SHA1) 167*f6dc9357SAndroid Build Coastguard Worker return SHA1_DIGEST_SIZE; 168*f6dc9357SAndroid Build Coastguard Worker return (16u >> XAR_CKSUM_MD5) << algo; 169*f6dc9357SAndroid Build Coastguard Worker } 170*f6dc9357SAndroid Build Coastguard Worker 171*f6dc9357SAndroid Build Coastguard Worker #define METHOD_NAME_ZLIB "zlib" 172*f6dc9357SAndroid Build Coastguard Worker 173*f6dc9357SAndroid Build Coastguard Worker static int Find_ChecksumId_for_Name(const AString &style) 174*f6dc9357SAndroid Build Coastguard Worker { 175*f6dc9357SAndroid Build Coastguard Worker for (unsigned i = 0; i < Z7_ARRAY_SIZE(k_ChecksumNames); i++) 176*f6dc9357SAndroid Build Coastguard Worker { 177*f6dc9357SAndroid Build Coastguard Worker // old xars used upper case in "style" 178*f6dc9357SAndroid Build Coastguard Worker // new xars use lower case in "style" 179*f6dc9357SAndroid Build Coastguard Worker if (style.IsEqualTo_Ascii_NoCase(k_ChecksumNames[i])) 180*f6dc9357SAndroid Build Coastguard Worker return (int)i; 181*f6dc9357SAndroid Build Coastguard Worker } 182*f6dc9357SAndroid Build Coastguard Worker return -1; 183*f6dc9357SAndroid Build Coastguard Worker } 184*f6dc9357SAndroid Build Coastguard Worker 185*f6dc9357SAndroid Build Coastguard Worker 186*f6dc9357SAndroid Build Coastguard Worker struct CCheckSum 187*f6dc9357SAndroid Build Coastguard Worker { 188*f6dc9357SAndroid Build Coastguard Worker int AlgoNumber; 189*f6dc9357SAndroid Build Coastguard Worker bool Error; 190*f6dc9357SAndroid Build Coastguard Worker CByteBuffer Data; 191*f6dc9357SAndroid Build Coastguard Worker AString Style; 192*f6dc9357SAndroid Build Coastguard Worker 193*f6dc9357SAndroid Build Coastguard Worker CCheckSum(): AlgoNumber(-1), Error(false) {} 194*f6dc9357SAndroid Build Coastguard Worker void AddNameToString(AString &s) const; 195*f6dc9357SAndroid Build Coastguard Worker }; 196*f6dc9357SAndroid Build Coastguard Worker 197*f6dc9357SAndroid Build Coastguard Worker void CCheckSum::AddNameToString(AString &s) const 198*f6dc9357SAndroid Build Coastguard Worker { 199*f6dc9357SAndroid Build Coastguard Worker if (Style.IsEmpty()) 200*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced("NO-CHECKSUM"); 201*f6dc9357SAndroid Build Coastguard Worker else 202*f6dc9357SAndroid Build Coastguard Worker { 203*f6dc9357SAndroid Build Coastguard Worker s.Add_OptSpaced(Style); 204*f6dc9357SAndroid Build Coastguard Worker if (Error) 205*f6dc9357SAndroid Build Coastguard Worker s += "-ERROR"; 206*f6dc9357SAndroid Build Coastguard Worker } 207*f6dc9357SAndroid Build Coastguard Worker } 208*f6dc9357SAndroid Build Coastguard Worker 209*f6dc9357SAndroid Build Coastguard Worker 210*f6dc9357SAndroid Build Coastguard Worker struct CFile 211*f6dc9357SAndroid Build Coastguard Worker { 212*f6dc9357SAndroid Build Coastguard Worker bool IsDir; 213*f6dc9357SAndroid Build Coastguard Worker bool Is_SymLink; 214*f6dc9357SAndroid Build Coastguard Worker bool HasData; 215*f6dc9357SAndroid Build Coastguard Worker bool Mode_Defined; 216*f6dc9357SAndroid Build Coastguard Worker bool INode_Defined; 217*f6dc9357SAndroid Build Coastguard Worker bool UserId_Defined; 218*f6dc9357SAndroid Build Coastguard Worker bool GroupId_Defined; 219*f6dc9357SAndroid Build Coastguard Worker // bool Device_Defined; 220*f6dc9357SAndroid Build Coastguard Worker bool Id_Defined; 221*f6dc9357SAndroid Build Coastguard Worker 222*f6dc9357SAndroid Build Coastguard Worker int Parent; 223*f6dc9357SAndroid Build Coastguard Worker UInt32 Mode; 224*f6dc9357SAndroid Build Coastguard Worker 225*f6dc9357SAndroid Build Coastguard Worker UInt64 Size; 226*f6dc9357SAndroid Build Coastguard Worker UInt64 PackSize; 227*f6dc9357SAndroid Build Coastguard Worker UInt64 Offset; 228*f6dc9357SAndroid Build Coastguard Worker UInt64 MTime; 229*f6dc9357SAndroid Build Coastguard Worker UInt64 CTime; 230*f6dc9357SAndroid Build Coastguard Worker UInt64 ATime; 231*f6dc9357SAndroid Build Coastguard Worker UInt64 INode; 232*f6dc9357SAndroid Build Coastguard Worker UInt64 UserId; 233*f6dc9357SAndroid Build Coastguard Worker UInt64 GroupId; 234*f6dc9357SAndroid Build Coastguard Worker // UInt64 Device; 235*f6dc9357SAndroid Build Coastguard Worker 236*f6dc9357SAndroid Build Coastguard Worker AString Name; 237*f6dc9357SAndroid Build Coastguard Worker AString Method; 238*f6dc9357SAndroid Build Coastguard Worker AString User; 239*f6dc9357SAndroid Build Coastguard Worker AString Group; 240*f6dc9357SAndroid Build Coastguard Worker // AString Id; 241*f6dc9357SAndroid Build Coastguard Worker AString Type; 242*f6dc9357SAndroid Build Coastguard Worker AString Link; 243*f6dc9357SAndroid Build Coastguard Worker // AString LinkType; 244*f6dc9357SAndroid Build Coastguard Worker // AString LinkFrom; 245*f6dc9357SAndroid Build Coastguard Worker 246*f6dc9357SAndroid Build Coastguard Worker UInt64 Id; 247*f6dc9357SAndroid Build Coastguard Worker CCheckSum extracted_checksum; 248*f6dc9357SAndroid Build Coastguard Worker CCheckSum archived_checksum; 249*f6dc9357SAndroid Build Coastguard Worker 250*f6dc9357SAndroid Build Coastguard Worker CFile(int parent): 251*f6dc9357SAndroid Build Coastguard Worker IsDir(false), 252*f6dc9357SAndroid Build Coastguard Worker Is_SymLink(false), 253*f6dc9357SAndroid Build Coastguard Worker HasData(false), 254*f6dc9357SAndroid Build Coastguard Worker Mode_Defined(false), 255*f6dc9357SAndroid Build Coastguard Worker INode_Defined(false), 256*f6dc9357SAndroid Build Coastguard Worker UserId_Defined(false), 257*f6dc9357SAndroid Build Coastguard Worker GroupId_Defined(false), 258*f6dc9357SAndroid Build Coastguard Worker // Device_Defined(false), 259*f6dc9357SAndroid Build Coastguard Worker Id_Defined(false), 260*f6dc9357SAndroid Build Coastguard Worker Parent(parent), 261*f6dc9357SAndroid Build Coastguard Worker Mode(0), 262*f6dc9357SAndroid Build Coastguard Worker Size(0), PackSize(0), Offset(0), 263*f6dc9357SAndroid Build Coastguard Worker MTime(0), CTime(0), ATime(0), 264*f6dc9357SAndroid Build Coastguard Worker INode(0) 265*f6dc9357SAndroid Build Coastguard Worker {} 266*f6dc9357SAndroid Build Coastguard Worker 267*f6dc9357SAndroid Build Coastguard Worker bool IsCopyMethod() const 268*f6dc9357SAndroid Build Coastguard Worker { 269*f6dc9357SAndroid Build Coastguard Worker return Method.IsEmpty() || Method == "octet-stream"; 270*f6dc9357SAndroid Build Coastguard Worker } 271*f6dc9357SAndroid Build Coastguard Worker 272*f6dc9357SAndroid Build Coastguard Worker void UpdateTotalPackSize(UInt64 &totalSize) const 273*f6dc9357SAndroid Build Coastguard Worker { 274*f6dc9357SAndroid Build Coastguard Worker const UInt64 t = Offset + PackSize; 275*f6dc9357SAndroid Build Coastguard Worker if (t >= Offset) 276*f6dc9357SAndroid Build Coastguard Worker if (totalSize < t) 277*f6dc9357SAndroid Build Coastguard Worker totalSize = t; 278*f6dc9357SAndroid Build Coastguard Worker } 279*f6dc9357SAndroid Build Coastguard Worker }; 280*f6dc9357SAndroid Build Coastguard Worker 281*f6dc9357SAndroid Build Coastguard Worker 282*f6dc9357SAndroid Build Coastguard Worker Z7_CLASS_IMP_CHandler_IInArchive_2( 283*f6dc9357SAndroid Build Coastguard Worker IArchiveGetRawProps, 284*f6dc9357SAndroid Build Coastguard Worker IInArchiveGetStream 285*f6dc9357SAndroid Build Coastguard Worker ) 286*f6dc9357SAndroid Build Coastguard Worker bool _is_pkg; 287*f6dc9357SAndroid Build Coastguard Worker bool _toc_CrcError; 288*f6dc9357SAndroid Build Coastguard Worker CObjectVector<CFile> _files; 289*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<IInStream> _inStream; 290*f6dc9357SAndroid Build Coastguard Worker UInt64 _dataStartPos; 291*f6dc9357SAndroid Build Coastguard Worker UInt64 _phySize; 292*f6dc9357SAndroid Build Coastguard Worker CAlignedBuffer _xmlBuf; 293*f6dc9357SAndroid Build Coastguard Worker size_t _xmlLen; 294*f6dc9357SAndroid Build Coastguard Worker // UInt64 CreationTime; 295*f6dc9357SAndroid Build Coastguard Worker AString CreationTime_String; 296*f6dc9357SAndroid Build Coastguard Worker UInt32 _checkSumAlgo; 297*f6dc9357SAndroid Build Coastguard Worker Int32 _mainSubfile; 298*f6dc9357SAndroid Build Coastguard Worker 299*f6dc9357SAndroid Build Coastguard Worker HRESULT Open2(IInStream *stream); 300*f6dc9357SAndroid Build Coastguard Worker }; 301*f6dc9357SAndroid Build Coastguard Worker 302*f6dc9357SAndroid Build Coastguard Worker 303*f6dc9357SAndroid Build Coastguard Worker static const Byte kArcProps[] = 304*f6dc9357SAndroid Build Coastguard Worker { 305*f6dc9357SAndroid Build Coastguard Worker kpidSubType, 306*f6dc9357SAndroid Build Coastguard Worker // kpidHeadersSize, 307*f6dc9357SAndroid Build Coastguard Worker kpidMethod, 308*f6dc9357SAndroid Build Coastguard Worker kpidCTime 309*f6dc9357SAndroid Build Coastguard Worker }; 310*f6dc9357SAndroid Build Coastguard Worker 311*f6dc9357SAndroid Build Coastguard Worker // #define kpidLinkType 250 312*f6dc9357SAndroid Build Coastguard Worker // #define kpidLinkFrom 251 313*f6dc9357SAndroid Build Coastguard Worker 314*f6dc9357SAndroid Build Coastguard Worker static const Byte kProps[] = 315*f6dc9357SAndroid Build Coastguard Worker { 316*f6dc9357SAndroid Build Coastguard Worker kpidPath, 317*f6dc9357SAndroid Build Coastguard Worker kpidSize, 318*f6dc9357SAndroid Build Coastguard Worker kpidPackSize, 319*f6dc9357SAndroid Build Coastguard Worker kpidMTime, 320*f6dc9357SAndroid Build Coastguard Worker kpidCTime, 321*f6dc9357SAndroid Build Coastguard Worker kpidATime, 322*f6dc9357SAndroid Build Coastguard Worker kpidPosixAttrib, 323*f6dc9357SAndroid Build Coastguard Worker kpidType, 324*f6dc9357SAndroid Build Coastguard Worker kpidUser, 325*f6dc9357SAndroid Build Coastguard Worker kpidGroup, 326*f6dc9357SAndroid Build Coastguard Worker kpidUserId, 327*f6dc9357SAndroid Build Coastguard Worker kpidGroupId, 328*f6dc9357SAndroid Build Coastguard Worker kpidINode, 329*f6dc9357SAndroid Build Coastguard Worker // kpidDeviceMajor, 330*f6dc9357SAndroid Build Coastguard Worker // kpidDeviceMinor, 331*f6dc9357SAndroid Build Coastguard Worker kpidSymLink, 332*f6dc9357SAndroid Build Coastguard Worker // kpidLinkType, 333*f6dc9357SAndroid Build Coastguard Worker // kpidLinkFrom, 334*f6dc9357SAndroid Build Coastguard Worker kpidMethod, 335*f6dc9357SAndroid Build Coastguard Worker kpidId, 336*f6dc9357SAndroid Build Coastguard Worker kpidOffset 337*f6dc9357SAndroid Build Coastguard Worker }; 338*f6dc9357SAndroid Build Coastguard Worker 339*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_Props 340*f6dc9357SAndroid Build Coastguard Worker IMP_IInArchive_ArcProps 341*f6dc9357SAndroid Build Coastguard Worker 342*f6dc9357SAndroid Build Coastguard Worker static bool ParseUInt64(const CXmlItem &item, const char *name, UInt64 &res) 343*f6dc9357SAndroid Build Coastguard Worker { 344*f6dc9357SAndroid Build Coastguard Worker const AString s (item.GetSubStringForTag(name)); 345*f6dc9357SAndroid Build Coastguard Worker if (s.IsEmpty()) 346*f6dc9357SAndroid Build Coastguard Worker return false; 347*f6dc9357SAndroid Build Coastguard Worker const char *end; 348*f6dc9357SAndroid Build Coastguard Worker res = ConvertStringToUInt64(s, &end); 349*f6dc9357SAndroid Build Coastguard Worker return *end == 0; 350*f6dc9357SAndroid Build Coastguard Worker } 351*f6dc9357SAndroid Build Coastguard Worker 352*f6dc9357SAndroid Build Coastguard Worker 353*f6dc9357SAndroid Build Coastguard Worker #define PARSE_NUM(_num_, _dest_) \ 354*f6dc9357SAndroid Build Coastguard Worker { const char *end; _dest_ = ConvertStringToUInt32(p, &end); \ 355*f6dc9357SAndroid Build Coastguard Worker if ((unsigned)(end - p) != _num_) return 0; \ 356*f6dc9357SAndroid Build Coastguard Worker p += _num_ + 1; } 357*f6dc9357SAndroid Build Coastguard Worker 358*f6dc9357SAndroid Build Coastguard Worker static UInt64 ParseTime(const CXmlItem &item, const char *name /* , bool z_isRequired */ ) 359*f6dc9357SAndroid Build Coastguard Worker { 360*f6dc9357SAndroid Build Coastguard Worker const AString s (item.GetSubStringForTag(name)); 361*f6dc9357SAndroid Build Coastguard Worker if (s.Len() < 20 /* (z_isRequired ? 20u : 19u) */) 362*f6dc9357SAndroid Build Coastguard Worker return 0; 363*f6dc9357SAndroid Build Coastguard Worker const char *p = s; 364*f6dc9357SAndroid Build Coastguard Worker if (p[ 4] != '-' || 365*f6dc9357SAndroid Build Coastguard Worker p[ 7] != '-' || 366*f6dc9357SAndroid Build Coastguard Worker p[10] != 'T' || 367*f6dc9357SAndroid Build Coastguard Worker p[13] != ':' || 368*f6dc9357SAndroid Build Coastguard Worker p[16] != ':') 369*f6dc9357SAndroid Build Coastguard Worker return 0; 370*f6dc9357SAndroid Build Coastguard Worker // if (z_isRequired) 371*f6dc9357SAndroid Build Coastguard Worker if (p[19] != 'Z') 372*f6dc9357SAndroid Build Coastguard Worker return 0; 373*f6dc9357SAndroid Build Coastguard Worker UInt32 year, month, day, hour, min, sec; 374*f6dc9357SAndroid Build Coastguard Worker PARSE_NUM(4, year) 375*f6dc9357SAndroid Build Coastguard Worker PARSE_NUM(2, month) 376*f6dc9357SAndroid Build Coastguard Worker PARSE_NUM(2, day) 377*f6dc9357SAndroid Build Coastguard Worker PARSE_NUM(2, hour) 378*f6dc9357SAndroid Build Coastguard Worker PARSE_NUM(2, min) 379*f6dc9357SAndroid Build Coastguard Worker PARSE_NUM(2, sec) 380*f6dc9357SAndroid Build Coastguard Worker UInt64 numSecs; 381*f6dc9357SAndroid Build Coastguard Worker if (!NTime::GetSecondsSince1601(year, month, day, hour, min, sec, numSecs)) 382*f6dc9357SAndroid Build Coastguard Worker return 0; 383*f6dc9357SAndroid Build Coastguard Worker return numSecs * 10000000; 384*f6dc9357SAndroid Build Coastguard Worker } 385*f6dc9357SAndroid Build Coastguard Worker 386*f6dc9357SAndroid Build Coastguard Worker 387*f6dc9357SAndroid Build Coastguard Worker static void ParseChecksum(const CXmlItem &item, const char *name, CCheckSum &checksum) 388*f6dc9357SAndroid Build Coastguard Worker { 389*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *checkItem = item.FindSubTag_GetPtr(name); 390*f6dc9357SAndroid Build Coastguard Worker if (!checkItem) 391*f6dc9357SAndroid Build Coastguard Worker return; // false; 392*f6dc9357SAndroid Build Coastguard Worker checksum.Style = checkItem->GetPropVal("style"); 393*f6dc9357SAndroid Build Coastguard Worker const AString s (checkItem->GetSubString()); 394*f6dc9357SAndroid Build Coastguard Worker if ((s.Len() & 1) == 0 && s.Len() <= (2u << 7)) // 1024-bit max 395*f6dc9357SAndroid Build Coastguard Worker { 396*f6dc9357SAndroid Build Coastguard Worker const size_t size = s.Len() / 2; 397*f6dc9357SAndroid Build Coastguard Worker CByteBuffer temp(size); 398*f6dc9357SAndroid Build Coastguard Worker if ((size_t)(ParseHexString(s, temp) - temp) == size) 399*f6dc9357SAndroid Build Coastguard Worker { 400*f6dc9357SAndroid Build Coastguard Worker checksum.Data = temp; 401*f6dc9357SAndroid Build Coastguard Worker const int index = Find_ChecksumId_for_Name(checksum.Style); 402*f6dc9357SAndroid Build Coastguard Worker if (index >= 0 && checksum.Data.Size() == GetHashSize(index)) 403*f6dc9357SAndroid Build Coastguard Worker { 404*f6dc9357SAndroid Build Coastguard Worker checksum.AlgoNumber = index; 405*f6dc9357SAndroid Build Coastguard Worker return; 406*f6dc9357SAndroid Build Coastguard Worker } 407*f6dc9357SAndroid Build Coastguard Worker } 408*f6dc9357SAndroid Build Coastguard Worker } 409*f6dc9357SAndroid Build Coastguard Worker checksum.Error = true; 410*f6dc9357SAndroid Build Coastguard Worker } 411*f6dc9357SAndroid Build Coastguard Worker 412*f6dc9357SAndroid Build Coastguard Worker 413*f6dc9357SAndroid Build Coastguard Worker static bool AddItem(const CXmlItem &item, CObjectVector<CFile> &files, int parent, int level) 414*f6dc9357SAndroid Build Coastguard Worker { 415*f6dc9357SAndroid Build Coastguard Worker if (!item.IsTag) 416*f6dc9357SAndroid Build Coastguard Worker return true; 417*f6dc9357SAndroid Build Coastguard Worker if (level >= 1024) 418*f6dc9357SAndroid Build Coastguard Worker return false; 419*f6dc9357SAndroid Build Coastguard Worker if (item.Name == "file") 420*f6dc9357SAndroid Build Coastguard Worker { 421*f6dc9357SAndroid Build Coastguard Worker CFile file(parent); 422*f6dc9357SAndroid Build Coastguard Worker parent = (int)files.Size(); 423*f6dc9357SAndroid Build Coastguard Worker { 424*f6dc9357SAndroid Build Coastguard Worker const AString id = item.GetPropVal("id"); 425*f6dc9357SAndroid Build Coastguard Worker const char *end; 426*f6dc9357SAndroid Build Coastguard Worker file.Id = ConvertStringToUInt64(id, &end); 427*f6dc9357SAndroid Build Coastguard Worker if (*end == 0) 428*f6dc9357SAndroid Build Coastguard Worker file.Id_Defined = true; 429*f6dc9357SAndroid Build Coastguard Worker } 430*f6dc9357SAndroid Build Coastguard Worker file.Name = item.GetSubStringForTag("name"); 431*f6dc9357SAndroid Build Coastguard Worker z7_xml_DecodeString(file.Name); 432*f6dc9357SAndroid Build Coastguard Worker { 433*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *typeItem = item.FindSubTag_GetPtr("type"); 434*f6dc9357SAndroid Build Coastguard Worker if (typeItem) 435*f6dc9357SAndroid Build Coastguard Worker { 436*f6dc9357SAndroid Build Coastguard Worker file.Type = typeItem->GetSubString(); 437*f6dc9357SAndroid Build Coastguard Worker // file.LinkFrom = typeItem->GetPropVal("link"); 438*f6dc9357SAndroid Build Coastguard Worker if (file.Type == "directory") 439*f6dc9357SAndroid Build Coastguard Worker file.IsDir = true; 440*f6dc9357SAndroid Build Coastguard Worker else 441*f6dc9357SAndroid Build Coastguard Worker { 442*f6dc9357SAndroid Build Coastguard Worker // file.IsDir = false; 443*f6dc9357SAndroid Build Coastguard Worker /* 444*f6dc9357SAndroid Build Coastguard Worker else if (file.Type == "file") 445*f6dc9357SAndroid Build Coastguard Worker {} 446*f6dc9357SAndroid Build Coastguard Worker else if (file.Type == "hardlink") 447*f6dc9357SAndroid Build Coastguard Worker {} 448*f6dc9357SAndroid Build Coastguard Worker else 449*f6dc9357SAndroid Build Coastguard Worker */ 450*f6dc9357SAndroid Build Coastguard Worker if (file.Type == "symlink") 451*f6dc9357SAndroid Build Coastguard Worker file.Is_SymLink = true; 452*f6dc9357SAndroid Build Coastguard Worker // file.IsDir = false; 453*f6dc9357SAndroid Build Coastguard Worker } 454*f6dc9357SAndroid Build Coastguard Worker } 455*f6dc9357SAndroid Build Coastguard Worker } 456*f6dc9357SAndroid Build Coastguard Worker { 457*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *linkItem = item.FindSubTag_GetPtr("link"); 458*f6dc9357SAndroid Build Coastguard Worker if (linkItem) 459*f6dc9357SAndroid Build Coastguard Worker { 460*f6dc9357SAndroid Build Coastguard Worker // file.LinkType = linkItem->GetPropVal("type"); 461*f6dc9357SAndroid Build Coastguard Worker file.Link = linkItem->GetSubString(); 462*f6dc9357SAndroid Build Coastguard Worker z7_xml_DecodeString(file.Link); 463*f6dc9357SAndroid Build Coastguard Worker } 464*f6dc9357SAndroid Build Coastguard Worker } 465*f6dc9357SAndroid Build Coastguard Worker 466*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *dataItem = item.FindSubTag_GetPtr("data"); 467*f6dc9357SAndroid Build Coastguard Worker if (dataItem && !file.IsDir) 468*f6dc9357SAndroid Build Coastguard Worker { 469*f6dc9357SAndroid Build Coastguard Worker file.HasData = true; 470*f6dc9357SAndroid Build Coastguard Worker if (!ParseUInt64(*dataItem, "size", file.Size)) 471*f6dc9357SAndroid Build Coastguard Worker return false; 472*f6dc9357SAndroid Build Coastguard Worker if (!ParseUInt64(*dataItem, "length", file.PackSize)) 473*f6dc9357SAndroid Build Coastguard Worker return false; 474*f6dc9357SAndroid Build Coastguard Worker if (!ParseUInt64(*dataItem, "offset", file.Offset)) 475*f6dc9357SAndroid Build Coastguard Worker return false; 476*f6dc9357SAndroid Build Coastguard Worker ParseChecksum(*dataItem, "extracted-checksum", file.extracted_checksum); 477*f6dc9357SAndroid Build Coastguard Worker ParseChecksum(*dataItem, "archived-checksum", file.archived_checksum); 478*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *encodingItem = dataItem->FindSubTag_GetPtr("encoding"); 479*f6dc9357SAndroid Build Coastguard Worker if (encodingItem) 480*f6dc9357SAndroid Build Coastguard Worker { 481*f6dc9357SAndroid Build Coastguard Worker AString s (encodingItem->GetPropVal("style")); 482*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty()) 483*f6dc9357SAndroid Build Coastguard Worker { 484*f6dc9357SAndroid Build Coastguard Worker const AString appl ("application/"); 485*f6dc9357SAndroid Build Coastguard Worker if (s.IsPrefixedBy(appl)) 486*f6dc9357SAndroid Build Coastguard Worker { 487*f6dc9357SAndroid Build Coastguard Worker s.DeleteFrontal(appl.Len()); 488*f6dc9357SAndroid Build Coastguard Worker const AString xx ("x-"); 489*f6dc9357SAndroid Build Coastguard Worker if (s.IsPrefixedBy(xx)) 490*f6dc9357SAndroid Build Coastguard Worker { 491*f6dc9357SAndroid Build Coastguard Worker s.DeleteFrontal(xx.Len()); 492*f6dc9357SAndroid Build Coastguard Worker if (s == "gzip") 493*f6dc9357SAndroid Build Coastguard Worker s = METHOD_NAME_ZLIB; 494*f6dc9357SAndroid Build Coastguard Worker } 495*f6dc9357SAndroid Build Coastguard Worker } 496*f6dc9357SAndroid Build Coastguard Worker file.Method = s; 497*f6dc9357SAndroid Build Coastguard Worker } 498*f6dc9357SAndroid Build Coastguard Worker } 499*f6dc9357SAndroid Build Coastguard Worker } 500*f6dc9357SAndroid Build Coastguard Worker 501*f6dc9357SAndroid Build Coastguard Worker file.INode_Defined = ParseUInt64(item, "inode", file.INode); 502*f6dc9357SAndroid Build Coastguard Worker file.UserId_Defined = ParseUInt64(item, "uid", file.UserId); 503*f6dc9357SAndroid Build Coastguard Worker file.GroupId_Defined = ParseUInt64(item, "gid", file.GroupId); 504*f6dc9357SAndroid Build Coastguard Worker // file.Device_Defined = ParseUInt64(item, "deviceno", file.Device); 505*f6dc9357SAndroid Build Coastguard Worker file.MTime = ParseTime(item, "mtime"); // z_IsRequied = true 506*f6dc9357SAndroid Build Coastguard Worker file.CTime = ParseTime(item, "ctime"); 507*f6dc9357SAndroid Build Coastguard Worker file.ATime = ParseTime(item, "atime"); 508*f6dc9357SAndroid Build Coastguard Worker { 509*f6dc9357SAndroid Build Coastguard Worker const AString s (item.GetSubStringForTag("mode")); 510*f6dc9357SAndroid Build Coastguard Worker if (s[0] == '0') 511*f6dc9357SAndroid Build Coastguard Worker { 512*f6dc9357SAndroid Build Coastguard Worker const char *end; 513*f6dc9357SAndroid Build Coastguard Worker file.Mode = ConvertOctStringToUInt32(s, &end); 514*f6dc9357SAndroid Build Coastguard Worker file.Mode_Defined = (*end == 0); 515*f6dc9357SAndroid Build Coastguard Worker } 516*f6dc9357SAndroid Build Coastguard Worker } 517*f6dc9357SAndroid Build Coastguard Worker file.User = item.GetSubStringForTag("user"); 518*f6dc9357SAndroid Build Coastguard Worker file.Group = item.GetSubStringForTag("group"); 519*f6dc9357SAndroid Build Coastguard Worker 520*f6dc9357SAndroid Build Coastguard Worker files.Add(file); 521*f6dc9357SAndroid Build Coastguard Worker } 522*f6dc9357SAndroid Build Coastguard Worker 523*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, item.SubItems) 524*f6dc9357SAndroid Build Coastguard Worker if (!AddItem(item.SubItems[i], files, parent, level + 1)) 525*f6dc9357SAndroid Build Coastguard Worker return false; 526*f6dc9357SAndroid Build Coastguard Worker return true; 527*f6dc9357SAndroid Build Coastguard Worker } 528*f6dc9357SAndroid Build Coastguard Worker 529*f6dc9357SAndroid Build Coastguard Worker 530*f6dc9357SAndroid Build Coastguard Worker 531*f6dc9357SAndroid Build Coastguard Worker struct CInStreamWithHash 532*f6dc9357SAndroid Build Coastguard Worker { 533*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha1> inStreamSha1; 534*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CInStreamWithSha256> inStreamSha256; 535*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialInStream, CLimitedSequentialInStream> inStreamLim; 536*f6dc9357SAndroid Build Coastguard Worker 537*f6dc9357SAndroid Build Coastguard Worker void SetStreamAndInit(ISequentialInStream *stream, int algo); 538*f6dc9357SAndroid Build Coastguard Worker bool CheckHash(int algo, const Byte *digest_from_arc) const; 539*f6dc9357SAndroid Build Coastguard Worker }; 540*f6dc9357SAndroid Build Coastguard Worker 541*f6dc9357SAndroid Build Coastguard Worker 542*f6dc9357SAndroid Build Coastguard Worker void CInStreamWithHash::SetStreamAndInit(ISequentialInStream *stream, int algo) 543*f6dc9357SAndroid Build Coastguard Worker { 544*f6dc9357SAndroid Build Coastguard Worker if (algo == XAR_CKSUM_SHA1) 545*f6dc9357SAndroid Build Coastguard Worker { 546*f6dc9357SAndroid Build Coastguard Worker inStreamSha1->SetStream(stream); 547*f6dc9357SAndroid Build Coastguard Worker inStreamSha1->Init(); 548*f6dc9357SAndroid Build Coastguard Worker stream = inStreamSha1; 549*f6dc9357SAndroid Build Coastguard Worker } 550*f6dc9357SAndroid Build Coastguard Worker else if (algo == XAR_CKSUM_SHA256 551*f6dc9357SAndroid Build Coastguard Worker || algo == XAR_CKSUM_SHA512) 552*f6dc9357SAndroid Build Coastguard Worker { 553*f6dc9357SAndroid Build Coastguard Worker inStreamSha256->SetStream(stream); 554*f6dc9357SAndroid Build Coastguard Worker inStreamSha256->Init(algo == XAR_CKSUM_SHA512); 555*f6dc9357SAndroid Build Coastguard Worker stream = inStreamSha256; 556*f6dc9357SAndroid Build Coastguard Worker } 557*f6dc9357SAndroid Build Coastguard Worker inStreamLim->SetStream(stream); 558*f6dc9357SAndroid Build Coastguard Worker } 559*f6dc9357SAndroid Build Coastguard Worker 560*f6dc9357SAndroid Build Coastguard Worker bool CInStreamWithHash::CheckHash(int algo, const Byte *digest_from_arc) const 561*f6dc9357SAndroid Build Coastguard Worker { 562*f6dc9357SAndroid Build Coastguard Worker if (algo == XAR_CKSUM_SHA1) 563*f6dc9357SAndroid Build Coastguard Worker { 564*f6dc9357SAndroid Build Coastguard Worker Byte digest[SHA1_DIGEST_SIZE]; 565*f6dc9357SAndroid Build Coastguard Worker inStreamSha1->Final(digest); 566*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0) 567*f6dc9357SAndroid Build Coastguard Worker return false; 568*f6dc9357SAndroid Build Coastguard Worker } 569*f6dc9357SAndroid Build Coastguard Worker else if (algo == XAR_CKSUM_SHA256) 570*f6dc9357SAndroid Build Coastguard Worker { 571*f6dc9357SAndroid Build Coastguard Worker Byte digest[SHA256_DIGEST_SIZE]; 572*f6dc9357SAndroid Build Coastguard Worker inStreamSha256->Final256(digest); 573*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0) 574*f6dc9357SAndroid Build Coastguard Worker return false; 575*f6dc9357SAndroid Build Coastguard Worker } 576*f6dc9357SAndroid Build Coastguard Worker else if (algo == XAR_CKSUM_SHA512) 577*f6dc9357SAndroid Build Coastguard Worker { 578*f6dc9357SAndroid Build Coastguard Worker Byte digest[SHA512_DIGEST_SIZE]; 579*f6dc9357SAndroid Build Coastguard Worker inStreamSha256->Final512(digest); 580*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, digest_from_arc, sizeof(digest)) != 0) 581*f6dc9357SAndroid Build Coastguard Worker return false; 582*f6dc9357SAndroid Build Coastguard Worker } 583*f6dc9357SAndroid Build Coastguard Worker return true; 584*f6dc9357SAndroid Build Coastguard Worker } 585*f6dc9357SAndroid Build Coastguard Worker 586*f6dc9357SAndroid Build Coastguard Worker 587*f6dc9357SAndroid Build Coastguard Worker HRESULT CHandler::Open2(IInStream *stream) 588*f6dc9357SAndroid Build Coastguard Worker { 589*f6dc9357SAndroid Build Coastguard Worker const unsigned kHeaderSize = 28; 590*f6dc9357SAndroid Build Coastguard Worker UInt32 buf32[kHeaderSize / sizeof(UInt32)]; 591*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, buf32, kHeaderSize)) 592*f6dc9357SAndroid Build Coastguard Worker const unsigned headerSize = Get16((const Byte *)(const void *)buf32 + 4); 593*f6dc9357SAndroid Build Coastguard Worker // xar library now writes 1 to version field. 594*f6dc9357SAndroid Build Coastguard Worker // some old xars could have version == 0 ? 595*f6dc9357SAndroid Build Coastguard Worker // specification allows (headerSize != 28), 596*f6dc9357SAndroid Build Coastguard Worker // but we don't expect big value in (headerSize). 597*f6dc9357SAndroid Build Coastguard Worker // so we restrict (headerSize) with 64 bytes to reduce false open. 598*f6dc9357SAndroid Build Coastguard Worker const unsigned kHeaderSize_MAX = 64; 599*f6dc9357SAndroid Build Coastguard Worker if (Get32(buf32) != 0x78617221 // signature: "xar!" 600*f6dc9357SAndroid Build Coastguard Worker || headerSize < kHeaderSize 601*f6dc9357SAndroid Build Coastguard Worker || headerSize > kHeaderSize_MAX 602*f6dc9357SAndroid Build Coastguard Worker || Get16((const Byte *)(const void *)buf32 + 6) > 1 // version 603*f6dc9357SAndroid Build Coastguard Worker ) 604*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 605*f6dc9357SAndroid Build Coastguard Worker _checkSumAlgo = Get32(buf32 + 6); 606*f6dc9357SAndroid Build Coastguard Worker const UInt64 packSize = Get64(buf32 + 2); 607*f6dc9357SAndroid Build Coastguard Worker const UInt64 unpackSize = Get64(buf32 + 4); 608*f6dc9357SAndroid Build Coastguard Worker if (packSize >= kXmlPackSizeMax || 609*f6dc9357SAndroid Build Coastguard Worker unpackSize >= kXmlSizeMax) 610*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 611*f6dc9357SAndroid Build Coastguard Worker /* some xar archives can have padding bytes at offset 28, 612*f6dc9357SAndroid Build Coastguard Worker or checksum algorithm name at offset 28 (in xar fork, if cksum_alg==3) 613*f6dc9357SAndroid Build Coastguard Worker But we didn't see such xar archives. 614*f6dc9357SAndroid Build Coastguard Worker */ 615*f6dc9357SAndroid Build Coastguard Worker if (headerSize != kHeaderSize) 616*f6dc9357SAndroid Build Coastguard Worker { 617*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, headerSize)) 618*f6dc9357SAndroid Build Coastguard Worker } 619*f6dc9357SAndroid Build Coastguard Worker _dataStartPos = headerSize + packSize; 620*f6dc9357SAndroid Build Coastguard Worker _phySize = _dataStartPos; 621*f6dc9357SAndroid Build Coastguard Worker 622*f6dc9357SAndroid Build Coastguard Worker _xmlBuf.Alloc((size_t)unpackSize + 1); 623*f6dc9357SAndroid Build Coastguard Worker if (!_xmlBuf.IsAllocated()) 624*f6dc9357SAndroid Build Coastguard Worker return E_OUTOFMEMORY; 625*f6dc9357SAndroid Build Coastguard Worker _xmlLen = (size_t)unpackSize; 626*f6dc9357SAndroid Build Coastguard Worker 627*f6dc9357SAndroid Build Coastguard Worker CInStreamWithHash hashStream; 628*f6dc9357SAndroid Build Coastguard Worker { 629*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> zlibCoder; 630*f6dc9357SAndroid Build Coastguard Worker hashStream.SetStreamAndInit(stream, (int)(unsigned)_checkSumAlgo); 631*f6dc9357SAndroid Build Coastguard Worker hashStream.inStreamLim->Init(packSize); 632*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CBufPtrSeqOutStream> outStreamLim; 633*f6dc9357SAndroid Build Coastguard Worker outStreamLim->Init(_xmlBuf, (size_t)unpackSize); 634*f6dc9357SAndroid Build Coastguard Worker RINOK(zlibCoder.Interface()->Code(hashStream.inStreamLim, outStreamLim, NULL, &unpackSize, NULL)) 635*f6dc9357SAndroid Build Coastguard Worker if (outStreamLim->GetPos() != (size_t)unpackSize) 636*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 637*f6dc9357SAndroid Build Coastguard Worker } 638*f6dc9357SAndroid Build Coastguard Worker _xmlBuf[(size_t)unpackSize] = 0; 639*f6dc9357SAndroid Build Coastguard Worker if (strlen((const char *)(const Byte *)_xmlBuf) != (size_t)unpackSize) 640*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 641*f6dc9357SAndroid Build Coastguard Worker CXml xml; 642*f6dc9357SAndroid Build Coastguard Worker if (!xml.Parse((const char *)(const Byte *)_xmlBuf)) 643*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 644*f6dc9357SAndroid Build Coastguard Worker 645*f6dc9357SAndroid Build Coastguard Worker if (!xml.Root.IsTagged("xar") || xml.Root.SubItems.Size() != 1) 646*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 647*f6dc9357SAndroid Build Coastguard Worker const CXmlItem &toc = xml.Root.SubItems[0]; 648*f6dc9357SAndroid Build Coastguard Worker if (!toc.IsTagged("toc")) 649*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 650*f6dc9357SAndroid Build Coastguard Worker 651*f6dc9357SAndroid Build Coastguard Worker // CreationTime = ParseTime(toc, "creation-time", false); // z_IsRequied 652*f6dc9357SAndroid Build Coastguard Worker CreationTime_String = toc.GetSubStringForTag("creation-time"); 653*f6dc9357SAndroid Build Coastguard Worker { 654*f6dc9357SAndroid Build Coastguard Worker // we suppose that offset of checksum is always 0; 655*f6dc9357SAndroid Build Coastguard Worker // but [TOC].xml contains exact offset value in <checksum> block. 656*f6dc9357SAndroid Build Coastguard Worker const UInt64 offset = 0; 657*f6dc9357SAndroid Build Coastguard Worker const unsigned hashSize = GetHashSize((int)(unsigned)_checkSumAlgo); 658*f6dc9357SAndroid Build Coastguard Worker if (hashSize) 659*f6dc9357SAndroid Build Coastguard Worker { 660*f6dc9357SAndroid Build Coastguard Worker /* 661*f6dc9357SAndroid Build Coastguard Worker const CXmlItem *csItem = toc.FindSubTag_GetPtr("checksum"); 662*f6dc9357SAndroid Build Coastguard Worker if (csItem) 663*f6dc9357SAndroid Build Coastguard Worker { 664*f6dc9357SAndroid Build Coastguard Worker const int checkSumAlgo2 = Find_ChecksumId_for_Name(csItem->GetPropVal("style")); 665*f6dc9357SAndroid Build Coastguard Worker UInt64 csSize, csOffset; 666*f6dc9357SAndroid Build Coastguard Worker if (ParseUInt64(*csItem, "size", csSize) && 667*f6dc9357SAndroid Build Coastguard Worker ParseUInt64(*csItem, "offset", csOffset) && 668*f6dc9357SAndroid Build Coastguard Worker csSize == hashSize && 669*f6dc9357SAndroid Build Coastguard Worker (unsigned)checkSumAlgo2 == _checkSumAlgo) 670*f6dc9357SAndroid Build Coastguard Worker offset = csOffset; 671*f6dc9357SAndroid Build Coastguard Worker } 672*f6dc9357SAndroid Build Coastguard Worker */ 673*f6dc9357SAndroid Build Coastguard Worker CByteBuffer digest_from_arc(hashSize); 674*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(stream, _dataStartPos + offset)) 675*f6dc9357SAndroid Build Coastguard Worker RINOK(ReadStream_FALSE(stream, digest_from_arc, hashSize)) 676*f6dc9357SAndroid Build Coastguard Worker if (!hashStream.CheckHash((int)(unsigned)_checkSumAlgo, digest_from_arc)) 677*f6dc9357SAndroid Build Coastguard Worker _toc_CrcError = true; 678*f6dc9357SAndroid Build Coastguard Worker } 679*f6dc9357SAndroid Build Coastguard Worker } 680*f6dc9357SAndroid Build Coastguard Worker 681*f6dc9357SAndroid Build Coastguard Worker if (!AddItem(toc, _files, 682*f6dc9357SAndroid Build Coastguard Worker -1, // parent 683*f6dc9357SAndroid Build Coastguard Worker 0)) // level 684*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 685*f6dc9357SAndroid Build Coastguard Worker 686*f6dc9357SAndroid Build Coastguard Worker UInt64 totalPackSize = 0; 687*f6dc9357SAndroid Build Coastguard Worker unsigned numMainFiles = 0; 688*f6dc9357SAndroid Build Coastguard Worker 689*f6dc9357SAndroid Build Coastguard Worker FOR_VECTOR (i, _files) 690*f6dc9357SAndroid Build Coastguard Worker { 691*f6dc9357SAndroid Build Coastguard Worker const CFile &file = _files[i]; 692*f6dc9357SAndroid Build Coastguard Worker file.UpdateTotalPackSize(totalPackSize); 693*f6dc9357SAndroid Build Coastguard Worker if (file.Parent == -1) 694*f6dc9357SAndroid Build Coastguard Worker { 695*f6dc9357SAndroid Build Coastguard Worker if (file.Name == "Payload" || file.Name == "Content") 696*f6dc9357SAndroid Build Coastguard Worker { 697*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = (Int32)(int)i; 698*f6dc9357SAndroid Build Coastguard Worker numMainFiles++; 699*f6dc9357SAndroid Build Coastguard Worker } 700*f6dc9357SAndroid Build Coastguard Worker else if (file.Name == "PackageInfo") 701*f6dc9357SAndroid Build Coastguard Worker _is_pkg = true; 702*f6dc9357SAndroid Build Coastguard Worker } 703*f6dc9357SAndroid Build Coastguard Worker } 704*f6dc9357SAndroid Build Coastguard Worker 705*f6dc9357SAndroid Build Coastguard Worker if (numMainFiles > 1) 706*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = -1; 707*f6dc9357SAndroid Build Coastguard Worker 708*f6dc9357SAndroid Build Coastguard Worker const UInt64 k_PhySizeLim = (UInt64)1 << 62; 709*f6dc9357SAndroid Build Coastguard Worker _phySize = (totalPackSize > k_PhySizeLim - _dataStartPos) ? 710*f6dc9357SAndroid Build Coastguard Worker k_PhySizeLim : 711*f6dc9357SAndroid Build Coastguard Worker _dataStartPos + totalPackSize; 712*f6dc9357SAndroid Build Coastguard Worker 713*f6dc9357SAndroid Build Coastguard Worker return S_OK; 714*f6dc9357SAndroid Build Coastguard Worker } 715*f6dc9357SAndroid Build Coastguard Worker 716*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Open(IInStream *stream, 717*f6dc9357SAndroid Build Coastguard Worker const UInt64 * /* maxCheckStartPosition */, 718*f6dc9357SAndroid Build Coastguard Worker IArchiveOpenCallback * /* openArchiveCallback */)) 719*f6dc9357SAndroid Build Coastguard Worker { 720*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 721*f6dc9357SAndroid Build Coastguard Worker { 722*f6dc9357SAndroid Build Coastguard Worker Close(); 723*f6dc9357SAndroid Build Coastguard Worker RINOK(Open2(stream)) 724*f6dc9357SAndroid Build Coastguard Worker _inStream = stream; 725*f6dc9357SAndroid Build Coastguard Worker } 726*f6dc9357SAndroid Build Coastguard Worker return S_OK; 727*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 728*f6dc9357SAndroid Build Coastguard Worker } 729*f6dc9357SAndroid Build Coastguard Worker 730*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Close()) 731*f6dc9357SAndroid Build Coastguard Worker { 732*f6dc9357SAndroid Build Coastguard Worker _phySize = 0; 733*f6dc9357SAndroid Build Coastguard Worker _dataStartPos = 0; 734*f6dc9357SAndroid Build Coastguard Worker _inStream.Release(); 735*f6dc9357SAndroid Build Coastguard Worker _files.Clear(); 736*f6dc9357SAndroid Build Coastguard Worker _xmlLen = 0; 737*f6dc9357SAndroid Build Coastguard Worker _xmlBuf.Free(); 738*f6dc9357SAndroid Build Coastguard Worker _mainSubfile = -1; 739*f6dc9357SAndroid Build Coastguard Worker _is_pkg = false; 740*f6dc9357SAndroid Build Coastguard Worker _toc_CrcError = false; 741*f6dc9357SAndroid Build Coastguard Worker _checkSumAlgo = 0; 742*f6dc9357SAndroid Build Coastguard Worker // CreationTime = 0; 743*f6dc9357SAndroid Build Coastguard Worker CreationTime_String.Empty(); 744*f6dc9357SAndroid Build Coastguard Worker return S_OK; 745*f6dc9357SAndroid Build Coastguard Worker } 746*f6dc9357SAndroid Build Coastguard Worker 747*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumberOfItems(UInt32 *numItems)) 748*f6dc9357SAndroid Build Coastguard Worker { 749*f6dc9357SAndroid Build Coastguard Worker *numItems = _files.Size() 750*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 751*f6dc9357SAndroid Build Coastguard Worker + 1 752*f6dc9357SAndroid Build Coastguard Worker #endif 753*f6dc9357SAndroid Build Coastguard Worker ; 754*f6dc9357SAndroid Build Coastguard Worker return S_OK; 755*f6dc9357SAndroid Build Coastguard Worker } 756*f6dc9357SAndroid Build Coastguard Worker 757*f6dc9357SAndroid Build Coastguard Worker static void TimeToProp(UInt64 t, NCOM::CPropVariant &prop) 758*f6dc9357SAndroid Build Coastguard Worker { 759*f6dc9357SAndroid Build Coastguard Worker if (t != 0) 760*f6dc9357SAndroid Build Coastguard Worker { 761*f6dc9357SAndroid Build Coastguard Worker FILETIME ft; 762*f6dc9357SAndroid Build Coastguard Worker ft.dwLowDateTime = (UInt32)(t); 763*f6dc9357SAndroid Build Coastguard Worker ft.dwHighDateTime = (UInt32)(t >> 32); 764*f6dc9357SAndroid Build Coastguard Worker prop = ft; 765*f6dc9357SAndroid Build Coastguard Worker } 766*f6dc9357SAndroid Build Coastguard Worker } 767*f6dc9357SAndroid Build Coastguard Worker 768*f6dc9357SAndroid Build Coastguard Worker static void Utf8StringToProp(const AString &s, NCOM::CPropVariant &prop) 769*f6dc9357SAndroid Build Coastguard Worker { 770*f6dc9357SAndroid Build Coastguard Worker if (!s.IsEmpty()) 771*f6dc9357SAndroid Build Coastguard Worker { 772*f6dc9357SAndroid Build Coastguard Worker UString us; 773*f6dc9357SAndroid Build Coastguard Worker ConvertUTF8ToUnicode(s, us); 774*f6dc9357SAndroid Build Coastguard Worker prop = us; 775*f6dc9357SAndroid Build Coastguard Worker } 776*f6dc9357SAndroid Build Coastguard Worker } 777*f6dc9357SAndroid Build Coastguard Worker 778*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)) 779*f6dc9357SAndroid Build Coastguard Worker { 780*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 781*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 782*f6dc9357SAndroid Build Coastguard Worker switch (propID) 783*f6dc9357SAndroid Build Coastguard Worker { 784*f6dc9357SAndroid Build Coastguard Worker // case kpidHeadersSize: prop = _dataStartPos; break; 785*f6dc9357SAndroid Build Coastguard Worker case kpidPhySize: prop = _phySize; break; 786*f6dc9357SAndroid Build Coastguard Worker case kpidMainSubfile: if (_mainSubfile >= 0) prop = (UInt32)_mainSubfile; break; 787*f6dc9357SAndroid Build Coastguard Worker case kpidSubType: if (_is_pkg) prop = "pkg"; break; 788*f6dc9357SAndroid Build Coastguard Worker case kpidExtension: prop = _is_pkg ? "pkg" : "xar"; break; 789*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: 790*f6dc9357SAndroid Build Coastguard Worker { 791*f6dc9357SAndroid Build Coastguard Worker // it's local time. We can transfer it to UTC time, if we use FILETIME. 792*f6dc9357SAndroid Build Coastguard Worker // TimeToProp(CreationTime, prop); break; 793*f6dc9357SAndroid Build Coastguard Worker if (!CreationTime_String.IsEmpty()) 794*f6dc9357SAndroid Build Coastguard Worker prop = CreationTime_String; 795*f6dc9357SAndroid Build Coastguard Worker break; 796*f6dc9357SAndroid Build Coastguard Worker } 797*f6dc9357SAndroid Build Coastguard Worker case kpidMethod: 798*f6dc9357SAndroid Build Coastguard Worker { 799*f6dc9357SAndroid Build Coastguard Worker AString s; 800*f6dc9357SAndroid Build Coastguard Worker if (_checkSumAlgo < Z7_ARRAY_SIZE(k_ChecksumNames)) 801*f6dc9357SAndroid Build Coastguard Worker s = k_ChecksumNames[_checkSumAlgo]; 802*f6dc9357SAndroid Build Coastguard Worker else 803*f6dc9357SAndroid Build Coastguard Worker { 804*f6dc9357SAndroid Build Coastguard Worker s += "Checksum"; 805*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(_checkSumAlgo); 806*f6dc9357SAndroid Build Coastguard Worker } 807*f6dc9357SAndroid Build Coastguard Worker prop = s; 808*f6dc9357SAndroid Build Coastguard Worker break; 809*f6dc9357SAndroid Build Coastguard Worker } 810*f6dc9357SAndroid Build Coastguard Worker case kpidWarningFlags: 811*f6dc9357SAndroid Build Coastguard Worker { 812*f6dc9357SAndroid Build Coastguard Worker UInt32 v = 0; 813*f6dc9357SAndroid Build Coastguard Worker if (_toc_CrcError) v |= kpv_ErrorFlags_CrcError; 814*f6dc9357SAndroid Build Coastguard Worker prop = v; 815*f6dc9357SAndroid Build Coastguard Worker break; 816*f6dc9357SAndroid Build Coastguard Worker } 817*f6dc9357SAndroid Build Coastguard Worker case kpidINode: prop = true; break; 818*f6dc9357SAndroid Build Coastguard Worker case kpidIsTree: prop = true; break; 819*f6dc9357SAndroid Build Coastguard Worker } 820*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value); 821*f6dc9357SAndroid Build Coastguard Worker return S_OK; 822*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 823*f6dc9357SAndroid Build Coastguard Worker } 824*f6dc9357SAndroid Build Coastguard Worker 825*f6dc9357SAndroid Build Coastguard Worker 826*f6dc9357SAndroid Build Coastguard Worker /* 827*f6dc9357SAndroid Build Coastguard Worker inline UInt32 MY_dev_major(UInt64 dev) 828*f6dc9357SAndroid Build Coastguard Worker { 829*f6dc9357SAndroid Build Coastguard Worker return ((UInt32)(dev >> 8) & (UInt32)0xfff) | ((UInt32)(dev >> 32) & ~(UInt32)0xfff); 830*f6dc9357SAndroid Build Coastguard Worker } 831*f6dc9357SAndroid Build Coastguard Worker inline UInt32 MY_dev_minor(UInt64 dev) 832*f6dc9357SAndroid Build Coastguard Worker { 833*f6dc9357SAndroid Build Coastguard Worker return ((UInt32)(dev) & 0xff) | ((UInt32)(dev >> 12) & ~(UInt32)0xff); 834*f6dc9357SAndroid Build Coastguard Worker } 835*f6dc9357SAndroid Build Coastguard Worker */ 836*f6dc9357SAndroid Build Coastguard Worker 837*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)) 838*f6dc9357SAndroid Build Coastguard Worker { 839*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 840*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 841*f6dc9357SAndroid Build Coastguard Worker 842*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 843*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 844*f6dc9357SAndroid Build Coastguard Worker { 845*f6dc9357SAndroid Build Coastguard Worker switch (propID) 846*f6dc9357SAndroid Build Coastguard Worker { 847*f6dc9357SAndroid Build Coastguard Worker case kpidName: 848*f6dc9357SAndroid Build Coastguard Worker case kpidPath: 849*f6dc9357SAndroid Build Coastguard Worker prop = "[TOC].xml"; break; 850*f6dc9357SAndroid Build Coastguard Worker case kpidSize: 851*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: prop = (UInt64)_xmlLen; break; 852*f6dc9357SAndroid Build Coastguard Worker } 853*f6dc9357SAndroid Build Coastguard Worker } 854*f6dc9357SAndroid Build Coastguard Worker else 855*f6dc9357SAndroid Build Coastguard Worker #endif 856*f6dc9357SAndroid Build Coastguard Worker { 857*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 858*f6dc9357SAndroid Build Coastguard Worker switch (propID) 859*f6dc9357SAndroid Build Coastguard Worker { 860*f6dc9357SAndroid Build Coastguard Worker case kpidPath: 861*f6dc9357SAndroid Build Coastguard Worker { 862*f6dc9357SAndroid Build Coastguard Worker AString path; 863*f6dc9357SAndroid Build Coastguard Worker unsigned cur = index; 864*f6dc9357SAndroid Build Coastguard Worker for (;;) 865*f6dc9357SAndroid Build Coastguard Worker { 866*f6dc9357SAndroid Build Coastguard Worker const CFile &item2 = _files[cur]; 867*f6dc9357SAndroid Build Coastguard Worker if (!path.IsEmpty()) 868*f6dc9357SAndroid Build Coastguard Worker path.InsertAtFront(CHAR_PATH_SEPARATOR); 869*f6dc9357SAndroid Build Coastguard Worker // #define XAR_EMPTY_NAME_REPLACEMENT "[]" 870*f6dc9357SAndroid Build Coastguard Worker if (item2.Name.IsEmpty()) 871*f6dc9357SAndroid Build Coastguard Worker { 872*f6dc9357SAndroid Build Coastguard Worker AString s('['); 873*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(cur); 874*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(']'); 875*f6dc9357SAndroid Build Coastguard Worker path.Insert(0, s); 876*f6dc9357SAndroid Build Coastguard Worker } 877*f6dc9357SAndroid Build Coastguard Worker else 878*f6dc9357SAndroid Build Coastguard Worker path.Insert(0, item2.Name); 879*f6dc9357SAndroid Build Coastguard Worker if (item2.Parent < 0) 880*f6dc9357SAndroid Build Coastguard Worker break; 881*f6dc9357SAndroid Build Coastguard Worker cur = (unsigned)item2.Parent; 882*f6dc9357SAndroid Build Coastguard Worker } 883*f6dc9357SAndroid Build Coastguard Worker Utf8StringToProp(path, prop); 884*f6dc9357SAndroid Build Coastguard Worker break; 885*f6dc9357SAndroid Build Coastguard Worker } 886*f6dc9357SAndroid Build Coastguard Worker 887*f6dc9357SAndroid Build Coastguard Worker case kpidName: 888*f6dc9357SAndroid Build Coastguard Worker { 889*f6dc9357SAndroid Build Coastguard Worker if (item.Name.IsEmpty()) 890*f6dc9357SAndroid Build Coastguard Worker { 891*f6dc9357SAndroid Build Coastguard Worker AString s('['); 892*f6dc9357SAndroid Build Coastguard Worker s.Add_UInt32(index); 893*f6dc9357SAndroid Build Coastguard Worker s.Add_Char(']'); 894*f6dc9357SAndroid Build Coastguard Worker prop = s; 895*f6dc9357SAndroid Build Coastguard Worker } 896*f6dc9357SAndroid Build Coastguard Worker else 897*f6dc9357SAndroid Build Coastguard Worker Utf8StringToProp(item.Name, prop); 898*f6dc9357SAndroid Build Coastguard Worker break; 899*f6dc9357SAndroid Build Coastguard Worker } 900*f6dc9357SAndroid Build Coastguard Worker 901*f6dc9357SAndroid Build Coastguard Worker case kpidIsDir: prop = item.IsDir; break; 902*f6dc9357SAndroid Build Coastguard Worker 903*f6dc9357SAndroid Build Coastguard Worker case kpidSize: if (item.HasData && !item.IsDir) prop = item.Size; break; 904*f6dc9357SAndroid Build Coastguard Worker case kpidPackSize: if (item.HasData && !item.IsDir) prop = item.PackSize; break; 905*f6dc9357SAndroid Build Coastguard Worker 906*f6dc9357SAndroid Build Coastguard Worker case kpidMethod: 907*f6dc9357SAndroid Build Coastguard Worker { 908*f6dc9357SAndroid Build Coastguard Worker if (item.HasData) 909*f6dc9357SAndroid Build Coastguard Worker { 910*f6dc9357SAndroid Build Coastguard Worker AString s = item.Method; 911*f6dc9357SAndroid Build Coastguard Worker item.extracted_checksum.AddNameToString(s); 912*f6dc9357SAndroid Build Coastguard Worker item.archived_checksum.AddNameToString(s); 913*f6dc9357SAndroid Build Coastguard Worker Utf8StringToProp(s, prop); 914*f6dc9357SAndroid Build Coastguard Worker } 915*f6dc9357SAndroid Build Coastguard Worker break; 916*f6dc9357SAndroid Build Coastguard Worker } 917*f6dc9357SAndroid Build Coastguard Worker 918*f6dc9357SAndroid Build Coastguard Worker case kpidMTime: TimeToProp(item.MTime, prop); break; 919*f6dc9357SAndroid Build Coastguard Worker case kpidCTime: TimeToProp(item.CTime, prop); break; 920*f6dc9357SAndroid Build Coastguard Worker case kpidATime: TimeToProp(item.ATime, prop); break; 921*f6dc9357SAndroid Build Coastguard Worker 922*f6dc9357SAndroid Build Coastguard Worker case kpidPosixAttrib: 923*f6dc9357SAndroid Build Coastguard Worker if (item.Mode_Defined) 924*f6dc9357SAndroid Build Coastguard Worker { 925*f6dc9357SAndroid Build Coastguard Worker UInt32 mode = item.Mode; 926*f6dc9357SAndroid Build Coastguard Worker if ((mode & MY_LIN_S_IFMT) == 0) 927*f6dc9357SAndroid Build Coastguard Worker mode |= ( 928*f6dc9357SAndroid Build Coastguard Worker item.Is_SymLink ? MY_LIN_S_IFLNK : 929*f6dc9357SAndroid Build Coastguard Worker item.IsDir ? MY_LIN_S_IFDIR : 930*f6dc9357SAndroid Build Coastguard Worker MY_LIN_S_IFREG); 931*f6dc9357SAndroid Build Coastguard Worker prop = mode; 932*f6dc9357SAndroid Build Coastguard Worker } 933*f6dc9357SAndroid Build Coastguard Worker break; 934*f6dc9357SAndroid Build Coastguard Worker 935*f6dc9357SAndroid Build Coastguard Worker case kpidType: Utf8StringToProp(item.Type, prop); break; 936*f6dc9357SAndroid Build Coastguard Worker case kpidUser: Utf8StringToProp(item.User, prop); break; 937*f6dc9357SAndroid Build Coastguard Worker case kpidGroup: Utf8StringToProp(item.Group, prop); break; 938*f6dc9357SAndroid Build Coastguard Worker case kpidSymLink: if (item.Is_SymLink) Utf8StringToProp(item.Link, prop); break; 939*f6dc9357SAndroid Build Coastguard Worker 940*f6dc9357SAndroid Build Coastguard Worker case kpidUserId: if (item.UserId_Defined) prop = item.UserId; break; 941*f6dc9357SAndroid Build Coastguard Worker case kpidGroupId: if (item.GroupId_Defined) prop = item.GroupId; break; 942*f6dc9357SAndroid Build Coastguard Worker case kpidINode: if (item.INode_Defined) prop = item.INode; break; 943*f6dc9357SAndroid Build Coastguard Worker case kpidId: if (item.Id_Defined) prop = item.Id; break; 944*f6dc9357SAndroid Build Coastguard Worker // Utf8StringToProp(item.Id, prop); 945*f6dc9357SAndroid Build Coastguard Worker /* 946*f6dc9357SAndroid Build Coastguard Worker case kpidDeviceMajor: if (item.Device_Defined) prop = (UInt32)MY_dev_major(item.Device); break; 947*f6dc9357SAndroid Build Coastguard Worker case kpidDeviceMinor: if (item.Device_Defined) prop = (UInt32)MY_dev_minor(item.Device); break; 948*f6dc9357SAndroid Build Coastguard Worker case kpidLinkType: 949*f6dc9357SAndroid Build Coastguard Worker if (!item.LinkType.IsEmpty()) 950*f6dc9357SAndroid Build Coastguard Worker Utf8StringToProp(item.LinkType, prop); 951*f6dc9357SAndroid Build Coastguard Worker break; 952*f6dc9357SAndroid Build Coastguard Worker case kpidLinkFrom: 953*f6dc9357SAndroid Build Coastguard Worker if (!item.LinkFrom.IsEmpty()) 954*f6dc9357SAndroid Build Coastguard Worker Utf8StringToProp(item.LinkFrom, prop); 955*f6dc9357SAndroid Build Coastguard Worker break; 956*f6dc9357SAndroid Build Coastguard Worker */ 957*f6dc9357SAndroid Build Coastguard Worker case kpidOffset: 958*f6dc9357SAndroid Build Coastguard Worker if (item.HasData) 959*f6dc9357SAndroid Build Coastguard Worker prop = _dataStartPos + item.Offset; 960*f6dc9357SAndroid Build Coastguard Worker break; 961*f6dc9357SAndroid Build Coastguard Worker } 962*f6dc9357SAndroid Build Coastguard Worker } 963*f6dc9357SAndroid Build Coastguard Worker prop.Detach(value); 964*f6dc9357SAndroid Build Coastguard Worker return S_OK; 965*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 966*f6dc9357SAndroid Build Coastguard Worker } 967*f6dc9357SAndroid Build Coastguard Worker 968*f6dc9357SAndroid Build Coastguard Worker 969*f6dc9357SAndroid Build Coastguard Worker // for debug: 970*f6dc9357SAndroid Build Coastguard Worker // #define Z7_XAR_SHOW_CHECKSUM_PACK 971*f6dc9357SAndroid Build Coastguard Worker 972*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_XAR_SHOW_CHECKSUM_PACK 973*f6dc9357SAndroid Build Coastguard Worker enum 974*f6dc9357SAndroid Build Coastguard Worker { 975*f6dc9357SAndroid Build Coastguard Worker kpidChecksumPack = kpidUserDefined 976*f6dc9357SAndroid Build Coastguard Worker }; 977*f6dc9357SAndroid Build Coastguard Worker #endif 978*f6dc9357SAndroid Build Coastguard Worker 979*f6dc9357SAndroid Build Coastguard Worker static const Byte kRawProps[] = 980*f6dc9357SAndroid Build Coastguard Worker { 981*f6dc9357SAndroid Build Coastguard Worker kpidChecksum 982*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_XAR_SHOW_CHECKSUM_PACK 983*f6dc9357SAndroid Build Coastguard Worker , kpidCRC // instead of kpidUserDefined / kpidCRC 984*f6dc9357SAndroid Build Coastguard Worker #endif 985*f6dc9357SAndroid Build Coastguard Worker }; 986*f6dc9357SAndroid Build Coastguard Worker 987*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetNumRawProps(UInt32 *numProps)) 988*f6dc9357SAndroid Build Coastguard Worker { 989*f6dc9357SAndroid Build Coastguard Worker *numProps = Z7_ARRAY_SIZE(kRawProps); 990*f6dc9357SAndroid Build Coastguard Worker return S_OK; 991*f6dc9357SAndroid Build Coastguard Worker } 992*f6dc9357SAndroid Build Coastguard Worker 993*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawPropInfo(UInt32 index, BSTR *name, PROPID *propID)) 994*f6dc9357SAndroid Build Coastguard Worker { 995*f6dc9357SAndroid Build Coastguard Worker *propID = kRawProps[index]; 996*f6dc9357SAndroid Build Coastguard Worker *name = NULL; 997*f6dc9357SAndroid Build Coastguard Worker 998*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_XAR_SHOW_CHECKSUM_PACK 999*f6dc9357SAndroid Build Coastguard Worker if (index != 0) 1000*f6dc9357SAndroid Build Coastguard Worker { 1001*f6dc9357SAndroid Build Coastguard Worker *propID = kpidChecksumPack; 1002*f6dc9357SAndroid Build Coastguard Worker *name = NWindows::NCOM::AllocBstrFromAscii("archived-checksum"); 1003*f6dc9357SAndroid Build Coastguard Worker } 1004*f6dc9357SAndroid Build Coastguard Worker #endif 1005*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1006*f6dc9357SAndroid Build Coastguard Worker } 1007*f6dc9357SAndroid Build Coastguard Worker 1008*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentType)) 1009*f6dc9357SAndroid Build Coastguard Worker { 1010*f6dc9357SAndroid Build Coastguard Worker *parentType = NParentType::kDir; 1011*f6dc9357SAndroid Build Coastguard Worker *parent = (UInt32)(Int32)-1; 1012*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1013*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 1014*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1015*f6dc9357SAndroid Build Coastguard Worker #endif 1016*f6dc9357SAndroid Build Coastguard Worker { 1017*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 1018*f6dc9357SAndroid Build Coastguard Worker *parent = (UInt32)(Int32)item.Parent; 1019*f6dc9357SAndroid Build Coastguard Worker } 1020*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1021*f6dc9357SAndroid Build Coastguard Worker } 1022*f6dc9357SAndroid Build Coastguard Worker 1023*f6dc9357SAndroid Build Coastguard Worker 1024*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetRawProp(UInt32 index, PROPID propID, const void **data, UInt32 *dataSize, UInt32 *propType)) 1025*f6dc9357SAndroid Build Coastguard Worker { 1026*f6dc9357SAndroid Build Coastguard Worker *data = NULL; 1027*f6dc9357SAndroid Build Coastguard Worker *dataSize = 0; 1028*f6dc9357SAndroid Build Coastguard Worker *propType = 0; 1029*f6dc9357SAndroid Build Coastguard Worker 1030*f6dc9357SAndroid Build Coastguard Worker // COM_TRY_BEGIN 1031*f6dc9357SAndroid Build Coastguard Worker NCOM::CPropVariant prop; 1032*f6dc9357SAndroid Build Coastguard Worker 1033*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidChecksum) 1034*f6dc9357SAndroid Build Coastguard Worker { 1035*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1036*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 1037*f6dc9357SAndroid Build Coastguard Worker { 1038*f6dc9357SAndroid Build Coastguard Worker // case kpidPath: prop = "[TOC].xml"; break; 1039*f6dc9357SAndroid Build Coastguard Worker } 1040*f6dc9357SAndroid Build Coastguard Worker else 1041*f6dc9357SAndroid Build Coastguard Worker #endif 1042*f6dc9357SAndroid Build Coastguard Worker { 1043*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 1044*f6dc9357SAndroid Build Coastguard Worker const size_t size = item.extracted_checksum.Data.Size(); 1045*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 1046*f6dc9357SAndroid Build Coastguard Worker { 1047*f6dc9357SAndroid Build Coastguard Worker *dataSize = (UInt32)size; 1048*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw; 1049*f6dc9357SAndroid Build Coastguard Worker *data = item.extracted_checksum.Data; 1050*f6dc9357SAndroid Build Coastguard Worker } 1051*f6dc9357SAndroid Build Coastguard Worker } 1052*f6dc9357SAndroid Build Coastguard Worker } 1053*f6dc9357SAndroid Build Coastguard Worker 1054*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_XAR_SHOW_CHECKSUM_PACK 1055*f6dc9357SAndroid Build Coastguard Worker if (propID == kpidChecksumPack) 1056*f6dc9357SAndroid Build Coastguard Worker { 1057*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1058*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 1059*f6dc9357SAndroid Build Coastguard Worker { 1060*f6dc9357SAndroid Build Coastguard Worker // we can show digest check sum here 1061*f6dc9357SAndroid Build Coastguard Worker } 1062*f6dc9357SAndroid Build Coastguard Worker else 1063*f6dc9357SAndroid Build Coastguard Worker #endif 1064*f6dc9357SAndroid Build Coastguard Worker { 1065*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 1066*f6dc9357SAndroid Build Coastguard Worker const size_t size = (UInt32)item.archived_checksum.Data.Size(); 1067*f6dc9357SAndroid Build Coastguard Worker if (size != 0) 1068*f6dc9357SAndroid Build Coastguard Worker { 1069*f6dc9357SAndroid Build Coastguard Worker *dataSize = (UInt32)size; 1070*f6dc9357SAndroid Build Coastguard Worker *propType = NPropDataType::kRaw; 1071*f6dc9357SAndroid Build Coastguard Worker *data = item.archived_checksum.Data; 1072*f6dc9357SAndroid Build Coastguard Worker } 1073*f6dc9357SAndroid Build Coastguard Worker } 1074*f6dc9357SAndroid Build Coastguard Worker } 1075*f6dc9357SAndroid Build Coastguard Worker #endif 1076*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1077*f6dc9357SAndroid Build Coastguard Worker } 1078*f6dc9357SAndroid Build Coastguard Worker 1079*f6dc9357SAndroid Build Coastguard Worker 1080*f6dc9357SAndroid Build Coastguard Worker 1081*f6dc9357SAndroid Build Coastguard Worker 1082*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::Extract(const UInt32 *indices, UInt32 numItems, 1083*f6dc9357SAndroid Build Coastguard Worker Int32 testMode, IArchiveExtractCallback *extractCallback)) 1084*f6dc9357SAndroid Build Coastguard Worker { 1085*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 1086*f6dc9357SAndroid Build Coastguard Worker const bool allFilesMode = (numItems == (UInt32)(Int32)-1); 1087*f6dc9357SAndroid Build Coastguard Worker if (allFilesMode) 1088*f6dc9357SAndroid Build Coastguard Worker numItems = _files.Size() 1089*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1090*f6dc9357SAndroid Build Coastguard Worker + 1 1091*f6dc9357SAndroid Build Coastguard Worker #endif 1092*f6dc9357SAndroid Build Coastguard Worker ; 1093*f6dc9357SAndroid Build Coastguard Worker if (numItems == 0) 1094*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1095*f6dc9357SAndroid Build Coastguard Worker UInt64 totalSize = 0; 1096*f6dc9357SAndroid Build Coastguard Worker UInt32 i; 1097*f6dc9357SAndroid Build Coastguard Worker for (i = 0; i < numItems; i++) 1098*f6dc9357SAndroid Build Coastguard Worker { 1099*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i]; 1100*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1101*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 1102*f6dc9357SAndroid Build Coastguard Worker totalSize += _xmlLen; 1103*f6dc9357SAndroid Build Coastguard Worker else 1104*f6dc9357SAndroid Build Coastguard Worker #endif 1105*f6dc9357SAndroid Build Coastguard Worker totalSize += _files[index].Size; 1106*f6dc9357SAndroid Build Coastguard Worker } 1107*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetTotal(totalSize)) 1108*f6dc9357SAndroid Build Coastguard Worker 1109*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressProgressInfo, CLocalProgress> lps; 1110*f6dc9357SAndroid Build Coastguard Worker lps->Init(extractCallback, false); 1111*f6dc9357SAndroid Build Coastguard Worker CInStreamWithHash inHashStream; 1112*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha1> outStreamSha1; 1113*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, COutStreamWithSha256> outStreamSha256; 1114*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ISequentialOutStream, CLimitedSequentialOutStream> outStreamLim; 1115*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::CCopyCoder> copyCoder; 1116*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::NZlib::CDecoder> zlibCoder; 1117*f6dc9357SAndroid Build Coastguard Worker CMyComPtr2_Create<ICompressCoder, NCompress::NBZip2::CDecoder> bzip2Coder; 1118*f6dc9357SAndroid Build Coastguard Worker bzip2Coder->FinishMode = true; 1119*f6dc9357SAndroid Build Coastguard Worker 1120*f6dc9357SAndroid Build Coastguard Worker UInt64 cur_PackSize, cur_UnpSize; 1121*f6dc9357SAndroid Build Coastguard Worker 1122*f6dc9357SAndroid Build Coastguard Worker for (i = 0;; i++, 1123*f6dc9357SAndroid Build Coastguard Worker lps->InSize += cur_PackSize, 1124*f6dc9357SAndroid Build Coastguard Worker lps->OutSize += cur_UnpSize) 1125*f6dc9357SAndroid Build Coastguard Worker { 1126*f6dc9357SAndroid Build Coastguard Worker cur_PackSize = 0; 1127*f6dc9357SAndroid Build Coastguard Worker cur_UnpSize = 0; 1128*f6dc9357SAndroid Build Coastguard Worker RINOK(lps->SetCur()) 1129*f6dc9357SAndroid Build Coastguard Worker if (i >= numItems) 1130*f6dc9357SAndroid Build Coastguard Worker break; 1131*f6dc9357SAndroid Build Coastguard Worker 1132*f6dc9357SAndroid Build Coastguard Worker CMyComPtr<ISequentialOutStream> realOutStream; 1133*f6dc9357SAndroid Build Coastguard Worker const Int32 askMode = testMode ? 1134*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kTest : 1135*f6dc9357SAndroid Build Coastguard Worker NExtract::NAskMode::kExtract; 1136*f6dc9357SAndroid Build Coastguard Worker const UInt32 index = allFilesMode ? i : indices[i]; 1137*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->GetStream(index, &realOutStream, askMode)) 1138*f6dc9357SAndroid Build Coastguard Worker 1139*f6dc9357SAndroid Build Coastguard Worker if (index < _files.Size()) 1140*f6dc9357SAndroid Build Coastguard Worker { 1141*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 1142*f6dc9357SAndroid Build Coastguard Worker if (item.IsDir) 1143*f6dc9357SAndroid Build Coastguard Worker { 1144*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode)) 1145*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release(); 1146*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kOK)) 1147*f6dc9357SAndroid Build Coastguard Worker continue; 1148*f6dc9357SAndroid Build Coastguard Worker } 1149*f6dc9357SAndroid Build Coastguard Worker } 1150*f6dc9357SAndroid Build Coastguard Worker 1151*f6dc9357SAndroid Build Coastguard Worker if (!testMode && !realOutStream) 1152*f6dc9357SAndroid Build Coastguard Worker continue; 1153*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->PrepareOperation(askMode)) 1154*f6dc9357SAndroid Build Coastguard Worker 1155*f6dc9357SAndroid Build Coastguard Worker Int32 opRes = NExtract::NOperationResult::kOK; 1156*f6dc9357SAndroid Build Coastguard Worker 1157*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1158*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 1159*f6dc9357SAndroid Build Coastguard Worker { 1160*f6dc9357SAndroid Build Coastguard Worker cur_PackSize = cur_UnpSize = _xmlLen; 1161*f6dc9357SAndroid Build Coastguard Worker if (realOutStream) 1162*f6dc9357SAndroid Build Coastguard Worker RINOK(WriteStream(realOutStream, _xmlBuf, _xmlLen)) 1163*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release(); 1164*f6dc9357SAndroid Build Coastguard Worker } 1165*f6dc9357SAndroid Build Coastguard Worker else 1166*f6dc9357SAndroid Build Coastguard Worker #endif 1167*f6dc9357SAndroid Build Coastguard Worker { 1168*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 1169*f6dc9357SAndroid Build Coastguard Worker if (!item.HasData) 1170*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release(); 1171*f6dc9357SAndroid Build Coastguard Worker else 1172*f6dc9357SAndroid Build Coastguard Worker { 1173*f6dc9357SAndroid Build Coastguard Worker cur_PackSize = item.PackSize; 1174*f6dc9357SAndroid Build Coastguard Worker cur_UnpSize = item.Size; 1175*f6dc9357SAndroid Build Coastguard Worker 1176*f6dc9357SAndroid Build Coastguard Worker RINOK(InStream_SeekSet(_inStream, _dataStartPos + item.Offset)) 1177*f6dc9357SAndroid Build Coastguard Worker 1178*f6dc9357SAndroid Build Coastguard Worker inHashStream.SetStreamAndInit(_inStream, item.archived_checksum.AlgoNumber); 1179*f6dc9357SAndroid Build Coastguard Worker inHashStream.inStreamLim->Init(item.PackSize); 1180*f6dc9357SAndroid Build Coastguard Worker 1181*f6dc9357SAndroid Build Coastguard Worker const int checksum_method = item.extracted_checksum.AlgoNumber; 1182*f6dc9357SAndroid Build Coastguard Worker if (checksum_method == XAR_CKSUM_SHA1) 1183*f6dc9357SAndroid Build Coastguard Worker { 1184*f6dc9357SAndroid Build Coastguard Worker outStreamLim->SetStream(outStreamSha1); 1185*f6dc9357SAndroid Build Coastguard Worker outStreamSha1->SetStream(realOutStream); 1186*f6dc9357SAndroid Build Coastguard Worker outStreamSha1->Init(); 1187*f6dc9357SAndroid Build Coastguard Worker } 1188*f6dc9357SAndroid Build Coastguard Worker else if (checksum_method == XAR_CKSUM_SHA256 1189*f6dc9357SAndroid Build Coastguard Worker || checksum_method == XAR_CKSUM_SHA512) 1190*f6dc9357SAndroid Build Coastguard Worker { 1191*f6dc9357SAndroid Build Coastguard Worker outStreamLim->SetStream(outStreamSha256); 1192*f6dc9357SAndroid Build Coastguard Worker outStreamSha256->SetStream(realOutStream); 1193*f6dc9357SAndroid Build Coastguard Worker outStreamSha256->Init(checksum_method == XAR_CKSUM_SHA512); 1194*f6dc9357SAndroid Build Coastguard Worker } 1195*f6dc9357SAndroid Build Coastguard Worker else 1196*f6dc9357SAndroid Build Coastguard Worker outStreamLim->SetStream(realOutStream); 1197*f6dc9357SAndroid Build Coastguard Worker 1198*f6dc9357SAndroid Build Coastguard Worker realOutStream.Release(); 1199*f6dc9357SAndroid Build Coastguard Worker 1200*f6dc9357SAndroid Build Coastguard Worker // outStreamSha1->Init(item.Sha1IsDefined); 1201*f6dc9357SAndroid Build Coastguard Worker 1202*f6dc9357SAndroid Build Coastguard Worker outStreamLim->Init(item.Size); 1203*f6dc9357SAndroid Build Coastguard Worker HRESULT res = S_OK; 1204*f6dc9357SAndroid Build Coastguard Worker 1205*f6dc9357SAndroid Build Coastguard Worker ICompressCoder *coder = NULL; 1206*f6dc9357SAndroid Build Coastguard Worker if (item.IsCopyMethod()) 1207*f6dc9357SAndroid Build Coastguard Worker { 1208*f6dc9357SAndroid Build Coastguard Worker if (item.PackSize == item.Size) 1209*f6dc9357SAndroid Build Coastguard Worker coder = copyCoder; 1210*f6dc9357SAndroid Build Coastguard Worker else 1211*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnsupportedMethod; 1212*f6dc9357SAndroid Build Coastguard Worker } 1213*f6dc9357SAndroid Build Coastguard Worker else if (item.Method == METHOD_NAME_ZLIB) 1214*f6dc9357SAndroid Build Coastguard Worker coder = zlibCoder; 1215*f6dc9357SAndroid Build Coastguard Worker else if (item.Method == "bzip2") 1216*f6dc9357SAndroid Build Coastguard Worker coder = bzip2Coder; 1217*f6dc9357SAndroid Build Coastguard Worker else 1218*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kUnsupportedMethod; 1219*f6dc9357SAndroid Build Coastguard Worker 1220*f6dc9357SAndroid Build Coastguard Worker if (coder) 1221*f6dc9357SAndroid Build Coastguard Worker res = coder->Code(inHashStream.inStreamLim, outStreamLim, NULL, &item.Size, lps); 1222*f6dc9357SAndroid Build Coastguard Worker 1223*f6dc9357SAndroid Build Coastguard Worker if (res != S_OK) 1224*f6dc9357SAndroid Build Coastguard Worker { 1225*f6dc9357SAndroid Build Coastguard Worker if (!outStreamLim->IsFinishedOK()) 1226*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1227*f6dc9357SAndroid Build Coastguard Worker else if (res != S_FALSE) 1228*f6dc9357SAndroid Build Coastguard Worker return res; 1229*f6dc9357SAndroid Build Coastguard Worker if (opRes == NExtract::NOperationResult::kOK) 1230*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1231*f6dc9357SAndroid Build Coastguard Worker } 1232*f6dc9357SAndroid Build Coastguard Worker 1233*f6dc9357SAndroid Build Coastguard Worker if (opRes == NExtract::NOperationResult::kOK) 1234*f6dc9357SAndroid Build Coastguard Worker { 1235*f6dc9357SAndroid Build Coastguard Worker if (outStreamLim->IsFinishedOK()) 1236*f6dc9357SAndroid Build Coastguard Worker { 1237*f6dc9357SAndroid Build Coastguard Worker if (checksum_method == XAR_CKSUM_SHA1) 1238*f6dc9357SAndroid Build Coastguard Worker { 1239*f6dc9357SAndroid Build Coastguard Worker Byte digest[SHA1_DIGEST_SIZE]; 1240*f6dc9357SAndroid Build Coastguard Worker outStreamSha1->Final(digest); 1241*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, item.extracted_checksum.Data, SHA1_DIGEST_SIZE) != 0) 1242*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kCRCError; 1243*f6dc9357SAndroid Build Coastguard Worker } 1244*f6dc9357SAndroid Build Coastguard Worker else if (checksum_method == XAR_CKSUM_SHA256) 1245*f6dc9357SAndroid Build Coastguard Worker { 1246*f6dc9357SAndroid Build Coastguard Worker Byte digest[SHA256_DIGEST_SIZE]; 1247*f6dc9357SAndroid Build Coastguard Worker outStreamSha256->Final256(digest); 1248*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0) 1249*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kCRCError; 1250*f6dc9357SAndroid Build Coastguard Worker } 1251*f6dc9357SAndroid Build Coastguard Worker else if (checksum_method == XAR_CKSUM_SHA512) 1252*f6dc9357SAndroid Build Coastguard Worker { 1253*f6dc9357SAndroid Build Coastguard Worker Byte digest[SHA512_DIGEST_SIZE]; 1254*f6dc9357SAndroid Build Coastguard Worker outStreamSha256->Final512(digest); 1255*f6dc9357SAndroid Build Coastguard Worker if (memcmp(digest, item.extracted_checksum.Data, sizeof(digest)) != 0) 1256*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kCRCError; 1257*f6dc9357SAndroid Build Coastguard Worker } 1258*f6dc9357SAndroid Build Coastguard Worker if (opRes == NExtract::NOperationResult::kOK) 1259*f6dc9357SAndroid Build Coastguard Worker if (!inHashStream.CheckHash( 1260*f6dc9357SAndroid Build Coastguard Worker item.archived_checksum.AlgoNumber, 1261*f6dc9357SAndroid Build Coastguard Worker item.archived_checksum.Data)) 1262*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kCRCError; 1263*f6dc9357SAndroid Build Coastguard Worker } 1264*f6dc9357SAndroid Build Coastguard Worker else 1265*f6dc9357SAndroid Build Coastguard Worker opRes = NExtract::NOperationResult::kDataError; 1266*f6dc9357SAndroid Build Coastguard Worker } 1267*f6dc9357SAndroid Build Coastguard Worker if (checksum_method == XAR_CKSUM_SHA1) 1268*f6dc9357SAndroid Build Coastguard Worker outStreamSha1->ReleaseStream(); 1269*f6dc9357SAndroid Build Coastguard Worker else if (checksum_method == XAR_CKSUM_SHA256) 1270*f6dc9357SAndroid Build Coastguard Worker outStreamSha256->ReleaseStream(); 1271*f6dc9357SAndroid Build Coastguard Worker } 1272*f6dc9357SAndroid Build Coastguard Worker outStreamLim->ReleaseStream(); 1273*f6dc9357SAndroid Build Coastguard Worker } 1274*f6dc9357SAndroid Build Coastguard Worker RINOK(extractCallback->SetOperationResult(opRes)) 1275*f6dc9357SAndroid Build Coastguard Worker } 1276*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1277*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 1278*f6dc9357SAndroid Build Coastguard Worker } 1279*f6dc9357SAndroid Build Coastguard Worker 1280*f6dc9357SAndroid Build Coastguard Worker Z7_COM7F_IMF(CHandler::GetStream(UInt32 index, ISequentialInStream **stream)) 1281*f6dc9357SAndroid Build Coastguard Worker { 1282*f6dc9357SAndroid Build Coastguard Worker *stream = NULL; 1283*f6dc9357SAndroid Build Coastguard Worker COM_TRY_BEGIN 1284*f6dc9357SAndroid Build Coastguard Worker #ifdef XAR_SHOW_RAW 1285*f6dc9357SAndroid Build Coastguard Worker if (index >= _files.Size()) 1286*f6dc9357SAndroid Build Coastguard Worker { 1287*f6dc9357SAndroid Build Coastguard Worker Create_BufInStream_WithNewBuffer(_xmlBuf, _xmlLen, stream); 1288*f6dc9357SAndroid Build Coastguard Worker return S_OK; 1289*f6dc9357SAndroid Build Coastguard Worker } 1290*f6dc9357SAndroid Build Coastguard Worker else 1291*f6dc9357SAndroid Build Coastguard Worker #endif 1292*f6dc9357SAndroid Build Coastguard Worker { 1293*f6dc9357SAndroid Build Coastguard Worker const CFile &item = _files[index]; 1294*f6dc9357SAndroid Build Coastguard Worker if (item.HasData && item.IsCopyMethod() && item.PackSize == item.Size) 1295*f6dc9357SAndroid Build Coastguard Worker return CreateLimitedInStream(_inStream, _dataStartPos + item.Offset, item.Size, stream); 1296*f6dc9357SAndroid Build Coastguard Worker } 1297*f6dc9357SAndroid Build Coastguard Worker return S_FALSE; 1298*f6dc9357SAndroid Build Coastguard Worker COM_TRY_END 1299*f6dc9357SAndroid Build Coastguard Worker } 1300*f6dc9357SAndroid Build Coastguard Worker 1301*f6dc9357SAndroid Build Coastguard Worker // 0x1c == 28 is expected header size value for most archives. 1302*f6dc9357SAndroid Build Coastguard Worker // but we want to support another (rare case) headers sizes. 1303*f6dc9357SAndroid Build Coastguard Worker // so we must reduce signature to 4 or 5 bytes. 1304*f6dc9357SAndroid Build Coastguard Worker static const Byte k_Signature[] = 1305*f6dc9357SAndroid Build Coastguard Worker // { 'x', 'a', 'r', '!', 0, 0x1C, 0 }; 1306*f6dc9357SAndroid Build Coastguard Worker { 'x', 'a', 'r', '!', 0 }; 1307*f6dc9357SAndroid Build Coastguard Worker 1308*f6dc9357SAndroid Build Coastguard Worker REGISTER_ARC_I( 1309*f6dc9357SAndroid Build Coastguard Worker "Xar", "xar pkg xip", NULL, 0xE1, 1310*f6dc9357SAndroid Build Coastguard Worker k_Signature, 1311*f6dc9357SAndroid Build Coastguard Worker 0, 1312*f6dc9357SAndroid Build Coastguard Worker 0, 1313*f6dc9357SAndroid Build Coastguard Worker NULL) 1314*f6dc9357SAndroid Build Coastguard Worker 1315*f6dc9357SAndroid Build Coastguard Worker }} 1316