1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <officecfg/Office/Common.hxx>
21 #include <vcl/errinf.hxx>
22 #include <sal/log.hxx>
23 #include <com/sun/star/container/XChild.hpp>
24 #include <com/sun/star/beans/XPropertySetInfo.hpp>
25 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <com/sun/star/xml/sax/SAXParseException.hpp>
27 #include <comphelper/processfactory.hxx>
28 #include <comphelper/propertysequence.hxx>
29 #include <o3tl/string_view.hxx>
30 #include <editeng/outlobj.hxx>
31 #include <sfx2/docfile.hxx>
32 #include <sfx2/docfilt.hxx>
33 #include <sfx2/sfxsids.hrc>
34 #include <drawdoc.hxx>
36 #include <Outliner.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <svx/dialmgr.hxx>
39 #include <svx/strings.hrc>
40 #include <svx/xmlgrhlp.hxx>
42 #include <DrawDocShell.hxx>
44 #include <sdxmlwrp.hxx>
45 #include <svx/xmleohlp.hxx>
46 #include <com/sun/star/xml/sax/Parser.hpp>
47 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
48 #include <com/sun/star/xml/sax/XFastParser.hpp>
49 #include <com/sun/star/document/XFilter.hpp>
50 #include <com/sun/star/document/XImporter.hpp>
51 #include <com/sun/star/document/XExporter.hpp>
52 #include <com/sun/star/lang/XInitialization.hpp>
53 #include <com/sun/star/lang/XServiceInfo.hpp>
54 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
55 #include <com/sun/star/beans/PropertyAttribute.hpp>
56 #include <com/sun/star/packages/WrongPasswordException.hpp>
57 #include <com/sun/star/packages/zip/ZipIOException.hpp>
59 #include <com/sun/star/xml/sax/InputSource.hpp>
60 #include <com/sun/star/xml/sax/Writer.hpp>
61 #include <comphelper/genericpropertyset.hxx>
62 #include <comphelper/propertysetinfo.hxx>
63 #include <editeng/eeitem.hxx>
65 // include necessary for XML progress bar at load time
66 #include <svl/itemset.hxx>
67 #include <svl/stritem.hxx>
68 #include <svtools/sfxecode.hxx>
71 #include <sderror.hxx>
72 #include <sdresid.hxx>
73 #include "sdtransform.hxx"
74 #include <strings.hrc>
76 #include <sfx2/frame.hxx>
77 #include <tools/debug.hxx>
78 #include <comphelper/diagnose_ex.hxx>
80 using namespace com::sun::star
;
81 using namespace com::sun::star::uno
;
82 using namespace com::sun::star::lang
;
83 using namespace com::sun::star::document
;
84 using namespace comphelper
;
86 #define SD_XML_READERROR ErrCode(1234)
88 char const sXML_export_impress_meta_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisMetaExporter";
89 char const sXML_export_impress_styles_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisStylesExporter";
90 char const sXML_export_impress_content_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisContentExporter";
91 char const sXML_export_impress_settings_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisSettingsExporter";
93 char const sXML_export_draw_meta_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisMetaExporter";
94 char const sXML_export_draw_styles_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisStylesExporter";
95 char const sXML_export_draw_content_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisContentExporter";
96 char const sXML_export_draw_settings_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisSettingsExporter";
98 char const sXML_import_impress_meta_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisMetaImporter";
99 char const sXML_import_impress_styles_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisStylesImporter";
100 char const sXML_import_impress_content_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisContentImporter";
101 char const sXML_import_impress_settings_oasis_service
[] = "com.sun.star.comp.Impress.XMLOasisSettingsImporter";
103 char const sXML_import_draw_meta_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisMetaImporter";
104 char const sXML_import_draw_styles_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisStylesImporter";
105 char const sXML_import_draw_content_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisContentImporter";
106 char const sXML_import_draw_settings_oasis_service
[] = "com.sun.star.comp.Draw.XMLOasisSettingsImporter";
109 char const sXML_import_impress_meta_ooo_service
[] = "com.sun.star.comp.Impress.XMLMetaImporter";
110 char const sXML_import_impress_styles_ooo_service
[] = "com.sun.star.comp.Impress.XMLStylesImporter";
111 char const sXML_import_impress_content_ooo_service
[] = "com.sun.star.comp.Impress.XMLContentImporter";
112 char const sXML_import_impress_settings_ooo_service
[] = "com.sun.star.comp.Impress.XMLSettingsImporter";
114 char const sXML_import_draw_meta_ooo_service
[] = "com.sun.star.comp.Draw.XMLMetaImporter";
115 char const sXML_import_draw_styles_ooo_service
[] = "com.sun.star.comp.Draw.XMLStylesImporter";
116 char const sXML_import_draw_content_ooo_service
[] = "com.sun.star.comp.Draw.XMLContentImporter";
117 char const sXML_import_draw_settings_ooo_service
[] = "com.sun.star.comp.Draw.XMLSettingsImporter";
121 struct XML_SERVICEMAP
123 const char* mpService
;
124 const char* mpStream
;
130 const char* mpStyles
;
131 const char* mpContent
;
132 const char* mpSettings
;
137 static XML_SERVICES
const * getServices( bool bImport
, bool bDraw
, sal_uLong nStoreVer
)
139 // Expect that export always sets nStoreVer to SOFFICE_FILEFORMAT_8.
140 assert(bImport
|| nStoreVer
!= SOFFICE_FILEFORMAT_60
);
142 static XML_SERVICES
const gServices
[] =
144 { sXML_import_impress_meta_oasis_service
, sXML_import_impress_styles_oasis_service
, sXML_import_impress_content_oasis_service
, sXML_import_impress_settings_oasis_service
},
145 { sXML_import_draw_meta_oasis_service
, sXML_import_draw_styles_oasis_service
, sXML_import_draw_content_oasis_service
, sXML_import_draw_settings_oasis_service
},
146 { sXML_export_impress_meta_oasis_service
, sXML_export_impress_styles_oasis_service
, sXML_export_impress_content_oasis_service
, sXML_export_impress_settings_oasis_service
},
147 { sXML_export_draw_meta_oasis_service
, sXML_export_draw_styles_oasis_service
, sXML_export_draw_content_oasis_service
, sXML_export_draw_settings_oasis_service
},
149 { sXML_import_impress_meta_ooo_service
, sXML_import_impress_styles_ooo_service
, sXML_import_impress_content_ooo_service
, sXML_import_impress_settings_ooo_service
},
150 { sXML_import_draw_meta_ooo_service
, sXML_import_draw_styles_ooo_service
, sXML_import_draw_content_ooo_service
, sXML_import_draw_settings_ooo_service
},
153 return &gServices
[ (bImport
? 0 : 2) + ((nStoreVer
== SOFFICE_FILEFORMAT_60
) ? 4 : 0) + (bDraw
? 1 : 0 ) ];
157 SdXMLFilter::SdXMLFilter( SfxMedium
& rMedium
, ::sd::DrawDocShell
& rDocShell
, SdXMLFilterMode eFilterMode
, sal_uLong nStoreVer
) :
158 SdFilter( rMedium
, rDocShell
), meFilterMode( eFilterMode
), mnStoreVer( nStoreVer
)
162 SdXMLFilter::~SdXMLFilter()
169 ErrCodeMsg
ReadThroughComponent(
170 const Reference
<io::XInputStream
>& xInputStream
,
171 const Reference
<XComponent
>& xModelComponent
,
172 const OUString
& rStreamName
,
173 Reference
<uno::XComponentContext
> const & rxContext
,
174 const char* pFilterName
,
175 const Sequence
<Any
>& rFilterArguments
,
176 const OUString
& rName
,
177 bool bMustBeSuccessful
,
180 DBG_ASSERT(xInputStream
.is(), "input stream missing");
181 DBG_ASSERT(xModelComponent
.is(), "document missing");
182 DBG_ASSERT(rxContext
.is(), "factory missing");
183 DBG_ASSERT(nullptr != pFilterName
,"I need a service name for the component!");
185 SAL_INFO( "sd.filter", "ReadThroughComponent" );
187 // prepare ParserInputSource
188 xml::sax::InputSource aParserInput
;
189 aParserInput
.sSystemId
= rName
;
190 aParserInput
.aInputStream
= xInputStream
;
193 OUString
aFilterName(OUString::createFromAscii(pFilterName
));
194 // the underlying SvXMLImport implements XFastParser, XImporter, XFastDocumentHandler
195 Reference
< XInterface
> xFilter(
196 rxContext
->getServiceManager()->createInstanceWithArgumentsAndContext(aFilterName
, rFilterArguments
, rxContext
),
198 SAL_WARN_IF(!xFilter
.is(), "sd.filter", "Can't instantiate filter component: " << aFilterName
);
200 return SD_XML_READERROR
;
201 Reference
< xml::sax::XFastParser
> xFastParser(xFilter
, UNO_QUERY
);
202 Reference
< xml::sax::XDocumentHandler
> xDocumentHandler
;
204 xDocumentHandler
.set(xFilter
, UNO_QUERY
);
205 if (!xFastParser
&& !xDocumentHandler
)
207 SAL_WARN("sd", "service does not implement XFastParser or XDocumentHandler");
209 return SD_XML_READERROR
;
211 SAL_INFO( "sd.filter", "" << pFilterName
<< " created" );
213 // connect model and filter
214 Reference
< XImporter
> xImporter( xFilter
, UNO_QUERY
);
215 xImporter
->setTargetDocument( xModelComponent
);
217 // finally, parser the stream
218 SAL_INFO( "sd.filter", "parsing stream" );
222 xFastParser
->parseStream( aParserInput
);
225 Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create(rxContext
);
226 // connect parser and filter
227 xParser
->setDocumentHandler( xDocumentHandler
);
228 xParser
->parseStream( aParserInput
);
231 catch (const xml::sax::SAXParseException
& r
)
233 css::uno::Any
ex( cppu::getCaughtException() );
234 // sax parser sends wrapped exceptions,
235 // try to find the original one
236 xml::sax::SAXException aSaxEx
= *static_cast<xml::sax::SAXException
const *>(&r
);
237 bool bTryChild
= true;
241 xml::sax::SAXException aTmp
;
242 if ( aSaxEx
.WrappedException
>>= aTmp
)
243 aSaxEx
= std::move(aTmp
);
248 packages::zip::ZipIOException aBrokenPackage
;
249 if ( aSaxEx
.WrappedException
>>= aBrokenPackage
)
250 return ERRCODE_IO_BROKENPACKAGE
;
253 return ERRCODE_SFX_WRONGPASSWORD
;
255 SAL_WARN( "sd.filter", "SAX parse exception caught while importing: " << exceptionToString(ex
));
257 OUString sErr
= OUString::number( r
.LineNumber
) +
258 "," + OUString::number( r
.ColumnNumber
);
260 if (!rStreamName
.isEmpty())
263 (bMustBeSuccessful
? ERR_FORMAT_FILE_ROWCOL
264 : WARN_FORMAT_FILE_ROWCOL
),
266 DialogMask::ButtonsOk
| DialogMask::MessageError
);
270 DBG_ASSERT( bMustBeSuccessful
, "Warnings are not supported" );
271 return ErrCodeMsg( ERR_FORMAT_ROWCOL
, sErr
,
272 DialogMask::ButtonsOk
| DialogMask::MessageError
);
275 catch (const xml::sax::SAXException
& r
)
277 css::uno::Any
ex( cppu::getCaughtException() );
278 packages::zip::ZipIOException aBrokenPackage
;
279 if ( r
.WrappedException
>>= aBrokenPackage
)
280 return ERRCODE_IO_BROKENPACKAGE
;
283 return ERRCODE_SFX_WRONGPASSWORD
;
285 SAL_WARN( "sd.filter", "SAX exception caught while importing: " << exceptionToString(ex
));
286 return SD_XML_READERROR
;
288 catch (const packages::zip::ZipIOException
&)
290 TOOLS_WARN_EXCEPTION( "sd.filter", "Zip exception caught while importing");
291 return ERRCODE_IO_BROKENPACKAGE
;
293 catch (const io::IOException
&)
295 TOOLS_WARN_EXCEPTION( "sd.filter", "IO exception caught while importing");
296 return SD_XML_READERROR
;
298 catch (const uno::Exception
&)
300 TOOLS_WARN_EXCEPTION( "sd.filter", "uno exception caught while importing");
301 return SD_XML_READERROR
;
308 ErrCodeMsg
ReadThroughComponent(
309 const uno::Reference
< embed::XStorage
>& xStorage
,
310 const Reference
<XComponent
>& xModelComponent
,
311 const char* pStreamName
,
312 Reference
<uno::XComponentContext
> const & rxContext
,
313 const char* pFilterName
,
314 const Sequence
<Any
>& rFilterArguments
,
315 const OUString
& rName
,
316 bool bMustBeSuccessful
)
318 DBG_ASSERT(xStorage
.is(), "Need storage!");
319 DBG_ASSERT(nullptr != pStreamName
, "Please, please, give me a name!");
321 // open stream (and set parser input)
322 OUString sStreamName
= OUString::createFromAscii(pStreamName
);
323 bool bContainsStream
= false;
326 bContainsStream
= xStorage
->isStreamElement(sStreamName
);
328 catch (const container::NoSuchElementException
&)
332 if (!bContainsStream
)
334 // stream name not found! return immediately with OK signal
339 uno::Reference
< beans::XPropertySet
> xInfoSet
;
340 if( rFilterArguments
.hasElements() )
341 rFilterArguments
.getConstArray()[0] >>= xInfoSet
;
342 DBG_ASSERT( xInfoSet
.is(), "missing property set" );
345 xInfoSet
->setPropertyValue( u
"StreamName"_ustr
, Any( sStreamName
) );
351 Reference
<io::XStream
> xStream
=
352 xStorage
->openStreamElement( sStreamName
, embed::ElementModes::READ
);
353 Reference
<beans::XPropertySet
> xProps( xStream
, uno::UNO_QUERY
);
354 if ( !xStream
.is() || ! xProps
.is() )
355 return SD_XML_READERROR
;
357 Any aAny
= xProps
->getPropertyValue( u
"Encrypted"_ustr
);
359 bool bEncrypted
= false;
362 Reference
<io::XInputStream
> xInputStream
= xStream
->getInputStream();
364 // read from the stream
365 return ReadThroughComponent(
366 xInputStream
, xModelComponent
, sStreamName
, rxContext
,
367 pFilterName
, rFilterArguments
,
368 rName
, bMustBeSuccessful
, bEncrypted
);
370 catch (const packages::WrongPasswordException
&)
372 return ERRCODE_SFX_WRONGPASSWORD
;
374 catch (const packages::zip::ZipIOException
&)
376 return ERRCODE_IO_BROKENPACKAGE
;
378 catch (const uno::Exception
&)
381 return SD_XML_READERROR
;
386 //PresObjKind::Outlines in master pages are the preview of the outline styles
387 //numbering format. Since fdo#78151 toggling bullets on and off changes
388 //the style they are a preview of, previously toggling bullets on and off
389 //would only affect the preview paragraph itself without an effect on the
390 //style. i.e. previews of numbering which don't match the real numbering
391 //they are supposed to be a preview of.
393 //But there exist documents which were saved previous to that modification
394 //so here we detect such cases and fix them up to ensure the previews
395 //numbering level matches that of the outline level it previews
396 static void fixupOutlinePlaceholderNumberingDepths(SdDrawDocument
* pDoc
)
398 for (sal_uInt16 i
= 0; i
< pDoc
->GetMasterSdPageCount(PageKind::Standard
); ++i
)
400 SdPage
*pMasterPage
= pDoc
->GetMasterSdPage(i
, PageKind::Standard
);
401 SdrObject
* pMasterOutline
= pMasterPage
->GetPresObj(PresObjKind::Outline
);
404 OutlinerParaObject
* pOutlParaObj
= pMasterOutline
->GetOutlinerParaObject();
407 SdOutliner
* pOutliner
= pDoc
->GetInternalOutliner();
409 pOutliner
->SetText(*pOutlParaObj
);
410 bool bInconsistent
= false;
411 const sal_Int32 nParaCount
= pOutliner
->GetParagraphCount();
412 for (sal_Int32 j
= 0; j
< nParaCount
; ++j
)
414 //Make sure the depth of the paragraph matches that of the outline style it previews
415 const sal_Int16 nExpectedDepth
= j
;
416 if (nExpectedDepth
!= pOutliner
->GetDepth(j
))
418 Paragraph
* p
= pOutliner
->GetParagraph(j
);
419 pOutliner
->SetDepth(p
, nExpectedDepth
);
420 bInconsistent
= true;
423 //If the preview has hard-coded bullets/numbering then they must
424 //be stripped to reveal the true underlying styles attributes
425 SfxItemSet
aAttrs(pOutliner
->GetParaAttribs(j
));
426 if (aAttrs
.GetItemState(EE_PARA_NUMBULLET
) == SfxItemState::SET
)
428 aAttrs
.ClearItem(EE_PARA_NUMBULLET
);
429 pOutliner
->SetParaAttribs(j
, aAttrs
);
430 bInconsistent
= true;
436 SAL_WARN("sd.filter", "Fixing inconsistent outline numbering placeholder preview");
437 pMasterOutline
->SetOutlinerParaObject(pOutliner
->CreateParaObject(0, nParaCount
));
443 bool SdXMLFilter::Import( ErrCode
& nError
)
445 ErrCodeMsg nRet
= ERRCODE_NONE
;
447 // Get service factory
448 const Reference
< uno::XComponentContext
>& rxContext
=
449 comphelper::getProcessComponentContext();
451 SdDrawDocument
* pDoc
= mrDocShell
.GetDoc();
452 bool const bWasUndo(pDoc
->IsUndoEnabled());
453 pDoc
->EnableUndo(false);
454 pDoc
->NewOrLoadCompleted( DocCreationMode::New
);
455 pDoc
->CreateFirstPages();
456 pDoc
->StopWorkStartupDelay();
458 mxModel
->lockControllers();
460 /** property map for import info set */
461 static PropertyMapEntry
const aImportInfoMap
[] =
463 // necessary properties for XML progress bar at load time
464 { u
"ProgressRange"_ustr
, 0, cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
465 { u
"ProgressMax"_ustr
, 0, cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
466 { u
"ProgressCurrent"_ustr
, 0, cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
467 { u
"Preview"_ustr
, 0, cppu::UnoType
<sal_Bool
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
468 { u
"PageLayouts"_ustr
, 0, cppu::UnoType
<container::XNameAccess
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
469 { u
"PrivateData"_ustr
, 0, cppu::UnoType
<XInterface
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
470 { u
"BaseURI"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
471 { u
"StreamRelPath"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
472 { u
"StreamName"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
473 { u
"BuildId"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
474 { u
"OrganizerMode"_ustr
, 0, cppu::UnoType
<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
475 { u
"SourceStorage"_ustr
, 0, cppu::UnoType
<embed::XStorage
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
478 uno::Reference
< beans::XPropertySet
> xInfoSet( GenericPropertySet_CreateInstance( new PropertySetInfo( aImportInfoMap
) ) );
479 xInfoSet
->setPropertyValue( u
"Preview"_ustr
, uno::Any( mrDocShell
.GetDoc()->IsStarDrawPreviewMode() ) );
481 // ---- get BuildId from parent container if available
483 uno::Reference
< container::XChild
> xChild( mxModel
, uno::UNO_QUERY
);
486 uno::Reference
< beans::XPropertySet
> xParentSet( xChild
->getParent(), uno::UNO_QUERY
);
487 if( xParentSet
.is() )
489 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xParentSet
->getPropertySetInfo() );
490 OUString
sPropName( u
"BuildId"_ustr
);
491 if( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName(sPropName
) )
493 xInfoSet
->setPropertyValue( sPropName
, xParentSet
->getPropertyValue(sPropName
) );
498 uno::Reference
<document::XGraphicStorageHandler
> xGraphicStorageHandler
;
499 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
500 Reference
< document::XEmbeddedObjectResolver
> xObjectResolver
;
501 rtl::Reference
<SvXMLEmbeddedObjectHelper
> xObjectHelper
;
503 Reference
< lang::XComponent
> xModelComp
= mxModel
;
505 // try to get an XStatusIndicator from the Medium
507 const SfxUnoAnyItem
* pItem
= mrMedium
.GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL
);
510 pItem
->GetValue() >>= mxStatusIndicator
;
513 if(mxStatusIndicator
.is())
515 sal_Int32
nProgressRange(1000000);
516 OUString
aMsg(SvxResId(RID_SVXSTR_DOC_LOAD
));
517 mxStatusIndicator
->start(aMsg
, nProgressRange
);
521 aProgRange
<<= nProgressRange
;
522 xInfoSet
->setPropertyValue( u
"ProgressRange"_ustr
, aProgRange
);
524 // set ProgressCurrent
525 uno::Any aProgCurrent
;
526 aProgCurrent
<<= sal_Int32(0);
527 xInfoSet
->setPropertyValue( u
"ProgressCurrent"_ustr
, aProgCurrent
);
531 // get the input stream (storage or stream)
533 uno::Reference
< embed::XStorage
> xStorage
= mrMedium
.GetStorage();
535 xInfoSet
->setPropertyValue( u
"SourceStorage"_ustr
, Any( xStorage
) );
538 nRet
= SD_XML_READERROR
;
540 if( ERRCODE_NONE
== nRet
)
542 xGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
,
543 SvXMLGraphicHelperMode::Read
);
544 xGraphicStorageHandler
= xGraphicHelper
.get();
545 xObjectHelper
= SvXMLEmbeddedObjectHelper::Create(
546 xStorage
, *pDoc
->GetPersist(),
547 SvXMLEmbeddedObjectHelperMode::Read
);
548 xObjectResolver
= xObjectHelper
.get();
552 OUString
const baseURI(mrMedium
.GetBaseURL());
553 // needed for relative URLs, but in clipboard copy/paste there may be none
554 SAL_INFO_IF(baseURI
.isEmpty(), "sd.filter", "SdXMLFilter: no base URL");
555 xInfoSet
->setPropertyValue(u
"BaseURI"_ustr
, Any(baseURI
));
557 if( ERRCODE_NONE
== nRet
&& SfxObjectCreateMode::EMBEDDED
== mrDocShell
.GetCreateMode() )
560 const SfxStringItem
* pDocHierarchItem
=
561 mrMedium
.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME
);
562 if ( pDocHierarchItem
)
563 aName
= pDocHierarchItem
->GetValue();
565 aName
= "dummyObjectName" ;
567 if( !aName
.isEmpty() )
568 xInfoSet
->setPropertyValue( u
"StreamRelPath"_ustr
, Any( aName
) );
571 if (SdXMLFilterMode::Organizer
== meFilterMode
)
572 xInfoSet
->setPropertyValue(u
"OrganizerMode"_ustr
, uno::Any(true));
574 if( ERRCODE_NONE
== nRet
)
577 // prepare filter arguments
578 Sequence
<Any
> aFilterArgs( 4 );
579 Any
*pArgs
= aFilterArgs
.getArray();
580 *pArgs
++ <<= xInfoSet
;
581 *pArgs
++ <<= xGraphicStorageHandler
;
582 *pArgs
++ <<= xObjectResolver
;
583 *pArgs
++ <<= mxStatusIndicator
;
585 Sequence
<Any
> aEmptyArgs( 2 );
586 pArgs
= aEmptyArgs
.getArray();
587 *pArgs
++ <<= xInfoSet
;
588 *pArgs
++ <<= mxStatusIndicator
;
590 const OUString
aName( mrMedium
.GetName() );
592 XML_SERVICES
const * pServices
= getServices( true, IsDraw(), mnStoreVer
);
594 ErrCodeMsg nWarn
= ERRCODE_NONE
;
595 ErrCodeMsg nWarn2
= ERRCODE_NONE
;
596 // read storage streams
597 // #i103539#: always read meta.xml for generator
598 nWarn
= ReadThroughComponent(
599 xStorage
, xModelComp
, "meta.xml", rxContext
,
601 aEmptyArgs
, aName
, false );
603 if( meFilterMode
!= SdXMLFilterMode::Organizer
)
605 nWarn2
= ReadThroughComponent(
606 xStorage
, xModelComp
, "settings.xml", rxContext
,
607 pServices
->mpSettings
,
608 aFilterArgs
, aName
, false );
611 nRet
= ReadThroughComponent(
612 xStorage
, xModelComp
, "styles.xml", rxContext
,
614 aFilterArgs
, aName
, true );
616 if( !nRet
&& (meFilterMode
!= SdXMLFilterMode::Organizer
) )
617 nRet
= ReadThroughComponent(
618 xStorage
, xModelComp
, "content.xml", rxContext
,
619 pServices
->mpContent
,
620 aFilterArgs
, aName
, true );
625 nRet
= std::move(nWarn
);
627 nRet
= std::move(nWarn2
);
632 xGraphicHelper
->dispose();
633 xGraphicHelper
.clear();
634 xGraphicStorageHandler
= nullptr;
635 if( xObjectHelper
.is() )
636 xObjectHelper
->dispose();
637 xObjectHelper
.clear();
638 xObjectResolver
= nullptr;
640 if( mxStatusIndicator
.is() )
641 mxStatusIndicator
->end();
644 mxModel
->unlockControllers();
646 if( nRet
== ERRCODE_NONE
)
647 pDoc
->UpdateAllLinks();
649 if( nRet
== ERRCODE_NONE
|| nRet
== SD_XML_READERROR
)
651 else if( nRet
== ERRCODE_IO_BROKENPACKAGE
&& xStorage
.is() )
652 nError
= ERRCODE_IO_BROKENPACKAGE
;
655 // TODO/LATER: this is completely wrong! Filter code should never call ErrorHandler directly!
656 ErrorHandler::HandleError( nRet
);
657 if( nRet
.IsWarning() )
661 // clear unused named items from item pool
663 ::svx::DropUnusedNamedItems(mxModel
);
665 // set BuildId on XModel for later OLE object loading
668 uno::Reference
< beans::XPropertySet
> xModelSet( mxModel
, uno::UNO_QUERY
);
671 uno::Reference
< beans::XPropertySetInfo
> xModelSetInfo( xModelSet
->getPropertySetInfo() );
672 static constexpr OUString
sPropName( u
"BuildId"_ustr
);
675 xInfoSet
->getPropertyValue(sPropName
) >>= sBuildId
;
677 if( xModelSetInfo
.is() && xModelSetInfo
->hasPropertyByName(sPropName
) )
679 xModelSet
->setPropertyValue( sPropName
, Any( sBuildId
) );
682 bool bTransform
= false;
684 if( nRet
== ERRCODE_NONE
)
686 if( !sBuildId
.isEmpty() )
688 sal_Int32 nIndex
= sBuildId
.indexOf('$');
689 if (sBuildId
.indexOf(';') == -1 && nIndex
!= -1)
691 sal_Int32 nUPD
= o3tl::toInt32(sBuildId
.subView( 0, nIndex
));
695 sal_Int32 nBuildId
= o3tl::toInt32(sBuildId
.subView( nIndex
+1 ));
696 if( (nBuildId
> 0) && (nBuildId
< 9316) )
697 bTransform
= true; // treat OOo 3.0 beta1 as OOo 2.x
699 else if( (nUPD
== 680) || ( nUPD
>= 640 && nUPD
<= 645 ) )
705 // check for binary formats
706 std::shared_ptr
<const SfxFilter
> pFilter
= mrMedium
.GetFilter();
709 OUString
typeName(pFilter
->GetRealTypeName());
710 if( typeName
.startsWith( "impress_StarImpress" ) ||
711 typeName
.startsWith( "draw_StarDraw" ) )
720 TransformOOo2xDocument( pDoc
);
724 fixupOutlinePlaceholderNumberingDepths(pDoc
);
726 pDoc
->EnableUndo(bWasUndo
);
727 mrDocShell
.ClearUndoBuffer();
728 return nRet
== ERRCODE_NONE
;
731 bool SdXMLFilter::Export()
733 rtl::Reference
<SvXMLEmbeddedObjectHelper
> xObjectHelper
;
734 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
735 bool bDocRet
= false;
739 SAL_WARN( "sd.filter","Got NO Model in XMLExport");
743 bool bLocked
= mxModel
->hasControllersLocked();
747 mxModel
->lockControllers();
749 uno::Reference
< lang::XServiceInfo
> xServiceInfo( mxModel
, uno::UNO_QUERY
);
751 if( !xServiceInfo
.is() || !xServiceInfo
->supportsService( u
"com.sun.star.drawing.GenericDrawingDocument"_ustr
) )
753 SAL_WARN( "sd.filter", "Model is no DrawingDocument in XMLExport" );
757 const uno::Reference
<uno::XComponentContext
>& xContext( ::comphelper::getProcessComponentContext() );
759 uno::Reference
< xml::sax::XWriter
> xWriter
= xml::sax::Writer::create( xContext
);
761 /** property map for export info set */
762 static PropertyMapEntry
const aExportInfoMap
[] =
764 { u
"ProgressRange"_ustr
, 0, cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
765 { u
"ProgressMax"_ustr
, 0, cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
766 { u
"ProgressCurrent"_ustr
, 0, cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
767 { u
"UsePrettyPrinting"_ustr
,0, cppu::UnoType
<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
768 { u
"PageLayoutNames"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
769 { u
"BaseURI"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
770 { u
"StreamRelPath"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
771 { u
"StreamName"_ustr
, 0, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
772 { u
"StyleNames"_ustr
, 0, cppu::UnoType
<Sequence
<OUString
>>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
773 { u
"StyleFamilies"_ustr
, 0, cppu::UnoType
<Sequence
<sal_Int32
>>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
774 { u
"TargetStorage"_ustr
, 0, cppu::UnoType
<embed::XStorage
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
777 uno::Reference
< beans::XPropertySet
> xInfoSet( GenericPropertySet_CreateInstance( new PropertySetInfo( aExportInfoMap
) ) );
779 bool bUsePrettyPrinting
= officecfg::Office::Common::Save::Document::PrettyPrinting::get();
780 xInfoSet
->setPropertyValue( u
"UsePrettyPrinting"_ustr
, Any( bUsePrettyPrinting
) );
782 const uno::Reference
< embed::XStorage
> xStorage
= mrMedium
.GetOutputStorage();
785 OUString
sPropName( u
"BaseURI"_ustr
);
786 xInfoSet
->setPropertyValue( sPropName
, Any( mrMedium
.GetBaseURL( true ) ) );
788 xInfoSet
->setPropertyValue( u
"TargetStorage"_ustr
, Any( xStorage
) );
790 if( SfxObjectCreateMode::EMBEDDED
== mrDocShell
.GetCreateMode() )
793 const SfxStringItem
* pDocHierarchItem
=
794 mrMedium
.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME
);
795 if ( pDocHierarchItem
)
796 aName
= pDocHierarchItem
->GetValue();
798 if( !aName
.isEmpty() )
800 sPropName
= "StreamRelPath";
801 xInfoSet
->setPropertyValue( sPropName
, Any( aName
) );
805 // initialize descriptor
806 uno::Sequence
< beans::PropertyValue
> aDescriptor( 1 );
807 beans::PropertyValue
* pProps
= aDescriptor
.getArray();
809 pProps
[0].Name
= "FileName";
810 pProps
[0].Value
<<= mrMedium
.GetName();
813 uno::Reference
< document::XEmbeddedObjectResolver
> xObjectResolver
;
814 uno::Reference
<document::XGraphicStorageHandler
> xGraphicStorageHandler
;
816 // create helper for graphic and ole export if we have a storage
819 xObjectHelper
= SvXMLEmbeddedObjectHelper::Create( xStorage
, *mrDocShell
.GetDoc()->GetPersist(), SvXMLEmbeddedObjectHelperMode::Write
);
820 xObjectResolver
= xObjectHelper
.get();
822 xGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, SvXMLGraphicHelperMode::Write
);
823 xGraphicStorageHandler
= xGraphicHelper
.get();
826 CreateStatusIndicator();
827 if(mxStatusIndicator
.is())
829 sal_Int32
nProgressRange(1000000);
830 OUString
aMsg(SdResId(STR_SAVE_DOC
));
831 mxStatusIndicator
->start(aMsg
, nProgressRange
);
835 aProgRange
<<= nProgressRange
;
836 xInfoSet
->setPropertyValue( u
"ProgressRange"_ustr
, aProgRange
);
838 // set ProgressCurrent
839 uno::Any aProgCurrent
;
840 aProgCurrent
<<= sal_Int32(0);
841 xInfoSet
->setPropertyValue( u
"ProgressCurrent"_ustr
, aProgCurrent
);
844 XML_SERVICES
const * pServiceNames
= getServices( false, IsDraw(), mnStoreVer
);
846 XML_SERVICEMAP aServices
[5]; sal_uInt16 i
= 0;
847 aServices
[i
].mpService
= pServiceNames
->mpStyles
;
848 aServices
[i
++].mpStream
= "styles.xml";
850 aServices
[i
].mpService
= pServiceNames
->mpContent
;
851 aServices
[i
++].mpStream
= "content.xml";
853 aServices
[i
].mpService
= pServiceNames
->mpSettings
;
854 aServices
[i
++].mpStream
= "settings.xml";
856 if( mrDocShell
.GetCreateMode() != SfxObjectCreateMode::EMBEDDED
)
858 aServices
[i
].mpService
= pServiceNames
->mpMeta
;
859 aServices
[i
++].mpStream
= "meta.xml";
862 aServices
[i
].mpService
= nullptr;
863 aServices
[i
].mpStream
= nullptr;
865 XML_SERVICEMAP
* pServices
= aServices
;
870 SAL_INFO( "sd.filter", "exporting substream " << pServices
->mpStream
);
872 uno::Reference
<io::XOutputStream
> xDocOut
;
875 const OUString
sDocName( OUString::createFromAscii( pServices
->mpStream
) );
876 uno::Reference
<io::XStream
> xStream
=
877 xStorage
->openStreamElement( sDocName
,
878 embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
880 DBG_ASSERT(xStream
.is(), "Can't create output stream in package!");
884 xDocOut
= xStream
->getOutputStream();
885 Reference
<beans::XPropertySet
> xProps( xStream
, uno::UNO_QUERY
);
886 if( !xDocOut
.is() || !xProps
.is() )
889 xProps
->setPropertyValue( u
"MediaType"_ustr
, Any(u
"text/xml"_ustr
));
891 // encrypt all streams
892 xProps
->setPropertyValue( u
"UseCommonStoragePasswordEncryption"_ustr
,
895 xInfoSet
->setPropertyValue( u
"StreamName"_ustr
, Any( sDocName
) );
898 xWriter
->setOutputStream( xDocOut
);
900 uno::Sequence
< uno::Any
> aArgs( 2 + ( mxStatusIndicator
.is() ? 1 : 0 ) + ( xGraphicStorageHandler
.is() ? 1 : 0 ) + ( xObjectResolver
.is() ? 1 : 0 ) );
901 uno::Any
* pArgs
= aArgs
.getArray();
902 *pArgs
++ <<= xInfoSet
;
903 if (xGraphicStorageHandler
.is())
904 *pArgs
++ <<= xGraphicStorageHandler
;
905 if (xObjectResolver
.is())
906 *pArgs
++ <<= xObjectResolver
;
907 if (mxStatusIndicator
.is())
908 *pArgs
++ <<= mxStatusIndicator
;
912 uno::Reference
< document::XFilter
> xFilter( xContext
->getServiceManager()->createInstanceWithArgumentsAndContext( OUString::createFromAscii( pServices
->mpService
), aArgs
, xContext
), uno::UNO_QUERY
);
915 uno::Reference
< document::XExporter
> xExporter( xFilter
, uno::UNO_QUERY
);
918 xExporter
->setSourceDocument( mxModel
);
919 // outputstream will be closed by SAX parser
920 bDocRet
= xFilter
->filter( aDescriptor
);
926 while( bDocRet
&& pServices
->mpService
);
928 if(mxStatusIndicator
.is())
929 mxStatusIndicator
->end();
932 catch (const uno::Exception
&)
934 TOOLS_WARN_EXCEPTION( "sd.filter", "uno Exception caught while exporting");
938 mxModel
->unlockControllers();
941 xGraphicHelper
->dispose();
942 xGraphicHelper
.clear();
945 xObjectHelper
->dispose();
946 xObjectHelper
.clear();
951 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportFODP(SvStream
&rStream
)
955 sd::DrawDocShellRef
xDocSh(new sd::DrawDocShell(SfxObjectCreateMode::EMBEDDED
, false, DocumentType::Impress
));
957 uno::Reference
<frame::XModel
> xModel(xDocSh
->GetModel());
959 uno::Reference
<lang::XMultiServiceFactory
> xMultiServiceFactory(comphelper::getProcessServiceFactory());
960 uno::Reference
<io::XInputStream
> xStream(new ::utl::OSeekableInputStreamWrapper(rStream
));
961 uno::Reference
<uno::XInterface
> xInterface(xMultiServiceFactory
->createInstance(u
"com.sun.star.comp.Writer.XmlFilterAdaptor"_ustr
), uno::UNO_SET_THROW
);
963 css::uno::Sequence
<OUString
> aUserData
965 u
"com.sun.star.comp.filter.OdfFlatXml"_ustr
,
967 u
"com.sun.star.comp.Impress.XMLOasisImporter"_ustr
,
968 u
"com.sun.star.comp.Impress.XMLOasisExporter"_ustr
,
973 uno::Sequence
<beans::PropertyValue
> aAdaptorArgs(comphelper::InitPropertySequence(
975 { "UserData", uno::Any(aUserData
) },
977 css::uno::Sequence
<uno::Any
> aOuterArgs
{ uno::Any(aAdaptorArgs
) };
979 uno::Reference
<lang::XInitialization
> xInit(xInterface
, uno::UNO_QUERY_THROW
);
980 xInit
->initialize(aOuterArgs
);
982 uno::Reference
<document::XImporter
> xImporter(xInterface
, uno::UNO_QUERY_THROW
);
983 uno::Sequence
<beans::PropertyValue
> aArgs(comphelper::InitPropertySequence(
985 { "InputStream", uno::Any(xStream
) },
986 { "URL", uno::Any(u
"private:stream"_ustr
) },
988 xImporter
->setTargetDocument(xModel
);
990 uno::Reference
<document::XFilter
> xFilter(xInterface
, uno::UNO_QUERY_THROW
);
991 //SetLoading hack because the document properties will be re-initted
992 //by the xml filter and during the init, while it's considered uninitialized,
993 //setting a property will inform the document it's modified, which attempts
994 //to update the properties, which throws cause the properties are uninitialized
995 xDocSh
->SetLoading(SfxLoadedFlags::NONE
);
996 bool ret
= xFilter
->filter(aArgs
);
997 xDocSh
->SetLoading(SfxLoadedFlags::ALL
);
1004 extern "C" SAL_DLLPUBLIC_EXPORT
bool TestImportPPTX(SvStream
&rStream
)
1008 sd::DrawDocShellRef
xDocSh(new sd::DrawDocShell(SfxObjectCreateMode::EMBEDDED
, false, DocumentType::Impress
));
1009 xDocSh
->DoInitNew();
1010 uno::Reference
<frame::XModel
> xModel(xDocSh
->GetModel());
1012 uno::Reference
<lang::XMultiServiceFactory
> xMultiServiceFactory(comphelper::getProcessServiceFactory());
1013 uno::Reference
<io::XInputStream
> xStream(new utl::OSeekableInputStreamWrapper(rStream
));
1015 uno::Reference
<document::XFilter
> xFilter(xMultiServiceFactory
->createInstance(u
"com.sun.star.comp.oox.ppt.PowerPointImport"_ustr
), uno::UNO_QUERY_THROW
);
1017 uno::Reference
<document::XImporter
> xImporter(xFilter
, uno::UNO_QUERY_THROW
);
1018 uno::Sequence
<beans::PropertyValue
> aArgs(comphelper::InitPropertySequence(
1020 { "InputStream", uno::Any(xStream
) },
1021 { "InputMode", uno::Any(true) },
1023 xImporter
->setTargetDocument(xModel
);
1025 //SetLoading hack because the document properties will be re-initted
1026 //by the xml filter and during the init, while it's considered uninitialized,
1027 //setting a property will inform the document it's modified, which attempts
1028 //to update the properties, which throws cause the properties are uninitialized
1029 xDocSh
->SetLoading(SfxLoadedFlags::NONE
);
1033 ret
= xFilter
->filter(aArgs
);
1038 xDocSh
->SetLoading(SfxLoadedFlags::ALL
);
1046 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */