Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / sc / source / filter / xml / xmlwrap.cxx
blob79cb3a9fc06a3d01fa001b2026e82e4fb0aa27b9
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 <utility>
22 #include <vcl/errinf.hxx>
23 #include <sfx2/docfile.hxx>
24 #include <sfx2/objsh.hxx>
25 #include <sot/storage.hxx>
26 #include <osl/diagnose.h>
27 #include <o3tl/unreachable.hxx>
28 #include <comphelper/fileformat.h>
29 #include <comphelper/processfactory.hxx>
30 #include <comphelper/propertysequence.hxx>
31 #include <svx/dialmgr.hxx>
32 #include <svx/strings.hrc>
33 #include <svx/xmlgrhlp.hxx>
34 #include <svtools/sfxecode.hxx>
35 #include <sfx2/frame.hxx>
36 #include <svl/itemset.hxx>
37 #include <svl/stritem.hxx>
38 #include <sfx2/sfxsids.hrc>
39 #include <com/sun/star/container/XChild.hpp>
40 #include <com/sun/star/beans/XPropertySetInfo.hpp>
41 #include <com/sun/star/xml/sax/InputSource.hpp>
42 #include <com/sun/star/xml/sax/Parser.hpp>
43 #include <com/sun/star/xml/sax/XFastParser.hpp>
44 #include <com/sun/star/xml/sax/Writer.hpp>
45 #include <com/sun/star/xml/sax/SAXParseException.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <comphelper/propertysetinfo.hxx>
49 #include <comphelper/genericpropertyset.hxx>
50 #include <com/sun/star/packages/WrongPasswordException.hpp>
51 #include <com/sun/star/packages/zip/ZipIOException.hpp>
52 #include <com/sun/star/embed/ElementModes.hpp>
53 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
54 #include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
55 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
56 #include <com/sun/star/task/XStatusIndicator.hpp>
58 #include <sfx2/DocumentMetadataAccess.hxx>
59 #include <comphelper/documentconstants.hxx>
60 #include <xmloff/shapeexport.hxx>
61 #include <svx/xmleohlp.hxx>
62 #include <sal/log.hxx>
63 #include <comphelper/diagnose_ex.hxx>
65 #include <document.hxx>
66 #include <xmlwrap.hxx>
67 #include "xmlimprt.hxx"
68 #include "xmlexprt.hxx"
69 #include <globstr.hrc>
70 #include <scresid.hxx>
71 #include <scerrors.hxx>
72 #include "XMLExportSharedData.hxx"
73 #include <docuno.hxx>
74 #include <drwlayer.hxx>
75 #include <sheetdata.hxx>
76 #include "XMLCodeNameProvider.hxx"
77 #include <docsh.hxx>
78 #include <unonames.hxx>
80 using namespace com::sun::star;
81 using namespace css::uno;
83 ScXMLImportWrapper::ScXMLImportWrapper( ScDocShell& rDocSh, SfxMedium* pM, uno::Reference < embed::XStorage > xStor ) :
84 mrDocShell(rDocSh),
85 rDoc(rDocSh.GetDocument()),
86 pMedium(pM),
87 xStorage(std::move(xStor))
89 OSL_ENSURE( pMedium || xStorage.is(), "ScXMLImportWrapper: Medium or Storage must be set" );
92 uno::Reference <task::XStatusIndicator> ScXMLImportWrapper::GetStatusIndicator() const
94 uno::Reference<task::XStatusIndicator> xStatusIndicator;
95 if (pMedium)
97 SfxItemSet* pSet = pMedium->GetItemSet();
98 if (pSet)
100 const SfxUnoAnyItem* pItem = pSet->GetItem<SfxUnoAnyItem>(SID_PROGRESS_STATUSBAR_CONTROL);
101 if (pItem)
102 xStatusIndicator.set(pItem->GetValue(), uno::UNO_QUERY);
105 return xStatusIndicator;
108 ErrCode ScXMLImportWrapper::ImportFromComponent(const uno::Reference<uno::XComponentContext>& xContext,
109 const uno::Reference<frame::XModel>& xModel,
110 xml::sax::InputSource& aParserInput,
111 const OUString& sComponentName, const OUString& sDocName,
112 const uno::Sequence<uno::Any>& aArgs,
113 bool bMustBeSuccessful)
115 uno::Reference < io::XStream > xDocStream;
116 if ( !xStorage.is() && pMedium )
117 xStorage = pMedium->GetStorage();
119 bool bEncrypted = false;
120 OUString sStream(sDocName);
121 if( xStorage.is() )
125 if ( xStorage->hasByName(sDocName) && xStorage->isStreamElement( sDocName) )
126 xDocStream = xStorage->openStreamElement( sDocName, embed::ElementModes::READ );
127 else
128 return ERRCODE_NONE;
130 aParserInput.aInputStream = xDocStream->getInputStream();
131 uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
133 uno::Any aAny = xSet->getPropertyValue("Encrypted");
134 aAny >>= bEncrypted;
136 catch( const packages::WrongPasswordException& )
138 return ERRCODE_SFX_WRONGPASSWORD;
140 catch( const packages::zip::ZipIOException& )
142 return ERRCODE_IO_BROKENPACKAGE;
144 catch( const uno::Exception& )
146 return SCERR_IMPORT_UNKNOWN;
149 else
150 return SCERR_IMPORT_UNKNOWN;
152 // set Base URL
153 uno::Reference< beans::XPropertySet > xInfoSet;
154 if( aArgs.hasElements() )
155 aArgs.getConstArray()[0] >>= xInfoSet;
156 OSL_ENSURE( xInfoSet.is(), "missing property set" );
157 if( xInfoSet.is() )
159 xInfoSet->setPropertyValue( "StreamName", uno::Any( sStream ) );
162 ErrCode nReturn = ERRCODE_NONE;
163 rDoc.SetRangeOverflowType(ERRCODE_NONE); // is modified by the importer if limits are exceeded
165 uno::Reference<XInterface> xImportInterface =
166 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
167 sComponentName, aArgs, xContext );
168 SAL_WARN_IF( !xImportInterface, "sc", "can't get Calc importer " << sComponentName );
169 uno::Reference<document::XImporter> xImporter( xImportInterface, uno::UNO_QUERY );
170 if (xImporter.is())
171 xImporter->setTargetDocument( xModel );
173 ScXMLImport* pImporterImpl = dynamic_cast<ScXMLImport*>(xImporter.get());
174 if (pImporterImpl)
175 pImporterImpl->SetPostProcessData(&maPostProcessData);
177 // connect parser and filter
180 // xImportInterface is either ScXMLImport or an XMLTransformer subclass.
181 // ScXMLImport implements XFastParser, but XMLTransformer only implements XExtendedDocumentHandler
183 uno::Reference< xml::sax::XFastParser > xFastParser(xImportInterface, uno::UNO_QUERY);
184 if (xFastParser)
185 xFastParser->parseStream( aParserInput );
186 else
188 uno::Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(xContext);
189 uno::Reference<css::xml::sax::XDocumentHandler> xDocumentHandler(xImportInterface, uno::UNO_QUERY);
190 xParser->setDocumentHandler( xDocumentHandler );
191 xParser->parseStream( aParserInput );
194 catch( const xml::sax::SAXParseException& r )
196 css::uno::Any ex( cppu::getCaughtException() );
197 // sax parser sends wrapped exceptions,
198 // try to find the original one
199 xml::sax::SAXException aSaxEx = *static_cast<xml::sax::SAXException const *>(&r);
200 bool bTryChild = true;
202 while( bTryChild )
204 xml::sax::SAXException aTmp;
205 if ( aSaxEx.WrappedException >>= aTmp )
206 aSaxEx = aTmp;
207 else
208 bTryChild = false;
211 packages::zip::ZipIOException aBrokenPackage;
212 if ( aSaxEx.WrappedException >>= aBrokenPackage )
213 return ERRCODE_IO_BROKENPACKAGE;
214 else if( bEncrypted )
215 nReturn = ERRCODE_SFX_WRONGPASSWORD;
216 else
218 SAL_WARN("sc.filter", "SAX parse exception caught while importing: " << exceptionToString(ex));
220 OUString sErr = OUString::number( r.LineNumber ) +
221 "," +
222 OUString::number( r.ColumnNumber );
224 if( !sDocName.isEmpty() )
226 nReturn = *new TwoStringErrorInfo(
227 (bMustBeSuccessful ? SCERR_IMPORT_FILE_ROWCOL
228 : SCWARN_IMPORT_FILE_ROWCOL),
229 sDocName, sErr,
230 DialogMask::ButtonsOk | DialogMask::MessageError );
232 else
234 OSL_ENSURE( bMustBeSuccessful, "Warnings are not supported" );
235 nReturn = *new StringErrorInfo( SCERR_IMPORT_FORMAT_ROWCOL, sErr,
236 DialogMask::ButtonsOk | DialogMask::MessageError );
240 catch( const xml::sax::SAXException& r )
242 css::uno::Any ex( cppu::getCaughtException() );
243 packages::zip::ZipIOException aBrokenPackage;
244 if ( r.WrappedException >>= aBrokenPackage )
245 return ERRCODE_IO_BROKENPACKAGE;
246 else if( bEncrypted )
247 nReturn = ERRCODE_SFX_WRONGPASSWORD;
248 else
250 SAL_WARN("sc.filter", "SAX exception caught while importing: " << exceptionToString(ex));
252 nReturn = SCERR_IMPORT_FORMAT;
255 catch( const packages::zip::ZipIOException& )
257 TOOLS_WARN_EXCEPTION("sc.filter", "Zip exception caught while importing");
259 nReturn = ERRCODE_IO_BROKENPACKAGE;
261 catch( const io::IOException& )
263 TOOLS_WARN_EXCEPTION("sc.filter", "IO exception caught while importing");
265 nReturn = SCERR_IMPORT_OPEN;
267 catch( const uno::Exception& )
269 TOOLS_WARN_EXCEPTION("sc.filter", "uno exception caught while importing");
271 nReturn = SCERR_IMPORT_UNKNOWN;
274 // #i31130# Can't use getImplementation here to get the ScXMLImport from xDocHandler,
275 // because when OOo 1.x files are loaded, xDocHandler is the OOo2OasisTransformer.
276 // So the overflow warning ErrorCode is now stored in the document.
277 // Export works differently, there getImplementation still works.
279 if (rDoc.HasRangeOverflow() && !nReturn)
280 nReturn = rDoc.GetRangeOverflowType();
282 // success!
283 return nReturn;
286 bool ScXMLImportWrapper::Import( ImportFlags nMode, ErrCode& rError )
288 uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
290 xml::sax::InputSource aParserInput;
291 if (pMedium)
292 aParserInput.sSystemId = pMedium->GetName();
294 if ( !xStorage.is() && pMedium )
295 xStorage = pMedium->GetStorage();
297 // get filter
298 uno::Reference<frame::XModel> xModel = mrDocShell.GetModel();
300 /** property map for export info set */
301 static comphelper::PropertyMapEntry const aImportInfoMap[] =
303 { OUString("ProgressRange"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
304 { OUString("ProgressMax"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
305 { OUString("ProgressCurrent"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
306 { OUString("NumberStyles"), 0, cppu::UnoType<container::XNameAccess>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
307 { OUString("PrivateData"), 0, cppu::UnoType<uno::XInterface>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
308 { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
309 { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
310 { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
311 { OUString("BuildId"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
312 { OUString("VBACompatibilityMode"), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
313 { OUString("ScriptConfiguration"), 0, cppu::UnoType<container::XNameAccess>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
314 { OUString("OrganizerMode"), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
315 { OUString("SourceStorage"), 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
316 { OUString(SC_UNO_ODS_LOCK_SOLAR_MUTEX), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
317 { OUString(SC_UNO_ODS_IMPORT_STYLES), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
319 uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aImportInfoMap ) ) );
321 // No need to lock solar mutex when calling from the wrapper.
322 xInfoSet->setPropertyValue(SC_UNO_ODS_LOCK_SOLAR_MUTEX, uno::Any(false));
324 // ---- get BuildId from parent container if available
326 uno::Reference< container::XChild > xChild( xModel, uno::UNO_QUERY );
327 if( xChild.is() )
329 uno::Reference< beans::XPropertySet > xParentSet( xChild->getParent(), uno::UNO_QUERY );
330 if( xParentSet.is() )
332 uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xParentSet->getPropertySetInfo() );
333 OUString sPropName("BuildId" );
334 if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(sPropName) )
336 xInfoSet->setPropertyValue( sPropName, xParentSet->getPropertyValue(sPropName) );
341 uno::Reference<task::XStatusIndicator> xStatusIndicator = GetStatusIndicator();
342 if (xStatusIndicator.is())
344 sal_Int32 nProgressRange(1000000);
345 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
346 xInfoSet->setPropertyValue("ProgressRange", uno::Any(nProgressRange));
349 // Set base URI
350 OSL_ENSURE( pMedium, "There is no medium to get MediaDescriptor from!" );
351 OUString aBaseURL = pMedium ? pMedium->GetBaseURL() : OUString();
352 // needed for relative URLs, but in clipboard copy/paste there may be none
353 SAL_INFO_IF(aBaseURL.isEmpty(), "sc.filter", "ScXMLImportWrapper: no base URL");
354 OUString sPropName("BaseURI");
355 xInfoSet->setPropertyValue( sPropName, uno::Any( aBaseURL ) );
357 // TODO/LATER: do not do it for embedded links
358 OUString aName;
359 if (SfxObjectCreateMode::EMBEDDED == mrDocShell.GetCreateMode())
361 if ( pMedium && pMedium->GetItemSet() )
363 const SfxStringItem* pDocHierarchItem =
364 pMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
365 if ( pDocHierarchItem )
366 aName = pDocHierarchItem->GetValue();
368 else
369 aName = "dummyObjectName";
371 if( !aName.isEmpty() )
373 sPropName = "StreamRelPath";
374 xInfoSet->setPropertyValue( sPropName, uno::Any( aName ) );
378 if (mrDocShell.GetCreateMode() == SfxObjectCreateMode::ORGANIZER)
379 xInfoSet->setPropertyValue("OrganizerMode", uno::Any(true));
381 xInfoSet->setPropertyValue( "SourceStorage", uno::Any( xStorage ) );
383 bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
385 if ((nMode & ImportFlags::Metadata) && bOasis)
387 // RDF metadata: ODF >= 1.2
390 const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
391 xModel, uno::UNO_QUERY_THROW );
392 const uno::Reference< rdf::XURI > xBaseURI(
393 ::sfx2::createBaseURI( xContext, xModel, aBaseURL, aName ) );
394 uno::Reference<task::XInteractionHandler> xHandler =
395 mrDocShell.GetMedium()->GetInteractionHandler();
396 xDMA->loadMetadataFromStorage( xStorage, xBaseURI, xHandler );
398 catch ( const lang::WrappedTargetException & e)
400 ucb::InteractiveAugmentedIOException iaioe;
401 if ( e.TargetException >>= iaioe )
403 rError = SCERR_IMPORT_UNKNOWN;
405 else
407 rError = SCWARN_IMPORT_FEATURES_LOST;
410 catch ( const uno::Exception &)
412 rError = SCWARN_IMPORT_FEATURES_LOST;
416 // #i103539#: always read meta.xml for generator
417 ErrCode nMetaRetval(ERRCODE_NONE);
418 if (nMode & ImportFlags::Metadata)
420 uno::Sequence<uno::Any> aMetaArgs { Any(xInfoSet) };
422 SAL_INFO( "sc.filter", "meta import start" );
424 nMetaRetval = ImportFromComponent(
425 xContext, xModel, aParserInput,
426 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisMetaImporter")
427 : OUString("com.sun.star.comp.Calc.XMLMetaImporter"),
428 "meta.xml", aMetaArgs, false);
430 SAL_INFO( "sc.filter", "meta import end" );
433 rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
434 uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
436 uno::Reference< document::XEmbeddedObjectResolver > xObjectResolver;
437 rtl::Reference<SvXMLEmbeddedObjectHelper> xObjectHelper;
439 if( xStorage.is() )
441 xGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Read );
442 xGraphicStorageHandler = xGraphicHelper.get();
444 xObjectHelper = SvXMLEmbeddedObjectHelper::Create(xStorage, mrDocShell, SvXMLEmbeddedObjectHelperMode::Read);
445 xObjectResolver = xObjectHelper.get();
447 uno::Sequence<uno::Any> aStylesArgs
449 Any(xInfoSet),
450 Any(xGraphicStorageHandler),
451 Any(xStatusIndicator),
452 Any(xObjectResolver)
455 ErrCode nSettingsRetval(ERRCODE_NONE);
456 if (nMode & ImportFlags::Settings)
458 // Settings must be loaded first because of the printer setting,
459 // which is needed in the page styles (paper tray).
461 uno::Sequence<uno::Any> aSettingsArgs { Any(xInfoSet) };
463 SAL_INFO( "sc.filter", "settings import start" );
465 nSettingsRetval = ImportFromComponent(
466 xContext, xModel, aParserInput,
467 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisSettingsImporter")
468 : OUString("com.sun.star.comp.Calc.XMLSettingsImporter"),
469 "settings.xml", aSettingsArgs, false);
471 SAL_INFO( "sc.filter", "settings import end" );
474 ErrCode nStylesRetval(ERRCODE_NONE);
475 if (nMode & ImportFlags::Styles)
477 SAL_INFO( "sc.filter", "styles import start" );
479 nStylesRetval = ImportFromComponent(xContext, xModel, aParserInput,
480 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisStylesImporter")
481 : OUString("com.sun.star.comp.Calc.XMLStylesImporter"),
482 "styles.xml",
483 aStylesArgs, true);
485 SAL_INFO( "sc.filter", "styles import end" );
488 ErrCode nDocRetval(ERRCODE_NONE);
489 if (nMode & ImportFlags::Content)
491 if (mrDocShell.GetCreateMode() == SfxObjectCreateMode::INTERNAL)
492 // We only need to import content for external link cache document.
493 xInfoSet->setPropertyValue(SC_UNO_ODS_IMPORT_STYLES, uno::Any(false));
495 uno::Sequence<uno::Any> aDocArgs
497 Any(xInfoSet),
498 Any(xGraphicStorageHandler),
499 Any(xStatusIndicator),
500 Any(xObjectResolver)
503 SAL_INFO( "sc.filter", "content import start" );
505 nDocRetval = ImportFromComponent(xContext, xModel, aParserInput,
506 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisContentImporter")
507 : OUString("com.sun.star.comp.Calc.XMLContentImporter"),
508 "content.xml",
509 aDocArgs,
510 true);
512 SAL_INFO( "sc.filter", "content import end" );
514 if( xGraphicHelper.is() )
515 xGraphicHelper->dispose();
516 xGraphicHelper.clear();
518 if( xObjectHelper.is() )
519 xObjectHelper->dispose();
520 xObjectHelper.clear();
522 if (xStatusIndicator.is())
523 xStatusIndicator->end();
525 bool bRet = false;
526 if (nDocRetval)
528 rError = nDocRetval;
529 if (nDocRetval == SCWARN_IMPORT_RANGE_OVERFLOW ||
530 nDocRetval == SCWARN_IMPORT_ROW_OVERFLOW ||
531 nDocRetval == SCWARN_IMPORT_COLUMN_OVERFLOW ||
532 nDocRetval == SCWARN_IMPORT_SHEET_OVERFLOW)
533 bRet = true;
535 else if (nStylesRetval)
536 rError = nStylesRetval;
537 else if (nMetaRetval)
538 rError = nMetaRetval;
539 else if (nSettingsRetval)
540 rError = nSettingsRetval;
541 else
542 bRet = true;
544 ::svx::DropUnusedNamedItems(xModel);
546 // set BuildId on XModel for later OLE object loading
547 if( xInfoSet.is() )
549 uno::Reference< beans::XPropertySet > xModelSet( xModel, uno::UNO_QUERY );
550 if( xModelSet.is() )
552 uno::Reference< beans::XPropertySetInfo > xModelSetInfo( xModelSet->getPropertySetInfo() );
553 OUString sBuildPropName("BuildId" );
554 if( xModelSetInfo.is() && xModelSetInfo->hasPropertyByName(sBuildPropName) )
556 xModelSet->setPropertyValue( sBuildPropName, xInfoSet->getPropertyValue(sBuildPropName) );
560 // Set Code Names
561 uno::Any aAny = xInfoSet->getPropertyValue("ScriptConfiguration");
562 uno::Reference <container::XNameAccess> xCodeNameAccess;
563 if( aAny >>= xCodeNameAccess )
564 XMLCodeNameProvider::set( xCodeNameAccess, &rDoc );
566 // VBA compatibility
567 bool bVBACompat = false;
568 if ( (xInfoSet->getPropertyValue("VBACompatibilityMode") >>= bVBACompat) && bVBACompat )
570 /* Set library container to VBA compatibility mode, this
571 forces loading the Basic project, which in turn creates the
572 VBA Globals object and does all related initialization. */
573 if ( xModelSet.is() ) try
575 uno::Reference< script::vba::XVBACompatibility > xVBACompat( xModelSet->getPropertyValue(
576 "BasicLibraries" ), uno::UNO_QUERY_THROW );
577 xVBACompat->setVBACompatibilityMode( true );
579 catch( const uno::Exception& )
585 // Don't test bStylesRetval and bMetaRetval, because it could be an older file which not contain such streams
586 return bRet;//!bStylesOnly ? bDocRetval : bStylesRetval;
589 static bool lcl_HasValidStream(const ScDocument& rDoc)
591 SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
592 if ( pObjSh->IsDocShared() )
593 return false; // never copy stream from shared file
595 // don't read remote file again
596 // (could instead re-use medium directly in that case)
597 SfxMedium* pSrcMed = rDoc.GetDocumentShell()->GetMedium();
598 if ( !pSrcMed || pSrcMed->IsRemote() )
599 return false;
601 SCTAB nTabCount = rDoc.GetTableCount();
602 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
603 if (rDoc.IsStreamValid(nTab))
604 return true;
605 return false;
608 bool ScXMLImportWrapper::ExportToComponent(const uno::Reference<uno::XComponentContext>& xContext,
609 const uno::Reference<frame::XModel>& xModel, const uno::Reference<xml::sax::XWriter>& xWriter,
610 const uno::Sequence<beans::PropertyValue>& aDescriptor, const OUString& sName,
611 const OUString& sMediaType, const OUString& sComponentName,
612 const uno::Sequence<uno::Any>& aArgs, std::unique_ptr<ScMySharedData>& pSharedData)
614 bool bRet(false);
615 uno::Reference<io::XOutputStream> xOut;
616 uno::Reference<io::XStream> xStream;
618 if ( !xStorage.is() && pMedium )
619 xStorage = pMedium->GetOutputStorage();
621 if( xStorage.is() )
623 // #96807#; trunc stream before use, because it could be an existing stream
624 // and the new content could be shorter than the old content. In this case
625 // would not all be over written by the new content and the xml file
626 // would not be valid.
627 xStream = xStorage->openStreamElement( sName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
628 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
629 if (xSet.is())
631 xSet->setPropertyValue("MediaType", uno::Any(sMediaType));
633 // advise storage impl to use common encryption
634 xSet->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::Any(true) );
637 xOut = xStream->getOutputStream();
640 // set Base URL
641 uno::Reference< beans::XPropertySet > xInfoSet;
642 if( aArgs.hasElements() )
643 aArgs.getConstArray()[0] >>= xInfoSet;
644 OSL_ENSURE( xInfoSet.is(), "missing property set" );
645 if( xInfoSet.is() )
647 xInfoSet->setPropertyValue( "StreamName", uno::Any( sName ) );
650 xWriter->setOutputStream( xOut );
652 uno::Reference<document::XFilter> xFilter(
653 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
654 sComponentName , aArgs, xContext ),
655 uno::UNO_QUERY );
656 OSL_ENSURE( xFilter.is(), "can't get exporter" );
657 uno::Reference<document::XExporter> xExporter( xFilter, uno::UNO_QUERY );
658 if (xExporter.is())
659 xExporter->setSourceDocument( xModel );
661 if ( xFilter.is() )
663 ScXMLExport* pExport = static_cast<ScXMLExport*>(comphelper::getFromUnoTunnel<SvXMLExport>(xFilter));
664 pExport->SetSharedData(std::move(pSharedData));
666 // if there are sheets to copy, get the source stream
667 if ( sName == "content.xml" && lcl_HasValidStream(rDoc) && ( pExport->getExportFlags() & SvXMLExportFlags::OASIS ) )
669 // old stream is still in this file's storage - open read-only
671 // #i106854# use the document's storage directly, without a temporary SfxMedium
672 uno::Reference<embed::XStorage> xTmpStorage = rDoc.GetDocumentShell()->GetStorage();
673 uno::Reference<io::XStream> xSrcStream;
674 uno::Reference<io::XInputStream> xSrcInput;
676 // #i108978# If an embedded object is saved and no events are notified, don't use the stream
677 // because without the ...DONE events, stream positions aren't updated.
678 ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(xModel)->GetSheetSaveData();
679 if (pSheetData && pSheetData->IsInSupportedSave())
683 if (xTmpStorage.is())
684 xSrcStream = xTmpStorage->openStreamElement( sName, embed::ElementModes::READ );
685 if (xSrcStream.is())
686 xSrcInput = xSrcStream->getInputStream();
688 catch ( const uno::Exception&)
690 // stream not available (for example, password protected) - save normally (xSrcInput is null)
694 pExport->SetSourceStream( xSrcInput );
695 bRet = xFilter->filter( aDescriptor );
696 pExport->SetSourceStream( uno::Reference<io::XInputStream>() );
698 // If there was an error, reset all stream flags, so the next save attempt will use normal saving.
699 // #i110692# For embedded objects, the stream may be unavailable for one save operation (m_pAntiImpl)
700 // and become available again later. But after saving normally once, the stream positions aren't
701 // valid anymore, so the flags also have to be reset if the stream wasn't available.
702 if ( !bRet || !xSrcInput.is() )
704 SCTAB nTabCount = rDoc.GetTableCount();
705 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
706 rDoc.SetStreamValid(nTab, false);
709 else
710 bRet = xFilter->filter( aDescriptor );
712 pSharedData = pExport->ReleaseSharedData();
715 return bRet;
718 bool ScXMLImportWrapper::Export(bool bStylesOnly)
720 // Prevent all broadcasting and repaints and notification of accessibility
721 // during mass creation of captions, which is a major bottleneck and not
722 // needed during Save.
723 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
724 bool bOldLock = bool();
725 if (pDrawLayer)
727 bOldLock = pDrawLayer->isLocked();
728 pDrawLayer->setLock(true);
731 rDoc.CreateAllNoteCaptions();
733 if (pDrawLayer)
734 pDrawLayer->setLock(bOldLock);
736 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
738 uno::Reference<xml::sax::XWriter> xWriter = xml::sax::Writer::create(xContext);
740 if ( !xStorage.is() && pMedium )
741 xStorage = pMedium->GetOutputStorage();
743 OUString sFileName;
744 if (pMedium)
745 sFileName = pMedium->GetName();
746 SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
747 uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
748 { "FileName", uno::Any(sFileName) }
749 }));
751 /** property map for export info set */
752 static comphelper::PropertyMapEntry const aExportInfoMap[] =
754 { OUString("ProgressRange"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
755 { OUString("ProgressMax"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
756 { OUString("ProgressCurrent"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
757 { OUString("WrittenNumberStyles"), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
758 { OUString("UsePrettyPrinting"), 0, ::cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
759 { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
760 { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
761 { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
762 { OUString("StyleNames"), 0, cppu::UnoType<uno::Sequence<OUString>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
763 { OUString("StyleFamilies"), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
764 { OUString("TargetStorage"), 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
766 uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
768 if ( pObjSh && xStorage.is() )
770 uno::Reference<frame::XModel> xModel(pObjSh->GetModel());
771 // sorting wants to create undo actions
772 assert(SfxObjectCreateMode::STANDARD != pObjSh->GetCreateMode() || rDoc.GetDrawLayer()->IsUndoEnabled());
773 uno::Reference<drawing::XDrawPagesSupplier> const xDPS(xModel, uno::UNO_QUERY);
774 uno::Reference<container::XIndexAccess> const xDPs(xDPS->getDrawPages());
775 assert(xDPs.is());
776 for (auto i = xDPs->getCount(); 0 < i; )
778 --i;
779 uno::Reference<drawing::XShapes> const xDP(xDPs->getByIndex(i), uno::UNO_QUERY);
780 assert(xDP.is());
781 xmloff::FixZOrder(xDP,
782 [](uno::Reference<beans::XPropertySet> const& xShape)
784 sal_Int16 nLayerID(0);
785 xShape->getPropertyValue("LayerID") >>= nLayerID;
786 switch (nLayerID)
788 case sal_Int16(SC_LAYER_FRONT):
789 return 1;
790 case sal_Int16(SC_LAYER_BACK):
791 return 0;
792 case sal_Int16(SC_LAYER_INTERN):
793 return 2;
794 case sal_Int16(SC_LAYER_CONTROLS):
795 return 3;
796 case sal_Int16(SC_LAYER_HIDDEN):
797 return 1; // treat as equivalent to front
798 default:
799 O3TL_UNREACHABLE;
804 uno::Reference<task::XStatusIndicator> xStatusIndicator(GetStatusIndicator());
805 sal_Int32 nProgressRange(1000000);
806 if(xStatusIndicator.is())
807 xStatusIndicator->start(ScResId(STR_SAVE_DOC), nProgressRange);
808 xInfoSet->setPropertyValue("ProgressRange", uno::Any(nProgressRange));
810 bool bUsePrettyPrinting = officecfg::Office::Common::Save::Document::PrettyPrinting::get();
811 xInfoSet->setPropertyValue("UsePrettyPrinting", uno::Any(bUsePrettyPrinting));
813 xInfoSet->setPropertyValue( "TargetStorage", uno::Any( xStorage ) );
815 OSL_ENSURE( pMedium, "There is no medium to get MediaDescriptor from!" );
816 OUString aBaseURL = pMedium ? pMedium->GetBaseURL( true ) : OUString();
817 OUString sPropName("BaseURI");
818 xInfoSet->setPropertyValue( sPropName, uno::Any( aBaseURL ) );
820 // TODO/LATER: do not do it for embedded links
821 if( SfxObjectCreateMode::EMBEDDED == pObjSh->GetCreateMode() )
823 OUString aName("dummyObjectName");
824 if ( pMedium && pMedium->GetItemSet() )
826 const SfxStringItem* pDocHierarchItem =
827 pMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
828 if ( pDocHierarchItem )
829 aName = pDocHierarchItem->GetValue();
832 if( !aName.isEmpty() )
834 sPropName = "StreamRelPath";
835 xInfoSet->setPropertyValue( sPropName, uno::Any( aName ) );
839 OUString sTextMediaType("text/xml");
840 bool bMetaRet(pObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED);
841 bool bStylesRet (false);
842 bool bDocRet(false);
843 bool bSettingsRet(false);
844 std::unique_ptr<ScMySharedData> pSharedData;
846 bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
848 // RDF metadata: ODF >= 1.2
849 if ( !bStylesOnly && bOasis )
851 const uno::Reference< beans::XPropertySet > xPropSet( xStorage, uno::UNO_QUERY_THROW );
854 OUString aVersion;
855 if (( xPropSet->getPropertyValue("Version") >>= aVersion )
856 && aVersion != ODFVER_010_TEXT
857 && aVersion != ODFVER_011_TEXT )
859 const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
860 xModel, uno::UNO_QUERY_THROW );
861 xDMA->storeMetadataToStorage( xStorage );
864 catch ( const beans::UnknownPropertyException &)
867 catch ( const uno::Exception &)
872 // meta export
873 if (!bStylesOnly && !bMetaRet)
875 uno::Sequence<uno::Any> aMetaArgs
877 Any(xInfoSet),
878 Any(xWriter),
879 Any(xStatusIndicator)
882 SAL_INFO( "sc.filter", "meta export start" );
884 bMetaRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
885 "meta.xml",
886 sTextMediaType,
887 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisMetaExporter")
888 : OUString("com.sun.star.comp.Calc.XMLMetaExporter"),
889 aMetaArgs, pSharedData);
891 SAL_INFO( "sc.filter", "meta export end" );
894 uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
895 rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
897 if( xStorage.is() )
899 xGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Write );
900 xGraphicStorageHandler = xGraphicHelper.get();
903 auto xObjectHelper = SvXMLEmbeddedObjectHelper::Create(
904 xStorage, *pObjSh, SvXMLEmbeddedObjectHelperMode::Write);
905 uno::Reference<document::XEmbeddedObjectResolver> xObjectResolver(xObjectHelper);
907 // styles export
910 uno::Sequence<uno::Any> aStylesArgs
912 Any(xInfoSet),
913 Any(xGraphicStorageHandler),
914 Any(xStatusIndicator),
915 Any(xWriter),
916 Any(xObjectResolver)
919 SAL_INFO( "sc.filter", "styles export start" );
921 bStylesRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
922 "styles.xml",
923 sTextMediaType,
924 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisStylesExporter")
925 : OUString("com.sun.star.comp.Calc.XMLStylesExporter"),
926 aStylesArgs, pSharedData);
928 SAL_INFO( "sc.filter", "styles export end" );
931 // content export
933 if (!bStylesOnly)
935 uno::Sequence<uno::Any> aDocArgs
937 Any(xInfoSet),
938 Any(xGraphicStorageHandler),
939 Any(xStatusIndicator),
940 Any(xWriter),
941 Any(xObjectResolver)
944 SAL_INFO( "sc.filter", "content export start" );
946 bDocRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
947 "content.xml",
948 sTextMediaType,
949 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisContentExporter")
950 : OUString("com.sun.star.comp.Calc.XMLContentExporter"),
951 aDocArgs, pSharedData);
953 SAL_INFO( "sc.filter", "content export end" );
956 if( xGraphicHelper )
957 xGraphicHelper->dispose();
958 xGraphicHelper.clear();
960 if( xObjectHelper )
961 xObjectHelper->dispose();
962 xObjectHelper.clear();
964 // settings export
966 if (!bStylesOnly)
968 uno::Sequence<uno::Any> aSettingsArgs
970 Any(xInfoSet),
971 Any(xWriter),
972 Any(xStatusIndicator)
975 SAL_INFO( "sc.filter", "settings export start" );
977 bSettingsRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
978 "settings.xml",
979 sTextMediaType,
980 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisSettingsExporter")
981 : OUString("com.sun.star.comp.Calc.XMLSettingsExporter"),
982 aSettingsArgs, pSharedData);
984 SAL_INFO( "sc.filter", "settings export end" );
987 pSharedData.reset();
989 if (xStatusIndicator.is())
990 xStatusIndicator->end();
991 return bStylesRet && ((!bStylesOnly && bDocRet && bMetaRet && bSettingsRet) || bStylesOnly);
994 // later: give string descriptor as parameter for doc type
996 return false;
999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */