Line | Count | Source (jump to first uncovered line) |
1 | | static bool IsAnsiEscComment(const wchar *Data,size_t Size); |
2 | | |
3 | | bool Archive::GetComment(Array<wchar> *CmtData) |
4 | 1 | { |
5 | 1 | if (!MainComment) |
6 | 1 | return false; |
7 | 0 | int64 SavePos=Tell(); |
8 | 0 | bool Success=DoGetComment(CmtData); |
9 | 0 | Seek(SavePos,SEEK_SET); |
10 | 0 | return Success; |
11 | 1 | } |
12 | | |
13 | | |
14 | | bool Archive::DoGetComment(Array<wchar> *CmtData) |
15 | 0 | { |
16 | 0 | #ifndef SFX_MODULE |
17 | 0 | uint CmtLength; |
18 | 0 | if (Format==RARFMT14) |
19 | 0 | { |
20 | 0 | Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET); |
21 | 0 | CmtLength=GetByte(); |
22 | 0 | CmtLength+=(GetByte()<<8); |
23 | 0 | } |
24 | 0 | else |
25 | 0 | #endif |
26 | 0 | { |
27 | 0 | if (MainHead.CommentInHeader) |
28 | 0 | { |
29 | | // Old style (RAR 2.9) archive comment embedded into the main |
30 | | // archive header. |
31 | 0 | Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET); |
32 | 0 | if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT) |
33 | 0 | return false; |
34 | 0 | } |
35 | 0 | else |
36 | 0 | { |
37 | | // Current (RAR 3.0+) version of archive comment. |
38 | 0 | Seek(GetStartPos(),SEEK_SET); |
39 | 0 | return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData); |
40 | 0 | } |
41 | 0 | #ifndef SFX_MODULE |
42 | | // Old style (RAR 2.9) comment header embedded into the main |
43 | | // archive header. |
44 | 0 | if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD) |
45 | 0 | { |
46 | 0 | uiMsg(UIERROR_CMTBROKEN,FileName); |
47 | 0 | return false; |
48 | 0 | } |
49 | 0 | CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD; |
50 | 0 | #endif |
51 | 0 | } |
52 | 0 | #ifndef SFX_MODULE |
53 | 0 | if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30) |
54 | 0 | { |
55 | 0 | if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35)) |
56 | 0 | return false; |
57 | 0 | ComprDataIO DataIO; |
58 | 0 | DataIO.SetTestMode(true); |
59 | 0 | uint UnpCmtLength; |
60 | 0 | if (Format==RARFMT14) |
61 | 0 | { |
62 | | #ifdef RAR_NOCRYPT |
63 | | return false; |
64 | | #else |
65 | 0 | UnpCmtLength=GetByte(); |
66 | 0 | UnpCmtLength+=(GetByte()<<8); |
67 | 0 | if (CmtLength<2) |
68 | 0 | return false; |
69 | 0 | CmtLength-=2; |
70 | 0 | DataIO.SetCmt13Encryption(); |
71 | 0 | CommHead.UnpVer=15; |
72 | 0 | #endif |
73 | 0 | } |
74 | 0 | else |
75 | 0 | UnpCmtLength=CommHead.UnpSize; |
76 | 0 | DataIO.SetFiles(this,NULL); |
77 | 0 | DataIO.EnableShowProgress(false); |
78 | 0 | DataIO.SetPackedSizeToRead(CmtLength); |
79 | 0 | DataIO.UnpHash.Init(HASH_CRC32,1); |
80 | 0 | DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet. |
81 | |
|
82 | 0 | Unpack CmtUnpack(&DataIO); |
83 | 0 | CmtUnpack.Init(0x10000,false); |
84 | 0 | CmtUnpack.SetDestSize(UnpCmtLength); |
85 | 0 | CmtUnpack.DoUnpack(CommHead.UnpVer,false); |
86 | |
|
87 | 0 | if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC) |
88 | 0 | { |
89 | 0 | uiMsg(UIERROR_CMTBROKEN,FileName); |
90 | 0 | return false; |
91 | 0 | } |
92 | 0 | else |
93 | 0 | { |
94 | 0 | byte *UnpData; |
95 | 0 | size_t UnpDataSize; |
96 | 0 | DataIO.GetUnpackedData(&UnpData,&UnpDataSize); |
97 | 0 | if (UnpDataSize>0) |
98 | 0 | { |
99 | | #ifdef _WIN_ALL |
100 | | // If we ever decide to extend it to Android, we'll need to alloc |
101 | | // 4x memory for OEM to UTF-8 output here. |
102 | | OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize); |
103 | | #endif |
104 | 0 | CmtData->Alloc(UnpDataSize+1); |
105 | 0 | memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar)); |
106 | 0 | CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size()); |
107 | 0 | CmtData->Alloc(wcslen(CmtData->Addr(0))); |
108 | 0 | } |
109 | 0 | } |
110 | 0 | } |
111 | 0 | else |
112 | 0 | { |
113 | 0 | if (CmtLength==0) |
114 | 0 | return false; |
115 | 0 | Array<byte> CmtRaw(CmtLength); |
116 | 0 | int ReadSize=Read(&CmtRaw[0],CmtLength); |
117 | 0 | if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared. |
118 | 0 | { |
119 | 0 | CmtLength=ReadSize; |
120 | 0 | CmtRaw.Alloc(CmtLength); |
121 | 0 | } |
122 | |
|
123 | 0 | if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff)) |
124 | 0 | { |
125 | 0 | uiMsg(UIERROR_CMTBROKEN,FileName); |
126 | 0 | return false; |
127 | 0 | } |
128 | 0 | CmtData->Alloc(CmtLength+1); |
129 | 0 | CmtRaw.Push(0); |
130 | | #ifdef _WIN_ALL |
131 | | // If we ever decide to extend it to Android, we'll need to alloc |
132 | | // 4x memory for OEM to UTF-8 output here. |
133 | | OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]); |
134 | | #endif |
135 | 0 | CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); |
136 | 0 | CmtData->Alloc(wcslen(CmtData->Addr(0))); |
137 | 0 | } |
138 | 0 | #endif |
139 | 0 | return CmtData->Size() > 0; |
140 | 0 | } |
141 | | |
142 | | |
143 | | bool Archive::ReadCommentData(Array<wchar> *CmtData) |
144 | 0 | { |
145 | 0 | Array<byte> CmtRaw; |
146 | 0 | if (!ReadSubData(&CmtRaw,NULL,false)) |
147 | 0 | return false; |
148 | 0 | size_t CmtSize=CmtRaw.Size(); |
149 | 0 | CmtRaw.Push(0); |
150 | 0 | CmtData->Alloc(CmtSize+1); |
151 | 0 | if (Format==RARFMT50) |
152 | 0 | UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); |
153 | 0 | else |
154 | 0 | if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0) |
155 | 0 | { |
156 | 0 | RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2); |
157 | 0 | (*CmtData)[CmtSize/2]=0; |
158 | |
|
159 | 0 | } |
160 | 0 | else |
161 | 0 | { |
162 | 0 | CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size()); |
163 | 0 | } |
164 | 0 | CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length. |
165 | 0 | return true; |
166 | 0 | } |
167 | | |
168 | | |
169 | | void Archive::ViewComment() |
170 | 1 | { |
171 | 1 | if (Cmd->DisableComment) |
172 | 0 | return; |
173 | 1 | Array<wchar> CmtBuf; |
174 | 1 | if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments. |
175 | 0 | { |
176 | 0 | size_t CmtSize=CmtBuf.Size(); |
177 | 0 | wchar *ChPtr=wcschr(&CmtBuf[0],0x1A); |
178 | 0 | if (ChPtr!=NULL) |
179 | 0 | CmtSize=ChPtr-&CmtBuf[0]; |
180 | 0 | mprintf(L"\n"); |
181 | 0 | OutComment(&CmtBuf[0],CmtSize); |
182 | 0 | } |
183 | 1 | } |
184 | | |
185 | | |