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 <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"
72 #include <drwlayer.hxx>
73 #include <sheetdata.hxx>
74 #include "XMLCodeNameProvider.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
) :
83 rDoc(rDocSh
.GetDocument()),
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
;
95 SfxItemSet
* pSet
= pMedium
->GetItemSet();
98 const SfxUnoAnyItem
* pItem
= pSet
->GetItem
<SfxUnoAnyItem
>(SID_PROGRESS_STATUSBAR_CONTROL
);
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
);
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
;
133 aParserInput
.aInputStream
= xDocStream
->getInputStream();
134 uno::Reference
< beans::XPropertySet
> xSet( xDocStream
, uno::UNO_QUERY
);
136 uno::Any aAny
= xSet
->getPropertyValue("Encrypted");
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
;
153 return SCERR_IMPORT_UNKNOWN
;
156 uno::Reference
< beans::XPropertySet
> xInfoSet
;
157 if( aArgs
.hasElements() )
158 aArgs
.getConstArray()[0] >>= xInfoSet
;
159 OSL_ENSURE( xInfoSet
.is(), "missing property set" );
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
),
172 OSL_ENSURE( xDocHandler
.is(), "can't get Calc importer" );
173 uno::Reference
<document::XImporter
> xImporter( xDocHandler
, uno::UNO_QUERY
);
175 xImporter
->setTargetDocument( xModel
);
177 ScXMLImport
* pImporterImpl
= dynamic_cast<ScXMLImport
*>(xImporter
.get());
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
);
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;
203 xml::sax::SAXException aTmp
;
204 if ( aSaxEx
.WrappedException
>>= aTmp
)
210 packages::zip::ZipIOException aBrokenPackage
;
211 if ( aSaxEx
.WrappedException
>>= aBrokenPackage
)
212 return ERRCODE_IO_BROKENPACKAGE
;
213 else if( bEncrypted
)
214 nReturn
= ERRCODE_SFX_WRONGPASSWORD
;
217 SAL_WARN("sc.filter", "SAX parse exception caught while importing: " << exceptionToString(ex
));
219 OUString sErr
= OUString::number( r
.LineNumber
) +
221 OUString::number( r
.ColumnNumber
);
223 if( !sDocName
.isEmpty() )
225 nReturn
= *new TwoStringErrorInfo(
226 (bMustBeSuccessfull
? SCERR_IMPORT_FILE_ROWCOL
227 : SCWARN_IMPORT_FILE_ROWCOL
),
229 DialogMask::ButtonsOk
| DialogMask::MessageError
);
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
;
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 );
288 bool ScXMLImportWrapper::Import( ImportFlags nMode
, ErrCode
& rError
)
290 uno::Reference
<uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
292 xml::sax::InputSource aParserInput
;
294 aParserInput
.sSystemId
= pMedium
->GetName();
296 if ( !xStorage
.is() && pMedium
)
297 xStorage
= pMedium
->GetStorage();
300 uno::Reference
<xml::sax::XParser
> xXMLParser
= xml::sax::Parser::create(xContext
);
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
);
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
));
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
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();
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
;
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
;
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"),
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"),
517 "Content.xml", aDocArgs
,
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();
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
)
543 else if (nStylesRetval
)
544 rError
= nStylesRetval
;
545 else if (nMetaRetval
)
546 rError
= nMetaRetval
;
547 else if (nSettingsRetval
)
548 rError
= nSettingsRetval
;
552 // set BuildId on XModel for later OLE object loading
555 uno::Reference
< beans::XPropertySet
> xModelSet( xModel
, uno::UNO_QUERY
);
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
) );
567 uno::Any aAny
= xInfoSet
->getPropertyValue("ScriptConfiguration");
568 uno::Reference
<container::XNameAccess
> xCodeNameAccess
;
569 if( aAny
>>= xCodeNameAccess
)
570 XMLCodeNameProvider::set( xCodeNameAccess
, &rDoc
);
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() )
607 SCTAB nTabCount
= rDoc
.GetTableCount();
608 for (SCTAB nTab
=0; nTab
<nTabCount
; ++nTab
)
609 if (rDoc
.IsStreamValid(nTab
))
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
)
621 uno::Reference
<io::XOutputStream
> xOut
;
622 uno::Reference
<io::XStream
> xStream
;
624 if ( !xStorage
.is() && pMedium
)
625 xStorage
= pMedium
->GetOutputStorage();
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
);
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();
647 uno::Reference
< beans::XPropertySet
> xInfoSet
;
648 if( aArgs
.hasElements() )
649 aArgs
.getConstArray()[0] >>= xInfoSet
;
650 OSL_ENSURE( xInfoSet
.is(), "missing property set" );
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
),
662 OSL_ENSURE( xFilter
.is(), "can't get exporter" );
663 uno::Reference
<document::XExporter
> xExporter( xFilter
, uno::UNO_QUERY
);
665 xExporter
->setSourceDocument( xModel
);
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
);
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);
716 bRet
= xFilter
->filter( aDescriptor
);
718 pSharedData
= pExport
->ReleaseSharedData();
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();
733 bOldLock
= pDrawLayer
->isLocked();
734 pDrawLayer
->setLock(true);
737 rDoc
.CreateAllNoteCaptions();
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();
750 OUString
sTextMediaType("text/xml");
752 sFileName
= pMedium
->GetName();
753 SfxObjectShell
* pObjSh
= rDoc
.GetDocumentShell();
754 uno::Sequence
<beans::PropertyValue
> aDescriptor( comphelper::InitPropertySequence({
755 { "FileName", uno::Any(sFileName
) }
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);
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
);
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
&)
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
,
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
;
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());
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
,
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" );
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
,
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" );
930 xGraphicHelper
->dispose();
931 xGraphicHelper
.clear();
934 xObjectHelper
->dispose();
935 xObjectHelper
.clear();
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
,
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" );
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
971 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */