Branch data 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 : : #include "oox/core/xmlfilterbase.hxx"
21 : :
22 : : #include <cstdio>
23 : : #include <com/sun/star/container/XNameContainer.hpp>
24 : : #include <com/sun/star/embed/XRelationshipAccess.hpp>
25 : : #include <com/sun/star/xml/sax/InputSource.hpp>
26 : : #include <com/sun/star/xml/sax/XFastParser.hpp>
27 : : #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
28 : : #include <com/sun/star/document/XDocumentProperties.hpp>
29 : : #include <comphelper/mediadescriptor.hxx>
30 : : #include <sax/fshelper.hxx>
31 : : #include <rtl/strbuf.hxx>
32 : : #include <rtl/ustrbuf.hxx>
33 : : #include <rtl/instance.hxx>
34 : : #include "oox/core/fastparser.hxx"
35 : : #include "oox/core/filterdetect.hxx"
36 : : #include "oox/core/fragmenthandler.hxx"
37 : : #include "oox/core/recordparser.hxx"
38 : : #include "oox/core/relationshandler.hxx"
39 : : #include "oox/helper/containerhelper.hxx"
40 : : #include "oox/helper/propertyset.hxx"
41 : : #include "oox/helper/zipstorage.hxx"
42 : : #include "oox/token/properties.hxx"
43 : : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
44 : : #include <com/sun/star/document/XOOXMLDocumentPropertiesImporter.hpp>
45 : : #include <com/sun/star/xml/dom/XDocument.hpp>
46 : : #include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
47 : : #include <com/sun/star/beans/XPropertySet.hpp>
48 : : #include <comphelper/processfactory.hxx>
49 : : #include <comphelper/mediadescriptor.hxx>
50 : : #include <oox/core/filterdetect.hxx>
51 : : #include <comphelper/storagehelper.hxx>
52 : : using ::com::sun::star::uno::XComponentContext;
53 : : using ::com::sun::star::document::XOOXMLDocumentPropertiesImporter;
54 : : using ::com::sun::star::document::XDocumentPropertiesSupplier;
55 : : using ::com::sun::star::xml::dom::XDocument;
56 : : using ::com::sun::star::xml::dom::XDocumentBuilder;
57 : : using ::com::sun::star::xml::sax::XFastSAXSerializable;
58 : : using ::com::sun::star::beans::XPropertySet;
59 : : using ::com::sun::star::lang::XComponent;
60 : :
61 : : namespace oox {
62 : : namespace core {
63 : :
64 : : // ============================================================================
65 : :
66 : : using namespace ::com::sun::star::beans;
67 : : using namespace ::com::sun::star::container;
68 : : using namespace ::com::sun::star::document;
69 : : using namespace ::com::sun::star::embed;
70 : : using namespace ::com::sun::star::io;
71 : : using namespace ::com::sun::star::lang;
72 : : using namespace ::com::sun::star::uno;
73 : : using namespace ::com::sun::star::util;
74 : : using namespace ::com::sun::star::xml::sax;
75 : :
76 : : using ::comphelper::MediaDescriptor;
77 : : using ::rtl::OStringBuffer;
78 : : using ::rtl::OUString;
79 : : using ::rtl::OUStringBuffer;
80 : : using ::sax_fastparser::FSHelperPtr;
81 : : using ::sax_fastparser::FastSerializerHelper;
82 : :
83 : :
84 : :
85 : :
86 : :
87 : : // ============================================================================
88 : :
89 : : namespace {
90 : :
91 : 465 : bool lclHasSuffix( const OUString& rFragmentPath, const OUString& rSuffix )
92 : : {
93 : 465 : sal_Int32 nSuffixPos = rFragmentPath.getLength() - rSuffix.getLength();
94 [ - + ][ + - ]: 465 : return (nSuffixPos >= 0) && rFragmentPath.match( rSuffix, nSuffixPos );
95 : : }
96 : :
97 : : } // namespace
98 : :
99 : : // ============================================================================
100 : :
101 : 123 : struct XmlFilterBaseImpl
102 : : {
103 : : typedef RefMap< OUString, Relations > RelationsMap;
104 : :
105 : : FastParser maFastParser;
106 : : const OUString maBinSuffix;
107 : : const OUString maVmlSuffix;
108 : : RelationsMap maRelationsMap;
109 : : TextFieldStack maTextFieldStack;
110 : :
111 : : explicit XmlFilterBaseImpl( const Reference< XComponentContext >& rxContext ) throw( RuntimeException );
112 : : };
113 : :
114 : : // ----------------------------------------------------------------------------
115 : :
116 : : namespace
117 : : {
118 : : struct NamespaceIds: public rtl::StaticWithInit<
119 : : Sequence< Pair< OUString, sal_Int32 > >,
120 : : NamespaceIds>
121 : : {
122 : 18 : Sequence< Pair< OUString, sal_Int32 > > operator()()
123 : : {
124 : : static const char* const namespaceURIs[] = {
125 : : "http://www.w3.org/XML/1998/namespace",
126 : : "http://schemas.openxmlformats.org/package/2006/relationships",
127 : : "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
128 : : "http://schemas.openxmlformats.org/drawingml/2006/main",
129 : : "http://schemas.openxmlformats.org/drawingml/2006/diagram",
130 : : "http://schemas.openxmlformats.org/drawingml/2006/chart",
131 : : "http://schemas.openxmlformats.org/drawingml/2006/chartDrawing",
132 : : "urn:schemas-microsoft-com:vml",
133 : : "urn:schemas-microsoft-com:office:office",
134 : : "urn:schemas-microsoft-com:office:word",
135 : : "urn:schemas-microsoft-com:office:excel",
136 : : "urn:schemas-microsoft-com:office:powerpoint",
137 : : "http://schemas.microsoft.com/office/2006/activeX",
138 : : "http://schemas.openxmlformats.org/spreadsheetml/2006/main",
139 : : "http://schemas.openxmlformats.org/drawingml/2006/spreadsheetDrawing",
140 : : "http://schemas.microsoft.com/office/excel/2006/main",
141 : : "http://schemas.openxmlformats.org/presentationml/2006/main",
142 : : "http://schemas.openxmlformats.org/markup-compatibility/2006",
143 : : "http://schemas.openxmlformats.org/spreadsheetml/2006/main/v2",
144 : : "http://schemas.microsoft.com/office/drawing/2008/diagram",
145 : : "http://schemas.microsoft.com/office/spreadsheetml/2009/9/main"
146 : : };
147 : :
148 : : static const sal_Int32 namespaceIds[] = {
149 : : NMSP_xml,
150 : : NMSP_packageRel,
151 : : NMSP_officeRel,
152 : : NMSP_dml,
153 : : NMSP_dmlDiagram,
154 : : NMSP_dmlChart,
155 : : NMSP_dmlChartDr,
156 : : NMSP_dmlSpreadDr,
157 : : NMSP_vml,
158 : : NMSP_vmlOffice,
159 : : NMSP_vmlWord,
160 : : NMSP_vmlExcel,
161 : : NMSP_vmlPowerpoint,
162 : : NMSP_xls,
163 : : NMSP_ppt,
164 : : NMSP_ax,
165 : : NMSP_xm,
166 : : NMSP_mce,
167 : : NMSP_mceTest,
168 : : NMSP_dsp,
169 : : NMSP_xlsExtLst
170 : : };
171 : :
172 : 18 : Sequence< Pair< OUString, sal_Int32 > > aRet(STATIC_ARRAY_SIZE(namespaceIds));
173 [ + + ]: 396 : for( sal_Int32 i=0; i<aRet.getLength(); ++i )
174 [ + - ]: 378 : aRet[i] = make_Pair(
175 : 378 : ::rtl::OUString::createFromAscii(namespaceURIs[i]),
176 [ + - ]: 756 : namespaceIds[i]);
177 : 18 : return aRet;
178 : : }
179 : : };
180 : : }
181 : :
182 : : // ----------------------------------------------------------------------------
183 : :
184 : 123 : XmlFilterBaseImpl::XmlFilterBaseImpl( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
185 : : maFastParser( rxContext ),
186 : : maBinSuffix( CREATE_OUSTRING( ".bin" ) ),
187 [ + - ][ + - ]: 123 : maVmlSuffix( CREATE_OUSTRING( ".vml" ) )
[ + - ][ + - ]
188 : : {
189 : : // register XML namespaces
190 : : const Sequence< Pair< OUString, sal_Int32 > > ids=
191 [ + - ][ + - ]: 123 : NamespaceIds::get();
192 [ + + ]: 2706 : for( sal_Int32 i=0; i<ids.getLength(); ++i )
193 [ + - ][ + - ]: 2706 : maFastParser.registerNamespace( ids[i].Second );
194 : 123 : }
195 : :
196 : :
197 : 39 : static Reference< XComponentContext > lcl_getComponentContext(Reference< XMultiServiceFactory > aFactory)
198 : : {
199 : 39 : Reference< XComponentContext > xContext;
200 : : try
201 : : {
202 [ + - ]: 39 : Reference< XPropertySet > xFactProp( aFactory, UNO_QUERY );
203 [ + - ]: 39 : if( xFactProp.is() )
204 [ + - ][ + - ]: 39 : xFactProp->getPropertyValue( "DefaultContext") >>= xContext;
[ + - ][ # # ]
205 : : }
206 [ # # ]: 0 : catch( Exception& )
207 : : {}
208 : :
209 : 39 : return xContext;
210 : : }
211 : :
212 : : // ============================================================================
213 : :
214 : : // ============================================================================
215 : :
216 : 123 : XmlFilterBase::XmlFilterBase( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
217 : : FilterBase( rxContext ),
218 [ + - ]: 123 : mxImpl( new XmlFilterBaseImpl( rxContext ) ),
219 : : mnRelId( 1 ),
220 [ + - ]: 246 : mnMaxDocId( 0 )
221 : : {
222 : 123 : }
223 : :
224 [ + - ]: 123 : XmlFilterBase::~XmlFilterBase()
225 : : {
226 [ - + ]: 123 : }
227 : :
228 : : // ----------------------------------------------------------------------------
229 : :
230 : 24 : void XmlFilterBase::importDocumentProperties() throw()
231 : : {
232 [ + - ][ + - ]: 24 : Reference< XMultiServiceFactory > xFactory( getServiceFactory(), UNO_QUERY );
233 [ + - ][ + - ]: 24 : MediaDescriptor aMediaDesc( getMediaDescriptor() );
234 : 24 : Reference< XInputStream > xInputStream;
235 [ + - ][ + - ]: 24 : Reference< XComponentContext > xContext = lcl_getComponentContext(getServiceFactory());
236 [ + - ]: 24 : ::oox::core::FilterDetect aDetector( xContext );
237 [ + - ][ + - ]: 24 : xInputStream = aDetector.extractUnencryptedPackage( aMediaDesc );
238 [ + - ][ + - ]: 24 : Reference< XComponent > xModel( getModel(), UNO_QUERY );
239 : : Reference< XStorage > xDocumentStorage (
240 [ + - ][ + - ]: 24 : ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( OFOPXML_STORAGE_FORMAT_STRING, xInputStream ) );
241 [ + - ][ + - ]: 48 : Reference< XInterface > xTemp = xContext->getServiceManager()->createInstanceWithContext(
[ + - ]
242 : : ::rtl::OUString("com.sun.star.document.OOXMLDocumentPropertiesImporter"),
243 [ + - ]: 24 : xContext);
244 [ + - ]: 24 : Reference< XOOXMLDocumentPropertiesImporter > xImporter( xTemp, UNO_QUERY );
245 [ + - ]: 24 : Reference< XDocumentPropertiesSupplier > xPropSupplier( xModel, UNO_QUERY);
246 [ + - ][ + - ]: 24 : xImporter->importProperties( xDocumentStorage, xPropSupplier->getDocumentProperties() );
[ + - ][ + - ]
[ + - ][ + - ]
247 : 24 : }
248 : :
249 : 33 : OUString XmlFilterBase::getFragmentPathFromFirstType( const OUString& rType )
250 : : {
251 : : // importRelations() caches the relations map for subsequence calls
252 [ + - ][ + - ]: 33 : return importRelations( OUString() )->getFragmentPathFromFirstType( rType );
[ + - ]
253 : : }
254 : :
255 : 465 : bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& rxHandler )
256 : : {
257 : : OSL_ENSURE( rxHandler.is(), "XmlFilterBase::importFragment - missing fragment handler" );
258 [ - + ]: 465 : if( !rxHandler.is() )
259 : 0 : return false;
260 : :
261 : : // fragment handler must contain path to fragment stream
262 [ + - ]: 465 : OUString aFragmentPath = rxHandler->getFragmentPath();
263 : : OSL_ENSURE( !aFragmentPath.isEmpty(), "XmlFilterBase::importFragment - missing fragment path" );
264 [ - + ]: 465 : if( aFragmentPath.isEmpty() )
265 : 0 : return false;
266 : :
267 : : // try to import binary streams (fragment extension must be '.bin')
268 [ - + ]: 465 : if( lclHasSuffix( aFragmentPath, mxImpl->maBinSuffix ) )
269 : : {
270 : : try
271 : : {
272 : : // try to open the fragment stream (this may fail - do not assert)
273 [ # # ][ # # ]: 0 : Reference< XInputStream > xInStrm( openInputStream( aFragmentPath ), UNO_SET_THROW );
274 : :
275 : : // create the record parser
276 [ # # ]: 0 : RecordParser aParser;
277 [ # # ]: 0 : aParser.setFragmentHandler( rxHandler );
278 : :
279 : : // create the input source and parse the stream
280 [ # # ]: 0 : RecordInputSource aSource;
281 [ # # ][ # # ]: 0 : aSource.mxInStream.reset( new BinaryXInputStream( xInStrm, true ) );
[ # # ]
282 : 0 : aSource.maSystemId = aFragmentPath;
283 [ # # ]: 0 : aParser.parseStream( aSource );
284 [ # # ][ # # ]: 0 : return true;
[ # # ]
285 : : }
286 [ # # # # ]: 0 : catch( Exception& )
287 : : {
288 : : }
289 : 0 : return false;
290 : : }
291 : :
292 : : // get the XFastDocumentHandler interface from the fragment handler
293 [ + - ][ + - ]: 465 : Reference< XFastDocumentHandler > xDocHandler( rxHandler.get() );
294 [ - + ]: 465 : if( !xDocHandler.is() )
295 : 0 : return false;
296 : :
297 : : // try to import XML stream
298 : : try
299 : : {
300 : : /* Try to open the fragment stream (may fail, do not throw/assert).
301 : : Using the virtual function openFragmentStream() allows a document
302 : : handler to create specialized input streams, e.g. VML streams that
303 : : have to preprocess the raw input data. */
304 [ + - ]: 465 : Reference< XInputStream > xInStrm = rxHandler->openFragmentStream();
305 : :
306 : : // own try/catch block for showing parser failure assertion with fragment path
307 [ + + ]: 465 : if( xInStrm.is() ) try
308 : : {
309 [ + - ]: 333 : mxImpl->maFastParser.setDocumentHandler( xDocHandler );
310 [ + - ]: 333 : mxImpl->maFastParser.parseStream( xInStrm, aFragmentPath );
311 : 465 : return true;
312 : : }
313 [ # # ]: 0 : catch( Exception& )
314 : : {
315 : : OSL_FAIL( OStringBuffer( "XmlFilterBase::importFragment - XML parser failed in fragment '" ).
316 : : append( OUStringToOString( aFragmentPath, RTL_TEXTENCODING_ASCII_US ) ).append( '\'' ).getStr() );
317 [ + + ][ # # ]: 465 : }
318 : : }
319 [ # # ]: 0 : catch( Exception& )
320 : : {
321 : : }
322 : 465 : return false;
323 : : }
324 : :
325 : 12 : OUString XmlFilterBase::getNamespaceURL( const OUString& rPrefix )
326 : : {
327 : 12 : return mxImpl->maFastParser.getNamespaceURL( rPrefix );
328 : : }
329 : :
330 : 12 : sal_Int32 XmlFilterBase::getNamespaceId( const OUString& rUrl )
331 : : {
332 : 12 : return mxImpl->maFastParser.getNamespaceId( rUrl );
333 : : }
334 : :
335 : 15 : Reference<XDocument> XmlFilterBase::importFragment( const ::rtl::OUString& aFragmentPath )
336 : : {
337 : 15 : Reference<XDocument> xRet;
338 : :
339 : : // path to fragment stream valid?
340 : : OSL_ENSURE( !aFragmentPath.isEmpty(), "XmlFilterBase::importFragment - empty fragment path" );
341 [ + - ]: 15 : if( aFragmentPath.isEmpty() )
342 : : return xRet;
343 : :
344 : : // try to open the fragment stream (this may fail - do not assert)
345 [ + - ]: 15 : Reference< XInputStream > xInStrm = openInputStream( aFragmentPath );
346 [ + - ]: 15 : if( !xInStrm.is() )
347 : : return xRet;
348 : :
349 : : // binary streams (fragment extension is '.bin') currently not supported
350 : 15 : sal_Int32 nBinSuffixPos = aFragmentPath.getLength() - mxImpl->maBinSuffix.getLength();
351 [ - + ][ + - ]: 15 : if( (nBinSuffixPos >= 0) && aFragmentPath.match( mxImpl->maBinSuffix, nBinSuffixPos ) )
[ + - ]
352 : : return xRet;
353 : :
354 : : // try to import XML stream
355 : : try
356 : : {
357 : : // create the dom parser
358 : : Reference< XComponentContext > xContext =
359 [ + - ][ + - ]: 15 : lcl_getComponentContext(getServiceFactory());
360 : : Reference<XDocumentBuilder> xDomBuilder(
361 [ + - ][ + - ]: 30 : xContext->getServiceManager()->createInstanceWithContext(
[ + - ]
362 : : ::rtl::OUString("com.sun.star.xml.dom.DocumentBuilder" ),
363 : 15 : xContext),
364 [ + - ][ + - ]: 15 : UNO_QUERY_THROW );
365 : :
366 : : // create DOM from fragment
367 [ + - ][ + - ]: 15 : xRet = xDomBuilder->parse(xInStrm);
[ # # ][ + - ]
368 : : }
369 [ # # ]: 0 : catch( Exception& )
370 : : {
371 : : }
372 : :
373 : 15 : return xRet;
374 : : }
375 : :
376 : 15 : bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& rxHandler,
377 : : const Reference< XFastSAXSerializable >& rxSerializer )
378 : : {
379 [ + - ][ + - ]: 15 : Reference< XFastDocumentHandler > xDocHandler( rxHandler.get() );
380 [ - + ]: 15 : if( !xDocHandler.is() )
381 : 0 : return false;
382 : :
383 : : // try to import XML stream
384 : : try
385 : : {
386 [ + - ]: 15 : rxSerializer->fastSerialize( xDocHandler,
387 : 15 : mxImpl->maFastParser.getTokenHandler(),
388 : : Sequence< StringPair >(),
389 [ + - ]: 30 : NamespaceIds::get() );
[ + - + - ]
[ + - ]
[ + - # # ]
390 : 15 : return true;
391 : : }
392 [ # # ]: 0 : catch( Exception& )
393 : : {}
394 : :
395 : 15 : return false;
396 : : }
397 : :
398 : 300 : RelationsRef XmlFilterBase::importRelations( const OUString& rFragmentPath )
399 : : {
400 : : // try to find cached relations
401 : 300 : RelationsRef& rxRelations = mxImpl->maRelationsMap[ rFragmentPath ];
402 [ + + ]: 300 : if( !rxRelations )
403 : : {
404 : : // import and cache relations
405 [ + - ]: 273 : rxRelations.reset( new Relations( rFragmentPath ) );
406 [ + - ][ + - ]: 273 : importFragment( new RelationsFragment( *this, rxRelations ) );
407 : : }
408 : 300 : return rxRelations;
409 : : }
410 : :
411 : 345 : Reference< XOutputStream > XmlFilterBase::openFragmentStream( const OUString& rStreamName, const OUString& rMediaType )
412 : : {
413 [ + - ]: 345 : Reference< XOutputStream > xOutputStream = openOutputStream( rStreamName );
414 [ + - ]: 345 : PropertySet aPropSet( xOutputStream );
415 [ + - ]: 345 : aPropSet.setProperty( PROP_MediaType, rMediaType );
416 [ + - ]: 345 : return xOutputStream;
417 : : }
418 : :
419 : 345 : FSHelperPtr XmlFilterBase::openFragmentStreamWithSerializer( const OUString& rStreamName, const OUString& rMediaType )
420 : : {
421 : 345 : bool bWriteHeader = true;
422 [ - + # # ]: 345 : if( rMediaType.indexOfAsciiL( "vml", 3 ) >= 0 &&
[ - + ]
423 : 0 : rMediaType.indexOfAsciiL( "+xml", 4 ) < 0 )
424 : 0 : bWriteHeader = false;
425 [ + - ][ + - ]: 345 : return FSHelperPtr( new FastSerializerHelper( openFragmentStream( rStreamName, rMediaType ), bWriteHeader ) );
[ + - ]
426 : : }
427 : :
428 : 9 : TextFieldStack& XmlFilterBase::getTextFieldStack() const
429 : : {
430 : 9 : return mxImpl->maTextFieldStack;
431 : : }
432 : :
433 : : namespace {
434 : :
435 : 345 : OUString lclAddRelation( const Reference< XRelationshipAccess > xRelations, sal_Int32 nId, const OUString& rType, const OUString& rTarget, bool bExternal )
436 : : {
437 [ + - ][ + - ]: 345 : OUString sId = OUStringBuffer().appendAscii( "rId" ).append( nId ).makeStringAndClear();
[ + - ]
438 : :
439 [ + - ][ - + ]: 345 : Sequence< StringPair > aEntry( bExternal ? 3 : 2 );
440 [ + - ][ + - ]: 345 : aEntry[0].First = CREATE_OUSTRING( "Type" );
441 [ + - ]: 345 : aEntry[0].Second = rType;
442 [ + - ][ + - ]: 345 : aEntry[1].First = CREATE_OUSTRING( "Target" );
443 [ + - ]: 345 : aEntry[1].Second = rTarget;
444 [ - + ]: 345 : if( bExternal )
445 : : {
446 [ # # ][ # # ]: 0 : aEntry[2].First = CREATE_OUSTRING( "TargetMode" );
447 [ # # ][ # # ]: 0 : aEntry[2].Second = CREATE_OUSTRING( "External" );
448 : : }
449 [ + - ][ + - ]: 345 : xRelations->insertRelationshipByID( sId, aEntry, sal_True );
450 : :
451 [ + - ]: 345 : return sId;
452 : : }
453 : :
454 : : } // namespace
455 : :
456 : 171 : OUString XmlFilterBase::addRelation( const OUString& rType, const OUString& rTarget, bool bExternal )
457 : : {
458 [ + - ][ + - ]: 171 : Reference< XRelationshipAccess > xRelations( getStorage()->getXStorage(), UNO_QUERY );
[ + - ][ + - ]
459 [ + - ]: 171 : if( xRelations.is() )
460 [ + - ]: 171 : return lclAddRelation( xRelations, mnRelId ++, rType, rTarget, bExternal );
461 : :
462 : 171 : return OUString();
463 : : }
464 : :
465 : 174 : OUString XmlFilterBase::addRelation( const Reference< XOutputStream > xOutputStream, const OUString& rType, const OUString& rTarget, bool bExternal )
466 : : {
467 : 174 : sal_Int32 nId = 0;
468 : :
469 [ + - ]: 174 : PropertySet aPropSet( xOutputStream );
470 [ + - ]: 174 : if( aPropSet.is() )
471 [ + - ]: 174 : aPropSet.getProperty( nId, PROP_RelId );
472 : : else
473 : 0 : nId = mnRelId++;
474 : :
475 [ + - ]: 174 : Reference< XRelationshipAccess > xRelations( xOutputStream, UNO_QUERY );
476 [ + - ]: 174 : if( xRelations.is() )
477 [ + - ]: 174 : return lclAddRelation( xRelations, nId, rType, rTarget, bExternal );
478 : :
479 [ + - ]: 174 : return OUString();
480 : : }
481 : :
482 : : static void
483 : 456 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const OUString& sValue )
484 : : {
485 [ + + ]: 456 : if( sValue.isEmpty() )
486 : 456 : return;
487 : 48 : pDoc->startElement( nXmlElement, FSEND );
488 : 48 : pDoc->write( sValue );
489 : 48 : pDoc->endElement( nXmlElement );
490 : : }
491 : :
492 : : static void
493 : 114 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const sal_Int32 nValue )
494 : : {
495 : 114 : pDoc->startElement( nXmlElement, FSEND );
496 [ + - ]: 114 : pDoc->write( OUString::valueOf( nValue ) );
497 : 114 : pDoc->endElement( nXmlElement );
498 : 114 : }
499 : :
500 : : static void
501 : 171 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const DateTime& rTime )
502 : : {
503 [ + + ]: 171 : if( rTime.Year == 0 )
504 : 171 : return;
505 : :
506 [ - + ]: 69 : if ( ( nXmlElement >> 16 ) != XML_dcterms )
507 [ # # ]: 0 : pDoc->startElement( nXmlElement, FSEND );
508 : : else
509 : : pDoc->startElement( nXmlElement,
510 : : FSNS( XML_xsi, XML_type ), "dcterms:W3CDTF",
511 [ + - ]: 69 : FSEND );
512 : :
513 : : char pStr[200];
514 : : snprintf( pStr, sizeof( pStr ), "%d-%02d-%02dT%02d:%02d:%02d.%02dZ",
515 : : rTime.Year, rTime.Month, rTime.Day,
516 : : rTime.Hours, rTime.Minutes, rTime.Seconds,
517 : 69 : rTime.HundredthSeconds );
518 : :
519 [ + - ]: 69 : pDoc->write( pStr );
520 : :
521 [ + - ]: 171 : pDoc->endElement( nXmlElement );
522 : : }
523 : :
524 : : static void
525 : 57 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, Sequence< rtl::OUString > aItems )
526 : : {
527 [ - + ]: 57 : if( aItems.getLength() == 0 )
528 : 57 : return;
529 : :
530 : 0 : OUStringBuffer sRep;
531 [ # # ][ # # ]: 0 : sRep.append( aItems[ 0 ] );
532 : :
533 [ # # ]: 0 : for( sal_Int32 i = 1, end = aItems.getLength(); i < end; ++i )
534 : : {
535 [ # # ][ # # ]: 0 : sRep.appendAscii( " " ).append( aItems[ i ] );
[ # # ]
536 : : }
537 : :
538 [ # # ][ # # ]: 57 : writeElement( pDoc, nXmlElement, sRep.makeStringAndClear() );
[ # # ][ # # ]
539 : : }
540 : :
541 : : static void
542 : 57 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const Locale& rLocale )
543 : : {
544 : : // TODO: what to do with .Country and .Variant
545 [ + - ]: 57 : writeElement( pDoc, nXmlElement, rLocale.Language );
546 : 57 : }
547 : :
548 : : static void
549 : 57 : writeCoreProperties( XmlFilterBase& rSelf, Reference< XDocumentProperties > xProperties )
550 : : {
551 : 57 : OUString sValue;
552 [ + - ][ + - ]: 57 : if( rSelf.getVersion() == oox::core::ISOIEC_29500_2008 )
553 [ + - ]: 57 : sValue = CREATE_OUSTRING( "http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties" );
554 : : else
555 [ # # ]: 0 : sValue = CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" );
556 : :
557 [ + - ][ + - ]: 57 : rSelf.addRelation( sValue, CREATE_OUSTRING( "docProps/core.xml" ) );
558 : : FSHelperPtr pCoreProps = rSelf.openFragmentStreamWithSerializer(
559 : : CREATE_OUSTRING( "docProps/core.xml" ),
560 [ + - ][ + - ]: 57 : CREATE_OUSTRING( "application/vnd.openxmlformats-package.core-properties+xml" ) );
[ + - ]
561 : : pCoreProps->startElementNS( XML_cp, XML_coreProperties,
562 : : FSNS( XML_xmlns, XML_cp ), "http://schemas.openxmlformats.org/package/2006/metadata/core-properties",
563 : : FSNS( XML_xmlns, XML_dc ), "http://purl.org/dc/elements/1.1/",
564 : : FSNS( XML_xmlns, XML_dcterms ), "http://purl.org/dc/terms/",
565 : : FSNS( XML_xmlns, XML_dcmitype ), "http://purl.org/dc/dcmitype/",
566 : : FSNS( XML_xmlns, XML_xsi ), "http://www.w3.org/2001/XMLSchema-instance",
567 [ + - ]: 57 : FSEND );
568 : :
569 : : #if OOXTODO
570 : : writeElement( pCoreProps, FSNS( XML_cp, XML_category ), "category" );
571 : : writeElement( pCoreProps, FSNS( XML_cp, XML_contentStatus ), "status" );
572 : : writeElement( pCoreProps, FSNS( XML_cp, XML_contentType ), "contentType" );
573 : : #endif /* def OOXTODO */
574 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dcterms, XML_created ), xProperties->getCreationDate() );
[ + - ][ + - ]
[ + - ]
575 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dc, XML_creator ), xProperties->getAuthor() );
[ + - ][ + - ]
[ + - ]
576 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dc, XML_description ), xProperties->getDescription() );
[ + - ][ + - ]
[ + - ]
577 : : #if OOXTODO
578 : : writeElement( pCoreProps, FSNS( XML_dc, XML_identifier ), "ident" );
579 : : #endif /* def OOXTODO */
580 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_cp, XML_keywords ), xProperties->getKeywords() );
[ + - ][ + - ]
[ + - ][ + - ]
581 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dc, XML_language ), xProperties->getLanguage() );
[ + - ][ + - ]
[ + - ]
582 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_cp, XML_lastModifiedBy ), xProperties->getModifiedBy() );
[ + - ][ + - ]
[ + - ]
583 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_cp, XML_lastPrinted ), xProperties->getPrintDate() );
[ + - ][ + - ]
[ + - ]
584 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dcterms, XML_modified ), xProperties->getModificationDate() );
[ + - ][ + - ]
[ + - ]
585 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_cp, XML_revision ), xProperties->getEditingCycles() );
[ + - ][ + - ]
[ + - ]
586 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dc, XML_subject ), xProperties->getSubject() );
[ + - ][ + - ]
[ + - ]
587 [ + - ][ + - ]: 57 : writeElement( pCoreProps, FSNS( XML_dc, XML_title ), xProperties->getTitle() );
[ + - ][ + - ]
[ + - ]
588 : : #if OOXTODO
589 : : writeElement( pCoreProps, FSNS( XML_cp, XML_version ), "version" );
590 : : #endif /* def OOXTODO */
591 : :
592 [ + - ][ + - ]: 57 : pCoreProps->endElementNS( XML_cp, XML_coreProperties );
593 : 57 : }
594 : :
595 : : static void
596 : 57 : writeAppProperties( XmlFilterBase& rSelf, Reference< XDocumentProperties > xProperties )
597 : : {
598 : : rSelf.addRelation(
599 : : CREATE_OUSTRING( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" ),
600 [ + - ][ + - ]: 57 : CREATE_OUSTRING( "docProps/app.xml" ) );
[ + - ]
601 : : FSHelperPtr pAppProps = rSelf.openFragmentStreamWithSerializer(
602 : : CREATE_OUSTRING( "docProps/app.xml" ),
603 [ + - ][ + - ]: 57 : CREATE_OUSTRING( "application/vnd.openxmlformats-officedocument.extended-properties+xml" ) );
[ + - ]
604 : : pAppProps->startElement( XML_Properties,
605 : : XML_xmlns, "http://schemas.openxmlformats.org/officeDocument/2006/extended-properties",
606 : : FSNS( XML_xmlns, XML_vt ), "http://schemas.openxmlformats.org/officeDocument/2006/docPropsVTypes",
607 [ + - ]: 57 : FSEND );
608 : :
609 [ + - ][ + - ]: 57 : writeElement( pAppProps, XML_Template, xProperties->getTemplateName() );
[ + - ][ + - ]
[ + - ]
610 : : #if OOXTODO
611 : : writeElement( pAppProps, XML_Manager, "manager" );
612 : : writeElement( pAppProps, XML_Company, "company" );
613 : : writeElement( pAppProps, XML_Pages, "pages" );
614 : : writeElement( pAppProps, XML_Words, "words" );
615 : : writeElement( pAppProps, XML_Characters, "characters" );
616 : : writeElement( pAppProps, XML_PresentationFormat, "presentation format" );
617 : : writeElement( pAppProps, XML_Lines, "lines" );
618 : : writeElement( pAppProps, XML_Paragraphs, "paragraphs" );
619 : : writeElement( pAppProps, XML_Slides, "slides" );
620 : : writeElement( pAppProps, XML_Notes, "notes" );
621 : : #endif /* def OOXTODO */
622 [ + - ][ + - ]: 57 : writeElement( pAppProps, XML_TotalTime, xProperties->getEditingDuration() );
[ + - ][ + - ]
[ + - ]
623 : : #if OOXTODO
624 : : writeElement( pAppProps, XML_HiddenSlides, "hidden slides" );
625 : : writeElement( pAppProps, XML_MMClips, "mm clips" );
626 : : writeElement( pAppProps, XML_ScaleCrop, "scale crop" );
627 : : writeElement( pAppProps, XML_HeadingPairs, "heading pairs" );
628 : : writeElement( pAppProps, XML_TitlesOfParts, "titles of parts" );
629 : : writeElement( pAppProps, XML_LinksUpToDate, "links up-to-date" );
630 : : writeElement( pAppProps, XML_CharactersWithSpaces, "characters with spaces" );
631 : : writeElement( pAppProps, XML_SharedDoc, "shared doc" );
632 : : writeElement( pAppProps, XML_HyperlinkBase, "hyperlink base" );
633 : : writeElement( pAppProps, XML_HLinks, "hlinks" );
634 : : writeElement( pAppProps, XML_HyperlinksChanged, "hyperlinks changed" );
635 : : writeElement( pAppProps, XML_DigSig, "digital signature" );
636 : : #endif /* def OOXTODO */
637 [ + - ][ + - ]: 57 : writeElement( pAppProps, XML_Application, xProperties->getGenerator() );
[ + - ][ + - ]
[ + - ]
638 : : #if OOXTODO
639 : : writeElement( pAppProps, XML_AppVersion, "app version" );
640 : : writeElement( pAppProps, XML_DocSecurity, "doc security" );
641 : : #endif /* def OOXTODO */
642 [ + - ][ + - ]: 57 : pAppProps->endElement( XML_Properties );
643 : 57 : }
644 : :
645 : 57 : XmlFilterBase& XmlFilterBase::exportDocumentProperties( Reference< XDocumentProperties > xProperties )
646 : : {
647 [ + - ]: 57 : if( xProperties.is() )
648 : : {
649 [ + - ]: 57 : writeCoreProperties( *this, xProperties );
650 [ + - ]: 57 : writeAppProperties( *this, xProperties );
651 [ + - ][ + - ]: 57 : Sequence< ::com::sun::star::beans::NamedValue > aStats = xProperties->getDocumentStatistics();
652 : : OSL_TRACE( "# Document Statistics:" );
653 [ + + ]: 141 : for( sal_Int32 i = 0, end = aStats.getLength(); i < end; ++i )
654 : : {
655 [ + - ]: 84 : ::com::sun::star::uno::Any aValue = aStats[ i ].Value;
656 : 84 : ::rtl::OUString sValue;
657 : 84 : bool bHaveString = aValue >>= sValue;
658 : : OSL_TRACE ("#\t%s=%s [%s]\n",
659 : : OUStringToOString( aStats[ i ].Name, RTL_TEXTENCODING_UTF8 ).getStr(),
660 : : bHaveString
661 : : ? OUStringToOString( sValue, RTL_TEXTENCODING_UTF8 ).getStr()
662 : : : "<unconvertable>",
663 : : OUStringToOString( aValue.getValueTypeName(), RTL_TEXTENCODING_UTF8 ).getStr());
664 [ + - ]: 141 : }
665 : : }
666 : 57 : return *this;
667 : : }
668 : :
669 : : // protected ------------------------------------------------------------------
670 : :
671 : 90 : Reference< XInputStream > XmlFilterBase::implGetInputStream( MediaDescriptor& rMediaDesc ) const
672 : : {
673 : : /* Get the input stream directly from the media descriptor, or decrypt the
674 : : package again. The latter is needed e.g. when the document is reloaded.
675 : : All this is implemented in the detector service. */
676 [ + - ][ + - ]: 90 : FilterDetect aDetector( getComponentContext() );
677 [ + - ][ + - ]: 90 : return aDetector.extractUnencryptedPackage( rMediaDesc );
678 : : }
679 : :
680 : : // private --------------------------------------------------------------------
681 : :
682 : 90 : StorageRef XmlFilterBase::implCreateStorage( const Reference< XInputStream >& rxInStream ) const
683 : : {
684 [ + - ]: 90 : return StorageRef( new ZipStorage( getComponentContext(), rxInStream ) );
685 : : }
686 : :
687 : 57 : StorageRef XmlFilterBase::implCreateStorage( const Reference< XStream >& rxOutStream ) const
688 : : {
689 [ + - ]: 57 : return StorageRef( new ZipStorage( getComponentContext(), rxOutStream ) );
690 : : }
691 : :
692 : : // ============================================================================
693 : :
694 : : } // namespace core
695 [ + - ][ + - ]: 285 : } // namespace oox
696 : :
697 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|