Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / sc / source / filter / xml / xmlwrap.cxx
bloba425e42140603ebc2dabc74abd25bc8b1321a270
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 <vcl/errinf.hxx>
21 #include <sfx2/docfile.hxx>
22 #include <sfx2/objsh.hxx>
23 #include <sot/storage.hxx>
24 #include <osl/diagnose.h>
25 #include <comphelper/fileformat.h>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/propertysequence.hxx>
28 #include <svx/dialmgr.hxx>
29 #include <svx/strings.hrc>
30 #include <svx/xmlgrhlp.hxx>
31 #include <svtools/sfxecode.hxx>
32 #include <sfx2/frame.hxx>
33 #include <svl/itemset.hxx>
34 #include <svl/stritem.hxx>
35 #include <sfx2/sfxsids.hrc>
36 #include <com/sun/star/container/XChild.hpp>
37 #include <com/sun/star/beans/XPropertySetInfo.hpp>
38 #include <com/sun/star/frame/XTransientDocumentsDocumentContentFactory.hpp>
39 #include <com/sun/star/xml/sax/InputSource.hpp>
40 #include <com/sun/star/xml/sax/Parser.hpp>
41 #include <com/sun/star/xml/sax/XFastParser.hpp>
42 #include <com/sun/star/xml/sax/Writer.hpp>
43 #include <com/sun/star/xml/sax/SAXParseException.hpp>
44 #include <com/sun/star/frame/XModel.hpp>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <comphelper/propertysetinfo.hxx>
47 #include <comphelper/genericpropertyset.hxx>
48 #include <com/sun/star/packages/WrongPasswordException.hpp>
49 #include <com/sun/star/packages/zip/ZipIOException.hpp>
50 #include <com/sun/star/embed/ElementModes.hpp>
51 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
52 #include <com/sun/star/rdf/XDocumentMetadataAccess.hpp>
53 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
54 #include <com/sun/star/task/XStatusIndicator.hpp>
56 #include <sfx2/DocumentMetadataAccess.hxx>
57 #include <comphelper/documentconstants.hxx>
58 #include <svx/xmleohlp.hxx>
59 #include <sal/log.hxx>
60 #include <unotools/saveopt.hxx>
61 #include <tools/diagnose_ex.h>
63 #include <document.hxx>
64 #include <xmlwrap.hxx>
65 #include "xmlimprt.hxx"
66 #include "xmlexprt.hxx"
67 #include <globstr.hrc>
68 #include <scresid.hxx>
69 #include <scerrors.hxx>
70 #include "XMLExportSharedData.hxx"
71 #include <docuno.hxx>
72 #include <drwlayer.hxx>
73 #include <sheetdata.hxx>
74 #include "XMLCodeNameProvider.hxx"
75 #include <docsh.hxx>
76 #include <unonames.hxx>
78 using namespace com::sun::star;
79 using namespace css::uno;
81 ScXMLImportWrapper::ScXMLImportWrapper( ScDocShell& rDocSh, SfxMedium* pM, const uno::Reference < embed::XStorage >& xStor ) :
82 mrDocShell(rDocSh),
83 rDoc(rDocSh.GetDocument()),
84 pMedium(pM),
85 xStorage(xStor)
87 OSL_ENSURE( pMedium || xStorage.is(), "ScXMLImportWrapper: Medium or Storage must be set" );
90 uno::Reference <task::XStatusIndicator> ScXMLImportWrapper::GetStatusIndicator() const
92 uno::Reference<task::XStatusIndicator> xStatusIndicator;
93 if (pMedium)
95 SfxItemSet* pSet = pMedium->GetItemSet();
96 if (pSet)
98 const SfxUnoAnyItem* pItem = pSet->GetItem<SfxUnoAnyItem>(SID_PROGRESS_STATUSBAR_CONTROL);
99 if (pItem)
100 xStatusIndicator.set(pItem->GetValue(), uno::UNO_QUERY);
103 return xStatusIndicator;
106 ErrCode ScXMLImportWrapper::ImportFromComponent(const uno::Reference<uno::XComponentContext>& xContext,
107 const uno::Reference<frame::XModel>& xModel, const uno::Reference<xml::sax::XParser>& xParser,
108 xml::sax::InputSource& aParserInput,
109 const OUString& sComponentName, const OUString& sDocName,
110 const OUString& sOldDocName, const uno::Sequence<uno::Any>& aArgs,
111 bool bMustBeSuccessfull)
113 uno::Reference < io::XStream > xDocStream;
114 if ( !xStorage.is() && pMedium )
115 xStorage = pMedium->GetStorage();
117 bool bEncrypted = false;
118 OUString sStream(sDocName);
119 if( xStorage.is() )
123 if ( xStorage->hasByName(sDocName) && xStorage->isStreamElement( sDocName) )
124 xDocStream = xStorage->openStreamElement( sDocName, embed::ElementModes::READ );
125 else if (!sOldDocName.isEmpty() && xStorage->hasByName(sOldDocName) && xStorage->isStreamElement( sOldDocName) )
127 xDocStream = xStorage->openStreamElement( sOldDocName, embed::ElementModes::READ );
128 sStream = sOldDocName;
130 else
131 return ERRCODE_NONE;
133 aParserInput.aInputStream = xDocStream->getInputStream();
134 uno::Reference < beans::XPropertySet > xSet( xDocStream, uno::UNO_QUERY );
136 uno::Any aAny = xSet->getPropertyValue("Encrypted");
137 aAny >>= bEncrypted;
139 catch( const packages::WrongPasswordException& )
141 return ERRCODE_SFX_WRONGPASSWORD;
143 catch( const packages::zip::ZipIOException& )
145 return ERRCODE_IO_BROKENPACKAGE;
147 catch( const uno::Exception& )
149 return SCERR_IMPORT_UNKNOWN;
152 else
153 return SCERR_IMPORT_UNKNOWN;
155 // set Base URL
156 uno::Reference< beans::XPropertySet > xInfoSet;
157 if( aArgs.hasElements() )
158 aArgs.getConstArray()[0] >>= xInfoSet;
159 OSL_ENSURE( xInfoSet.is(), "missing property set" );
160 if( xInfoSet.is() )
162 xInfoSet->setPropertyValue( "StreamName", uno::makeAny( sStream ) );
165 ErrCode nReturn = ERRCODE_NONE;
166 rDoc.SetRangeOverflowType(ERRCODE_NONE); // is modified by the importer if limits are exceeded
168 uno::Reference<xml::sax::XDocumentHandler> xDocHandler(
169 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
170 sComponentName, aArgs, xContext ),
171 uno::UNO_QUERY );
172 OSL_ENSURE( xDocHandler.is(), "can't get Calc importer" );
173 uno::Reference<document::XImporter> xImporter( xDocHandler, uno::UNO_QUERY );
174 if (xImporter.is())
175 xImporter->setTargetDocument( xModel );
177 ScXMLImport* pImporterImpl = dynamic_cast<ScXMLImport*>(xImporter.get());
178 if (pImporterImpl)
179 pImporterImpl->SetPostProcessData(&maPostProcessData);
181 // connect parser and filter
182 uno::Reference< xml::sax::XFastParser > xFastParser = dynamic_cast<
183 xml::sax::XFastParser* >( xDocHandler.get() );
184 xParser->setDocumentHandler( xDocHandler );
188 if( xFastParser.is() )
189 xFastParser->parseStream( aParserInput );
190 else
191 xParser->parseStream( aParserInput );
193 catch( const xml::sax::SAXParseException& r )
195 css::uno::Any ex( cppu::getCaughtException() );
196 // sax parser sends wrapped exceptions,
197 // try to find the original one
198 xml::sax::SAXException aSaxEx = *static_cast<xml::sax::SAXException const *>(&r);
199 bool bTryChild = true;
201 while( bTryChild )
203 xml::sax::SAXException aTmp;
204 if ( aSaxEx.WrappedException >>= aTmp )
205 aSaxEx = aTmp;
206 else
207 bTryChild = false;
210 packages::zip::ZipIOException aBrokenPackage;
211 if ( aSaxEx.WrappedException >>= aBrokenPackage )
212 return ERRCODE_IO_BROKENPACKAGE;
213 else if( bEncrypted )
214 nReturn = ERRCODE_SFX_WRONGPASSWORD;
215 else
217 SAL_WARN("sc.filter", "SAX parse exception caught while importing: " << exceptionToString(ex));
219 OUString sErr = OUString::number( r.LineNumber ) +
220 "," +
221 OUString::number( r.ColumnNumber );
223 if( !sDocName.isEmpty() )
225 nReturn = *new TwoStringErrorInfo(
226 (bMustBeSuccessfull ? SCERR_IMPORT_FILE_ROWCOL
227 : SCWARN_IMPORT_FILE_ROWCOL),
228 sDocName, sErr,
229 DialogMask::ButtonsOk | DialogMask::MessageError );
231 else
233 OSL_ENSURE( bMustBeSuccessfull, "Warnings are not supported" );
234 nReturn = *new StringErrorInfo( SCERR_IMPORT_FORMAT_ROWCOL, sErr,
235 DialogMask::ButtonsOk | DialogMask::MessageError );
239 catch( const xml::sax::SAXException& r )
241 css::uno::Any ex( cppu::getCaughtException() );
242 packages::zip::ZipIOException aBrokenPackage;
243 if ( r.WrappedException >>= aBrokenPackage )
244 return ERRCODE_IO_BROKENPACKAGE;
245 else if( bEncrypted )
246 nReturn = ERRCODE_SFX_WRONGPASSWORD;
247 else
249 SAL_WARN("sc.filter", "SAX exception caught while importing: " << exceptionToString(ex));
251 nReturn = SCERR_IMPORT_FORMAT;
254 catch( const packages::zip::ZipIOException& )
256 TOOLS_WARN_EXCEPTION("sc.filter", "Zip exception caught while importing");
258 nReturn = ERRCODE_IO_BROKENPACKAGE;
260 catch( const io::IOException& )
262 TOOLS_WARN_EXCEPTION("sc.filter", "IO exception caught while importing");
264 nReturn = SCERR_IMPORT_OPEN;
266 catch( const uno::Exception& )
268 TOOLS_WARN_EXCEPTION("sc.filter", "uno exception caught while importing");
270 nReturn = SCERR_IMPORT_UNKNOWN;
273 // #i31130# Can't use getImplementation here to get the ScXMLImport from xDocHandler,
274 // because when OOo 1.x files are loaded, xDocHandler is the OOo2OasisTransformer.
275 // So the overflow warning ErrorCode is now stored in the document.
276 // Export works differently, there getImplementation still works.
278 if (rDoc.HasRangeOverflow() && !nReturn)
279 nReturn = rDoc.GetRangeOverflowType();
281 // free the component
282 xParser->setDocumentHandler( nullptr );
284 // success!
285 return nReturn;
288 bool ScXMLImportWrapper::Import( ImportFlags nMode, ErrCode& rError )
290 uno::Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
292 xml::sax::InputSource aParserInput;
293 if (pMedium)
294 aParserInput.sSystemId = pMedium->GetName();
296 if ( !xStorage.is() && pMedium )
297 xStorage = pMedium->GetStorage();
299 // get parser
300 uno::Reference<xml::sax::XParser> xXMLParser = xml::sax::Parser::create(xContext);
302 // get filter
303 uno::Reference<frame::XModel> xModel = mrDocShell.GetModel();
305 /** property map for export info set */
306 comphelper::PropertyMapEntry const aImportInfoMap[] =
308 { OUString("ProgressRange"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
309 { OUString("ProgressMax"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
310 { OUString("ProgressCurrent"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
311 { OUString("NumberStyles"), 0, cppu::UnoType<container::XNameAccess>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
312 { OUString("PrivateData"), 0, cppu::UnoType<uno::XInterface>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
313 { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
314 { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
315 { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
316 { OUString("BuildId"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
317 { OUString("VBACompatibilityMode"), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
318 { OUString("ScriptConfiguration"), 0, cppu::UnoType<container::XNameAccess>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
319 { OUString("OrganizerMode"), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
320 { OUString("SourceStorage"), 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
321 { OUString(SC_UNO_ODS_LOCK_SOLAR_MUTEX), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
322 { OUString(SC_UNO_ODS_IMPORT_STYLES), 0, cppu::UnoType<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
323 { OUString(), 0, css::uno::Type(), 0, 0 }
325 uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aImportInfoMap ) ) );
327 // No need to lock solar mutex when calling from the wrapper.
328 xInfoSet->setPropertyValue(SC_UNO_ODS_LOCK_SOLAR_MUTEX, uno::makeAny(false));
330 // ---- get BuildId from parent container if available
332 uno::Reference< container::XChild > xChild( xModel, uno::UNO_QUERY );
333 if( xChild.is() )
335 uno::Reference< beans::XPropertySet > xParentSet( xChild->getParent(), uno::UNO_QUERY );
336 if( xParentSet.is() )
338 uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xParentSet->getPropertySetInfo() );
339 OUString sPropName("BuildId" );
340 if( xPropSetInfo.is() && xPropSetInfo->hasPropertyByName(sPropName) )
342 xInfoSet->setPropertyValue( sPropName, xParentSet->getPropertyValue(sPropName) );
347 uno::Reference<task::XStatusIndicator> xStatusIndicator = GetStatusIndicator();
348 if (xStatusIndicator.is())
350 sal_Int32 nProgressRange(1000000);
351 xStatusIndicator->start(SvxResId(RID_SVXSTR_DOC_LOAD), nProgressRange);
352 xInfoSet->setPropertyValue("ProgressRange", uno::makeAny(nProgressRange));
355 // Set base URI
356 OSL_ENSURE( pMedium, "There is no medium to get MediaDescriptor from!" );
357 OUString aBaseURL = pMedium ? pMedium->GetBaseURL() : OUString();
358 // needed for relative URLs, but in clipboard copy/paste there may be none
359 SAL_INFO_IF(aBaseURL.isEmpty(), "sc.filter", "ScXMLImportWrapper: no base URL");
360 OUString sPropName("BaseURI");
361 xInfoSet->setPropertyValue( sPropName, uno::makeAny( aBaseURL ) );
363 // TODO/LATER: do not do it for embedded links
364 OUString aName;
365 if (SfxObjectCreateMode::EMBEDDED == mrDocShell.GetCreateMode())
367 if ( pMedium && pMedium->GetItemSet() )
369 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
370 pMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
371 if ( pDocHierarchItem )
372 aName = pDocHierarchItem->GetValue();
374 else
375 aName = "dummyObjectName";
377 if( !aName.isEmpty() )
379 sPropName = "StreamRelPath";
380 xInfoSet->setPropertyValue( sPropName, uno::makeAny( aName ) );
384 if (mrDocShell.GetCreateMode() == SfxObjectCreateMode::ORGANIZER)
385 xInfoSet->setPropertyValue("OrganizerMode", uno::makeAny(true));
387 xInfoSet->setPropertyValue( "SourceStorage", uno::Any( xStorage ) );
389 bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
391 if ((nMode & ImportFlags::Metadata) && bOasis)
393 // RDF metadata: ODF >= 1.2
396 const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
397 xModel, uno::UNO_QUERY_THROW );
398 const uno::Reference< rdf::XURI > xBaseURI(
399 ::sfx2::createBaseURI( xContext, xModel, aBaseURL, aName ) );
400 uno::Reference<task::XInteractionHandler> xHandler =
401 mrDocShell.GetMedium()->GetInteractionHandler();
402 xDMA->loadMetadataFromStorage( xStorage, xBaseURI, xHandler );
404 catch ( const lang::WrappedTargetException & e)
406 ucb::InteractiveAugmentedIOException iaioe;
407 if ( e.TargetException >>= iaioe )
409 rError = SCERR_IMPORT_UNKNOWN;
411 else
413 rError = SCWARN_IMPORT_FEATURES_LOST;
416 catch ( const uno::Exception &)
418 rError = SCWARN_IMPORT_FEATURES_LOST;
422 // #i103539#: always read meta.xml for generator
423 ErrCode nMetaRetval(ERRCODE_NONE);
424 if (nMode & ImportFlags::Metadata)
426 uno::Sequence<uno::Any> aMetaArgs(1);
427 uno::Any* pMetaArgs = aMetaArgs.getArray();
428 pMetaArgs[0] <<= xInfoSet;
430 SAL_INFO( "sc.filter", "meta import start" );
432 nMetaRetval = ImportFromComponent(
433 xContext, xModel, xXMLParser, aParserInput,
434 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisMetaImporter")
435 : OUString("com.sun.star.comp.Calc.XMLMetaImporter"),
436 "meta.xml", "Meta.xml", aMetaArgs, false);
438 SAL_INFO( "sc.filter", "meta import end" );
441 rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
442 uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
444 uno::Reference< document::XEmbeddedObjectResolver > xObjectResolver;
445 rtl::Reference<SvXMLEmbeddedObjectHelper> xObjectHelper;
447 if( xStorage.is() )
449 xGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Read );
450 xGraphicStorageHandler = xGraphicHelper.get();
452 xObjectHelper = SvXMLEmbeddedObjectHelper::Create(xStorage, mrDocShell, SvXMLEmbeddedObjectHelperMode::Read);
453 xObjectResolver = xObjectHelper.get();
455 uno::Sequence<uno::Any> aStylesArgs(4);
456 uno::Any* pStylesArgs = aStylesArgs.getArray();
457 pStylesArgs[0] <<= xInfoSet;
458 pStylesArgs[1] <<= xGraphicStorageHandler;
459 pStylesArgs[2] <<= xStatusIndicator;
460 pStylesArgs[3] <<= xObjectResolver;
462 ErrCode nSettingsRetval(ERRCODE_NONE);
463 if (nMode & ImportFlags::Settings)
465 // Settings must be loaded first because of the printer setting,
466 // which is needed in the page styles (paper tray).
468 uno::Sequence<uno::Any> aSettingsArgs(1);
469 uno::Any* pSettingsArgs = aSettingsArgs.getArray();
470 pSettingsArgs[0] <<= xInfoSet;
472 SAL_INFO( "sc.filter", "settings import start" );
474 nSettingsRetval = ImportFromComponent(
475 xContext, xModel, xXMLParser, aParserInput,
476 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisSettingsImporter")
477 : OUString("com.sun.star.comp.Calc.XMLSettingsImporter"),
478 "settings.xml", "", aSettingsArgs, false);
480 SAL_INFO( "sc.filter", "settings import end" );
483 ErrCode nStylesRetval(ERRCODE_NONE);
484 if (nMode & ImportFlags::Styles)
486 SAL_INFO( "sc.filter", "styles import start" );
488 nStylesRetval = ImportFromComponent(xContext, xModel, xXMLParser, aParserInput,
489 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisStylesImporter")
490 : OUString("com.sun.star.comp.Calc.XMLStylesImporter"),
491 "styles.xml",
492 "", aStylesArgs, true);
494 SAL_INFO( "sc.filter", "styles import end" );
497 ErrCode nDocRetval(ERRCODE_NONE);
498 if (nMode & ImportFlags::Content)
500 if (mrDocShell.GetCreateMode() == SfxObjectCreateMode::INTERNAL)
501 // We only need to import content for external link cache document.
502 xInfoSet->setPropertyValue(SC_UNO_ODS_IMPORT_STYLES, uno::makeAny(false));
504 uno::Sequence<uno::Any> aDocArgs(4);
505 uno::Any* pDocArgs = aDocArgs.getArray();
506 pDocArgs[0] <<= xInfoSet;
507 pDocArgs[1] <<= xGraphicStorageHandler;
508 pDocArgs[2] <<= xStatusIndicator;
509 pDocArgs[3] <<= xObjectResolver;
511 SAL_INFO( "sc.filter", "content import start" );
513 nDocRetval = ImportFromComponent(xContext, xModel, xXMLParser, aParserInput,
514 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisContentImporter")
515 : OUString("com.sun.star.comp.Calc.XMLContentImporter"),
516 "content.xml",
517 "Content.xml", aDocArgs,
518 true);
520 SAL_INFO( "sc.filter", "content import end" );
522 if( xGraphicHelper.is() )
523 xGraphicHelper->dispose();
524 xGraphicHelper.clear();
526 if( xObjectHelper.is() )
527 xObjectHelper->dispose();
528 xObjectHelper.clear();
530 if (xStatusIndicator.is())
531 xStatusIndicator->end();
533 bool bRet = false;
534 if (nDocRetval)
536 rError = nDocRetval;
537 if (nDocRetval == SCWARN_IMPORT_RANGE_OVERFLOW ||
538 nDocRetval == SCWARN_IMPORT_ROW_OVERFLOW ||
539 nDocRetval == SCWARN_IMPORT_COLUMN_OVERFLOW ||
540 nDocRetval == SCWARN_IMPORT_SHEET_OVERFLOW)
541 bRet = true;
543 else if (nStylesRetval)
544 rError = nStylesRetval;
545 else if (nMetaRetval)
546 rError = nMetaRetval;
547 else if (nSettingsRetval)
548 rError = nSettingsRetval;
549 else
550 bRet = true;
552 // set BuildId on XModel for later OLE object loading
553 if( xInfoSet.is() )
555 uno::Reference< beans::XPropertySet > xModelSet( xModel, uno::UNO_QUERY );
556 if( xModelSet.is() )
558 uno::Reference< beans::XPropertySetInfo > xModelSetInfo( xModelSet->getPropertySetInfo() );
559 OUString sBuildPropName("BuildId" );
560 if( xModelSetInfo.is() && xModelSetInfo->hasPropertyByName(sBuildPropName) )
562 xModelSet->setPropertyValue( sBuildPropName, xInfoSet->getPropertyValue(sBuildPropName) );
566 // Set Code Names
567 uno::Any aAny = xInfoSet->getPropertyValue("ScriptConfiguration");
568 uno::Reference <container::XNameAccess> xCodeNameAccess;
569 if( aAny >>= xCodeNameAccess )
570 XMLCodeNameProvider::set( xCodeNameAccess, &rDoc );
572 // VBA compatibility
573 bool bVBACompat = false;
574 if ( (xInfoSet->getPropertyValue("VBACompatibilityMode") >>= bVBACompat) && bVBACompat )
576 /* Set library container to VBA compatibility mode, this
577 forces loading the Basic project, which in turn creates the
578 VBA Globals object and does all related initialization. */
579 if ( xModelSet.is() ) try
581 uno::Reference< script::vba::XVBACompatibility > xVBACompat( xModelSet->getPropertyValue(
582 "BasicLibraries" ), uno::UNO_QUERY_THROW );
583 xVBACompat->setVBACompatibilityMode( true );
585 catch( const uno::Exception& )
591 // Don't test bStylesRetval and bMetaRetval, because it could be an older file which not contain such streams
592 return bRet;//!bStylesOnly ? bDocRetval : bStylesRetval;
595 static bool lcl_HasValidStream(const ScDocument& rDoc)
597 SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
598 if ( pObjSh->IsDocShared() )
599 return false; // never copy stream from shared file
601 // don't read remote file again
602 // (could instead re-use medium directly in that case)
603 SfxMedium* pSrcMed = rDoc.GetDocumentShell()->GetMedium();
604 if ( !pSrcMed || pSrcMed->IsRemote() )
605 return false;
607 SCTAB nTabCount = rDoc.GetTableCount();
608 for (SCTAB nTab=0; nTab<nTabCount; ++nTab)
609 if (rDoc.IsStreamValid(nTab))
610 return true;
611 return false;
614 bool ScXMLImportWrapper::ExportToComponent(const uno::Reference<uno::XComponentContext>& xContext,
615 const uno::Reference<frame::XModel>& xModel, const uno::Reference<xml::sax::XWriter>& xWriter,
616 const uno::Sequence<beans::PropertyValue>& aDescriptor, const OUString& sName,
617 const OUString& sMediaType, const OUString& sComponentName,
618 const uno::Sequence<uno::Any>& aArgs, std::unique_ptr<ScMySharedData>& pSharedData)
620 bool bRet(false);
621 uno::Reference<io::XOutputStream> xOut;
622 uno::Reference<io::XStream> xStream;
624 if ( !xStorage.is() && pMedium )
625 xStorage = pMedium->GetOutputStorage();
627 if( xStorage.is() )
629 // #96807#; trunc stream before use, because it could be an existing stream
630 // and the new content could be shorter than the old content. In this case
631 // would not all be over written by the new content and the xml file
632 // would not be valid.
633 xStream = xStorage->openStreamElement( sName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
634 uno::Reference < beans::XPropertySet > xSet( xStream, uno::UNO_QUERY );
635 if (xSet.is())
637 xSet->setPropertyValue("MediaType", uno::makeAny(sMediaType));
639 // advise storage impl to use common encryption
640 xSet->setPropertyValue( "UseCommonStoragePasswordEncryption", uno::makeAny(true) );
643 xOut = xStream->getOutputStream();
646 // set Base URL
647 uno::Reference< beans::XPropertySet > xInfoSet;
648 if( aArgs.hasElements() )
649 aArgs.getConstArray()[0] >>= xInfoSet;
650 OSL_ENSURE( xInfoSet.is(), "missing property set" );
651 if( xInfoSet.is() )
653 xInfoSet->setPropertyValue( "StreamName", uno::makeAny( sName ) );
656 xWriter->setOutputStream( xOut );
658 uno::Reference<document::XFilter> xFilter(
659 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
660 sComponentName , aArgs, xContext ),
661 uno::UNO_QUERY );
662 OSL_ENSURE( xFilter.is(), "can't get exporter" );
663 uno::Reference<document::XExporter> xExporter( xFilter, uno::UNO_QUERY );
664 if (xExporter.is())
665 xExporter->setSourceDocument( xModel );
667 if ( xFilter.is() )
669 ScXMLExport* pExport = static_cast<ScXMLExport*>(comphelper::getUnoTunnelImplementation<SvXMLExport>(xFilter));
670 pExport->SetSharedData(std::move(pSharedData));
672 // if there are sheets to copy, get the source stream
673 if ( sName == "content.xml" && lcl_HasValidStream(rDoc) && ( pExport->getExportFlags() & SvXMLExportFlags::OASIS ) )
675 // old stream is still in this file's storage - open read-only
677 // #i106854# use the document's storage directly, without a temporary SfxMedium
678 uno::Reference<embed::XStorage> xTmpStorage = rDoc.GetDocumentShell()->GetStorage();
679 uno::Reference<io::XStream> xSrcStream;
680 uno::Reference<io::XInputStream> xSrcInput;
682 // #i108978# If an embedded object is saved and no events are notified, don't use the stream
683 // because without the ...DONE events, stream positions aren't updated.
684 ScSheetSaveData* pSheetData = comphelper::getUnoTunnelImplementation<ScModelObj>(xModel)->GetSheetSaveData();
685 if (pSheetData && pSheetData->IsInSupportedSave())
689 if (xTmpStorage.is())
690 xSrcStream = xTmpStorage->openStreamElement( sName, embed::ElementModes::READ );
691 if (xSrcStream.is())
692 xSrcInput = xSrcStream->getInputStream();
694 catch ( const uno::Exception&)
696 // stream not available (for example, password protected) - save normally (xSrcInput is null)
700 pExport->SetSourceStream( xSrcInput );
701 bRet = xFilter->filter( aDescriptor );
702 pExport->SetSourceStream( uno::Reference<io::XInputStream>() );
704 // If there was an error, reset all stream flags, so the next save attempt will use normal saving.
705 // #i110692# For embedded objects, the stream may be unavailable for one save operation (m_pAntiImpl)
706 // and become available again later. But after saving normally once, the stream positions aren't
707 // valid anymore, so the flags also have to be reset if the stream wasn't available.
708 if ( !bRet || !xSrcInput.is() )
710 SCTAB nTabCount = rDoc.GetTableCount();
711 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
712 rDoc.SetStreamValid(nTab, false);
715 else
716 bRet = xFilter->filter( aDescriptor );
718 pSharedData = pExport->ReleaseSharedData();
721 return bRet;
724 bool ScXMLImportWrapper::Export(bool bStylesOnly)
726 // Prevent all broadcasting and repaints and notification of accessibility
727 // during mass creation of captions, which is a major bottleneck and not
728 // needed during Save.
729 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
730 bool bOldLock = bool();
731 if (pDrawLayer)
733 bOldLock = pDrawLayer->isLocked();
734 pDrawLayer->setLock(true);
737 rDoc.CreateAllNoteCaptions();
739 if (pDrawLayer)
740 pDrawLayer->setLock(bOldLock);
742 uno::Reference<uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
744 uno::Reference<xml::sax::XWriter> xWriter = xml::sax::Writer::create(xContext);
746 if ( !xStorage.is() && pMedium )
747 xStorage = pMedium->GetOutputStorage();
749 OUString sFileName;
750 OUString sTextMediaType("text/xml");
751 if (pMedium)
752 sFileName = pMedium->GetName();
753 SfxObjectShell* pObjSh = rDoc.GetDocumentShell();
754 uno::Sequence<beans::PropertyValue> aDescriptor( comphelper::InitPropertySequence({
755 { "FileName", uno::Any(sFileName) }
756 }));
758 /** property map for export info set */
759 comphelper::PropertyMapEntry const aExportInfoMap[] =
761 { OUString("ProgressRange"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
762 { OUString("ProgressMax"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
763 { OUString("ProgressCurrent"), 0, ::cppu::UnoType<sal_Int32>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
764 { OUString("WrittenNumberStyles"), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
765 { OUString("UsePrettyPrinting"), 0, ::cppu::UnoType<sal_Bool>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0},
766 { OUString("BaseURI"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
767 { OUString("StreamRelPath"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
768 { OUString("StreamName"), 0, ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
769 { OUString("StyleNames"), 0, cppu::UnoType<uno::Sequence<OUString>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
770 { OUString("StyleFamilies"), 0, cppu::UnoType<uno::Sequence<sal_Int32>>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
771 { OUString("TargetStorage"), 0, cppu::UnoType<embed::XStorage>::get(), css::beans::PropertyAttribute::MAYBEVOID, 0 },
772 { OUString(), 0, css::uno::Type(), 0, 0 }
774 uno::Reference< beans::XPropertySet > xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) ) );
776 if ( pObjSh && xStorage.is() )
778 uno::Reference<frame::XModel> xModel(pObjSh->GetModel());
779 uno::Reference<task::XStatusIndicator> xStatusIndicator(GetStatusIndicator());
780 sal_Int32 nProgressRange(1000000);
781 if(xStatusIndicator.is())
782 xStatusIndicator->start(ScResId(STR_SAVE_DOC), nProgressRange);
783 xInfoSet->setPropertyValue("ProgressRange", uno::makeAny(nProgressRange));
785 SvtSaveOptions aSaveOpt;
786 bool bUsePrettyPrinting(aSaveOpt.IsPrettyPrinting());
787 xInfoSet->setPropertyValue("UsePrettyPrinting", uno::makeAny(bUsePrettyPrinting));
789 const OUString sTargetStorage("TargetStorage");
790 xInfoSet->setPropertyValue( sTargetStorage, uno::Any( xStorage ) );
792 OSL_ENSURE( pMedium, "There is no medium to get MediaDescriptor from!" );
793 OUString aBaseURL = pMedium ? pMedium->GetBaseURL( true ) : OUString();
794 OUString sPropName("BaseURI");
795 xInfoSet->setPropertyValue( sPropName, uno::makeAny( aBaseURL ) );
797 // TODO/LATER: do not do it for embedded links
798 if( SfxObjectCreateMode::EMBEDDED == pObjSh->GetCreateMode() )
800 OUString aName("dummyObjectName");
801 if ( pMedium && pMedium->GetItemSet() )
803 const SfxStringItem* pDocHierarchItem = static_cast<const SfxStringItem*>(
804 pMedium->GetItemSet()->GetItem(SID_DOC_HIERARCHICALNAME) );
805 if ( pDocHierarchItem )
806 aName = pDocHierarchItem->GetValue();
809 if( !aName.isEmpty() )
811 sPropName = "StreamRelPath";
812 xInfoSet->setPropertyValue( sPropName, uno::makeAny( aName ) );
816 bool bMetaRet(pObjSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED);
817 bool bStylesRet (false);
818 bool bDocRet(false);
819 bool bSettingsRet(false);
820 std::unique_ptr<ScMySharedData> pSharedData;
822 bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
824 // RDF metadata: ODF >= 1.2
825 if ( !bStylesOnly && bOasis )
827 const uno::Reference< beans::XPropertySet > xPropSet( xStorage, uno::UNO_QUERY_THROW );
830 OUString aVersion;
831 if (( xPropSet->getPropertyValue("Version") >>= aVersion )
832 && aVersion != ODFVER_010_TEXT
833 && aVersion != ODFVER_011_TEXT )
835 const uno::Reference< rdf::XDocumentMetadataAccess > xDMA(
836 xModel, uno::UNO_QUERY_THROW );
837 xDMA->storeMetadataToStorage( xStorage );
840 catch ( const beans::UnknownPropertyException &)
843 catch ( const uno::Exception &)
848 // meta export
849 if (!bStylesOnly && !bMetaRet)
851 uno::Sequence<uno::Any> aMetaArgs(3);
852 uno::Any* pMetaArgs = aMetaArgs.getArray();
853 pMetaArgs[0] <<= xInfoSet;
854 pMetaArgs[1] <<= xWriter;
855 pMetaArgs[2] <<= xStatusIndicator;
857 SAL_INFO( "sc.filter", "meta export start" );
859 bMetaRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
860 "meta.xml",
861 sTextMediaType,
862 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisMetaExporter")
863 : OUString("com.sun.star.comp.Calc.XMLMetaExporter"),
864 aMetaArgs, pSharedData);
866 SAL_INFO( "sc.filter", "meta export end" );
869 uno::Reference<document::XGraphicStorageHandler> xGraphicStorageHandler;
870 rtl::Reference<SvXMLGraphicHelper> xGraphicHelper;
872 if( xStorage.is() )
874 xGraphicHelper = SvXMLGraphicHelper::Create( xStorage, SvXMLGraphicHelperMode::Write );
875 xGraphicStorageHandler = xGraphicHelper.get();
878 auto xObjectHelper = SvXMLEmbeddedObjectHelper::Create(
879 xStorage, *pObjSh, SvXMLEmbeddedObjectHelperMode::Write);
880 uno::Reference<document::XEmbeddedObjectResolver> xObjectResolver(xObjectHelper.get());
882 // styles export
885 uno::Sequence<uno::Any> aStylesArgs(5);
886 uno::Any* pStylesArgs = aStylesArgs.getArray();
887 pStylesArgs[0] <<= xInfoSet;
888 pStylesArgs[1] <<= xGraphicStorageHandler;
889 pStylesArgs[2] <<= xStatusIndicator;
890 pStylesArgs[3] <<= xWriter;
891 pStylesArgs[4] <<= xObjectResolver;
893 SAL_INFO( "sc.filter", "styles export start" );
895 bStylesRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
896 "styles.xml",
897 sTextMediaType,
898 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisStylesExporter")
899 : OUString("com.sun.star.comp.Calc.XMLStylesExporter"),
900 aStylesArgs, pSharedData);
902 SAL_INFO( "sc.filter", "styles export end" );
905 // content export
907 if (!bStylesOnly)
909 uno::Sequence<uno::Any> aDocArgs(5);
910 uno::Any* pDocArgs = aDocArgs.getArray();
911 pDocArgs[0] <<= xInfoSet;
912 pDocArgs[1] <<= xGraphicStorageHandler;
913 pDocArgs[2] <<= xStatusIndicator;
914 pDocArgs[3] <<= xWriter;
915 pDocArgs[4] <<= xObjectResolver;
917 SAL_INFO( "sc.filter", "content export start" );
919 bDocRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
920 "content.xml",
921 sTextMediaType,
922 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisContentExporter")
923 : OUString("com.sun.star.comp.Calc.XMLContentExporter"),
924 aDocArgs, pSharedData);
926 SAL_INFO( "sc.filter", "content export end" );
929 if( xGraphicHelper )
930 xGraphicHelper->dispose();
931 xGraphicHelper.clear();
933 if( xObjectHelper )
934 xObjectHelper->dispose();
935 xObjectHelper.clear();
937 // settings export
939 if (!bStylesOnly)
941 uno::Sequence<uno::Any> aSettingsArgs(3);
942 uno::Any* pSettingsArgs = aSettingsArgs.getArray();
943 pSettingsArgs[0] <<= xInfoSet;
944 pSettingsArgs[1] <<= xWriter;
945 pSettingsArgs[2] <<= xStatusIndicator;
947 SAL_INFO( "sc.filter", "settings export start" );
949 bSettingsRet = ExportToComponent(xContext, xModel, xWriter, aDescriptor,
950 "settings.xml",
951 sTextMediaType,
952 bOasis ? OUString("com.sun.star.comp.Calc.XMLOasisSettingsExporter")
953 : OUString("com.sun.star.comp.Calc.XMLSettingsExporter"),
954 aSettingsArgs, pSharedData);
956 SAL_INFO( "sc.filter", "settings export end" );
959 pSharedData.reset();
961 if (xStatusIndicator.is())
962 xStatusIndicator->end();
963 return bStylesRet && ((!bStylesOnly && bDocRet && bMetaRet && bSettingsRet) || bStylesOnly);
966 // later: give string descriptor as parameter for doc type
968 return false;
971 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */