Coverage Report

Created: 2026-10-28 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libwpd/src/lib/WP3ResourceFork.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
2
/* libwpd
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) 2005 Fridrich Strba (fridrich.strba@bluewin.ch)
11
 *
12
 * For minor contributions see the git repository.
13
 *
14
 * Alternatively, the contents of this file may be used under the terms
15
 * of the GNU Lesser General Public License Version 2.1 or later
16
 * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are
17
 * applicable instead of those above.
18
 *
19
 * For further information visit http://libwpd.sourceforge.net
20
 */
21
22
/* "This product is not manufactured, approved, or supported by
23
 * Corel Corporation or Corel Corporation Limited."
24
 */
25
26
#include "WP3ResourceFork.h"
27
#include "libwpd_internal.h"
28
#include "WPXEncryption.h"
29
#include <vector>
30
#include <sstream>
31
32
WP3ResourceFork::WP3ResourceFork(librevenge::RVNGInputStream *input, WPXEncryption *encryption) :
33
387
  m_resourcesTypeMultimap(), m_resourcesIDMultimap()
34
387
{
35
387
  input->seek(16, librevenge::RVNG_SEEK_SET);
36
387
  unsigned dataOffset = readU32(input, encryption, true);
37
387
  unsigned mapOffset = readU32(input, encryption, true);
38
  /* unsigned dataLength = */
39
387
  readU32(input, encryption, true);
40
  /* unsigned mapLength = */
41
387
  readU32(input, encryption, true);
42
43
387
  input->seek(40+mapOffset, librevenge::RVNG_SEEK_SET);
44
45
387
  unsigned typeOffset = readU16(input, encryption, true);
46
387
  unsigned nameListOffset = readU16(input, encryption, true);
47
48
387
  input->seek(16+typeOffset+mapOffset, librevenge::RVNG_SEEK_SET);
49
387
  auto resourceTypesNumber = (unsigned short)(1 + readU16(input, encryption, true));
50
51
2.47k
  for (unsigned i=0; i < resourceTypesNumber; i++)
52
2.09k
  {
53
2.09k
    unsigned resourceType = readU32(input,encryption, true);
54
2.09k
    unsigned resourcesNumber = 1+readU16(input, encryption, true);
55
2.09k
    unsigned referenceListOffset = 16+typeOffset+mapOffset+readU16(input, encryption, true);
56
2.09k
    long position = input->tell();
57
2.09k
    input->seek(referenceListOffset, librevenge::RVNG_SEEK_SET);
58
6.52k
    for (unsigned j=0; j < resourcesNumber; j++)
59
4.43k
    {
60
4.43k
      unsigned resourceReferenceID = readU16(input, encryption, true);
61
4.43k
      unsigned short resourceNameOffset = readU16(input, encryption, true);
62
4.43k
      librevenge::RVNGString resourceName;
63
4.43k
      if (resourceNameOffset != 0xffff)
64
3.60k
      {
65
3.60k
        long position2 = input->tell();
66
3.60k
        input->seek(16+mapOffset+nameListOffset+resourceNameOffset, librevenge::RVNG_SEEK_SET);
67
3.60k
        resourceName = readPascalString(input, encryption);
68
3.60k
        input->seek(position2, librevenge::RVNG_SEEK_SET);
69
3.60k
      }
70
4.43k
      unsigned char resourceAttributes = readU8(input, encryption);
71
4.43k
      auto offsetToData = (unsigned)((unsigned)readU8(input, encryption) << 16);
72
4.43k
      offsetToData |= readU16(input, encryption, true);
73
4.43k
      offsetToData += 16+dataOffset;
74
4.43k
      long position3 = input->tell();
75
4.43k
      input->seek(offsetToData, librevenge::RVNG_SEEK_SET);
76
4.43k
      unsigned resourceDataSize = readU32(input, encryption, true);
77
78
4.43k
      unsigned long oldEncryptionOffset = 0;
79
4.43k
      unsigned char oldEncryptionMaskBase = 0;
80
4.43k
      if (encryption)
81
4.27k
      {
82
4.27k
        oldEncryptionOffset = encryption->getEncryptionStartOffset();
83
4.27k
        oldEncryptionMaskBase = encryption->getEncryptionMaskBase();
84
        /* WBOX resource and PICT resource for the time being */
85
4.27k
        if (resourceType == 0x57424f58 /* WBOX */ || resourceType == 0x50494354 /* PICT */)
86
423
        {
87
423
          encryption->setEncryptionStartOffset((unsigned long)input->tell());
88
423
          encryption->setEncryptionMaskBase(0);
89
423
        }
90
4.27k
      }
91
92
4.43k
      librevenge::RVNGBinaryData resourceData;
93
1.32M
      for (unsigned long k = 0; k < (unsigned long)resourceDataSize && !input->isEnd(); k++)
94
1.32M
        resourceData.append((unsigned char)readU8(input, encryption));
95
96
4.43k
      if (encryption)
97
4.27k
      {
98
4.27k
        encryption->setEncryptionStartOffset(oldEncryptionOffset);
99
4.27k
        encryption->setEncryptionMaskBase(oldEncryptionMaskBase);
100
4.27k
      }
101
102
4.43k
      input->seek(position3, librevenge::RVNG_SEEK_SET);
103
4.43k
      auto resource = std::make_shared<WP3Resource>(resourceType, resourceReferenceID, resourceName, resourceAttributes, resourceData);
104
4.43k
      m_resourcesTypeMultimap.insert(std::make_pair(resourceType, resource));
105
4.43k
      m_resourcesIDMultimap.insert(std::make_pair(resourceReferenceID, resource));
106
4.43k
      WPD_DEBUG_MSG(("WP3Resource: Type 0x%.8x, ID %i, name %s, attributes 0x%.2x\n", resourceType, resourceReferenceID, resourceName.cstr(), resourceAttributes));
107
4.43k
      input->seek(4, librevenge::RVNG_SEEK_CUR);
108
#if 0
109
      librevenge::RVNGInputStream *tmpBinaryStream = resourceData.getDataStream();
110
      int indexNumber = 0;
111
      while (!tmpBinaryStream->isEnd())
112
      {
113
        if (!(indexNumber % 16))
114
          printf("%.8x: ", indexNumber);
115
        else if (!(indexNumber % 8))
116
          printf("| ");
117
        printf("%.2x ", readU8(tmpBinaryStream, 0));
118
        indexNumber++;
119
        if (!(indexNumber % 16))
120
          printf("\n");
121
      }
122
      printf("\n");
123
#endif
124
#if 0
125
      std::ostringstream filename;
126
      filename << "binarydump" << m_resourcesTypeMultimap.size() << ".bin";
127
      FILE *f = fopen(filename.str().c_str(), "wb");
128
      librevenge::RVNGBinaryData tmpResData;
129
      for (int tmpIndex = 0; tmpIndex < 512; tmpIndex++)
130
        tmpResData.append((const unsigned char)0);
131
      tmpResData.append(resourceData);
132
      if (f)
133
      {
134
        librevenge::RVNGInputStream *tmpStream = tmpResData.getDataStream();
135
        while (!tmpStream->isEnd())
136
          fprintf(f, "%c", readU8(tmpStream, 0));
137
        fclose(f);
138
      }
139
#endif
140
4.43k
    }
141
2.09k
    input->seek(position, librevenge::RVNG_SEEK_SET);
142
2.09k
  }
143
387
}
144
145
WP3ResourceFork::~WP3ResourceFork()
146
188
{
147
188
}
148
149
const WP3Resource *WP3ResourceFork::getResource(unsigned type, unsigned ID) const
150
7.06k
{
151
7.06k
  auto tempPair = m_resourcesTypeMultimap.equal_range(type);
152
153
7.06k
  if (tempPair.first == m_resourcesTypeMultimap.end())
154
551
    return nullptr;
155
156
10.6k
  for (auto iter = tempPair.first; iter != tempPair.second; ++iter)
157
9.76k
    if (iter->second->getResourceReferenceID() == ID)
158
5.67k
      return iter->second.get();
159
160
835
  return nullptr;
161
6.51k
}
162
163
/* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */