annotate src/win32/7zip/7z/CPP/7zip/Archive/Rar/RarIn.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
rev   line source
rlm@1 1 // Archive/RarIn.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "Common/StringConvert.h"
rlm@1 6 #include "Common/UTFConvert.h"
rlm@1 7
rlm@1 8 #include "RarIn.h"
rlm@1 9 #include "../../Common/LimitedStreams.h"
rlm@1 10 #include "../../Common/StreamUtils.h"
rlm@1 11
rlm@1 12 #include "../Common/FindSignature.h"
rlm@1 13
rlm@1 14 extern "C"
rlm@1 15 {
rlm@1 16 #include "../../../../C/7zCrc.h"
rlm@1 17 }
rlm@1 18
rlm@1 19 namespace NArchive {
rlm@1 20 namespace NRar {
rlm@1 21
rlm@1 22 void CInArchive::ThrowExceptionWithCode(
rlm@1 23 CInArchiveException::CCauseType cause)
rlm@1 24 {
rlm@1 25 throw CInArchiveException(cause);
rlm@1 26 }
rlm@1 27
rlm@1 28 HRESULT CInArchive::Open(IInStream *inStream, const UInt64 *searchHeaderSizeLimit)
rlm@1 29 {
rlm@1 30 try
rlm@1 31 {
rlm@1 32 Close();
rlm@1 33 HRESULT res = Open2(inStream, searchHeaderSizeLimit);
rlm@1 34 if (res == S_OK)
rlm@1 35 return res;
rlm@1 36 Close();
rlm@1 37 return res;
rlm@1 38 }
rlm@1 39 catch(...) { Close(); throw; }
rlm@1 40 }
rlm@1 41
rlm@1 42 void CInArchive::Close()
rlm@1 43 {
rlm@1 44 m_Stream.Release();
rlm@1 45 }
rlm@1 46
rlm@1 47
rlm@1 48 static inline bool TestMarkerCandidate(const void *aTestBytes)
rlm@1 49 {
rlm@1 50 for (UInt32 i = 0; i < NHeader::kMarkerSize; i++)
rlm@1 51 if (((const Byte *)aTestBytes)[i] != NHeader::kMarker[i])
rlm@1 52 return false;
rlm@1 53 return true;
rlm@1 54 }
rlm@1 55
rlm@1 56 HRESULT CInArchive::FindAndReadMarker(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
rlm@1 57 {
rlm@1 58 RINOK(FindSignatureInStream(stream,
rlm@1 59 NHeader::kMarker, NHeader::kMarkerSize,
rlm@1 60 searchHeaderSizeLimit, m_ArchiveStartPosition));
rlm@1 61 m_Stream = stream;
rlm@1 62 m_Position = m_ArchiveStartPosition + NHeader::kMarkerSize;
rlm@1 63 return m_Stream->Seek(m_Position, STREAM_SEEK_SET, NULL);
rlm@1 64 }
rlm@1 65
rlm@1 66 void CInArchive::ThrowUnexpectedEndOfArchiveException()
rlm@1 67 {
rlm@1 68 ThrowExceptionWithCode(CInArchiveException::kUnexpectedEndOfArchive);
rlm@1 69 }
rlm@1 70
rlm@1 71 bool CInArchive::ReadBytesAndTestSize(void *data, UInt32 size)
rlm@1 72 {
rlm@1 73 if (m_CryptoMode)
rlm@1 74 {
rlm@1 75 const Byte *bufData = (const Byte *)m_DecryptedData;
rlm@1 76 UInt32 bufSize = m_DecryptedDataSize;
rlm@1 77 UInt32 i;
rlm@1 78 for (i = 0; i < size && m_CryptoPos < bufSize; i++)
rlm@1 79 ((Byte *)data)[i] = bufData[m_CryptoPos++];
rlm@1 80 return (i == size);
rlm@1 81 }
rlm@1 82 return (ReadStream_FALSE(m_Stream, data, size) == S_OK);
rlm@1 83 }
rlm@1 84
rlm@1 85 void CInArchive::ReadBytesAndTestResult(void *data, UInt32 size)
rlm@1 86 {
rlm@1 87 if(!ReadBytesAndTestSize(data,size))
rlm@1 88 ThrowUnexpectedEndOfArchiveException();
rlm@1 89 }
rlm@1 90
rlm@1 91 HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 *processedSize)
rlm@1 92 {
rlm@1 93 size_t realProcessedSize = size;
rlm@1 94 HRESULT result = ReadStream(m_Stream, data, &realProcessedSize);
rlm@1 95 if (processedSize != NULL)
rlm@1 96 *processedSize = (UInt32)realProcessedSize;
rlm@1 97 AddToSeekValue(realProcessedSize);
rlm@1 98 return result;
rlm@1 99 }
rlm@1 100
rlm@1 101 static UInt32 CrcUpdateUInt16(UInt32 crc, UInt16 v)
rlm@1 102 {
rlm@1 103 crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
rlm@1 104 crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
rlm@1 105 return crc;
rlm@1 106 }
rlm@1 107
rlm@1 108 static UInt32 CrcUpdateUInt32(UInt32 crc, UInt32 v)
rlm@1 109 {
rlm@1 110 crc = CRC_UPDATE_BYTE(crc, (Byte)(v & 0xFF));
rlm@1 111 crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 8) & 0xFF));
rlm@1 112 crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 16) & 0xFF));
rlm@1 113 crc = CRC_UPDATE_BYTE(crc, (Byte)((v >> 24) & 0xFF));
rlm@1 114 return crc;
rlm@1 115 }
rlm@1 116
rlm@1 117
rlm@1 118 HRESULT CInArchive::Open2(IInStream *stream, const UInt64 *searchHeaderSizeLimit)
rlm@1 119 {
rlm@1 120 m_CryptoMode = false;
rlm@1 121 RINOK(stream->Seek(0, STREAM_SEEK_SET, &m_StreamStartPosition));
rlm@1 122 m_Position = m_StreamStartPosition;
rlm@1 123
rlm@1 124 RINOK(FindAndReadMarker(stream, searchHeaderSizeLimit));
rlm@1 125
rlm@1 126 Byte buf[NHeader::NArchive::kArchiveHeaderSize];
rlm@1 127 UInt32 processedSize;
rlm@1 128 ReadBytes(buf, sizeof(buf), &processedSize);
rlm@1 129 if (processedSize != sizeof(buf))
rlm@1 130 return S_FALSE;
rlm@1 131 m_CurData = buf;
rlm@1 132 m_CurPos = 0;
rlm@1 133 m_PosLimit = sizeof(buf);
rlm@1 134
rlm@1 135 m_ArchiveHeader.CRC = ReadUInt16();
rlm@1 136 m_ArchiveHeader.Type = ReadByte();
rlm@1 137 m_ArchiveHeader.Flags = ReadUInt16();
rlm@1 138 m_ArchiveHeader.Size = ReadUInt16();
rlm@1 139 m_ArchiveHeader.Reserved1 = ReadUInt16();
rlm@1 140 m_ArchiveHeader.Reserved2 = ReadUInt32();
rlm@1 141 m_ArchiveHeader.EncryptVersion = 0;
rlm@1 142
rlm@1 143 UInt32 crc = CRC_INIT_VAL;
rlm@1 144 crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.Type);
rlm@1 145 crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Flags);
rlm@1 146 crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Size);
rlm@1 147 crc = CrcUpdateUInt16(crc, m_ArchiveHeader.Reserved1);
rlm@1 148 crc = CrcUpdateUInt32(crc, m_ArchiveHeader.Reserved2);
rlm@1 149
rlm@1 150 if (m_ArchiveHeader.IsThereEncryptVer() && m_ArchiveHeader.Size > NHeader::NArchive::kArchiveHeaderSize)
rlm@1 151 {
rlm@1 152 ReadBytes(&m_ArchiveHeader.EncryptVersion, 1, &processedSize);
rlm@1 153 if (processedSize != 1)
rlm@1 154 return S_FALSE;
rlm@1 155 crc = CRC_UPDATE_BYTE(crc, m_ArchiveHeader.EncryptVersion);
rlm@1 156 }
rlm@1 157
rlm@1 158 if(m_ArchiveHeader.CRC != (CRC_GET_DIGEST(crc) & 0xFFFF))
rlm@1 159 ThrowExceptionWithCode(CInArchiveException::kArchiveHeaderCRCError);
rlm@1 160 if (m_ArchiveHeader.Type != NHeader::NBlockType::kArchiveHeader)
rlm@1 161 return S_FALSE;
rlm@1 162 m_ArchiveCommentPosition = m_Position;
rlm@1 163 m_SeekOnArchiveComment = true;
rlm@1 164 return S_OK;
rlm@1 165 }
rlm@1 166
rlm@1 167 void CInArchive::SkipArchiveComment()
rlm@1 168 {
rlm@1 169 if (!m_SeekOnArchiveComment)
rlm@1 170 return;
rlm@1 171 AddToSeekValue(m_ArchiveHeader.Size - m_ArchiveHeader.GetBaseSize());
rlm@1 172 m_SeekOnArchiveComment = false;
rlm@1 173 }
rlm@1 174
rlm@1 175 void CInArchive::GetArchiveInfo(CInArchiveInfo &archiveInfo) const
rlm@1 176 {
rlm@1 177 archiveInfo.StartPosition = m_ArchiveStartPosition;
rlm@1 178 archiveInfo.Flags = m_ArchiveHeader.Flags;
rlm@1 179 archiveInfo.CommentPosition = m_ArchiveCommentPosition;
rlm@1 180 archiveInfo.CommentSize = (UInt16)(m_ArchiveHeader.Size - NHeader::NArchive::kArchiveHeaderSize);
rlm@1 181 }
rlm@1 182
rlm@1 183 static void DecodeUnicodeFileName(const char *name, const Byte *encName,
rlm@1 184 int encSize, wchar_t *unicodeName, int maxDecSize)
rlm@1 185 {
rlm@1 186 int encPos = 0;
rlm@1 187 int decPos = 0;
rlm@1 188 int flagBits = 0;
rlm@1 189 Byte flags = 0;
rlm@1 190 Byte highByte = encName[encPos++];
rlm@1 191 while (encPos < encSize && decPos < maxDecSize)
rlm@1 192 {
rlm@1 193 if (flagBits == 0)
rlm@1 194 {
rlm@1 195 flags = encName[encPos++];
rlm@1 196 flagBits = 8;
rlm@1 197 }
rlm@1 198 switch(flags >> 6)
rlm@1 199 {
rlm@1 200 case 0:
rlm@1 201 unicodeName[decPos++] = encName[encPos++];
rlm@1 202 break;
rlm@1 203 case 1:
rlm@1 204 unicodeName[decPos++] = (wchar_t)(encName[encPos++] + (highByte << 8));
rlm@1 205 break;
rlm@1 206 case 2:
rlm@1 207 unicodeName[decPos++] = (wchar_t)(encName[encPos] + (encName[encPos + 1] << 8));
rlm@1 208 encPos += 2;
rlm@1 209 break;
rlm@1 210 case 3:
rlm@1 211 {
rlm@1 212 int length = encName[encPos++];
rlm@1 213 if (length & 0x80)
rlm@1 214 {
rlm@1 215 Byte correction = encName[encPos++];
rlm@1 216 for (length = (length & 0x7f) + 2;
rlm@1 217 length > 0 && decPos < maxDecSize; length--, decPos++)
rlm@1 218 unicodeName[decPos] = (wchar_t)(((name[decPos] + correction) & 0xff) + (highByte << 8));
rlm@1 219 }
rlm@1 220 else
rlm@1 221 for (length += 2; length > 0 && decPos < maxDecSize; length--, decPos++)
rlm@1 222 unicodeName[decPos] = name[decPos];
rlm@1 223 }
rlm@1 224 break;
rlm@1 225 }
rlm@1 226 flags <<= 2;
rlm@1 227 flagBits -= 2;
rlm@1 228 }
rlm@1 229 unicodeName[decPos < maxDecSize ? decPos : maxDecSize - 1] = 0;
rlm@1 230 }
rlm@1 231
rlm@1 232 void CInArchive::ReadName(CItemEx &item, int nameSize)
rlm@1 233 {
rlm@1 234 item.UnicodeName.Empty();
rlm@1 235 if (nameSize > 0)
rlm@1 236 {
rlm@1 237 m_NameBuffer.EnsureCapacity(nameSize + 1);
rlm@1 238 char *buffer = (char *)m_NameBuffer;
rlm@1 239
rlm@1 240 for (int i = 0; i < nameSize; i++)
rlm@1 241 buffer[i] = ReadByte();
rlm@1 242
rlm@1 243 int mainLen;
rlm@1 244 for (mainLen = 0; mainLen < nameSize; mainLen++)
rlm@1 245 if (buffer[mainLen] == '\0')
rlm@1 246 break;
rlm@1 247 buffer[mainLen] = '\0';
rlm@1 248 item.Name = buffer;
rlm@1 249
rlm@1 250 if(item.HasUnicodeName())
rlm@1 251 {
rlm@1 252 if(mainLen < nameSize)
rlm@1 253 {
rlm@1 254 int unicodeNameSizeMax = MyMin(nameSize, (0x400));
rlm@1 255 _unicodeNameBuffer.EnsureCapacity(unicodeNameSizeMax + 1);
rlm@1 256 DecodeUnicodeFileName(buffer, (const Byte *)buffer + mainLen + 1,
rlm@1 257 nameSize - (mainLen + 1), _unicodeNameBuffer, unicodeNameSizeMax);
rlm@1 258 item.UnicodeName = _unicodeNameBuffer;
rlm@1 259 }
rlm@1 260 else if (!ConvertUTF8ToUnicode(item.Name, item.UnicodeName))
rlm@1 261 item.UnicodeName.Empty();
rlm@1 262 }
rlm@1 263 }
rlm@1 264 else
rlm@1 265 item.Name.Empty();
rlm@1 266 }
rlm@1 267
rlm@1 268 Byte CInArchive::ReadByte()
rlm@1 269 {
rlm@1 270 if (m_CurPos >= m_PosLimit)
rlm@1 271 throw CInArchiveException(CInArchiveException::kIncorrectArchive);
rlm@1 272 return m_CurData[m_CurPos++];
rlm@1 273 }
rlm@1 274
rlm@1 275 UInt16 CInArchive::ReadUInt16()
rlm@1 276 {
rlm@1 277 UInt16 value = 0;
rlm@1 278 for (int i = 0; i < 2; i++)
rlm@1 279 {
rlm@1 280 Byte b = ReadByte();
rlm@1 281 value |= (UInt16(b) << (8 * i));
rlm@1 282 }
rlm@1 283 return value;
rlm@1 284 }
rlm@1 285
rlm@1 286 UInt32 CInArchive::ReadUInt32()
rlm@1 287 {
rlm@1 288 UInt32 value = 0;
rlm@1 289 for (int i = 0; i < 4; i++)
rlm@1 290 {
rlm@1 291 Byte b = ReadByte();
rlm@1 292 value |= (UInt32(b) << (8 * i));
rlm@1 293 }
rlm@1 294 return value;
rlm@1 295 }
rlm@1 296
rlm@1 297 void CInArchive::ReadTime(Byte mask, CRarTime &rarTime)
rlm@1 298 {
rlm@1 299 rarTime.LowSecond = (Byte)(((mask & 4) != 0) ? 1 : 0);
rlm@1 300 int numDigits = (mask & 3);
rlm@1 301 rarTime.SubTime[0] = rarTime.SubTime[1] = rarTime.SubTime[2] = 0;
rlm@1 302 for (int i = 0; i < numDigits; i++)
rlm@1 303 rarTime.SubTime[3 - numDigits + i] = ReadByte();
rlm@1 304 }
rlm@1 305
rlm@1 306 void CInArchive::ReadHeaderReal(CItemEx &item)
rlm@1 307 {
rlm@1 308 item.Flags = m_BlockHeader.Flags;
rlm@1 309 item.PackSize = ReadUInt32();
rlm@1 310 item.Size = ReadUInt32();
rlm@1 311 item.HostOS = ReadByte();
rlm@1 312 item.FileCRC = ReadUInt32();
rlm@1 313 item.MTime.DosTime = ReadUInt32();
rlm@1 314 item.UnPackVersion = ReadByte();
rlm@1 315 item.Method = ReadByte();
rlm@1 316 int nameSize = ReadUInt16();
rlm@1 317 item.Attrib = ReadUInt32();
rlm@1 318
rlm@1 319 item.MTime.LowSecond = 0;
rlm@1 320 item.MTime.SubTime[0] =
rlm@1 321 item.MTime.SubTime[1] =
rlm@1 322 item.MTime.SubTime[2] = 0;
rlm@1 323
rlm@1 324 if((item.Flags & NHeader::NFile::kSize64Bits) != 0)
rlm@1 325 {
rlm@1 326 item.PackSize |= ((UInt64)ReadUInt32() << 32);
rlm@1 327 item.Size |= ((UInt64)ReadUInt32() << 32);
rlm@1 328 }
rlm@1 329
rlm@1 330 ReadName(item, nameSize);
rlm@1 331
rlm@1 332 if (item.HasSalt())
rlm@1 333 for (int i = 0; i < sizeof(item.Salt); i++)
rlm@1 334 item.Salt[i] = ReadByte();
rlm@1 335
rlm@1 336 // some rar archives have HasExtTime flag without field.
rlm@1 337 if (m_CurPos < m_PosLimit && item.HasExtTime())
rlm@1 338 {
rlm@1 339 Byte accessMask = (Byte)(ReadByte() >> 4);
rlm@1 340 Byte b = ReadByte();
rlm@1 341 Byte modifMask = (Byte)(b >> 4);
rlm@1 342 Byte createMask = (Byte)(b & 0xF);
rlm@1 343 if ((modifMask & 8) != 0)
rlm@1 344 ReadTime(modifMask, item.MTime);
rlm@1 345 item.CTimeDefined = ((createMask & 8) != 0);
rlm@1 346 if (item.CTimeDefined)
rlm@1 347 {
rlm@1 348 item.CTime.DosTime = ReadUInt32();
rlm@1 349 ReadTime(createMask, item.CTime);
rlm@1 350 }
rlm@1 351 item.ATimeDefined = ((accessMask & 8) != 0);
rlm@1 352 if (item.ATimeDefined)
rlm@1 353 {
rlm@1 354 item.ATime.DosTime = ReadUInt32();
rlm@1 355 ReadTime(accessMask, item.ATime);
rlm@1 356 }
rlm@1 357 }
rlm@1 358
rlm@1 359 UInt16 fileHeaderWithNameSize = (UInt16)m_CurPos;
rlm@1 360
rlm@1 361 item.Position = m_Position;
rlm@1 362 item.MainPartSize = fileHeaderWithNameSize;
rlm@1 363 item.CommentSize = (UInt16)(m_BlockHeader.HeadSize - fileHeaderWithNameSize);
rlm@1 364
rlm@1 365 if (m_CryptoMode)
rlm@1 366 item.AlignSize = (UInt16)((16 - ((m_BlockHeader.HeadSize) & 0xF)) & 0xF);
rlm@1 367 else
rlm@1 368 item.AlignSize = 0;
rlm@1 369 AddToSeekValue(m_BlockHeader.HeadSize);
rlm@1 370 }
rlm@1 371
rlm@1 372 void CInArchive::AddToSeekValue(UInt64 addValue)
rlm@1 373 {
rlm@1 374 m_Position += addValue;
rlm@1 375 }
rlm@1 376
rlm@1 377 HRESULT CInArchive::GetNextItem(CItemEx &item, ICryptoGetTextPassword *getTextPassword)
rlm@1 378 {
rlm@1 379 if (m_SeekOnArchiveComment)
rlm@1 380 SkipArchiveComment();
rlm@1 381 for (;;)
rlm@1 382 {
rlm@1 383 if(!SeekInArchive(m_Position))
rlm@1 384 return S_FALSE;
rlm@1 385 if (!m_CryptoMode && (m_ArchiveHeader.Flags &
rlm@1 386 NHeader::NArchive::kBlockHeadersAreEncrypted) != 0)
rlm@1 387 {
rlm@1 388 m_CryptoMode = false;
rlm@1 389 if (getTextPassword == 0)
rlm@1 390 return S_FALSE;
rlm@1 391 if(!SeekInArchive(m_Position))
rlm@1 392 return S_FALSE;
rlm@1 393 if (!m_RarAES)
rlm@1 394 {
rlm@1 395 m_RarAESSpec = new NCrypto::NRar29::CDecoder;
rlm@1 396 m_RarAES = m_RarAESSpec;
rlm@1 397 }
rlm@1 398 m_RarAESSpec->SetRar350Mode(m_ArchiveHeader.IsEncryptOld());
rlm@1 399
rlm@1 400 // Salt
rlm@1 401 const UInt32 kSaltSize = 8;
rlm@1 402 Byte salt[kSaltSize];
rlm@1 403 if(!ReadBytesAndTestSize(salt, kSaltSize))
rlm@1 404 return S_FALSE;
rlm@1 405 m_Position += kSaltSize;
rlm@1 406 RINOK(m_RarAESSpec->SetDecoderProperties2(salt, kSaltSize))
rlm@1 407 // Password
rlm@1 408 CMyComBSTR password;
rlm@1 409 RINOK(getTextPassword->CryptoGetTextPassword(&password))
rlm@1 410 UString unicodePassword(password);
rlm@1 411
rlm@1 412 CByteBuffer buffer;
rlm@1 413 const UInt32 sizeInBytes = unicodePassword.Length() * 2;
rlm@1 414 buffer.SetCapacity(sizeInBytes);
rlm@1 415 for (int i = 0; i < unicodePassword.Length(); i++)
rlm@1 416 {
rlm@1 417 wchar_t c = unicodePassword[i];
rlm@1 418 ((Byte *)buffer)[i * 2] = (Byte)c;
rlm@1 419 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
rlm@1 420 }
rlm@1 421
rlm@1 422 RINOK(m_RarAESSpec->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
rlm@1 423
rlm@1 424 const UInt32 kDecryptedBufferSize = (1 << 12);
rlm@1 425 if (m_DecryptedData.GetCapacity() == 0)
rlm@1 426 {
rlm@1 427 m_DecryptedData.SetCapacity(kDecryptedBufferSize);
rlm@1 428 }
rlm@1 429 RINOK(m_RarAES->Init());
rlm@1 430 size_t decryptedDataSizeT = kDecryptedBufferSize;
rlm@1 431 RINOK(ReadStream(m_Stream, (Byte *)m_DecryptedData, &decryptedDataSizeT));
rlm@1 432 m_DecryptedDataSize = (UInt32)decryptedDataSizeT;
rlm@1 433 m_DecryptedDataSize = m_RarAES->Filter((Byte *)m_DecryptedData, m_DecryptedDataSize);
rlm@1 434
rlm@1 435 m_CryptoMode = true;
rlm@1 436 m_CryptoPos = 0;
rlm@1 437 }
rlm@1 438
rlm@1 439 m_FileHeaderData.EnsureCapacity(7);
rlm@1 440 if(!ReadBytesAndTestSize((Byte *)m_FileHeaderData, 7))
rlm@1 441 return S_FALSE;
rlm@1 442
rlm@1 443 m_CurData = (Byte *)m_FileHeaderData;
rlm@1 444 m_CurPos = 0;
rlm@1 445 m_PosLimit = 7;
rlm@1 446 m_BlockHeader.CRC = ReadUInt16();
rlm@1 447 m_BlockHeader.Type = ReadByte();
rlm@1 448 m_BlockHeader.Flags = ReadUInt16();
rlm@1 449 m_BlockHeader.HeadSize = ReadUInt16();
rlm@1 450
rlm@1 451 if (m_BlockHeader.HeadSize < 7)
rlm@1 452 ThrowExceptionWithCode(CInArchiveException::kIncorrectArchive);
rlm@1 453
rlm@1 454 if (m_BlockHeader.Type == NHeader::NBlockType::kEndOfArchive)
rlm@1 455 return S_FALSE;
rlm@1 456
rlm@1 457 if (m_BlockHeader.Type == NHeader::NBlockType::kFileHeader)
rlm@1 458 {
rlm@1 459 m_FileHeaderData.EnsureCapacity(m_BlockHeader.HeadSize);
rlm@1 460 m_CurData = (Byte *)m_FileHeaderData;
rlm@1 461 m_PosLimit = m_BlockHeader.HeadSize;
rlm@1 462 ReadBytesAndTestResult(m_CurData + m_CurPos, m_BlockHeader.HeadSize - 7);
rlm@1 463 ReadHeaderReal(item);
rlm@1 464 if ((CrcCalc(m_CurData + 2,
rlm@1 465 m_BlockHeader.HeadSize - item.CommentSize - 2) & 0xFFFF) != m_BlockHeader.CRC)
rlm@1 466 ThrowExceptionWithCode(CInArchiveException::kFileHeaderCRCError);
rlm@1 467
rlm@1 468 FinishCryptoBlock();
rlm@1 469 m_CryptoMode = false;
rlm@1 470 SeekInArchive(m_Position); // Move Position to compressed Data;
rlm@1 471 AddToSeekValue(item.PackSize); // m_Position points to next header;
rlm@1 472 return S_OK;
rlm@1 473 }
rlm@1 474 if (m_CryptoMode && m_BlockHeader.HeadSize > (1 << 12))
rlm@1 475 return E_FAIL; // it's for bad passwords
rlm@1 476 if ((m_BlockHeader.Flags & NHeader::NBlock::kLongBlock) != 0)
rlm@1 477 {
rlm@1 478 m_FileHeaderData.EnsureCapacity(7 + 4);
rlm@1 479 m_CurData = (Byte *)m_FileHeaderData;
rlm@1 480 ReadBytesAndTestResult(m_CurData + m_CurPos, 4); // test it
rlm@1 481 m_PosLimit = 7 + 4;
rlm@1 482 UInt32 dataSize = ReadUInt32();
rlm@1 483 AddToSeekValue(dataSize);
rlm@1 484 if (m_CryptoMode && dataSize > (1 << 27))
rlm@1 485 return E_FAIL; // it's for bad passwords
rlm@1 486 m_CryptoPos = m_BlockHeader.HeadSize;
rlm@1 487 }
rlm@1 488 else
rlm@1 489 m_CryptoPos = 0;
rlm@1 490 AddToSeekValue(m_BlockHeader.HeadSize);
rlm@1 491 FinishCryptoBlock();
rlm@1 492 m_CryptoMode = false;
rlm@1 493 }
rlm@1 494 }
rlm@1 495
rlm@1 496 bool CInArchive::SeekInArchive(UInt64 position)
rlm@1 497 {
rlm@1 498 UInt64 newPosition;
rlm@1 499 m_Stream->Seek(position, STREAM_SEEK_SET, &newPosition);
rlm@1 500 return newPosition == position;
rlm@1 501 }
rlm@1 502
rlm@1 503 ISequentialInStream* CInArchive::CreateLimitedStream(UInt64 position, UInt64 size)
rlm@1 504 {
rlm@1 505 CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
rlm@1 506 CMyComPtr<ISequentialInStream> inStream(streamSpec);
rlm@1 507 SeekInArchive(position);
rlm@1 508 streamSpec->SetStream(m_Stream);
rlm@1 509 streamSpec->Init(size);
rlm@1 510 return inStream.Detach();
rlm@1 511 }
rlm@1 512
rlm@1 513 }}