1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <officecfg/Office/Common.hxx>
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"
74 #include <drwlayer.hxx>
75 #include <sheetdata.hxx>
76 #include "XMLCodeNameProvider.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
) :
85 rDoc(rDocSh
.GetDocument()),
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
;
97 SfxItemSet
* pSet
= pMedium
->GetItemSet();
100 const SfxUnoAnyItem
* pItem
= pSet
->GetItem
<SfxUnoAnyItem
>(SID_PROGRESS_STATUSBAR_CONTROL
);
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
);
125 if ( xStorage
->hasByName(sDocName
) && xStorage
->isStreamElement( sDocName
) )
126 xDocStream
= xStorage
->openStreamElement( sDocName
, embed::ElementModes::READ
);
130 aParserInput
.aInputStream
= xDocStream
->getInputStream();
131 uno::Reference
< beans::XPropertySet
> xSet( xDocStream
, uno::UNO_QUERY
);
133 uno::Any aAny
= xSet
->getPropertyValue("Encrypted");
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
;
150 return SCERR_IMPORT_UNKNOWN
;
153 uno::Reference
< beans::XPropertySet
> xInfoSet
;
154 if( aArgs
.hasElements() )
155 aArgs
.getConstArray()[0] >>= xInfoSet
;
156 OSL_ENSURE( xInfoSet
.is(), "missing property set" );
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
);
171 xImporter
->setTargetDocument( xModel
);
173 ScXMLImport
* pImporterImpl
= dynamic_cast<ScXMLImport
*>(xImporter
.get());
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
);
185 xFastParser
->parseStream( aParserInput
);
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;
204 xml::sax::SAXException aTmp
;
205 if ( aSaxEx
.WrappedException
>>= aTmp
)
211 packages::zip::ZipIOException aBrokenPackage
;
212 if ( aSaxEx
.WrappedException
>>= aBrokenPackage
)
213 return ERRCODE_IO_BROKENPACKAGE
;
214 else if( bEncrypted
)
215 nReturn
= ERRCODE_SFX_WRONGPASSWORD
;
218 SAL_WARN("sc.filter", "SAX parse exception caught while importing: " << exceptionToString(ex
));
220 OUString sErr
= OUString::number( r
.LineNumber
) +
222 OUString::number( r
.ColumnNumber
);
224 if( !sDocName
.isEmpty() )
226 nReturn
= *new TwoStringErrorInfo(
227 (bMustBeSuccessful
? SCERR_IMPORT_FILE_ROWCOL
228 : SCWARN_IMPORT_FILE_ROWCOL
),
230 DialogMask::ButtonsOk
| DialogMask::MessageError
);
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
;
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();
286 bool ScXMLImportWrapper::Import( ImportFlags nMode
, ErrCode
& rError
)
288 uno::Reference
<uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
290 xml::sax::InputSource aParserInput
;
292 aParserInput
.sSystemId
= pMedium
->GetName();
294 if ( !xStorage
.is() && pMedium
)
295 xStorage
= pMedium
->GetStorage();
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
);
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
));
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
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();
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
;
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
;
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
450 Any(xGraphicStorageHandler
),
451 Any(xStatusIndicator
),
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"),
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
498 Any(xGraphicStorageHandler
),
499 Any(xStatusIndicator
),
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"),
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();
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
)
535 else if (nStylesRetval
)
536 rError
= nStylesRetval
;
537 else if (nMetaRetval
)
538 rError
= nMetaRetval
;
539 else if (nSettingsRetval
)
540 rError
= nSettingsRetval
;
544 ::svx::DropUnusedNamedItems(xModel
);
546 // set BuildId on XModel for later OLE object loading
549 uno::Reference
< beans::XPropertySet
> xModelSet( xModel
, uno::UNO_QUERY
);
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
) );
561 uno::Any aAny
= xInfoSet
->getPropertyValue("ScriptConfiguration");
562 uno::Reference
<container::XNameAccess
> xCodeNameAccess
;
563 if( aAny
>>= xCodeNameAccess
)
564 XMLCodeNameProvider::set( xCodeNameAccess
, &rDoc
);
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() )
601 SCTAB nTabCount
= rDoc
.GetTableCount();
602 for (SCTAB nTab
=0; nTab
<nTabCount
; ++nTab
)
603 if (rDoc
.IsStreamValid(nTab
))
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
)
615 uno::Reference
<io::XOutputStream
> xOut
;
616 uno::Reference
<io::XStream
> xStream
;
618 if ( !xStorage
.is() && pMedium
)
619 xStorage
= pMedium
->GetOutputStorage();
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
);
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();
641 uno::Reference
< beans::XPropertySet
> xInfoSet
;
642 if( aArgs
.hasElements() )
643 aArgs
.getConstArray()[0] >>= xInfoSet
;
644 OSL_ENSURE( xInfoSet
.is(), "missing property set" );
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
),
656 OSL_ENSURE( xFilter
.is(), "can't get exporter" );
657 uno::Reference
<document::XExporter
> xExporter( xFilter
, uno::UNO_QUERY
);
659 xExporter
->setSourceDocument( xModel
);
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
);
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);
710 bRet
= xFilter
->filter( aDescriptor
);
712 pSharedData
= pExport
->ReleaseSharedData();
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();
727 bOldLock
= pDrawLayer
->isLocked();
728 pDrawLayer
->setLock(true);
731 rDoc
.CreateAllNoteCaptions();
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();
745 sFileName
= pMedium
->GetName();
746 SfxObjectShell
* pObjSh
= rDoc
.GetDocumentShell();
747 uno::Sequence
<beans::PropertyValue
> aDescriptor( comphelper::InitPropertySequence({
748 { "FileName", uno::Any(sFileName
) }
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());
776 for (auto i
= xDPs
->getCount(); 0 < i
; )
779 uno::Reference
<drawing::XShapes
> const xDP(xDPs
->getByIndex(i
), uno::UNO_QUERY
);
781 xmloff::FixZOrder(xDP
,
782 [](uno::Reference
<beans::XPropertySet
> const& xShape
)
784 sal_Int16
nLayerID(0);
785 xShape
->getPropertyValue("LayerID") >>= nLayerID
;
788 case sal_Int16(SC_LAYER_FRONT
):
790 case sal_Int16(SC_LAYER_BACK
):
792 case sal_Int16(SC_LAYER_INTERN
):
794 case sal_Int16(SC_LAYER_CONTROLS
):
796 case sal_Int16(SC_LAYER_HIDDEN
):
797 return 1; // treat as equivalent to front
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);
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
);
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
&)
873 if (!bStylesOnly
&& !bMetaRet
)
875 uno::Sequence
<uno::Any
> aMetaArgs
879 Any(xStatusIndicator
)
882 SAL_INFO( "sc.filter", "meta export start" );
884 bMetaRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
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
;
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
);
910 uno::Sequence
<uno::Any
> aStylesArgs
913 Any(xGraphicStorageHandler
),
914 Any(xStatusIndicator
),
919 SAL_INFO( "sc.filter", "styles export start" );
921 bStylesRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
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" );
935 uno::Sequence
<uno::Any
> aDocArgs
938 Any(xGraphicStorageHandler
),
939 Any(xStatusIndicator
),
944 SAL_INFO( "sc.filter", "content export start" );
946 bDocRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
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" );
957 xGraphicHelper
->dispose();
958 xGraphicHelper
.clear();
961 xObjectHelper
->dispose();
962 xObjectHelper
.clear();
968 uno::Sequence
<uno::Any
> aSettingsArgs
972 Any(xStatusIndicator
)
975 SAL_INFO( "sc.filter", "settings export start" );
977 bSettingsRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
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" );
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
999 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */