summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/xml/xmlwrap.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/xml/xmlwrap.cxx')
-rw-r--r--sc/source/filter/xml/xmlwrap.cxx998
1 files changed, 998 insertions, 0 deletions
diff --git a/sc/source/filter/xml/xmlwrap.cxx b/sc/source/filter/xml/xmlwrap.cxx
new file mode 100644
index 000000000..cdf2a53f7
--- /dev/null
+++ b/sc/source/filter/xml/xmlwrap.cxx
@@ -0,0 +1,998 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <officecfg/Office/Common.hxx>
+#include <vcl/errinf.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/objsh.hxx>
+#include <sot/storage.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/unreachable.hxx>
+#include <comphelper/fileformat.h>
+#include <comphelper/processfactory.hxx>
+#include <comphelper/propertysequence.hxx>
+#include <svx/dialmgr.hxx>
+#include <svx/strings.hrc>
+#include <svx/xmlgrhlp.hxx>
+#include <svtools/sfxecode.hxx>
+#include <sfx2/frame.hxx>
+#include <svl/itemset.hxx>
+#include <svl/stritem.hxx>
+#include <sfx2/sfxsids.hrc>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/xml/sax/InputSource.hpp>
+#include <com/sun/star/xml/sax/Parser.hpp>
+#include <com/sun/star/xml/sax/XFastParser.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
+#include <com/sun/star/xml/sax/SAXParseException.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <comphelper/propertysetinfo.hxx>
+#include <comphelper/genericpropertyset.hxx>
+#include <com/sun/star/packages/WrongPasswordException.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
+#include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+
+#include <sfx2/DocumentMetadataAccess.hxx>
+#include <comphelper/documentconstants.hxx>
+#include <xmloff/shapeexport.hxx>
+#include <svx/xmleohlp.hxx>
+#include <sal/log.hxx>
+#include <tools/diagnose_ex.h>
+
+#include <document.hxx>
+#include <xmlwrap.hxx>
+#include "xmlimprt.hxx"
+#include "xmlexprt.hxx"
+#include <globstr.hrc>
+#include <scresid.hxx>
+#include <scerrors.hxx>
+#include "XMLExportSharedData.hxx"
+#include <docuno.hxx>
+#include <drwlayer.hxx>
+#include <sheetdata.hxx>
+#include "XMLCodeNameProvider.hxx"
+#include <docsh.hxx>
+#include <unonames.hxx>
+
+using namespace com::sun::star;
+using namespace css::uno;
+
+ScXMLImportWrapper::ScXMLImportWrapper( ScDocShell& rDocSh, SfxMedium* pM, const uno::Reference < embed::XStorage >& xStor ) :
+ mrDocShell(rDocSh),
+ rDoc(rDocSh.GetDocument()),
+ pMedium(pM),
+ xStorage(xStor)
+{
+ OSL_ENSURE( pMedium || xStorage.is(), "ScXMLImportWrapper: Medium or Storage must be set" );
+}
+
+uno::Reference <task::XStatusIndicator> ScXMLImportWrapper::GetStatusIndicator() const
+{
+ uno::Reference<task::XStatusIndicator> xStatusIndicator;
+ if (pMedium)
+ {
+ SfxItemSet* pSet = pMedium->GetItemSet();
+ if (pSet)
+ {
+ const SfxUnoAnyItem* pItem = pSet->GetItem<SfxUnoAnyItem>(SID_PROGRESS_STATUSBAR_CONTROL);
+ if (pItem)
+ xStatusIndicator.set(pItem->GetValue(), uno::UNO_QUERY);
+ }
+ }
+ return xStatusIndicator;
+}
+
+ErrCode ScXMLImportWrapper::ImportFromComponent(const uno::Reference<uno::XComponentContext>& xContext,
+ const uno::Reference<frame::XModel>& xModel,
+ xml::sax::InputSource& aParserInput,
+ const OUString& sComponentName, const OUString& sDocName,
+ const uno::Sequence<uno::Any>& aArgs,
+ bool bMustBeSuccessful)
+{
+ uno::Reference < io::XStream > xDocStream;
+ if ( !xStorage.is() && pMedium )
+ xStorage = pMedium->GetStorage();
+
+ bool bEncrypted = false;
+ OUString sStream(sDocName);
+ if( xStorage.is() )
+ {
+ try
+ {
+ if ( xStorage->hasByName(sDocName) && xStorage->isStreamElement( sDocName) )
+ xDocStream = xStorage->openStreamElement( sDocName, embed::ElementModes::READ );
+ else
+ return ERRCODE_NONE;
+
+ aParserInput.aInputStream = xDocStream->getInputStream();
+ uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
+
+ uno::Any aAny = xSet->getPropertyValue("Encrypted");
+ aAny >>= bEncrypted;
+ }
+ catch( const packages::WrongPasswordException& )
+ {
+ return ERRCODE_SFX_WRONGPASSWORD;
+ }
+ catch( const packages::zip::ZipIOException& )
+ {
+ return ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch( const uno::Exception& )
+ {
+ return SCERR_IMPORT_UNKNOWN;
+ }
+ }
+ else
+ return SCERR_IMPORT_UNKNOWN;
+
+ // set Base URL
+ uno::Reference< beans::XPropertySet > xInfoSet;
+ if( aArgs.hasElements() )
+ aArgs.getConstArray()[0] >>= xInfoSet;
+ OSL_ENSURE( xInfoSet.is(), "missing property set" );
+ if( xInfoSet.is() )
+ {
+ xInfoSet->setPropertyValue( "StreamName", uno::Any( sStream ) );
+ }
+
+ ErrCode nReturn = ERRCODE_NONE;
+ rDoc.SetRangeOverflowType(ERRCODE_NONE); // is modified by the importer if limits are exceeded
+
+ uno::Reference<XInterface> xImportInterface =
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ sComponentName, aArgs, xContext );
+ SAL_WARN_IF( !xImportInterface, "sc", "can't get Calc importer " << sComponentName );
+ uno::Reference<document::XImporter> xImporter( xImportInterface, uno::UNO_QUERY );
+ if (xImporter.is())
+ xImporter->setTargetDocument( xModel );
+
+ ScXMLImport* pImporterImpl = dynamic_cast<ScXMLImport*>(xImporter.get());
+ if (pImporterImpl)
+ pImporterImpl->SetPostProcessData(&maPostProcessData);
+
+ // connect parser and filter
+ try
+ {
+ // xImportInterface is either ScXMLImport or an XMLTransformer subclass.
+ // ScXMLImport implements XFastParser, but XMLTransformer only implements XExtendedDocumentHandler
+
+ uno::Reference< xml::sax::XFastParser > xFastParser(xImportInterface, uno::UNO_QUERY);
+ if (xFastParser)
+ xFastParser->parseStream( aParserInput );
+ else
+ {
+ uno::Reference<xml::sax::XParser> xParser = xml::sax::Parser::create(xContext);
+ uno::Reference<css::xml::sax::XDocumentHandler> xDocumentHandler(xImportInterface, uno::UNO_QUERY);
+ xParser->setDocumentHandler( xDocumentHandler );
+ xParser->parseStream( aParserInput );
+ }
+ }
+ catch( const xml::sax::SAXParseException& r )
+ {
+ css::uno::Any ex( cppu::getCaughtException() );
+ // sax parser sends wrapped exceptions,
+ // try to find the original one
+ xml::sax::SAXException aSaxEx = *static_cast<xml::sax::SAXException const *>(&r);
+ bool bTryChild = true;
+
+ while( bTryChild )
+ {
+ xml::sax::SAXException aTmp;
+ if ( aSaxEx.WrappedException >>= aTmp )
+ aSaxEx = aTmp;
+ else
+ bTryChild = false;
+ }
+
+ packages::zip::ZipIOException aBrokenPackage;
+ if ( aSaxEx.WrappedException >>= aBrokenPackage )
+ return ERRCODE_IO_BROKENPACKAGE;
+ else if( bEncrypted )
+ nReturn = ERRCODE_SFX_WRONGPASSWORD;
+ else
+ {
+ SAL_WARN("sc.filter", "SAX parse exception caught while importing: " << exceptionToString(ex));
+
+ OUString sErr = OUString::number( r.LineNumber ) +
+ "," +
+ OUString::number( r.ColumnNumber );
+
+ if( !sDocName.isEmpty() )
+ {
+ nReturn = *new TwoStringErrorInfo(
+ (bMustBeSuccessful ? SCERR_IMPORT_FILE_ROWCOL
+ : SCWARN_IMPORT_FILE_ROWCOL),
+ sDocName, sErr,
+ DialogMask::ButtonsOk | DialogMask::MessageError );
+ }
+ else
+ {
+ OSL_ENSURE( bMustBeSuccessful, "Warnings are not supported" );
+ nReturn = *new StringErrorInfo( SCERR_IMPORT_FORMAT_ROWCOL, sErr,
+ DialogMask::ButtonsOk | DialogMask::MessageError );
+ }
+ }
+ }
+ catch( const xml::sax::SAXException& r )
+ {
+ css::uno::Any ex( cppu::getCaughtException() );
+ packages::zip::ZipIOException aBrokenPackage;
+ if ( r.WrappedException >>= aBrokenPackage )
+ return ERRCODE_IO_BROKENPACKAGE;
+ else if( bEncrypted )
+ nReturn = ERRCODE_SFX_WRONGPASSWORD;
+ else
+ {
+ SAL_WARN("sc.filter", "SAX exception caught while importing: " << exceptionToString(ex));
+
+ nReturn = SCERR_IMPORT_FORMAT;
+ }
+ }
+ catch( const packages::zip::ZipIOException& )
+ {
+ TOOLS_WARN_EXCEPTION("sc.filter", "Zip exception caught while importing");
+
+ nReturn = ERRCODE_IO_BROKENPACKAGE;
+ }
+ catch( const io::IOException& )
+ {
+ TOOLS_WARN_EXCEPTION("sc.filter", "IO exception caught while importing");
+
+ nReturn = SCERR_IMPORT_OPEN;
+ }
+ catch( const uno::Exception& )
+ {
+ TOOLS_WARN_EXCEPTION("sc.filter", "uno exception caught while importing");
+
+ nReturn = SCERR_IMPORT_UNKNOWN;
+ }
+
+ // #i31130# Can't use getImplementation here to get the ScXMLImport from xDocHandler,
+ // because when OOo 1.x files are loaded, xDocHandler is the OOo2OasisTransformer.
+ // So the overflow warning ErrorCode is now stored in the document.
+ // Export works differently, there getImplementation still works.
+
+ if (rDoc.HasRangeOverflow() && !nReturn)
+ nReturn = rDoc.GetRangeOverflowType();
+
+ // success!
+ return nReturn;
+}
+
+bool ScXMLImportWrapper::Import( ImportFlags nMode, ErrCode& rError )
+{
+ uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
+
+ xml::sax::InputSource aParserInput;
+ if (pMedium)
+ aParserInput.sSystemId = pMedium->GetName();
+
+ if ( !xStorage.is() && pMedium )
+ xStorage = pMedium->GetStorage();
+
+ // get filter
+ uno::Reference<frame::XModel> xModel = mrDocShell.GetModel();
+
+ /** property map for export info set */
+ static comphelper::PropertyMapEntry const aImportInfoMap[] =
+ {
+ { OUString("ProgressRange"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ProgressMax"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ProgressCurrent"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("NumberStyles"), 0, cppu::UnoType<container::XNameAccess>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("PrivateData"), 0, cppu::UnoType<uno::XInterface>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("BuildId"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("VBACompatibilityMode"), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("ScriptConfiguration"), 0, cppu::UnoType<container::XNameAccess>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("OrganizerMode"), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("SourceStorage"), 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString(SC_UNO_ODS_LOCK_SOLAR_MUTEX), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString(SC_UNO_ODS_IMPORT_STYLES), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ };
+ uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aImportInfoMap ) ) );
+
+ // No need to lock solar mutex when calling from the wrapper.
+ xInfoSet->setPropertyValue(SC_UNO_ODS_LOCK_SOLAR_MUTEX, uno::Any(false));
+
+ // ---- get BuildId from parent container if available
+
+ uno::Reference< container::XChild > xChild( xModel, uno::UNO_QUERY );
+ if( xChild.is() )
+ {
+ uno::Reference< beans::XPropertySet > xParentSet( xChild->getParent(), uno::UNO_QUERY );
+ if( xParentSet.is() )
+ {
+ uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xParentSet->getPropertySetInfo() );
+ OUString sPropName("BuildId" );
+ if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(sPropName) )
+ {
+ xInfoSet->setPropertyValue( sPropName, xParentSet->getPropertyValue(sPropName) );
+ }
+ }
+ }
+
+ uno::Reference<task::XStatusIndicator> xStatusIndicator = GetStatusIndicator();
+ if (xStatusIndicator.is())
+ {
+ sal_Int32 nProgressRange(1000000);
+ xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
+ xInfoSet->setPropertyValue("ProgressRange", uno::Any(nProgressRange));
+ }
+
+ // Set base URI
+ OSL_ENSURE( pMedium, "There is no medium to get MediaDescriptor from!" );
+ OUString aBaseURL = pMedium ? pMedium->GetBaseURL() : OUString();
+ // needed for relative URLs, but in clipboard copy/paste there may be none
+ SAL_INFO_IF(aBaseURL.isEmpty(), "sc.filter", "ScXMLImportWrapper: no base URL");
+ OUString sPropName("BaseURI");
+ xInfoSet->setPropertyValue( sPropName, uno::Any( aBaseURL ) );
+
+ // TODO/LATER: do not do it for embedded links
+ OUString aName;
+ if (SfxObjectCreateMode::EMBEDDED == mrDocShell.GetCreateMode())
+ {
+ if ( pMedium && pMedium->GetItemSet() )
+ {
+ const SfxStringItem* pDocHierarchItem =
+ pMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
+ if ( pDocHierarchItem )
+ aName = pDocHierarchItem->GetValue();
+ }
+ else
+ aName = "dummyObjectName";
+
+ if( !aName.isEmpty() )
+ {
+ sPropName = "StreamRelPath";
+ xInfoSet->setPropertyValue( sPropName, uno::Any( aName ) );
+ }
+ }
+
+ if (mrDocShell.GetCreateMode() == SfxObjectCreateMode::ORGANIZER)
+ xInfoSet->setPropertyValue("OrganizerMode", uno::Any(true));
+
+ xInfoSet->setPropertyValue( "SourceStorage", uno::Any( xStorage ) );
+
+ bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
+
+ if ((nMode & ImportFlags::Metadata) && bOasis)
+ {
+ // RDF metadata: ODF >= 1.2
+ try
+ {
+ const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
+ xModel, uno::UNO_QUERY_THROW );
+ const uno::Reference< rdf::XURI > xBaseURI(
+ ::sfx2::createBaseURI( xContext, xModel, aBaseURL, aName ) );
+ uno::Reference<task::XInteractionHandler> xHandler =
+ mrDocShell.GetMedium()->GetInteractionHandler();
+ xDMA->loadMetadataFromStorage( xStorage, xBaseURI, xHandler );
+ }
+ catch ( const lang::WrappedTargetException & e)
+ {
+ ucb::InteractiveAugmentedIOException iaioe;
+ if ( e.TargetException >>= iaioe )
+ {
+ rError = SCERR_IMPORT_UNKNOWN;
+ }
+ else
+ {
+ rError = SCWARN_IMPORT_FEATURES_LOST;
+ }
+ }
+ catch ( const uno::Exception &)
+ {
+ rError = SCWARN_IMPORT_FEATURES_LOST;
+ }
+ }
+
+ // #i103539#: always read meta.xml for generator
+ ErrCode nMetaRetval(ERRCODE_NONE);
+ if (nMode & ImportFlags::Metadata)
+ {
+ uno::Sequence<uno::Any> aMetaArgs { Any(xInfoSet) };
+
+ SAL_INFO( "sc.filter", "meta import start" );
+
+ nMetaRetval = ImportFromComponent(
+ xContext, xModel, aParserInput,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisMetaImporter")
+ : OUString("com.sun.star.comp.Calc.XMLMetaImporter"),
+ "meta.xml", aMetaArgs, false);
+
+ SAL_INFO( "sc.filter", "meta import end" );
+ }
+
+ rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
+ uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
+
+ uno::Reference< document::XEmbeddedObjectResolver > xObjectResolver;
+ rtl::Reference<SvXMLEmbeddedObjectHelper> xObjectHelper;
+
+ if( xStorage.is() )
+ {
+ xGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Read );
+ xGraphicStorageHandler = xGraphicHelper.get();
+
+ xObjectHelper = SvXMLEmbeddedObjectHelper::Create(xStorage, mrDocShell, SvXMLEmbeddedObjectHelperMode::Read);
+ xObjectResolver = xObjectHelper.get();
+ }
+ uno::Sequence<uno::Any> aStylesArgs
+ {
+ Any(xInfoSet),
+ Any(xGraphicStorageHandler),
+ Any(xStatusIndicator),
+ Any(xObjectResolver)
+ };
+
+ ErrCode nSettingsRetval(ERRCODE_NONE);
+ if (nMode & ImportFlags::Settings)
+ {
+ // Settings must be loaded first because of the printer setting,
+ // which is needed in the page styles (paper tray).
+
+ uno::Sequence<uno::Any> aSettingsArgs { Any(xInfoSet) };
+
+ SAL_INFO( "sc.filter", "settings import start" );
+
+ nSettingsRetval = ImportFromComponent(
+ xContext, xModel, aParserInput,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisSettingsImporter")
+ : OUString("com.sun.star.comp.Calc.XMLSettingsImporter"),
+ "settings.xml", aSettingsArgs, false);
+
+ SAL_INFO( "sc.filter", "settings import end" );
+ }
+
+ ErrCode nStylesRetval(ERRCODE_NONE);
+ if (nMode & ImportFlags::Styles)
+ {
+ SAL_INFO( "sc.filter", "styles import start" );
+
+ nStylesRetval = ImportFromComponent(xContext, xModel, aParserInput,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisStylesImporter")
+ : OUString("com.sun.star.comp.Calc.XMLStylesImporter"),
+ "styles.xml",
+ aStylesArgs, true);
+
+ SAL_INFO( "sc.filter", "styles import end" );
+ }
+
+ ErrCode nDocRetval(ERRCODE_NONE);
+ if (nMode & ImportFlags::Content)
+ {
+ if (mrDocShell.GetCreateMode() == SfxObjectCreateMode::INTERNAL)
+ // We only need to import content for external link cache document.
+ xInfoSet->setPropertyValue(SC_UNO_ODS_IMPORT_STYLES, uno::Any(false));
+
+ uno::Sequence<uno::Any> aDocArgs
+ {
+ Any(xInfoSet),
+ Any(xGraphicStorageHandler),
+ Any(xStatusIndicator),
+ Any(xObjectResolver)
+ };
+
+ SAL_INFO( "sc.filter", "content import start" );
+
+ nDocRetval = ImportFromComponent(xContext, xModel, aParserInput,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisContentImporter")
+ : OUString("com.sun.star.comp.Calc.XMLContentImporter"),
+ "content.xml",
+ aDocArgs,
+ true);
+
+ SAL_INFO( "sc.filter", "content import end" );
+ }
+ if( xGraphicHelper.is() )
+ xGraphicHelper->dispose();
+ xGraphicHelper.clear();
+
+ if( xObjectHelper.is() )
+ xObjectHelper->dispose();
+ xObjectHelper.clear();
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+
+ bool bRet = false;
+ if (nDocRetval)
+ {
+ rError = nDocRetval;
+ if (nDocRetval == SCWARN_IMPORT_RANGE_OVERFLOW ||
+ nDocRetval == SCWARN_IMPORT_ROW_OVERFLOW ||
+ nDocRetval == SCWARN_IMPORT_COLUMN_OVERFLOW ||
+ nDocRetval == SCWARN_IMPORT_SHEET_OVERFLOW)
+ bRet = true;
+ }
+ else if (nStylesRetval)
+ rError = nStylesRetval;
+ else if (nMetaRetval)
+ rError = nMetaRetval;
+ else if (nSettingsRetval)
+ rError = nSettingsRetval;
+ else
+ bRet = true;
+
+ ::svx::DropUnusedNamedItems(xModel);
+
+ // set BuildId on XModel for later OLE object loading
+ if( xInfoSet.is() )
+ {
+ uno::Reference< beans::XPropertySet > xModelSet( xModel, uno::UNO_QUERY );
+ if( xModelSet.is() )
+ {
+ uno::Reference< beans::XPropertySetInfo > xModelSetInfo( xModelSet->getPropertySetInfo() );
+ OUString sBuildPropName("BuildId" );
+ if( xModelSetInfo.is() && xModelSetInfo->hasPropertyByName(sBuildPropName) )
+ {
+ xModelSet->setPropertyValue( sBuildPropName, xInfoSet->getPropertyValue(sBuildPropName) );
+ }
+ }
+
+ // Set Code Names
+ uno::Any aAny = xInfoSet->getPropertyValue("ScriptConfiguration");
+ uno::Reference <container::XNameAccess> xCodeNameAccess;
+ if( aAny >>= xCodeNameAccess )
+ XMLCodeNameProvider::set( xCodeNameAccess, &rDoc );
+
+ // VBA compatibility
+ bool bVBACompat = false;
+ if ( (xInfoSet->getPropertyValue("VBACompatibilityMode") >>= bVBACompat) && bVBACompat )
+ {
+ /* Set library container to VBA compatibility mode, this
+ forces loading the Basic project, which in turn creates the
+ VBA Globals object and does all related initialization. */
+ if ( xModelSet.is() ) try
+ {
+ uno::Reference< script::vba::XVBACompatibility > xVBACompat( xModelSet->getPropertyValue(
+ "BasicLibraries" ), uno::UNO_QUERY_THROW );
+ xVBACompat->setVBACompatibilityMode( true );
+ }
+ catch( const uno::Exception& )
+ {
+ }
+ }
+ }
+
+ // Don't test bStylesRetval and bMetaRetval, because it could be an older file which not contain such streams
+ return bRet;//!bStylesOnly ? bDocRetval : bStylesRetval;
+}
+
+static bool lcl_HasValidStream(const ScDocument& rDoc)
+{
+ SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
+ if ( pObjSh->IsDocShared() )
+ return false; // never copy stream from shared file
+
+ // don't read remote file again
+ // (could instead re-use medium directly in that case)
+ SfxMedium* pSrcMed = rDoc.GetDocumentShell()->GetMedium();
+ if ( !pSrcMed || pSrcMed->IsRemote() )
+ return false;
+
+ SCTAB nTabCount = rDoc.GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
+ if (rDoc.IsStreamValid(nTab))
+ return true;
+ return false;
+}
+
+bool ScXMLImportWrapper::ExportToComponent(const uno::Reference<uno::XComponentContext>& xContext,
+ const uno::Reference<frame::XModel>& xModel, const uno::Reference<xml::sax::XWriter>& xWriter,
+ const uno::Sequence<beans::PropertyValue>& aDescriptor, const OUString& sName,
+ const OUString& sMediaType, const OUString& sComponentName,
+ const uno::Sequence<uno::Any>& aArgs, std::unique_ptr<ScMySharedData>& pSharedData)
+{
+ bool bRet(false);
+ uno::Reference<io::XOutputStream> xOut;
+ uno::Reference<io::XStream> xStream;
+
+ if ( !xStorage.is() && pMedium )
+ xStorage = pMedium->GetOutputStorage();
+
+ if( xStorage.is() )
+ {
+ // #96807#; trunc stream before use, because it could be an existing stream
+ // and the new content could be shorter than the old content. In this case
+ // would not all be over written by the new content and the xml file
+ // would not be valid.
+ xStream = xStorage->openStreamElement( sName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
+ uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
+ if (xSet.is())
+ {
+ xSet->setPropertyValue("MediaType", uno::Any(sMediaType));
+
+ // advise storage impl to use common encryption
+ xSet->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::Any(true) );
+ }
+
+ xOut = xStream->getOutputStream();
+ }
+
+ // set Base URL
+ uno::Reference< beans::XPropertySet > xInfoSet;
+ if( aArgs.hasElements() )
+ aArgs.getConstArray()[0] >>= xInfoSet;
+ OSL_ENSURE( xInfoSet.is(), "missing property set" );
+ if( xInfoSet.is() )
+ {
+ xInfoSet->setPropertyValue( "StreamName", uno::Any( sName ) );
+ }
+
+ xWriter->setOutputStream( xOut );
+
+ uno::Reference<document::XFilter> xFilter(
+ xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ sComponentName , aArgs, xContext ),
+ uno::UNO_QUERY );
+ OSL_ENSURE( xFilter.is(), "can't get exporter" );
+ uno::Reference<document::XExporter> xExporter( xFilter, uno::UNO_QUERY );
+ if (xExporter.is())
+ xExporter->setSourceDocument( xModel );
+
+ if ( xFilter.is() )
+ {
+ ScXMLExport* pExport = static_cast<ScXMLExport*>(comphelper::getFromUnoTunnel<SvXMLExport>(xFilter));
+ pExport->SetSharedData(std::move(pSharedData));
+
+ // if there are sheets to copy, get the source stream
+ if ( sName == "content.xml" && lcl_HasValidStream(rDoc) && ( pExport->getExportFlags() & SvXMLExportFlags::OASIS ) )
+ {
+ // old stream is still in this file's storage - open read-only
+
+ // #i106854# use the document's storage directly, without a temporary SfxMedium
+ uno::Reference<embed::XStorage> xTmpStorage = rDoc.GetDocumentShell()->GetStorage();
+ uno::Reference<io::XStream> xSrcStream;
+ uno::Reference<io::XInputStream> xSrcInput;
+
+ // #i108978# If an embedded object is saved and no events are notified, don't use the stream
+ // because without the ...DONE events, stream positions aren't updated.
+ ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(xModel)->GetSheetSaveData();
+ if (pSheetData && pSheetData->IsInSupportedSave())
+ {
+ try
+ {
+ if (xTmpStorage.is())
+ xSrcStream = xTmpStorage->openStreamElement( sName, embed::ElementModes::READ );
+ if (xSrcStream.is())
+ xSrcInput = xSrcStream->getInputStream();
+ }
+ catch ( const uno::Exception&)
+ {
+ // stream not available (for example, password protected) - save normally (xSrcInput is null)
+ }
+ }
+
+ pExport->SetSourceStream( xSrcInput );
+ bRet = xFilter->filter( aDescriptor );
+ pExport->SetSourceStream( uno::Reference<io::XInputStream>() );
+
+ // If there was an error, reset all stream flags, so the next save attempt will use normal saving.
+ // #i110692# For embedded objects, the stream may be unavailable for one save operation (m_pAntiImpl)
+ // and become available again later. But after saving normally once, the stream positions aren't
+ // valid anymore, so the flags also have to be reset if the stream wasn't available.
+ if ( !bRet || !xSrcInput.is() )
+ {
+ SCTAB nTabCount = rDoc.GetTableCount();
+ for (SCTAB nTab=0; nTab<nTabCount; nTab++)
+ rDoc.SetStreamValid(nTab, false);
+ }
+ }
+ else
+ bRet = xFilter->filter( aDescriptor );
+
+ pSharedData = pExport->ReleaseSharedData();
+ }
+
+ return bRet;
+}
+
+bool ScXMLImportWrapper::Export(bool bStylesOnly)
+{
+ // Prevent all broadcasting and repaints and notification of accessibility
+ // during mass creation of captions, which is a major bottleneck and not
+ // needed during Save.
+ ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
+ bool bOldLock = bool();
+ if (pDrawLayer)
+ {
+ bOldLock = pDrawLayer->isLocked();
+ pDrawLayer->setLock(true);
+ }
+
+ rDoc.CreateAllNoteCaptions();
+
+ if (pDrawLayer)
+ pDrawLayer->setLock(bOldLock);
+
+ uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+
+ uno::Reference<xml::sax::XWriter> xWriter = xml::sax::Writer::create(xContext);
+
+ if ( !xStorage.is() && pMedium )
+ xStorage = pMedium->GetOutputStorage();
+
+ OUString sFileName;
+ if (pMedium)
+ sFileName = pMedium->GetName();
+ SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
+ uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
+ { "FileName", uno::Any(sFileName) }
+ }));
+
+ /** property map for export info set */
+ static comphelper::PropertyMapEntry const aExportInfoMap[] =
+ {
+ { OUString("ProgressRange"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ProgressMax"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("ProgressCurrent"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("WrittenNumberStyles"), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("UsePrettyPrinting"), 0, ::cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
+ { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StyleNames"), 0, cppu::UnoType<uno::Sequence<OUString>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("StyleFamilies"), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ { OUString("TargetStorage"), 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
+ };
+ uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
+
+ if ( pObjSh && xStorage.is() )
+ {
+ uno::Reference<frame::XModel> xModel(pObjSh->GetModel());
+ // sorting wants to create undo actions
+ assert(SfxObjectCreateMode::STANDARD != pObjSh->GetCreateMode() || rDoc.GetDrawLayer()->IsUndoEnabled());
+ uno::Reference<drawing::XDrawPagesSupplier> const xDPS(xModel, uno::UNO_QUERY);
+ uno::Reference<container::XIndexAccess> const xDPs(xDPS->getDrawPages());
+ assert(xDPs.is());
+ for (auto i = xDPs->getCount(); 0 < i; )
+ {
+ --i;
+ uno::Reference<drawing::XShapes> const xDP(xDPs->getByIndex(i), uno::UNO_QUERY);
+ assert(xDP.is());
+ xmloff::FixZOrder(xDP,
+ [](uno::Reference<beans::XPropertySet> const& xShape)
+ {
+ sal_Int16 nLayerID(0);
+ xShape->getPropertyValue("LayerID") >>= nLayerID;
+ switch (nLayerID)
+ {
+ case sal_Int16(SC_LAYER_FRONT):
+ return 1;
+ case sal_Int16(SC_LAYER_BACK):
+ return 0;
+ case sal_Int16(SC_LAYER_INTERN):
+ return 2;
+ case sal_Int16(SC_LAYER_CONTROLS):
+ return 3;
+ case sal_Int16(SC_LAYER_HIDDEN):
+ return 1; // treat as equivalent to front
+ default:
+ O3TL_UNREACHABLE;
+ }
+ });
+ }
+
+ uno::Reference<task::XStatusIndicator> xStatusIndicator(GetStatusIndicator());
+ sal_Int32 nProgressRange(1000000);
+ if(xStatusIndicator.is())
+ xStatusIndicator->start(ScResId(STR_SAVE_DOC), nProgressRange);
+ xInfoSet->setPropertyValue("ProgressRange", uno::Any(nProgressRange));
+
+ bool bUsePrettyPrinting = officecfg::Office::Common::Save::Document::PrettyPrinting::get();
+ xInfoSet->setPropertyValue("UsePrettyPrinting", uno::Any(bUsePrettyPrinting));
+
+ xInfoSet->setPropertyValue( "TargetStorage", uno::Any( xStorage ) );
+
+ OSL_ENSURE( pMedium, "There is no medium to get MediaDescriptor from!" );
+ OUString aBaseURL = pMedium ? pMedium->GetBaseURL( true ) : OUString();
+ OUString sPropName("BaseURI");
+ xInfoSet->setPropertyValue( sPropName, uno::Any( aBaseURL ) );
+
+ // TODO/LATER: do not do it for embedded links
+ if( SfxObjectCreateMode::EMBEDDED == pObjSh->GetCreateMode() )
+ {
+ OUString aName("dummyObjectName");
+ if ( pMedium && pMedium->GetItemSet() )
+ {
+ const SfxStringItem* pDocHierarchItem =
+ pMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME);
+ if ( pDocHierarchItem )
+ aName = pDocHierarchItem->GetValue();
+ }
+
+ if( !aName.isEmpty() )
+ {
+ sPropName = "StreamRelPath";
+ xInfoSet->setPropertyValue( sPropName, uno::Any( aName ) );
+ }
+ }
+
+ OUString sTextMediaType("text/xml");
+ bool bMetaRet(pObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED);
+ bool bStylesRet (false);
+ bool bDocRet(false);
+ bool bSettingsRet(false);
+ std::unique_ptr<ScMySharedData> pSharedData;
+
+ bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
+
+ // RDF metadata: ODF >= 1.2
+ if ( !bStylesOnly && bOasis )
+ {
+ const uno::Reference< beans::XPropertySet > xPropSet( xStorage, uno::UNO_QUERY_THROW );
+ try
+ {
+ OUString aVersion;
+ if (( xPropSet->getPropertyValue("Version") >>= aVersion )
+ && aVersion != ODFVER_010_TEXT
+ && aVersion != ODFVER_011_TEXT )
+ {
+ const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
+ xModel, uno::UNO_QUERY_THROW );
+ xDMA->storeMetadataToStorage( xStorage );
+ }
+ }
+ catch ( const beans::UnknownPropertyException &)
+ {
+ }
+ catch ( const uno::Exception &)
+ {
+ }
+ }
+
+ // meta export
+ if (!bStylesOnly && !bMetaRet)
+ {
+ uno::Sequence<uno::Any> aMetaArgs
+ {
+ Any(xInfoSet),
+ Any(xWriter),
+ Any(xStatusIndicator)
+ };
+
+ SAL_INFO( "sc.filter", "meta export start" );
+
+ bMetaRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
+ "meta.xml",
+ sTextMediaType,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisMetaExporter")
+ : OUString("com.sun.star.comp.Calc.XMLMetaExporter"),
+ aMetaArgs, pSharedData);
+
+ SAL_INFO( "sc.filter", "meta export end" );
+ }
+
+ uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
+ rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
+
+ if( xStorage.is() )
+ {
+ xGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Write );
+ xGraphicStorageHandler = xGraphicHelper.get();
+ }
+
+ auto xObjectHelper = SvXMLEmbeddedObjectHelper::Create(
+ xStorage, *pObjSh, SvXMLEmbeddedObjectHelperMode::Write);
+ uno::Reference<document::XEmbeddedObjectResolver> xObjectResolver(xObjectHelper);
+
+ // styles export
+
+ {
+ uno::Sequence<uno::Any> aStylesArgs
+ {
+ Any(xInfoSet),
+ Any(xGraphicStorageHandler),
+ Any(xStatusIndicator),
+ Any(xWriter),
+ Any(xObjectResolver)
+ };
+
+ SAL_INFO( "sc.filter", "styles export start" );
+
+ bStylesRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
+ "styles.xml",
+ sTextMediaType,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisStylesExporter")
+ : OUString("com.sun.star.comp.Calc.XMLStylesExporter"),
+ aStylesArgs, pSharedData);
+
+ SAL_INFO( "sc.filter", "styles export end" );
+ }
+
+ // content export
+
+ if (!bStylesOnly)
+ {
+ uno::Sequence<uno::Any> aDocArgs
+ {
+ Any(xInfoSet),
+ Any(xGraphicStorageHandler),
+ Any(xStatusIndicator),
+ Any(xWriter),
+ Any(xObjectResolver)
+ };
+
+ SAL_INFO( "sc.filter", "content export start" );
+
+ bDocRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
+ "content.xml",
+ sTextMediaType,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisContentExporter")
+ : OUString("com.sun.star.comp.Calc.XMLContentExporter"),
+ aDocArgs, pSharedData);
+
+ SAL_INFO( "sc.filter", "content export end" );
+ }
+
+ if( xGraphicHelper )
+ xGraphicHelper->dispose();
+ xGraphicHelper.clear();
+
+ if( xObjectHelper )
+ xObjectHelper->dispose();
+ xObjectHelper.clear();
+
+ // settings export
+
+ if (!bStylesOnly)
+ {
+ uno::Sequence<uno::Any> aSettingsArgs
+ {
+ Any(xInfoSet),
+ Any(xWriter),
+ Any(xStatusIndicator)
+ };
+
+ SAL_INFO( "sc.filter", "settings export start" );
+
+ bSettingsRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
+ "settings.xml",
+ sTextMediaType,
+ bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisSettingsExporter")
+ : OUString("com.sun.star.comp.Calc.XMLSettingsExporter"),
+ aSettingsArgs, pSharedData);
+
+ SAL_INFO( "sc.filter", "settings export end" );
+ }
+
+ pSharedData.reset();
+
+ if (xStatusIndicator.is())
+ xStatusIndicator->end();
+ return bStylesRet && ((!bStylesOnly && bDocRet && bMetaRet && bSettingsRet) || bStylesOnly);
+ }
+
+ // later: give string descriptor as parameter for doc type
+
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */