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 418 : bool lclHasSuffix( const OUString& rFragmentPath, const OUString& rSuffix )
91 : {
92 418 : sal_Int32 nSuffixPos = rFragmentPath.getLength() - rSuffix.getLength();
93 418 : return (nSuffixPos >= 0) && rFragmentPath.match( rSuffix, nSuffixPos );
94 : }
95 :
96 : } // namespace
97 :
98 : // ============================================================================
99 :
100 122 : 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 14 : 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 14 : Sequence< beans::Pair< OUString, sal_Int32 > > aRet(STATIC_ARRAY_SIZE(namespaceIds));
172 308 : for( sal_Int32 i=0; i<aRet.getLength(); ++i )
173 294 : aRet[i] = make_Pair(
174 294 : OUString::createFromAscii(namespaceURIs[i]),
175 882 : namespaceIds[i]);
176 14 : return aRet;
177 : }
178 : };
179 : }
180 :
181 : // ----------------------------------------------------------------------------
182 :
183 122 : XmlFilterBaseImpl::XmlFilterBaseImpl( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
184 : maFastParser( rxContext ),
185 : maBinSuffix( CREATE_OUSTRING( ".bin" ) ),
186 122 : maVmlSuffix( CREATE_OUSTRING( ".vml" ) )
187 : {
188 : // register XML namespaces
189 : const Sequence< beans::Pair< OUString, sal_Int32 > > ids=
190 122 : NamespaceIds::get();
191 2684 : for( sal_Int32 i=0; i<ids.getLength(); ++i )
192 2684 : maFastParser.registerNamespace( ids[i].Second );
193 122 : }
194 :
195 122 : XmlFilterBase::XmlFilterBase( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
196 : FilterBase( rxContext ),
197 122 : mxImpl( new XmlFilterBaseImpl( rxContext ) ),
198 : mnRelId( 1 ),
199 244 : mnMaxDocId( 0 )
200 : {
201 122 : }
202 :
203 122 : XmlFilterBase::~XmlFilterBase()
204 : {
205 122 : }
206 :
207 : // ----------------------------------------------------------------------------
208 :
209 22 : void XmlFilterBase::importDocumentProperties()
210 : {
211 22 : Reference< XMultiServiceFactory > xFactory( getServiceFactory(), UNO_QUERY );
212 22 : MediaDescriptor aMediaDesc( getMediaDescriptor() );
213 22 : Reference< XInputStream > xInputStream;
214 22 : Reference< XComponentContext > xContext = comphelper::getComponentContext(getServiceFactory());
215 22 : ::oox::core::FilterDetect aDetector( xContext );
216 22 : xInputStream = aDetector.extractUnencryptedPackage( aMediaDesc );
217 22 : Reference< XComponent > xModel( getModel(), UNO_QUERY );
218 : Reference< XStorage > xDocumentStorage (
219 22 : ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( OFOPXML_STORAGE_FORMAT_STRING, xInputStream ) );
220 44 : Reference< XInterface > xTemp = xContext->getServiceManager()->createInstanceWithContext(
221 : "com.sun.star.document.OOXMLDocumentPropertiesImporter",
222 22 : xContext);
223 22 : Reference< XOOXMLDocumentPropertiesImporter > xImporter( xTemp, UNO_QUERY );
224 22 : Reference< XDocumentPropertiesSupplier > xPropSupplier( xModel, UNO_QUERY);
225 22 : xImporter->importProperties( xDocumentStorage, xPropSupplier->getDocumentProperties() );
226 22 : }
227 :
228 30 : OUString XmlFilterBase::getFragmentPathFromFirstType( const OUString& rType )
229 : {
230 : // importRelations() caches the relations map for subsequence calls
231 30 : return importRelations( OUString() )->getFragmentPathFromFirstType( rType );
232 : }
233 :
234 418 : bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& rxHandler )
235 : {
236 : OSL_ENSURE( rxHandler.is(), "XmlFilterBase::importFragment - missing fragment handler" );
237 418 : if( !rxHandler.is() )
238 0 : return false;
239 :
240 : // fragment handler must contain path to fragment stream
241 418 : OUString aFragmentPath = rxHandler->getFragmentPath();
242 : OSL_ENSURE( !aFragmentPath.isEmpty(), "XmlFilterBase::importFragment - missing fragment path" );
243 418 : if( aFragmentPath.isEmpty() )
244 0 : return false;
245 :
246 : // try to import binary streams (fragment extension must be '.bin')
247 418 : 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 418 : Reference< XFastDocumentHandler > xDocHandler( rxHandler.get() );
273 418 : 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 418 : Reference< XInputStream > xInStrm = rxHandler->openFragmentStream();
284 :
285 : // own try/catch block for showing parser failure assertion with fragment path
286 418 : if( xInStrm.is() ) try
287 : {
288 302 : mxImpl->maFastParser.setDocumentHandler( xDocHandler );
289 302 : mxImpl->maFastParser.parseStream( xInStrm, aFragmentPath );
290 302 : 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 418 : }
297 : }
298 0 : catch( Exception& )
299 : {
300 : }
301 116 : return false;
302 : }
303 :
304 12 : OUString XmlFilterBase::getNamespaceURL( const OUString& rPrefix )
305 : {
306 12 : return mxImpl->maFastParser.getNamespaceURL( rPrefix );
307 : }
308 :
309 12 : sal_Int32 XmlFilterBase::getNamespaceId( const OUString& rUrl )
310 : {
311 12 : return mxImpl->maFastParser.getNamespaceId( rUrl );
312 : }
313 :
314 12 : Reference<XDocument> XmlFilterBase::importFragment( const OUString& aFragmentPath )
315 : {
316 12 : Reference<XDocument> xRet;
317 :
318 : // path to fragment stream valid?
319 : OSL_ENSURE( !aFragmentPath.isEmpty(), "XmlFilterBase::importFragment - empty fragment path" );
320 12 : if( aFragmentPath.isEmpty() )
321 : return xRet;
322 :
323 : // try to open the fragment stream (this may fail - do not assert)
324 12 : Reference< XInputStream > xInStrm = openInputStream( aFragmentPath );
325 12 : if( !xInStrm.is() )
326 : return xRet;
327 :
328 : // binary streams (fragment extension is '.bin') currently not supported
329 12 : sal_Int32 nBinSuffixPos = aFragmentPath.getLength() - mxImpl->maBinSuffix.getLength();
330 12 : 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 12 : comphelper::getComponentContext(getServiceFactory());
339 12 : Reference<XDocumentBuilder> xDomBuilder( DocumentBuilder::create(xContext) );
340 :
341 : // create DOM from fragment
342 12 : xRet = xDomBuilder->parse(xInStrm);
343 : }
344 0 : catch( Exception& )
345 : {
346 : }
347 :
348 12 : return xRet;
349 : }
350 :
351 12 : bool XmlFilterBase::importFragment( const ::rtl::Reference< FragmentHandler >& rxHandler,
352 : const Reference< XFastSAXSerializable >& rxSerializer )
353 : {
354 12 : Reference< XFastDocumentHandler > xDocHandler( rxHandler.get() );
355 12 : if( !xDocHandler.is() )
356 0 : return false;
357 :
358 : // try to import XML stream
359 : try
360 : {
361 12 : rxSerializer->fastSerialize( xDocHandler,
362 12 : mxImpl->maFastParser.getTokenHandler(),
363 : Sequence< StringPair >(),
364 24 : NamespaceIds::get() );
365 12 : return true;
366 : }
367 0 : catch( Exception& )
368 : {}
369 :
370 0 : return false;
371 : }
372 :
373 288 : RelationsRef XmlFilterBase::importRelations( const OUString& rFragmentPath )
374 : {
375 : // try to find cached relations
376 288 : RelationsRef& rxRelations = mxImpl->maRelationsMap[ rFragmentPath ];
377 288 : if( !rxRelations )
378 : {
379 : // import and cache relations
380 250 : rxRelations.reset( new Relations( rFragmentPath ) );
381 250 : importFragment( new RelationsFragment( *this, rxRelations ) );
382 : }
383 288 : return rxRelations;
384 : }
385 :
386 304 : Reference< XOutputStream > XmlFilterBase::openFragmentStream( const OUString& rStreamName, const OUString& rMediaType )
387 : {
388 304 : Reference< XOutputStream > xOutputStream = openOutputStream( rStreamName );
389 304 : PropertySet aPropSet( xOutputStream );
390 304 : aPropSet.setProperty( PROP_MediaType, rMediaType );
391 304 : return xOutputStream;
392 : }
393 :
394 302 : FSHelperPtr XmlFilterBase::openFragmentStreamWithSerializer( const OUString& rStreamName, const OUString& rMediaType )
395 : {
396 302 : bool bWriteHeader = true;
397 302 : if( rMediaType.indexOfAsciiL( "vml", 3 ) >= 0 &&
398 0 : rMediaType.indexOfAsciiL( "+xml", 4 ) < 0 )
399 0 : bWriteHeader = false;
400 302 : return FSHelperPtr( new FastSerializerHelper( openFragmentStream( rStreamName, rMediaType ), bWriteHeader ) );
401 : }
402 :
403 8 : TextFieldStack& XmlFilterBase::getTextFieldStack() const
404 : {
405 8 : return mxImpl->maTextFieldStack;
406 : }
407 :
408 : namespace {
409 :
410 306 : OUString lclAddRelation( const Reference< XRelationshipAccess > xRelations, sal_Int32 nId, const OUString& rType, const OUString& rTarget, bool bExternal )
411 : {
412 306 : OUString sId = OUStringBuffer().appendAscii( "rId" ).append( nId ).makeStringAndClear();
413 :
414 306 : Sequence< StringPair > aEntry( bExternal ? 3 : 2 );
415 306 : aEntry[0].First = CREATE_OUSTRING( "Type" );
416 306 : aEntry[0].Second = rType;
417 306 : aEntry[1].First = CREATE_OUSTRING( "Target" );
418 306 : aEntry[1].Second = rTarget;
419 306 : if( bExternal )
420 : {
421 2 : aEntry[2].First = CREATE_OUSTRING( "TargetMode" );
422 2 : aEntry[2].Second = CREATE_OUSTRING( "External" );
423 : }
424 306 : xRelations->insertRelationshipByID( sId, aEntry, sal_True );
425 :
426 306 : return sId;
427 : }
428 :
429 : } // namespace
430 :
431 150 : OUString XmlFilterBase::addRelation( const OUString& rType, const OUString& rTarget, bool bExternal )
432 : {
433 150 : Reference< XRelationshipAccess > xRelations( getStorage()->getXStorage(), UNO_QUERY );
434 150 : if( xRelations.is() )
435 150 : return lclAddRelation( xRelations, mnRelId ++, rType, rTarget, bExternal );
436 :
437 0 : return OUString();
438 : }
439 :
440 156 : OUString XmlFilterBase::addRelation( const Reference< XOutputStream > xOutputStream, const OUString& rType, const OUString& rTarget, bool bExternal )
441 : {
442 156 : sal_Int32 nId = 0;
443 :
444 156 : PropertySet aPropSet( xOutputStream );
445 156 : if( aPropSet.is() )
446 156 : aPropSet.getProperty( nId, PROP_RelId );
447 : else
448 0 : nId = mnRelId++;
449 :
450 156 : Reference< XRelationshipAccess > xRelations( xOutputStream, UNO_QUERY );
451 156 : if( xRelations.is() )
452 156 : return lclAddRelation( xRelations, nId, rType, rTarget, bExternal );
453 :
454 0 : return OUString();
455 : }
456 :
457 : static void
458 400 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const OUString& sValue )
459 : {
460 400 : if( sValue.isEmpty() )
461 738 : return;
462 62 : pDoc->startElement( nXmlElement, FSEND );
463 62 : pDoc->write( sValue );
464 62 : pDoc->endElement( nXmlElement );
465 : }
466 :
467 : static void
468 100 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const sal_Int32 nValue )
469 : {
470 100 : pDoc->startElement( nXmlElement, FSEND );
471 100 : pDoc->write( OUString::valueOf( nValue ) );
472 100 : pDoc->endElement( nXmlElement );
473 100 : }
474 :
475 : static void
476 150 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const util::DateTime& rTime )
477 : {
478 150 : if( rTime.Year == 0 )
479 150 : return;
480 :
481 68 : 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 68 : 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 68 : rTime.HundredthSeconds );
493 :
494 68 : pDoc->write( pStr );
495 :
496 68 : pDoc->endElement( nXmlElement );
497 : }
498 :
499 : static void
500 50 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, Sequence< rtl::OUString > aItems )
501 : {
502 50 : if( aItems.getLength() == 0 )
503 50 : 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 50 : writeElement( FSHelperPtr pDoc, sal_Int32 nXmlElement, const Locale& rLocale )
518 : {
519 : // TODO: what to do with .Country and .Variant
520 50 : writeElement( pDoc, nXmlElement, rLocale.Language );
521 50 : }
522 :
523 : static void
524 50 : writeCoreProperties( XmlFilterBase& rSelf, Reference< XDocumentProperties > xProperties )
525 : {
526 50 : OUString sValue;
527 50 : if( rSelf.getVersion() == oox::core::ISOIEC_29500_2008 )
528 48 : sValue = CREATE_OUSTRING( "http://schemas.openxmlformats.org/officedocument/2006/relationships/metadata/core-properties" );
529 : else
530 2 : sValue = CREATE_OUSTRING( "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" );
531 :
532 50 : rSelf.addRelation( sValue, CREATE_OUSTRING( "docProps/core.xml" ) );
533 : FSHelperPtr pCoreProps = rSelf.openFragmentStreamWithSerializer(
534 : CREATE_OUSTRING( "docProps/core.xml" ),
535 50 : 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 50 : 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 50 : writeElement( pCoreProps, FSNS( XML_dcterms, XML_created ), xProperties->getCreationDate() );
550 50 : writeElement( pCoreProps, FSNS( XML_dc, XML_creator ), xProperties->getAuthor() );
551 50 : 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 50 : writeElement( pCoreProps, FSNS( XML_cp, XML_keywords ), xProperties->getKeywords() );
556 50 : writeElement( pCoreProps, FSNS( XML_dc, XML_language ), xProperties->getLanguage() );
557 50 : writeElement( pCoreProps, FSNS( XML_cp, XML_lastModifiedBy ), xProperties->getModifiedBy() );
558 50 : writeElement( pCoreProps, FSNS( XML_cp, XML_lastPrinted ), xProperties->getPrintDate() );
559 50 : writeElement( pCoreProps, FSNS( XML_dcterms, XML_modified ), xProperties->getModificationDate() );
560 50 : writeElement( pCoreProps, FSNS( XML_cp, XML_revision ), xProperties->getEditingCycles() );
561 50 : writeElement( pCoreProps, FSNS( XML_dc, XML_subject ), xProperties->getSubject() );
562 50 : 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 50 : pCoreProps->endElementNS( XML_cp, XML_coreProperties );
568 50 : }
569 :
570 : static void
571 50 : writeAppProperties( XmlFilterBase& rSelf, Reference< XDocumentProperties > xProperties )
572 : {
573 : rSelf.addRelation(
574 : CREATE_OUSTRING( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" ),
575 50 : CREATE_OUSTRING( "docProps/app.xml" ) );
576 : FSHelperPtr pAppProps = rSelf.openFragmentStreamWithSerializer(
577 : CREATE_OUSTRING( "docProps/app.xml" ),
578 50 : 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 50 : FSEND );
583 :
584 50 : 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 50 : 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 50 : 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 50 : pAppProps->endElement( XML_Properties );
618 50 : }
619 :
620 50 : XmlFilterBase& XmlFilterBase::exportDocumentProperties( Reference< XDocumentProperties > xProperties )
621 : {
622 50 : if( xProperties.is() )
623 : {
624 50 : writeCoreProperties( *this, xProperties );
625 50 : writeAppProperties( *this, xProperties );
626 50 : Sequence< ::com::sun::star::beans::NamedValue > aStats = xProperties->getDocumentStatistics();
627 : OSL_TRACE( "# Document Statistics:" );
628 146 : for( sal_Int32 i = 0, end = aStats.getLength(); i < end; ++i )
629 : {
630 96 : ::com::sun::star::uno::Any aValue = aStats[ i ].Value;
631 96 : OUString sValue;
632 96 : 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 146 : }
640 : }
641 50 : return *this;
642 : }
643 :
644 : // protected ------------------------------------------------------------------
645 :
646 102 : 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 102 : FilterDetect aDetector( getComponentContext() );
652 102 : return aDetector.extractUnencryptedPackage( rMediaDesc );
653 : }
654 :
655 : // private --------------------------------------------------------------------
656 :
657 102 : StorageRef XmlFilterBase::implCreateStorage( const Reference< XInputStream >& rxInStream ) const
658 : {
659 102 : return StorageRef( new ZipStorage( getComponentContext(), rxInStream ) );
660 : }
661 :
662 52 : StorageRef XmlFilterBase::implCreateStorage( const Reference< XStream >& rxOutStream ) const
663 : {
664 52 : return StorageRef( new ZipStorage( getComponentContext(), rxOutStream ) );
665 : }
666 :
667 : // ============================================================================
668 :
669 : } // namespace core
670 174 : } // namespace oox
671 :
672 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|