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