Line data Source code
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 <com/sun/star/beans/StringPair.hpp>
22 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
23 : #include <com/sun/star/io/XActiveDataSource.hpp>
24 : #include <com/sun/star/xml/sax/Parser.hpp>
25 : #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
26 : #include <com/sun/star/xml/sax/Writer.hpp>
27 : #include <com/sun/star/lang/IllegalArgumentException.hpp>
28 :
29 : #include <comphelper/ofopxmlhelper.hxx>
30 : #include <comphelper/attributelist.hxx>
31 :
32 : #define RELATIONINFO_FORMAT 0
33 : #define CONTENTTYPE_FORMAT 1
34 : #define FORMAT_MAX_ID CONTENTTYPE_FORMAT
35 :
36 : using namespace ::com::sun::star;
37 :
38 : namespace comphelper {
39 :
40 8516 : uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadRelationsInfoSequence( const uno::Reference< io::XInputStream >& xInStream, const OUString & aStreamName, const uno::Reference< uno::XComponentContext >& rContext )
41 : throw( uno::Exception )
42 : {
43 8516 : OUString aStringID = "_rels/";
44 8516 : aStringID += aStreamName;
45 8516 : return ReadSequence_Impl( xInStream, aStringID, RELATIONINFO_FORMAT, rContext );
46 : }
47 :
48 :
49 4798 : uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadContentTypeSequence( const uno::Reference< io::XInputStream >& xInStream, const uno::Reference< uno::XComponentContext >& rContext )
50 : throw( uno::Exception )
51 : {
52 4798 : OUString aStringID = "[Content_Types].xml";
53 4798 : return ReadSequence_Impl( xInStream, aStringID, CONTENTTYPE_FORMAT, rContext );
54 : }
55 :
56 :
57 2286 : void SAL_CALL OFOPXMLHelper::WriteRelationsInfoSequence( const uno::Reference< io::XOutputStream >& xOutStream, const uno::Sequence< uno::Sequence< beans::StringPair > >& aSequence, const uno::Reference< uno::XComponentContext >& rContext )
58 : throw( uno::Exception )
59 : {
60 2286 : if ( !xOutStream.is() )
61 0 : throw uno::RuntimeException();
62 :
63 2286 : uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(rContext);
64 :
65 2286 : xWriter->setOutputStream( xOutStream );
66 :
67 4572 : OUString aRelListElement( "Relationships" );
68 4572 : OUString aRelElement( "Relationship" );
69 4572 : OUString aIDAttr( "Id" );
70 4572 : OUString aTypeAttr( "Type" );
71 4572 : OUString aTargetModeAttr( "TargetMode" );
72 4572 : OUString aTargetAttr( "Target" );
73 4572 : OUString aCDATAString( "CDATA" );
74 4572 : OUString aWhiteSpace( " " );
75 :
76 : // write the namespace
77 2286 : AttributeList* pRootAttrList = new AttributeList;
78 4572 : uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList );
79 : pRootAttrList->AddAttribute(
80 : OUString( "xmlns" ),
81 : aCDATAString,
82 2286 : OUString( "http://schemas.openxmlformats.org/package/2006/relationships" ) );
83 :
84 2286 : xWriter->startDocument();
85 2286 : xWriter->startElement( aRelListElement, xRootAttrList );
86 :
87 9561 : for ( sal_Int32 nInd = 0; nInd < aSequence.getLength(); nInd++ )
88 : {
89 7275 : AttributeList *pAttrList = new AttributeList;
90 7275 : uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList );
91 29228 : for( sal_Int32 nSecInd = 0; nSecInd < aSequence[nInd].getLength(); nSecInd++ )
92 : {
93 43906 : if ( aSequence[nInd][nSecInd].First.equals( aIDAttr )
94 14678 : || aSequence[nInd][nSecInd].First.equals( aTypeAttr )
95 7403 : || aSequence[nInd][nSecInd].First.equals( aTargetModeAttr )
96 29228 : || aSequence[nInd][nSecInd].First.equals( aTargetAttr ) )
97 : {
98 21953 : pAttrList->AddAttribute( aSequence[nInd][nSecInd].First, aCDATAString, aSequence[nInd][nSecInd].Second );
99 : }
100 : else
101 : {
102 : // TODO/LATER: should the extensions be allowed?
103 0 : throw lang::IllegalArgumentException();
104 : }
105 : }
106 :
107 7275 : xWriter->startElement( aRelElement, xAttrList );
108 7275 : xWriter->ignorableWhitespace( aWhiteSpace );
109 7275 : xWriter->endElement( aRelElement );
110 7275 : }
111 :
112 2286 : xWriter->ignorableWhitespace( aWhiteSpace );
113 2286 : xWriter->endElement( aRelListElement );
114 4572 : xWriter->endDocument();
115 2286 : }
116 :
117 :
118 563 : void SAL_CALL OFOPXMLHelper::WriteContentSequence( const uno::Reference< io::XOutputStream >& xOutStream, const uno::Sequence< beans::StringPair >& aDefaultsSequence, const uno::Sequence< beans::StringPair >& aOverridesSequence, const uno::Reference< uno::XComponentContext >& rContext )
119 : throw( uno::Exception )
120 : {
121 563 : if ( !xOutStream.is() )
122 0 : throw uno::RuntimeException();
123 :
124 563 : uno::Reference< xml::sax::XWriter > xWriter = xml::sax::Writer::create(rContext);
125 :
126 563 : xWriter->setOutputStream( xOutStream );
127 :
128 1126 : OUString aTypesElement( "Types" );
129 1126 : OUString aDefaultElement( "Default" );
130 1126 : OUString aOverrideElement( "Override" );
131 1126 : OUString aExtensionAttr( "Extension" );
132 1126 : OUString aPartNameAttr( "PartName" );
133 1126 : OUString aContentTypeAttr( "ContentType" );
134 1126 : OUString aCDATAString( "CDATA" );
135 1126 : OUString aWhiteSpace( " " );
136 :
137 : // write the namespace
138 563 : AttributeList* pRootAttrList = new AttributeList;
139 1126 : uno::Reference< xml::sax::XAttributeList > xRootAttrList( pRootAttrList );
140 : pRootAttrList->AddAttribute(
141 : OUString( "xmlns" ),
142 : aCDATAString,
143 563 : OUString( "http://schemas.openxmlformats.org/package/2006/content-types" ) );
144 :
145 563 : xWriter->startDocument();
146 563 : xWriter->startElement( aTypesElement, xRootAttrList );
147 :
148 563 : for ( sal_Int32 nInd = 0; nInd < aDefaultsSequence.getLength(); nInd++ )
149 : {
150 0 : AttributeList *pAttrList = new AttributeList;
151 0 : uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList );
152 0 : pAttrList->AddAttribute( aExtensionAttr, aCDATAString, aDefaultsSequence[nInd].First );
153 0 : pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aDefaultsSequence[nInd].Second );
154 :
155 0 : xWriter->startElement( aDefaultElement, xAttrList );
156 0 : xWriter->ignorableWhitespace( aWhiteSpace );
157 0 : xWriter->endElement( aDefaultElement );
158 0 : }
159 :
160 9623 : for ( sal_Int32 nInd = 0; nInd < aOverridesSequence.getLength(); nInd++ )
161 : {
162 9060 : AttributeList *pAttrList = new AttributeList;
163 9060 : uno::Reference< xml::sax::XAttributeList > xAttrList( pAttrList );
164 9060 : pAttrList->AddAttribute( aPartNameAttr, aCDATAString, aOverridesSequence[nInd].First );
165 9060 : pAttrList->AddAttribute( aContentTypeAttr, aCDATAString, aOverridesSequence[nInd].Second );
166 :
167 9060 : xWriter->startElement( aOverrideElement, xAttrList );
168 9060 : xWriter->ignorableWhitespace( aWhiteSpace );
169 9060 : xWriter->endElement( aOverrideElement );
170 9060 : }
171 :
172 563 : xWriter->ignorableWhitespace( aWhiteSpace );
173 563 : xWriter->endElement( aTypesElement );
174 1126 : xWriter->endDocument();
175 :
176 563 : }
177 :
178 13314 : uno::Sequence< uno::Sequence< beans::StringPair > > SAL_CALL OFOPXMLHelper::ReadSequence_Impl( const uno::Reference< io::XInputStream >& xInStream, const OUString& aStringID, sal_uInt16 nFormat, const uno::Reference< uno::XComponentContext >& rContext )
179 : throw( uno::Exception )
180 : {
181 13314 : if ( !rContext.is() || !xInStream.is() || nFormat > FORMAT_MAX_ID )
182 0 : throw uno::RuntimeException();
183 :
184 13314 : uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( rContext );
185 :
186 13314 : OFOPXMLHelper* pHelper = new OFOPXMLHelper( nFormat );
187 26628 : uno::Reference< xml::sax::XDocumentHandler > xHelper( static_cast< xml::sax::XDocumentHandler* >( pHelper ) );
188 26628 : xml::sax::InputSource aParserInput;
189 13314 : aParserInput.aInputStream = xInStream;
190 13314 : aParserInput.sSystemId = aStringID;
191 13314 : xParser->setDocumentHandler( xHelper );
192 13314 : xParser->parseStream( aParserInput );
193 13314 : xParser->setDocumentHandler( uno::Reference < xml::sax::XDocumentHandler > () );
194 :
195 26628 : return pHelper->GetParsingResult();
196 : }
197 :
198 13314 : OFOPXMLHelper::OFOPXMLHelper( sal_uInt16 nFormat )
199 : : m_nFormat( nFormat )
200 : , m_aRelListElement( "Relationships" )
201 : , m_aRelElement( "Relationship" )
202 : , m_aIDAttr( "Id" )
203 : , m_aTypeAttr( "Type" )
204 : , m_aTargetModeAttr( "TargetMode" )
205 : , m_aTargetAttr( "Target" )
206 : , m_aTypesElement( "Types" )
207 : , m_aDefaultElement( "Default" )
208 : , m_aOverrideElement( "Override" )
209 : , m_aExtensionAttr( "Extension" )
210 : , m_aPartNameAttr( "PartName" )
211 13314 : , m_aContentTypeAttr( "ContentType" )
212 : {
213 13314 : }
214 :
215 :
216 26628 : OFOPXMLHelper::~OFOPXMLHelper()
217 : {
218 26628 : }
219 :
220 :
221 13314 : uno::Sequence< uno::Sequence< beans::StringPair > > OFOPXMLHelper::GetParsingResult()
222 : {
223 13314 : if ( m_aElementsSeq.getLength() )
224 0 : throw uno::RuntimeException(); // the parsing has still not finished!
225 :
226 13314 : return m_aResultSeq;
227 : }
228 :
229 :
230 13314 : void SAL_CALL OFOPXMLHelper::startDocument()
231 : throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
232 : {
233 13314 : }
234 :
235 :
236 13314 : void SAL_CALL OFOPXMLHelper::endDocument()
237 : throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
238 : {
239 13314 : }
240 :
241 :
242 117489 : void SAL_CALL OFOPXMLHelper::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs )
243 : throw( xml::sax::SAXException, uno::RuntimeException, std::exception )
244 : {
245 117489 : if ( m_nFormat == RELATIONINFO_FORMAT )
246 : {
247 41112 : if ( aName == m_aRelListElement )
248 : {
249 8516 : sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
250 :
251 8516 : if ( nNewLength != 1 )
252 0 : throw xml::sax::SAXException(); // TODO: this element must be the first level element
253 :
254 8516 : m_aElementsSeq.realloc( nNewLength );
255 8516 : m_aElementsSeq[nNewLength-1] = aName;
256 :
257 8516 : return; // nothing to do
258 : }
259 32596 : else if ( aName == m_aRelElement )
260 : {
261 32596 : sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
262 32596 : if ( nNewLength != 2 )
263 0 : throw xml::sax::SAXException(); // TODO: this element must be the second level element
264 :
265 32596 : m_aElementsSeq.realloc( nNewLength );
266 32596 : m_aElementsSeq[nNewLength-1] = aName;
267 :
268 32596 : sal_Int32 nNewEntryNum = m_aResultSeq.getLength() + 1;
269 32596 : m_aResultSeq.realloc( nNewEntryNum );
270 32596 : sal_Int32 nAttrNum = 0;
271 32596 : m_aResultSeq[nNewEntryNum-1].realloc( 4 ); // the maximal expected number of arguments is 4
272 :
273 32596 : OUString aIDValue = xAttribs->getValueByName( m_aIDAttr );
274 32596 : if ( aIDValue.isEmpty() )
275 0 : throw xml::sax::SAXException(); // TODO: the ID value must present
276 :
277 65192 : OUString aTypeValue = xAttribs->getValueByName( m_aTypeAttr );
278 65192 : OUString aTargetValue = xAttribs->getValueByName( m_aTargetAttr );
279 65192 : OUString aTargetModeValue = xAttribs->getValueByName( m_aTargetModeAttr );
280 :
281 32596 : m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aIDAttr;
282 32596 : m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aIDValue;
283 :
284 32596 : if ( !aTypeValue.isEmpty() )
285 : {
286 32596 : m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTypeAttr;
287 32596 : m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTypeValue;
288 : }
289 :
290 32596 : if ( !aTargetValue.isEmpty() )
291 : {
292 32595 : m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetAttr;
293 32595 : m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetValue;
294 : }
295 :
296 32596 : if ( !aTargetModeValue.isEmpty() )
297 : {
298 871 : m_aResultSeq[nNewEntryNum-1][++nAttrNum - 1].First = m_aTargetModeAttr;
299 871 : m_aResultSeq[nNewEntryNum-1][nAttrNum - 1].Second = aTargetModeValue;
300 : }
301 :
302 65192 : m_aResultSeq[nNewEntryNum-1].realloc( nAttrNum );
303 : }
304 : else
305 0 : throw xml::sax::SAXException(); // TODO: no other elements expected!
306 : }
307 76377 : else if ( m_nFormat == CONTENTTYPE_FORMAT )
308 : {
309 76377 : if ( aName == m_aTypesElement )
310 : {
311 4798 : sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
312 :
313 4798 : if ( nNewLength != 1 )
314 0 : throw xml::sax::SAXException(); // TODO: this element must be the first level element
315 :
316 4798 : m_aElementsSeq.realloc( nNewLength );
317 4798 : m_aElementsSeq[nNewLength-1] = aName;
318 :
319 4798 : if ( !m_aResultSeq.getLength() )
320 4798 : m_aResultSeq.realloc( 2 );
321 :
322 4798 : return; // nothing to do
323 : }
324 71579 : else if ( aName == m_aDefaultElement )
325 : {
326 7083 : sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
327 7083 : if ( nNewLength != 2 )
328 0 : throw xml::sax::SAXException(); // TODO: this element must be the second level element
329 :
330 7083 : m_aElementsSeq.realloc( nNewLength );
331 7083 : m_aElementsSeq[nNewLength-1] = aName;
332 :
333 7083 : if ( !m_aResultSeq.getLength() )
334 0 : m_aResultSeq.realloc( 2 );
335 :
336 7083 : if ( m_aResultSeq.getLength() != 2 )
337 0 : throw uno::RuntimeException();
338 :
339 7083 : OUString aExtensionValue = xAttribs->getValueByName( m_aExtensionAttr );
340 7083 : if ( aExtensionValue.isEmpty() )
341 0 : throw xml::sax::SAXException(); // TODO: the Extension value must present
342 :
343 14166 : OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr );
344 7083 : if ( aContentTypeValue.isEmpty() )
345 0 : throw xml::sax::SAXException(); // TODO: the ContentType value must present
346 :
347 7083 : sal_Int32 nNewResultLen = m_aResultSeq[0].getLength() + 1;
348 7083 : m_aResultSeq[0].realloc( nNewResultLen );
349 :
350 7083 : m_aResultSeq[0][nNewResultLen-1].First = aExtensionValue;
351 14166 : m_aResultSeq[0][nNewResultLen-1].Second = aContentTypeValue;
352 : }
353 64496 : else if ( aName == m_aOverrideElement )
354 : {
355 64496 : sal_Int32 nNewLength = m_aElementsSeq.getLength() + 1;
356 64496 : if ( nNewLength != 2 )
357 0 : throw xml::sax::SAXException(); // TODO: this element must be the second level element
358 :
359 64496 : m_aElementsSeq.realloc( nNewLength );
360 64496 : m_aElementsSeq[nNewLength-1] = aName;
361 :
362 64496 : if ( !m_aResultSeq.getLength() )
363 0 : m_aResultSeq.realloc( 2 );
364 :
365 64496 : if ( m_aResultSeq.getLength() != 2 )
366 0 : throw uno::RuntimeException();
367 :
368 64496 : OUString aPartNameValue = xAttribs->getValueByName( m_aPartNameAttr );
369 64496 : if ( aPartNameValue.isEmpty() )
370 0 : throw xml::sax::SAXException(); // TODO: the PartName value must present
371 :
372 128992 : OUString aContentTypeValue = xAttribs->getValueByName( m_aContentTypeAttr );
373 64496 : if ( aContentTypeValue.isEmpty() )
374 0 : throw xml::sax::SAXException(); // TODO: the ContentType value must present
375 :
376 64496 : sal_Int32 nNewResultLen = m_aResultSeq[1].getLength() + 1;
377 64496 : m_aResultSeq[1].realloc( nNewResultLen );
378 :
379 64496 : m_aResultSeq[1][nNewResultLen-1].First = aPartNameValue;
380 128992 : m_aResultSeq[1][nNewResultLen-1].Second = aContentTypeValue;
381 : }
382 : else
383 0 : throw xml::sax::SAXException(); // TODO: no other elements expected!
384 : }
385 : else
386 0 : throw xml::sax::SAXException(); // TODO: no other elements expected!
387 : }
388 :
389 :
390 117489 : void SAL_CALL OFOPXMLHelper::endElement( const OUString& aName )
391 : throw( xml::sax::SAXException, uno::RuntimeException, std::exception )
392 : {
393 117489 : if ( m_nFormat == RELATIONINFO_FORMAT || m_nFormat == CONTENTTYPE_FORMAT )
394 : {
395 117489 : sal_Int32 nLength = m_aElementsSeq.getLength();
396 117489 : if ( nLength <= 0 )
397 0 : throw xml::sax::SAXException(); // TODO: no other end elements expected!
398 :
399 117489 : if ( !m_aElementsSeq[nLength-1].equals( aName ) )
400 0 : throw xml::sax::SAXException(); // TODO: unexpected element ended
401 :
402 117489 : m_aElementsSeq.realloc( nLength - 1 );
403 : }
404 117489 : }
405 :
406 :
407 5686 : void SAL_CALL OFOPXMLHelper::characters( const OUString& /*aChars*/ )
408 : throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
409 : {
410 5686 : }
411 :
412 :
413 0 : void SAL_CALL OFOPXMLHelper::ignorableWhitespace( const OUString& /*aWhitespaces*/ )
414 : throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
415 : {
416 0 : }
417 :
418 :
419 0 : void SAL_CALL OFOPXMLHelper::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ )
420 : throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
421 : {
422 0 : }
423 :
424 :
425 13314 : void SAL_CALL OFOPXMLHelper::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ )
426 : throw(xml::sax::SAXException, uno::RuntimeException, std::exception)
427 : {
428 13314 : }
429 :
430 : } // namespace comphelper
431 :
432 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|