Coverage Report

Created: 2024-04-23 06:19

/src/unrar/arccmt.cpp
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
4.04k
{
5
4.04k
  if (!MainComment)
6
3.11k
    return false;
7
927
  int64 SavePos=Tell();
8
927
  bool Success=DoGetComment(CmtData);
9
927
  Seek(SavePos,SEEK_SET);
10
927
  return Success;
11
4.04k
}
12
13
14
bool Archive::DoGetComment(Array<wchar> *CmtData)
15
927
{
16
927
#ifndef SFX_MODULE
17
927
  uint CmtLength;
18
927
  if (Format==RARFMT14)
19
253
  {
20
253
    Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
21
253
    CmtLength=GetByte();
22
253
    CmtLength+=(GetByte()<<8);
23
253
  }
24
674
  else
25
674
#endif
26
674
  {
27
674
    if (MainHead.CommentInHeader)
28
612
    {
29
      // Old style (RAR 2.9) archive comment embedded into the main 
30
      // archive header.
31
612
      Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
32
612
      if (!ReadHeader() || GetHeaderType()!=HEAD3_CMT)
33
609
        return false;
34
612
    }
35
62
    else
36
62
    {
37
      // Current (RAR 3.0+) version of archive comment.
38
62
      Seek(GetStartPos(),SEEK_SET);
39
62
      return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
40
62
    }
41
3
#ifndef SFX_MODULE
42
    // Old style (RAR 2.9) comment header embedded into the main 
43
    // archive header.
44
3
    if (BrokenHeader || CommHead.HeadSize<SIZEOF_COMMHEAD)
45
2
    {
46
2
      uiMsg(UIERROR_CMTBROKEN,FileName);
47
2
      return false;
48
2
    }
49
1
    CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
50
1
#endif
51
1
  }
52
254
#ifndef SFX_MODULE
53
254
  if (Format==RARFMT14 && MainHead.PackComment || Format!=RARFMT14 && CommHead.Method!=0x30)
54
199
  {
55
199
    if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
56
0
      return false;
57
199
    ComprDataIO DataIO;
58
199
    DataIO.SetTestMode(true);
59
199
    uint UnpCmtLength;
60
199
    if (Format==RARFMT14)
61
199
    {
62
#ifdef RAR_NOCRYPT
63
      return false;
64
#else
65
199
      UnpCmtLength=GetByte();
66
199
      UnpCmtLength+=(GetByte()<<8);
67
199
      if (CmtLength<2)
68
0
        return false;
69
199
      CmtLength-=2;
70
199
      DataIO.SetCmt13Encryption();
71
199
      CommHead.UnpVer=15;
72
199
#endif
73
199
    }
74
0
    else
75
0
      UnpCmtLength=CommHead.UnpSize;
76
199
    DataIO.SetFiles(this,NULL);
77
199
    DataIO.EnableShowProgress(false);
78
199
    DataIO.SetPackedSizeToRead(CmtLength);
79
199
    DataIO.UnpHash.Init(HASH_CRC32,1);
80
199
    DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.
81
82
199
    Unpack CmtUnpack(&DataIO);
83
199
    CmtUnpack.Init(0x10000,false);
84
199
    CmtUnpack.SetDestSize(UnpCmtLength);
85
199
    CmtUnpack.DoUnpack(CommHead.UnpVer,false);
86
87
199
    if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
88
0
    {
89
0
      uiMsg(UIERROR_CMTBROKEN,FileName);
90
0
      return false;
91
0
    }
92
199
    else
93
199
    {
94
199
      byte *UnpData;
95
199
      size_t UnpDataSize;
96
199
      DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
97
199
      if (UnpDataSize>0)
98
198
      {
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
198
        CmtData->Alloc(UnpDataSize+1);
105
198
        memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
106
198
        CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
107
198
        CmtData->Alloc(wcslen(CmtData->Addr(0)));
108
198
      }
109
199
    }
110
199
  }
111
55
  else
112
55
  {
113
55
    if (CmtLength==0)
114
0
      return false;
115
55
    Array<byte> CmtRaw(CmtLength);
116
55
    int ReadSize=Read(&CmtRaw[0],CmtLength);
117
55
    if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
118
52
    {
119
52
      CmtLength=ReadSize;
120
52
      CmtRaw.Alloc(CmtLength);
121
52
    }
122
123
55
    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
55
    CmtData->Alloc(CmtLength+1);
129
55
    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
55
    CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
136
55
    CmtData->Alloc(wcslen(CmtData->Addr(0)));
137
55
  }
138
254
#endif
139
254
  return CmtData->Size() > 0;
140
254
}
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
4.04k
{
171
4.04k
  if (Cmd->DisableComment)
172
0
    return;
173
4.04k
  Array<wchar> CmtBuf;
174
4.04k
  if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
175
230
  {
176
230
    size_t CmtSize=CmtBuf.Size();
177
230
    wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
178
230
    if (ChPtr!=NULL)
179
0
      CmtSize=ChPtr-&CmtBuf[0];
180
230
    mprintf(L"\n");
181
230
    OutComment(&CmtBuf[0],CmtSize);
182
230
  }
183
4.04k
}
184
185