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