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