/src/libreoffice/comphelper/source/xml/ofopxmlhelper.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
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 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | |
21 | | #include <comphelper/ofopxmlhelper.hxx> |
22 | | #include <comphelper/attributelist.hxx> |
23 | | |
24 | | #include <cppuhelper/implbase.hxx> |
25 | | #include <rtl/ref.hxx> |
26 | | |
27 | | #include <com/sun/star/beans/StringPair.hpp> |
28 | | #include <com/sun/star/xml/sax/Parser.hpp> |
29 | | #include <com/sun/star/xml/sax/XDocumentHandler.hpp> |
30 | | #include <com/sun/star/xml/sax/SAXException.hpp> |
31 | | #include <com/sun/star/xml/sax/Writer.hpp> |
32 | | #include <com/sun/star/lang/IllegalArgumentException.hpp> |
33 | | #include <vector> |
34 | | |
35 | 811k | #define RELATIONINFO_FORMAT 0 |
36 | 437k | #define CONTENTTYPE_FORMAT 1 |
37 | 26.4k | #define FORMAT_MAX_ID CONTENTTYPE_FORMAT |
38 | | |
39 | | using namespace ::com::sun::star; |
40 | | |
41 | | namespace comphelper { |
42 | | |
43 | | namespace { |
44 | | |
45 | | // this helper class is designed to allow to parse ContentType- and Relationship-related information from OfficeOpenXML format |
46 | | class OFOPXMLHelper_Impl |
47 | | : public cppu::WeakImplHelper< css::xml::sax::XDocumentHandler > |
48 | | { |
49 | | sal_uInt16 const m_nFormat; // which format to parse |
50 | | |
51 | | css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > m_aResultSeq; |
52 | | std::vector< OUString > m_aElementsSeq; // stack of elements being parsed |
53 | | |
54 | | |
55 | | public: |
56 | | css::uno::Sequence< css::uno::Sequence< css::beans::StringPair > > const & GetParsingResult() const; |
57 | | |
58 | | explicit OFOPXMLHelper_Impl( sal_uInt16 nFormat ); // must not be created directly |
59 | | |
60 | | // XDocumentHandler |
61 | | virtual void SAL_CALL startDocument() override; |
62 | | virtual void SAL_CALL endDocument() override; |
63 | | virtual void SAL_CALL startElement( const OUString& aName, const css::uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) override; |
64 | | virtual void SAL_CALL endElement( const OUString& aName ) override; |
65 | | virtual void SAL_CALL characters( const OUString& aChars ) override; |
66 | | virtual void SAL_CALL ignorableWhitespace( const OUString& aWhitespaces ) override; |
67 | | virtual void SAL_CALL processingInstruction( const OUString& aTarget, const OUString& aData ) override; |
68 | | virtual void SAL_CALL setDocumentLocator( const css::uno::Reference< css::xml::sax::XLocator >& xLocator ) override; |
69 | | }; |
70 | | |
71 | | } |
72 | | |
73 | | namespace OFOPXMLHelper { |
74 | | |
75 | | /// @throws css::uno::Exception |
76 | | static uno::Sequence<uno::Sequence< beans::StringPair>> ReadSequence_Impl( |
77 | | const uno::Reference<io::XInputStream>& xInStream, |
78 | | const OUString& aStringID, sal_uInt16 nFormat, |
79 | | const uno::Reference<uno::XComponentContext>& xContext); |
80 | | |
81 | | uno::Sequence< uno::Sequence< beans::StringPair > > ReadRelationsInfoSequence( |
82 | | const uno::Reference< io::XInputStream >& xInStream, |
83 | | std::u16string_view aStreamName, |
84 | | const uno::Reference< uno::XComponentContext >& rContext ) |
85 | 14.5k | { |
86 | 14.5k | OUString aStringID = OUString::Concat("_rels/") + aStreamName; |
87 | 14.5k | return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, rContext ); |
88 | 14.5k | } |
89 | | |
90 | | |
91 | | uno::Sequence< uno::Sequence< beans::StringPair > > ReadContentTypeSequence( |
92 | | const uno::Reference< io::XInputStream >& xInStream, |
93 | | const uno::Reference< uno::XComponentContext >& rContext ) |
94 | 11.8k | { |
95 | 11.8k | return ReadSequence_Impl( xInStream, u"[Content_Types].xml"_ustr, CONTENTTYPE_FORMAT, rContext ); |
96 | 11.8k | } |
97 | | |
98 | | OUString GetContentTypeByName( |
99 | | const css::uno::Sequence<css::uno::Sequence<css::beans::StringPair>>& rContentTypes, |
100 | | const OUString& rFilename) |
101 | 0 | { |
102 | 0 | if (rContentTypes.getLength() < 2) |
103 | 0 | { |
104 | 0 | return OUString(); |
105 | 0 | } |
106 | | |
107 | 0 | const uno::Sequence<beans::StringPair>& rDefaults = rContentTypes[0]; |
108 | 0 | const uno::Sequence<beans::StringPair>& rOverrides = rContentTypes[1]; |
109 | | |
110 | | // Find the extension and use it to get the type. |
111 | 0 | const sal_Int32 nDotOffset = rFilename.lastIndexOf('.'); |
112 | 0 | const OUString aExt = (nDotOffset >= 0 ? rFilename.copy(nDotOffset + 1) : rFilename); // Skip the dot. |
113 | |
|
114 | 0 | const std::vector<OUString> aNames = { aExt, "/" + rFilename }; |
115 | 0 | for (const OUString& aName : aNames) |
116 | 0 | { |
117 | 0 | const auto it1 = std::find_if(rOverrides.begin(), rOverrides.end(), [&aName](const beans::StringPair& rPair) |
118 | 0 | { return rPair.First == aName; }); |
119 | 0 | if (it1 != rOverrides.end()) |
120 | 0 | return it1->Second; |
121 | | |
122 | 0 | const auto it2 = std::find_if(rDefaults.begin(), rDefaults.end(), [&aName](const beans::StringPair& rPair) |
123 | 0 | { return rPair.First == aName; }); |
124 | 0 | if (it2 != rDefaults.end()) |
125 | 0 | return it2->Second; |
126 | 0 | } |
127 | | |
128 | 0 | return OUString(); |
129 | 0 | } |
130 | | |
131 | | void WriteRelationsInfoSequence( |
132 | | const uno::Reference< io::XOutputStream >& xOutStream, |
133 | | const uno::Sequence< uno::Sequence< beans::StringPair > >& aSequence, |
134 | | const uno::Reference< uno::XComponentContext >& rContext ) |
135 | 0 | { |
136 | 0 | if ( !xOutStream.is() ) |
137 | 0 | throw uno::RuntimeException(u"Invalid output stream"_ustr); |
138 | | |
139 | 0 | uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(rContext); |
140 | |
|
141 | 0 | xWriter->setOutputStream( xOutStream ); |
142 | |
|
143 | 0 | OUString aRelListElement( u"Relationships"_ustr ); |
144 | 0 | OUString aRelElement( u"Relationship"_ustr ); |
145 | 0 | OUString aWhiteSpace( u" "_ustr ); |
146 | | |
147 | | // write the namespace |
148 | 0 | rtl::Reference<AttributeList> pRootAttrList = new AttributeList; |
149 | 0 | pRootAttrList->AddAttribute( |
150 | 0 | u"xmlns"_ustr, |
151 | 0 | u"http://schemas.openxmlformats.org/package/2006/relationships"_ustr ); |
152 | |
|
153 | 0 | xWriter->startDocument(); |
154 | 0 | xWriter->startElement( aRelListElement, pRootAttrList ); |
155 | |
|
156 | 0 | for ( const auto & i : aSequence ) |
157 | 0 | { |
158 | 0 | rtl::Reference<AttributeList> pAttrList = new AttributeList; |
159 | 0 | for( const beans::StringPair & pair : i ) |
160 | 0 | { |
161 | 0 | if ( !(pair.First == "Id" |
162 | 0 | || pair.First == "Type" |
163 | 0 | || pair.First == "TargetMode" |
164 | 0 | || pair.First == "Target") ) |
165 | 0 | { |
166 | | // TODO/LATER: should the extensions be allowed? |
167 | 0 | throw lang::IllegalArgumentException(); |
168 | 0 | } |
169 | 0 | pAttrList->AddAttribute( pair.First, pair.Second ); |
170 | 0 | } |
171 | | |
172 | 0 | xWriter->startElement( aRelElement, pAttrList ); |
173 | 0 | xWriter->ignorableWhitespace( aWhiteSpace ); |
174 | 0 | xWriter->endElement( aRelElement ); |
175 | 0 | } |
176 | | |
177 | 0 | xWriter->ignorableWhitespace( aWhiteSpace ); |
178 | 0 | xWriter->endElement( aRelListElement ); |
179 | 0 | xWriter->endDocument(); |
180 | 0 | } |
181 | | |
182 | | |
183 | | void WriteContentSequence( |
184 | | const uno::Reference< io::XOutputStream >& xOutStream, |
185 | | const uno::Sequence< beans::StringPair >& aDefaultsSequence, |
186 | | const uno::Sequence< beans::StringPair >& aOverridesSequence, |
187 | | const uno::Reference< uno::XComponentContext >& rContext ) |
188 | 0 | { |
189 | 0 | if ( !xOutStream.is() ) |
190 | 0 | throw uno::RuntimeException(u"Invalid output stream"_ustr); |
191 | | |
192 | 0 | uno::Reference< css::xml::sax::XWriter > xWriter = css::xml::sax::Writer::create(rContext); |
193 | |
|
194 | 0 | xWriter->setOutputStream( xOutStream ); |
195 | |
|
196 | 0 | static constexpr OUString aTypesElement(u"Types"_ustr); |
197 | 0 | static constexpr OUString aDefaultElement(u"Default"_ustr); |
198 | 0 | static constexpr OUString aOverrideElement(u"Override"_ustr); |
199 | 0 | static constexpr OUString aContentTypeAttr(u"ContentType"_ustr); |
200 | 0 | static constexpr OUString aWhiteSpace(u" "_ustr); |
201 | | |
202 | | // write the namespace |
203 | 0 | rtl::Reference<AttributeList> pRootAttrList = new AttributeList; |
204 | 0 | pRootAttrList->AddAttribute( |
205 | 0 | u"xmlns"_ustr, |
206 | 0 | u"http://schemas.openxmlformats.org/package/2006/content-types"_ustr ); |
207 | |
|
208 | 0 | xWriter->startDocument(); |
209 | 0 | xWriter->startElement( aTypesElement, pRootAttrList ); |
210 | |
|
211 | 0 | for ( const beans::StringPair & pair : aDefaultsSequence ) |
212 | 0 | { |
213 | 0 | rtl::Reference<AttributeList> pAttrList = new AttributeList; |
214 | 0 | pAttrList->AddAttribute( u"Extension"_ustr, pair.First ); |
215 | 0 | pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); |
216 | |
|
217 | 0 | xWriter->startElement( aDefaultElement, pAttrList ); |
218 | 0 | xWriter->ignorableWhitespace( aWhiteSpace ); |
219 | 0 | xWriter->endElement( aDefaultElement ); |
220 | 0 | } |
221 | |
|
222 | 0 | for ( const beans::StringPair & pair : aOverridesSequence ) |
223 | 0 | { |
224 | 0 | rtl::Reference<AttributeList> pAttrList = new AttributeList; |
225 | 0 | pAttrList->AddAttribute( u"PartName"_ustr, pair.First ); |
226 | 0 | pAttrList->AddAttribute( aContentTypeAttr, pair.Second ); |
227 | |
|
228 | 0 | xWriter->startElement( aOverrideElement, pAttrList ); |
229 | 0 | xWriter->ignorableWhitespace( aWhiteSpace ); |
230 | 0 | xWriter->endElement( aOverrideElement ); |
231 | 0 | } |
232 | |
|
233 | 0 | xWriter->ignorableWhitespace( aWhiteSpace ); |
234 | 0 | xWriter->endElement( aTypesElement ); |
235 | 0 | xWriter->endDocument(); |
236 | |
|
237 | 0 | } |
238 | | |
239 | | uno::Sequence< uno::Sequence< beans::StringPair > > ReadSequence_Impl( |
240 | | const uno::Reference< io::XInputStream >& xInStream, |
241 | | const OUString& aStringID, sal_uInt16 nFormat, |
242 | | const uno::Reference< uno::XComponentContext >& rContext ) |
243 | 26.4k | { |
244 | 26.4k | if ( !rContext.is() || !xInStream.is() || nFormat > FORMAT_MAX_ID ) |
245 | 0 | throw uno::RuntimeException(u"Invalid input stream or context"_ustr); |
246 | | |
247 | | |
248 | 26.4k | uno::Reference< css::xml::sax::XParser > xParser = css::xml::sax::Parser::create( rContext ); |
249 | | |
250 | 26.4k | rtl::Reference<OFOPXMLHelper_Impl> pHelper = new OFOPXMLHelper_Impl( nFormat ); |
251 | 26.4k | css::xml::sax::InputSource aParserInput; |
252 | 26.4k | aParserInput.aInputStream = xInStream; |
253 | 26.4k | aParserInput.sSystemId = aStringID; |
254 | 26.4k | xParser->setDocumentHandler( pHelper ); |
255 | 26.4k | xParser->parseStream( aParserInput ); |
256 | 26.4k | xParser->setDocumentHandler( uno::Reference < css::xml::sax::XDocumentHandler > () ); |
257 | | |
258 | 26.4k | return pHelper->GetParsingResult(); |
259 | 26.4k | } |
260 | | |
261 | | } // namespace OFOPXMLHelper |
262 | | |
263 | | // Relations info related strings |
264 | | constexpr OUStringLiteral g_aRelListElement(u"Relationships"); |
265 | | constexpr OUStringLiteral g_aRelElement( u"Relationship" ); |
266 | | constexpr OUString g_aIDAttr( u"Id"_ustr ); |
267 | | constexpr OUString g_aTypeAttr( u"Type"_ustr ); |
268 | | constexpr OUString g_aTargetModeAttr( u"TargetMode"_ustr ); |
269 | | constexpr OUString g_aTargetAttr( u"Target"_ustr ); |
270 | | |
271 | | // ContentType related strings |
272 | | constexpr OUStringLiteral g_aTypesElement( u"Types" ); |
273 | | constexpr OUStringLiteral g_aDefaultElement( u"Default" ); |
274 | | constexpr OUStringLiteral g_aOverrideElement( u"Override" ); |
275 | | constexpr OUStringLiteral g_aExtensionAttr( u"Extension" ); |
276 | | constexpr OUStringLiteral g_aPartNameAttr( u"PartName" ); |
277 | | constexpr OUString g_aContentTypeAttr( u"ContentType"_ustr ); |
278 | | |
279 | | OFOPXMLHelper_Impl::OFOPXMLHelper_Impl( sal_uInt16 nFormat ) |
280 | 26.4k | : m_nFormat( nFormat ) |
281 | 26.4k | { |
282 | 26.4k | } |
283 | | |
284 | | uno::Sequence< uno::Sequence< beans::StringPair > > const & OFOPXMLHelper_Impl::GetParsingResult() const |
285 | 26.3k | { |
286 | 26.3k | if ( !m_aElementsSeq.empty() ) |
287 | 0 | throw uno::RuntimeException(); // the parsing has still not finished! |
288 | | |
289 | 26.3k | return m_aResultSeq; |
290 | 26.3k | } |
291 | | |
292 | | |
293 | | void SAL_CALL OFOPXMLHelper_Impl::startDocument() |
294 | 26.4k | { |
295 | 26.4k | } |
296 | | |
297 | | |
298 | | void SAL_CALL OFOPXMLHelper_Impl::endDocument() |
299 | 26.3k | { |
300 | 26.3k | } |
301 | | |
302 | | |
303 | | void SAL_CALL OFOPXMLHelper_Impl::startElement( const OUString& aName, const uno::Reference< css::xml::sax::XAttributeList >& xAttribs ) |
304 | 265k | { |
305 | 265k | if ( m_nFormat == RELATIONINFO_FORMAT ) |
306 | 66.0k | { |
307 | 66.0k | if ( aName == g_aRelListElement ) |
308 | 14.5k | { |
309 | 14.5k | sal_Int32 nNewLength = m_aElementsSeq.size() + 1; |
310 | | |
311 | 14.5k | if ( nNewLength != 1 ) |
312 | 0 | throw css::xml::sax::SAXException(); // TODO: this element must be the first level element |
313 | | |
314 | 14.5k | m_aElementsSeq.push_back( aName ); |
315 | | |
316 | 14.5k | return; // nothing to do |
317 | 14.5k | } |
318 | 51.5k | else if ( aName == g_aRelElement ) |
319 | 51.4k | { |
320 | 51.4k | sal_Int32 nNewLength = m_aElementsSeq.size() + 1; |
321 | 51.4k | if ( nNewLength != 2 ) |
322 | 0 | throw css::xml::sax::SAXException(); // TODO: this element must be the second level element |
323 | | |
324 | 51.4k | m_aElementsSeq.push_back( aName ); |
325 | | |
326 | 51.4k | sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1; |
327 | 51.4k | m_aResultSeq.realloc( nNewEntryNum ); |
328 | 51.4k | auto pResultSeq = m_aResultSeq.getArray(); |
329 | 51.4k | sal_Int32 nAttrNum = 0; |
330 | 51.4k | pResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4 |
331 | 51.4k | auto pAttrs = pResultSeq[nNewEntryNum-1].getArray(); |
332 | | |
333 | 51.4k | OUString aIDValue = xAttribs->getValueByName( g_aIDAttr ); |
334 | 51.4k | if ( aIDValue.isEmpty() ) |
335 | 0 | throw css::xml::sax::SAXException(); // TODO: the ID value must present |
336 | | |
337 | 51.4k | OUString aTypeValue = xAttribs->getValueByName( g_aTypeAttr ); |
338 | 51.4k | OUString aTargetValue = xAttribs->getValueByName( g_aTargetAttr ); |
339 | 51.4k | OUString aTargetModeValue = xAttribs->getValueByName( g_aTargetModeAttr ); |
340 | | |
341 | 51.4k | pAttrs[++nAttrNum - 1].First = g_aIDAttr; |
342 | 51.4k | pAttrs[nAttrNum - 1].Second = aIDValue; |
343 | | |
344 | 51.4k | if ( !aTypeValue.isEmpty() ) |
345 | 51.4k | { |
346 | 51.4k | pAttrs[++nAttrNum - 1].First = g_aTypeAttr; |
347 | 51.4k | pAttrs[nAttrNum - 1].Second = aTypeValue; |
348 | 51.4k | } |
349 | | |
350 | 51.4k | if ( !aTargetValue.isEmpty() ) |
351 | 51.4k | { |
352 | 51.4k | pAttrs[++nAttrNum - 1].First = g_aTargetAttr; |
353 | 51.4k | pAttrs[nAttrNum - 1].Second = aTargetValue; |
354 | 51.4k | } |
355 | | |
356 | 51.4k | if ( !aTargetModeValue.isEmpty() ) |
357 | 1.43k | { |
358 | 1.43k | pAttrs[++nAttrNum - 1].First = g_aTargetModeAttr; |
359 | 1.43k | pAttrs[nAttrNum - 1].Second = aTargetModeValue; |
360 | 1.43k | } |
361 | | |
362 | 51.4k | pResultSeq[nNewEntryNum-1].realloc( nAttrNum ); |
363 | 51.4k | } |
364 | 3 | else |
365 | 3 | throw css::xml::sax::SAXException(); // TODO: no other elements expected! |
366 | 66.0k | } |
367 | 199k | else if ( m_nFormat == CONTENTTYPE_FORMAT ) |
368 | 199k | { |
369 | 199k | if ( aName == g_aTypesElement ) |
370 | 11.8k | { |
371 | 11.8k | sal_Int32 nNewLength = m_aElementsSeq.size() + 1; |
372 | | |
373 | 11.8k | if ( nNewLength != 1 ) |
374 | 0 | throw css::xml::sax::SAXException(); // TODO: this element must be the first level element |
375 | | |
376 | 11.8k | m_aElementsSeq.push_back( aName ); |
377 | | |
378 | 11.8k | if ( !m_aResultSeq.hasElements() ) |
379 | 11.8k | m_aResultSeq.realloc( 2 ); |
380 | | |
381 | 11.8k | return; // nothing to do |
382 | 11.8k | } |
383 | 187k | else if ( aName == g_aDefaultElement ) |
384 | 20.4k | { |
385 | 20.4k | sal_Int32 nNewLength = m_aElementsSeq.size() + 1; |
386 | 20.4k | if ( nNewLength != 2 ) |
387 | 0 | throw css::xml::sax::SAXException(); // TODO: this element must be the second level element |
388 | | |
389 | 20.4k | m_aElementsSeq.push_back( aName ); |
390 | | |
391 | 20.4k | if ( !m_aResultSeq.hasElements() ) |
392 | 0 | m_aResultSeq.realloc( 2 ); |
393 | | |
394 | 20.4k | if ( m_aResultSeq.getLength() != 2 ) |
395 | 0 | throw uno::RuntimeException(u"m_aResultSeq already has elements and is not reallocated to 2."_ustr); |
396 | | |
397 | 20.4k | auto pResultSeq = m_aResultSeq.getArray(); |
398 | | |
399 | 20.4k | const OUString aExtensionValue = xAttribs->getValueByName( g_aExtensionAttr ); |
400 | 20.4k | if ( aExtensionValue.isEmpty() ) |
401 | 1 | throw css::xml::sax::SAXException(); // TODO: the Extension value must present |
402 | | |
403 | 20.4k | const OUString aContentTypeValue = xAttribs->getValueByName( g_aContentTypeAttr ); |
404 | 20.4k | if ( aContentTypeValue.isEmpty() ) |
405 | 4 | throw css::xml::sax::SAXException(); // TODO: the ContentType value must present |
406 | | |
407 | 20.4k | const sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1; |
408 | 20.4k | pResultSeq[0].realloc( nNewResultLen ); |
409 | 20.4k | auto pSeq = pResultSeq[0].getArray(); |
410 | | |
411 | 20.4k | pSeq[nNewResultLen-1].First = aExtensionValue; |
412 | 20.4k | pSeq[nNewResultLen-1].Second = aContentTypeValue; |
413 | 20.4k | } |
414 | 167k | else if ( aName == g_aOverrideElement ) |
415 | 167k | { |
416 | 167k | sal_Int32 nNewLength = m_aElementsSeq.size() + 1; |
417 | 167k | if ( nNewLength != 2 ) |
418 | 0 | throw css::xml::sax::SAXException(); // TODO: this element must be the second level element |
419 | | |
420 | 167k | m_aElementsSeq.push_back( aName ); |
421 | | |
422 | 167k | if ( !m_aResultSeq.hasElements() ) |
423 | 0 | m_aResultSeq.realloc( 2 ); |
424 | | |
425 | 167k | if ( m_aResultSeq.getLength() != 2 ) |
426 | 0 | throw uno::RuntimeException(u"m_aResultSeq already has elements and is not reallocated to 2."_ustr); |
427 | | |
428 | 167k | auto pResultSeq = m_aResultSeq.getArray(); |
429 | | |
430 | 167k | OUString aPartNameValue = xAttribs->getValueByName( g_aPartNameAttr ); |
431 | 167k | if ( aPartNameValue.isEmpty() ) |
432 | 0 | throw css::xml::sax::SAXException(); // TODO: the PartName value must present |
433 | | |
434 | 167k | OUString aContentTypeValue = xAttribs->getValueByName( g_aContentTypeAttr ); |
435 | 167k | if ( aContentTypeValue.isEmpty() ) |
436 | 1 | throw css::xml::sax::SAXException(); // TODO: the ContentType value must present |
437 | | |
438 | 167k | sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1; |
439 | 167k | pResultSeq[1].realloc( nNewResultLen ); |
440 | 167k | auto pSeq = pResultSeq[1].getArray(); |
441 | | |
442 | 167k | pSeq[nNewResultLen-1].First = aPartNameValue; |
443 | 167k | pSeq[nNewResultLen-1].Second = aContentTypeValue; |
444 | 167k | } |
445 | 5 | else |
446 | 5 | throw css::xml::sax::SAXException(); // TODO: no other elements expected! |
447 | 199k | } |
448 | 0 | else |
449 | 0 | throw css::xml::sax::SAXException(); // TODO: no other elements expected! |
450 | 265k | } |
451 | | |
452 | | |
453 | | void SAL_CALL OFOPXMLHelper_Impl::endElement( const OUString& aName ) |
454 | 265k | { |
455 | 265k | if ( m_nFormat == RELATIONINFO_FORMAT || m_nFormat == CONTENTTYPE_FORMAT ) |
456 | 265k | { |
457 | 265k | sal_Int32 nLength = m_aElementsSeq.size(); |
458 | 265k | if ( nLength <= 0 ) |
459 | 0 | throw css::xml::sax::SAXException(); // TODO: no other end elements expected! |
460 | | |
461 | 265k | if ( m_aElementsSeq[nLength-1] != aName ) |
462 | 0 | throw css::xml::sax::SAXException(); // TODO: unexpected element ended |
463 | | |
464 | 265k | m_aElementsSeq.resize( nLength - 1 ); |
465 | 265k | } |
466 | 265k | } |
467 | | |
468 | | |
469 | | void SAL_CALL OFOPXMLHelper_Impl::characters( const OUString& /*aChars*/ ) |
470 | 20.4k | { |
471 | 20.4k | } |
472 | | |
473 | | |
474 | | void SAL_CALL OFOPXMLHelper_Impl::ignorableWhitespace( const OUString& /*aWhitespaces*/ ) |
475 | 0 | { |
476 | 0 | } |
477 | | |
478 | | |
479 | | void SAL_CALL OFOPXMLHelper_Impl::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ ) |
480 | 3 | { |
481 | 3 | } |
482 | | |
483 | | |
484 | | void SAL_CALL OFOPXMLHelper_Impl::setDocumentLocator( const uno::Reference< css::xml::sax::XLocator >& /*xLocator*/ ) |
485 | 26.4k | { |
486 | 26.4k | } |
487 | | |
488 | | } // namespace comphelper |
489 | | |
490 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |