Coverage Report

Created: 2026-03-12 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libstaroffice/src/lib/SDAParser.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
/* libstaroffice
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 <cstring>
35
#include <iomanip>
36
#include <iostream>
37
#include <limits>
38
#include <sstream>
39
40
#include <librevenge/librevenge.h>
41
42
#include "STOFFGraphicListener.hxx"
43
#include "STOFFOLEParser.hxx"
44
45
#include "StarFileManager.hxx"
46
#include "StarObjectDraw.hxx"
47
#include "StarZone.hxx"
48
49
#include "SDAParser.hxx"
50
51
/** Internal: the structures of a SDAParser */
52
namespace SDAParserInternal
53
{
54
////////////////////////////////////////
55
//! Internal: the state of a SDAParser
56
struct State {
57
  //! constructor
58
  State()
59
91.3k
    : m_actPage(0)
60
91.3k
    , m_numPages(0)
61
91.3k
    , m_mainGraphic()
62
91.3k
  {
63
91.3k
  }
64
65
  int m_actPage /** the actual page */, m_numPages /** the number of page of the final document */;
66
  std::shared_ptr<StarObjectDraw> m_mainGraphic;
67
};
68
69
}
70
71
////////////////////////////////////////////////////////////
72
// constructor/destructor, ...
73
////////////////////////////////////////////////////////////
74
SDAParser::SDAParser(STOFFInputStreamPtr &input, STOFFHeader *header)
75
36.6k
  : STOFFGraphicParser(input, header)
76
36.6k
  , m_password(nullptr)
77
36.6k
  , m_oleParser()
78
36.6k
  , m_state(new SDAParserInternal::State)
79
36.6k
{
80
36.6k
}
81
82
SDAParser::~SDAParser()
83
36.6k
{
84
36.6k
}
85
86
////////////////////////////////////////////////////////////
87
// the parser
88
////////////////////////////////////////////////////////////
89
void SDAParser::parse(librevenge::RVNGDrawingInterface *docInterface)
90
16.5k
{
91
16.5k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libstoff::ParseException());
92
16.5k
  bool ok = true;
93
16.5k
  try {
94
    // create the asciiFile
95
16.5k
    checkHeader(nullptr);
96
16.5k
    ok = createZones();
97
16.5k
    if (ok) {
98
16.0k
      createDocument(docInterface);
99
16.0k
      if (m_state->m_mainGraphic)
100
16.0k
        m_state->m_mainGraphic->sendPages(getGraphicListener());
101
#ifdef DEBUG
102
      StarFileManager::checkUnparsed(getInput(), m_oleParser, m_password);
103
#endif
104
16.0k
    }
105
16.5k
    ascii().reset();
106
16.5k
  }
107
16.5k
  catch (...) {
108
19
    STOFF_DEBUG_MSG(("SDAParser::parse: exception catched when parsing\n"));
109
19
    ok = false;
110
19
  }
111
112
16.5k
  resetGraphicListener();
113
16.5k
  if (!ok) throw(libstoff::ParseException());
114
16.5k
}
115
116
void SDAParser::parse(librevenge::RVNGPresentationInterface *docInterface)
117
1.57k
{
118
1.57k
  if (!getInput().get() || !checkHeader(nullptr))  throw(libstoff::ParseException());
119
1.57k
  bool ok = true;
120
1.57k
  try {
121
    // create the asciiFile
122
1.57k
    checkHeader(nullptr);
123
1.57k
    ok = createZones();
124
1.57k
    if (ok) {
125
1.57k
      createDocument(docInterface);
126
1.57k
      if (m_state->m_mainGraphic)
127
1.57k
        m_state->m_mainGraphic->sendPages(getGraphicListener());
128
#ifdef DEBUG
129
      StarFileManager::checkUnparsed(getInput(), m_oleParser, m_password);
130
#endif
131
1.57k
    }
132
1.57k
    ascii().reset();
133
1.57k
  }
134
1.57k
  catch (...) {
135
4
    STOFF_DEBUG_MSG(("SDAParser::parse: exception catched when parsing\n"));
136
4
    ok = false;
137
4
  }
138
139
1.57k
  resetGraphicListener();
140
1.57k
  if (!ok) throw(libstoff::ParseException());
141
1.57k
}
142
143
bool SDAParser::createZones()
144
18.0k
{
145
18.0k
  m_oleParser.reset(new STOFFOLEParser);
146
18.0k
  m_oleParser->parse(getInput());
147
148
18.0k
  auto mainOle=m_oleParser->getDirectory("/");
149
18.0k
  if (!mainOle) {
150
334
    STOFF_DEBUG_MSG(("SDAParser::parse: can not find the main ole\n"));
151
334
    return false;
152
334
  }
153
17.7k
  mainOle->m_parsed=true;
154
17.7k
  StarObject mainObject(m_password, m_oleParser, mainOle);
155
17.7k
  if (mainObject.getDocumentKind()!=STOFFDocument::STOFF_K_DRAW) {
156
125
    STOFF_DEBUG_MSG(("SDAParser::createZones: can not find the main graphic\n"));
157
125
    return false;
158
125
  }
159
17.6k
  m_state->m_mainGraphic.reset(new StarObjectDraw(mainObject, false));
160
17.6k
  return m_state->m_mainGraphic->parse();
161
17.7k
}
162
163
////////////////////////////////////////////////////////////
164
// create the document and send data
165
////////////////////////////////////////////////////////////
166
void SDAParser::createDocument(librevenge::RVNGDrawingInterface *documentInterface)
167
16.0k
{
168
16.0k
  if (!documentInterface) return;
169
170
16.0k
  std::vector<STOFFPageSpan> pageList;
171
16.0k
  if (!m_state->m_mainGraphic || !m_state->m_mainGraphic->updatePageSpans(pageList, m_state->m_numPages)) {
172
14.4k
    STOFFPageSpan ps(getPageSpan());
173
14.4k
    ps.m_pageSpan=1;
174
14.4k
    pageList.push_back(ps);
175
14.4k
    m_state->m_numPages = 1;
176
14.4k
  }
177
16.0k
  STOFFGraphicListenerPtr listen(new STOFFGraphicListener(getParserState()->m_listManager, pageList, documentInterface));
178
16.0k
  setGraphicListener(listen);
179
16.0k
  if (m_state->m_mainGraphic)
180
16.0k
    listen->setDocumentMetaData(m_state->m_mainGraphic->getMetaData());
181
182
16.0k
  listen->startDocument();
183
16.0k
  if (m_state->m_mainGraphic)
184
16.0k
    m_state->m_mainGraphic->sendMasterPages(listen);
185
16.0k
}
186
187
void SDAParser::createDocument(librevenge::RVNGPresentationInterface *documentInterface)
188
1.57k
{
189
1.57k
  if (!documentInterface) return;
190
191
1.57k
  std::vector<STOFFPageSpan> pageList;
192
1.57k
  if (!m_state->m_mainGraphic || !m_state->m_mainGraphic->updatePageSpans(pageList, m_state->m_numPages)) {
193
220
    STOFFPageSpan ps(getPageSpan());
194
220
    ps.m_pageSpan=1;
195
220
    pageList.push_back(ps);
196
220
    m_state->m_numPages = 1;
197
220
  }
198
1.57k
  STOFFGraphicListenerPtr listen(new STOFFGraphicListener(getParserState()->m_listManager, pageList, documentInterface));
199
1.57k
  setGraphicListener(listen);
200
1.57k
  if (m_state->m_mainGraphic)
201
1.57k
    listen->setDocumentMetaData(m_state->m_mainGraphic->getMetaData());
202
203
1.57k
  listen->startDocument();
204
1.57k
  if (m_state->m_mainGraphic)
205
1.57k
    m_state->m_mainGraphic->sendMasterPages(listen);
206
1.57k
}
207
208
////////////////////////////////////////////////////////////
209
//
210
// Intermediate level
211
//
212
////////////////////////////////////////////////////////////
213
214
////////////////////////////////////////////////////////////
215
//
216
// Low level
217
//
218
////////////////////////////////////////////////////////////
219
220
////////////////////////////////////////////////////////////
221
// read the header
222
////////////////////////////////////////////////////////////
223
bool SDAParser::checkHeader(STOFFHeader *header, bool /*strict*/)
224
54.7k
{
225
54.7k
  *m_state = SDAParserInternal::State();
226
227
54.7k
  STOFFInputStreamPtr input = getInput();
228
54.7k
  if (!input || !input->hasDataFork() || !input->isStructured())
229
0
    return false;
230
54.7k
  bool isPres=false;
231
54.7k
  STOFFInputStreamPtr drawInput=input->getSubStreamByName("StarDrawDocument");
232
54.7k
  if (!drawInput) {
233
47.6k
    drawInput=input->getSubStreamByName("StarDrawDocument3");
234
47.6k
    if (!drawInput)
235
0
      return false;
236
47.6k
    STOFFOLEParser oleParser;
237
47.6k
    std::string clipName;
238
47.6k
    isPres=oleParser.getCompObjName(input, clipName) && clipName.substr(0,11)=="StarImpress";
239
47.6k
  }
240
54.7k
  if (header) {
241
18.5k
    header->reset(1, isPres ? STOFFDocument::STOFF_K_PRESENTATION : STOFFDocument::STOFF_K_DRAW);
242
18.5k
    drawInput->seek(0, librevenge::RVNG_SEEK_SET);
243
18.5k
    header->setEncrypted(drawInput->readULong(2)!=0x7244);
244
18.5k
  }
245
54.7k
  return true;
246
54.7k
}
247
248
249
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: