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 const SfxUnoAnyItem
* pItem
= pMedium
->GetItemSet().GetItem(SID_PROGRESS_STATUSBAR_CONTROL
);
99 xStatusIndicator
.set(pItem
->GetValue(), uno::UNO_QUERY
);
101 return xStatusIndicator
;
104 ErrCodeMsg
ScXMLImportWrapper::ImportFromComponent(const uno::Reference
<uno::XComponentContext
>& xContext
,
105 const uno::Reference
<frame::XModel
>& xModel
,
106 xml::sax::InputSource
& aParserInput
,
107 const OUString
& sComponentName
, const OUString
& sDocName
,
108 const uno::Sequence
<uno::Any
>& aArgs
,
109 bool bMustBeSuccessful
)
111 uno::Reference
< io::XStream
> xDocStream
;
112 if ( !xStorage
.is() && pMedium
)
113 xStorage
= pMedium
->GetStorage();
115 bool bEncrypted
= false;
120 if ( xStorage
->hasByName(sDocName
) && xStorage
->isStreamElement( sDocName
) )
121 xDocStream
= xStorage
->openStreamElement( sDocName
, embed::ElementModes::READ
);
125 aParserInput
.aInputStream
= xDocStream
->getInputStream();
126 uno::Reference
< beans::XPropertySet
> xSet( xDocStream
, uno::UNO_QUERY
);
128 uno::Any aAny
= xSet
->getPropertyValue(u
"Encrypted"_ustr
);
131 catch( const packages::WrongPasswordException
& )
133 return ERRCODE_SFX_WRONGPASSWORD
;
135 catch( const packages::zip::ZipIOException
& )
137 return ERRCODE_IO_BROKENPACKAGE
;
139 catch( const uno::Exception
& )
141 return SCERR_IMPORT_UNKNOWN
;
145 return SCERR_IMPORT_UNKNOWN
;
148 uno::Reference
< beans::XPropertySet
> xInfoSet
;
149 if( aArgs
.hasElements() )
150 aArgs
.getConstArray()[0] >>= xInfoSet
;
151 OSL_ENSURE( xInfoSet
.is(), "missing property set" );
154 xInfoSet
->setPropertyValue( u
"StreamName"_ustr
, uno::Any( sDocName
) );
157 ErrCodeMsg nReturn
= ERRCODE_NONE
;
158 rDoc
.SetRangeOverflowType(ERRCODE_NONE
); // is modified by the importer if limits are exceeded
160 uno::Reference
<XInterface
> xImportInterface
=
161 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
162 sComponentName
, aArgs
, xContext
);
163 SAL_WARN_IF( !xImportInterface
, "sc", "can't get Calc importer " << sComponentName
);
164 uno::Reference
<document::XImporter
> xImporter( xImportInterface
, uno::UNO_QUERY
);
166 xImporter
->setTargetDocument( xModel
);
168 ScXMLImport
* pImporterImpl
= dynamic_cast<ScXMLImport
*>(xImporter
.get());
170 pImporterImpl
->SetPostProcessData(&maPostProcessData
);
172 // connect parser and filter
175 // xImportInterface is either ScXMLImport or an XMLTransformer subclass.
176 // ScXMLImport implements XFastParser, but XMLTransformer only implements XExtendedDocumentHandler
178 uno::Reference
< xml::sax::XFastParser
> xFastParser(xImportInterface
, uno::UNO_QUERY
);
180 xFastParser
->parseStream( aParserInput
);
183 uno::Reference
<xml::sax::XParser
> xParser
= xml::sax::Parser::create(xContext
);
184 uno::Reference
<css::xml::sax::XDocumentHandler
> xDocumentHandler(xImportInterface
, uno::UNO_QUERY
);
185 xParser
->setDocumentHandler( xDocumentHandler
);
186 xParser
->parseStream( aParserInput
);
189 catch( const xml::sax::SAXParseException
& r
)
191 css::uno::Any
ex( cppu::getCaughtException() );
192 // sax parser sends wrapped exceptions,
193 // try to find the original one
194 xml::sax::SAXException aSaxEx
= *static_cast<xml::sax::SAXException
const *>(&r
);
195 bool bTryChild
= true;
199 xml::sax::SAXException aTmp
;
200 if ( aSaxEx
.WrappedException
>>= aTmp
)
201 aSaxEx
= std::move(aTmp
);
206 packages::zip::ZipIOException aBrokenPackage
;
207 if ( aSaxEx
.WrappedException
>>= aBrokenPackage
)
208 return ERRCODE_IO_BROKENPACKAGE
;
209 else if( bEncrypted
)
210 nReturn
= ERRCODE_SFX_WRONGPASSWORD
;
213 SAL_WARN("sc.filter", "SAX parse exception caught while importing: " << exceptionToString(ex
));
215 OUString sErr
= OUString::number( r
.LineNumber
) +
217 OUString::number( r
.ColumnNumber
);
219 if( !sDocName
.isEmpty() )
221 nReturn
= ErrCodeMsg(
222 (bMustBeSuccessful
? SCERR_IMPORT_FILE_ROWCOL
223 : SCWARN_IMPORT_FILE_ROWCOL
),
225 DialogMask::ButtonsOk
| DialogMask::MessageError
);
229 OSL_ENSURE( bMustBeSuccessful
, "Warnings are not supported" );
230 nReturn
= ErrCodeMsg( SCERR_IMPORT_FORMAT_ROWCOL
, sErr
,
231 DialogMask::ButtonsOk
| DialogMask::MessageError
);
235 catch( const xml::sax::SAXException
& r
)
237 css::uno::Any
ex( cppu::getCaughtException() );
238 packages::zip::ZipIOException aBrokenPackage
;
239 if ( r
.WrappedException
>>= aBrokenPackage
)
240 return ERRCODE_IO_BROKENPACKAGE
;
241 else if( bEncrypted
)
242 nReturn
= ERRCODE_SFX_WRONGPASSWORD
;
245 SAL_WARN("sc.filter", "SAX exception caught while importing: " << exceptionToString(ex
));
247 nReturn
= SCERR_IMPORT_FORMAT
;
250 catch( const packages::zip::ZipIOException
& )
252 TOOLS_WARN_EXCEPTION("sc.filter", "Zip exception caught while importing");
254 nReturn
= ERRCODE_IO_BROKENPACKAGE
;
256 catch( const io::IOException
& )
258 TOOLS_WARN_EXCEPTION("sc.filter", "IO exception caught while importing");
260 nReturn
= SCERR_IMPORT_OPEN
;
262 catch( const uno::Exception
& )
264 TOOLS_WARN_EXCEPTION("sc.filter", "uno exception caught while importing");
266 nReturn
= SCERR_IMPORT_UNKNOWN
;
269 // #i31130# Can't use getImplementation here to get the ScXMLImport from xDocHandler,
270 // because when OOo 1.x files are loaded, xDocHandler is the OOo2OasisTransformer.
271 // So the overflow warning ErrorCode is now stored in the document.
272 // Export works differently, there getImplementation still works.
274 if (rDoc
.HasRangeOverflow() && !nReturn
)
275 nReturn
= rDoc
.GetRangeOverflowType();
281 bool ScXMLImportWrapper::Import( ImportFlags nMode
, ErrCodeMsg
& rError
)
283 const uno::Reference
<uno::XComponentContext
>& xContext
= comphelper::getProcessComponentContext();
285 xml::sax::InputSource aParserInput
;
287 aParserInput
.sSystemId
= pMedium
->GetName();
289 if ( !xStorage
.is() && pMedium
)
290 xStorage
= pMedium
->GetStorage();
293 uno::Reference
<frame::XModel
> xModel
= mrDocShell
.GetModel();
295 /** property map for export info set */
296 static comphelper::PropertyMapEntry
const aImportInfoMap
[] =
298 { u
"ProgressRange"_ustr
, 0, ::cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
299 { u
"ProgressMax"_ustr
, 0, ::cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
300 { u
"ProgressCurrent"_ustr
, 0, ::cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
301 { u
"NumberStyles"_ustr
, 0, cppu::UnoType
<container::XNameAccess
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
302 { u
"PrivateData"_ustr
, 0, cppu::UnoType
<uno::XInterface
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
303 { u
"BaseURI"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
304 { u
"StreamRelPath"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
305 { u
"StreamName"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
306 { u
"BuildId"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
307 { u
"VBACompatibilityMode"_ustr
, 0, cppu::UnoType
<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
308 { u
"ScriptConfiguration"_ustr
, 0, cppu::UnoType
<container::XNameAccess
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
309 { u
"OrganizerMode"_ustr
, 0, cppu::UnoType
<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
310 { u
"SourceStorage"_ustr
, 0, cppu::UnoType
<embed::XStorage
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
311 { SC_UNO_ODS_LOCK_SOLAR_MUTEX
, 0, cppu::UnoType
<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
312 { SC_UNO_ODS_IMPORT_STYLES
, 0, cppu::UnoType
<bool>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
314 uno::Reference
< beans::XPropertySet
> xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aImportInfoMap
) ) );
316 // No need to lock solar mutex when calling from the wrapper.
317 xInfoSet
->setPropertyValue(SC_UNO_ODS_LOCK_SOLAR_MUTEX
, uno::Any(false));
319 // ---- get BuildId from parent container if available
321 uno::Reference
< container::XChild
> xChild( xModel
, uno::UNO_QUERY
);
324 uno::Reference
< beans::XPropertySet
> xParentSet( xChild
->getParent(), uno::UNO_QUERY
);
325 if( xParentSet
.is() )
327 uno::Reference
< beans::XPropertySetInfo
> xPropSetInfo( xParentSet
->getPropertySetInfo() );
328 OUString
sPropName(u
"BuildId"_ustr
);
329 if( xPropSetInfo
.is() && xPropSetInfo
->hasPropertyByName(sPropName
) )
331 xInfoSet
->setPropertyValue( sPropName
, xParentSet
->getPropertyValue(sPropName
) );
336 uno::Reference
<task::XStatusIndicator
> xStatusIndicator
= GetStatusIndicator();
337 if (xStatusIndicator
.is())
339 sal_Int32
nProgressRange(1000000);
340 xStatusIndicator
->start(SvxResId(RID_SVXSTR_DOC_LOAD
), nProgressRange
);
341 xInfoSet
->setPropertyValue(u
"ProgressRange"_ustr
, uno::Any(nProgressRange
));
345 OSL_ENSURE( pMedium
, "There is no medium to get MediaDescriptor from!" );
346 OUString aBaseURL
= pMedium
? pMedium
->GetBaseURL() : OUString();
347 // needed for relative URLs, but in clipboard copy/paste there may be none
348 SAL_INFO_IF(aBaseURL
.isEmpty(), "sc.filter", "ScXMLImportWrapper: no base URL");
349 OUString
sPropName(u
"BaseURI"_ustr
);
350 xInfoSet
->setPropertyValue( sPropName
, uno::Any( aBaseURL
) );
352 // TODO/LATER: do not do it for embedded links
354 if (SfxObjectCreateMode::EMBEDDED
== mrDocShell
.GetCreateMode())
358 const SfxStringItem
* pDocHierarchItem
=
359 pMedium
->GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME
);
360 if ( pDocHierarchItem
)
361 aName
= pDocHierarchItem
->GetValue();
364 aName
= "dummyObjectName";
366 if( !aName
.isEmpty() )
368 sPropName
= "StreamRelPath";
369 xInfoSet
->setPropertyValue( sPropName
, uno::Any( aName
) );
373 if (mrDocShell
.GetCreateMode() == SfxObjectCreateMode::ORGANIZER
)
374 xInfoSet
->setPropertyValue(u
"OrganizerMode"_ustr
, uno::Any(true));
376 xInfoSet
->setPropertyValue( u
"SourceStorage"_ustr
, uno::Any( xStorage
) );
378 bool bOasis
= ( SotStorage::GetVersion( xStorage
) > SOFFICE_FILEFORMAT_60
);
380 if ((nMode
& ImportFlags::Metadata
) && bOasis
)
382 // RDF metadata: ODF >= 1.2
385 const uno::Reference
< rdf::XDocumentMetadataAccess
> xDMA(
386 xModel
, uno::UNO_QUERY_THROW
);
387 const uno::Reference
< rdf::XURI
> xBaseURI(
388 ::sfx2::createBaseURI( xContext
, xModel
, aBaseURL
, aName
) );
389 uno::Reference
<task::XInteractionHandler
> xHandler
=
390 mrDocShell
.GetMedium()->GetInteractionHandler();
391 xDMA
->loadMetadataFromStorage( xStorage
, xBaseURI
, xHandler
);
393 catch ( const lang::WrappedTargetException
& e
)
395 ucb::InteractiveAugmentedIOException iaioe
;
396 if ( e
.TargetException
>>= iaioe
)
398 rError
= SCERR_IMPORT_UNKNOWN
;
402 rError
= SCWARN_IMPORT_FEATURES_LOST
;
405 catch ( const uno::Exception
&)
407 rError
= SCWARN_IMPORT_FEATURES_LOST
;
411 // #i103539#: always read meta.xml for generator
412 ErrCodeMsg
nMetaRetval(ERRCODE_NONE
);
413 if (nMode
& ImportFlags::Metadata
)
415 uno::Sequence
<uno::Any
> aMetaArgs
{ Any(xInfoSet
) };
417 SAL_INFO( "sc.filter", "meta import start" );
419 nMetaRetval
= ImportFromComponent(
420 xContext
, xModel
, aParserInput
,
421 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisMetaImporter"_ustr
422 : u
"com.sun.star.comp.Calc.XMLMetaImporter"_ustr
,
423 u
"meta.xml"_ustr
, aMetaArgs
, false);
425 SAL_INFO( "sc.filter", "meta import end" );
428 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
429 uno::Reference
<document::XGraphicStorageHandler
> xGraphicStorageHandler
;
431 uno::Reference
< document::XEmbeddedObjectResolver
> xObjectResolver
;
432 rtl::Reference
<SvXMLEmbeddedObjectHelper
> xObjectHelper
;
436 xGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, SvXMLGraphicHelperMode::Read
);
437 xGraphicStorageHandler
= xGraphicHelper
.get();
439 xObjectHelper
= SvXMLEmbeddedObjectHelper::Create(xStorage
, mrDocShell
, SvXMLEmbeddedObjectHelperMode::Read
);
440 xObjectResolver
= xObjectHelper
.get();
442 uno::Sequence
<uno::Any
> aStylesArgs
445 Any(xGraphicStorageHandler
),
446 Any(xStatusIndicator
),
450 ErrCodeMsg
nSettingsRetval(ERRCODE_NONE
);
451 if (nMode
& ImportFlags::Settings
)
453 // Settings must be loaded first because of the printer setting,
454 // which is needed in the page styles (paper tray).
456 uno::Sequence
<uno::Any
> aSettingsArgs
{ Any(xInfoSet
) };
458 SAL_INFO( "sc.filter", "settings import start" );
460 nSettingsRetval
= ImportFromComponent(
461 xContext
, xModel
, aParserInput
,
462 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisSettingsImporter"_ustr
463 : u
"com.sun.star.comp.Calc.XMLSettingsImporter"_ustr
,
464 u
"settings.xml"_ustr
, aSettingsArgs
, false);
466 SAL_INFO( "sc.filter", "settings import end" );
469 ErrCodeMsg
nStylesRetval(ERRCODE_NONE
);
470 if (nMode
& ImportFlags::Styles
)
472 SAL_INFO( "sc.filter", "styles import start" );
474 nStylesRetval
= ImportFromComponent(xContext
, xModel
, aParserInput
,
475 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisStylesImporter"_ustr
476 : u
"com.sun.star.comp.Calc.XMLStylesImporter"_ustr
,
480 SAL_INFO( "sc.filter", "styles import end" );
483 ErrCodeMsg
nDocRetval(ERRCODE_NONE
);
484 if (nMode
& ImportFlags::Content
)
486 if (mrDocShell
.GetCreateMode() == SfxObjectCreateMode::INTERNAL
)
487 // We only need to import content for external link cache document.
488 xInfoSet
->setPropertyValue(SC_UNO_ODS_IMPORT_STYLES
, uno::Any(false));
490 uno::Sequence
<uno::Any
> aDocArgs
493 Any(xGraphicStorageHandler
),
494 Any(xStatusIndicator
),
498 SAL_INFO( "sc.filter", "content import start" );
500 nDocRetval
= ImportFromComponent(xContext
, xModel
, aParserInput
,
501 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisContentImporter"_ustr
502 : u
"com.sun.star.comp.Calc.XMLContentImporter"_ustr
,
507 SAL_INFO( "sc.filter", "content import end" );
509 if( xGraphicHelper
.is() )
510 xGraphicHelper
->dispose();
511 xGraphicHelper
.clear();
513 if( xObjectHelper
.is() )
514 xObjectHelper
->dispose();
515 xObjectHelper
.clear();
517 if (xStatusIndicator
.is())
518 xStatusIndicator
->end();
521 rError
= std::move(nDocRetval
);
522 else if (nStylesRetval
)
523 rError
= std::move(nStylesRetval
);
524 else if (nMetaRetval
)
525 rError
= std::move(nMetaRetval
);
526 else if (nSettingsRetval
)
527 rError
= std::move(nSettingsRetval
);
529 bool bRet
= !rError
.IsError();
531 ::svx::DropUnusedNamedItems(xModel
);
533 // set BuildId on XModel for later OLE object loading
536 uno::Reference
< beans::XPropertySet
> xModelSet( xModel
, uno::UNO_QUERY
);
539 uno::Reference
< beans::XPropertySetInfo
> xModelSetInfo( xModelSet
->getPropertySetInfo() );
540 OUString
sBuildPropName(u
"BuildId"_ustr
);
541 if( xModelSetInfo
.is() && xModelSetInfo
->hasPropertyByName(sBuildPropName
) )
543 xModelSet
->setPropertyValue( sBuildPropName
, xInfoSet
->getPropertyValue(sBuildPropName
) );
548 uno::Any aAny
= xInfoSet
->getPropertyValue(u
"ScriptConfiguration"_ustr
);
549 uno::Reference
<container::XNameAccess
> xCodeNameAccess
;
550 if( aAny
>>= xCodeNameAccess
)
551 XMLCodeNameProvider::set( xCodeNameAccess
, &rDoc
);
554 bool bVBACompat
= false;
555 if ( (xInfoSet
->getPropertyValue(u
"VBACompatibilityMode"_ustr
) >>= bVBACompat
) && bVBACompat
)
557 /* Set library container to VBA compatibility mode, this
558 forces loading the Basic project, which in turn creates the
559 VBA Globals object and does all related initialization. */
560 if ( xModelSet
.is() ) try
562 uno::Reference
< script::vba::XVBACompatibility
> xVBACompat( xModelSet
->getPropertyValue(
563 u
"BasicLibraries"_ustr
), uno::UNO_QUERY_THROW
);
564 xVBACompat
->setVBACompatibilityMode( true );
566 catch( const uno::Exception
& )
572 // Don't test bStylesRetval and bMetaRetval, because it could be an older file which not contain such streams
573 return bRet
;//!bStylesOnly ? bDocRetval : bStylesRetval;
576 static bool lcl_HasValidStream(const ScDocument
& rDoc
)
578 ScDocShell
* pObjSh
= rDoc
.GetDocumentShell();
579 if ( pObjSh
->IsDocShared() )
580 return false; // never copy stream from shared file
582 // don't read remote file again
583 // (could instead re-use medium directly in that case)
584 SfxMedium
* pSrcMed
= rDoc
.GetDocumentShell()->GetMedium();
585 if ( !pSrcMed
|| pSrcMed
->IsRemote() )
588 SCTAB nTabCount
= rDoc
.GetTableCount();
589 for (SCTAB nTab
=0; nTab
<nTabCount
; ++nTab
)
590 if (rDoc
.IsStreamValid(nTab
))
595 bool ScXMLImportWrapper::ExportToComponent(const uno::Reference
<uno::XComponentContext
>& xContext
,
596 const uno::Reference
<frame::XModel
>& xModel
, const uno::Reference
<xml::sax::XWriter
>& xWriter
,
597 const uno::Sequence
<beans::PropertyValue
>& aDescriptor
, const OUString
& sName
,
598 const OUString
& sMediaType
, const OUString
& sComponentName
,
599 const uno::Sequence
<uno::Any
>& aArgs
, std::unique_ptr
<ScMySharedData
>& pSharedData
)
602 uno::Reference
<io::XOutputStream
> xOut
;
603 uno::Reference
<io::XStream
> xStream
;
605 if ( !xStorage
.is() && pMedium
)
606 xStorage
= pMedium
->GetOutputStorage();
610 // #96807#; trunc stream before use, because it could be an existing stream
611 // and the new content could be shorter than the old content. In this case
612 // would not all be over written by the new content and the xml file
613 // would not be valid.
614 xStream
= xStorage
->openStreamElement( sName
, embed::ElementModes::READWRITE
| embed::ElementModes::TRUNCATE
);
615 uno::Reference
< beans::XPropertySet
> xSet( xStream
, uno::UNO_QUERY
);
618 xSet
->setPropertyValue(u
"MediaType"_ustr
, uno::Any(sMediaType
));
620 // advise storage impl to use common encryption
621 xSet
->setPropertyValue( u
"UseCommonStoragePasswordEncryption"_ustr
, uno::Any(true) );
624 xOut
= xStream
->getOutputStream();
628 uno::Reference
< beans::XPropertySet
> xInfoSet
;
629 if( aArgs
.hasElements() )
630 aArgs
.getConstArray()[0] >>= xInfoSet
;
631 OSL_ENSURE( xInfoSet
.is(), "missing property set" );
634 xInfoSet
->setPropertyValue( u
"StreamName"_ustr
, uno::Any( sName
) );
637 xWriter
->setOutputStream( xOut
);
639 uno::Reference
<document::XFilter
> xFilter(
640 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
641 sComponentName
, aArgs
, xContext
),
643 OSL_ENSURE( xFilter
.is(), "can't get exporter" );
644 uno::Reference
<document::XExporter
> xExporter( xFilter
, uno::UNO_QUERY
);
646 xExporter
->setSourceDocument( xModel
);
650 ScXMLExport
* pExport
= static_cast<ScXMLExport
*>(dynamic_cast<SvXMLExport
*>(xFilter
.get()));
651 assert(pExport
&& "can only succeed");
652 pExport
->SetSharedData(std::move(pSharedData
));
654 // if there are sheets to copy, get the source stream
655 if ( sName
== "content.xml" && lcl_HasValidStream(rDoc
) && ( pExport
->getExportFlags() & SvXMLExportFlags::OASIS
) )
657 // old stream is still in this file's storage - open read-only
659 // #i106854# use the document's storage directly, without a temporary SfxMedium
660 uno::Reference
<embed::XStorage
> xTmpStorage
= rDoc
.GetDocumentShell()->GetStorage();
661 uno::Reference
<io::XStream
> xSrcStream
;
662 uno::Reference
<io::XInputStream
> xSrcInput
;
664 // #i108978# If an embedded object is saved and no events are notified, don't use the stream
665 // because without the ...DONE events, stream positions aren't updated.
666 ScSheetSaveData
* pSheetData
= comphelper::getFromUnoTunnel
<ScModelObj
>(xModel
)->GetSheetSaveData();
667 if (pSheetData
&& pSheetData
->IsInSupportedSave())
671 if (xTmpStorage
.is())
672 xSrcStream
= xTmpStorage
->openStreamElement( sName
, embed::ElementModes::READ
);
674 xSrcInput
= xSrcStream
->getInputStream();
676 catch ( const uno::Exception
&)
678 // stream not available (for example, password protected) - save normally (xSrcInput is null)
682 pExport
->SetSourceStream( xSrcInput
);
683 bRet
= xFilter
->filter( aDescriptor
);
684 pExport
->SetSourceStream( uno::Reference
<io::XInputStream
>() );
686 // If there was an error, reset all stream flags, so the next save attempt will use normal saving.
687 // #i110692# For embedded objects, the stream may be unavailable for one save operation (m_pAntiImpl)
688 // and become available again later. But after saving normally once, the stream positions aren't
689 // valid anymore, so the flags also have to be reset if the stream wasn't available.
690 if ( !bRet
|| !xSrcInput
.is() )
692 SCTAB nTabCount
= rDoc
.GetTableCount();
693 for (SCTAB nTab
=0; nTab
<nTabCount
; nTab
++)
694 rDoc
.SetStreamValid(nTab
, false);
698 bRet
= xFilter
->filter( aDescriptor
);
700 pSharedData
= pExport
->ReleaseSharedData();
706 bool ScXMLImportWrapper::Export(bool bStylesOnly
)
708 // Prevent all broadcasting and repaints and notification of accessibility
709 // during mass creation of captions, which is a major bottleneck and not
710 // needed during Save.
711 ScDrawLayer
* pDrawLayer
= rDoc
.GetDrawLayer();
712 bool bOldLock
= bool();
715 bOldLock
= pDrawLayer
->isLocked();
716 pDrawLayer
->setLock(true);
719 rDoc
.CreateAllNoteCaptions();
722 pDrawLayer
->setLock(bOldLock
);
724 const uno::Reference
<uno::XComponentContext
>& xContext(comphelper::getProcessComponentContext());
726 uno::Reference
<xml::sax::XWriter
> xWriter
= xml::sax::Writer::create(xContext
);
728 if ( !xStorage
.is() && pMedium
)
729 xStorage
= pMedium
->GetOutputStorage();
733 sFileName
= pMedium
->GetName();
734 ScDocShell
* pObjSh
= rDoc
.GetDocumentShell();
735 uno::Sequence
<beans::PropertyValue
> aDescriptor( comphelper::InitPropertySequence({
736 { "FileName", uno::Any(sFileName
) }
739 /** property map for export info set */
740 static comphelper::PropertyMapEntry
const aExportInfoMap
[] =
742 { u
"ProgressRange"_ustr
, 0, ::cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
743 { u
"ProgressMax"_ustr
, 0, ::cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
744 { u
"ProgressCurrent"_ustr
, 0, ::cppu::UnoType
<sal_Int32
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
745 { u
"WrittenNumberStyles"_ustr
, 0, cppu::UnoType
<uno::Sequence
<sal_Int32
>>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
746 { u
"UsePrettyPrinting"_ustr
, 0, ::cppu::UnoType
<sal_Bool
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0},
747 { u
"BaseURI"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
748 { u
"StreamRelPath"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
749 { u
"StreamName"_ustr
, 0, ::cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
750 { u
"StyleNames"_ustr
, 0, cppu::UnoType
<uno::Sequence
<OUString
>>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
751 { u
"StyleFamilies"_ustr
, 0, cppu::UnoType
<uno::Sequence
<sal_Int32
>>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
752 { u
"TargetStorage"_ustr
, 0, cppu::UnoType
<embed::XStorage
>::get(), css::beans::PropertyAttribute::MAYBEVOID
, 0 },
754 uno::Reference
< beans::XPropertySet
> xInfoSet( comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap
) ) );
756 if ( pObjSh
&& xStorage
.is() )
758 uno::Reference
<frame::XModel
> xModel(pObjSh
->GetModel());
759 // sorting wants to create undo actions
760 assert(SfxObjectCreateMode::STANDARD
!= pObjSh
->GetCreateMode() || rDoc
.GetDrawLayer()->IsUndoEnabled());
761 uno::Reference
<drawing::XDrawPagesSupplier
> const xDPS(xModel
, uno::UNO_QUERY
);
762 uno::Reference
<container::XIndexAccess
> const xDPs(xDPS
->getDrawPages());
764 for (auto i
= xDPs
->getCount(); 0 < i
; )
767 uno::Reference
<drawing::XShapes
> const xDP(xDPs
->getByIndex(i
), uno::UNO_QUERY
);
769 xmloff::FixZOrder(xDP
,
770 [](uno::Reference
<beans::XPropertySet
> const& xShape
)
772 sal_Int16
nLayerID(0);
773 xShape
->getPropertyValue(u
"LayerID"_ustr
) >>= nLayerID
;
776 case sal_Int16(SC_LAYER_FRONT
):
778 case sal_Int16(SC_LAYER_BACK
):
780 case sal_Int16(SC_LAYER_INTERN
):
782 case sal_Int16(SC_LAYER_CONTROLS
):
784 case sal_Int16(SC_LAYER_HIDDEN
):
785 return 1; // treat as equivalent to front
792 uno::Reference
<task::XStatusIndicator
> xStatusIndicator(GetStatusIndicator());
793 sal_Int32
nProgressRange(1000000);
794 if(xStatusIndicator
.is())
795 xStatusIndicator
->start(ScResId(STR_SAVE_DOC
), nProgressRange
);
796 xInfoSet
->setPropertyValue(u
"ProgressRange"_ustr
, uno::Any(nProgressRange
));
798 bool bUsePrettyPrinting
= officecfg::Office::Common::Save::Document::PrettyPrinting::get();
799 xInfoSet
->setPropertyValue(u
"UsePrettyPrinting"_ustr
, uno::Any(bUsePrettyPrinting
));
801 xInfoSet
->setPropertyValue( u
"TargetStorage"_ustr
, uno::Any( xStorage
) );
803 OSL_ENSURE( pMedium
, "There is no medium to get MediaDescriptor from!" );
804 OUString aBaseURL
= pMedium
? pMedium
->GetBaseURL( true ) : OUString();
805 OUString
sPropName(u
"BaseURI"_ustr
);
806 xInfoSet
->setPropertyValue( sPropName
, uno::Any( aBaseURL
) );
808 // TODO/LATER: do not do it for embedded links
809 if( SfxObjectCreateMode::EMBEDDED
== pObjSh
->GetCreateMode() )
811 OUString
aName(u
"dummyObjectName"_ustr
);
814 const SfxStringItem
* pDocHierarchItem
=
815 pMedium
->GetItemSet().GetItem(SID_DOC_HIERARCHICALNAME
);
816 if ( pDocHierarchItem
)
817 aName
= pDocHierarchItem
->GetValue();
820 if( !aName
.isEmpty() )
822 sPropName
= "StreamRelPath";
823 xInfoSet
->setPropertyValue( sPropName
, uno::Any( aName
) );
827 OUString
sTextMediaType(u
"text/xml"_ustr
);
828 bool bMetaRet(pObjSh
->GetCreateMode() == SfxObjectCreateMode::EMBEDDED
);
829 bool bStylesRet (false);
831 bool bSettingsRet(false);
832 std::unique_ptr
<ScMySharedData
> pSharedData
;
834 bool bOasis
= ( SotStorage::GetVersion( xStorage
) > SOFFICE_FILEFORMAT_60
);
836 // RDF metadata: ODF >= 1.2
837 if ( !bStylesOnly
&& bOasis
)
839 const uno::Reference
< beans::XPropertySet
> xPropSet( xStorage
, uno::UNO_QUERY_THROW
);
843 if (( xPropSet
->getPropertyValue(u
"Version"_ustr
) >>= aVersion
)
844 && aVersion
!= ODFVER_010_TEXT
845 && aVersion
!= ODFVER_011_TEXT
)
847 const uno::Reference
< rdf::XDocumentMetadataAccess
> xDMA(
848 xModel
, uno::UNO_QUERY_THROW
);
849 xDMA
->storeMetadataToStorage( xStorage
);
852 catch ( const beans::UnknownPropertyException
&)
855 catch ( const uno::Exception
&)
861 if (!bStylesOnly
&& !bMetaRet
)
863 uno::Sequence
<uno::Any
> aMetaArgs
867 Any(xStatusIndicator
)
870 SAL_INFO( "sc.filter", "meta export start" );
872 bMetaRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
875 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisMetaExporter"_ustr
876 : u
"com.sun.star.comp.Calc.XMLMetaExporter"_ustr
,
877 aMetaArgs
, pSharedData
);
879 SAL_INFO( "sc.filter", "meta export end" );
882 uno::Reference
<document::XGraphicStorageHandler
> xGraphicStorageHandler
;
883 rtl::Reference
<SvXMLGraphicHelper
> xGraphicHelper
;
887 xGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, SvXMLGraphicHelperMode::Write
);
888 xGraphicStorageHandler
= xGraphicHelper
.get();
891 auto xObjectHelper
= SvXMLEmbeddedObjectHelper::Create(
892 xStorage
, *pObjSh
, SvXMLEmbeddedObjectHelperMode::Write
);
893 uno::Reference
<document::XEmbeddedObjectResolver
> xObjectResolver(xObjectHelper
);
898 uno::Sequence
<uno::Any
> aStylesArgs
901 Any(xGraphicStorageHandler
),
902 Any(xStatusIndicator
),
907 SAL_INFO( "sc.filter", "styles export start" );
909 bStylesRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
912 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisStylesExporter"_ustr
913 : u
"com.sun.star.comp.Calc.XMLStylesExporter"_ustr
,
914 aStylesArgs
, pSharedData
);
916 SAL_INFO( "sc.filter", "styles export end" );
923 uno::Sequence
<uno::Any
> aDocArgs
926 Any(xGraphicStorageHandler
),
927 Any(xStatusIndicator
),
932 SAL_INFO( "sc.filter", "content export start" );
934 bDocRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
937 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisContentExporter"_ustr
938 : u
"com.sun.star.comp.Calc.XMLContentExporter"_ustr
,
939 aDocArgs
, pSharedData
);
941 SAL_INFO( "sc.filter", "content export end" );
945 xGraphicHelper
->dispose();
946 xGraphicHelper
.clear();
949 xObjectHelper
->dispose();
950 xObjectHelper
.clear();
956 uno::Sequence
<uno::Any
> aSettingsArgs
960 Any(xStatusIndicator
)
963 SAL_INFO( "sc.filter", "settings export start" );
965 bSettingsRet
= ExportToComponent(xContext
, xModel
, xWriter
, aDescriptor
,
966 u
"settings.xml"_ustr
,
968 bOasis
? u
"com.sun.star.comp.Calc.XMLOasisSettingsExporter"_ustr
969 : u
"com.sun.star.comp.Calc.XMLSettingsExporter"_ustr
,
970 aSettingsArgs
, pSharedData
);
972 SAL_INFO( "sc.filter", "settings export end" );
977 if (xStatusIndicator
.is())
978 xStatusIndicator
->end();
979 return bStylesRet
&& ((!bStylesOnly
&& bDocRet
&& bMetaRet
&& bSettingsRet
) || bStylesOnly
);
982 // later: give string descriptor as parameter for doc type
987 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */