1 #include "rar.hpp"
2 
RawRead()3 RawRead::RawRead()
4 {
5   RawRead::SrcFile=NULL;
6   Reset();
7 }
8 
9 
RawRead(File * SrcFile)10 RawRead::RawRead(File *SrcFile)
11 {
12   RawRead::SrcFile=SrcFile;
13   Reset();
14 }
15 
16 
Reset()17 void RawRead::Reset()
18 {
19   Data.SoftReset();
20   ReadPos=0;
21   DataSize=0;
22   Crypt=NULL;
23 }
24 
25 
Read(size_t Size)26 size_t RawRead::Read(size_t Size)
27 {
28   size_t ReadSize=0;
29 #if !defined(RAR_NOCRYPT)
30   if (Crypt!=NULL)
31   {
32     // Full size of buffer with already read data including data read
33     // for encryption block alignment.
34     size_t FullSize=Data.Size();
35 
36     // Data read for alignment and not processed yet.
37     size_t DataLeft=FullSize-DataSize;
38 
39     if (Size>DataLeft) // Need to read more than we already have.
40     {
41       size_t SizeToRead=Size-DataLeft;
42       size_t AlignedReadSize=SizeToRead+((~SizeToRead+1) & CRYPT_BLOCK_MASK);
43       Data.Add(AlignedReadSize);
44       ReadSize=SrcFile->Read(&Data[FullSize],AlignedReadSize);
45       Crypt->DecryptBlock(&Data[FullSize],AlignedReadSize);
46       DataSize+=ReadSize==0 ? 0:Size;
47     }
48     else // Use buffered data, no real read.
49     {
50       ReadSize=Size;
51       DataSize+=Size;
52     }
53   }
54   else
55 #endif
56     if (Size!=0)
57     {
58       Data.Add(Size);
59       ReadSize=SrcFile->Read(&Data[DataSize],Size);
60       DataSize+=ReadSize;
61     }
62   return ReadSize;
63 }
64 
65 
Read(byte * SrcData,size_t Size)66 void RawRead::Read(byte *SrcData,size_t Size)
67 {
68   if (Size!=0)
69   {
70     Data.Add(Size);
71     memcpy(&Data[DataSize],SrcData,Size);
72     DataSize+=Size;
73   }
74 }
75 
76 
Get1()77 byte RawRead::Get1()
78 {
79   return ReadPos<DataSize ? Data[ReadPos++]:0;
80 }
81 
82 
Get2()83 ushort RawRead::Get2()
84 {
85   if (ReadPos+1<DataSize)
86   {
87     ushort Result=Data[ReadPos]+(Data[ReadPos+1]<<8);
88     ReadPos+=2;
89     return Result;
90   }
91   return 0;
92 }
93 
94 
Get4()95 uint RawRead::Get4()
96 {
97   if (ReadPos+3<DataSize)
98   {
99     uint Result=Data[ReadPos]+(Data[ReadPos+1]<<8)+(Data[ReadPos+2]<<16)+
100                 (Data[ReadPos+3]<<24);
101     ReadPos+=4;
102     return Result;
103   }
104   return 0;
105 }
106 
107 
Get8()108 uint64 RawRead::Get8()
109 {
110   uint Low=Get4(),High=Get4();
111   return INT32TO64(High,Low);
112 }
113 
114 
GetV()115 uint64 RawRead::GetV()
116 {
117   uint64 Result=0;
118   // Need to check Shift<64, because for shift greater than or equal to
119   // the width of the promoted left operand, the behavior is undefined.
120   for (uint Shift=0;ReadPos<DataSize && Shift<64;Shift+=7)
121   {
122     byte CurByte=Data[ReadPos++];
123     Result+=uint64(CurByte & 0x7f)<<Shift;
124     if ((CurByte & 0x80)==0)
125       return Result; // Decoded successfully.
126   }
127   return 0; // Out of buffer border.
128 }
129 
130 
131 // Return a number of bytes in current variable length integer.
GetVSize(size_t Pos)132 uint RawRead::GetVSize(size_t Pos)
133 {
134   for (size_t CurPos=Pos;CurPos<DataSize;CurPos++)
135     if ((Data[CurPos] & 0x80)==0)
136       return int(CurPos-Pos+1);
137   return 0; // Buffer overflow.
138 }
139 
140 
GetB(void * Field,size_t Size)141 size_t RawRead::GetB(void *Field,size_t Size)
142 {
143   byte *F=(byte *)Field;
144   size_t CopySize=Min(DataSize-ReadPos,Size);
145   if (CopySize>0)
146     memcpy(F,&Data[ReadPos],CopySize);
147   if (Size>CopySize)
148     memset(F+CopySize,0,Size-CopySize);
149   ReadPos+=CopySize;
150   return CopySize;
151 }
152 
153 
GetW(wchar * Field,size_t Size)154 void RawRead::GetW(wchar *Field,size_t Size)
155 {
156   if (ReadPos+2*Size-1<DataSize)
157   {
158     RawToWide(&Data[ReadPos],Field,Size);
159     ReadPos+=sizeof(wchar)*Size;
160   }
161   else
162     memset(Field,0,sizeof(wchar)*Size);
163 }
164 
165 
GetCRC15(bool ProcessedOnly)166 uint RawRead::GetCRC15(bool ProcessedOnly) // RAR 1.5 block CRC.
167 {
168   if (DataSize<=2)
169     return 0;
170   uint HeaderCRC=CRC32(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2);
171   return ~HeaderCRC & 0xffff;
172 }
173 
174 
GetCRC50()175 uint RawRead::GetCRC50() // RAR 5.0 block CRC.
176 {
177   if (DataSize<=4)
178     return 0xffffffff;
179   return CRC32(0xffffffff,&Data[4],DataSize-4) ^ 0xffffffff;
180 }
181 
182 
183 // Read vint from arbitrary byte array.
RawGetV(const byte * Data,uint & ReadPos,uint DataSize,bool & Overflow)184 uint64 RawGetV(const byte *Data,uint &ReadPos,uint DataSize,bool &Overflow)
185 {
186   Overflow=false;
187   uint64 Result=0;
188   for (uint Shift=0;ReadPos<DataSize;Shift+=7)
189   {
190     byte CurByte=Data[ReadPos++];
191     Result+=uint64(CurByte & 0x7f)<<Shift;
192     if ((CurByte & 0x80)==0)
193       return Result; // Decoded successfully.
194   }
195   Overflow=true;
196   return 0; // Out of buffer border.
197 }
198