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 <config_features.h>
22 #include <sal/config.h>
26 #include <vcl/msgbox.hxx>
27 #include <svl/eitem.hxx>
28 #include <svl/stritem.hxx>
29 #include <svl/intitem.hxx>
30 #include <com/sun/star/frame/theGlobalEventBroadcaster.hpp>
31 #include <com/sun/star/frame/XStorable.hpp>
32 #include <com/sun/star/frame/XModel.hpp>
33 #include <com/sun/star/frame/XFrame.hpp>
34 #include <com/sun/star/document/XFilter.hpp>
35 #include <com/sun/star/document/XImporter.hpp>
36 #include <com/sun/star/document/XExporter.hpp>
37 #include <com/sun/star/document/XInteractionFilterOptions.hpp>
38 #include <com/sun/star/packages/zip/ZipIOException.hpp>
39 #include <com/sun/star/task/XInteractionHandler.hpp>
40 #include <com/sun/star/task/XInteractionAskLater.hpp>
41 #include <com/sun/star/task/InteractionClassification.hpp>
42 #include <com/sun/star/lang/XInitialization.hpp>
43 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
44 #include <com/sun/star/document/MacroExecMode.hpp>
45 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
46 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
47 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
48 #include <com/sun/star/beans/XPropertySetInfo.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/beans/XPropertyAccess.hpp>
51 #include <com/sun/star/beans/PropertyValue.hpp>
52 #include <com/sun/star/beans/XPropertySet.hpp>
53 #include <com/sun/star/container/XNameAccess.hpp>
54 #include <com/sun/star/container/XSet.hpp>
55 #include <com/sun/star/embed/ElementModes.hpp>
56 #include <com/sun/star/embed/EmbedStates.hpp>
57 #include <com/sun/star/embed/Aspects.hpp>
58 #include <com/sun/star/embed/XTransactedObject.hpp>
59 #include <com/sun/star/embed/XEmbedPersist.hpp>
60 #include <com/sun/star/embed/XLinkageSupport.hpp>
61 #include <com/sun/star/embed/EntryInitModes.hpp>
62 #include <com/sun/star/embed/XOptimizedStorage.hpp>
63 #include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
64 #include <com/sun/star/io/XTruncate.hpp>
65 #include <com/sun/star/util/XModifiable.hpp>
66 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
67 #include <com/sun/star/text/XTextRange.hpp>
68 #include <com/sun/star/xml/crypto/CipherID.hpp>
69 #include <com/sun/star/xml/crypto/DigestID.hpp>
71 #include <com/sun/star/document/XDocumentProperties.hpp>
72 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
73 #include <comphelper/processfactory.hxx>
74 #include <comphelper/interaction.hxx>
75 #include <svtools/sfxecode.hxx>
76 #include <unotools/securityoptions.hxx>
77 #include <cppuhelper/weak.hxx>
78 #include <unotools/streamwrap.hxx>
80 #include <unotools/saveopt.hxx>
81 #include <unotools/useroptions.hxx>
82 #include <unotools/pathoptions.hxx>
83 #include <tools/urlobj.hxx>
84 #include <tools/diagnose_ex.h>
85 #include <unotools/localfilehelper.hxx>
86 #include <unotools/ucbhelper.hxx>
87 #include <unotools/tempfile.hxx>
88 #include <unotools/docinfohelper.hxx>
89 #include <ucbhelper/content.hxx>
90 #include <sot/storage.hxx>
91 #include <sot/storinfo.hxx>
92 #include <sot/exchange.hxx>
93 #include <sot/formats.hxx>
94 #include <comphelper/storagehelper.hxx>
95 #include <comphelper/seqstream.hxx>
96 #include <comphelper/documentconstants.hxx>
97 #include <comphelper/string.hxx>
98 #include <vcl/bitmapex.hxx>
99 #include <svtools/embedhlp.hxx>
100 #include <basic/modsizeexceeded.hxx>
101 #include <officecfg/Office/Common.hxx>
102 #include <osl/file.hxx>
104 #include <sfx2/signaturestate.hxx>
105 #include <sfx2/app.hxx>
106 #include <sfx2/objsh.hxx>
107 #include <sfx2/childwin.hxx>
108 #include <sfx2/request.hxx>
109 #include <sfx2/sfxresid.hxx>
110 #include <sfx2/docfile.hxx>
111 #include <sfx2/fcontnr.hxx>
112 #include <sfx2/docfilt.hxx>
113 #include <sfx2/docfac.hxx>
114 #include "appopen.hxx"
115 #include "objshimp.hxx"
116 #include "sfxtypes.hxx"
118 #include <sfx2/sfxsids.hrc>
119 #include <sfx2/module.hxx>
120 #include <sfx2/dispatch.hxx>
121 #include "openflag.hxx"
122 #include "helper.hxx"
123 #include <sfx2/event.hxx>
124 #include "fltoptint.hxx"
125 #include <sfx2/viewfrm.hxx>
126 #include "graphhelp.hxx"
127 #include "appbaslib.hxx"
128 #include "appdata.hxx"
129 #include <objstor.hxx>
131 #include "../appl/app.hrc"
133 using namespace ::com::sun::star
;
134 using namespace ::com::sun::star::container
;
135 using namespace ::com::sun::star::lang
;
136 using namespace ::com::sun::star::ui::dialogs
;
137 using namespace ::com::sun::star::uno
;
138 using namespace ::com::sun::star::beans
;
139 using namespace ::com::sun::star::ucb
;
140 using namespace ::com::sun::star::task
;
141 using namespace ::com::sun::star::document
;
142 using namespace ::cppu
;
145 void impl_addToModelCollection(const css::uno::Reference
< css::frame::XModel
>& xModel
)
150 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
151 css::uno::Reference
< css::frame::XGlobalEventBroadcaster
> xModelCollection
=
152 css::frame::theGlobalEventBroadcaster::get(xContext
);
155 xModelCollection
->insert(css::uno::makeAny(xModel
));
157 catch ( uno::Exception
& )
159 SAL_WARN( "sfx.doc", "The document seems to be in the collection already!\n" );
165 bool SfxObjectShell::Save()
167 return SaveChildren();
172 bool SfxObjectShell::SaveAs( SfxMedium
& rMedium
)
174 return SaveAsChildren( rMedium
);
179 bool SfxObjectShell::QuerySlotExecutable( sal_uInt16
/*nSlotId*/ )
186 bool GetEncryptionData_Impl( const SfxItemSet
* pSet
, uno::Sequence
< beans::NamedValue
>& o_rEncryptionData
)
188 bool bResult
= false;
191 SFX_ITEMSET_ARG( pSet
, pEncryptionDataItem
, SfxUnoAnyItem
, SID_ENCRYPTIONDATA
, false);
192 if ( pEncryptionDataItem
)
194 pEncryptionDataItem
->GetValue() >>= o_rEncryptionData
;
199 SFX_ITEMSET_ARG( pSet
, pPasswordItem
, SfxStringItem
, SID_PASSWORD
, false);
202 OUString aPassword
= pPasswordItem
->GetValue();
203 o_rEncryptionData
= ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPassword
);
213 bool SfxObjectShell::PutURLContentsToVersionStream_Impl(
214 const OUString
& aURL
,
215 const uno::Reference
< embed::XStorage
>& xDocStorage
,
216 const OUString
& aStreamName
)
218 bool bResult
= false;
221 uno::Reference
< embed::XStorage
> xVersion
= xDocStorage
->openStorageElement(
222 OUString("Versions"),
223 embed::ElementModes::READWRITE
);
225 DBG_ASSERT( xVersion
.is(),
226 "The method must throw an exception if the storage can not be opened!\n" );
227 if ( !xVersion
.is() )
228 throw uno::RuntimeException();
230 uno::Reference
< io::XStream
> xVerStream
= xVersion
->openStreamElement(
232 embed::ElementModes::READWRITE
);
233 DBG_ASSERT( xVerStream
.is(), "The method must throw an exception if the storage can not be opened!\n" );
234 if ( !xVerStream
.is() )
235 throw uno::RuntimeException();
237 uno::Reference
< io::XOutputStream
> xOutStream
= xVerStream
->getOutputStream();
238 uno::Reference
< io::XTruncate
> xTrunc( xOutStream
, uno::UNO_QUERY
);
240 DBG_ASSERT( xTrunc
.is(), "The output stream must exist and implement XTruncate interface!\n" );
242 throw RuntimeException();
244 uno::Reference
< io::XInputStream
> xTmpInStream
=
245 ::comphelper::OStorageHelper::GetInputStreamFromURL(
246 aURL
, comphelper::getProcessComponentContext() );
247 assert( xTmpInStream
.is() );
250 ::comphelper::OStorageHelper::CopyInputToOutput( xTmpInStream
, xOutStream
);
251 xOutStream
->closeOutput();
253 uno::Reference
< embed::XTransactedObject
> xTransact( xVersion
, uno::UNO_QUERY
);
254 DBG_ASSERT( xTransact
.is(), "The storage must implement XTransacted interface!\n" );
255 if ( xTransact
.is() )
260 catch( uno::Exception
& )
262 // TODO/LATER: handle the error depending on exception
263 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
270 OUString
SfxObjectShell::CreateTempCopyOfStorage_Impl( const uno::Reference
< embed::XStorage
>& xStorage
)
272 OUString aTempURL
= ::utl::TempFile().GetURL();
274 DBG_ASSERT( !aTempURL
.isEmpty(), "Can't create a temporary file!\n" );
275 if ( !aTempURL
.isEmpty() )
279 uno::Reference
< embed::XStorage
> xTempStorage
=
280 ::comphelper::OStorageHelper::GetStorageFromURL( aTempURL
, embed::ElementModes::READWRITE
);
282 // the password will be transferred from the xStorage to xTempStorage by storage implementation
283 xStorage
->copyToStorage( xTempStorage
);
285 // the temporary storage was committed by the previous method and it will die by refcount
287 catch ( uno::Exception
& )
289 SAL_WARN( "sfx.doc", "Creation of a storage copy is failed!" );
290 ::utl::UCBContentHelper::Kill( aTempURL
);
294 // TODO/LATER: may need error code setting based on exception
295 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
303 SvGlobalName
SfxObjectShell::GetClassName() const
305 return GetFactory().GetClassId();
311 * Chart2 does not have an Object shell, so handle this here for now
312 * If we ever implement a full scale object shell in chart2 move it there
314 SotClipboardFormatId
GetChartVersion( sal_Int32 nVersion
, bool bTemplate
)
316 if( nVersion
== SOFFICE_FILEFORMAT_60
)
318 return SotClipboardFormatId::STARCHART_60
;
320 else if( nVersion
== SOFFICE_FILEFORMAT_8
)
324 SAL_WARN("sfx", "no chart template support yet");
325 return SotClipboardFormatId::STARCHART_8
;
328 return SotClipboardFormatId::STARCHART_8
;
331 SAL_WARN("sfx", "unsupported version");
332 return SotClipboardFormatId::NONE
;
338 void SfxObjectShell::SetupStorage( const uno::Reference
< embed::XStorage
>& xStorage
,
339 sal_Int32 nVersion
, bool bTemplate
, bool bChart
) const
341 uno::Reference
< beans::XPropertySet
> xProps( xStorage
, uno::UNO_QUERY
);
346 OUString aFullTypeName
, aShortTypeName
, aAppName
;
347 SotClipboardFormatId nClipFormat
= SotClipboardFormatId::NONE
;
350 FillClass( &aName
, &nClipFormat
, &aAppName
, &aFullTypeName
, &aShortTypeName
, nVersion
, bTemplate
);
352 nClipFormat
= GetChartVersion(nVersion
, bTemplate
);
354 if ( nClipFormat
!= SotClipboardFormatId::NONE
)
356 // basic doesn't have a ClipFormat
357 // without MediaType the storage is not really usable, but currently the BasicIDE still
358 // is an SfxObjectShell and so we can't take this as an error
359 datatransfer::DataFlavor aDataFlavor
;
360 SotExchange::GetFormatDataFlavor( nClipFormat
, aDataFlavor
);
361 if ( !aDataFlavor
.MimeType
.isEmpty() )
365 xProps
->setPropertyValue("MediaType", uno::makeAny( aDataFlavor
.MimeType
) );
367 catch( uno::Exception
& )
369 const_cast<SfxObjectShell
*>( this )->SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
372 SvtSaveOptions aSaveOpt
;
373 SvtSaveOptions::ODFDefaultVersion nDefVersion
= aSaveOpt
.GetODFDefaultVersion();
375 uno::Sequence
< beans::NamedValue
> aEncryptionAlgs( 3 );
376 aEncryptionAlgs
[0].Name
= "StartKeyGenerationAlgorithm";
377 aEncryptionAlgs
[1].Name
= "EncryptionAlgorithm";
378 aEncryptionAlgs
[2].Name
= "ChecksumAlgorithm";
379 // the default values, that should be used for ODF1.1 and older formats
380 aEncryptionAlgs
[0].Value
<<= xml::crypto::DigestID::SHA1
;
381 aEncryptionAlgs
[1].Value
<<= xml::crypto::CipherID::BLOWFISH_CFB_8
;
382 aEncryptionAlgs
[2].Value
<<= xml::crypto::DigestID::SHA1_1K
;
384 if ( nDefVersion
>= SvtSaveOptions::ODFVER_012
)
388 // older versions can not have this property set, it exists only starting from ODF1.2
389 xProps
->setPropertyValue("Version", uno::makeAny
<OUString
>( ODFVER_012_TEXT
) );
391 catch( uno::Exception
& )
395 if ( !aSaveOpt
.IsUseSHA1InODF12() && nDefVersion
!= SvtSaveOptions::ODFVER_012_EXT_COMPAT
)
397 aEncryptionAlgs
[0].Value
<<= xml::crypto::DigestID::SHA256
;
398 aEncryptionAlgs
[2].Value
<<= xml::crypto::DigestID::SHA256_1K
;
400 if ( !aSaveOpt
.IsUseBlowfishInODF12() && nDefVersion
!= SvtSaveOptions::ODFVER_012_EXT_COMPAT
)
401 aEncryptionAlgs
[1].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
406 // set the encryption algorithms accordingly;
407 // the setting does not trigger encryption,
408 // it just provides the format for the case that contents should be encrypted
409 uno::Reference
< embed::XEncryptionProtectedStorage
> xEncr( xStorage
, uno::UNO_QUERY_THROW
);
410 xEncr
->setEncryptionAlgorithms( aEncryptionAlgs
);
412 catch( uno::Exception
& )
414 const_cast<SfxObjectShell
*>( this )->SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
423 void SfxObjectShell::PrepareSecondTryLoad_Impl()
425 // only for internal use
426 pImp
->m_xDocStorage
= uno::Reference
< embed::XStorage
>();
427 pImp
->m_bIsInit
= false;
432 bool SfxObjectShell::GeneralInit_Impl( const uno::Reference
< embed::XStorage
>& xStorage
,
433 bool bTypeMustBeSetAlready
)
435 if ( pImp
->m_bIsInit
)
438 pImp
->m_bIsInit
= true;
441 // no notification is required the storage is set the first time
442 pImp
->m_xDocStorage
= xStorage
;
445 uno::Reference
< beans::XPropertySet
> xPropSet( xStorage
, uno::UNO_QUERY_THROW
);
446 Any a
= xPropSet
->getPropertyValue("MediaType");
448 if ( !(a
>>=aMediaType
) || aMediaType
.isEmpty() )
450 if ( bTypeMustBeSetAlready
)
452 SetError( ERRCODE_IO_BROKENPACKAGE
, OUString( OSL_LOG_PREFIX
) );
456 SetupStorage( xStorage
, SOFFICE_FILEFORMAT_CURRENT
, false, false );
459 catch ( uno::Exception
& )
461 SAL_WARN( "sfx.doc", "Can't check storage's mediatype!" );
465 pImp
->m_bCreateTempStor
= true;
471 bool SfxObjectShell::InitNew( const uno::Reference
< embed::XStorage
>& xStorage
)
473 return GeneralInit_Impl( xStorage
, false );
477 bool SfxObjectShell::Load( SfxMedium
& rMedium
)
479 return GeneralInit_Impl( rMedium
.GetStorage(), true );
482 bool SfxObjectShell::DoInitUnitTest()
484 pMedium
= new SfxMedium
;
485 return true; // always a success!
488 bool SfxObjectShell::DoInitNew( SfxMedium
* pMed
)
491 This from SvPersist inherited virtual method is called to initialize
492 the SfxObjectShell instance from a storage (PStore! = 0) or (PStore == 0)
494 Like with all Do...-methods there is a from a control, the actual
495 implementation is done by the virtual method in which also the
496 InitNew(SvStorate *) from the SfxObjectShell-Subclass is implemented.
498 For pStore == 0 the SfxObjectShell-instance is connected to an empty
499 SfxMedium, otherwise a SfxMedium, which refers to the SotStorage
500 passed as a parameter.
502 The object is only initialized correctly after InitNew() or Load().
505 true The object has been initialized.
506 false The object could not be initialized
510 ModifyBlocker_Impl
aBlock( this );
514 pMedium
= new SfxMedium
;
517 pMedium
->CanDisposeStorage_Impl( true );
519 if ( InitNew( pMed
? pMed
->GetStorage() : uno::Reference
< embed::XStorage
>() ) )
521 // empty documents always get their macros from the user, so there is no reason to restrict access
522 pImp
->aMacroMode
.allowMacroExecution();
523 if ( SfxObjectCreateMode::EMBEDDED
== eCreateMode
)
524 SetTitle(SfxResId(STR_NONAME
).toString());
526 uno::Reference
< frame::XModel
> xModel ( GetModel(), uno::UNO_QUERY
);
529 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
530 uno::Sequence
< beans::PropertyValue
> aArgs
;
531 TransformItems( SID_OPENDOC
, *pSet
, aArgs
);
532 sal_Int32 nLength
= aArgs
.getLength();
533 aArgs
.realloc( nLength
+ 1 );
534 aArgs
[nLength
].Name
= "Title";
535 aArgs
[nLength
].Value
<<= OUString( GetTitle( SFX_TITLE_DETECT
) );
536 xModel
->attachResource( OUString(), aArgs
);
537 impl_addToModelCollection(xModel
);
540 SetInitialized_Impl( true );
549 bool SfxObjectShell::ImportFromGeneratedStream_Impl(
550 const uno::Reference
< io::XStream
>& xStream
,
551 const uno::Sequence
< beans::PropertyValue
>& rMediaDescr
)
556 if ( pMedium
&& pMedium
->HasStorage_Impl() )
557 pMedium
->CloseStorage();
559 bool bResult
= false;
563 uno::Reference
< embed::XStorage
> xStorage
=
564 ::comphelper::OStorageHelper::GetStorageFromStream( xStream
, embed::ElementModes::READWRITE
);
566 if ( !xStorage
.is() )
567 throw uno::RuntimeException();
570 pMedium
= new SfxMedium( xStorage
, OUString() );
572 pMedium
->SetStorage_Impl( xStorage
);
574 SfxAllItemSet
aSet( SfxGetpApp()->GetPool() );
575 TransformParameters( SID_OPENDOC
, rMediaDescr
, aSet
);
576 pMedium
->GetItemSet()->Put( aSet
);
577 pMedium
->CanDisposeStorage_Impl( false );
578 uno::Reference
<text::XTextRange
> xInsertTextRange
;
579 for (sal_Int32 i
= 0; i
< rMediaDescr
.getLength(); ++i
)
581 if (rMediaDescr
[i
].Name
== "TextInsertModeRange")
583 rMediaDescr
[i
].Value
>>= xInsertTextRange
;
587 if (xInsertTextRange
.is())
589 bResult
= InsertGeneratedStream(*pMedium
, xInsertTextRange
);
594 // allow the subfilter to reinit the model
595 if ( pImp
->m_bIsInit
)
596 pImp
->m_bIsInit
= false;
598 if ( LoadOwnFormat( *pMedium
) )
601 if ( !IsReadOnly() && IsLoadReadonly() )
605 OSL_ENSURE( pImp
->m_xDocStorage
== xStorage
, "Wrong storage is used!\n" );
609 // now the medium can be disconnected from the storage
610 // the medium is not allowed to dispose the storage so CloseStorage() can be used
611 pMedium
->CloseStorage();
613 catch( uno::Exception
& )
622 bool SfxObjectShell::DoLoad( SfxMedium
*pMed
)
624 ModifyBlocker_Impl
aBlock( this );
627 pMedium
->CanDisposeStorage_Impl( true );
630 const SfxFilter
* pFilter
= pMed
->GetFilter();
631 SfxItemSet
* pSet
= pMedium
->GetItemSet();
632 if( !pImp
->nEventId
)
635 pSet
, pTemplateItem
, SfxBoolItem
,
636 SID_TEMPLATE
, false);
637 SetActivateEvent_Impl(
638 ( pTemplateItem
&& pTemplateItem
->GetValue() )
639 ? SFX_EVENT_CREATEDOC
: SFX_EVENT_OPENDOC
);
643 SFX_ITEMSET_ARG( pSet
, pBaseItem
, SfxStringItem
,
646 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, false);
648 aBaseURL
= pBaseItem
->GetValue();
653 OUString
aName( pMed
->GetPhysicalName() );
654 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aBaseURL
);
657 aBaseURL
= pMed
->GetBaseURL();
659 pMed
->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, aBaseURL
) );
661 pImp
->nLoadedFlags
= SfxLoadedFlags::NONE
;
662 pImp
->bModelInitialized
= false;
664 //TODO/LATER: make a clear strategy how to handle "UsesStorage" etc.
665 bool bOwnStorageFormat
= IsOwnStorageFormat_Impl( *pMedium
);
666 bool bHasStorage
= IsPackageStorageFormat_Impl( *pMedium
);
667 if ( pMedium
->GetFilter() )
669 sal_uInt32 nError
= HandleFilter( pMedium
, this );
670 if ( nError
!= ERRCODE_NONE
)
671 SetError( nError
, OUString( OSL_LOG_PREFIX
) );
673 if (pMedium
->GetFilter()->GetFilterFlags() & SfxFilterFlags::STARTPRESENTATION
)
674 pSet
->Put( SfxBoolItem( SID_DOC_STARTPRESENTATION
, true) );
677 EnableSetModified( false );
679 pMedium
->LockOrigFileOnDemand( true, false );
680 if ( GetError() == ERRCODE_NONE
&& bOwnStorageFormat
&& ( !pFilter
|| !( pFilter
->GetFilterFlags() & SfxFilterFlags::STARONEFILTER
) ) )
682 uno::Reference
< embed::XStorage
> xStorage
;
683 if ( pMedium
->GetError() == ERRCODE_NONE
)
684 xStorage
= pMedium
->GetStorage();
686 if( xStorage
.is() && pMedium
->GetLastStorageCreationState() == ERRCODE_NONE
)
688 DBG_ASSERT( pFilter
, "No filter for storage found!" );
692 bool bWarnMediaTypeFallback
= false;
693 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pRepairPackageItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, false);
695 // treat the package as broken if the mediatype was retrieved as a fallback
696 uno::Reference
< beans::XPropertySet
> xStorProps( xStorage
, uno::UNO_QUERY_THROW
);
697 xStorProps
->getPropertyValue("MediaTypeFallbackUsed")
698 >>= bWarnMediaTypeFallback
;
700 if ( pRepairPackageItem
&& pRepairPackageItem
->GetValue() )
702 // the macros in repaired documents should be disabled
703 pMedium
->GetItemSet()->Put( SfxUInt16Item( SID_MACROEXECMODE
, document::MacroExecMode::NEVER_EXECUTE
) );
705 // the mediatype was retrieved by using fallback solution but this is a repairing mode
706 // so it is acceptable to open the document if there is no contents that required manifest.xml
707 bWarnMediaTypeFallback
= false;
710 if ( bWarnMediaTypeFallback
|| !xStorage
->getElementNames().getLength() )
711 SetError( ERRCODE_IO_BROKENPACKAGE
, OUString( OSL_LOG_PREFIX
) );
713 catch( uno::Exception
& )
715 // TODO/LATER: may need error code setting based on exception
716 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
722 pImp
->nLoadedFlags
= SfxLoadedFlags::NONE
;
723 pImp
->bModelInitialized
= false;
724 bOk
= xStorage
.is() && LoadOwnFormat( *pMed
);
727 // the document loaded from template has no name
728 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, false);
729 if ( !pTemplateItem
|| !pTemplateItem
->GetValue() )
733 SetError( ERRCODE_ABORT
, OUString( OSL_LOG_PREFIX
) );
737 SetError( pMed
->GetLastStorageCreationState(), OUString( OSL_LOG_PREFIX
) );
739 else if ( GetError() == ERRCODE_NONE
&& InitNew(0) )
741 // Name vor ConvertFrom setzen, damit GetSbxObject() schon funktioniert
743 SetName( SfxResId(STR_NONAME
).toString() );
746 pMedium
->GetInStream();
748 pMedium
->GetStorage();
750 if ( GetError() == ERRCODE_NONE
)
752 pImp
->nLoadedFlags
= SfxLoadedFlags::NONE
;
753 pImp
->bModelInitialized
= false;
754 if ( pMedium
->GetFilter() && ( pMedium
->GetFilter()->GetFilterFlags() & SfxFilterFlags::STARONEFILTER
) )
756 uno::Reference
< beans::XPropertySet
> xSet( GetModel(), uno::UNO_QUERY
);
757 OUString
sLockUpdates("LockUpdates");
758 bool bSetProperty
= true;
761 xSet
->setPropertyValue( sLockUpdates
, makeAny( true ) );
763 catch(const beans::UnknownPropertyException
& )
765 bSetProperty
= false;
767 bOk
= ImportFrom(*pMedium
, 0);
772 xSet
->setPropertyValue( sLockUpdates
, makeAny( false ) );
774 catch(const beans::UnknownPropertyException
& )
778 FinishedLoading( SfxLoadedFlags::ALL
);
782 bOk
= ConvertFrom(*pMedium
);
790 if ( IsReadOnlyMedium() || IsLoadReadonly() )
795 ::ucbhelper::Content
aContent( pMedium
->GetName(), com::sun::star::uno::Reference
< XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
796 com::sun::star::uno::Reference
< XPropertySetInfo
> xProps
= aContent
.getProperties();
799 OUString
aAuthor( "Author" );
800 OUString
aKeywords( "Keywords" );
801 OUString
aSubject( "Subject" );
804 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
805 GetModel(), uno::UNO_QUERY_THROW
);
806 uno::Reference
<document::XDocumentProperties
> xDocProps
807 = xDPS
->getDocumentProperties();
808 if ( xProps
->hasPropertyByName( aAuthor
) )
810 aAny
= aContent
.getPropertyValue( aAuthor
);
811 if ( ( aAny
>>= aValue
) )
812 xDocProps
->setAuthor(aValue
);
814 if ( xProps
->hasPropertyByName( aKeywords
) )
816 aAny
= aContent
.getPropertyValue( aKeywords
);
817 if ( ( aAny
>>= aValue
) )
818 xDocProps
->setKeywords(
819 ::comphelper::string::convertCommaSeparated(aValue
));
822 if ( xProps
->hasPropertyByName( aSubject
) )
824 aAny
= aContent
.getPropertyValue( aSubject
);
825 if ( ( aAny
>>= aValue
) ) {
826 xDocProps
->setSubject(aValue
);
835 // If not loaded asynchronously call FinishedLoading
836 if ( !( pImp
->nLoadedFlags
& SfxLoadedFlags::MAINDOCUMENT
) &&
837 ( !pMedium
->GetFilter() || pMedium
->GetFilter()->UsesStorage() )
839 FinishedLoading( SfxLoadedFlags::MAINDOCUMENT
);
841 if( IsOwnStorageFormat_Impl(*pMed
) && pMed
->GetFilter() )
844 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED
) );
846 if ( SfxObjectCreateMode::EMBEDDED
!= eCreateMode
)
848 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pAsTempItem
, SfxBoolItem
, SID_TEMPLATE
, false);
849 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pPreviewItem
, SfxBoolItem
, SID_PREVIEW
, false);
850 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pHiddenItem
, SfxBoolItem
, SID_HIDDEN
, false);
851 if( bOk
&& !pMedium
->GetOrigURL().isEmpty()
852 && !( pAsTempItem
&& pAsTempItem
->GetValue() )
853 && !( pPreviewItem
&& pPreviewItem
->GetValue() )
854 && !( pHiddenItem
&& pHiddenItem
->GetValue() ) )
856 AddToRecentlyUsedList();
860 const SfxBoolItem
* pDdeReconnectItem
= static_cast<const SfxBoolItem
*>(
861 SfxRequest::GetItem(pMedium
->GetItemSet(), SID_DDE_RECONNECT_ONLOAD
, false, TYPE(SfxBoolItem
)));
863 bool bReconnectDde
= true; // by default, we try to auto-connect DDE connections.
864 if (pDdeReconnectItem
)
865 bReconnectDde
= pDdeReconnectItem
->GetValue();
868 ReconnectDdeLinks(*this);
874 bool SfxObjectShell::DoLoadExternal( SfxMedium
*pMed
)
877 return LoadExternal(*pMedium
);
880 sal_uInt32
SfxObjectShell::HandleFilter( SfxMedium
* pMedium
, SfxObjectShell
* pDoc
)
882 sal_uInt32 nError
= ERRCODE_NONE
;
883 SfxItemSet
* pSet
= pMedium
->GetItemSet();
884 SFX_ITEMSET_ARG( pSet
, pOptions
, SfxStringItem
, SID_FILE_FILTEROPTIONS
, false );
885 SFX_ITEMSET_ARG( pSet
, pData
, SfxUnoAnyItem
, SID_FILTER_DATA
, false );
886 if ( !pData
&& !pOptions
)
888 com::sun::star::uno::Reference
< XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
889 com::sun::star::uno::Reference
< XNameAccess
> xFilterCFG
;
890 if( xServiceManager
.is() )
892 xFilterCFG
= com::sun::star::uno::Reference
< XNameAccess
>(
893 xServiceManager
->createInstance("com.sun.star.document.FilterFactory"),
897 if( xFilterCFG
.is() )
901 const SfxFilter
* pFilter
= pMedium
->GetFilter();
902 Sequence
< PropertyValue
> aProps
;
903 Any aAny
= xFilterCFG
->getByName( pFilter
->GetName() );
904 if ( aAny
>>= aProps
)
906 sal_Int32 nPropertyCount
= aProps
.getLength();
907 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
908 if( aProps
[nProperty
].Name
== "UIComponent" )
910 OUString aServiceName
;
911 aProps
[nProperty
].Value
>>= aServiceName
;
912 if( !aServiceName
.isEmpty() )
914 com::sun::star::uno::Reference
< XInteractionHandler
> rHandler
= pMedium
->GetInteractionHandler();
917 // we need some properties in the media descriptor, so we have to make sure that they are in
919 aStreamAny
<<= pMedium
->GetInputStream();
920 if ( pSet
->GetItemState( SID_INPUTSTREAM
) < SfxItemState::SET
)
921 pSet
->Put( SfxUnoAnyItem( SID_INPUTSTREAM
, aStreamAny
) );
922 if ( pSet
->GetItemState( SID_FILE_NAME
) < SfxItemState::SET
)
923 pSet
->Put( SfxStringItem( SID_FILE_NAME
, pMedium
->GetName() ) );
924 if ( pSet
->GetItemState( SID_FILTER_NAME
) < SfxItemState::SET
)
925 pSet
->Put( SfxStringItem( SID_FILTER_NAME
, pFilter
->GetName() ) );
927 Sequence
< PropertyValue
> rProperties
;
928 TransformItems( SID_OPENDOC
, *pSet
, rProperties
, NULL
);
929 RequestFilterOptions
* pFORequest
= new RequestFilterOptions( pDoc
->GetModel(), rProperties
);
931 com::sun::star::uno::Reference
< XInteractionRequest
> rRequest( pFORequest
);
932 rHandler
->handle( rRequest
);
934 if ( !pFORequest
->isAbort() )
936 SfxAllItemSet
aNewParams( pDoc
->GetPool() );
937 TransformParameters( SID_OPENDOC
,
938 pFORequest
->getFilterOptions(),
942 SFX_ITEMSET_ARG( &aNewParams
,
945 SID_FILE_FILTEROPTIONS
,
947 if ( pFilterOptions
)
948 pSet
->Put( *pFilterOptions
);
950 SFX_ITEMSET_ARG( &aNewParams
,
956 pSet
->Put( *pFilterData
);
969 // filter options were not entered
970 nError
= ERRCODE_ABORT
;
973 catch( NoSuchElementException
& )
975 // the filter name is unknown
976 nError
= ERRCODE_IO_INVALIDPARAMETER
;
980 nError
= ERRCODE_ABORT
;
990 bool SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium
&rMedium
) const
992 return !rMedium
.GetFilter() || // Embedded
993 ( rMedium
.GetFilter()->IsOwnFormat() &&
994 rMedium
.GetFilter()->UsesStorage() &&
995 rMedium
.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60
);
1000 bool SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium
&rMedium
) const
1002 return !rMedium
.GetFilter() || // Embedded
1003 ( rMedium
.GetFilter()->UsesStorage() &&
1004 rMedium
.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60
);
1009 bool SfxObjectShell::DoSave()
1010 // DoSave is only invoked for OLE. Save your own documents in the SFX through
1011 // DoSave_Impl order to allow for the creation of backups.
1012 // Save in your own format again.
1016 ModifyBlocker_Impl
aBlock( this );
1018 pImp
->bIsSaving
= true;
1020 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
1021 if ( IsPackageStorageFormat_Impl( *GetMedium() ) )
1023 if ( GetEncryptionData_Impl( GetMedium()->GetItemSet(), aEncryptionData
) )
1027 //TODO/MBA: GetOutputStorage?! Special mode, because it's "Save"?!
1028 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( GetMedium()->GetStorage(), aEncryptionData
);
1031 catch( uno::Exception
& )
1033 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1036 DBG_ASSERT( bOk
, "The root storage must allow to set common password!\n" );
1040 #if HAVE_FEATURE_SCRIPTING
1045 // The basic and dialogs related contents are still not able to proceed with save operation ( saveTo only )
1046 // so since the document storage is locked a workaround has to be used
1048 uno::Reference
< embed::XStorage
> xTmpStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
1049 DBG_ASSERT( xTmpStorage
.is(), "If a storage can not be created an exception must be thrown!\n" );
1050 if ( !xTmpStorage
.is() )
1051 throw uno::RuntimeException();
1053 OUString
aBasicStorageName( "Basic" );
1054 OUString
aDialogsStorageName( "Dialogs" );
1055 if ( GetMedium()->GetStorage()->hasByName( aBasicStorageName
) )
1056 GetMedium()->GetStorage()->copyElementTo( aBasicStorageName
, xTmpStorage
, aBasicStorageName
);
1057 if ( GetMedium()->GetStorage()->hasByName( aDialogsStorageName
) )
1058 GetMedium()->GetStorage()->copyElementTo( aDialogsStorageName
, xTmpStorage
, aDialogsStorageName
);
1062 // disconnect from the current storage
1063 pImp
->aBasicManager
.setStorage( xTmpStorage
);
1065 // store to the current storage
1066 pImp
->aBasicManager
.storeLibrariesToStorage( GetMedium()->GetStorage() );
1068 // connect to the current storage back
1069 pImp
->aBasicManager
.setStorage( GetMedium()->GetStorage() );
1071 catch( uno::Exception
& )
1073 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1084 bOk
= pMedium
->Commit();
1090 void Lock_Impl( SfxObjectShell
* pDoc
, bool bLock
)
1092 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst( pDoc
);
1095 pFrame
->GetDispatcher()->Lock( bLock
);
1096 pFrame
->Enable( !bLock
);
1097 pFrame
= SfxViewFrame::GetNext( *pFrame
, pDoc
);
1104 bool SfxObjectShell::SaveTo_Impl
1106 SfxMedium
&rMedium
, // Medium, in which it will be stored
1107 const SfxItemSet
* pSet
1112 Writes the current contents to the medium rMedium. If the target medium is
1113 no storage, then saving to a temporary storage, or directly if the medium
1114 is transacted, if we ourselves have opened it, and if we are a server
1115 either the container a transacted storage provides or created a
1116 temporary storage by one self.
1120 SAL_INFO( "sfx.doc", "saving \"" << rMedium
.GetName() << "\"" );
1122 UpdateDocInfoForSave();
1124 AddLog( OUString( OSL_LOG_PREFIX
"Begin" ) );
1126 ModifyBlocker_Impl
aMod(this);
1128 const SfxFilter
*pFilter
= rMedium
.GetFilter();
1131 // if no filter was set, use the default filter
1132 // this should be changed in the feature, it should be an error!
1133 SAL_WARN( "sfx.doc","No filter set!");
1134 pFilter
= GetFactory().GetFilterContainer()->GetAnyFilter( SfxFilterFlags::IMPORT
| SfxFilterFlags::EXPORT
);
1135 rMedium
.SetFilter(pFilter
);
1138 bool bStorageBasedSource
= IsPackageStorageFormat_Impl( *pMedium
);
1139 bool bStorageBasedTarget
= IsPackageStorageFormat_Impl( rMedium
);
1140 bool bOwnSource
= IsOwnStorageFormat_Impl( *pMedium
);
1141 bool bOwnTarget
= IsOwnStorageFormat_Impl( rMedium
);
1143 // Examine target format to determine whether to query if any password
1144 // protected libraries exceed the size we can handler
1145 if ( bOwnTarget
&& !QuerySaveSizeExceededModules_Impl( rMedium
.GetInteractionHandler() ) )
1147 SetError( ERRCODE_IO_ABORT
, OUString( OSL_LOG_PREFIX
) );
1151 bool bNeedsDisconnectionOnFail
= false;
1153 bool bStoreToSameLocation
= false;
1155 // the detection whether the script is changed should be done before saving
1156 bool bTryToPreserveScriptSignature
= false;
1157 // no way to detect whether a filter is oasis format, have to wait for saving process
1158 bool bNoPreserveForOasis
= false;
1159 if ( bOwnSource
&& bOwnTarget
1160 && ( pImp
->nScriptingSignatureState
== SignatureState::OK
1161 || pImp
->nScriptingSignatureState
== SignatureState::NOTVALIDATED
1162 || pImp
->nScriptingSignatureState
== SignatureState::INVALID
) )
1164 AddLog( OUString( OSL_LOG_PREFIX
"MacroSignaturePreserving" ) );
1166 // the checking of the library modified state iterates over the libraries, should be done only when required
1167 // currently the check is commented out since it is broken, we have to check the signature every time we save
1168 // TODO/LATER: let isAnyContainerModified() work!
1169 bTryToPreserveScriptSignature
= true; // !pImp->pBasicManager->isAnyContainerModified();
1170 if ( bTryToPreserveScriptSignature
)
1172 // check that the storage format stays the same
1173 SvtSaveOptions aSaveOpt
;
1174 SvtSaveOptions::ODFDefaultVersion nVersion
= aSaveOpt
.GetODFDefaultVersion();
1176 OUString aODFVersion
;
1179 uno::Reference
< beans::XPropertySet
> xPropSet( GetStorage(), uno::UNO_QUERY_THROW
);
1180 xPropSet
->getPropertyValue("Version") >>= aODFVersion
;
1182 catch( uno::Exception
& )
1185 // preserve only if the same filter has been used
1186 bTryToPreserveScriptSignature
= pMedium
->GetFilter() && pFilter
&& pMedium
->GetFilter()->GetFilterName() == pFilter
->GetFilterName();
1188 bNoPreserveForOasis
= (
1189 (aODFVersion
== ODFVER_012_TEXT
&& nVersion
== SvtSaveOptions::ODFVER_011
) ||
1190 (aODFVersion
.isEmpty() && nVersion
>= SvtSaveOptions::ODFVER_012
)
1195 bool bCopyTo
= false;
1196 SfxItemSet
*pMedSet
= rMedium
.GetItemSet();
1199 SFX_ITEMSET_ARG( pMedSet
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, false );
1200 bCopyTo
= GetCreateMode() == SfxObjectCreateMode::EMBEDDED
||
1201 (pSaveToItem
&& pSaveToItem
->GetValue());
1204 // use UCB for case sensitive/insensitive file name comparison
1205 if ( !pMedium
->GetName().equalsIgnoreAsciiCase("private:stream")
1206 && !rMedium
.GetName().equalsIgnoreAsciiCase("private:stream")
1207 && ::utl::UCBContentHelper::EqualURLs( pMedium
->GetName(), rMedium
.GetName() ) )
1209 bStoreToSameLocation
= true;
1210 AddLog( OUString( OSL_LOG_PREFIX
"Save" ) );
1212 if ( pMedium
->DocNeedsFileDateCheck() )
1213 rMedium
.CheckFileDate( pMedium
->GetInitFileDate( false ) );
1215 if ( bCopyTo
&& GetCreateMode() != SfxObjectCreateMode::EMBEDDED
)
1217 // export to the same location is forbidden
1218 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
1222 // before we overwrite the original file, we will make a backup if there is a demand for that
1223 // if the backup is not created here it will be created internally and will be removed in case of successful saving
1224 const bool bDoBackup
= SvtSaveOptions().IsBackup();
1227 AddLog( OUString( OSL_LOG_PREFIX
"DoBackup" ) );
1228 rMedium
.DoBackup_Impl();
1229 if ( rMedium
.GetError() )
1231 SetError( rMedium
.GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
1232 rMedium
.ResetError();
1236 if ( bStorageBasedSource
&& bStorageBasedTarget
)
1238 // The active storage must be switched. The simple saving is not enough.
1239 // The problem is that the target medium contains target MediaDescriptor.
1241 // In future the switch of the persistence could be done on stream level:
1242 // a new wrapper service will be implemented that allows to exchange
1243 // persistence on the fly. So the real persistence will be set
1244 // to that stream only after successful commit of the storage.
1246 // create wrapper stream based on the URL
1247 // create a new storage based on this stream
1248 // store to this new storage
1249 // commit the new storage
1250 // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
1251 // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
1252 // if the last step is failed the stream should stay to be transacted and should be committed on any flush
1253 // so we can forget the stream in any way and the next storage commit will flush it
1255 AddLog( OUString( OSL_LOG_PREFIX
"Save: Own to Own" ) );
1257 bNeedsDisconnectionOnFail
= DisconnectStorage_Impl(
1258 *pMedium
, rMedium
);
1259 if ( bNeedsDisconnectionOnFail
1260 || ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1262 pMedium
->CloseAndRelease();
1264 // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
1265 // in future those streams should not be copied in case a valid target url is provided,
1266 // if the url is not provided ( means the document is based on a stream ) this code is not
1268 rMedium
.CloseAndRelease();
1269 rMedium
.GetOutputStorage();
1272 else if ( !bStorageBasedSource
&& !bStorageBasedTarget
)
1274 // the source and the target formats are alien
1275 // just disconnect the stream from the source format
1276 // so that the target medium can use it
1278 AddLog( OUString( OSL_LOG_PREFIX
"Save: Alien to Alien" ) );
1280 pMedium
->CloseAndRelease();
1281 rMedium
.CloseAndRelease();
1282 rMedium
.CreateTempFileNoCopy();
1283 rMedium
.GetOutStream();
1285 else if ( !bStorageBasedSource
&& bStorageBasedTarget
)
1287 // the source format is an alien one but the target
1288 // format is an own one so just disconnect the source
1291 AddLog( OUString( OSL_LOG_PREFIX
"Save: Alien to Own" ) );
1293 pMedium
->CloseAndRelease();
1294 rMedium
.CloseAndRelease();
1295 rMedium
.GetOutputStorage();
1297 else // means if ( bStorageBasedSource && !bStorageBasedTarget )
1299 // the source format is an own one but the target is
1300 // an alien format, just connect the source to temporary
1303 AddLog( OUString( OSL_LOG_PREFIX
"Save: Own to Alien" ) );
1305 bNeedsDisconnectionOnFail
= DisconnectStorage_Impl(
1306 *pMedium
, rMedium
);
1307 if ( bNeedsDisconnectionOnFail
1308 || ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1310 pMedium
->CloseAndRelease();
1311 rMedium
.CloseAndRelease();
1312 rMedium
.CreateTempFileNoCopy();
1313 rMedium
.GetOutStream();
1320 // This is SaveAs or export action, prepare the target medium
1321 // the alien filters still might write directly to the file, that is of course a bug,
1322 // but for now the framework has to be ready for it
1323 // TODO/LATER: let the medium be prepared for alien formats as well
1325 AddLog( OUString( OSL_LOG_PREFIX
"SaveAs/Export" ) );
1327 rMedium
.CloseAndRelease();
1328 if ( bStorageBasedTarget
)
1330 rMedium
.GetOutputStorage();
1334 // TODO/LATER: error handling
1335 if( rMedium
.GetErrorCode() || pMedium
->GetErrorCode() || GetErrorCode() )
1338 AddLog( OUString( OSL_LOG_PREFIX
"Locking" ) );
1340 rMedium
.LockOrigFileOnDemand( false, false );
1342 if ( bStorageBasedTarget
)
1344 if ( rMedium
.GetErrorCode() )
1347 // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from
1348 // a draw document ), the ClassId of the destination storage is different from the ClassId of this
1349 // document. It can be retrieved from the default filter for the desired target format
1350 SotClipboardFormatId nFormat
= rMedium
.GetFilter()->GetFormat();
1351 SfxFilterMatcher
& rMatcher
= SfxGetpApp()->GetFilterMatcher();
1352 const SfxFilter
*pFilt
= rMatcher
.GetFilter4ClipBoardId( nFormat
);
1355 if ( pFilt
->GetServiceName() != rMedium
.GetFilter()->GetServiceName() )
1357 datatransfer::DataFlavor aDataFlavor
;
1358 SotExchange::GetFormatDataFlavor( nFormat
, aDataFlavor
);
1362 uno::Reference
< beans::XPropertySet
> xProps( rMedium
.GetStorage(), uno::UNO_QUERY
);
1363 DBG_ASSERT( xProps
.is(), "The storage implementation must implement XPropertySet!" );
1365 throw uno::RuntimeException();
1367 xProps
->setPropertyValue("MediaType",
1368 uno::makeAny( aDataFlavor
.MimeType
) );
1370 catch( uno::Exception
& )
1377 // TODO/LATER: error handling
1378 if( rMedium
.GetErrorCode() || pMedium
->GetErrorCode() || GetErrorCode() )
1381 bool bOldStat
= pImp
->bForbidReload
;
1382 pImp
->bForbidReload
= true;
1384 // lock user interface while saving the document
1385 Lock_Impl( this, true );
1388 // TODO/LATER: get rid of bOk
1389 if (bOwnTarget
&& pFilter
&& !(pFilter
->GetFilterFlags() & SfxFilterFlags::STARONEFILTER
))
1391 AddLog( OUString( OSL_LOG_PREFIX
"Storing in own format." ) );
1392 uno::Reference
< embed::XStorage
> xMedStorage
= rMedium
.GetStorage();
1393 if ( !xMedStorage
.is() )
1395 // no saving without storage, unlock UI and return
1396 Lock_Impl( this, false );
1397 pImp
->bForbidReload
= bOldStat
;
1398 AddLog( OUString( OSL_LOG_PREFIX
"Storing failed, still no error set." ) );
1402 // transfer password from the parameters to the storage
1403 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
1404 bool bPasswdProvided
= false;
1405 if ( GetEncryptionData_Impl( rMedium
.GetItemSet(), aEncryptionData
) )
1407 bPasswdProvided
= true;
1409 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage
, aEncryptionData
);
1412 catch( uno::Exception
& )
1414 SAL_WARN( "sfx.doc", "Setting of common encryption key failed!" );
1415 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1421 pFilter
= rMedium
.GetFilter();
1423 const SfxStringItem
*pVersionItem
= ( !rMedium
.IsInCheckIn( ) && pSet
)
1424 ? static_cast<const SfxStringItem
*>( SfxRequest::GetItem( pSet
, SID_DOCINFO_COMMENTS
, false, TYPE(SfxStringItem
) ) )
1426 OUString aTmpVersionURL
;
1431 // currently the case that the storage is the same should be impossible
1432 if ( xMedStorage
== GetStorage() )
1434 OSL_ENSURE( !pVersionItem
, "This scenario is impossible currently!\n" );
1435 AddLog( OUString( OSL_LOG_PREFIX
"Should be impossible." ) );
1436 // usual save procedure
1442 AddLog( OUString( OSL_LOG_PREFIX
"Save as own format." ) );
1443 bOk
= SaveAsOwnFormat( rMedium
);
1444 if ( bOk
&& pVersionItem
)
1446 AddLog( OUString( OSL_LOG_PREFIX
"pVersionItem != NULL" ) );
1447 aTmpVersionURL
= CreateTempCopyOfStorage_Impl( xMedStorage
);
1448 bOk
= !aTmpVersionURL
.isEmpty();
1453 //fdo#61320: only store thumbnail image if the corresponding option is enabled in the configuration
1454 if ( bOk
&& officecfg::Office::Common::Save::Document::GenerateThumbnail::get()
1455 && GetCreateMode() != SfxObjectCreateMode::EMBEDDED
&& !bPasswdProvided
)
1457 // store the thumbnail representation image
1458 // the thumbnail is not stored in case of encrypted document
1459 AddLog( OUString( OSL_LOG_PREFIX
"Thumbnail creation." ) );
1460 if ( !GenerateAndStoreThumbnail( bPasswdProvided
,
1461 pFilter
->IsOwnTemplateFormat(),
1464 // TODO: error handling
1465 SAL_WARN( "sfx.doc", "Couldn't store thumbnail representation!" );
1471 if ( pImp
->bIsSaving
|| pImp
->bPreserveVersions
)
1473 AddLog( OUString( OSL_LOG_PREFIX
"Preserve versions." ) );
1476 Sequence
< util::RevisionTag
> aVersions
= rMedium
.GetVersionList();
1477 if ( aVersions
.getLength() )
1479 // copy the version streams
1480 OUString
aVersionsName( "Versions" );
1481 uno::Reference
< embed::XStorage
> xNewVerStor
= xMedStorage
->openStorageElement(
1483 embed::ElementModes::READWRITE
);
1484 uno::Reference
< embed::XStorage
> xOldVerStor
= GetStorage()->openStorageElement(
1486 embed::ElementModes::READ
);
1487 if ( !xNewVerStor
.is() || !xOldVerStor
.is() )
1488 throw uno::RuntimeException();
1490 for ( sal_Int32 n
=0; n
<aVersions
.getLength(); n
++ )
1492 if ( xOldVerStor
->hasByName( aVersions
[n
].Identifier
) )
1493 xOldVerStor
->copyElementTo( aVersions
[n
].Identifier
, xNewVerStor
, aVersions
[n
].Identifier
);
1496 uno::Reference
< embed::XTransactedObject
> xTransact( xNewVerStor
, uno::UNO_QUERY
);
1497 if ( xTransact
.is() )
1498 xTransact
->commit();
1501 catch( uno::Exception
& )
1503 AddLog( OUString( OSL_LOG_PREFIX
"Preserve versions has failed." ) );
1504 SAL_WARN( "sfx.doc", "Couldn't copy versions!" );
1506 // TODO/LATER: a specific error could be set
1510 if ( bOk
&& pVersionItem
&& !rMedium
.IsInCheckIn() )
1512 // store a version also
1513 const SfxStringItem
*pAuthorItem
= pSet
1514 ? static_cast<const SfxStringItem
*>( SfxRequest::GetItem( pSet
, SID_DOCINFO_AUTHOR
, false, TYPE(SfxStringItem
) ) )
1518 util::RevisionTag aInfo
;
1519 aInfo
.Comment
= pVersionItem
->GetValue();
1523 aInfo
.Author
= pAuthorItem
->GetValue();
1525 // if not transferred as a parameter, get it from user settings
1526 aInfo
.Author
= SvtUserOptions().GetFullName();
1528 DateTime
aTime( DateTime::SYSTEM
);
1529 aInfo
.TimeStamp
.Day
= aTime
.GetDay();
1530 aInfo
.TimeStamp
.Month
= aTime
.GetMonth();
1531 aInfo
.TimeStamp
.Year
= aTime
.GetYear();
1532 aInfo
.TimeStamp
.Hours
= aTime
.GetHour();
1533 aInfo
.TimeStamp
.Minutes
= aTime
.GetMin();
1534 aInfo
.TimeStamp
.Seconds
= aTime
.GetSec();
1538 // add new version information into the versionlist and save the versionlist
1539 // the version list must have been transferred from the "old" medium before
1540 rMedium
.AddVersion_Impl( aInfo
);
1541 rMedium
.SaveVersionList_Impl( true );
1542 bOk
= PutURLContentsToVersionStream_Impl( aTmpVersionURL
, xMedStorage
, aInfo
.Identifier
);
1545 else if ( bOk
&& ( pImp
->bIsSaving
|| pImp
->bPreserveVersions
) )
1547 rMedium
.SaveVersionList_Impl( true );
1551 if ( !aTmpVersionURL
.isEmpty() )
1552 ::utl::UCBContentHelper::Kill( aTmpVersionURL
);
1556 AddLog( OUString( OSL_LOG_PREFIX
"Storing in alien format." ) );
1557 // it's a "SaveAs" in an alien format
1558 if ( rMedium
.GetFilter() && ( rMedium
.GetFilter()->GetFilterFlags() & SfxFilterFlags::STARONEFILTER
) )
1559 bOk
= ExportTo( rMedium
);
1561 bOk
= ConvertTo( rMedium
);
1563 // after saving the document, the temporary object storage must be updated
1564 // if the old object storage was not a temporary one, it will be updated also, because it will be used
1565 // as a source for copying the objects into the new temporary storage that will be created below
1566 // updating means: all child objects must be stored into it
1567 // ( same as on loading, where these objects are copied to the temporary storage )
1568 // but don't commit these changes, because in the case when the old object storage is not a temporary one,
1569 // all changes will be written into the original file !
1571 if( bOk
&& !bCopyTo
)
1572 // we also don't touch any graphical replacements here
1573 bOk
= SaveChildren( true );
1578 // if ODF version of oasis format changes on saving the signature should not be preserved
1579 if ( bOk
&& bTryToPreserveScriptSignature
&& bNoPreserveForOasis
)
1580 bTryToPreserveScriptSignature
= ( SotStorage::GetVersion( rMedium
.GetStorage() ) == SOFFICE_FILEFORMAT_60
);
1582 uno::Reference
< security::XDocumentDigitalSignatures
> xDDSigns
;
1583 if ( bOk
&& bTryToPreserveScriptSignature
)
1585 AddLog( OUString( OSL_LOG_PREFIX
"Copying scripting signature." ) );
1587 // if the scripting code was not changed and it is signed the signature should be preserved
1588 // unfortunately at this point we have only information whether the basic code has changed or not
1589 // so the only way is to check the signature if the basic was not changed
1592 // get the ODF version of the new medium
1596 uno::Reference
< beans::XPropertySet
> xPropSet( rMedium
.GetStorage(), uno::UNO_QUERY_THROW
);
1597 xPropSet
->getPropertyValue("Version") >>= aVersion
;
1599 catch( uno::Exception
& )
1603 xDDSigns
= security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), aVersion
);
1605 OUString aScriptSignName
= xDDSigns
->getScriptingContentSignatureDefaultStreamName();
1607 if ( !aScriptSignName
.isEmpty() )
1611 // target medium is still not committed, it should not be closed
1612 // commit the package storage and close it, but leave the streams open
1613 rMedium
.StorageCommit_Impl();
1614 rMedium
.CloseStorage();
1616 uno::Reference
< embed::XStorage
> xReadOrig
= pMedium
->GetZipStorageToSign_Impl();
1617 if ( !xReadOrig
.is() )
1618 throw uno::RuntimeException();
1619 uno::Reference
< embed::XStorage
> xMetaInf
= xReadOrig
->openStorageElement(
1620 OUString( "META-INF" ),
1621 embed::ElementModes::READ
);
1623 uno::Reference
< embed::XStorage
> xTarget
= rMedium
.GetZipStorageToSign_Impl( false );
1624 if ( !xTarget
.is() )
1625 throw uno::RuntimeException();
1626 uno::Reference
< embed::XStorage
> xTargetMetaInf
= xTarget
->openStorageElement(
1627 OUString( "META-INF" ),
1628 embed::ElementModes::READWRITE
);
1630 if ( xMetaInf
.is() && xTargetMetaInf
.is() )
1632 xMetaInf
->copyElementTo( aScriptSignName
, xTargetMetaInf
, aScriptSignName
);
1634 uno::Reference
< embed::XTransactedObject
> xTransact( xTargetMetaInf
, uno::UNO_QUERY
);
1635 if ( xTransact
.is() )
1636 xTransact
->commit();
1638 xTargetMetaInf
->dispose();
1640 // now check the copied signature
1641 uno::Sequence
< security::DocumentSignatureInformation
> aInfos
=
1642 xDDSigns
->verifyScriptingContentSignatures( xTarget
,
1643 uno::Reference
< io::XInputStream
>() );
1644 SignatureState nState
= ImplCheckSignaturesInformation( aInfos
);
1645 if ( nState
== SignatureState::OK
|| nState
== SignatureState::NOTVALIDATED
1646 || nState
== SignatureState::PARTIAL_OK
)
1648 rMedium
.SetCachedSignatureState_Impl( nState
);
1650 // commit the ZipStorage from target medium
1651 xTransact
.set( xTarget
, uno::UNO_QUERY
);
1652 if ( xTransact
.is() )
1653 xTransact
->commit();
1657 // it should not happen, the copies signature is invalid!
1658 // throw the changes away
1659 SAL_WARN( "sfx.doc", "An invalid signature was copied!" );
1664 catch( uno::Exception
& )
1669 rMedium
.CloseZipStorage_Impl();
1672 AddLog( OUString( OSL_LOG_PREFIX
"Medium commit." ) );
1674 OUString
sName( rMedium
.GetName( ) );
1675 bOk
= rMedium
.Commit();
1676 OUString
sNewName( rMedium
.GetName( ) );
1678 if ( sName
!= sNewName
)
1679 GetMedium( )->SwitchDocumentToFile( sNewName
);
1683 AddLog( OUString( OSL_LOG_PREFIX
"Storing is successful." ) );
1685 // if the target medium is an alien format and the "old" medium was an own format and the "old" medium
1686 // has a name, the object storage must be exchanged, because now we need a new temporary storage
1687 // as object storage
1688 if ( !bCopyTo
&& bStorageBasedSource
&& !bStorageBasedTarget
)
1690 if ( bStoreToSameLocation
)
1692 // if the old medium already disconnected from document storage, the storage still must
1693 // be switched if backup file is used
1694 if ( bNeedsDisconnectionOnFail
)
1695 ConnectTmpStorage_Impl( pImp
->m_xDocStorage
, NULL
);
1697 else if (!pMedium
->GetName().isEmpty()
1698 || ( pMedium
->HasStorage_Impl() && pMedium
->WillDisposeStorageOnClose_Impl() ) )
1700 OSL_ENSURE(!pMedium
->GetName().isEmpty(), "Fallback is used, the medium without name should not dispose the storage!\n");
1701 // copy storage of old medium to new temporary storage and take this over
1702 if( !ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1704 AddLog( OUString( OSL_LOG_PREFIX
"Process after storing has failed." ) );
1712 AddLog( OUString( OSL_LOG_PREFIX
"Storing has failed." ) );
1714 // in case the document storage was connected to backup temporarely it must be disconnected now
1715 if ( bNeedsDisconnectionOnFail
)
1716 ConnectTmpStorage_Impl( pImp
->m_xDocStorage
, NULL
);
1720 // unlock user interface
1721 Lock_Impl( this, false );
1722 pImp
->bForbidReload
= bOldStat
;
1728 ::ucbhelper::Content
aContent( rMedium
.GetName(), com::sun::star::uno::Reference
< XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
1729 com::sun::star::uno::Reference
< XPropertySetInfo
> xProps
= aContent
.getProperties();
1732 OUString
aAuthor( "Author" );
1733 OUString
aKeywords( "Keywords" );
1734 OUString
aSubject( "Subject" );
1737 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1738 GetModel(), uno::UNO_QUERY_THROW
);
1739 uno::Reference
<document::XDocumentProperties
> xDocProps
1740 = xDPS
->getDocumentProperties();
1742 if ( xProps
->hasPropertyByName( aAuthor
) )
1744 aAny
<<= xDocProps
->getAuthor();
1745 aContent
.setPropertyValue( aAuthor
, aAny
);
1747 if ( xProps
->hasPropertyByName( aKeywords
) )
1749 aAny
<<= ::comphelper::string::convertCommaSeparated(
1750 xDocProps
->getKeywords());
1751 aContent
.setPropertyValue( aKeywords
, aAny
);
1753 if ( xProps
->hasPropertyByName( aSubject
) )
1755 aAny
<<= xDocProps
->getSubject();
1756 aContent
.setPropertyValue( aSubject
, aAny
);
1769 bool SfxObjectShell::DisconnectStorage_Impl( SfxMedium
& rSrcMedium
, SfxMedium
& rTargetMedium
)
1771 // this method disconnects the storage from source medium, and attaches it to the backup created by the target medium
1773 uno::Reference
< embed::XStorage
> xStorage
= rSrcMedium
.GetStorage();
1775 bool bResult
= false;
1776 if ( xStorage
== pImp
->m_xDocStorage
)
1780 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY_THROW
);
1781 OUString aBackupURL
= rTargetMedium
.GetBackup_Impl();
1782 if ( aBackupURL
.isEmpty() )
1784 // the backup could not be created, try to disconnect the storage and close the source SfxMedium
1785 // in this case the optimization is not possible, connect storage to a temporary file
1786 rTargetMedium
.ResetError();
1787 xOptStorage
->writeAndAttachToStream( uno::Reference
< io::XStream
>() );
1788 rSrcMedium
.CanDisposeStorage_Impl( false );
1791 // now try to create the backup
1792 rTargetMedium
.GetBackup_Impl();
1796 // the following call will only compare stream sizes
1797 // TODO/LATER: this is a very risky part, since if the URL contents are different from the storage
1798 // contents, the storag will be broken
1799 xOptStorage
->attachToURL( aBackupURL
, sal_True
);
1801 // the storage is successfully attached to backup, thus it is owned by the document not by the medium
1802 rSrcMedium
.CanDisposeStorage_Impl( false );
1806 catch ( uno::Exception
& )
1815 bool SfxObjectShell::ConnectTmpStorage_Impl(
1816 const uno::Reference
< embed::XStorage
>& xStorage
,
1817 SfxMedium
* pMediumArg
)
1821 If the application operates on a temporary storage, then it may not take
1822 the temporary storage from the SaveCompleted. Therefore the new storage
1823 is connected already here in this case and SaveCompleted then does nothing.
1827 bool bResult
= false;
1829 if ( xStorage
.is() )
1833 // the empty argument means that the storage will create temporary stream itself
1834 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY_THROW
);
1835 xOptStorage
->writeAndAttachToStream( uno::Reference
< io::XStream
>() );
1837 // the storage is successfully disconnected from the original sources, thus the medium must not dispose it
1839 pMediumArg
->CanDisposeStorage_Impl( false );
1843 catch( uno::Exception
& )
1847 // if switching of the storage does not work for any reason ( nonroot storage for example ) use the old method
1850 uno::Reference
< embed::XStorage
> xTmpStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
1852 DBG_ASSERT( xTmpStorage
.is(), "If a storage can not be created an exception must be thrown!\n" );
1853 if ( !xTmpStorage
.is() )
1854 throw uno::RuntimeException();
1856 // TODO/LATER: may be it should be done in SwitchPersistence also
1857 // TODO/LATER: find faster way to copy storage; perhaps sharing with backup?!
1858 xStorage
->copyToStorage( xTmpStorage
);
1859 bResult
= SaveCompleted( xTmpStorage
);
1863 pImp
->aBasicManager
.setStorage( xTmpStorage
);
1865 // Get rid of this workaround after issue i113914 is fixed
1868 uno::Reference
< script::XStorageBasedLibraryContainer
> xBasicLibraries( pImp
->xBasicLibraries
, uno::UNO_QUERY_THROW
);
1869 xBasicLibraries
->setRootStorage( xTmpStorage
);
1871 catch( uno::Exception
& )
1875 uno::Reference
< script::XStorageBasedLibraryContainer
> xDialogLibraries( pImp
->xDialogLibraries
, uno::UNO_QUERY_THROW
);
1876 xDialogLibraries
->setRootStorage( xTmpStorage
);
1878 catch( uno::Exception
& )
1882 catch( uno::Exception
& )
1887 // TODO/LATER: may need error code setting based on exception
1888 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1897 bool SfxObjectShell::DoSaveObjectAs( SfxMedium
& rMedium
, bool bCommit
)
1901 ModifyBlocker_Impl
aBlock( this );
1903 uno::Reference
< embed::XStorage
> xNewStor
= rMedium
.GetStorage();
1904 if ( !xNewStor
.is() )
1907 uno::Reference
< beans::XPropertySet
> xPropSet( xNewStor
, uno::UNO_QUERY
);
1908 if ( !xPropSet
.is() )
1911 Any a
= xPropSet
->getPropertyValue("MediaType");
1912 OUString aMediaType
;
1913 if ( !(a
>>=aMediaType
) || aMediaType
.isEmpty() )
1915 SAL_WARN( "sfx.doc", "The mediatype must be set already!" );
1916 SetupStorage( xNewStor
, SOFFICE_FILEFORMAT_CURRENT
, false, false );
1919 pImp
->bIsSaving
= false;
1920 bOk
= SaveAsOwnFormat( rMedium
);
1925 uno::Reference
< embed::XTransactedObject
> xTransact( xNewStor
, uno::UNO_QUERY_THROW
);
1926 xTransact
->commit();
1928 catch( uno::Exception
& )
1930 SAL_WARN( "sfx.doc", "The strotage was not committed on DoSaveAs!" );
1938 // TODO/LATER: may be the call must be removed completelly
1939 bool SfxObjectShell::DoSaveAs( SfxMedium
& rMedium
)
1941 // here only root storages are included, which are stored via temp file
1942 rMedium
.CreateTempFileNoCopy();
1943 SetError(rMedium
.GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
1947 // copy version list from "old" medium to target medium, so it can be used on saving
1948 if ( pImp
->bPreserveVersions
)
1949 rMedium
.TransferVersionList_Impl( *pMedium
);
1951 bool bRet
= SaveTo_Impl( rMedium
, NULL
);
1953 SetError(rMedium
.GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
1959 bool SfxObjectShell::DoSaveCompleted( SfxMedium
* pNewMed
)
1962 bool bMedChanged
= pNewMed
&& pNewMed
!=pMedium
;
1964 DBG_ASSERT( !pNewMed
|| pNewMed
->GetError() == ERRCODE_NONE
, "DoSaveCompleted: Medium has error!" );
1966 // delete Medium (and Storage!) after all notifications
1967 SfxMedium
* pOld
= pMedium
;
1971 pMedium
->CanDisposeStorage_Impl( true );
1974 const SfxFilter
*pFilter
= pMedium
? pMedium
->GetFilter() : 0;
1979 if (!pNewMed
->GetName().isEmpty())
1981 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED
) );
1982 EnableSetModified(false);
1983 getDocProperties()->setGenerator(
1984 ::utl::DocInfoHelper::GetGeneratorString() );
1985 EnableSetModified(true);
1988 uno::Reference
< embed::XStorage
> xStorage
;
1989 if ( !pFilter
|| IsPackageStorageFormat_Impl( *pMedium
) )
1991 uno::Reference
< embed::XStorage
> xOld
= GetStorage();
1993 // when the package based medium is broken and has no storage or if the storage
1994 // is the same as the document storage the current document storage should be preserved
1995 xStorage
= pMedium
->GetStorage();
1996 bOk
= SaveCompleted( xStorage
);
1997 if ( bOk
&& xStorage
.is() && xOld
!= xStorage
1998 && (!pOld
|| !pOld
->HasStorage_Impl() || xOld
!= pOld
->GetStorage() ) )
2000 // old own storage was not controlled by old Medium -> dispose it
2003 } catch( uno::Exception
& )
2005 // the storage is disposed already
2006 // can happen during reload scenario when the medium has
2007 // disposed it during the closing
2008 // will be fixed in one of the next milestones
2014 if( pMedium
->GetOpenMode() & StreamMode::WRITE
)
2015 pMedium
->GetInStream();
2016 xStorage
= GetStorage();
2019 // TODO/LATER: may be this code will be replaced, but not sure
2020 // Set storage in document library containers
2021 pImp
->aBasicManager
.setStorage( xStorage
);
2023 // Get rid of this workaround after issue i113914 is fixed
2026 uno::Reference
< script::XStorageBasedLibraryContainer
> xBasicLibraries( pImp
->xBasicLibraries
, uno::UNO_QUERY_THROW
);
2027 xBasicLibraries
->setRootStorage( xStorage
);
2029 catch( uno::Exception
& )
2033 uno::Reference
< script::XStorageBasedLibraryContainer
> xDialogLibraries( pImp
->xDialogLibraries
, uno::UNO_QUERY_THROW
);
2034 xDialogLibraries
->setRootStorage( xStorage
);
2036 catch( uno::Exception
& )
2043 if( pFilter
&& !IsPackageStorageFormat_Impl( *pMedium
) && (pMedium
->GetOpenMode() & StreamMode::WRITE
))
2046 bOk
= SaveCompletedChildren( false );
2049 bOk
= SaveCompleted( NULL
);
2051 // either Save or ConvertTo
2053 bOk
= SaveCompleted( NULL
);
2056 if ( bOk
&& pNewMed
)
2062 uno::Reference
< frame::XModel
> xModel
= GetModel();
2065 OUString aURL
= pNewMed
->GetOrigURL();
2066 uno::Sequence
< beans::PropertyValue
> aMediaDescr
;
2067 TransformItems( SID_OPENDOC
, *pNewMed
->GetItemSet(), aMediaDescr
);
2070 xModel
->attachResource( aURL
, aMediaDescr
);
2072 catch( uno::Exception
& )
2076 // before the title regenerated the document must lose the signatures
2077 pImp
->nDocumentSignatureState
= SignatureState::NOSIGNATURES
;
2078 pImp
->nScriptingSignatureState
= pNewMed
->GetCachedSignatureState_Impl();
2079 OSL_ENSURE( pImp
->nScriptingSignatureState
!= SignatureState::BROKEN
, "The signature must not be broken at this place" );
2080 pImp
->bSignatureErrorIsShown
= false;
2082 // TODO/LATER: in future the medium must control own signature state, not the document
2083 pNewMed
->SetCachedSignatureState_Impl( SignatureState::NOSIGNATURES
); // set the default value back
2086 if (!pNewMed
->GetName().isEmpty() && SfxObjectCreateMode::EMBEDDED
!= eCreateMode
)
2088 SetModified(false); // reset only by set medium
2089 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED
) );
2091 // this is the end of the saving process, it is possible that
2092 // the file was changed
2093 // between medium commit and this step (attributes change and so on)
2094 // so get the file date again
2095 if ( pNewMed
->DocNeedsFileDateCheck() )
2096 pNewMed
->GetInitFileDate( true );
2100 pMedium
->ClearBackup_Impl();
2101 pMedium
->LockOrigFileOnDemand( true, false );
2103 AddToRecentlyUsedList();
2108 void SfxObjectShell::AddToRecentlyUsedList()
2110 INetURLObject
aUrl( pMedium
->GetOrigURL() );
2112 if ( aUrl
.GetProtocol() == INetProtocol::File
)
2114 const SfxFilter
* pOrgFilter
= pMedium
->GetOrigFilter();
2115 Application::AddToRecentDocumentList( aUrl
.GetURLNoPass( INetURLObject::NO_DECODE
),
2116 (pOrgFilter
) ? pOrgFilter
->GetMimeType() : OUString(),
2117 (pOrgFilter
) ? pOrgFilter
->GetServiceName() : OUString() );
2123 bool SfxObjectShell::ConvertFrom
2125 SfxMedium
& /*rMedium*/ /* <SfxMedium>, which describes the source file
2126 (for example file name, <SfxFilter>,
2127 Open-Modi and so on) */
2132 This method is called for loading of documents over all filters which are
2133 not SfxFilterFlags::OWN or for which no clipboard format has been registered
2134 (thus no storage format that is used). In other words, with this method
2137 Files which are to be opened here should be opened through 'rMedium'
2138 to guarantee the right open modes. Especially if the format is retained
2139 (only possible with SfxFilterFlags::SIMULATE or SfxFilterFlags::ONW) file which must
2140 be opened STREAM_SHARE_DENYWRITE.
2145 The document could be loaded.
2148 The document could not be loaded, an error code
2149 received through <SvMedium::GetError()const>
2153 bool DocSh::ConvertFrom( SfxMedium &rMedium )
2155 SvStreamRef xStream = rMedium.GetInStream();
2158 xStream->SetBufferSize(4096);
2161 // Do not call 'rMedium.CloseInStream()'! Keep File locked!
2162 return SVSTREAM_OK == rMedium.GetError();
2170 <SfxObjectShell::ConvertTo(SfxMedium&)>
2171 <SfxFilterFlags::REGISTRATION>
2177 bool SfxObjectShell::ImportFrom(SfxMedium
& rMedium
,
2178 css::uno::Reference
<css::text::XTextRange
> const& xInsertPosition
)
2180 OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2182 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2183 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2184 xMan
->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY
);
2186 uno::Sequence
< beans::PropertyValue
> aProps
;
2187 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2188 if ( xFilters
->hasByName( aFilterName
) )
2190 xFilters
->getByName( aFilterName
) >>= aProps
;
2191 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME
, aFilterName
) );
2194 OUString aFilterImplName
;
2195 sal_Int32 nFilterProps
= aProps
.getLength();
2196 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2198 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2199 if (rFilterProp
.Name
== "FilterService")
2201 rFilterProp
.Value
>>= aFilterImplName
;
2206 uno::Reference
< document::XFilter
> xLoader
;
2207 if ( !aFilterImplName
.isEmpty() )
2210 xLoader
= uno::Reference
< document::XFilter
>
2211 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2212 }catch(const uno::Exception
&)
2213 { xLoader
.clear(); }
2217 // it happens that xLoader does not support xImporter!
2219 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2220 uno::Reference
< document::XImporter
> xImporter( xLoader
, uno::UNO_QUERY_THROW
);
2221 xImporter
->setTargetDocument( xComp
);
2223 uno::Sequence
< beans::PropertyValue
> lDescriptor
;
2224 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, rMedium
.GetName() ) );
2225 TransformItems( SID_OPENDOC
, *rMedium
.GetItemSet(), lDescriptor
);
2227 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( lDescriptor
.getLength() );
2228 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2229 const com::sun::star::beans::PropertyValue
* pOldValue
= lDescriptor
.getConstArray();
2230 const OUString
sInputStream ( "InputStream" );
2232 bool bHasInputStream
= false;
2233 bool bHasBaseURL
= false;
2235 sal_Int32 nEnd
= lDescriptor
.getLength();
2237 for ( i
= 0; i
< nEnd
; i
++ )
2239 pNewValue
[i
] = pOldValue
[i
];
2240 if ( pOldValue
[i
].Name
== sInputStream
)
2241 bHasInputStream
= true;
2242 else if ( pOldValue
[i
].Name
== "DocumentBaseURL" )
2246 if ( !bHasInputStream
)
2248 aArgs
.realloc ( ++nEnd
);
2249 aArgs
[nEnd
-1].Name
= sInputStream
;
2250 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
> ( new utl::OSeekableInputStreamWrapper ( *rMedium
.GetInStream() ) );
2255 aArgs
.realloc ( ++nEnd
);
2256 aArgs
[nEnd
-1].Name
= "DocumentBaseURL";
2257 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL();
2260 if (xInsertPosition
.is()) {
2261 aArgs
.realloc( ++nEnd
);
2262 aArgs
[nEnd
-1].Name
= "InsertMode";
2263 aArgs
[nEnd
-1].Value
<<= true;
2264 aArgs
.realloc( ++nEnd
);
2265 aArgs
[nEnd
-1].Name
= "TextInsertModeRange";
2266 aArgs
[nEnd
-1].Value
<<= xInsertPosition
;
2269 // #i119492# During loading, some OLE objects like chart will be set
2270 // modified flag, so needs to reset the flag to false after loading
2271 bool bRtn
= xLoader
->filter( aArgs
);
2272 uno::Sequence
< OUString
> aNames
= GetEmbeddedObjectContainer().GetObjectNames();
2273 for ( sal_Int32 n
= 0; n
< aNames
.getLength(); ++n
)
2275 OUString aName
= aNames
[n
];
2276 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObjectContainer().GetEmbeddedObject( aName
);
2277 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
2280 sal_Int32 nState
= xObj
->getCurrentState();
2281 if ( nState
== embed::EmbedStates::LOADED
|| nState
== embed::EmbedStates::RUNNING
) // means that the object is not active
2283 uno::Reference
< util::XModifiable
> xModifiable( xObj
->getComponent(), uno::UNO_QUERY
);
2284 if ( xModifiable
.is() )
2285 xModifiable
->setModified(sal_False
);
2291 catch (const packages::zip::ZipIOException
&)
2293 SetError( ERRCODE_IO_BROKENPACKAGE
, "Badness in the underlying package format." );
2295 catch (const lang::WrappedTargetRuntimeException
& rWrapped
)
2297 io::WrongFormatException e
;
2298 if (rWrapped
.TargetException
>>= e
)
2300 SetError(*new StringErrorInfo(ERRCODE_SFX_FORMAT_ROWCOL
,
2301 e
.Message
, ERRCODE_BUTTON_OK
| ERRCODE_MSG_ERROR
), "");
2311 bool SfxObjectShell::ExportTo( SfxMedium
& rMedium
)
2313 OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2314 uno::Reference
< document::XExporter
> xExporter
;
2317 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2318 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2319 xMan
->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY
);
2321 uno::Sequence
< beans::PropertyValue
> aProps
;
2322 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2323 if ( xFilters
->hasByName( aFilterName
) )
2324 xFilters
->getByName( aFilterName
) >>= aProps
;
2326 OUString aFilterImplName
;
2327 sal_Int32 nFilterProps
= aProps
.getLength();
2328 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2330 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2331 if (rFilterProp
.Name
== "FilterService")
2333 rFilterProp
.Value
>>= aFilterImplName
;
2338 if ( !aFilterImplName
.isEmpty() )
2341 xExporter
= uno::Reference
< document::XExporter
>
2342 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2343 }catch(const uno::Exception
&)
2344 { xExporter
.clear(); }
2348 if ( xExporter
.is() )
2351 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2352 uno::Reference
< document::XFilter
> xFilter( xExporter
, uno::UNO_QUERY_THROW
);
2353 xExporter
->setSourceDocument( xComp
);
2355 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aOldArgs
;
2356 SfxItemSet
* pItems
= rMedium
.GetItemSet();
2357 TransformItems( SID_SAVEASDOC
, *pItems
, aOldArgs
);
2359 const com::sun::star::beans::PropertyValue
* pOldValue
= aOldArgs
.getConstArray();
2360 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( aOldArgs
.getLength() );
2361 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2363 // put in the REAL file name, and copy all PropertyValues
2364 const OUString
sOutputStream ( "OutputStream" );
2365 const OUString
sStream ( "StreamForOutput" );
2366 bool bHasOutputStream
= false;
2367 bool bHasStream
= false;
2368 bool bHasBaseURL
= false;
2369 bool bHasFilterName
= false;
2371 sal_Int32 nEnd
= aOldArgs
.getLength();
2373 for ( i
= 0; i
< nEnd
; i
++ )
2375 pNewValue
[i
] = pOldValue
[i
];
2376 if ( pOldValue
[i
].Name
== "FileName" )
2377 pNewValue
[i
].Value
<<= OUString ( rMedium
.GetName() );
2378 else if ( pOldValue
[i
].Name
== sOutputStream
)
2379 bHasOutputStream
= true;
2380 else if ( pOldValue
[i
].Name
== sStream
)
2382 else if ( pOldValue
[i
].Name
== "DocumentBaseURL" )
2384 else if( pOldValue
[i
].Name
== "FilterName" )
2385 bHasFilterName
= true;
2388 if ( !bHasOutputStream
)
2390 aArgs
.realloc ( ++nEnd
);
2391 aArgs
[nEnd
-1].Name
= sOutputStream
;
2392 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XOutputStream
> ( new utl::OOutputStreamWrapper ( *rMedium
.GetOutStream() ) );
2395 // add stream as well, for OOX export and maybe others
2398 aArgs
.realloc ( ++nEnd
);
2399 aArgs
[nEnd
-1].Name
= sStream
;
2400 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XStream
> ( new utl::OStreamWrapper ( *rMedium
.GetOutStream() ) );
2405 aArgs
.realloc ( ++nEnd
);
2406 aArgs
[nEnd
-1].Name
= "DocumentBaseURL";
2407 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL( true );
2410 if( !bHasFilterName
)
2412 aArgs
.realloc( ++nEnd
);
2413 aArgs
[nEnd
-1].Name
= "FilterName";
2414 aArgs
[nEnd
-1].Value
<<= aFilterName
;
2417 return xFilter
->filter( aArgs
);
2418 }catch(const uno::Exception
&)
2427 bool SfxObjectShell::ConvertTo
2429 SfxMedium
& /*rMedium*/ /* <SfxMedium>, which describes the target file
2430 (for example file name, <SfxFilter>,
2431 Open-Modi and so on) */
2436 This method is called for saving of documents over all filters which are
2437 not SfxFilterFlags::OWN or for which no clipboard format has been registered
2438 (thus no storage format that is used). In other words, with this method
2441 Files which are to be opened here should be opened through 'rMedium'
2442 to guarantee the right open modes. Especially if the format is retained
2443 (only possible with SfxFilterFlags::SIMULATE or SfxFilterFlags::ONW) file which must
2444 be opened STREAM_SHARE_DENYWRITE.
2449 The document could be saved.
2452 The document could not be saved, an error code is
2453 received by <SvMedium::GetError()const>
2458 bool DocSh::ConvertTo( SfxMedium &rMedium )
2460 SvStreamRef xStream = rMedium.GetOutStream();
2463 xStream->SetBufferSize(4096);
2466 rMedium.CloseOutStream(); // opens the InStream automatically
2467 return SVSTREAM_OK == rMedium.GetError();
2474 <SfxObjectShell::ConvertFrom(SfxMedium&)>
2475 <SfxFilterFlags::REGISTRATION>
2484 bool SfxObjectShell::DoSave_Impl( const SfxItemSet
* pArgs
)
2486 SfxMedium
* pRetrMedium
= GetMedium();
2487 const SfxFilter
* pFilter
= pRetrMedium
->GetFilter();
2489 // copy the original itemset, but remove the "version" item, because pMediumTmp
2490 // is a new medium "from scratch", so no version should be stored into it
2491 SfxItemSet
* pSet
= new SfxAllItemSet(*pRetrMedium
->GetItemSet());
2492 pSet
->ClearItem( SID_VERSION
);
2493 pSet
->ClearItem( SID_DOC_BASEURL
);
2495 // copy the version comment and major items for the checkin only
2496 if ( pRetrMedium
->IsInCheckIn( ) )
2498 const SfxPoolItem
* pMajor
= pArgs
->GetItem( SID_DOCINFO_MAJOR
);
2500 pSet
->Put( *pMajor
);
2502 const SfxPoolItem
* pComments
= pArgs
->GetItem( SID_DOCINFO_COMMENTS
);
2504 pSet
->Put( *pComments
);
2507 // create a medium as a copy; this medium is only for writingm, because it
2508 // uses the same name as the original one writing is done through a copy,
2509 // that will be transferred to the target (of course after calling HandsOff)
2510 SfxMedium
* pMediumTmp
= new SfxMedium( pRetrMedium
->GetName(), pRetrMedium
->GetOpenMode(), pFilter
, pSet
);
2511 pMediumTmp
->SetInCheckIn( pRetrMedium
->IsInCheckIn( ) );
2512 pMediumTmp
->SetLongName( pRetrMedium
->GetLongName() );
2513 if ( pMediumTmp
->GetErrorCode() != ERRCODE_NONE
)
2515 SetError( pMediumTmp
->GetError(), OUString( OSL_LOG_PREFIX
) );
2520 // copy version list from "old" medium to target medium, so it can be used on saving
2521 pMediumTmp
->TransferVersionList_Impl( *pRetrMedium
);
2523 // an interaction handler here can acquire only in case of GUI Saving
2524 // and should be removed after the saving is done
2525 com::sun::star::uno::Reference
< XInteractionHandler
> xInteract
;
2526 SFX_ITEMSET_ARG( pArgs
, pxInteractionItem
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, false );
2527 if ( pxInteractionItem
&& ( pxInteractionItem
->GetValue() >>= xInteract
) && xInteract
.is() )
2528 pMediumTmp
->GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny( xInteract
) ) );
2530 bool bSaved
= false;
2531 if( !GetError() && SaveTo_Impl( *pMediumTmp
, pArgs
) )
2535 if( pMediumTmp
->GetItemSet() )
2537 pMediumTmp
->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER
);
2538 pMediumTmp
->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2541 SetError(pMediumTmp
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2543 bool bOpen( false );
2544 bOpen
= DoSaveCompleted( pMediumTmp
);
2546 DBG_ASSERT(bOpen
,"Error handling for DoSaveCompleted not implemented");
2551 // transfer error code from medium to objectshell
2552 SetError( pMediumTmp
->GetError(), OUString( OSL_LOG_PREFIX
) );
2554 // reconnect to object storage
2555 DoSaveCompleted( 0 );
2557 if( pRetrMedium
->GetItemSet() )
2559 pRetrMedium
->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER
);
2560 pRetrMedium
->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2566 SetModified( !bSaved
);
2572 bool SfxObjectShell::Save_Impl( const SfxItemSet
* pSet
)
2576 SetError( ERRCODE_SFX_DOCUMENTREADONLY
, OUString( OSL_LOG_PREFIX
) );
2581 pImp
->bIsSaving
= true;
2582 bool bSaved
= false;
2583 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, false);
2586 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pFilterItem
, SfxStringItem
, SID_FILTER_NAME
, false);
2587 OUString aFilterName
;
2588 const SfxFilter
*pFilter
= NULL
;
2590 pFilter
= SfxFilterMatcher( OUString::createFromAscii( GetFactory().GetShortName()) ).GetFilter4FilterName( aFilterName
);
2592 SfxMedium
*pMed
= new SfxMedium(
2593 pSalvageItem
->GetValue(), STREAM_READWRITE
| StreamMode::SHARE_DENYWRITE
| StreamMode::TRUNC
, pFilter
);
2595 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem
, SfxStringItem
, SID_PASSWORD
, false );
2596 if ( pPasswordItem
)
2597 pMed
->GetItemSet()->Put( *pPasswordItem
);
2599 bSaved
= DoSaveAs( *pMed
);
2601 bSaved
= DoSaveCompleted( pMed
);
2606 bSaved
= DoSave_Impl( pSet
);
2612 bool SfxObjectShell::CommonSaveAs_Impl
2614 const INetURLObject
& aURL
,
2615 const OUString
& aFilterName
,
2619 if( aURL
.HasError() )
2621 SetError( ERRCODE_IO_INVALIDPARAMETER
, OUString( OSL_LOG_PREFIX
) );
2625 if ( aURL
!= INetURLObject( OUString( "private:stream" ) ) )
2627 // Is there already a Document with this name?
2628 SfxObjectShell
* pDoc
= 0;
2629 for ( SfxObjectShell
* pTmp
= SfxObjectShell::GetFirst();
2631 pTmp
= SfxObjectShell::GetNext(*pTmp
) )
2633 if( ( pTmp
!= this ) && pTmp
->GetMedium() )
2635 INetURLObject
aCompare( pTmp
->GetMedium()->GetName() );
2636 if ( aCompare
== aURL
)
2642 // Then error message: "already opened"
2643 SetError(ERRCODE_SFX_ALREADYOPEN
, OUString( OSL_LOG_PREFIX
));
2648 DBG_ASSERT( aURL
.GetProtocol() != INetProtocol::NotValid
, "Illegal URL!" );
2649 DBG_ASSERT( aParams
->Count() != 0, "Incorrect Parameter");
2651 SFX_ITEMSET_ARG( aParams
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, false );
2652 bool bSaveTo
= pSaveToItem
&& pSaveToItem
->GetValue();
2654 const SfxFilter
* pFilter
= GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName
);
2656 || !pFilter
->CanExport()
2657 || (!bSaveTo
&& !pFilter
->CanImport()) )
2659 SetError( ERRCODE_IO_INVALIDPARAMETER
, OUString( OSL_LOG_PREFIX
) );
2663 SFX_ITEMSET_ARG( aParams
, pCopyStreamItem
, SfxBoolItem
, SID_COPY_STREAM_IF_POSSIBLE
, false );
2664 if ( bSaveTo
&& pCopyStreamItem
&& pCopyStreamItem
->GetValue() && !IsModified() )
2666 if ( pMedium
->TryDirectTransfer( aURL
.GetMainURL( INetURLObject::NO_DECODE
), *aParams
) )
2669 aParams
->ClearItem( SID_COPY_STREAM_IF_POSSIBLE
);
2671 pImp
->bPasswd
= SfxItemState::SET
== aParams
->GetItemState(SID_PASSWORD
);
2673 SfxMedium
*pActMed
= GetMedium();
2674 const INetURLObject
aActName(pActMed
->GetName());
2676 bool bWasReadonly
= IsReadOnly();
2678 if ( aURL
== aActName
&& aURL
!= INetURLObject( OUString("private:stream") )
2681 SetError(ERRCODE_SFX_DOCUMENTREADONLY
, OUString( OSL_LOG_PREFIX
));
2685 if( SfxItemState::SET
!= aParams
->GetItemState(SID_UNPACK
) && SvtSaveOptions().IsSaveUnpacked() )
2686 aParams
->Put( SfxBoolItem( SID_UNPACK
, false ) );
2688 OUString aTempFileURL
;
2689 if ( IsDocShared() )
2690 aTempFileURL
= pMedium
->GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
2692 if ( PreDoSaveAs_Impl(aURL
.GetMainURL( INetURLObject::NO_DECODE
),aFilterName
,aParams
))
2694 // Update Data on media
2695 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
2696 pSet
->ClearItem( SID_INTERACTIONHANDLER
);
2697 pSet
->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2698 pSet
->ClearItem( SID_STANDARD_DIR
);
2699 pSet
->ClearItem( SID_PATH
);
2703 pSet
->ClearItem( SID_REFERER
);
2704 pSet
->ClearItem( SID_POSTDATA
);
2705 pSet
->ClearItem( SID_TEMPLATE
);
2706 pSet
->ClearItem( SID_DOC_READONLY
);
2707 pSet
->ClearItem( SID_CONTENTTYPE
);
2708 pSet
->ClearItem( SID_CHARSET
);
2709 pSet
->ClearItem( SID_FILTER_NAME
);
2710 pSet
->ClearItem( SID_OPTIONS
);
2711 pSet
->ClearItem( SID_VERSION
);
2712 pSet
->ClearItem( SID_EDITDOC
);
2713 pSet
->ClearItem( SID_OVERWRITE
);
2714 pSet
->ClearItem( SID_DEFAULTFILEPATH
);
2715 pSet
->ClearItem( SID_DEFAULTFILENAME
);
2717 SFX_ITEMSET_GET( (*aParams
), pFilterItem
, SfxStringItem
, SID_FILTER_NAME
, false );
2719 pSet
->Put( *pFilterItem
);
2721 SFX_ITEMSET_GET( (*aParams
), pOptionsItem
, SfxStringItem
, SID_OPTIONS
, false );
2723 pSet
->Put( *pOptionsItem
);
2725 SFX_ITEMSET_GET( (*aParams
), pFilterOptItem
, SfxStringItem
, SID_FILE_FILTEROPTIONS
, false );
2726 if ( pFilterOptItem
)
2727 pSet
->Put( *pFilterOptItem
);
2729 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2730 if ( IsDocShared() && !aTempFileURL
.isEmpty() )
2732 // this is a shared document that has to be disconnected from the old location
2733 FreeSharedFile( aTempFileURL
);
2735 if ( pFilter
->IsOwnFormat()
2736 && pFilter
->UsesStorage()
2737 && pFilter
->GetVersion() >= SOFFICE_FILEFORMAT_60
)
2739 // the target format is the own format
2740 // the target document must be shared
2741 SwitchToShared( true, false );
2747 if ( bWasReadonly
&& !bSaveTo
)
2748 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED
) );
2758 bool SfxObjectShell::PreDoSaveAs_Impl
2760 const OUString
& rFileName
,
2761 const OUString
& aFilterName
,
2765 // copy all items stored in the itemset of the current medium
2766 SfxAllItemSet
* pMergedParams
= new SfxAllItemSet( *pMedium
->GetItemSet() );
2768 // in "SaveAs" title and password will be cleared ( maybe the new itemset contains new values, otherwise they will be empty )
2769 pMergedParams
->ClearItem( SID_ENCRYPTIONDATA
);
2770 pMergedParams
->ClearItem( SID_PASSWORD
);
2771 // #i119366# - As the SID_ENCRYPTIONDATA and SID_PASSWORD are using for setting password together, we need to clear them both.
2772 // Also, ( maybe the new itemset contains new values, otherwise they will be empty )
2773 pMergedParams
->ClearItem( SID_ENCRYPTIONDATA
);
2774 pMergedParams
->ClearItem( SID_DOCINFO_TITLE
);
2776 pMergedParams
->ClearItem( SID_INPUTSTREAM
);
2777 pMergedParams
->ClearItem( SID_STREAM
);
2778 pMergedParams
->ClearItem( SID_CONTENT
);
2779 pMergedParams
->ClearItem( SID_DOC_READONLY
);
2780 pMergedParams
->ClearItem( SID_DOC_BASEURL
);
2782 pMergedParams
->ClearItem( SID_REPAIRPACKAGE
);
2784 // "SaveAs" will never store any version information - it's a complete new file !
2785 pMergedParams
->ClearItem( SID_VERSION
);
2787 // merge the new parameters into the copy
2788 // all values present in both itemsets will be overwritten by the new parameters
2790 pMergedParams
->Put( *pParams
);
2793 if ( pMergedParams
->GetItemState( SID_DOC_SALVAGE
) >= SfxItemState::SET
)
2794 SAL_WARN( "sfx.doc","Salvage item present in Itemset, check the parameters!");
2797 // should be unnecessary - too hot to handle!
2798 pMergedParams
->ClearItem( SID_DOC_SALVAGE
);
2800 // take over the new merged itemset
2801 pParams
= pMergedParams
;
2803 // create a medium for the target URL
2804 SfxMedium
*pNewFile
= new SfxMedium( rFileName
, STREAM_READWRITE
| StreamMode::SHARE_DENYWRITE
| StreamMode::TRUNC
, 0, pParams
);
2806 // set filter; if no filter is given, take the default filter of the factory
2807 if ( !aFilterName
.isEmpty() )
2808 pNewFile
->SetFilter( GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName
) );
2810 pNewFile
->SetFilter( GetFactory().GetFilterContainer()->GetAnyFilter( SfxFilterFlags::IMPORT
| SfxFilterFlags::EXPORT
) );
2812 if ( pNewFile
->GetErrorCode() != ERRCODE_NONE
)
2814 // creating temporary file failed ( f.e. floppy disk not inserted! )
2815 SetError( pNewFile
->GetError(), OUString( OSL_LOG_PREFIX
) );
2820 // check if a "SaveTo" is wanted, no "SaveAs"
2821 SFX_ITEMSET_ARG( pParams
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, false );
2822 bool bCopyTo
= GetCreateMode() == SfxObjectCreateMode::EMBEDDED
|| (pSaveToItem
&& pSaveToItem
->GetValue());
2824 // distinguish between "Save" and "SaveAs"
2825 pImp
->bIsSaving
= false;
2827 // copy version list from "old" medium to target medium, so it can be used on saving
2828 if ( pImp
->bPreserveVersions
)
2829 pNewFile
->TransferVersionList_Impl( *pMedium
);
2831 // Save the document ( first as temporary file, then transfer to the target URL by committing the medium )
2833 if ( !pNewFile
->GetErrorCode() && SaveTo_Impl( *pNewFile
, NULL
) )
2837 // transfer a possible error from the medium to the document
2838 SetError( pNewFile
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2840 // notify the document that saving was done successfully
2843 bOk
= DoSaveCompleted( pNewFile
);
2846 bOk
= DoSaveCompleted(0);
2851 SetModified( false );
2855 // TODO/LATER: the code below must be dead since the storage commit makes all the stuff
2856 // and the DoSaveCompleted call should not be able to fail in general
2858 DBG_ASSERT( !bCopyTo
, "Error while reconnecting to medium, can't be handled!");
2859 SetError( pNewFile
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2863 // reconnect to the old medium
2865 bRet
= DoSaveCompleted( pMedium
);
2866 DBG_ASSERT( bRet
, "Error in DoSaveCompleted, can't be handled!");
2870 // TODO/LATER: disconnect the new file from the storage for the case when pure saving is done
2871 // if storing has corrupted the file, probably it must be restored either here or
2873 DELETEZ( pNewFile
);
2878 SetError( pNewFile
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2880 // reconnect to the old storage
2881 DoSaveCompleted( 0 );
2883 DELETEZ( pNewFile
);
2887 DELETEZ( pNewFile
);
2889 SetModified( true );
2896 bool SfxObjectShell::LoadFrom( SfxMedium
& /*rMedium*/ )
2898 SAL_WARN( "sfx.doc", "Base implementation, must not be called in general!" );
2903 bool SfxObjectShell::IsInformationLost()
2905 Sequence
< PropertyValue
> aProps
= GetModel()->getArgs();
2906 OUString aFilterName
;
2907 OUString aPreusedFilterName
;
2908 for ( sal_Int32 nInd
= 0; nInd
< aProps
.getLength(); nInd
++ )
2910 if ( aProps
[nInd
].Name
== "FilterName" )
2911 aProps
[nInd
].Value
>>= aFilterName
;
2912 else if ( aProps
[nInd
].Name
== "PreusedFilterName" )
2913 aProps
[nInd
].Value
>>= aPreusedFilterName
;
2916 // if current filter can lead to information loss and it was used
2917 // for the latest store then the user should be asked to store in own format
2918 if ( !aFilterName
.isEmpty() && aFilterName
.equals( aPreusedFilterName
) )
2920 const SfxFilter
*pFilt
= GetMedium()->GetFilter();
2921 DBG_ASSERT( pFilt
&& aFilterName
.equals( pFilt
->GetName() ), "MediaDescriptor contains wrong filter!\n" );
2922 return ( pFilt
&& pFilt
->IsAlienFormat() );
2929 bool SfxObjectShell::CanReload_Impl()
2933 Internal method for determining whether a reload of the document
2934 (as RevertToSaved or last known version) is possible.
2938 return pMedium
&& HasName() && !IsInModalMode() && !pImp
->bForbidReload
;
2943 HiddenInformation
SfxObjectShell::GetHiddenInformationState( HiddenInformation nStates
)
2945 HiddenInformation nState
= HiddenInformation::NONE
;
2946 if ( nStates
& HiddenInformation::DOCUMENTVERSIONS
)
2948 if ( GetMedium()->GetVersionList().getLength() )
2949 nState
|= HiddenInformation::DOCUMENTVERSIONS
;
2955 sal_Int16
SfxObjectShell::QueryHiddenInformation( HiddenWarningFact eFact
, vcl::Window
* pParent
)
2957 sal_Int16 nRet
= RET_YES
;
2958 sal_uInt16 nResId
= sal_uInt16();
2959 SvtSecurityOptions::EOption eOption
= SvtSecurityOptions::EOption();
2963 case HiddenWarningFact::WhenSaving
:
2965 nResId
= STR_HIDDENINFO_CONTINUE_SAVING
;
2966 eOption
= SvtSecurityOptions::E_DOCWARN_SAVEORSEND
;
2969 case HiddenWarningFact::WhenPrinting
:
2971 nResId
= STR_HIDDENINFO_CONTINUE_PRINTING
;
2972 eOption
= SvtSecurityOptions::E_DOCWARN_PRINT
;
2975 case HiddenWarningFact::WhenSigning
:
2977 nResId
= STR_HIDDENINFO_CONTINUE_SIGNING
;
2978 eOption
= SvtSecurityOptions::E_DOCWARN_SIGNING
;
2981 case HiddenWarningFact::WhenCreatingPDF
:
2983 nResId
= STR_HIDDENINFO_CONTINUE_CREATEPDF
;
2984 eOption
= SvtSecurityOptions::E_DOCWARN_CREATEPDF
;
2988 assert(false); // this cannot happen
2991 if ( SvtSecurityOptions().IsOptionSet( eOption
) )
2993 OUString
sMessage( SfxResId(STR_HIDDENINFO_CONTAINS
).toString() );
2994 HiddenInformation nWantedStates
= HiddenInformation::RECORDEDCHANGES
| HiddenInformation::NOTES
;
2995 if ( eFact
!= HiddenWarningFact::WhenPrinting
)
2996 nWantedStates
|= HiddenInformation::DOCUMENTVERSIONS
;
2997 HiddenInformation nStates
= GetHiddenInformationState( nWantedStates
);
2998 bool bWarning
= false;
3000 if ( nStates
& HiddenInformation::RECORDEDCHANGES
)
3002 sMessage
+= SfxResId(STR_HIDDENINFO_RECORDCHANGES
).toString();
3006 if ( nStates
& HiddenInformation::NOTES
)
3008 sMessage
+= SfxResId(STR_HIDDENINFO_NOTES
).toString();
3012 if ( nStates
& HiddenInformation::DOCUMENTVERSIONS
)
3014 sMessage
+= SfxResId(STR_HIDDENINFO_DOCVERSIONS
).toString();
3022 sMessage
+= SfxResId(nResId
).toString();
3023 ScopedVclPtrInstance
< WarningBox
> aWBox(pParent
, WB_YES_NO
| WB_DEF_NO
, sMessage
);
3024 nRet
= aWBox
->Execute();
3031 bool SfxObjectShell::IsSecurityOptOpenReadOnly() const
3033 return IsLoadReadonly();
3036 void SfxObjectShell::SetSecurityOptOpenReadOnly( bool _b
)
3038 SetLoadReadonly( _b
);
3041 bool SfxObjectShell::LoadOwnFormat( SfxMedium
& rMedium
)
3043 SAL_INFO( "sfx.doc", "loading \" " << rMedium
.GetName() << "\"" );
3045 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3046 if ( xStorage
.is() )
3049 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pPasswdItem
, SfxStringItem
, SID_PASSWORD
, false );
3050 if ( pPasswdItem
|| ERRCODE_IO_ABORT
!= CheckPasswd_Impl( this, SfxGetpApp()->GetPool(), pMedium
) )
3052 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
3053 if ( GetEncryptionData_Impl(pMedium
->GetItemSet(), aEncryptionData
) )
3057 // the following code must throw an exception in case of failure
3058 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xStorage
, aEncryptionData
);
3060 catch( uno::Exception
& )
3062 // TODO/LATER: handle the error code
3067 return Load( rMedium
);
3075 bool SfxObjectShell::SaveAsOwnFormat( SfxMedium
& rMedium
)
3077 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3080 sal_Int32 nVersion
= rMedium
.GetFilter()->GetVersion();
3082 // OASIS templates have own mediatypes ( SO7 also actually, but it is to late to use them here )
3083 const bool bTemplate
= rMedium
.GetFilter()->IsOwnTemplateFormat()
3084 && nVersion
> SOFFICE_FILEFORMAT_60
;
3086 const SfxFilter
* pFilter
= rMedium
.GetFilter();
3087 bool bChart
= false;
3088 if(pFilter
->GetName() == "chart8")
3091 SetupStorage( xStorage
, nVersion
, bTemplate
, bChart
);
3092 #if HAVE_FEATURE_SCRIPTING
3098 // Save dialog/script container
3099 pImp
->aBasicManager
.storeLibrariesToStorage( xStorage
);
3102 return SaveAs( rMedium
);
3107 uno::Reference
< embed::XStorage
> SfxObjectShell::GetStorage()
3109 if ( !pImp
->m_xDocStorage
.is() )
3111 OSL_ENSURE( pImp
->m_bCreateTempStor
, "The storage must exist already!\n" );
3113 // no notification is required the storage is set the first time
3114 pImp
->m_xDocStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3115 OSL_ENSURE( pImp
->m_xDocStorage
.is(), "The method must either return storage or throw an exception!" );
3117 SetupStorage( pImp
->m_xDocStorage
, SOFFICE_FILEFORMAT_CURRENT
, false, false );
3118 pImp
->m_bCreateTempStor
= false;
3119 SfxGetpApp()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED
, GlobalEventConfig::GetEventName(GlobalEventId::STORAGECHANGED
), this ) );
3121 catch( uno::Exception
& )
3123 // TODO/LATER: error handling?
3124 DBG_UNHANDLED_EXCEPTION();
3128 OSL_ENSURE( pImp
->m_xDocStorage
.is(), "The document storage must be created!" );
3129 return pImp
->m_xDocStorage
;
3133 bool SfxObjectShell::SaveChildren( bool bObjectsOnly
)
3135 bool bResult
= true;
3136 if ( pImp
->mpObjectContainer
)
3138 bool bOasis
= ( SotStorage::GetVersion( GetStorage() ) > SOFFICE_FILEFORMAT_60
);
3139 GetEmbeddedObjectContainer().StoreChildren(bOasis
,bObjectsOnly
);
3145 bool SfxObjectShell::SaveAsChildren( SfxMedium
& rMedium
)
3147 bool bResult
= true;
3149 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3150 if ( !xStorage
.is() )
3153 if ( xStorage
== GetStorage() )
3154 return SaveChildren();
3156 if ( pImp
->mpObjectContainer
)
3158 bool bOasis
= ( SotStorage::GetVersion( xStorage
) > SOFFICE_FILEFORMAT_60
);
3159 GetEmbeddedObjectContainer().StoreAsChildren(bOasis
,SfxObjectCreateMode::EMBEDDED
== eCreateMode
,xStorage
);
3163 bResult
= CopyStoragesOfUnknownMediaType( GetStorage(), xStorage
);
3168 bool SfxObjectShell::SaveCompletedChildren( bool bSuccess
)
3170 bool bResult
= true;
3172 if ( pImp
->mpObjectContainer
)
3174 uno::Sequence
< OUString
> aNames
= GetEmbeddedObjectContainer().GetObjectNames();
3175 for ( sal_Int32 n
=0; n
<aNames
.getLength(); n
++ )
3177 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObjectContainer().GetEmbeddedObject( aNames
[n
] );
3178 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
3181 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
3182 if ( xPersist
.is() )
3186 xPersist
->saveCompleted( bSuccess
);
3188 catch( uno::Exception
& )
3190 // TODO/LATER: error handling
3202 bool SfxObjectShell::SwitchChildrenPersistance( const uno::Reference
< embed::XStorage
>& xStorage
,
3203 bool bForceNonModified
)
3205 if ( !xStorage
.is() )
3207 // TODO/LATER: error handling
3211 bool bResult
= true;
3213 if ( pImp
->mpObjectContainer
)
3214 pImp
->mpObjectContainer
->SetPersistentEntries(xStorage
,bForceNonModified
);
3219 // Never call this method directly, always use the DoSaveCompleted call
3220 bool SfxObjectShell::SaveCompleted( const uno::Reference
< embed::XStorage
>& xStorage
)
3222 bool bResult
= false;
3223 bool bSendNotification
= false;
3224 uno::Reference
< embed::XStorage
> xOldStorageHolder
;
3227 // check for wrong creation of object container
3228 bool bHasContainer
= ( pImp
->mpObjectContainer
!= 0 );
3231 if ( !xStorage
.is() || xStorage
== GetStorage() )
3233 // no persistence change
3234 bResult
= SaveCompletedChildren( false );
3238 if ( pImp
->mpObjectContainer
)
3239 GetEmbeddedObjectContainer().SwitchPersistence( xStorage
);
3241 bResult
= SwitchChildrenPersistance( xStorage
, true );
3246 if ( xStorage
.is() && pImp
->m_xDocStorage
!= xStorage
)
3248 // make sure that until the storage is assigned the object
3249 // container is not created by accident!
3250 DBG_ASSERT( bHasContainer
== (pImp
->mpObjectContainer
!= 0), "Wrong storage in object container!" );
3251 xOldStorageHolder
= pImp
->m_xDocStorage
;
3252 pImp
->m_xDocStorage
= xStorage
;
3253 bSendNotification
= true;
3255 if ( IsEnableSetModified() )
3256 SetModified( false );
3261 if ( pImp
->mpObjectContainer
)
3262 GetEmbeddedObjectContainer().SwitchPersistence( pImp
->m_xDocStorage
);
3264 // let already successfully connected objects be switched back
3265 SwitchChildrenPersistance( pImp
->m_xDocStorage
, true );
3268 if ( bSendNotification
)
3270 SfxGetpApp()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED
, GlobalEventConfig::GetEventName(GlobalEventId::STORAGECHANGED
), this ) );
3276 #if OSL_DEBUG_LEVEL > 0
3277 bool StoragesOfUnknownMediaTypeAreCopied_Impl( const uno::Reference
< embed::XStorage
>& xSource
,
3278 const uno::Reference
< embed::XStorage
>& xTarget
)
3280 OSL_ENSURE( xSource
.is() && xTarget
.is(), "Source and/or target storages are not available!\n" );
3281 if ( !xSource
.is() || !xTarget
.is() || xSource
== xTarget
)
3286 uno::Sequence
< OUString
> aSubElements
= xSource
->getElementNames();
3287 for ( sal_Int32 nInd
= 0; nInd
< aSubElements
.getLength(); nInd
++ )
3289 if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3291 OUString aMediaType
;
3292 OUString
aMediaTypePropName( "MediaType" );
3293 bool bGotMediaType
= false;
3297 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xSource
, uno::UNO_QUERY_THROW
);
3299 ( xOptStorage
->getElementPropertyValue( aSubElements
[nInd
], aMediaTypePropName
) >>= aMediaType
);
3301 catch( uno::Exception
& )
3304 if ( !bGotMediaType
)
3306 uno::Reference
< embed::XStorage
> xSubStorage
;
3308 xSubStorage
= xSource
->openStorageElement( aSubElements
[nInd
], embed::ElementModes::READ
);
3309 } catch( uno::Exception
& )
3312 if ( !xSubStorage
.is() )
3314 xSubStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3315 xSource
->copyStorageElementLastCommitTo( aSubElements
[nInd
], xSubStorage
);
3318 uno::Reference
< beans::XPropertySet
> xProps( xSubStorage
, uno::UNO_QUERY_THROW
);
3319 bGotMediaType
= ( xProps
->getPropertyValue( aMediaTypePropName
) >>= aMediaType
);
3322 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3323 // probably it should be placed in the MimeType-ClassID table or in standalone table
3324 if ( !aMediaType
.isEmpty()
3325 && aMediaType
!= "application/vnd.sun.star.oleobject" )
3327 ::com::sun::star::datatransfer::DataFlavor aDataFlavor
;
3328 aDataFlavor
.MimeType
= aMediaType
;
3329 SotClipboardFormatId nFormat
= SotExchange::GetFormat( aDataFlavor
);
3333 case SotClipboardFormatId::STARWRITER_60
:
3334 case SotClipboardFormatId::STARWRITERWEB_60
:
3335 case SotClipboardFormatId::STARWRITERGLOB_60
:
3336 case SotClipboardFormatId::STARDRAW_60
:
3337 case SotClipboardFormatId::STARIMPRESS_60
:
3338 case SotClipboardFormatId::STARCALC_60
:
3339 case SotClipboardFormatId::STARCHART_60
:
3340 case SotClipboardFormatId::STARMATH_60
:
3341 case SotClipboardFormatId::STARWRITER_8
:
3342 case SotClipboardFormatId::STARWRITERWEB_8
:
3343 case SotClipboardFormatId::STARWRITERGLOB_8
:
3344 case SotClipboardFormatId::STARDRAW_8
:
3345 case SotClipboardFormatId::STARIMPRESS_8
:
3346 case SotClipboardFormatId::STARCALC_8
:
3347 case SotClipboardFormatId::STARCHART_8
:
3348 case SotClipboardFormatId::STARMATH_8
:
3353 if ( !xTarget
->hasByName( aSubElements
[nInd
] ) )
3361 catch( uno::Exception
& )
3363 SAL_WARN( "sfx.doc", "Can not check storage consistency!" );
3370 bool SfxObjectShell::SwitchPersistance( const uno::Reference
< embed::XStorage
>& xStorage
)
3372 bool bResult
= false;
3374 // check for wrong creation of object container
3375 bool bHasContainer
= ( pImp
->mpObjectContainer
!= 0 );
3377 if ( xStorage
.is() )
3379 if ( pImp
->mpObjectContainer
)
3380 GetEmbeddedObjectContainer().SwitchPersistence( xStorage
);
3381 bResult
= SwitchChildrenPersistance( xStorage
);
3383 // TODO/LATER: substorages that have unknown mimetypes probably should be copied to the target storage here
3384 OSL_ENSURE( StoragesOfUnknownMediaTypeAreCopied_Impl( pImp
->m_xDocStorage
, xStorage
),
3385 "Some of substorages with unknown mimetypes is lost!" );
3390 // make sure that until the storage is assigned the object container is not created by accident!
3391 DBG_ASSERT( bHasContainer
== (pImp
->mpObjectContainer
!= 0), "Wrong storage in object container!" );
3392 if ( pImp
->m_xDocStorage
!= xStorage
)
3393 DoSaveCompleted( new SfxMedium( xStorage
, GetMedium()->GetBaseURL() ) );
3395 if ( IsEnableSetModified() )
3396 SetModified( true ); // ???
3402 bool SfxObjectShell::CopyStoragesOfUnknownMediaType( const uno::Reference
< embed::XStorage
>& xSource
,
3403 const uno::Reference
< embed::XStorage
>& xTarget
)
3405 // This method does not commit the target storage and should not do it
3406 bool bResult
= true;
3410 uno::Sequence
< OUString
> aSubElements
= xSource
->getElementNames();
3411 for ( sal_Int32 nInd
= 0; nInd
< aSubElements
.getLength(); nInd
++ )
3413 if ( aSubElements
[nInd
] == "Configurations" )
3415 // The workaround for compatibility with SO7, "Configurations" substorage must be preserved
3416 if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3418 OSL_ENSURE( !xTarget
->hasByName( aSubElements
[nInd
] ),
3419 "The target storage is an output storage, the element should not exist in the target!\n" );
3421 xSource
->copyElementTo( aSubElements
[nInd
], xTarget
, aSubElements
[nInd
] );
3424 else if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3426 OUString aMediaType
;
3427 OUString
aMediaTypePropName( "MediaType" );
3428 bool bGotMediaType
= false;
3432 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xSource
, uno::UNO_QUERY_THROW
);
3434 ( xOptStorage
->getElementPropertyValue( aSubElements
[nInd
], aMediaTypePropName
) >>= aMediaType
);
3436 catch( uno::Exception
& )
3439 if ( !bGotMediaType
)
3441 uno::Reference
< embed::XStorage
> xSubStorage
;
3443 xSubStorage
= xSource
->openStorageElement( aSubElements
[nInd
], embed::ElementModes::READ
);
3444 } catch( uno::Exception
& )
3447 if ( !xSubStorage
.is() )
3449 // TODO/LATER: as optimization in future a substorage of target storage could be used
3450 // instead of the temporary storage; this substorage should be removed later
3451 // if the MimeType is wrong
3452 xSubStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3453 xSource
->copyStorageElementLastCommitTo( aSubElements
[nInd
], xSubStorage
);
3456 uno::Reference
< beans::XPropertySet
> xProps( xSubStorage
, uno::UNO_QUERY_THROW
);
3457 bGotMediaType
= ( xProps
->getPropertyValue( aMediaTypePropName
) >>= aMediaType
);
3460 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3461 // probably it should be placed in the MimeType-ClassID table or in standalone table
3462 if ( !aMediaType
.isEmpty()
3463 && aMediaType
!= "application/vnd.sun.star.oleobject" )
3465 ::com::sun::star::datatransfer::DataFlavor aDataFlavor
;
3466 aDataFlavor
.MimeType
= aMediaType
;
3467 SotClipboardFormatId nFormat
= SotExchange::GetFormat( aDataFlavor
);
3471 case SotClipboardFormatId::STARWRITER_60
:
3472 case SotClipboardFormatId::STARWRITERWEB_60
:
3473 case SotClipboardFormatId::STARWRITERGLOB_60
:
3474 case SotClipboardFormatId::STARDRAW_60
:
3475 case SotClipboardFormatId::STARIMPRESS_60
:
3476 case SotClipboardFormatId::STARCALC_60
:
3477 case SotClipboardFormatId::STARCHART_60
:
3478 case SotClipboardFormatId::STARMATH_60
:
3479 case SotClipboardFormatId::STARWRITER_8
:
3480 case SotClipboardFormatId::STARWRITERWEB_8
:
3481 case SotClipboardFormatId::STARWRITERGLOB_8
:
3482 case SotClipboardFormatId::STARDRAW_8
:
3483 case SotClipboardFormatId::STARIMPRESS_8
:
3484 case SotClipboardFormatId::STARCALC_8
:
3485 case SotClipboardFormatId::STARCHART_8
:
3486 case SotClipboardFormatId::STARMATH_8
:
3491 OSL_ENSURE( aSubElements
[nInd
] == "Configurations2" || !xTarget
->hasByName( aSubElements
[nInd
] ),
3492 "The target storage is an output storage, the element should not exist in the target!\n" );
3494 if ( !xTarget
->hasByName( aSubElements
[nInd
] ) )
3496 xSource
->copyElementTo( aSubElements
[nInd
], xTarget
, aSubElements
[nInd
] );
3504 catch( uno::Exception
& )
3507 // TODO/LATER: a specific error could be provided
3513 bool SfxObjectShell::GenerateAndStoreThumbnail(bool bEncrypted
, bool bIsTemplate
, const uno::Reference
<embed::XStorage
>& xStorage
)
3515 //optimize thumbnail generate and store procedure to improve odt saving performance, i120030
3516 bIsInGenerateThumbnail
= true;
3518 bool bResult
= false;
3522 uno::Reference
<embed::XStorage
> xThumbnailStorage
= xStorage
->openStorageElement(OUString("Thumbnails"), embed::ElementModes::READWRITE
);
3524 if (xThumbnailStorage
.is())
3526 uno::Reference
<io::XStream
> xStream
= xThumbnailStorage
->openStreamElement(OUString("thumbnail.png"), embed::ElementModes::READWRITE
);
3528 if (xStream
.is() && WriteThumbnail(bEncrypted
, bIsTemplate
, xStream
))
3530 uno::Reference
<embed::XTransactedObject
> xTransactedObject(xThumbnailStorage
, uno::UNO_QUERY_THROW
);
3531 xTransactedObject
->commit();
3536 catch( uno::Exception
& )
3540 //optimize thumbnail generate and store procedure to improve odt saving performance, i120030
3541 bIsInGenerateThumbnail
= false;
3546 bool SfxObjectShell::WriteThumbnail(bool bEncrypted
, bool bIsTemplate
, const uno::Reference
<io::XStream
>& xStream
)
3548 bool bResult
= false;
3555 uno::Reference
<io::XTruncate
> xTruncate(xStream
->getOutputStream(), uno::UNO_QUERY_THROW
);
3556 xTruncate
->truncate();
3558 uno::Reference
<beans::XPropertySet
> xSet(xStream
, uno::UNO_QUERY
);
3560 xSet
->setPropertyValue("MediaType", uno::makeAny(OUString("image/png")));
3563 OUString sFactoryName
= OUString::createFromAscii(GetFactory().GetShortName());
3564 sal_uInt16 nResID
= GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl(sFactoryName
, bIsTemplate
);
3566 bResult
= GraphicHelper::getThumbnailReplacement_Impl(nResID
, xStream
);
3570 std::shared_ptr
<GDIMetaFile
> xMetaFile
= GetPreviewMetaFile(false);
3573 bResult
= GraphicHelper::getThumbnailFormatFromGDI_Impl(xMetaFile
.get(), xStream
);
3577 catch(uno::Exception
&)
3583 void SfxObjectShell::UpdateLinks()
3587 bool SfxObjectShell::LoadExternal( SfxMedium
& )
3589 // Not implemented. It's an error if the code path ever comes here.
3594 bool SfxObjectShell::InsertGeneratedStream(SfxMedium
&,
3595 uno::Reference
<text::XTextRange
> const&)
3597 // Not implemented. It's an error if the code path ever comes here.
3602 void SfxObjectShell::CheckConfigOptions()
3604 // not handled. Each app's shell needs to overwrite this method to add handler.
3605 SetConfigOptionsChecked(true);
3608 bool SfxObjectShell::IsConfigOptionsChecked() const
3610 return pImp
->m_bConfigOptionsChecked
;
3613 void SfxObjectShell::SetConfigOptionsChecked( bool bChecked
)
3615 pImp
->m_bConfigOptionsChecked
= bChecked
;
3618 bool SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference
< task::XInteractionHandler
>& xHandler
)
3620 #if !HAVE_FEATURE_SCRIPTING
3626 if ( !pImp
->aBasicManager
.isValid() )
3628 uno::Sequence
< OUString
> sModules
;
3629 if ( xHandler
.is() )
3631 if( pImp
->aBasicManager
.LegacyPsswdBinaryLimitExceeded( sModules
) )
3633 ModuleSizeExceeded
* pReq
= new ModuleSizeExceeded( sModules
);
3634 uno::Reference
< task::XInteractionRequest
> xReq( pReq
);
3635 xHandler
->handle( xReq
);
3636 return pReq
->isApprove();
3640 // No interaction handler, default is to continue to save
3644 uno::Reference
< task::XInteractionHandler
> SfxObjectShell::getInteractionHandler() const
3646 uno::Reference
< task::XInteractionHandler
> xRet
;
3648 xRet
= GetMedium()->GetInteractionHandler();
3652 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */