1 bool IsAnsiComment(const char *Data,int Size);
2 
GetComment(Array<byte> * CmtData,Array<wchar> * CmtDataW)3 bool Archive::GetComment(Array<byte> *CmtData,Array<wchar> *CmtDataW)
4 {
5   if (!MainComment)
6     return(false);
7   SaveFilePos SavePos(*this);
8 
9 #ifndef SFX_MODULE
10   ushort CmtLength;
11   if (OldFormat)
12   {
13     Seek(SFXSize+SIZEOF_OLDMHD,SEEK_SET);
14     CmtLength=GetByte();
15     CmtLength+=(GetByte()<<8);
16   }
17   else
18 #endif
19   {
20     if ((NewMhd.Flags & MHD_COMMENT)!=0)
21     {
22       // Old style (RAR 2.9) archive comment embedded into the main
23       // archive header.
24       Seek(SFXSize+SIZEOF_MARKHEAD+SIZEOF_NEWMHD,SEEK_SET);
25       ReadHeader();
26     }
27     else
28     {
29       // Current (RAR 3.0+) version of archive comment.
30       Seek(SFXSize+SIZEOF_MARKHEAD+NewMhd.HeadSize,SEEK_SET);
31       return(SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData,CmtDataW)!=0);
32     }
33 #ifndef SFX_MODULE
34     // Old style (RAR 2.9) comment header embedded into the main
35     // archive header.
36     if (CommHead.HeadCRC!=HeaderCRC)
37     {
38       Log(FileName,St(MLogCommHead));
39       Alarm();
40       return(false);
41     }
42     CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
43 #endif
44   }
45 #ifndef SFX_MODULE
46   if (OldFormat && (OldMhd.Flags & MHD_PACK_COMMENT)!=0 || !OldFormat && CommHead.Method!=0x30)
47   {
48     if (!OldFormat && (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER || CommHead.Method > 0x35))
49       return(false);
50     ComprDataIO DataIO;
51     Unpack Unpack(&DataIO);
52     Unpack.Init();
53     DataIO.SetTestMode(true);
54     uint UnpCmtLength;
55     if (OldFormat)
56     {
57 #ifdef RAR_NOCRYPT
58       return(false);
59 #else
60       UnpCmtLength=GetByte();
61       UnpCmtLength+=(GetByte()<<8);
62       CmtLength-=2;
63       DataIO.SetCmt13Encryption();
64 #endif
65     }
66     else
67       UnpCmtLength=CommHead.UnpSize;
68     DataIO.SetFiles(this,NULL);
69     DataIO.EnableShowProgress(false);
70     DataIO.SetPackedSizeToRead(CmtLength);
71     Unpack.SetDestSize(UnpCmtLength);
72     Unpack.DoUnpack(CommHead.UnpVer,false);
73 
74     if (!OldFormat && ((~DataIO.UnpFileCRC)&0xffff)!=CommHead.CommCRC)
75     {
76       Log(FileName,St(MLogCommBrk));
77       Alarm();
78       return(false);
79     }
80     else
81     {
82       byte *UnpData;
83       size_t UnpDataSize;
84       DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
85       CmtData->Alloc(UnpDataSize);
86       memcpy(&((*CmtData)[0]),UnpData,UnpDataSize);
87     }
88   }
89   else
90   {
91     CmtData->Alloc(CmtLength);
92 
93     Read(&((*CmtData)[0]),CmtLength);
94     if (!OldFormat && CommHead.CommCRC!=(~CRC(0xffffffff,&((*CmtData)[0]),CmtLength)&0xffff))
95     {
96       Log(FileName,St(MLogCommBrk));
97       Alarm();
98       CmtData->Reset();
99       return(false);
100     }
101   }
102 #endif
103 #if defined(_WIN_ALL) && !defined(_WIN_CE)
104   if (CmtData->Size()>0)
105   {
106     size_t CmtSize=CmtData->Size();
107     char *DataA=(char *)CmtData->Addr();
108     OemToCharBuffA(DataA,DataA,(DWORD)CmtSize);
109 
110     if (CmtDataW!=NULL)
111     {
112       CmtDataW->Alloc(CmtSize+1);
113 
114       // It can cause reallocation, so we should not use 'DataA' variable
115       // with previosuly saved CmtData->Addr() after Push() call.
116       CmtData->Push(0);
117 
118       CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
119       CmtData->Alloc(CmtSize);
120       CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
121     }
122   }
123 #endif
124   return(CmtData->Size()>0);
125 }
126 
127 
ReadCommentData(Array<byte> * CmtData,Array<wchar> * CmtDataW)128 size_t Archive::ReadCommentData(Array<byte> *CmtData,Array<wchar> *CmtDataW)
129 {
130   bool Unicode=SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE;
131   if (!ReadSubData(CmtData,NULL))
132     return(0);
133   size_t CmtSize=CmtData->Size();
134   if (Unicode)
135   {
136     CmtSize/=2;
137     Array<wchar> DataW(CmtSize+1);
138     RawToWide(CmtData->Addr(),DataW.Addr(),CmtSize);
139     DataW[CmtSize]=0;
140     size_t DestSize=CmtSize*4;
141     CmtData->Alloc(DestSize+1);
142     WideToChar(DataW.Addr(),(char *)CmtData->Addr(),DestSize);
143     (*CmtData)[DestSize]=0;
144     CmtSize=strlen((char *)CmtData->Addr());
145     CmtData->Alloc(CmtSize);
146     if (CmtDataW!=NULL)
147     {
148       *CmtDataW=DataW;
149       CmtDataW->Alloc(CmtSize);
150     }
151   }
152   else
153     if (CmtDataW!=NULL)
154     {
155       CmtData->Push(0);
156       CmtDataW->Alloc(CmtSize+1);
157       CharToWide((char *)CmtData->Addr(),CmtDataW->Addr(),CmtSize+1);
158       CmtData->Alloc(CmtSize);
159       CmtDataW->Alloc(wcslen(CmtDataW->Addr()));
160     }
161   return(CmtSize);
162 }
163 
164 
ViewComment()165 void Archive::ViewComment()
166 {
167 #ifndef GUI
168   if (Cmd->DisableComment)
169     return;
170   Array<byte> CmtBuf;
171   if (GetComment(&CmtBuf,NULL))
172   {
173     size_t CmtSize=CmtBuf.Size();
174     char *ChPtr=(char *)memchr(&CmtBuf[0],0x1A,CmtSize);
175     if (ChPtr!=NULL)
176       CmtSize=ChPtr-(char *)&CmtBuf[0];
177     mprintf("\n");
178     OutComment((char *)&CmtBuf[0],CmtSize);
179   }
180 #endif
181 }
182 
183 
184 #ifndef SFX_MODULE
185 // Used for archives created by old RAR versions up to and including RAR 2.9.
186 // New RAR versions store file comments in separate headers and such comments
187 // are displayed in ListNewSubHeader function.
ViewFileComment()188 void Archive::ViewFileComment()
189 {
190   if (!(NewLhd.Flags & LHD_COMMENT) || Cmd->DisableComment || OldFormat)
191     return;
192 #ifndef GUI
193   mprintf(St(MFileComment));
194 #endif
195   const int MaxSize=0x8000;
196   Array<char> CmtBuf(MaxSize);
197   SaveFilePos SavePos(*this);
198   Seek(CurBlockPos+SIZEOF_NEWLHD+NewLhd.NameSize,SEEK_SET);
199   int64 SaveCurBlockPos=CurBlockPos;
200   int64 SaveNextBlockPos=NextBlockPos;
201 
202   size_t Size=ReadHeader();
203 
204   CurBlockPos=SaveCurBlockPos;
205   NextBlockPos=SaveNextBlockPos;
206 
207   if (Size<7 || CommHead.HeadType!=COMM_HEAD)
208     return;
209   if (CommHead.HeadCRC!=HeaderCRC)
210   {
211 #ifndef GUI
212     Log(FileName,St(MLogCommHead));
213 #endif
214     return;
215   }
216   if (CommHead.UnpVer < 15 || CommHead.UnpVer > UNP_VER ||
217       CommHead.Method > 0x30 || CommHead.UnpSize > MaxSize)
218     return;
219   Read(&CmtBuf[0],CommHead.UnpSize);
220   if (CommHead.CommCRC!=((~CRC(0xffffffff,&CmtBuf[0],CommHead.UnpSize)&0xffff)))
221   {
222     Log(FileName,St(MLogBrokFCmt));
223   }
224   else
225   {
226     OutComment(&CmtBuf[0],CommHead.UnpSize);
227 #ifndef GUI
228     mprintf("\n");
229 #endif
230   }
231 }
232 #endif
233 
234 
235