Coverage Report

Created: 2026-10-28 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MWAWRSRCParser.cxx
Line
Count
Source
1
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3
/* libmwaw
4
* Version: MPL 2.0 / LGPLv2+
5
*
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 2.0 (the "License"); you may not use this file except in compliance with
8
* the License or as specified alternatively below. You may obtain a copy of
9
* the License at http://www.mozilla.org/MPL/
10
*
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
14
* License.
15
*
16
* Major Contributor(s):
17
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20
* Copyright (C) 2006, 2007 Andrew Ziem
21
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22
*
23
*
24
* All Rights Reserved.
25
*
26
* For minor contributions see the git repository.
27
*
28
* Alternatively, the contents of this file may be used under the terms of
29
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30
* in which case the provisions of the LGPLv2+ are applicable
31
* instead of those above.
32
*/
33
34
#include <librevenge/librevenge.h>
35
36
#include "MWAWCell.hxx"
37
#include "MWAWInputStream.hxx"
38
#include "MWAWEntry.hxx"
39
40
#include "MWAWRSRCParser.hxx"
41
42
MWAWRSRCParser::MWAWRSRCParser(MWAWInputStreamPtr const &input)
43
59.8k
  : m_input(input)
44
59.8k
  , m_entryMap()
45
59.8k
  , m_asciiName("")
46
59.8k
  , m_asciiFile(MWAWInputStreamPtr())
47
59.8k
  , m_parsed(false)
48
59.8k
{
49
59.8k
}
50
51
MWAWRSRCParser::~MWAWRSRCParser()
52
59.8k
{
53
#ifdef DEBUG
54
  try {
55
    libmwaw::DebugStream f;
56
    for (auto const &it : m_entryMap) {
57
      MWAWEntry const &tEntry = it.second;
58
      if (tEntry.isParsed()) continue;
59
60
      if (tEntry.type()=="CODE") { // skip the code...
61
        ascii().skipZone(tEntry.begin()-4, tEntry.end()-1);
62
        continue;
63
      }
64
      f.str("");
65
      f << "Entries(RSRC" << tEntry.type() << "):" << tEntry.id();
66
      ascii().addPos(tEntry.begin()-4);
67
      ascii().addNote(f.str().c_str());
68
      ascii().addPos(tEntry.end());
69
      ascii().addNote("_");
70
    }
71
  }
72
  catch (...) {
73
  }
74
#endif
75
76
59.8k
  ascii().reset();
77
59.8k
}
78
79
MWAWEntry MWAWRSRCParser::getEntry(std::string type, int id) const
80
82.8k
{
81
82.8k
  if (!m_parsed)
82
758
    const_cast<MWAWRSRCParser *>(this)->parse();
83
82.8k
  auto it = m_entryMap.lower_bound(type);
84
192k
  while (it != m_entryMap.end()) {
85
170k
    if (it->first != type)
86
5.32k
      break;
87
165k
    MWAWEntry const &tEntry = (it++)->second;
88
165k
    if (tEntry.id()==id)
89
55.7k
      return tEntry;
90
165k
  }
91
92
27.1k
  return MWAWEntry();
93
82.8k
}
94
95
bool MWAWRSRCParser::parse()
96
55.0k
{
97
55.0k
  if (m_parsed)
98
0
    return !m_entryMap.empty();
99
55.0k
  m_parsed = true;
100
55.0k
  if (!m_input) return false;
101
102
55.0k
  if (m_asciiName.length()) {
103
53.9k
    ascii().setStream(m_input);
104
53.9k
    ascii().open("RSRC");
105
53.9k
  }
106
55.0k
  try {
107
55.0k
    libmwaw::DebugStream f;
108
55.0k
    m_input->seek(0, librevenge::RVNG_SEEK_SET);
109
55.0k
    long pos = m_input->tell();
110
55.0k
    MWAWEntry data, map;
111
55.0k
    data.setBegin(m_input->readLong(4));
112
55.0k
    map.setBegin(m_input->readLong(4));
113
55.0k
    data.setLength(m_input->readLong(4));
114
55.0k
    map.setLength(m_input->readLong(4));
115
    // data.length()==0 can be ok, if no data
116
55.0k
    if (!map.valid() || (!data.valid()&&data.length()!=0)) {
117
17.9k
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parse: can not read the header\n"));
118
17.9k
      return false;
119
17.9k
    }
120
37.1k
    long endPos = data.end() > map.end() ? data.end() : map.end();
121
37.1k
    m_input->seek(endPos, librevenge::RVNG_SEEK_SET);
122
37.1k
    if (m_input->tell() != endPos) {
123
9.31k
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parse: stream seems too small\n"));
124
9.31k
      return false;
125
9.31k
    }
126
27.8k
    f << "Header:";
127
27.8k
    ascii().addPos(pos);
128
27.8k
    ascii().addNote(f.str().c_str());
129
27.8k
    ascii().addPos(16);
130
27.8k
    ascii().addNote("_");
131
132
27.8k
    if (!parseMap(map, data.begin())) return false;
133
134
#ifdef DEBUG_WITH_FILES
135
    // try to parse the system reserved zone
136
    m_input->seek(48, librevenge::RVNG_SEEK_SET);
137
    int strSz=int(m_input->readULong(1));
138
    if (data.begin()>=0x100 && map.begin()>=0x100 && (strSz>0 && strSz<32)) {
139
      f.str("");
140
      f << "Entries(RSRCPriv):name=";
141
      pos=48;
142
      std::string name;
143
      for (int i=0; i<strSz; ++i) name+=char(m_input->readULong(1));
144
      f << name << ",";
145
      ascii().addDelimiter(m_input->tell(),'|');
146
      ascii().addPos(pos);
147
      ascii().addNote(f.str().c_str());
148
      m_input->seek(pos+32, librevenge::RVNG_SEEK_SET);
149
150
      f.str("");
151
      f << "RSRCPriv-2:";
152
      pos=m_input->tell();
153
      int val=int(m_input->readLong(2));
154
      if (val) f << "f0=" << val << ",";
155
      for (int w=0; w<2; ++w) {
156
        long aPos=m_input->tell();
157
        std::string type;
158
        for (int j=0; j<4; ++j) {
159
          char c=char(m_input->readULong(1));
160
          if (!c) break;
161
          type+=c;
162
        }
163
        f << (w==0 ? "type" : "creator") << "=" << type << ",";
164
        m_input->seek(aPos+4, librevenge::RVNG_SEEK_SET);
165
      }
166
      for (int i=0; i<12; ++i) { // f1=256, f2-3: small number
167
        val=int(m_input->readLong(2));
168
        if (val)
169
          f << "f" << i+1 << "=" << val << ",";
170
      }
171
      auto date=m_input->readULong(4);
172
      if (date) {
173
        int Y, M, D, HH, MM, SS;
174
        MWAWCellContent::double2Date(double(date/3600/24)+1460., Y, M, D); // change the reference date from 1/1/1904 to 1/1/1900
175
        double time=double(date%(3600*24))/3600/24;
176
        MWAWCellContent::double2Time(time, HH, MM, SS);
177
        f << "date=" << D << "/" << M << "/" << Y << " " << HH << ":" << MM << ",";
178
      }
179
      f << "sz=[";
180
      for (int i=0; i<2; ++i) {
181
        val=int(m_input->readULong(4));
182
        if (val)
183
          f << val << ",";
184
        else
185
          f << "_,";
186
      }
187
      f << "],";
188
      ascii().addPos(pos);
189
      ascii().addNote(f.str().c_str());
190
191
      ascii().addPos(m_input->tell());
192
      ascii().addNote("_");
193
    }
194
#endif
195
655k
    for (auto &it : m_entryMap) {
196
655k
      MWAWEntry &tEntry = it.second;
197
655k
      if (tEntry.begin()+4 >= data.end()) {
198
265k
        MWAW_DEBUG_MSG(("MWAWRSRCParser::parseMap: can not read entry %s[%d]\n", tEntry.type().c_str(), tEntry.id()));
199
265k
        continue;
200
265k
      }
201
390k
      m_input->seek(tEntry.begin(), librevenge::RVNG_SEEK_SET);
202
390k
      tEntry.setBegin(tEntry.begin()+4);
203
390k
      const auto length = long(m_input->readULong(4));
204
390k
      if (tEntry.begin() + length > data.end()) {
205
50.4k
        MWAW_DEBUG_MSG(("MWAWRSRCParser::parse: entry %s[%d] has got invalid length %ld\n", tEntry.type().c_str(), tEntry.id(), length));
206
50.4k
        continue;
207
50.4k
      }
208
340k
      tEntry.setLength(length);
209
340k
    }
210
211
26.7k
    auto it = m_entryMap.lower_bound("vers");
212
59.8k
    while (it != m_entryMap.end()) {
213
37.4k
      if (it->first != "vers")
214
4.43k
        break;
215
33.0k
      MWAWEntry const &tEntry = (it++)->second;
216
33.0k
      Version vers;
217
33.0k
      parseVers(tEntry, vers);
218
33.0k
    }
219
26.7k
    it = m_entryMap.lower_bound("STR ");
220
47.6k
    while (it != m_entryMap.end()) {
221
44.4k
      if (it->first != "STR ")
222
23.6k
        break;
223
20.8k
      std::string str;
224
20.8k
      MWAWEntry const &tEntry = (it++)->second;
225
20.8k
      parseSTR(tEntry, str);
226
20.8k
    }
227
26.7k
    it = m_entryMap.lower_bound("STR#");
228
45.8k
    while (it != m_entryMap.end()) {
229
42.4k
      if (it->first != "STR#")
230
23.4k
        break;
231
19.0k
      std::vector<std::string> list;
232
19.0k
      MWAWEntry const &tEntry = (it++)->second;
233
19.0k
      parseSTRList(tEntry, list);
234
19.0k
    }
235
26.7k
  }
236
55.0k
  catch (...) {
237
0
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parse: can not parse the input\n"));
238
0
    return false;
239
0
  }
240
26.7k
  return true;
241
55.0k
}
242
243
bool MWAWRSRCParser::parseMap(MWAWEntry const &entry, long dataBegin)
244
27.8k
{
245
27.8k
  if (!m_input) return false;
246
247
27.8k
  if (entry.length() < 28) {
248
120
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseMap: entry map is two short\n"));
249
120
    return false;
250
120
  }
251
252
27.7k
  libmwaw::DebugStream f, f2;
253
27.7k
  m_input->seek(entry.begin()+24, librevenge::RVNG_SEEK_SET);
254
27.7k
  f << "Entries(RSRCMap):";
255
27.7k
  auto offsetTypes=long(m_input->readULong(2));
256
27.7k
  auto offsetNameLists=long(m_input->readULong(2));
257
27.7k
  auto numTypes = static_cast<int>(m_input->readULong(2));
258
27.7k
  if (offsetTypes+2 > entry.length() || offsetNameLists > entry.length()) {
259
779
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseMap: the offsets seems bad\n"));
260
779
    return false;
261
779
  }
262
  // this case can appear if no data
263
26.9k
  if (numTypes == 0xFFFF)
264
104
    numTypes = -1;
265
26.9k
  f << "N=" << numTypes+1;
266
26.9k
  ascii().addPos(entry.begin());
267
26.9k
  ascii().addNote(f.str().c_str());
268
26.9k
  if (m_input->tell() != entry.begin()+offsetTypes+2) {
269
2.27k
    ascii().addPos(m_input->tell());
270
2.27k
    ascii().addNote("_");
271
2.27k
  }
272
273
26.9k
  long pos = entry.begin()+offsetTypes+2;
274
26.9k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
275
26.9k
  if (pos+8*(numTypes+1) > entry.end()) {
276
150
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseMap: the type zones seems too short\n"));
277
150
    return false;
278
150
  }
279
26.7k
  std::vector<MWAWEntry> typesList;
280
448k
  for (int i = 0; i <= numTypes; i++) {
281
421k
    pos = m_input->tell();
282
421k
    f.str("");
283
421k
    f << "RSRCMap[Type" << i << "]:";
284
421k
    std::string type("");
285
2.10M
    for (int c = 0; c < 4; c++)
286
1.68M
      type+=char(m_input->readULong(1));
287
421k
    MWAWEntry tEntry;
288
421k
    tEntry.setType(type);
289
421k
    tEntry.setId(static_cast<int>(m_input->readULong(2))+1); // the number of entry
290
421k
    tEntry.setBegin(entry.begin()+offsetTypes+long(m_input->readULong(2)));
291
421k
    typesList.push_back(tEntry);
292
421k
    f << tEntry << ":" << std::hex << tEntry.begin() << std::dec << ",";
293
421k
    ascii().addPos(pos);
294
421k
    ascii().addNote(f.str().c_str());
295
421k
    m_input->seek(pos+8, librevenge::RVNG_SEEK_SET);
296
421k
  }
297
26.7k
  ascii().addPos(m_input->tell());
298
26.7k
  ascii().addNote("_");
299
421k
  for (auto const &tEntry : typesList) {
300
421k
    if (tEntry.begin()+12*tEntry.id() > entry.end()) {
301
57.2k
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parseMap: can not read entry %s[%d]\n", tEntry.type().c_str(), tEntry.id()));
302
57.2k
      continue;
303
57.2k
    }
304
363k
    m_input->seek(tEntry.begin(), librevenge::RVNG_SEEK_SET);
305
1.01M
    for (int n = 0; n < tEntry.id(); n++) {
306
655k
      pos = m_input->tell();
307
655k
      f.str("");
308
655k
      f << "RSRCMap[Rsrc" << n << "]:";
309
655k
      MWAWEntry rsrc(tEntry);
310
655k
      rsrc.setId(static_cast<int>(m_input->readLong(2)));
311
655k
      auto offset = long(m_input->readULong(2));
312
655k
      if (offset != 0xFFFF) {
313
402k
        std::string name("");
314
402k
        if (offset+offsetNameLists+1 <= entry.length()) {
315
127k
          long actPos = m_input->tell();
316
127k
          m_input->seek(entry.begin()+offset+offsetNameLists, librevenge::RVNG_SEEK_SET);
317
127k
          auto nSz = static_cast<int>(m_input->readULong(1));
318
127k
          if (offset+offsetNameLists+1+nSz <= entry.length()) {
319
2.98M
            for (int j = 0; j < nSz; j++)
320
2.86M
              name+=char(m_input->readULong(1));
321
119k
            f2.str("");
322
119k
            f2 << "nameList:" << name;
323
119k
            ascii().addPos(entry.begin()+offset+offsetNameLists);
324
119k
            ascii().addNote(f2.str().c_str());
325
119k
          }
326
127k
          m_input->seek(actPos, librevenge::RVNG_SEEK_SET);
327
127k
        }
328
402k
        if (!name.length()) {
329
347k
          MWAW_DEBUG_MSG(("MWAWRSRCParser::parseMap: can not read name of entry %s[%d]\n", tEntry.type().c_str(), tEntry.id()));
330
347k
          f << "#listNamesOffset=" << std::hex << offset << std::dec << ",";
331
347k
        }
332
54.8k
        else {
333
54.8k
          rsrc.setName(name);
334
54.8k
          f << "name=" << name << ",";
335
54.8k
        }
336
402k
      }
337
655k
      unsigned long dOffset = m_input->readULong(4);
338
655k
      if (dOffset & 0xFF000000) {
339
181k
        f << "attributes=" << (dOffset>>12) << ",";
340
181k
        dOffset &= 0xFFFFFF;
341
181k
      }
342
655k
      rsrc.setBegin(dataBegin+long(dOffset));
343
655k
      m_entryMap.insert(std::multimap<std::string, MWAWEntry>::value_type(rsrc.type(), rsrc));
344
655k
      f << rsrc.type() << ":" << rsrc.id() << ",";
345
655k
      f << "pos=" << std::hex << rsrc.begin() << std::dec << ",";
346
347
655k
      ascii().addPos(pos);
348
655k
      ascii().addNote(f.str().c_str());
349
655k
      m_input->seek(pos+12, librevenge::RVNG_SEEK_SET);
350
655k
    }
351
363k
  }
352
26.7k
  if (offsetNameLists != entry.length()) {
353
6.67k
    ascii().addPos(entry.begin()+offsetNameLists);
354
6.67k
    ascii().addNote("RSRCMap[nameList]");
355
6.67k
  }
356
26.7k
  return true;
357
26.9k
}
358
359
////////////////////////////////////////////////////////////
360
// read a string resource
361
// -16396: application-missing name string resource
362
// -16397: application-missing string resource
363
////////////////////////////////////////////////////////////
364
bool MWAWRSRCParser::parseSTR(MWAWEntry const &entry, std::string &str)
365
22.5k
{
366
22.5k
  str="";
367
22.5k
  if (!m_input || !entry.valid()) {
368
6.18k
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTR: entry is invalid\n"));
369
6.18k
    return false;
370
6.18k
  }
371
16.3k
  entry.setParsed(true);
372
16.3k
  libmwaw::DebugStream f;
373
16.3k
  m_input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
374
16.3k
  auto sz = long(m_input->readULong(1));
375
16.3k
  if (sz+1 > entry.length()) {
376
453
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTR: string length is too small\n"));
377
453
    return false;
378
453
  }
379
1.29M
  for (long i = 0; i < sz; i++) {
380
1.28M
    if (m_input->isEnd()) {
381
0
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTR: file is too short\n"));
382
0
      return false;
383
0
    }
384
1.28M
    str += char(m_input->readULong(1));
385
1.28M
  }
386
15.8k
  f << "Entries(RSRCSTR)[" << entry.type() << ":" << entry.id() << "]:" << str;
387
15.8k
  if (sz+1 != entry.length()) {
388
    // can this happens ?
389
6.15k
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTR: ARGGS multiple strings\n"));
390
6.15k
    ascii().addDelimiter(m_input->tell(),'|');
391
6.15k
    f << "###";
392
6.15k
  }
393
15.8k
  ascii().addPos(entry.begin()-4);
394
15.8k
  ascii().addNote(f.str().c_str());
395
15.8k
  return true;
396
15.8k
}
397
398
bool MWAWRSRCParser::parseSTRList(MWAWEntry const &entry, std::vector<std::string> &list)
399
19.0k
{
400
19.0k
  list.resize(0);
401
19.0k
  if (!m_input || !entry.valid() || entry.length()<2) {
402
9.30k
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTRList: the entry is bad\n"));
403
9.30k
    return false;
404
9.30k
  }
405
9.71k
  entry.setParsed(true);
406
9.71k
  long pos = entry.begin();
407
9.71k
  long endPos = entry.end();
408
9.71k
  m_input->seek(pos, librevenge::RVNG_SEEK_SET);
409
410
9.71k
  libmwaw::DebugStream f;
411
9.71k
  f << "Entries(RSRCListStr)[" << entry.type() << ":" << entry.id() << "]:";
412
9.71k
  auto N=static_cast<int>(m_input->readULong(2));
413
9.71k
  ascii().addPos(pos-4);
414
9.71k
  ascii().addNote(f.str().c_str());
415
416
93.3k
  for (int i = 0; i < N; i++) {
417
87.6k
    f.str("");
418
87.6k
    f << "RSRCListStr-" << i << ":";
419
87.6k
    pos = m_input->tell();
420
87.6k
    if (pos+1 > endPos) {
421
1.56k
      f << "###";
422
1.56k
      ascii().addPos(pos);
423
1.56k
      ascii().addNote(f.str().c_str());
424
425
1.56k
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTRList: can not read string %d\n", i));
426
1.56k
      return false;
427
1.56k
    }
428
86.0k
    auto sz = static_cast<int>(m_input->readULong(1));
429
86.0k
    if (pos+1+sz > endPos) {
430
2.40k
      f.str("");
431
2.40k
      f << "###";
432
2.40k
      ascii().addPos(pos);
433
2.40k
      ascii().addNote(f.str().c_str());
434
435
2.40k
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parseSTRList: string size %d is bad\n", i));
436
2.40k
      return false;
437
2.40k
    }
438
439
83.6k
    std::string str("");
440
885k
    for (int c=0; c < sz; c++)
441
802k
      str += char(m_input->readULong(1));
442
83.6k
    list.push_back(str);
443
83.6k
    f << str << ",";
444
445
83.6k
    ascii().addPos(pos);
446
83.6k
    ascii().addNote(f.str().c_str());
447
83.6k
  }
448
5.74k
  return true;
449
9.71k
}
450
451
bool MWAWRSRCParser::parseClut(MWAWEntry const &entry, std::vector<MWAWColor> &list)
452
0
{
453
0
  list.resize(0);
454
0
  if (!m_input || !entry.valid() || entry.length()<8) {
455
0
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseClut: the entry is bad\n"));
456
0
    return false;
457
0
  }
458
0
  entry.setParsed(true);
459
0
  long pos = entry.begin();
460
  // skip seed
461
0
  m_input->seek(pos+4, librevenge::RVNG_SEEK_SET);
462
463
0
  libmwaw::DebugStream f;
464
0
  f << "Entries(RSRCClut)[" << entry.type() << ":" << entry.id() << "]:";
465
0
  auto flags = static_cast<int>(m_input->readULong(2));
466
0
  if (flags==0x8000) f << "indexed,";
467
0
  else if (flags) f << "#flags=" << std::hex << flags << ",";
468
0
  auto N= static_cast<int>(m_input->readULong(2));
469
0
  if (entry.length()==8+8*(N+1)) // N can be num or maxId
470
0
    N++;
471
0
  f << "N=" << N << ",";
472
0
  if (entry.length()!=8+8*N) {
473
0
    f << "###";
474
0
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseClut: find unexpected size/format\n"));
475
0
    ascii().addPos(pos-4);
476
0
    ascii().addNote(f.str().c_str());
477
0
    return false;
478
0
  }
479
0
  ascii().addPos(pos-4);
480
0
  ascii().addNote(f.str().c_str());
481
482
0
  for (int i = 0; i < N; i++) {
483
0
    pos = m_input->tell();
484
0
    f.str("");
485
0
    f << "RSRCClut-" << i << ":";
486
0
    auto index = static_cast<int>(m_input->readULong(2));
487
0
    if (index != i) {
488
0
      static bool first=true;
489
0
      if (first) {
490
0
        MWAW_DEBUG_MSG(("MWAWRSRCParser::parseClut: find some odd index value\n"));
491
0
        first = false;
492
0
      }
493
0
      f << "#index=" << index << ",";
494
0
    }
495
0
    unsigned char col[3];
496
0
    for (auto &c : col) c = static_cast<unsigned char>(m_input->readULong(2)>>8);
497
0
    MWAWColor color(col[0],col[1],col[2]);
498
0
    list.push_back(color);
499
0
    f << color << ",";
500
501
0
    ascii().addPos(pos);
502
0
    ascii().addNote(f.str().c_str());
503
0
  }
504
0
  return true;
505
0
}
506
507
////////////////////////////////////////////////////////////
508
// read the version:
509
//     id=1 version of the appliction
510
//     id=2 version of the file
511
////////////////////////////////////////////////////////////
512
std::ostream &operator<< (std::ostream &o, MWAWRSRCParser::Version const &vers)
513
0
{
514
0
  o << vers.m_string;
515
0
  if (vers.m_versionString.length())
516
0
    o << "(" << vers.m_versionString << ")";
517
0
  o << ",";
518
0
  o << "vers=" << vers.m_majorVersion;
519
0
  if (vers.m_minorVersion)
520
0
    o << "(" << vers.m_minorVersion << ")";
521
0
  o << ",";
522
0
  if (vers.m_countryCode)
523
0
    o << "country=" << std::hex << vers.m_countryCode << std::dec << ",";
524
0
  o << vers.m_extra;
525
0
  return o;
526
0
}
527
528
bool MWAWRSRCParser::parseVers(MWAWEntry const &entry, Version &vers)
529
73.8k
{
530
73.8k
  vers = Version();
531
73.8k
  if (!m_input || !entry.valid() || entry.length()<8 || !m_input->checkPosition(entry.end())) {
532
7.81k
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parseVers: entry is invalid\n"));
533
7.81k
    return false;
534
7.81k
  }
535
66.0k
  entry.setParsed(true);
536
66.0k
  libmwaw::DebugStream f;
537
66.0k
  m_input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
538
66.0k
  vers.m_majorVersion = static_cast<int>(m_input->readULong(1));
539
66.0k
  vers.m_minorVersion = static_cast<int>(m_input->readULong(1));
540
66.0k
  auto val = long(m_input->readULong(1));
541
66.0k
  if (val) f << "devStage=" << val << ",";
542
66.0k
  val = long(m_input->readULong(1));
543
66.0k
  if (val) f << "preReleaseLevel=" << std::hex << val << std::dec << ",";
544
66.0k
  vers.m_countryCode = static_cast<int>(m_input->readULong(2));
545
193k
  for (int i = 0; i < 2; i++) {
546
131k
    auto sz = static_cast<int>(m_input->readULong(1));
547
131k
    long pos = m_input->tell();
548
131k
    if (pos+sz > entry.end()) {
549
4.65k
      MWAW_DEBUG_MSG(("MWAWRSRCParser::parseVers: can not read strings %d\n",i));
550
4.65k
      return false;
551
4.65k
    }
552
127k
    std::string str("");
553
3.29M
    for (int c = 0; c < sz; c++)
554
3.16M
      str+=char(m_input->readULong(1));
555
127k
    if (i==0)
556
65.7k
      vers.m_versionString = str;
557
61.3k
    else
558
61.3k
      vers.m_string = str;
559
127k
  }
560
61.3k
  vers.m_extra = f.str();
561
61.3k
  f << "Entries(RSRCvers)[" << entry.id() << "]:" << vers;
562
61.3k
  ascii().addPos(entry.begin()-4);
563
61.3k
  ascii().addNote(f.str().c_str());
564
61.3k
  return true;
565
66.0k
}
566
567
////////////////////////////////////////////////////////////
568
// read a pict resource
569
////////////////////////////////////////////////////////////
570
bool MWAWRSRCParser::parsePICT(MWAWEntry const &entry, librevenge::RVNGBinaryData &pict)
571
6.67k
{
572
6.67k
  pict.clear();
573
6.67k
  if (!m_input || !entry.valid() || entry.length()<0xd) {
574
958
    MWAW_DEBUG_MSG(("MWAWRSRCParser::parsePICT: entry is invalid\n"));
575
958
    return false;
576
958
  }
577
578
5.71k
  libmwaw::DebugStream f;
579
5.71k
  f << "Entries(RSRC" << entry.type() << ")[" << entry.id() << "]:";
580
5.71k
  m_input->seek(entry.begin(), librevenge::RVNG_SEEK_SET);
581
5.71k
  m_input->readDataBlock(entry.length(), pict);
582
583
#ifdef DEBUG_WITH_FILES
584
  if (!entry.isParsed()) {
585
    ascii().skipZone(entry.begin(), entry.end()-1);
586
    libmwaw::DebugStream f2;
587
    f2 << "RSRC-" << entry.type() << "_" << entry.id() << ".pct";
588
    libmwaw::Debug::dumpFile(pict, f2.str().c_str());
589
  }
590
#endif
591
592
5.71k
  ascii().addPos(entry.begin()-4);
593
5.71k
  ascii().addNote(f.str().c_str());
594
595
5.71k
  entry.setParsed(true);
596
5.71k
  return true;
597
6.67k
}
598
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: