Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwps/src/lib/WPS8Struct.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwps
3
 * Version: MPL 2.0 / LGPLv2.1+
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * Major Contributor(s):
10
 * Copyright (C) 2009, 2011 Alonso Laurent (alonso@loria.fr)
11
 * Copyright (C) 2006, 2007 Andrew Ziem
12
 * Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
13
 * Copyright (C) 2004 Marc Maurer (uwog@uwog.net)
14
 * Copyright (C) 2003-2005 William Lachance (william.lachance@sympatico.ca)
15
 *
16
 * For minor contributions see the git repository.
17
 *
18
 * Alternatively, the contents of this file may be used under the terms
19
 * of the GNU Lesser General Public License Version 2.1 or later
20
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
21
 * applicable instead of those above.
22
 *
23
 * For further information visit http://libwps.sourceforge.net
24
 */
25
26
#include "WPS8Struct.h"
27
28
#include "WPSDebug.h"
29
30
namespace WPS8Struct
31
{
32
// try to read a block, which can be or not a list of data
33
bool FileData::readArrayBlock() const
34
20.3k
{
35
20.3k
  if (isRead()) return isArray();
36
20.3k
  long actPos = m_input->tell();
37
20.3k
  m_input->seek(m_beginOffset, librevenge::RVNG_SEEK_SET);
38
20.3k
  std::string error;
39
20.3k
  bool ok = readBlockData(m_input, m_endOffset, const_cast<FileData &>(*this), error);
40
20.3k
  m_input->seek(actPos, librevenge::RVNG_SEEK_SET);
41
20.3k
  return ok;
42
20.3k
}
43
44
// create a message to store unparsed data
45
std::string FileData::createErrorString(RVNGInputStreamPtr input, long endPos)
46
184k
{
47
184k
  libwps::DebugStream f;
48
184k
  f << ",###unread=(" << std::hex;
49
184k
  while (input->tell() < endPos-1) f << libwps::readU16(input) << ", ";
50
184k
  if (input->tell() < endPos)  f << libwps::readU8(input) << ", ";
51
184k
  f << ")";
52
53
184k
  return f.str();
54
184k
}
55
56
bool FileData::getBorderStyles(WPSBorder::Style &style, WPSBorder::Type &borderType, std::string &mess) const
57
186k
{
58
186k
  style = WPSBorder::Simple;
59
186k
  borderType = WPSBorder::Single;
60
186k
  libwps::DebugStream f;
61
186k
  switch (m_value)
62
186k
  {
63
8.05k
  case 0:
64
8.05k
    style  = WPSBorder::None;
65
8.05k
    break;
66
4.25k
  case 1: // normal
67
4.25k
    break;
68
10.4k
  case 2: // double normal
69
10.4k
    borderType  = WPSBorder::Double;
70
10.4k
    break;
71
22.6k
  case 3:
72
22.6k
    f << "ext=2,int=1,";
73
22.6k
    borderType  = WPSBorder::Double;
74
22.6k
    break;
75
16.2k
  case 4:
76
16.2k
    f << "ext=1,int=2,";
77
16.2k
    borderType  = WPSBorder::Double;
78
16.2k
    break;
79
27.2k
  case 5:
80
27.2k
    style  = WPSBorder::Dash;
81
27.2k
    break;
82
14.9k
  case 6:
83
14.9k
    style  = WPSBorder::LargeDot;
84
14.9k
    break;
85
25.7k
  case 7:
86
25.7k
    style  = WPSBorder::Dot;
87
25.7k
    break;
88
21.5k
  case 8:
89
21.5k
    f << "dash+rot-5,";
90
21.5k
    style  = WPSBorder::Dash;
91
21.5k
    break;
92
9.91k
  case 9:
93
9.91k
    f << "dash+rot5,";
94
9.91k
    style  = WPSBorder::Dash;
95
9.91k
    break;
96
10.3k
  case 0xa:
97
10.3k
    f << "triple,";
98
10.3k
    borderType  = WPSBorder::Triple;
99
10.3k
    break;
100
15.5k
  default:
101
15.5k
    f << "#style=" << std::hex << m_value << std::dec << ",";
102
15.5k
    break;
103
186k
  }
104
105
186k
  mess = f.str();
106
186k
  return true;
107
186k
}
108
109
// operator <<
110
std::ostream &operator<< (std::ostream &o, FileData const &dt)
111
0
{
112
0
  if (dt.id() != -1)
113
0
    o << "unkn" << std::hex << dt.id() << "[typ=" << dt.m_type << "]:" << std::dec;
114
0
  auto &DT = const_cast<FileData &>(dt);
115
  // If the data are unread, try to read them as a block list
116
0
  if (!dt.isRead() && !dt.readArrayBlock())
117
0
  {
118
    // if this fails...
119
0
    long size = dt.m_endOffset-dt.m_beginOffset-2;
120
0
    int sz = (size%4) == 0 ? 4 : (size%2) == 0 ? 2 : 1;
121
0
    auto numElt = int(size/sz);
122
123
0
    long actPos = DT.m_input->tell();
124
0
    DT.m_input->seek(dt.m_beginOffset, librevenge::RVNG_SEEK_SET);
125
0
    o << "###FAILS[sz="<< sz << "]=(" << std::hex;
126
0
    auto val = long(libwps::read16(DT.m_input));
127
0
    if (val) o << "unkn=" << val <<",";
128
0
    for (int i = 0; i < numElt; i++)
129
0
    {
130
0
      switch (sz)
131
0
      {
132
0
      case 1:
133
0
        o << libwps::readU8(DT.m_input) << ",";
134
0
        break;
135
0
      case 2:
136
0
        o << libwps::readU16(DT.m_input) << ",";
137
0
        break;
138
0
      case 4:
139
0
        o << libwps::readU32(DT.m_input) << ",";
140
0
        break;
141
0
      default:
142
0
        break;
143
0
      }
144
0
    }
145
0
    o << ")" << std::dec;
146
147
0
    DT.m_input->seek(actPos, librevenge::RVNG_SEEK_SET);
148
149
0
    return o;
150
0
  }
151
0
  if (dt.hasStr()) o << "('" << dt.m_text << "')";
152
0
  if (dt.isFalse()) o << "=false,";
153
0
  if ((dt.m_type & 0x30) || dt.m_value)
154
0
    o << "=" << dt.m_value << ":" << std::hex << dt.m_value << std::dec;
155
0
  if (dt.m_recursData.empty()) return o;
156
157
0
  o << ",ch=(";
158
0
  for (auto const &data : dt.m_recursData)
159
0
  {
160
0
    if (data.isBad()) continue;
161
0
    o << data << ",";
162
0
  }
163
0
  o << ")";
164
0
  return o;
165
0
}
166
167
// try to read a data : which can be an item, a list or unknown zone
168
bool readBlockData(RVNGInputStreamPtr input, long endPos, FileData &dt, std::string &error)
169
6.02M
{
170
6.02M
  std::string saveError = error;
171
6.02M
  long actPos = input->tell();
172
6.02M
  dt.m_recursData.resize(0);
173
174
6.02M
  if (actPos+2 > endPos)   // to short
175
184k
  {
176
184k
    error += FileData::createErrorString(input, endPos);
177
184k
    return false;
178
184k
  }
179
180
5.84M
  dt.m_value = libwps::readU16(input); // normally 0, but who know ...
181
5.84M
  dt.m_beginOffset = dt.m_endOffset = -1;
182
183
5.84M
  int prevId = -1;
184
5.84M
  bool ok = true;
185
17.2M
  while (input->tell() != endPos)
186
16.1M
  {
187
16.1M
    FileData child;
188
16.1M
    if (!readData(input, endPos, child, error))
189
2.86M
    {
190
2.86M
      ok = false;
191
2.86M
      break;
192
2.86M
    }
193
13.2M
    if (child.isBad()) continue;
194
13.2M
    if (prevId > child.id())
195
1.87M
    {
196
1.87M
      ok = false;
197
1.87M
      break;
198
1.87M
    }
199
11.4M
    prevId = child.id();
200
11.4M
    dt.m_recursData.push_back(child);
201
11.4M
  }
202
5.84M
  if (ok) return true;
203
204
4.74M
  if (dt.m_type == -1) dt.m_type = 0x80;
205
4.74M
  dt.m_beginOffset = actPos;
206
4.74M
  dt.m_endOffset = endPos;
207
4.74M
  dt.m_input = input;
208
209
4.74M
  error = saveError;
210
4.74M
  input->seek(endPos, librevenge::RVNG_SEEK_SET);
211
212
4.74M
  return false;
213
5.84M
}
214
215
// try to read an item
216
bool readData(RVNGInputStreamPtr input, long endPos,
217
              FileData &dt, std::string &/*error*/)
218
16.1M
{
219
16.1M
  long actPos = input->tell();
220
16.1M
  dt = FileData();
221
222
16.1M
  if (actPos >= endPos) return false;
223
224
16.0M
  auto val = long(libwps::readU16(input));
225
16.0M
  dt.m_type = int((val & 0xFF00)>>8);
226
16.0M
  dt.m_id = (val & 0xFF);
227
228
16.0M
  if (dt.m_type & 5)
229
1.69M
  {
230
1.69M
    dt.m_type = -1;
231
1.69M
    return false;
232
1.69M
  }
233
234
14.3M
  dt.m_value = 0;
235
  // what is the meaning of dt.m_type & 0xF
236
  //   maybe :
237
  //           0x1/0x4 -> never seem
238
  //           0x2 -> set for the main child ?
239
  //           0x8 -> signed/unsigned ? set/unset for bool ?
240
14.3M
  switch (dt.m_type>>4)
241
14.3M
  {
242
7.69M
  case 0:
243
7.69M
    return true;
244
1.85M
  case 1:
245
1.85M
    if (actPos+4 > endPos) break;
246
1.77M
    if (dt.m_type == 0x12)
247
1.14M
    {
248
1.14M
      dt.m_value = libwps::readU8(input);
249
1.14M
      input->seek(1, librevenge::RVNG_SEEK_CUR);
250
1.14M
    }
251
628k
    else
252
628k
      dt.m_value = libwps::readU16(input);
253
1.77M
    return true;
254
3.53M
  case 2:
255
3.53M
  {
256
3.53M
    if (dt.m_type == 0x2a)   // special case : STR4 + long
257
338k
    {
258
338k
      if (actPos+10 > endPos) break;
259
1.22M
      for (int i = 0; i < 4; i++) dt.m_text += char(libwps::readU8(input));
260
245k
      dt.m_value = libwps::read32(input);
261
245k
      return true;
262
338k
    }
263
3.19M
    if (actPos+6 > endPos) break;
264
3.06M
    dt.m_value = libwps::read32(input);
265
3.06M
    return true;
266
3.19M
  }
267
867k
  case 8:
268
867k
  {
269
867k
    if (actPos+4 > endPos) break;
270
271
806k
    auto extraSize = long(libwps::readU16(input));
272
806k
    long newEndPos = actPos+2+extraSize;
273
274
806k
    if ((extraSize%2) || newEndPos > endPos) break;
275
276
    // can either be a list of data or a structured list, so we stored the information
277
499k
    dt.m_beginOffset = actPos+4;
278
499k
    dt.m_endOffset = newEndPos;
279
499k
    dt.m_input = input;
280
499k
    input->seek(newEndPos, librevenge::RVNG_SEEK_SET);
281
499k
    return true;
282
806k
  }
283
437k
  default:
284
437k
    break;
285
14.3M
  }
286
287
1.10M
  dt.m_type = -1;
288
1.10M
  return false;
289
14.3M
}
290
291
}
292
293
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */