tdf#164098 sw: Fix word overflow kashida justification crash
[LibreOffice.git] / sd / source / filter / xml / sdxmlwrp.cxx
blobb8cc7bf102263515969eae55232913801da1dd19
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
35 #include <sdpage.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>
70 #include <sddll.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";
108 // OOo
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";
119 namespace {
121 struct XML_SERVICEMAP
123 const char* mpService;
124 const char* mpStream;
127 struct XML_SERVICES
129 const char* mpMeta;
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()
166 namespace
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,
178 bool bEncrypted )
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;
192 // get filter
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),
197 UNO_QUERY );
198 SAL_WARN_IF(!xFilter.is(), "sd.filter", "Can't instantiate filter component: " << aFilterName);
199 if( !xFilter.is() )
200 return SD_XML_READERROR;
201 Reference< xml::sax::XFastParser > xFastParser(xFilter, UNO_QUERY);
202 Reference< xml::sax::XDocumentHandler > xDocumentHandler;
203 if (!xFastParser)
204 xDocumentHandler.set(xFilter, UNO_QUERY);
205 if (!xFastParser && !xDocumentHandler)
207 SAL_WARN("sd", "service does not implement XFastParser or XDocumentHandler");
208 assert(false);
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" );
221 if (xFastParser)
222 xFastParser->parseStream( aParserInput );
223 else
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;
239 while( bTryChild )
241 xml::sax::SAXException aTmp;
242 if ( aSaxEx.WrappedException >>= aTmp )
243 aSaxEx = std::move(aTmp);
244 else
245 bTryChild = false;
248 packages::zip::ZipIOException aBrokenPackage;
249 if ( aSaxEx.WrappedException >>= aBrokenPackage )
250 return ERRCODE_IO_BROKENPACKAGE;
252 if( bEncrypted )
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())
262 return ErrCodeMsg(
263 (bMustBeSuccessful ? ERR_FORMAT_FILE_ROWCOL
264 : WARN_FORMAT_FILE_ROWCOL),
265 rStreamName, sErr,
266 DialogMask::ButtonsOk | DialogMask::MessageError );
268 else
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;
282 if( bEncrypted )
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;
304 // success!
305 return ERRCODE_NONE;
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
335 return ERRCODE_NONE;
338 // set Base URL
339 uno::Reference< beans::XPropertySet > xInfoSet;
340 if( rFilterArguments.hasElements() )
341 rFilterArguments.getConstArray()[0] >>= xInfoSet;
342 DBG_ASSERT( xInfoSet.is(), "missing property set" );
343 if( xInfoSet.is() )
345 xInfoSet->setPropertyValue( u"StreamName"_ustr, Any( sStreamName ) );
350 // get input stream
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;
360 aAny >>= bEncrypted;
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);
402 if (!pMasterOutline)
403 continue;
404 OutlinerParaObject* pOutlParaObj = pMasterOutline->GetOutlinerParaObject();
405 if (!pOutlParaObj)
406 continue;
407 SdOutliner* pOutliner = pDoc->GetInternalOutliner();
408 pOutliner->Clear();
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;
434 if (bInconsistent)
436 SAL_WARN("sd.filter", "Fixing inconsistent outline numbering placeholder preview");
437 pMasterOutline->SetOutlinerParaObject(pOutliner->CreateParaObject(0, nParaCount));
439 pOutliner->Clear();
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 );
484 if( xChild.is() )
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);
508 if (pItem)
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);
519 // set ProgressRange
520 uno::Any aProgRange;
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 ) );
537 if( !xStorage.is() )
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();
551 // Set base URI
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() )
559 OUString aName;
560 const SfxStringItem* pDocHierarchItem =
561 mrMedium.GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME);
562 if ( pDocHierarchItem )
563 aName = pDocHierarchItem->GetValue();
564 else
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,
600 pServices->mpMeta,
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,
613 pServices->mpStyles,
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 );
622 if( !nRet )
624 if( nWarn )
625 nRet = std::move(nWarn);
626 else if( nWarn2 )
627 nRet = std::move(nWarn2);
631 if( xGraphicHelper )
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();
643 if( mxModel.is() )
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;
653 else
655 // TODO/LATER: this is completely wrong! Filter code should never call ErrorHandler directly!
656 ErrorHandler::HandleError( nRet );
657 if( nRet.IsWarning() )
658 nRet = ERRCODE_NONE;
661 // clear unused named items from item pool
663 ::svx::DropUnusedNamedItems(mxModel);
665 // set BuildId on XModel for later OLE object loading
666 if( xInfoSet.is() )
668 uno::Reference< beans::XPropertySet > xModelSet( mxModel, uno::UNO_QUERY );
669 if( xModelSet.is() )
671 uno::Reference< beans::XPropertySetInfo > xModelSetInfo( xModelSet->getPropertySetInfo() );
672 static constexpr OUString sPropName( u"BuildId"_ustr );
674 OUString sBuildId;
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 ));
693 if( nUPD == 300 )
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 ) )
700 bTransform = true;
703 else
705 // check for binary formats
706 std::shared_ptr<const SfxFilter> pFilter = mrMedium.GetFilter();
707 if( pFilter )
709 OUString typeName(pFilter->GetRealTypeName());
710 if( typeName.startsWith( "impress_StarImpress" ) ||
711 typeName.startsWith( "draw_StarDraw" ) )
713 bTransform = true;
719 if( bTransform )
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;
737 if( !mxModel.is() )
739 SAL_WARN( "sd.filter","Got NO Model in XMLExport");
740 return false;
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" );
754 return false;
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();
784 // Set base URI
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() )
792 OUString aName;
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
817 if( xStorage.is() )
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);
833 // set ProgressRange
834 uno::Any aProgRange;
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;
867 // doc export
870 SAL_INFO( "sd.filter", "exporting substream " << pServices->mpStream );
872 uno::Reference<io::XOutputStream> xDocOut;
873 if( xStorage.is() )
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!");
881 if( !xStream.is() )
882 return false;
884 xDocOut = xStream->getOutputStream();
885 Reference <beans::XPropertySet > xProps( xStream, uno::UNO_QUERY );
886 if( !xDocOut.is() || !xProps.is() )
887 return false;
889 xProps->setPropertyValue( u"MediaType"_ustr, Any(u"text/xml"_ustr));
891 // encrypt all streams
892 xProps->setPropertyValue( u"UseCommonStoragePasswordEncryption"_ustr,
893 uno::Any( true ) );
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;
910 *pArgs <<= xWriter;
912 uno::Reference< document::XFilter > xFilter( xContext->getServiceManager()->createInstanceWithArgumentsAndContext( OUString::createFromAscii( pServices->mpService ), aArgs, xContext ), uno::UNO_QUERY );
913 if( xFilter.is() )
915 uno::Reference< document::XExporter > xExporter( xFilter, uno::UNO_QUERY );
916 if( xExporter.is() )
918 xExporter->setSourceDocument( mxModel );
919 // outputstream will be closed by SAX parser
920 bDocRet = xFilter->filter( aDescriptor );
924 pServices++;
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");
935 bDocRet = false;
937 if ( !bLocked )
938 mxModel->unlockControllers();
940 if( xGraphicHelper )
941 xGraphicHelper->dispose();
942 xGraphicHelper.clear();
944 if( xObjectHelper )
945 xObjectHelper->dispose();
946 xObjectHelper.clear();
948 return bDocRet;
951 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportFODP(SvStream &rStream)
953 SdDLL::Init();
955 sd::DrawDocShellRef xDocSh(new sd::DrawDocShell(SfxObjectCreateMode::EMBEDDED, false, DocumentType::Impress));
956 xDocSh->DoInitNew();
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,
966 u""_ustr,
967 u"com.sun.star.comp.Impress.XMLOasisImporter"_ustr,
968 u"com.sun.star.comp.Impress.XMLOasisExporter"_ustr,
969 u""_ustr,
970 u""_ustr,
971 u"true"_ustr
973 uno::Sequence<beans::PropertyValue> aAdaptorArgs(comphelper::InitPropertySequence(
975 { "UserData", uno::Any(aUserData) },
976 }));
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) },
987 }));
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);
999 xDocSh->DoClose();
1001 return ret;
1004 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportPPTX(SvStream &rStream)
1006 SdDLL::Init();
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) },
1022 }));
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);
1030 bool ret = false;
1033 ret = xFilter->filter(aArgs);
1035 catch (...)
1038 xDocSh->SetLoading(SfxLoadedFlags::ALL);
1040 xDocSh->DoClose();
1042 return ret;
1046 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */