Coverage Report

Created: 2026-01-07 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poco/XML/src/SAXParser.cpp
Line
Count
Source
1
//
2
// SAXParser.cpp
3
//
4
// Library: XML
5
// Package: SAX
6
// Module:  SAX
7
//
8
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
9
// and Contributors.
10
//
11
// SPDX-License-Identifier: BSL-1.0
12
//
13
14
15
#include "Poco/SAX/SAXParser.h"
16
#include "Poco/SAX/SAXException.h"
17
#include "Poco/SAX/EntityResolverImpl.h"
18
#include "Poco/SAX/InputSource.h"
19
#include "Poco/XML/NamespaceStrategy.h"
20
#include "Poco/NumberParser.h"
21
#include "ParserEngine.h"
22
#include <sstream>
23
24
25
namespace Poco {
26
namespace XML {
27
28
29
const XMLString SAXParser::FEATURE_PARTIAL_READS = toXMLString("http://www.appinf.com/features/enable-partial-reads");
30
const XMLString SAXParser::PROPERTY_BLA_MAXIMUM_AMPLIFICATION = toXMLString("http://www.appinf.com/properties/bla-maximum-amplification");
31
const XMLString SAXParser::PROPERTY_BLA_ACTIVATION_THRESHOLD = toXMLString("http://www.appinf.com/properties/bla-activation-threshold");
32
33
34
SAXParser::SAXParser():
35
61.1k
  _namespaces(true),
36
61.1k
  _namespacePrefixes(false)
37
61.1k
{
38
61.1k
  _engine = new ParserEngine;
39
61.1k
}
40
41
42
SAXParser::SAXParser(const XMLString& encoding):
43
0
  _namespaces(true),
44
0
  _namespacePrefixes(false)
45
0
{
46
0
  _engine = new ParserEngine(encoding);
47
0
}
48
49
50
SAXParser::~SAXParser()
51
61.1k
{
52
61.1k
  delete _engine;
53
61.1k
}
54
55
56
void SAXParser::setEncoding(const XMLString& encoding)
57
0
{
58
0
  _engine->setEncoding(encoding);
59
0
}
60
61
62
const XMLString& SAXParser::getEncoding() const
63
0
{
64
0
  return _engine->getEncoding();
65
0
}
66
67
68
void SAXParser::addEncoding(const XMLString& name, Poco::TextEncoding* pEncoding)
69
0
{
70
0
  _engine->addEncoding(name, pEncoding);
71
0
}
72
73
74
void SAXParser::setEntityResolver(EntityResolver* pResolver)
75
45.9k
{
76
45.9k
  _engine->setEntityResolver(pResolver);
77
45.9k
}
78
79
80
EntityResolver* SAXParser::getEntityResolver() const
81
0
{
82
0
  return _engine->getEntityResolver();
83
0
}
84
85
86
void SAXParser::setDTDHandler(DTDHandler* pDTDHandler)
87
61.1k
{
88
61.1k
  _engine->setDTDHandler(pDTDHandler);
89
61.1k
}
90
91
92
DTDHandler* SAXParser::getDTDHandler() const
93
0
{
94
0
  return _engine->getDTDHandler();
95
0
}
96
97
98
void SAXParser::setContentHandler(ContentHandler* pContentHandler)
99
61.1k
{
100
61.1k
  _engine->setContentHandler(pContentHandler);
101
61.1k
}
102
103
104
ContentHandler* SAXParser::getContentHandler() const
105
0
{
106
0
  return _engine->getContentHandler();
107
0
}
108
109
110
void SAXParser::setErrorHandler(ErrorHandler* pErrorHandler)
111
45.9k
{
112
45.9k
  _engine->setErrorHandler(pErrorHandler);
113
45.9k
}
114
115
116
ErrorHandler* SAXParser::getErrorHandler() const
117
0
{
118
0
  return _engine->getErrorHandler();
119
0
}
120
121
122
void SAXParser::setFeature(const XMLString& featureId, bool state)
123
336k
{
124
336k
  if (featureId == XMLReader::FEATURE_VALIDATION || featureId == XMLReader::FEATURE_STRING_INTERNING)
125
0
    throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_VALIDATION));
126
336k
  else if (featureId == XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES)
127
61.1k
    _engine->setExternalGeneralEntities(state);
128
275k
  else if (featureId == XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES)
129
61.1k
    _engine->setExternalParameterEntities(state);
130
213k
  else if (featureId == XMLReader::FEATURE_NAMESPACES)
131
91.7k
    _namespaces = state;
132
122k
  else if (featureId == XMLReader::FEATURE_NAMESPACE_PREFIXES)
133
91.7k
    _namespacePrefixes = state;
134
30.5k
  else if (featureId == FEATURE_PARTIAL_READS)
135
30.5k
    _engine->setEnablePartialReads(state);
136
0
  else throw SAXNotRecognizedException(fromXMLString(featureId));
137
336k
}
138
139
140
bool SAXParser::getFeature(const XMLString& featureId) const
141
30.5k
{
142
30.5k
  if (featureId == XMLReader::FEATURE_VALIDATION || featureId == XMLReader::FEATURE_STRING_INTERNING)
143
0
    throw SAXNotSupportedException(fromXMLString(XMLReader::FEATURE_VALIDATION));
144
30.5k
  else if (featureId == XMLReader::FEATURE_EXTERNAL_GENERAL_ENTITIES)
145
0
    return _engine->getExternalGeneralEntities();
146
30.5k
  else if (featureId == XMLReader::FEATURE_EXTERNAL_PARAMETER_ENTITIES)
147
0
    return _engine->getExternalParameterEntities();
148
30.5k
  else if (featureId == XMLReader::FEATURE_NAMESPACES)
149
30.5k
    return _namespaces;
150
0
  else if (featureId == XMLReader::FEATURE_NAMESPACE_PREFIXES)
151
0
    return _namespacePrefixes;
152
0
  else if (featureId == FEATURE_PARTIAL_READS)
153
0
    return _engine->getEnablePartialReads();
154
0
  else throw SAXNotRecognizedException(fromXMLString(featureId));
155
30.5k
}
156
157
158
void SAXParser::setProperty(const XMLString& propertyId, const XMLString& value)
159
0
{
160
0
  if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER || propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER)
161
0
    throw SAXNotSupportedException(std::string("property does not take a string value: ") + fromXMLString(propertyId));
162
0
  else if (propertyId == PROPERTY_BLA_MAXIMUM_AMPLIFICATION)
163
0
    _engine->setBillionLaughsAttackProtectionMaximumAmplification(static_cast<float>(Poco::NumberParser::parseFloat(value)));
164
0
  else if (propertyId == PROPERTY_BLA_ACTIVATION_THRESHOLD)
165
0
    _engine->setBillionLaughsAttackProtectionActivationThreshold(Poco::NumberParser::parseUnsigned64(value));
166
0
  else
167
0
    throw SAXNotRecognizedException(fromXMLString(propertyId));
168
0
}
169
170
171
void SAXParser::setProperty(const XMLString& propertyId, void* value)
172
30.5k
{
173
30.5k
  if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER)
174
0
    _engine->setDeclHandler(reinterpret_cast<DeclHandler*>(value));
175
30.5k
  else if (propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER)
176
30.5k
    _engine->setLexicalHandler(reinterpret_cast<LexicalHandler*>(value));
177
0
  else throw SAXNotRecognizedException(fromXMLString(propertyId));
178
30.5k
}
179
180
181
void* SAXParser::getProperty(const XMLString& propertyId) const
182
0
{
183
0
  if (propertyId == XMLReader::PROPERTY_DECLARATION_HANDLER)
184
0
    return _engine->getDeclHandler();
185
0
  else if (propertyId == XMLReader::PROPERTY_LEXICAL_HANDLER)
186
0
    return _engine->getLexicalHandler();
187
0
  else throw SAXNotSupportedException(fromXMLString(propertyId));
188
0
}
189
190
191
void SAXParser::parse(InputSource* pInputSource)
192
0
{
193
0
  if (pInputSource->getByteStream() || pInputSource->getCharacterStream())
194
0
  {
195
0
    setupParse();
196
0
    _engine->parse(pInputSource);
197
0
  }
198
0
  else parse(pInputSource->getSystemId());
199
0
}
200
201
202
void SAXParser::parse(const XMLString& systemId)
203
0
{
204
0
  setupParse();
205
0
  EntityResolverImpl entityResolver;
206
0
  InputSource* pInputSource = entityResolver.resolveEntity(nullptr, systemId);
207
0
  if (pInputSource)
208
0
  {
209
0
    try
210
0
    {
211
0
      _engine->parse(pInputSource);
212
0
    }
213
0
    catch (...)
214
0
    {
215
0
      entityResolver.releaseInputSource(pInputSource);
216
0
      throw;
217
0
    }
218
0
    entityResolver.releaseInputSource(pInputSource);
219
0
  }
220
0
  else throw XMLException("Cannot resolve system identifier", fromXMLString(systemId));
221
0
}
222
223
224
void SAXParser::parseString(const std::string& xml)
225
30.5k
{
226
30.5k
  parseMemoryNP(xml.data(), xml.size());
227
30.5k
}
228
229
230
void SAXParser::parseMemoryNP(const char* xml, std::size_t size)
231
61.1k
{
232
61.1k
  setupParse();
233
61.1k
  _engine->parse(xml, size);
234
61.1k
}
235
236
237
void SAXParser::setupParse()
238
61.1k
{
239
61.1k
  if (_namespaces && !_namespacePrefixes)
240
7.45k
    _engine->setNamespaceStrategy(new NoNamespacePrefixesStrategy);
241
53.6k
  else if (_namespaces && _namespacePrefixes)
242
20.2k
    _engine->setNamespaceStrategy(new NamespacePrefixesStrategy);
243
33.4k
  else
244
33.4k
    _engine->setNamespaceStrategy(new NoNamespacesStrategy);
245
61.1k
}
246
247
248
} } // namespace Poco::XML