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/GlobalEventBroadcaster.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/FilterOptionsRequest.hpp>
38 #include <com/sun/star/document/XInteractionFilterOptions.hpp>
39 #include <com/sun/star/packages/zip/ZipIOException.hpp>
40 #include <com/sun/star/task/XInteractionHandler.hpp>
41 #include <com/sun/star/task/XInteractionAskLater.hpp>
42 #include <com/sun/star/task/FutureDocumentVersionProductUpdateRequest.hpp>
43 #include <com/sun/star/task/InteractionClassification.hpp>
44 #include <com/sun/star/lang/XInitialization.hpp>
45 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
46 #include <com/sun/star/document/MacroExecMode.hpp>
47 #include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp>
48 #include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp>
49 #include <com/sun/star/ui/dialogs/XFilePicker.hpp>
50 #include <com/sun/star/beans/XPropertySetInfo.hpp>
51 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
52 #include <com/sun/star/beans/XPropertyAccess.hpp>
53 #include <com/sun/star/beans/PropertyValue.hpp>
54 #include <com/sun/star/beans/XPropertySet.hpp>
55 #include <com/sun/star/container/XNameAccess.hpp>
56 #include <com/sun/star/container/XSet.hpp>
57 #include <com/sun/star/embed/ElementModes.hpp>
58 #include <com/sun/star/embed/EmbedStates.hpp>
59 #include <com/sun/star/embed/Aspects.hpp>
60 #include <com/sun/star/embed/XTransactedObject.hpp>
61 #include <com/sun/star/embed/XEmbedPersist.hpp>
62 #include <com/sun/star/embed/XLinkageSupport.hpp>
63 #include <com/sun/star/embed/EntryInitModes.hpp>
64 #include <com/sun/star/embed/XOptimizedStorage.hpp>
65 #include <com/sun/star/embed/XEncryptionProtectedStorage.hpp>
66 #include <com/sun/star/io/XTruncate.hpp>
67 #include <com/sun/star/util/XModifiable.hpp>
68 #include <com/sun/star/security/DocumentDigitalSignatures.hpp>
69 #include <com/sun/star/xml/crypto/CipherID.hpp>
70 #include <com/sun/star/xml/crypto/DigestID.hpp>
72 #include <com/sun/star/document/XDocumentProperties.hpp>
73 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
74 #include <comphelper/processfactory.hxx>
75 #include <comphelper/configurationhelper.hxx>
76 #include <comphelper/interaction.hxx>
77 #include <svtools/sfxecode.hxx>
78 #include <unotools/securityoptions.hxx>
79 #include <cppuhelper/weak.hxx>
80 #include <unotools/streamwrap.hxx>
82 #include <unotools/saveopt.hxx>
83 #include <unotools/useroptions.hxx>
84 #include <unotools/pathoptions.hxx>
85 #include <tools/urlobj.hxx>
86 #include <tools/diagnose_ex.h>
87 #include <unotools/localfilehelper.hxx>
88 #include <unotools/ucbhelper.hxx>
89 #include <unotools/tempfile.hxx>
90 #include <unotools/docinfohelper.hxx>
91 #include <ucbhelper/content.hxx>
92 #include <sot/storinfo.hxx>
93 #include <sot/exchange.hxx>
94 #include <sot/formats.hxx>
95 #include <comphelper/storagehelper.hxx>
96 #include <comphelper/seqstream.hxx>
97 #include <comphelper/documentconstants.hxx>
98 #include <comphelper/string.hxx>
99 #include <vcl/bitmapex.hxx>
100 #include <svtools/embedhlp.hxx>
101 #include <rtl/logfile.hxx>
102 #include <basic/modsizeexceeded.hxx>
103 #include <osl/file.hxx>
105 #include <sfx2/signaturestate.hxx>
106 #include <sfx2/app.hxx>
107 #include <sfx2/objsh.hxx>
108 #include <sfx2/childwin.hxx>
109 #include <sfx2/request.hxx>
110 #include "sfx2/sfxresid.hxx"
111 #include <sfx2/docfile.hxx>
112 #include "fltfnc.hxx"
113 #include <sfx2/docfilt.hxx>
114 #include <sfx2/docfac.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"
130 #include "../appl/app.hrc"
132 extern sal_uInt32
CheckPasswd_Impl( SfxObjectShell
*, SfxItemPool
&, SfxMedium
* );
134 using namespace ::com::sun::star
;
135 using namespace ::com::sun::star::container
;
136 using namespace ::com::sun::star::lang
;
137 using namespace ::com::sun::star::ui::dialogs
;
138 using namespace ::com::sun::star::uno
;
139 using namespace ::com::sun::star::beans
;
140 using namespace ::com::sun::star::ucb
;
141 using namespace ::com::sun::star::task
;
142 using namespace ::com::sun::star::document
;
143 using namespace ::rtl
;
144 using namespace ::cppu
;
146 //=========================================================================
147 void impl_addToModelCollection(const css::uno::Reference
< css::frame::XModel
>& xModel
)
152 css::uno::Reference
< css::uno::XComponentContext
> xContext
= ::comphelper::getProcessComponentContext();
153 css::uno::Reference
< css::frame::XGlobalEventBroadcaster
> xModelCollection
=
154 css::frame::GlobalEventBroadcaster::create(xContext
);
157 xModelCollection
->insert(css::uno::makeAny(xModel
));
159 catch ( uno::Exception
& )
161 OSL_FAIL( "The document seems to be in the collection already!\n" );
165 //=========================================================================
167 sal_Bool
SfxObjectShell::Save()
169 return SaveChildren();
172 //--------------------------------------------------------------------------
174 sal_Bool
SfxObjectShell::SaveAs( SfxMedium
& rMedium
)
176 return SaveAsChildren( rMedium
);
179 //-------------------------------------------------------------------------
181 sal_Bool
SfxObjectShell::QuerySlotExecutable( sal_uInt16
/*nSlotId*/ )
186 //-------------------------------------------------------------------------
188 bool GetEncryptionData_Impl( const SfxItemSet
* pSet
, uno::Sequence
< beans::NamedValue
>& o_rEncryptionData
)
190 bool bResult
= false;
193 SFX_ITEMSET_ARG( pSet
, pEncryptionDataItem
, SfxUnoAnyItem
, SID_ENCRYPTIONDATA
, sal_False
);
194 if ( pEncryptionDataItem
)
196 pEncryptionDataItem
->GetValue() >>= o_rEncryptionData
;
201 SFX_ITEMSET_ARG( pSet
, pPasswordItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
204 OUString aPassword
= pPasswordItem
->GetValue();
205 o_rEncryptionData
= ::comphelper::OStorageHelper::CreatePackageEncryptionData( aPassword
);
214 //-------------------------------------------------------------------------
215 sal_Bool
SfxObjectShell::PutURLContentsToVersionStream_Impl(
217 const uno::Reference
< embed::XStorage
>& xDocStorage
,
218 OUString aStreamName
)
220 sal_Bool bResult
= sal_False
;
223 uno::Reference
< embed::XStorage
> xVersion
= xDocStorage
->openStorageElement(
224 OUString("Versions"),
225 embed::ElementModes::READWRITE
);
227 DBG_ASSERT( xVersion
.is(),
228 "The method must throw an exception if the storage can not be opened!\n" );
229 if ( !xVersion
.is() )
230 throw uno::RuntimeException();
232 uno::Reference
< io::XStream
> xVerStream
= xVersion
->openStreamElement(
234 embed::ElementModes::READWRITE
);
235 DBG_ASSERT( xVerStream
.is(), "The method must throw an exception if the storage can not be opened!\n" );
236 if ( !xVerStream
.is() )
237 throw uno::RuntimeException();
239 uno::Reference
< io::XOutputStream
> xOutStream
= xVerStream
->getOutputStream();
240 uno::Reference
< io::XTruncate
> xTrunc( xOutStream
, uno::UNO_QUERY
);
242 DBG_ASSERT( xTrunc
.is(), "The output stream must exist and implement XTruncate interface!\n" );
244 throw RuntimeException();
246 uno::Reference
< io::XInputStream
> xTmpInStream
=
247 ::comphelper::OStorageHelper::GetInputStreamFromURL(
248 aURL
, comphelper::getProcessComponentContext() );
249 assert( xTmpInStream
.is() );
252 ::comphelper::OStorageHelper::CopyInputToOutput( xTmpInStream
, xOutStream
);
253 xOutStream
->closeOutput();
255 uno::Reference
< embed::XTransactedObject
> xTransact( xVersion
, uno::UNO_QUERY
);
256 DBG_ASSERT( xTransact
.is(), "The storage must implement XTransacted interface!\n" );
257 if ( xTransact
.is() )
262 catch( uno::Exception
& )
264 // TODO/LATER: handle the error depending on exception
265 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
271 //-------------------------------------------------------------------------
272 OUString
SfxObjectShell::CreateTempCopyOfStorage_Impl( const uno::Reference
< embed::XStorage
>& xStorage
)
274 OUString aTempURL
= ::utl::TempFile().GetURL();
276 DBG_ASSERT( !aTempURL
.isEmpty(), "Can't create a temporary file!\n" );
277 if ( !aTempURL
.isEmpty() )
281 uno::Reference
< embed::XStorage
> xTempStorage
=
282 ::comphelper::OStorageHelper::GetStorageFromURL( aTempURL
, embed::ElementModes::READWRITE
);
284 // the password will be transferred from the xStorage to xTempStorage by storage implemetation
285 xStorage
->copyToStorage( xTempStorage
);
287 // the temporary storage was commited by the previous method and it will die by refcount
289 catch ( uno::Exception
& )
291 OSL_FAIL( "Creation of a storage copy is failed!" );
292 ::utl::UCBContentHelper::Kill( aTempURL
);
294 aTempURL
= OUString();
296 // TODO/LATER: may need error code setting based on exception
297 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
304 //-------------------------------------------------------------------------
305 SvGlobalName
SfxObjectShell::GetClassName() const
307 return GetFactory().GetClassId();
313 * Chart2 does not have an Object shell, so handle this here for now
314 * If we ever implement a full scale object shell in chart2 move it there
316 sal_uInt32
GetChartVersion( sal_Int32 nVersion
, bool bTemplate
)
318 if( nVersion
== SOFFICE_FILEFORMAT_60
)
320 return SOT_FORMATSTR_ID_STARCHART_60
;
322 else if( nVersion
== SOFFICE_FILEFORMAT_8
)
326 SAL_WARN("sfx2", "no chart template support yet");
327 return SOT_FORMATSTR_ID_STARCHART_8
;
330 return SOT_FORMATSTR_ID_STARCHART_8
;
333 SAL_WARN("sfx2", "unsupported version");
339 //-------------------------------------------------------------------------
340 void SfxObjectShell::SetupStorage( const uno::Reference
< embed::XStorage
>& xStorage
,
341 sal_Int32 nVersion
, sal_Bool bTemplate
, bool bChart
) const
343 uno::Reference
< beans::XPropertySet
> xProps( xStorage
, uno::UNO_QUERY
);
348 OUString aFullTypeName
, aShortTypeName
, aAppName
;
349 sal_uInt32 nClipFormat
=0;
352 FillClass( &aName
, &nClipFormat
, &aAppName
, &aFullTypeName
, &aShortTypeName
, nVersion
, bTemplate
);
354 nClipFormat
= GetChartVersion(nVersion
, bTemplate
);
358 // basic doesn't have a ClipFormat
359 // without MediaType the storage is not really usable, but currently the BasicIDE still
360 // is an SfxObjectShell and so we can't take this as an error
361 datatransfer::DataFlavor aDataFlavor
;
362 SotExchange::GetFormatDataFlavor( nClipFormat
, aDataFlavor
);
363 if ( !aDataFlavor
.MimeType
.isEmpty() )
367 xProps
->setPropertyValue( OUString("MediaType"), uno::makeAny( aDataFlavor
.MimeType
) );
369 catch( uno::Exception
& )
371 const_cast<SfxObjectShell
*>( this )->SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
374 SvtSaveOptions aSaveOpt
;
375 SvtSaveOptions::ODFDefaultVersion nDefVersion
= aSaveOpt
.GetODFDefaultVersion();
377 uno::Sequence
< beans::NamedValue
> aEncryptionAlgs( 3 );
378 aEncryptionAlgs
[0].Name
= OUString( "StartKeyGenerationAlgorithm" );
379 aEncryptionAlgs
[1].Name
= OUString( "EncryptionAlgorithm" );
380 aEncryptionAlgs
[2].Name
= OUString( "ChecksumAlgorithm" );
381 // the default values, that should be used for ODF1.1 and older formats
382 aEncryptionAlgs
[0].Value
<<= xml::crypto::DigestID::SHA1
;
383 aEncryptionAlgs
[1].Value
<<= xml::crypto::CipherID::BLOWFISH_CFB_8
;
384 aEncryptionAlgs
[2].Value
<<= xml::crypto::DigestID::SHA1_1K
;
386 if ( nVersion
>= SOFFICE_FILEFORMAT_8
)
390 // older versions can not have this property set, it exists only starting from ODF1.2
391 xProps
->setPropertyValue( OUString("Version" ), uno::makeAny( ODFVER_012_TEXT
) );
393 catch( uno::Exception
& )
397 if ( !aSaveOpt
.IsUseSHA1InODF12() && nDefVersion
!= SvtSaveOptions::ODFVER_012_EXT_COMPAT
)
399 aEncryptionAlgs
[0].Value
<<= xml::crypto::DigestID::SHA256
;
400 aEncryptionAlgs
[2].Value
<<= xml::crypto::DigestID::SHA256_1K
;
402 if ( !aSaveOpt
.IsUseBlowfishInODF12() && nDefVersion
!= SvtSaveOptions::ODFVER_012_EXT_COMPAT
)
403 aEncryptionAlgs
[1].Value
<<= xml::crypto::CipherID::AES_CBC_W3C_PADDING
;
408 // set the encryption algorithms accordingly;
409 // the setting does not trigger encryption,
410 // it just provides the format for the case that contents should be encrypted
411 uno::Reference
< embed::XEncryptionProtectedStorage
> xEncr( xStorage
, uno::UNO_QUERY_THROW
);
412 xEncr
->setEncryptionAlgorithms( aEncryptionAlgs
);
414 catch( uno::Exception
& )
416 const_cast<SfxObjectShell
*>( this )->SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
424 //-------------------------------------------------------------------------
425 void SfxObjectShell::PrepareSecondTryLoad_Impl()
427 // only for internal use
428 pImp
->m_xDocStorage
= uno::Reference
< embed::XStorage
>();
429 pImp
->m_bIsInit
= sal_False
;
433 //-------------------------------------------------------------------------
434 sal_Bool
SfxObjectShell::GeneralInit_Impl( const uno::Reference
< embed::XStorage
>& xStorage
,
435 sal_Bool bTypeMustBeSetAlready
)
437 if ( pImp
->m_bIsInit
)
440 pImp
->m_bIsInit
= sal_True
;
443 // no notification is required the storage is set the first time
444 pImp
->m_xDocStorage
= xStorage
;
447 uno::Reference
< beans::XPropertySet
> xPropSet( xStorage
, uno::UNO_QUERY_THROW
);
448 Any a
= xPropSet
->getPropertyValue( OUString("MediaType" ) );
450 if ( !(a
>>=aMediaType
) || aMediaType
.isEmpty() )
452 if ( bTypeMustBeSetAlready
)
454 SetError( ERRCODE_IO_BROKENPACKAGE
, OUString( OSL_LOG_PREFIX
) );
458 SetupStorage( xStorage
, SOFFICE_FILEFORMAT_CURRENT
, sal_False
, false );
461 catch ( uno::Exception
& )
463 OSL_FAIL( "Can't check storage's mediatype!\n" );
467 pImp
->m_bCreateTempStor
= sal_True
;
472 //-------------------------------------------------------------------------
473 sal_Bool
SfxObjectShell::InitNew( const uno::Reference
< embed::XStorage
>& xStorage
)
475 return GeneralInit_Impl( xStorage
, sal_False
);
478 //-------------------------------------------------------------------------
479 sal_Bool
SfxObjectShell::Load( SfxMedium
& rMedium
)
481 return GeneralInit_Impl( rMedium
.GetStorage(), sal_True
);
484 bool SfxObjectShell::DoInitUnitTest()
486 pMedium
= new SfxMedium
;
487 return true; // always a success!
490 sal_Bool
SfxObjectShell::DoInitNew( SfxMedium
* pMed
)
493 This from SvPersist inherited virtual method is called to initialize
494 the SfxObjectShell instance from a storage (PStore! = 0) or (PStore == 0)
496 Like with all Do...-methods there is a from a control, the actual
497 implementation is done by the virtual method in which also the
498 InitNew(SvStorate *) from the SfxObjectShell-Subclass is implemented.
500 For pStore == 0 the SfxObjectShell-instance is connected to an empty
501 SfxMedium, otherwise a SfxMedium, which refers to the SvStorage
502 passed as a parameter.
504 The object is only initialized correctly after InitNew() or Load().
507 sal_True The object has been initialized.
508 sal_False The object could not be initialized
512 ModifyBlocker_Impl
aBlock( this );
517 pMedium
= new SfxMedium
;
520 pMedium
->CanDisposeStorage_Impl( sal_True
);
522 if ( InitNew( pMed
? pMed
->GetStorage() : uno::Reference
< embed::XStorage
>() ) )
524 // empty documents always get their macros from the user, so there is no reason to restrict access
525 pImp
->aMacroMode
.allowMacroExecution();
526 if ( SFX_CREATE_MODE_EMBEDDED
== eCreateMode
)
527 SetTitle(SfxResId(STR_NONAME
).toString());
529 uno::Reference
< frame::XModel
> xModel ( GetModel(), uno::UNO_QUERY
);
532 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
533 uno::Sequence
< beans::PropertyValue
> aArgs
;
534 TransformItems( SID_OPENDOC
, *pSet
, aArgs
);
535 sal_Int32 nLength
= aArgs
.getLength();
536 aArgs
.realloc( nLength
+ 1 );
537 aArgs
[nLength
].Name
= "Title";
538 aArgs
[nLength
].Value
<<= OUString( GetTitle( SFX_TITLE_DETECT
) );
539 xModel
->attachResource( OUString(), aArgs
);
540 impl_addToModelCollection(xModel
);
543 SetInitialized_Impl( true );
550 //-------------------------------------------------------------------------
552 sal_Bool
SfxObjectShell::ImportFromGeneratedStream_Impl(
553 const uno::Reference
< io::XStream
>& xStream
,
554 const uno::Sequence
< beans::PropertyValue
>& aMediaDescr
)
559 if ( pMedium
&& pMedium
->HasStorage_Impl() )
560 pMedium
->CloseStorage();
562 sal_Bool bResult
= sal_False
;
566 uno::Reference
< embed::XStorage
> xStorage
=
567 ::comphelper::OStorageHelper::GetStorageFromStream( xStream
, embed::ElementModes::READWRITE
);
569 if ( !xStorage
.is() )
570 throw uno::RuntimeException();
573 pMedium
= new SfxMedium( xStorage
, String() );
575 pMedium
->SetStorage_Impl( xStorage
);
577 SfxAllItemSet
aSet( SFX_APP()->GetPool() );
578 TransformParameters( SID_OPENDOC
, aMediaDescr
, aSet
);
579 pMedium
->GetItemSet()->Put( aSet
);
580 pMedium
->CanDisposeStorage_Impl( sal_False
);
582 // allow the subfilter to reinit the model
583 if ( pImp
->m_bIsInit
)
584 pImp
->m_bIsInit
= sal_False
;
586 if ( LoadOwnFormat( *pMedium
) )
589 if ( !IsReadOnly() && IsLoadReadonly() )
593 OSL_ENSURE( pImp
->m_xDocStorage
== xStorage
, "Wrong storage is used!\n" );
596 // now the medium can be disconnected from the storage
597 // the medium is not allowed to dispose the storage so CloseStorage() can be used
598 pMedium
->CloseStorage();
600 catch( uno::Exception
& )
607 //-------------------------------------------------------------------------
609 sal_Bool
SfxObjectShell::DoLoad( SfxMedium
*pMed
)
611 ModifyBlocker_Impl
aBlock( this );
614 pMedium
->CanDisposeStorage_Impl( sal_True
);
616 sal_Bool bOk
= sal_False
;
617 const SfxFilter
* pFilter
= pMed
->GetFilter();
618 SfxItemSet
* pSet
= pMedium
->GetItemSet();
619 if( !pImp
->nEventId
)
622 pSet
, pTemplateItem
, SfxBoolItem
,
623 SID_TEMPLATE
, sal_False
);
624 SetActivateEvent_Impl(
625 ( pTemplateItem
&& pTemplateItem
->GetValue() )
626 ? SFX_EVENT_CREATEDOC
: SFX_EVENT_OPENDOC
);
630 SFX_ITEMSET_ARG( pSet
, pBaseItem
, SfxStringItem
,
631 SID_BASEURL
, sal_False
);
633 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
635 aBaseURL
= pBaseItem
->GetValue();
640 OUString
aName( pMed
->GetPhysicalName() );
641 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName
, aBaseURL
);
644 aBaseURL
= pMed
->GetBaseURL();
646 pMed
->GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL
, aBaseURL
) );
648 pImp
->nLoadedFlags
= 0;
649 pImp
->bModelInitialized
= sal_False
;
651 //TODO/LATER: make a clear strategy how to handle "UsesStorage" etc.
652 sal_Bool bOwnStorageFormat
= IsOwnStorageFormat_Impl( *pMedium
);
653 sal_Bool bHasStorage
= IsPackageStorageFormat_Impl( *pMedium
);
654 if ( pMedium
->GetFilter() )
656 sal_uInt32 nError
= HandleFilter( pMedium
, this );
657 if ( nError
!= ERRCODE_NONE
)
658 SetError( nError
, OUString( OSL_LOG_PREFIX
) );
660 if (pMedium
->GetFilter()->GetFilterFlags() & SFX_FILTER_STARTPRESENTATION
)
661 pSet
->Put( SfxBoolItem( SID_DOC_STARTPRESENTATION
, sal_True
) );
664 EnableSetModified( sal_False
);
666 pMedium
->LockOrigFileOnDemand( sal_True
, sal_False
);
667 if ( GetError() == ERRCODE_NONE
&& bOwnStorageFormat
&& ( !pFilter
|| !( pFilter
->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) ) )
669 uno::Reference
< embed::XStorage
> xStorage
;
670 if ( pMedium
->GetError() == ERRCODE_NONE
)
671 xStorage
= pMedium
->GetStorage();
673 if( xStorage
.is() && pMedium
->GetLastStorageCreationState() == ERRCODE_NONE
)
675 DBG_ASSERT( pFilter
, "No filter for storage found!" );
679 sal_Bool bWarnMediaTypeFallback
= sal_False
;
680 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pRepairPackageItem
, SfxBoolItem
, SID_REPAIRPACKAGE
, sal_False
);
682 // treat the package as broken if the mediatype was retrieved as a fallback
683 uno::Reference
< beans::XPropertySet
> xStorProps( xStorage
, uno::UNO_QUERY_THROW
);
684 xStorProps
->getPropertyValue( OUString( "MediaTypeFallbackUsed" ) )
685 >>= bWarnMediaTypeFallback
;
687 if ( pRepairPackageItem
&& pRepairPackageItem
->GetValue() )
689 // the macros in repaired documents should be disabled
690 pMedium
->GetItemSet()->Put( SfxUInt16Item( SID_MACROEXECMODE
, document::MacroExecMode::NEVER_EXECUTE
) );
692 // the mediatype was retrieved by using fallback solution but this is a repairing mode
693 // so it is acceptable to open the document if there is no contents that required manifest.xml
694 bWarnMediaTypeFallback
= sal_False
;
697 if ( bWarnMediaTypeFallback
|| !xStorage
->getElementNames().getLength() )
698 SetError( ERRCODE_IO_BROKENPACKAGE
, OUString( OSL_LOG_PREFIX
) );
700 catch( uno::Exception
& )
702 // TODO/LATER: may need error code setting based on exception
703 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
709 pImp
->nLoadedFlags
= 0;
710 pImp
->bModelInitialized
= sal_False
;
711 bOk
= xStorage
.is() && LoadOwnFormat( *pMed
);
714 // the document loaded from template has no name
715 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pTemplateItem
, SfxBoolItem
, SID_TEMPLATE
, sal_False
);
716 if ( !pTemplateItem
|| !pTemplateItem
->GetValue() )
720 SetError( ERRCODE_ABORT
, OUString( OSL_LOG_PREFIX
) );
724 SetError( pMed
->GetLastStorageCreationState(), OUString( OSL_LOG_PREFIX
) );
726 else if ( GetError() == ERRCODE_NONE
&& InitNew(0) )
728 // Name vor ConvertFrom setzen, damit GetSbxObject() schon funktioniert
730 SetName( SfxResId(STR_NONAME
).toString() );
733 pMedium
->GetInStream();
735 pMedium
->GetStorage();
737 if ( GetError() == ERRCODE_NONE
)
739 pImp
->nLoadedFlags
= 0;
740 pImp
->bModelInitialized
= sal_False
;
741 if ( pMedium
->GetFilter() && ( pMedium
->GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) )
743 uno::Reference
< beans::XPropertySet
> xSet( GetModel(), uno::UNO_QUERY
);
744 OUString
sLockUpdates("LockUpdates");
745 bool bSetProperty
= true;
748 xSet
->setPropertyValue( sLockUpdates
, makeAny( (sal_Bool
) sal_True
) );
750 catch(const beans::UnknownPropertyException
& )
752 bSetProperty
= false;
754 bOk
= ImportFrom( *pMedium
, false );
759 xSet
->setPropertyValue( sLockUpdates
, makeAny( (sal_Bool
) sal_False
) );
761 catch(const beans::UnknownPropertyException
& )
765 FinishedLoading( SFX_LOADED_ALL
);
769 bOk
= ConvertFrom(*pMedium
);
777 if ( IsReadOnlyMedium() || IsLoadReadonly() )
782 ::ucbhelper::Content
aContent( pMedium
->GetName(), com::sun::star::uno::Reference
< XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
783 com::sun::star::uno::Reference
< XPropertySetInfo
> xProps
= aContent
.getProperties();
786 OUString
aAuthor( "Author" );
787 OUString
aKeywords( "Keywords" );
788 OUString
aSubject( "Subject" );
791 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
792 GetModel(), uno::UNO_QUERY_THROW
);
793 uno::Reference
<document::XDocumentProperties
> xDocProps
794 = xDPS
->getDocumentProperties();
795 if ( xProps
->hasPropertyByName( aAuthor
) )
797 aAny
= aContent
.getPropertyValue( aAuthor
);
798 if ( ( aAny
>>= aValue
) )
799 xDocProps
->setAuthor(aValue
);
801 if ( xProps
->hasPropertyByName( aKeywords
) )
803 aAny
= aContent
.getPropertyValue( aKeywords
);
804 if ( ( aAny
>>= aValue
) )
805 xDocProps
->setKeywords(
806 ::comphelper::string::convertCommaSeparated(aValue
));
809 if ( xProps
->hasPropertyByName( aSubject
) )
811 aAny
= aContent
.getPropertyValue( aSubject
);
812 if ( ( aAny
>>= aValue
) ) {
813 xDocProps
->setSubject(aValue
);
822 // If not loaded asynchronously call FinishedLoading
823 if ( !( pImp
->nLoadedFlags
& SFX_LOADED_MAINDOCUMENT
) &&
824 ( !pMedium
->GetFilter() || pMedium
->GetFilter()->UsesStorage() )
826 FinishedLoading( SFX_LOADED_MAINDOCUMENT
);
828 if( IsOwnStorageFormat_Impl(*pMed
) && pMed
->GetFilter() )
831 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED
) );
833 if ( SFX_CREATE_MODE_EMBEDDED
!= eCreateMode
)
835 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pAsTempItem
, SfxBoolItem
, SID_TEMPLATE
, sal_False
);
836 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pPreviewItem
, SfxBoolItem
, SID_PREVIEW
, sal_False
);
837 SFX_ITEMSET_ARG( pMedium
->GetItemSet(), pHiddenItem
, SfxBoolItem
, SID_HIDDEN
, sal_False
);
838 if( bOk
&& !pMedium
->GetOrigURL().isEmpty()
839 && !( pAsTempItem
&& pAsTempItem
->GetValue() )
840 && !( pPreviewItem
&& pPreviewItem
->GetValue() )
841 && !( pHiddenItem
&& pHiddenItem
->GetValue() ) )
843 AddToRecentlyUsedList();
847 const SfxBoolItem
* pDdeReconnectItem
= static_cast<const SfxBoolItem
*>(
848 SfxRequest::GetItem(pMedium
->GetItemSet(), SID_DDE_RECONNECT_ONLOAD
, false, TYPE(SfxBoolItem
)));
850 bool bReconnectDde
= true; // by default, we try to auto-connect DDE connections.
851 if (pDdeReconnectItem
)
852 bReconnectDde
= pDdeReconnectItem
->GetValue();
855 ReconnectDdeLinks(*this);
861 bool SfxObjectShell::DoLoadExternal( SfxMedium
*pMed
)
864 return LoadExternal(*pMedium
);
867 sal_uInt32
SfxObjectShell::HandleFilter( SfxMedium
* pMedium
, SfxObjectShell
* pDoc
)
869 sal_uInt32 nError
= ERRCODE_NONE
;
870 SfxItemSet
* pSet
= pMedium
->GetItemSet();
871 SFX_ITEMSET_ARG( pSet
, pOptions
, SfxStringItem
, SID_FILE_FILTEROPTIONS
, sal_False
);
872 SFX_ITEMSET_ARG( pSet
, pData
, SfxUnoAnyItem
, SID_FILTER_DATA
, sal_False
);
873 if ( !pData
&& !pOptions
)
875 com::sun::star::uno::Reference
< XMultiServiceFactory
> xServiceManager
= ::comphelper::getProcessServiceFactory();
876 com::sun::star::uno::Reference
< XNameAccess
> xFilterCFG
;
877 if( xServiceManager
.is() )
879 xFilterCFG
= com::sun::star::uno::Reference
< XNameAccess
>(
880 xServiceManager
->createInstance( OUString("com.sun.star.document.FilterFactory") ),
884 if( xFilterCFG
.is() )
886 sal_Bool bAbort
= sal_False
;
888 const SfxFilter
* pFilter
= pMedium
->GetFilter();
889 Sequence
< PropertyValue
> aProps
;
890 Any aAny
= xFilterCFG
->getByName( pFilter
->GetName() );
891 if ( aAny
>>= aProps
)
893 sal_Int32 nPropertyCount
= aProps
.getLength();
894 for( sal_Int32 nProperty
=0; nProperty
< nPropertyCount
; ++nProperty
)
895 if( aProps
[nProperty
].Name
== "UIComponent" )
897 OUString aServiceName
;
898 aProps
[nProperty
].Value
>>= aServiceName
;
899 if( !aServiceName
.isEmpty() )
901 com::sun::star::uno::Reference
< XInteractionHandler
> rHandler
= pMedium
->GetInteractionHandler();
904 // we need some properties in the media descriptor, so we have to make sure that they are in
906 aStreamAny
<<= pMedium
->GetInputStream();
907 if ( pSet
->GetItemState( SID_INPUTSTREAM
) < SFX_ITEM_SET
)
908 pSet
->Put( SfxUnoAnyItem( SID_INPUTSTREAM
, aStreamAny
) );
909 if ( pSet
->GetItemState( SID_FILE_NAME
) < SFX_ITEM_SET
)
910 pSet
->Put( SfxStringItem( SID_FILE_NAME
, pMedium
->GetName() ) );
911 if ( pSet
->GetItemState( SID_FILTER_NAME
) < SFX_ITEM_SET
)
912 pSet
->Put( SfxStringItem( SID_FILTER_NAME
, pFilter
->GetName() ) );
914 Sequence
< PropertyValue
> rProperties
;
915 TransformItems( SID_OPENDOC
, *pSet
, rProperties
, NULL
);
916 RequestFilterOptions
* pFORequest
= new RequestFilterOptions( pDoc
->GetModel(), rProperties
);
918 com::sun::star::uno::Reference
< XInteractionRequest
> rRequest( pFORequest
);
919 rHandler
->handle( rRequest
);
921 if ( !pFORequest
->isAbort() )
923 SfxAllItemSet
aNewParams( pDoc
->GetPool() );
924 TransformParameters( SID_OPENDOC
,
925 pFORequest
->getFilterOptions(),
929 SFX_ITEMSET_ARG( &aNewParams
,
932 SID_FILE_FILTEROPTIONS
,
934 if ( pFilterOptions
)
935 pSet
->Put( *pFilterOptions
);
937 SFX_ITEMSET_ARG( &aNewParams
,
943 pSet
->Put( *pFilterData
);
956 // filter options were not entered
957 nError
= ERRCODE_ABORT
;
960 catch( NoSuchElementException
& )
962 // the filter name is unknown
963 nError
= ERRCODE_IO_INVALIDPARAMETER
;
967 nError
= ERRCODE_ABORT
;
975 //-------------------------------------------------------------------------
977 sal_Bool
SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium
&rMedium
) const
979 return !rMedium
.GetFilter() || // Embedded
980 ( rMedium
.GetFilter()->IsOwnFormat() &&
981 rMedium
.GetFilter()->UsesStorage() &&
982 rMedium
.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60
);
985 //-------------------------------------------------------------------------
987 sal_Bool
SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium
&rMedium
) const
989 return !rMedium
.GetFilter() || // Embedded
990 ( rMedium
.GetFilter()->UsesStorage() &&
991 rMedium
.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60
);
994 //-------------------------------------------------------------------------
996 sal_Bool
SfxObjectShell::DoSave()
997 // DoSave is only invoked for OLE. Save your own documents in the SFX through
998 // DoSave_Impl order to allow for the creation of backups.
999 // Save in your own format again.
1001 sal_Bool bOk
= sal_False
;
1003 ModifyBlocker_Impl
aBlock( this );
1005 pImp
->bIsSaving
= sal_True
;
1007 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
1008 if ( IsPackageStorageFormat_Impl( *GetMedium() ) )
1010 if ( GetEncryptionData_Impl( GetMedium()->GetItemSet(), aEncryptionData
) )
1014 //TODO/MBA: GetOutputStorage?! Special mode, because it's "Save"?!
1015 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( GetMedium()->GetStorage(), aEncryptionData
);
1018 catch( uno::Exception
& )
1020 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1023 DBG_ASSERT( bOk
, "The root storage must allow to set common password!\n" );
1027 #ifndef DISABLE_SCRIPTING
1032 // The basic and dialogs related contents are still not able to proceed with save operation ( saveTo only )
1033 // so since the document storage is locked a workaround has to be used
1035 uno::Reference
< embed::XStorage
> xTmpStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
1036 DBG_ASSERT( xTmpStorage
.is(), "If a storage can not be created an exception must be thrown!\n" );
1037 if ( !xTmpStorage
.is() )
1038 throw uno::RuntimeException();
1040 OUString
aBasicStorageName( "Basic" );
1041 OUString
aDialogsStorageName( "Dialogs" );
1042 if ( GetMedium()->GetStorage()->hasByName( aBasicStorageName
) )
1043 GetMedium()->GetStorage()->copyElementTo( aBasicStorageName
, xTmpStorage
, aBasicStorageName
);
1044 if ( GetMedium()->GetStorage()->hasByName( aDialogsStorageName
) )
1045 GetMedium()->GetStorage()->copyElementTo( aDialogsStorageName
, xTmpStorage
, aDialogsStorageName
);
1049 // disconnect from the current storage
1050 pImp
->pBasicManager
->setStorage( xTmpStorage
);
1052 // store to the current storage
1053 pImp
->pBasicManager
->storeLibrariesToStorage( GetMedium()->GetStorage() );
1055 // connect to the current storage back
1056 pImp
->pBasicManager
->setStorage( GetMedium()->GetStorage() );
1058 catch( uno::Exception
& )
1060 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1070 bOk
= pMedium
->Commit();
1076 void Lock_Impl( SfxObjectShell
* pDoc
, sal_Bool bLock
)
1078 SfxViewFrame
*pFrame
= SfxViewFrame::GetFirst( pDoc
);
1081 pFrame
->GetDispatcher()->Lock( bLock
);
1082 pFrame
->Enable( !bLock
);
1083 pFrame
= SfxViewFrame::GetNext( *pFrame
, pDoc
);
1088 //-------------------------------------------------------------------------
1090 sal_Bool
SfxObjectShell::SaveTo_Impl
1092 SfxMedium
&rMedium
, // Medium, in which it will be stored
1093 const SfxItemSet
* pSet
1098 Writes the current contents to the medium rMedium. If the target medium is
1099 no storage, then saving to a temporary storage, or directly if the medium
1100 is transacted, if we ourselves have opened it, and if we are a server
1101 either the container a transacted storage provides or created a
1102 temporary storage by one self.
1106 RTL_LOGFILE_PRODUCT_CONTEXT( aLog
, "PERFORMANCE SfxObjectShell::SaveTo_Impl" );
1107 if( RTL_LOGFILE_HASLOGFILE() )
1110 OUStringToOString(rMedium
.GetName(), RTL_TEXTENCODING_ASCII_US
));
1111 RTL_LOGFILE_PRODUCT_CONTEXT_TRACE1(aLog
, "saving \"%s\"", aString
.getStr());
1114 AddLog( OUString( OSL_LOG_PREFIX
"Begin" ) );
1116 ModifyBlocker_Impl
aMod(this);
1118 const SfxFilter
*pFilter
= rMedium
.GetFilter();
1121 // if no filter was set, use the default filter
1122 // this should be changed in the feature, it should be an error!
1123 OSL_FAIL("No filter set!");
1124 pFilter
= GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT
| SFX_FILTER_EXPORT
);
1125 rMedium
.SetFilter(pFilter
);
1128 sal_Bool bStorageBasedSource
= IsPackageStorageFormat_Impl( *pMedium
);
1129 sal_Bool bStorageBasedTarget
= IsPackageStorageFormat_Impl( rMedium
);
1130 sal_Bool bOwnSource
= IsOwnStorageFormat_Impl( *pMedium
);
1131 sal_Bool bOwnTarget
= IsOwnStorageFormat_Impl( rMedium
);
1133 // Examine target format to determine whether to query if any password
1134 // protected libraries exceed the size we can handler
1135 if ( bOwnTarget
&& !QuerySaveSizeExceededModules_Impl( rMedium
.GetInteractionHandler() ) )
1137 SetError( ERRCODE_IO_ABORT
, OUString( OSL_LOG_PREFIX
) );
1141 sal_Bool bNeedsDisconnectionOnFail
= sal_False
;
1143 sal_Bool bStoreToSameLocation
= sal_False
;
1145 // the detection whether the script is changed should be done before saving
1146 sal_Bool bTryToPreserveScriptSignature
= sal_False
;
1147 // no way to detect whether a filter is oasis format, have to wait for saving process
1148 sal_Bool bNoPreserveForOasis
= sal_False
;
1149 if ( bOwnSource
&& bOwnTarget
1150 && ( pImp
->nScriptingSignatureState
== SIGNATURESTATE_SIGNATURES_OK
1151 || pImp
->nScriptingSignatureState
== SIGNATURESTATE_SIGNATURES_NOTVALIDATED
1152 || pImp
->nScriptingSignatureState
== SIGNATURESTATE_SIGNATURES_INVALID
) )
1154 AddLog( OUString( OSL_LOG_PREFIX
"MacroSignaturePreserving" ) );
1156 // the checking of the library modified state iterates over the libraries, should be done only when required
1157 // currently the check is commented out since it is broken, we have to check the signature every time we save
1158 // TODO/LATER: let isAnyContainerModified() work!
1159 bTryToPreserveScriptSignature
= sal_True
; // !pImp->pBasicManager->isAnyContainerModified();
1160 if ( bTryToPreserveScriptSignature
)
1162 // check that the storage format stays the same
1163 SvtSaveOptions aSaveOpt
;
1164 SvtSaveOptions::ODFDefaultVersion nVersion
= aSaveOpt
.GetODFDefaultVersion();
1166 OUString aODFVersion
;
1169 uno::Reference
< beans::XPropertySet
> xPropSet( GetStorage(), uno::UNO_QUERY_THROW
);
1170 xPropSet
->getPropertyValue( OUString( "Version" ) ) >>= aODFVersion
;
1172 catch( uno::Exception
& )
1175 // preserve only if the same filter has been used
1176 bTryToPreserveScriptSignature
= pMedium
->GetFilter() && pFilter
&& pMedium
->GetFilter()->GetFilterName() == pFilter
->GetFilterName();
1178 bNoPreserveForOasis
= (
1179 (aODFVersion
.equals( ODFVER_012_TEXT
) && nVersion
== SvtSaveOptions::ODFVER_011
) ||
1180 (aODFVersion
.isEmpty() && nVersion
>= SvtSaveOptions::ODFVER_012
)
1185 sal_Bool bCopyTo
= sal_False
;
1186 SfxItemSet
*pMedSet
= rMedium
.GetItemSet();
1189 SFX_ITEMSET_ARG( pMedSet
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, sal_False
);
1190 bCopyTo
= GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
||
1191 (pSaveToItem
&& pSaveToItem
->GetValue());
1194 // use UCB for case sensitive/insensitive file name comparison
1196 && !pMedium
->GetName().equalsIgnoreAsciiCase("private:stream")
1197 && !rMedium
.GetName().equalsIgnoreAsciiCase("private:stream")
1198 && ::utl::UCBContentHelper::EqualURLs( pMedium
->GetName(), rMedium
.GetName() ) )
1200 bStoreToSameLocation
= sal_True
;
1201 AddLog( OUString( OSL_LOG_PREFIX
"Save" ) );
1203 if ( pMedium
->DocNeedsFileDateCheck() )
1204 rMedium
.CheckFileDate( pMedium
->GetInitFileDate( sal_False
) );
1206 if ( bCopyTo
&& GetCreateMode() != SFX_CREATE_MODE_EMBEDDED
)
1208 // export to the same location is forbidden
1209 SetError( ERRCODE_IO_CANTWRITE
, OUString( OSL_LOG_PREFIX
) );
1213 // before we overwrite the original file, we will make a backup if there is a demand for that
1214 // if the backup is not created here it will be created internally and will be removed in case of successful saving
1215 const sal_Bool bDoBackup
= SvtSaveOptions().IsBackup();
1218 AddLog( OUString( OSL_LOG_PREFIX
"DoBackup" ) );
1219 rMedium
.DoBackup_Impl();
1220 if ( rMedium
.GetError() )
1222 SetError( rMedium
.GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
1223 rMedium
.ResetError();
1227 if ( bStorageBasedSource
&& bStorageBasedTarget
)
1229 // The active storage must be switched. The simple saving is not enough.
1230 // The problem is that the target medium contains target MediaDescriptor.
1232 // In future the switch of the persistance could be done on stream level:
1233 // a new wrapper service will be implemented that allows to exchange
1234 // persistance on the fly. So the real persistance will be set
1235 // to that stream only after successful commit of the storage.
1237 // create wrapper stream based on the URL
1238 // create a new storage based on this stream
1239 // store to this new storage
1240 // commit the new storage
1241 // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
1242 // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
1243 // if the last step is failed the stream should stay to be transacted and should be commited on any flush
1244 // so we can forget the stream in any way and the next storage commit will flush it
1246 AddLog( OUString( OSL_LOG_PREFIX
"Save: Own to Own" ) );
1248 bNeedsDisconnectionOnFail
= DisconnectStorage_Impl(
1249 *pMedium
, rMedium
);
1250 if ( bNeedsDisconnectionOnFail
1251 || ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1253 pMedium
->CloseAndRelease();
1255 // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
1256 // in future those streams should not be copied in case a valid target url is provided,
1257 // if the url is not provided ( means the document is based on a stream ) this code is not
1259 rMedium
.CloseAndRelease();
1260 rMedium
.GetOutputStorage();
1263 else if ( !bStorageBasedSource
&& !bStorageBasedTarget
)
1265 // the source and the target formats are alien
1266 // just disconnect the stream from the source format
1267 // so that the target medium can use it
1269 AddLog( OUString( OSL_LOG_PREFIX
"Save: Alien to Alien" ) );
1271 pMedium
->CloseAndRelease();
1272 rMedium
.CloseAndRelease();
1273 rMedium
.CreateTempFileNoCopy();
1274 rMedium
.GetOutStream();
1276 else if ( !bStorageBasedSource
&& bStorageBasedTarget
)
1278 // the source format is an alien one but the target
1279 // format is an own one so just disconnect the source
1282 AddLog( OUString( OSL_LOG_PREFIX
"Save: Alien to Own" ) );
1284 pMedium
->CloseAndRelease();
1285 rMedium
.CloseAndRelease();
1286 rMedium
.GetOutputStorage();
1288 else // means if ( bStorageBasedSource && !bStorageBasedTarget )
1290 // the source format is an own one but the target is
1291 // an alien format, just connect the source to temporary
1294 AddLog( OUString( OSL_LOG_PREFIX
"Save: Own to Alien" ) );
1296 bNeedsDisconnectionOnFail
= DisconnectStorage_Impl(
1297 *pMedium
, rMedium
);
1298 if ( bNeedsDisconnectionOnFail
1299 || ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1301 pMedium
->CloseAndRelease();
1302 rMedium
.CloseAndRelease();
1303 rMedium
.CreateTempFileNoCopy();
1304 rMedium
.GetOutStream();
1311 // This is SaveAs or export action, prepare the target medium
1312 // the alien filters still might write directly to the file, that is of course a bug,
1313 // but for now the framework has to be ready for it
1314 // TODO/LATER: let the medium be prepared for alien formats as well
1316 AddLog( OUString( OSL_LOG_PREFIX
"SaveAs/Export" ) );
1318 rMedium
.CloseAndRelease();
1319 if ( bStorageBasedTarget
)
1321 rMedium
.GetOutputStorage();
1325 // TODO/LATER: error handling
1326 if( rMedium
.GetErrorCode() || pMedium
->GetErrorCode() || GetErrorCode() )
1329 AddLog( OUString( OSL_LOG_PREFIX
"Locking" ) );
1331 rMedium
.LockOrigFileOnDemand( sal_False
, sal_False
);
1333 if ( bStorageBasedTarget
)
1335 if ( rMedium
.GetErrorCode() )
1338 // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from
1339 // a draw document ), the ClassId of the destination storage is different from the ClassId of this
1340 // document. It can be retrieved from the default filter for the desired target format
1341 long nFormat
= rMedium
.GetFilter()->GetFormat();
1342 SfxFilterMatcher
& rMatcher
= SFX_APP()->GetFilterMatcher();
1343 const SfxFilter
*pFilt
= rMatcher
.GetFilter4ClipBoardId( nFormat
);
1346 if ( pFilt
->GetServiceName() != rMedium
.GetFilter()->GetServiceName() )
1348 datatransfer::DataFlavor aDataFlavor
;
1349 SotExchange::GetFormatDataFlavor( nFormat
, aDataFlavor
);
1353 uno::Reference
< beans::XPropertySet
> xProps( rMedium
.GetStorage(), uno::UNO_QUERY
);
1354 DBG_ASSERT( xProps
.is(), "The storage implementation must implement XPropertySet!" );
1356 throw uno::RuntimeException();
1358 xProps
->setPropertyValue( OUString("MediaType"),
1359 uno::makeAny( aDataFlavor
.MimeType
) );
1361 catch( uno::Exception
& )
1368 // TODO/LATER: error handling
1369 if( rMedium
.GetErrorCode() || pMedium
->GetErrorCode() || GetErrorCode() )
1372 sal_Bool bOldStat
= pImp
->bForbidReload
;
1373 pImp
->bForbidReload
= sal_True
;
1375 // lock user interface while saving the document
1376 Lock_Impl( this, sal_True
);
1378 sal_Bool bOk
= sal_False
;
1379 // TODO/LATER: get rid of bOk
1381 if( bOwnTarget
&& !( pFilter
->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) )
1383 AddLog( OUString( OSL_LOG_PREFIX
"Storing in own format." ) );
1384 uno::Reference
< embed::XStorage
> xMedStorage
= rMedium
.GetStorage();
1385 if ( !xMedStorage
.is() )
1387 // no saving without storage, unlock UI and return
1388 Lock_Impl( this, sal_False
);
1389 pImp
->bForbidReload
= bOldStat
;
1390 AddLog( OUString( OSL_LOG_PREFIX
"Storing failed, still no error set." ) );
1394 // transfer password from the parameters to the storage
1395 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
1396 sal_Bool bPasswdProvided
= sal_False
;
1397 if ( GetEncryptionData_Impl( rMedium
.GetItemSet(), aEncryptionData
) )
1399 bPasswdProvided
= sal_True
;
1401 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage
, aEncryptionData
);
1404 catch( uno::Exception
& )
1406 OSL_FAIL( "Setting of common encryption key failed!" );
1407 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1413 pFilter
= rMedium
.GetFilter();
1415 const SfxStringItem
*pVersionItem
= ( !rMedium
.IsInCheckIn( ) && pSet
) ? (const SfxStringItem
*)
1416 SfxRequest::GetItem( pSet
, SID_DOCINFO_COMMENTS
, sal_False
, TYPE(SfxStringItem
) ) : NULL
;
1417 OUString aTmpVersionURL
;
1422 // currently the case that the storage is the same should be impossible
1423 if ( xMedStorage
== GetStorage() )
1425 OSL_ENSURE( !pVersionItem
, "This scenario is impossible currently!\n" );
1426 AddLog( OUString( OSL_LOG_PREFIX
"Should be impossible." ) );
1427 // usual save procedure
1433 AddLog( OUString( OSL_LOG_PREFIX
"Save as own format." ) );
1434 bOk
= SaveAsOwnFormat( rMedium
);
1435 if ( bOk
&& pVersionItem
)
1437 AddLog( OUString( OSL_LOG_PREFIX
"pVersionItem != NULL" ) );
1438 aTmpVersionURL
= CreateTempCopyOfStorage_Impl( xMedStorage
);
1439 bOk
= !aTmpVersionURL
.isEmpty();
1445 if ( bOk
&& GetCreateMode() != SFX_CREATE_MODE_EMBEDDED
&& !bPasswdProvided
)
1447 // store the thumbnail representation image
1448 // the thumbnail is not stored in case of encrypted document
1449 AddLog( OUString( OSL_LOG_PREFIX
"Thumbnail creation." ) );
1450 if ( !GenerateAndStoreThumbnail( bPasswdProvided
,
1452 pFilter
->IsOwnTemplateFormat(),
1455 // TODO: error handling
1456 OSL_FAIL( "Couldn't store thumbnail representation!" );
1462 if ( pImp
->bIsSaving
|| pImp
->bPreserveVersions
)
1464 AddLog( OUString( OSL_LOG_PREFIX
"Preserve versions." ) );
1467 Sequence
< util::RevisionTag
> aVersions
= rMedium
.GetVersionList();
1468 if ( aVersions
.getLength() )
1470 // copy the version streams
1471 OUString
aVersionsName( "Versions" );
1472 uno::Reference
< embed::XStorage
> xNewVerStor
= xMedStorage
->openStorageElement(
1474 embed::ElementModes::READWRITE
);
1475 uno::Reference
< embed::XStorage
> xOldVerStor
= GetStorage()->openStorageElement(
1477 embed::ElementModes::READ
);
1478 if ( !xNewVerStor
.is() || !xOldVerStor
.is() )
1479 throw uno::RuntimeException();
1481 for ( sal_Int32 n
=0; n
<aVersions
.getLength(); n
++ )
1483 if ( xOldVerStor
->hasByName( aVersions
[n
].Identifier
) )
1484 xOldVerStor
->copyElementTo( aVersions
[n
].Identifier
, xNewVerStor
, aVersions
[n
].Identifier
);
1487 uno::Reference
< embed::XTransactedObject
> xTransact( xNewVerStor
, uno::UNO_QUERY
);
1488 if ( xTransact
.is() )
1489 xTransact
->commit();
1492 catch( uno::Exception
& )
1494 AddLog( OUString( OSL_LOG_PREFIX
"Preserve versions has failed." ) );
1495 OSL_FAIL( "Couldn't copy versions!\n" );
1497 // TODO/LATER: a specific error could be set
1501 if ( bOk
&& pVersionItem
&& !rMedium
.IsInCheckIn() )
1503 // store a version also
1504 const SfxStringItem
*pAuthorItem
= pSet
? (const SfxStringItem
*)
1505 SfxRequest::GetItem( pSet
, SID_DOCINFO_AUTHOR
, sal_False
, TYPE(SfxStringItem
) ) : NULL
;
1508 util::RevisionTag aInfo
;
1509 aInfo
.Comment
= pVersionItem
->GetValue();
1513 aInfo
.Author
= pAuthorItem
->GetValue();
1515 // if not transferred as a parameter, get it from user settings
1516 aInfo
.Author
= SvtUserOptions().GetFullName();
1518 DateTime
aTime( DateTime::SYSTEM
);
1519 aInfo
.TimeStamp
.Day
= aTime
.GetDay();
1520 aInfo
.TimeStamp
.Month
= aTime
.GetMonth();
1521 aInfo
.TimeStamp
.Year
= aTime
.GetYear();
1522 aInfo
.TimeStamp
.Hours
= aTime
.GetHour();
1523 aInfo
.TimeStamp
.Minutes
= aTime
.GetMin();
1524 aInfo
.TimeStamp
.Seconds
= aTime
.GetSec();
1528 // add new version information into the versionlist and save the versionlist
1529 // the version list must have been transferred from the "old" medium before
1530 rMedium
.AddVersion_Impl( aInfo
);
1531 rMedium
.SaveVersionList_Impl( sal_True
);
1532 bOk
= PutURLContentsToVersionStream_Impl( aTmpVersionURL
, xMedStorage
, aInfo
.Identifier
);
1535 else if ( bOk
&& ( pImp
->bIsSaving
|| pImp
->bPreserveVersions
) )
1537 rMedium
.SaveVersionList_Impl( sal_True
);
1541 if ( !aTmpVersionURL
.isEmpty() )
1542 ::utl::UCBContentHelper::Kill( aTmpVersionURL
);
1546 AddLog( OUString( OSL_LOG_PREFIX
"Storing in alien format." ) );
1547 // it's a "SaveAs" in an alien format
1548 if ( rMedium
.GetFilter() && ( rMedium
.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER
) )
1549 bOk
= ExportTo( rMedium
);
1551 bOk
= ConvertTo( rMedium
);
1553 // after saving the document, the temporary object storage must be updated
1554 // if the old object storage was not a temporary one, it will be updated also, because it will be used
1555 // as a source for copying the objects into the new temporary storage that will be created below
1556 // updating means: all child objects must be stored into it
1557 // ( same as on loading, where these objects are copied to the temporary storage )
1558 // but don't commit these changes, because in the case when the old object storage is not a temporary one,
1559 // all changes will be written into the original file !
1561 if( bOk
&& !bCopyTo
)
1562 // we also don't touch any graphical replacements here
1563 bOk
= SaveChildren( sal_True
);
1568 // if ODF version of oasis format changes on saving the signature should not be preserved
1569 if ( bOk
&& bTryToPreserveScriptSignature
&& bNoPreserveForOasis
)
1570 bTryToPreserveScriptSignature
= ( SotStorage::GetVersion( rMedium
.GetStorage() ) == SOFFICE_FILEFORMAT_60
);
1572 uno::Reference
< security::XDocumentDigitalSignatures
> xDDSigns
;
1573 if ( bOk
&& bTryToPreserveScriptSignature
)
1575 AddLog( OUString( OSL_LOG_PREFIX
"Copying scripting signature." ) );
1577 // if the scripting code was not changed and it is signed the signature should be preserved
1578 // unfortunately at this point we have only information whether the basic code has changed or not
1579 // so the only way is to check the signature if the basic was not changed
1582 // get the ODF version of the new medium
1586 uno::Reference
< beans::XPropertySet
> xPropSet( rMedium
.GetStorage(), uno::UNO_QUERY_THROW
);
1587 xPropSet
->getPropertyValue( OUString( "Version" ) ) >>= aVersion
;
1589 catch( uno::Exception
& )
1593 xDDSigns
= security::DocumentDigitalSignatures::createWithVersion(comphelper::getProcessComponentContext(), aVersion
);
1595 OUString aScriptSignName
= xDDSigns
->getScriptingContentSignatureDefaultStreamName();
1597 if ( !aScriptSignName
.isEmpty() )
1601 // target medium is still not commited, it should not be closed
1602 // commit the package storage and close it, but leave the streams open
1603 rMedium
.StorageCommit_Impl();
1604 rMedium
.CloseStorage();
1606 uno::Reference
< embed::XStorage
> xReadOrig
= pMedium
->GetZipStorageToSign_Impl();
1607 if ( !xReadOrig
.is() )
1608 throw uno::RuntimeException();
1609 uno::Reference
< embed::XStorage
> xMetaInf
= xReadOrig
->openStorageElement(
1610 OUString( "META-INF" ),
1611 embed::ElementModes::READ
);
1613 uno::Reference
< embed::XStorage
> xTarget
= rMedium
.GetZipStorageToSign_Impl( sal_False
);
1614 if ( !xTarget
.is() )
1615 throw uno::RuntimeException();
1616 uno::Reference
< embed::XStorage
> xTargetMetaInf
= xTarget
->openStorageElement(
1617 OUString( "META-INF" ),
1618 embed::ElementModes::READWRITE
);
1620 if ( xMetaInf
.is() && xTargetMetaInf
.is() )
1622 xMetaInf
->copyElementTo( aScriptSignName
, xTargetMetaInf
, aScriptSignName
);
1624 uno::Reference
< embed::XTransactedObject
> xTransact( xTargetMetaInf
, uno::UNO_QUERY
);
1625 if ( xTransact
.is() )
1626 xTransact
->commit();
1628 xTargetMetaInf
->dispose();
1630 // now check the copied signature
1631 uno::Sequence
< security::DocumentSignatureInformation
> aInfos
=
1632 xDDSigns
->verifyScriptingContentSignatures( xTarget
,
1633 uno::Reference
< io::XInputStream
>() );
1634 sal_uInt16 nState
= ImplCheckSignaturesInformation( aInfos
);
1635 if ( nState
== SIGNATURESTATE_SIGNATURES_OK
|| nState
== SIGNATURESTATE_SIGNATURES_NOTVALIDATED
1636 || nState
== SIGNATURESTATE_SIGNATURES_PARTIAL_OK
)
1638 rMedium
.SetCachedSignatureState_Impl( nState
);
1640 // commit the ZipStorage from target medium
1641 xTransact
.set( xTarget
, uno::UNO_QUERY
);
1642 if ( xTransact
.is() )
1643 xTransact
->commit();
1647 // it should not happen, the copies signature is invalid!
1648 // throw the changes away
1649 OSL_FAIL( "An invalid signature was copied!" );
1654 catch( uno::Exception
& )
1659 rMedium
.CloseZipStorage_Impl();
1662 AddLog( OUString( OSL_LOG_PREFIX
"Medium commit." ) );
1664 OUString
sName( rMedium
.GetName( ) );
1665 bOk
= rMedium
.Commit();
1666 OUString
sNewName( rMedium
.GetName( ) );
1668 if ( sName
!= sNewName
)
1669 GetMedium( )->SwitchDocumentToFile( sNewName
);
1673 AddLog( OUString( OSL_LOG_PREFIX
"Storing is successful." ) );
1675 // if the target medium is an alien format and the "old" medium was an own format and the "old" medium
1676 // has a name, the object storage must be exchanged, because now we need a new temporary storage
1677 // as object storage
1678 if ( !bCopyTo
&& bStorageBasedSource
&& !bStorageBasedTarget
)
1680 if ( bStoreToSameLocation
)
1682 // if the old medium already disconnected from document storage, the storage still must
1683 // be switched if backup file is used
1684 if ( bNeedsDisconnectionOnFail
)
1685 ConnectTmpStorage_Impl( pImp
->m_xDocStorage
, NULL
);
1687 else if (!pMedium
->GetName().isEmpty()
1688 || ( pMedium
->HasStorage_Impl() && pMedium
->WillDisposeStorageOnClose_Impl() ) )
1690 OSL_ENSURE(!pMedium
->GetName().isEmpty(), "Fallback is used, the medium without name should not dispose the storage!\n");
1691 // copy storage of old medium to new temporary storage and take this over
1692 if( !ConnectTmpStorage_Impl( pMedium
->GetStorage(), pMedium
) )
1694 AddLog( OUString( OSL_LOG_PREFIX
"Process after storing has failed." ) );
1702 AddLog( OUString( OSL_LOG_PREFIX
"Storing has failed." ) );
1704 // in case the document storage was connected to backup temporarely it must be disconnected now
1705 if ( bNeedsDisconnectionOnFail
)
1706 ConnectTmpStorage_Impl( pImp
->m_xDocStorage
, NULL
);
1710 // unlock user interface
1711 Lock_Impl( this, sal_False
);
1712 pImp
->bForbidReload
= bOldStat
;
1718 ::ucbhelper::Content
aContent( rMedium
.GetName(), com::sun::star::uno::Reference
< XCommandEnvironment
>(), comphelper::getProcessComponentContext() );
1719 com::sun::star::uno::Reference
< XPropertySetInfo
> xProps
= aContent
.getProperties();
1722 OUString
aAuthor( "Author" );
1723 OUString
aKeywords( "Keywords" );
1724 OUString
aSubject( "Subject" );
1727 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1728 GetModel(), uno::UNO_QUERY_THROW
);
1729 uno::Reference
<document::XDocumentProperties
> xDocProps
1730 = xDPS
->getDocumentProperties();
1732 if ( xProps
->hasPropertyByName( aAuthor
) )
1734 aAny
<<= xDocProps
->getAuthor();
1735 aContent
.setPropertyValue( aAuthor
, aAny
);
1737 if ( xProps
->hasPropertyByName( aKeywords
) )
1739 aAny
<<= ::comphelper::string::convertCommaSeparated(
1740 xDocProps
->getKeywords());
1741 aContent
.setPropertyValue( aKeywords
, aAny
);
1743 if ( xProps
->hasPropertyByName( aSubject
) )
1745 aAny
<<= xDocProps
->getSubject();
1746 aContent
.setPropertyValue( aSubject
, aAny
);
1758 //------------------------------------------------------------------------
1759 sal_Bool
SfxObjectShell::DisconnectStorage_Impl( SfxMedium
& rSrcMedium
, SfxMedium
& rTargetMedium
)
1761 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::DisconnectStorage_Impl" );
1763 // this method disconnects the storage from source medium, and attaches it to the backup created by the target medium
1765 uno::Reference
< embed::XStorage
> xStorage
= rSrcMedium
.GetStorage();
1767 sal_Bool bResult
= sal_False
;
1768 if ( xStorage
== pImp
->m_xDocStorage
)
1772 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY_THROW
);
1773 OUString aBackupURL
= rTargetMedium
.GetBackup_Impl();
1774 if ( aBackupURL
.isEmpty() )
1776 // the backup could not be created, try to disconnect the storage and close the source SfxMedium
1777 // in this case the optimization is not possible, connect storage to a temporary file
1778 rTargetMedium
.ResetError();
1779 xOptStorage
->writeAndAttachToStream( uno::Reference
< io::XStream
>() );
1780 rSrcMedium
.CanDisposeStorage_Impl( sal_False
);
1783 // now try to create the backup
1784 rTargetMedium
.GetBackup_Impl();
1788 // the following call will only compare stream sizes
1789 // TODO/LATER: this is a very risky part, since if the URL contents are different from the storage
1790 // contents, the storag will be broken
1791 xOptStorage
->attachToURL( aBackupURL
, sal_True
);
1793 // the storage is successfully attached to backup, thus it it owned by the document not by the medium
1794 rSrcMedium
.CanDisposeStorage_Impl( sal_False
);
1798 catch ( uno::Exception
& )
1805 //------------------------------------------------------------------------
1807 sal_Bool
SfxObjectShell::ConnectTmpStorage_Impl(
1808 const uno::Reference
< embed::XStorage
>& xStorage
,
1809 SfxMedium
* pMediumArg
)
1813 If the application operates on a temporary storage, then it may not take
1814 the temporary storage from the SaveCompleted. Therefore the new storage
1815 is connected already here in this case and SaveCompleted then does nothing.
1819 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::ConnectTmpStorage_Impl" );
1821 sal_Bool bResult
= sal_False
;
1823 if ( xStorage
.is() )
1827 // the empty argument means that the storage will create temporary stream itself
1828 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xStorage
, uno::UNO_QUERY_THROW
);
1829 xOptStorage
->writeAndAttachToStream( uno::Reference
< io::XStream
>() );
1831 // the storage is successfully disconnected from the original sources, thus the medium must not dispose it
1833 pMediumArg
->CanDisposeStorage_Impl( sal_False
);
1837 catch( uno::Exception
& )
1841 // if switching of the storage does not work for any reason ( nonroot storage for example ) use the old method
1844 uno::Reference
< embed::XStorage
> xTmpStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
1846 DBG_ASSERT( xTmpStorage
.is(), "If a storage can not be created an exception must be thrown!\n" );
1847 if ( !xTmpStorage
.is() )
1848 throw uno::RuntimeException();
1850 // TODO/LATER: may be it should be done in SwitchPersistence also
1851 // TODO/LATER: find faster way to copy storage; perhaps sharing with backup?!
1852 xStorage
->copyToStorage( xTmpStorage
);
1853 bResult
= SaveCompleted( xTmpStorage
);
1857 pImp
->pBasicManager
->setStorage( xTmpStorage
);
1859 // Get rid of this workaround after issue i113914 is fixed
1862 uno::Reference
< script::XStorageBasedLibraryContainer
> xBasicLibraries( pImp
->xBasicLibraries
, uno::UNO_QUERY_THROW
);
1863 xBasicLibraries
->setRootStorage( xTmpStorage
);
1865 catch( uno::Exception
& )
1869 uno::Reference
< script::XStorageBasedLibraryContainer
> xDialogLibraries( pImp
->xDialogLibraries
, uno::UNO_QUERY_THROW
);
1870 xDialogLibraries
->setRootStorage( xTmpStorage
);
1872 catch( uno::Exception
& )
1876 catch( uno::Exception
& )
1881 // TODO/LATER: may need error code setting based on exception
1882 SetError( ERRCODE_IO_GENERAL
, OUString( OSL_LOG_PREFIX
) );
1889 //-------------------------------------------------------------------------
1891 sal_Bool
SfxObjectShell::DoSaveObjectAs( SfxMedium
& rMedium
, sal_Bool bCommit
)
1893 sal_Bool bOk
= sal_False
;
1895 ModifyBlocker_Impl
aBlock( this );
1897 uno::Reference
< embed::XStorage
> xNewStor
= rMedium
.GetStorage();
1898 if ( !xNewStor
.is() )
1901 uno::Reference
< beans::XPropertySet
> xPropSet( xNewStor
, uno::UNO_QUERY
);
1902 if ( xPropSet
.is() )
1904 Any a
= xPropSet
->getPropertyValue( OUString("MediaType" ) );
1905 OUString aMediaType
;
1906 if ( !(a
>>=aMediaType
) || aMediaType
.isEmpty() )
1908 OSL_FAIL( "The mediatype must be set already!\n" );
1909 SetupStorage( xNewStor
, SOFFICE_FILEFORMAT_CURRENT
, sal_False
, false );
1912 pImp
->bIsSaving
= sal_False
;
1913 bOk
= SaveAsOwnFormat( rMedium
);
1918 uno::Reference
< embed::XTransactedObject
> xTransact( xNewStor
, uno::UNO_QUERY_THROW
);
1919 xTransact
->commit();
1921 catch( uno::Exception
& )
1923 OSL_FAIL( "The strotage was not commited on DoSaveAs!\n" );
1932 //-------------------------------------------------------------------------
1933 // TODO/LATER: may be the call must be removed completelly
1934 sal_Bool
SfxObjectShell::DoSaveAs( SfxMedium
& rMedium
)
1936 // here only root storages are included, which are stored via temp file
1937 rMedium
.CreateTempFileNoCopy();
1938 SetError(rMedium
.GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
1942 // copy version list from "old" medium to target medium, so it can be used on saving
1943 if ( pImp
->bPreserveVersions
)
1944 rMedium
.TransferVersionList_Impl( *pMedium
);
1946 sal_Bool bRet
= SaveTo_Impl( rMedium
, NULL
);
1948 SetError(rMedium
.GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
1952 //-------------------------------------------------------------------------
1954 sal_Bool
SfxObjectShell::DoSaveCompleted( SfxMedium
* pNewMed
)
1956 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::DoSaveCompleted" );
1958 sal_Bool bOk
= sal_True
;
1959 sal_Bool bMedChanged
= pNewMed
&& pNewMed
!=pMedium
;
1961 DBG_ASSERT( !pNewMed
|| pNewMed
->GetError() == ERRCODE_NONE
, "DoSaveCompleted: Medium has error!" );
1963 // delete Medium (and Storage!) after all notifications
1964 SfxMedium
* pOld
= pMedium
;
1968 pMedium
->CanDisposeStorage_Impl( sal_True
);
1971 const SfxFilter
*pFilter
= pMedium
? pMedium
->GetFilter() : 0;
1976 if (!pNewMed
->GetName().isEmpty())
1977 bHasName
= sal_True
;
1978 Broadcast( SfxSimpleHint(SFX_HINT_NAMECHANGED
) );
1979 getDocProperties()->setGenerator(
1980 ::utl::DocInfoHelper::GetGeneratorString() );
1983 uno::Reference
< embed::XStorage
> xStorage
;
1984 if ( !pFilter
|| IsPackageStorageFormat_Impl( *pMedium
) )
1986 uno::Reference
< embed::XStorage
> xOld
= GetStorage();
1988 // when the package based medium is broken and has no storage or if the storage
1989 // is the same as the document storage the current document storage should be preserved
1990 xStorage
= pMedium
->GetStorage();
1991 bOk
= SaveCompleted( xStorage
);
1992 if ( bOk
&& xStorage
.is() && xOld
!= xStorage
1993 && (!pOld
|| !pOld
->HasStorage_Impl() || xOld
!= pOld
->GetStorage() ) )
1995 // old own storage was not controlled by old Medium -> dispose it
1998 } catch( uno::Exception
& )
2000 // the storage is disposed already
2001 // can happen during reload scenario when the medium has
2002 // disposed it during the closing
2003 // will be fixed in one of the next milestones
2009 if( pMedium
->GetOpenMode() & STREAM_WRITE
)
2010 pMedium
->GetInStream();
2011 xStorage
= GetStorage();
2014 // TODO/LATER: may be this code will be replaced, but not sure
2015 // Set storage in document library containers
2016 pImp
->pBasicManager
->setStorage( xStorage
);
2018 // Get rid of this workaround after issue i113914 is fixed
2021 uno::Reference
< script::XStorageBasedLibraryContainer
> xBasicLibraries( pImp
->xBasicLibraries
, uno::UNO_QUERY_THROW
);
2022 xBasicLibraries
->setRootStorage( xStorage
);
2024 catch( uno::Exception
& )
2028 uno::Reference
< script::XStorageBasedLibraryContainer
> xDialogLibraries( pImp
->xDialogLibraries
, uno::UNO_QUERY_THROW
);
2029 xDialogLibraries
->setRootStorage( xStorage
);
2031 catch( uno::Exception
& )
2038 if( pFilter
&& !IsPackageStorageFormat_Impl( *pMedium
) && (pMedium
->GetOpenMode() & STREAM_WRITE
))
2041 bOk
= SaveCompletedChildren( sal_False
);
2044 bOk
= SaveCompleted( NULL
);
2046 // either Save or ConvertTo
2048 bOk
= SaveCompleted( NULL
);
2051 if ( bOk
&& pNewMed
)
2057 uno::Reference
< frame::XModel
> xModel
= GetModel();
2060 OUString aURL
= pNewMed
->GetOrigURL();
2061 uno::Sequence
< beans::PropertyValue
> aMediaDescr
;
2062 TransformItems( SID_OPENDOC
, *pNewMed
->GetItemSet(), aMediaDescr
);
2065 xModel
->attachResource( aURL
, aMediaDescr
);
2067 catch( uno::Exception
& )
2071 // before the title regenerated the document must loose the signatures
2072 pImp
->nDocumentSignatureState
= SIGNATURESTATE_NOSIGNATURES
;
2073 pImp
->nScriptingSignatureState
= pNewMed
->GetCachedSignatureState_Impl();
2074 OSL_ENSURE( pImp
->nScriptingSignatureState
!= SIGNATURESTATE_SIGNATURES_BROKEN
, "The signature must not be broken at this place" );
2075 pImp
->bSignatureErrorIsShown
= sal_False
;
2077 // TODO/LATER: in future the medium must control own signature state, not the document
2078 pNewMed
->SetCachedSignatureState_Impl( SIGNATURESTATE_NOSIGNATURES
); // set the default value back
2081 if (!pNewMed
->GetName().isEmpty() && SFX_CREATE_MODE_EMBEDDED
!= eCreateMode
)
2083 SetModified(sal_False
); // reset only by set medium
2084 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED
) );
2086 // this is the end of the saving process, it is possible that
2087 // the file was changed
2088 // between medium commit and this step (attributes change and so on)
2089 // so get the file date again
2090 if ( pNewMed
->DocNeedsFileDateCheck() )
2091 pNewMed
->GetInitFileDate( sal_True
);
2095 pMedium
->ClearBackup_Impl();
2096 pMedium
->LockOrigFileOnDemand( sal_True
, sal_False
);
2098 AddToRecentlyUsedList();
2103 void SfxObjectShell::AddToRecentlyUsedList()
2105 INetURLObject
aUrl( pMedium
->GetOrigURL() );
2107 if ( aUrl
.GetProtocol() == INET_PROT_FILE
)
2109 const SfxFilter
* pOrgFilter
= pMedium
->GetOrigFilter();
2110 Application::AddToRecentDocumentList( aUrl
.GetURLNoPass( INetURLObject::NO_DECODE
),
2111 (pOrgFilter
) ? pOrgFilter
->GetMimeType() : OUString(),
2112 (pOrgFilter
) ? pOrgFilter
->GetServiceName() : OUString() );
2116 //-------------------------------------------------------------------------
2118 sal_Bool
SfxObjectShell::ConvertFrom
2120 SfxMedium
& /*rMedium*/ /* <SfxMedium>, which describes the source file
2121 (for example file name, <SfxFilter>,
2122 Open-Modi and so on) */
2127 This method is called for loading of documents over all filters which are
2128 not SFX_FILTER_OWN or for which no clipboard format has been registered
2129 (thus no storage format that is used). In other words, with this method
2132 Files which are to be opened here should be opened through 'rMedium'
2133 to guarantee the right open modes. Especially if the format is retained
2134 (only possible with SFX_FILTER_SIMULATE or SFX_FILTER_ONW) file which must
2135 be opened STREAM_SHARE_DENYWRITE.
2140 The document could be loaded.
2143 The document could not be loaded, an error code
2144 received through <SvMedium::GetError()const>
2148 sal_Bool DocSh::ConvertFrom( SfxMedium &rMedium )
2150 SvStreamRef xStream = rMedium.GetInStream();
2153 xStream->SetBufferSize(4096);
2156 // Do not call 'rMedium.CloseInStream()'! Keep File locked!
2157 return SVSTREAM_OK == rMedium.GetError();
2165 <SfxObjectShell::ConvertTo(SfxMedium&)>
2166 <SFX_FILTER_REGISTRATION>
2172 sal_Bool
SfxObjectShell::ImportFrom( SfxMedium
& rMedium
, bool bInsert
)
2174 OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2176 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2177 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2178 xMan
->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY
);
2180 uno::Sequence
< beans::PropertyValue
> aProps
;
2181 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2182 if ( xFilters
->hasByName( aFilterName
) )
2184 xFilters
->getByName( aFilterName
) >>= aProps
;
2185 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILTER_NAME
, aFilterName
) );
2188 OUString aFilterImplName
;
2189 sal_Int32 nFilterProps
= aProps
.getLength();
2190 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2192 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2193 if ( rFilterProp
.Name
.compareToAscii("FilterService") == COMPARE_EQUAL
)
2195 rFilterProp
.Value
>>= aFilterImplName
;
2200 uno::Reference
< document::XFilter
> xLoader
;
2201 if ( !aFilterImplName
.isEmpty() )
2204 xLoader
= uno::Reference
< document::XFilter
>
2205 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2206 }catch(const uno::Exception
&)
2207 { xLoader
.clear(); }
2211 // it happens that xLoader does not support xImporter!
2213 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2214 uno::Reference
< document::XImporter
> xImporter( xLoader
, uno::UNO_QUERY_THROW
);
2215 xImporter
->setTargetDocument( xComp
);
2217 uno::Sequence
< beans::PropertyValue
> lDescriptor
;
2218 rMedium
.GetItemSet()->Put( SfxStringItem( SID_FILE_NAME
, rMedium
.GetName() ) );
2219 TransformItems( SID_OPENDOC
, *rMedium
.GetItemSet(), lDescriptor
);
2221 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( lDescriptor
.getLength() );
2222 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2223 const com::sun::star::beans::PropertyValue
* pOldValue
= lDescriptor
.getConstArray();
2224 const OUString
sInputStream ( "InputStream" );
2226 sal_Bool bHasInputStream
= sal_False
;
2227 sal_Bool bHasBaseURL
= sal_False
;
2229 sal_Int32 nEnd
= lDescriptor
.getLength();
2231 for ( i
= 0; i
< nEnd
; i
++ )
2233 pNewValue
[i
] = pOldValue
[i
];
2234 if ( pOldValue
[i
].Name
== sInputStream
)
2235 bHasInputStream
= sal_True
;
2236 else if ( pOldValue
[i
].Name
== "DocumentBaseURL" )
2237 bHasBaseURL
= sal_True
;
2240 if ( !bHasInputStream
)
2242 aArgs
.realloc ( ++nEnd
);
2243 aArgs
[nEnd
-1].Name
= sInputStream
;
2244 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
> ( new utl::OSeekableInputStreamWrapper ( *rMedium
.GetInStream() ) );
2249 aArgs
.realloc ( ++nEnd
);
2250 aArgs
[nEnd
-1].Name
= OUString( "DocumentBaseURL" );
2251 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL();
2255 aArgs
.realloc( ++nEnd
);
2256 aArgs
[nEnd
-1].Name
= OUString( "InsertMode" );
2257 aArgs
[nEnd
-1].Value
<<= (sal_Bool
) sal_True
;
2260 // #i119492# During loading, some OLE objects like chart will be set
2261 // modified flag, so needs to reset the flag to false after loading
2262 sal_Bool bRtn
= xLoader
->filter( aArgs
);
2263 uno::Sequence
< OUString
> aNames
= GetEmbeddedObjectContainer().GetObjectNames();
2264 for ( sal_Int32 n
= 0; n
< aNames
.getLength(); ++n
)
2266 OUString aName
= aNames
[n
];
2267 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObjectContainer().GetEmbeddedObject( aName
);
2268 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
2271 sal_Int32 nState
= xObj
->getCurrentState();
2272 if ( nState
== embed::EmbedStates::LOADED
|| nState
== embed::EmbedStates::RUNNING
) // means that the object is not active
2274 uno::Reference
< util::XModifiable
> xModifiable( xObj
->getComponent(), uno::UNO_QUERY
);
2275 if ( xModifiable
.is() )
2276 xModifiable
->setModified(sal_False
);
2282 catch (const packages::zip::ZipIOException
&)
2284 SetError( ERRCODE_IO_BROKENPACKAGE
, "Badness in the underlying package format." );
2286 catch (const lang::WrappedTargetRuntimeException
& rWrapped
)
2288 io::WrongFormatException e
;
2289 if (rWrapped
.TargetException
>>= e
)
2291 SetError(*new StringErrorInfo(ERRCODE_SFX_FORMAT_ROWCOL
,
2292 e
.Message
, ERRCODE_BUTTON_OK
| ERRCODE_MSG_ERROR
), "");
2302 sal_Bool
SfxObjectShell::ExportTo( SfxMedium
& rMedium
)
2304 OUString
aFilterName( rMedium
.GetFilter()->GetFilterName() );
2305 uno::Reference
< document::XExporter
> xExporter
;
2308 uno::Reference
< lang::XMultiServiceFactory
> xMan
= ::comphelper::getProcessServiceFactory();
2309 uno::Reference
< lang::XMultiServiceFactory
> xFilterFact (
2310 xMan
->createInstance( "com.sun.star.document.FilterFactory" ), uno::UNO_QUERY
);
2312 uno::Sequence
< beans::PropertyValue
> aProps
;
2313 uno::Reference
< container::XNameAccess
> xFilters ( xFilterFact
, uno::UNO_QUERY
);
2314 if ( xFilters
->hasByName( aFilterName
) )
2315 xFilters
->getByName( aFilterName
) >>= aProps
;
2317 OUString aFilterImplName
;
2318 sal_Int32 nFilterProps
= aProps
.getLength();
2319 for ( sal_Int32 nFilterProp
= 0; nFilterProp
<nFilterProps
; nFilterProp
++ )
2321 const beans::PropertyValue
& rFilterProp
= aProps
[nFilterProp
];
2322 if ( rFilterProp
.Name
.compareToAscii("FilterService") == COMPARE_EQUAL
)
2324 rFilterProp
.Value
>>= aFilterImplName
;
2329 if ( !aFilterImplName
.isEmpty() )
2332 xExporter
= uno::Reference
< document::XExporter
>
2333 ( xFilterFact
->createInstanceWithArguments( aFilterName
, uno::Sequence
< uno::Any
>() ), uno::UNO_QUERY
);
2334 }catch(const uno::Exception
&)
2335 { xExporter
.clear(); }
2339 if ( xExporter
.is() )
2342 uno::Reference
< lang::XComponent
> xComp( GetModel(), uno::UNO_QUERY_THROW
);
2343 uno::Reference
< document::XFilter
> xFilter( xExporter
, uno::UNO_QUERY_THROW
);
2344 xExporter
->setSourceDocument( xComp
);
2346 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aOldArgs
;
2347 SfxItemSet
* pItems
= rMedium
.GetItemSet();
2348 TransformItems( SID_SAVEASDOC
, *pItems
, aOldArgs
);
2350 const com::sun::star::beans::PropertyValue
* pOldValue
= aOldArgs
.getConstArray();
2351 com::sun::star::uno::Sequence
< com::sun::star::beans::PropertyValue
> aArgs ( aOldArgs
.getLength() );
2352 com::sun::star::beans::PropertyValue
* pNewValue
= aArgs
.getArray();
2354 // put in the REAL file name, and copy all PropertyValues
2355 const OUString
sOutputStream ( "OutputStream" );
2356 const OUString
sStream ( "StreamForOutput" );
2357 sal_Bool bHasOutputStream
= sal_False
;
2358 sal_Bool bHasStream
= sal_False
;
2359 sal_Bool bHasBaseURL
= sal_False
;
2361 sal_Int32 nEnd
= aOldArgs
.getLength();
2363 for ( i
= 0; i
< nEnd
; i
++ )
2365 pNewValue
[i
] = pOldValue
[i
];
2366 if ( pOldValue
[i
].Name
== "FileName" )
2367 pNewValue
[i
].Value
<<= OUString ( rMedium
.GetName() );
2368 else if ( pOldValue
[i
].Name
== sOutputStream
)
2369 bHasOutputStream
= sal_True
;
2370 else if ( pOldValue
[i
].Name
== sStream
)
2371 bHasStream
= sal_True
;
2372 else if ( pOldValue
[i
].Name
== "DocumentBaseURL" )
2373 bHasBaseURL
= sal_True
;
2376 if ( !bHasOutputStream
)
2378 aArgs
.realloc ( ++nEnd
);
2379 aArgs
[nEnd
-1].Name
= sOutputStream
;
2380 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XOutputStream
> ( new utl::OOutputStreamWrapper ( *rMedium
.GetOutStream() ) );
2383 // add stream as well, for OOX export and maybe others
2386 aArgs
.realloc ( ++nEnd
);
2387 aArgs
[nEnd
-1].Name
= sStream
;
2388 aArgs
[nEnd
-1].Value
<<= com::sun::star::uno::Reference
< com::sun::star::io::XStream
> ( new utl::OStreamWrapper ( *rMedium
.GetOutStream() ) );
2393 aArgs
.realloc ( ++nEnd
);
2394 aArgs
[nEnd
-1].Name
= OUString( "DocumentBaseURL" );
2395 aArgs
[nEnd
-1].Value
<<= rMedium
.GetBaseURL( sal_True
);
2398 return xFilter
->filter( aArgs
);
2399 }catch(const uno::Exception
&)
2406 //-------------------------------------------------------------------------
2408 sal_Bool
SfxObjectShell::ConvertTo
2410 SfxMedium
& /*rMedium*/ /* <SfxMedium>, which describes the target file
2411 (for example file name, <SfxFilter>,
2412 Open-Modi and so on) */
2417 This method is called for saving of documents over all filters which are
2418 not SFX_FILTER_OWN or for which no clipboard format has been registered
2419 (thus no storage format that is used). In other words, with this method
2422 Files which are to be opened here should be opened through 'rMedium'
2423 to guarantee the right open modes. Especially if the format is retained
2424 (only possible with SFX_FILTER_SIMULATE or SFX_FILTER_ONW) file which must
2425 be opened STREAM_SHARE_DENYWRITE.
2430 The document could be saved.
2433 The document could not be saved, an error code is
2434 received by <SvMedium::GetError()const>
2439 sal_Bool DocSh::ConvertTo( SfxMedium &rMedium )
2441 SvStreamRef xStream = rMedium.GetOutStream();
2444 xStream->SetBufferSize(4096);
2447 rMedium.CloseOutStream(); // opens the InStream automatically
2448 return SVSTREAM_OK == rMedium.GetError();
2455 <SfxObjectShell::ConvertFrom(SfxMedium&)>
2456 <SFX_FILTER_REGISTRATION>
2463 //-------------------------------------------------------------------------
2465 sal_Bool
SfxObjectShell::DoSave_Impl( const SfxItemSet
* pArgs
)
2467 SfxMedium
* pRetrMedium
= GetMedium();
2468 const SfxFilter
* pFilter
= pRetrMedium
->GetFilter();
2470 // copy the original itemset, but remove the "version" item, because pMediumTmp
2471 // is a new medium "from scratch", so no version should be stored into it
2472 SfxItemSet
* pSet
= new SfxAllItemSet(*pRetrMedium
->GetItemSet());
2473 pSet
->ClearItem( SID_VERSION
);
2474 pSet
->ClearItem( SID_DOC_BASEURL
);
2476 // copy the version comment and major items for the checkin only
2477 if ( pRetrMedium
->IsInCheckIn( ) )
2479 const SfxPoolItem
* pMajor
= pArgs
->GetItem( SID_DOCINFO_MAJOR
);
2481 pSet
->Put( *pMajor
);
2483 const SfxPoolItem
* pComments
= pArgs
->GetItem( SID_DOCINFO_COMMENTS
);
2485 pSet
->Put( *pComments
);
2488 // create a medium as a copy; this medium is only for writingm, because it
2489 // uses the same name as the original one writing is done through a copy,
2490 // that will be transferred to the target (of course after calling HandsOff)
2491 SfxMedium
* pMediumTmp
= new SfxMedium( pRetrMedium
->GetName(), pRetrMedium
->GetOpenMode(), pFilter
, pSet
);
2492 pMediumTmp
->SetInCheckIn( pRetrMedium
->IsInCheckIn( ) );
2493 pMediumTmp
->SetLongName( pRetrMedium
->GetLongName() );
2494 if ( pMediumTmp
->GetErrorCode() != ERRCODE_NONE
)
2496 SetError( pMediumTmp
->GetError(), OUString( OSL_LOG_PREFIX
) );
2501 // copy version list from "old" medium to target medium, so it can be used on saving
2502 pMediumTmp
->TransferVersionList_Impl( *pRetrMedium
);
2504 // an interaction handler here can aquire only in case of GUI Saving
2505 // and should be removed after the saving is done
2506 com::sun::star::uno::Reference
< XInteractionHandler
> xInteract
;
2507 SFX_ITEMSET_ARG( pArgs
, pxInteractionItem
, SfxUnoAnyItem
, SID_INTERACTIONHANDLER
, sal_False
);
2508 if ( pxInteractionItem
&& ( pxInteractionItem
->GetValue() >>= xInteract
) && xInteract
.is() )
2509 pMediumTmp
->GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER
, makeAny( xInteract
) ) );
2511 sal_Bool bSaved
= sal_False
;
2512 if( !GetError() && SaveTo_Impl( *pMediumTmp
, pArgs
) )
2516 if( pMediumTmp
->GetItemSet() )
2518 pMediumTmp
->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER
);
2519 pMediumTmp
->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2522 SetError(pMediumTmp
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2524 sal_Bool
bOpen( sal_False
);
2525 bOpen
= DoSaveCompleted( pMediumTmp
);
2527 DBG_ASSERT(bOpen
,"Error handling for DoSaveCompleted not implemented");
2532 // transfer error code from medium to objectshell
2533 SetError( pMediumTmp
->GetError(), OUString( OSL_LOG_PREFIX
) );
2535 // reconnect to object storage
2536 DoSaveCompleted( 0 );
2538 if( pRetrMedium
->GetItemSet() )
2540 pRetrMedium
->GetItemSet()->ClearItem( SID_INTERACTIONHANDLER
);
2541 pRetrMedium
->GetItemSet()->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2547 SetModified( !bSaved
);
2551 //-------------------------------------------------------------------------
2553 sal_Bool
SfxObjectShell::Save_Impl( const SfxItemSet
* pSet
)
2557 SetError( ERRCODE_SFX_DOCUMENTREADONLY
, OUString( OSL_LOG_PREFIX
) );
2561 DBG_CHKTHIS(SfxObjectShell
, 0);
2563 pImp
->bIsSaving
= sal_True
;
2564 sal_Bool bSaved
= sal_False
;
2565 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pSalvageItem
, SfxStringItem
, SID_DOC_SALVAGE
, sal_False
);
2568 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
2570 const SfxFilter
*pFilter
= NULL
;
2572 pFilter
= SfxFilterMatcher( OUString::createFromAscii( GetFactory().GetShortName()) ).GetFilter4FilterName( aFilterName
);
2574 SfxMedium
*pMed
= new SfxMedium(
2575 pSalvageItem
->GetValue(), STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
| STREAM_TRUNC
, pFilter
);
2577 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
2578 if ( pPasswordItem
)
2579 pMed
->GetItemSet()->Put( *pPasswordItem
);
2581 bSaved
= DoSaveAs( *pMed
);
2583 bSaved
= DoSaveCompleted( pMed
);
2588 bSaved
= DoSave_Impl( pSet
);
2592 //-------------------------------------------------------------------------
2594 sal_Bool
SfxObjectShell::CommonSaveAs_Impl
2596 const INetURLObject
& aURL
,
2597 const String
& aFilterName
,
2601 if( aURL
.HasError() )
2603 SetError( ERRCODE_IO_INVALIDPARAMETER
, OUString( OSL_LOG_PREFIX
) );
2607 if ( aURL
!= INetURLObject( OUString( "private:stream" ) ) )
2609 // Is there already a Document with this name?
2610 SfxObjectShell
* pDoc
= 0;
2611 for ( SfxObjectShell
* pTmp
= SfxObjectShell::GetFirst();
2613 pTmp
= SfxObjectShell::GetNext(*pTmp
) )
2615 if( ( pTmp
!= this ) && pTmp
->GetMedium() )
2617 INetURLObject
aCompare( pTmp
->GetMedium()->GetName() );
2618 if ( aCompare
== aURL
)
2624 // Then error message: "already opened"
2625 SetError(ERRCODE_SFX_ALREADYOPEN
, OUString( OSL_LOG_PREFIX
));
2630 DBG_ASSERT( aURL
.GetProtocol() != INET_PROT_NOT_VALID
, "Illegal URL!" );
2631 DBG_ASSERT( aParams
->Count() != 0, "Incorrect Parameter");
2633 SFX_ITEMSET_ARG( aParams
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, sal_False
);
2634 sal_Bool bSaveTo
= pSaveToItem
? pSaveToItem
->GetValue() : sal_False
;
2636 const SfxFilter
* pFilter
= GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName
);
2638 || !pFilter
->CanExport()
2639 || (!bSaveTo
&& !pFilter
->CanImport()) )
2641 SetError( ERRCODE_IO_INVALIDPARAMETER
, OUString( OSL_LOG_PREFIX
) );
2645 SFX_ITEMSET_ARG( aParams
, pCopyStreamItem
, SfxBoolItem
, SID_COPY_STREAM_IF_POSSIBLE
, sal_False
);
2646 if ( bSaveTo
&& pCopyStreamItem
&& pCopyStreamItem
->GetValue() && !IsModified() )
2648 if ( pMedium
->TryDirectTransfer( aURL
.GetMainURL( INetURLObject::NO_DECODE
), *aParams
) )
2651 aParams
->ClearItem( SID_COPY_STREAM_IF_POSSIBLE
);
2653 pImp
->bPasswd
= aParams
&& SFX_ITEM_SET
== aParams
->GetItemState(SID_PASSWORD
);
2655 SfxMedium
*pActMed
= GetMedium();
2656 const INetURLObject
aActName(pActMed
->GetName());
2658 sal_Bool bWasReadonly
= IsReadOnly();
2660 if ( aURL
== aActName
&& aURL
!= INetURLObject( OUString("private:stream") )
2663 SetError(ERRCODE_SFX_DOCUMENTREADONLY
, OUString( OSL_LOG_PREFIX
));
2667 if( SFX_ITEM_SET
!= aParams
->GetItemState(SID_UNPACK
) && SvtSaveOptions().IsSaveUnpacked() )
2668 aParams
->Put( SfxBoolItem( SID_UNPACK
, sal_False
) );
2670 OUString aTempFileURL
;
2671 if ( IsDocShared() )
2672 aTempFileURL
= pMedium
->GetURLObject().GetMainURL( INetURLObject::NO_DECODE
);
2674 if ( PreDoSaveAs_Impl(aURL
.GetMainURL( INetURLObject::NO_DECODE
),aFilterName
,aParams
))
2676 // Update Data on media
2677 SfxItemSet
*pSet
= GetMedium()->GetItemSet();
2678 pSet
->ClearItem( SID_INTERACTIONHANDLER
);
2679 pSet
->ClearItem( SID_PROGRESS_STATUSBAR_CONTROL
);
2680 pSet
->ClearItem( SID_STANDARD_DIR
);
2681 pSet
->ClearItem( SID_PATH
);
2685 pSet
->ClearItem( SID_REFERER
);
2686 pSet
->ClearItem( SID_POSTDATA
);
2687 pSet
->ClearItem( SID_TEMPLATE
);
2688 pSet
->ClearItem( SID_DOC_READONLY
);
2689 pSet
->ClearItem( SID_CONTENTTYPE
);
2690 pSet
->ClearItem( SID_CHARSET
);
2691 pSet
->ClearItem( SID_FILTER_NAME
);
2692 pSet
->ClearItem( SID_OPTIONS
);
2693 pSet
->ClearItem( SID_VERSION
);
2694 pSet
->ClearItem( SID_EDITDOC
);
2695 pSet
->ClearItem( SID_OVERWRITE
);
2696 pSet
->ClearItem( SID_DEFAULTFILEPATH
);
2697 pSet
->ClearItem( SID_DEFAULTFILENAME
);
2699 SFX_ITEMSET_GET( (*aParams
), pFilterItem
, SfxStringItem
, SID_FILTER_NAME
, sal_False
);
2701 pSet
->Put( *pFilterItem
);
2703 SFX_ITEMSET_GET( (*aParams
), pOptionsItem
, SfxStringItem
, SID_OPTIONS
, sal_False
);
2705 pSet
->Put( *pOptionsItem
);
2707 SFX_ITEMSET_GET( (*aParams
), pFilterOptItem
, SfxStringItem
, SID_FILE_FILTEROPTIONS
, sal_False
);
2708 if ( pFilterOptItem
)
2709 pSet
->Put( *pFilterOptItem
);
2711 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2712 if ( IsDocShared() && !aTempFileURL
.isEmpty() )
2714 // this is a shared document that has to be disconnected from the old location
2715 FreeSharedFile( aTempFileURL
);
2717 if ( pFilter
->IsOwnFormat()
2718 && pFilter
->UsesStorage()
2719 && pFilter
->GetVersion() >= SOFFICE_FILEFORMAT_60
)
2721 // the target format is the own format
2722 // the target document must be shared
2723 SwitchToShared( sal_True
, sal_False
);
2729 if ( bWasReadonly
&& !bSaveTo
)
2730 Broadcast( SfxSimpleHint(SFX_HINT_MODECHANGED
) );
2738 //-------------------------------------------------------------------------
2740 sal_Bool
SfxObjectShell::PreDoSaveAs_Impl
2742 const String
& rFileName
,
2743 const String
& aFilterName
,
2747 // copy all items stored in the itemset of the current medium
2748 SfxAllItemSet
* pMergedParams
= new SfxAllItemSet( *pMedium
->GetItemSet() );
2750 // in "SaveAs" title and password will be cleared ( maybe the new itemset contains new values, otherwise they will be empty )
2751 pMergedParams
->ClearItem( SID_ENCRYPTIONDATA
);
2752 pMergedParams
->ClearItem( SID_PASSWORD
);
2753 // #i119366# - As the SID_ENCRYPTIONDATA and SID_PASSWORD are using for setting password together, we need to clear them both.
2754 // Also, ( maybe the new itemset contains new values, otherwise they will be empty )
2755 pMergedParams
->ClearItem( SID_ENCRYPTIONDATA
);
2756 pMergedParams
->ClearItem( SID_DOCINFO_TITLE
);
2758 pMergedParams
->ClearItem( SID_INPUTSTREAM
);
2759 pMergedParams
->ClearItem( SID_STREAM
);
2760 pMergedParams
->ClearItem( SID_CONTENT
);
2761 pMergedParams
->ClearItem( SID_DOC_READONLY
);
2762 pMergedParams
->ClearItem( SID_DOC_BASEURL
);
2764 pMergedParams
->ClearItem( SID_REPAIRPACKAGE
);
2766 // "SaveAs" will never store any version information - it's a complete new file !
2767 pMergedParams
->ClearItem( SID_VERSION
);
2769 // merge the new parameters into the copy
2770 // all values present in both itemsets will be overwritten by the new parameters
2772 pMergedParams
->Put( *pParams
);
2775 if ( pMergedParams
->GetItemState( SID_DOC_SALVAGE
) >= SFX_ITEM_SET
)
2776 OSL_FAIL("Salvage item present in Itemset, check the parameters!");
2779 // should be unneccessary - too hot to handle!
2780 pMergedParams
->ClearItem( SID_DOC_SALVAGE
);
2782 // take over the new merged itemset
2783 pParams
= pMergedParams
;
2785 // create a medium for the target URL
2786 SfxMedium
*pNewFile
= new SfxMedium( rFileName
, STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
| STREAM_TRUNC
, 0, pParams
);
2788 // set filter; if no filter is given, take the default filter of the factory
2789 if ( aFilterName
.Len() )
2790 pNewFile
->SetFilter( GetFactory().GetFilterContainer()->GetFilter4FilterName( aFilterName
) );
2792 pNewFile
->SetFilter( GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT
| SFX_FILTER_EXPORT
) );
2794 if ( pNewFile
->GetErrorCode() != ERRCODE_NONE
)
2796 // creating temporary file failed ( f.e. floppy disk not inserted! )
2797 SetError( pNewFile
->GetError(), OUString( OSL_LOG_PREFIX
) );
2802 // check if a "SaveTo" is wanted, no "SaveAs"
2803 SFX_ITEMSET_ARG( pParams
, pSaveToItem
, SfxBoolItem
, SID_SAVETO
, sal_False
);
2804 sal_Bool bCopyTo
= GetCreateMode() == SFX_CREATE_MODE_EMBEDDED
|| (pSaveToItem
&& pSaveToItem
->GetValue());
2806 // distinguish between "Save" and "SaveAs"
2807 pImp
->bIsSaving
= sal_False
;
2809 // copy version list from "old" medium to target medium, so it can be used on saving
2810 if ( pImp
->bPreserveVersions
)
2811 pNewFile
->TransferVersionList_Impl( *pMedium
);
2813 // Save the document ( first as temporary file, then transfer to the target URL by committing the medium )
2814 sal_Bool bOk
= sal_False
;
2815 if ( !pNewFile
->GetErrorCode() && SaveTo_Impl( *pNewFile
, NULL
) )
2819 // transfer a possible error from the medium to the document
2820 SetError( pNewFile
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2822 // notify the document that saving was done successfully
2825 bOk
= DoSaveCompleted( pNewFile
);
2828 bOk
= DoSaveCompleted(0);
2833 SetModified( sal_False
);
2837 // TODO/LATER: the code below must be dead since the storage commit makes all the stuff
2838 // and the DoSaveCompleted call should not be able to fail in general
2840 DBG_ASSERT( !bCopyTo
, "Error while reconnecting to medium, can't be handled!");
2841 SetError( pNewFile
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2845 // reconnect to the old medium
2846 sal_Bool
bRet( sal_False
);
2847 bRet
= DoSaveCompleted( pMedium
);
2848 DBG_ASSERT( bRet
, "Error in DoSaveCompleted, can't be handled!");
2852 // TODO/LATER: disconnect the new file from the storage for the case when pure saving is done
2853 // if storing has corrupted the file, probably it must be restored either here or
2855 DELETEZ( pNewFile
);
2860 SetError( pNewFile
->GetErrorCode(), OUString( OSL_LOG_PREFIX
) );
2862 // reconnect to the old storage
2863 DoSaveCompleted( 0 );
2865 DELETEZ( pNewFile
);
2869 DELETEZ( pNewFile
);
2871 SetModified( sal_True
);
2876 //------------------------------------------------------------------------
2878 sal_Bool
SfxObjectShell::LoadFrom( SfxMedium
& /*rMedium*/ )
2880 OSL_FAIL( "Base implementation, must not be called in general!" );
2884 //-------------------------------------------------------------------------
2885 sal_Bool
SfxObjectShell::IsInformationLost()
2887 Sequence
< PropertyValue
> aProps
= GetModel()->getArgs();
2888 OUString aFilterName
;
2889 OUString aPreusedFilterName
;
2890 for ( sal_Int32 nInd
= 0; nInd
< aProps
.getLength(); nInd
++ )
2892 if ( aProps
[nInd
].Name
== "FilterName" )
2893 aProps
[nInd
].Value
>>= aFilterName
;
2894 else if ( aProps
[nInd
].Name
== "PreusedFilterName" )
2895 aProps
[nInd
].Value
>>= aPreusedFilterName
;
2898 // if current filter can lead to information loss and it was used
2899 // for the latest store then the user should be asked to store in own format
2900 if ( !aFilterName
.isEmpty() && aFilterName
.equals( aPreusedFilterName
) )
2902 const SfxFilter
*pFilt
= GetMedium()->GetFilter();
2903 DBG_ASSERT( pFilt
&& aFilterName
.equals( pFilt
->GetName() ), "MediaDescriptor contains wrong filter!\n" );
2904 return ( pFilt
&& pFilt
->IsAlienFormat() );
2910 //-------------------------------------------------------------------------
2911 sal_Bool
SfxObjectShell::CanReload_Impl()
2915 Internal method for determining whether a reload of the document
2916 (as RevertToSaved or last known version) is possible.
2920 return pMedium
&& HasName() && !IsInModalMode() && !pImp
->bForbidReload
;
2923 //-------------------------------------------------------------------------
2925 sal_uInt16
SfxObjectShell::GetHiddenInformationState( sal_uInt16 nStates
)
2927 sal_uInt16 nState
= 0;
2928 if ( nStates
& HIDDENINFORMATION_DOCUMENTVERSIONS
)
2930 if ( GetMedium()->GetVersionList().getLength() )
2931 nState
|= HIDDENINFORMATION_DOCUMENTVERSIONS
;
2937 sal_Int16
SfxObjectShell::QueryHiddenInformation( HiddenWarningFact eFact
, Window
* pParent
)
2939 sal_Int16 nRet
= RET_YES
;
2940 sal_uInt16 nResId
= sal_uInt16();
2941 SvtSecurityOptions::EOption eOption
= SvtSecurityOptions::EOption();
2947 nResId
= STR_HIDDENINFO_CONTINUE_SAVING
;
2948 eOption
= SvtSecurityOptions::E_DOCWARN_SAVEORSEND
;
2953 nResId
= STR_HIDDENINFO_CONTINUE_PRINTING
;
2954 eOption
= SvtSecurityOptions::E_DOCWARN_PRINT
;
2959 nResId
= STR_HIDDENINFO_CONTINUE_SIGNING
;
2960 eOption
= SvtSecurityOptions::E_DOCWARN_SIGNING
;
2963 case WhenCreatingPDF
:
2965 nResId
= STR_HIDDENINFO_CONTINUE_CREATEPDF
;
2966 eOption
= SvtSecurityOptions::E_DOCWARN_CREATEPDF
;
2970 assert(false); // this cannot happen
2973 if ( SvtSecurityOptions().IsOptionSet( eOption
) )
2975 String
sMessage( SfxResId(STR_HIDDENINFO_CONTAINS
).toString() );
2976 sal_uInt16 nWantedStates
= HIDDENINFORMATION_RECORDEDCHANGES
| HIDDENINFORMATION_NOTES
;
2977 if ( eFact
!= WhenPrinting
)
2978 nWantedStates
|= HIDDENINFORMATION_DOCUMENTVERSIONS
;
2979 sal_uInt16 nStates
= GetHiddenInformationState( nWantedStates
);
2980 bool bWarning
= false;
2982 if ( ( nStates
& HIDDENINFORMATION_RECORDEDCHANGES
) == HIDDENINFORMATION_RECORDEDCHANGES
)
2984 sMessage
+= SfxResId(STR_HIDDENINFO_RECORDCHANGES
).toString();
2988 if ( ( nStates
& HIDDENINFORMATION_NOTES
) == HIDDENINFORMATION_NOTES
)
2990 sMessage
+= SfxResId(STR_HIDDENINFO_NOTES
).toString();
2994 if ( ( nStates
& HIDDENINFORMATION_DOCUMENTVERSIONS
) == HIDDENINFORMATION_DOCUMENTVERSIONS
)
2996 sMessage
+= SfxResId(STR_HIDDENINFO_DOCVERSIONS
).toString();
3004 sMessage
+= SfxResId(nResId
).toString();
3005 WarningBox
aWBox( pParent
, WB_YES_NO
| WB_DEF_NO
, sMessage
);
3006 nRet
= aWBox
.Execute();
3013 sal_Bool
SfxObjectShell::HasSecurityOptOpenReadOnly() const
3018 sal_Bool
SfxObjectShell::IsSecurityOptOpenReadOnly() const
3020 return IsLoadReadonly();
3023 void SfxObjectShell::SetSecurityOptOpenReadOnly( sal_Bool _b
)
3025 SetLoadReadonly( _b
);
3028 sal_Bool
SfxObjectShell::LoadOwnFormat( SfxMedium
& rMedium
)
3030 RTL_LOGFILE_PRODUCT_CONTEXT( aLog
, "PERFORMANCE SfxObjectShell::LoadOwnFormat" );
3031 if( RTL_LOGFILE_HASLOGFILE() )
3034 OUStringToOString(rMedium
.GetName(), RTL_TEXTENCODING_ASCII_US
));
3035 RTL_LOGFILE_PRODUCT_CONTEXT_TRACE1(aLog
, "loading \"%s\"", aString
.getStr());
3038 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3039 if ( xStorage
.is() )
3042 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pPasswdItem
, SfxStringItem
, SID_PASSWORD
, sal_False
);
3043 if ( pPasswdItem
|| ERRCODE_IO_ABORT
!= CheckPasswd_Impl( this, SFX_APP()->GetPool(), pMedium
) )
3045 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
3046 if ( GetEncryptionData_Impl(pMedium
->GetItemSet(), aEncryptionData
) )
3050 // the following code must throw an exception in case of failure
3051 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xStorage
, aEncryptionData
);
3053 catch( uno::Exception
& )
3055 // TODO/LATER: handle the error code
3060 return Load( rMedium
);
3068 sal_Bool
SfxObjectShell::SaveAsOwnFormat( SfxMedium
& rMedium
)
3070 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3073 sal_Int32 nVersion
= rMedium
.GetFilter()->GetVersion();
3075 // OASIS templates have own mediatypes ( SO7 also actually, but it is to late to use them here )
3076 sal_Bool bTemplate
= ( rMedium
.GetFilter()->IsOwnTemplateFormat() && nVersion
> SOFFICE_FILEFORMAT_60
);
3078 const SfxFilter
* pFilter
= rMedium
.GetFilter();
3079 bool bChart
= false;
3080 if(pFilter
->GetName() == OUString("chart8"))
3083 SetupStorage( xStorage
, nVersion
, bTemplate
, bChart
);
3084 #ifndef DISABLE_SCRIPTING
3090 // Save dialog/script container
3091 pImp
->pBasicManager
->storeLibrariesToStorage( xStorage
);
3094 return SaveAs( rMedium
);
3096 else return sal_False
;
3099 uno::Reference
< embed::XStorage
> SfxObjectShell::GetStorage()
3101 if ( !pImp
->m_xDocStorage
.is() )
3103 OSL_ENSURE( pImp
->m_bCreateTempStor
, "The storage must exist already!\n" );
3105 // no notification is required the storage is set the first time
3106 pImp
->m_xDocStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3107 OSL_ENSURE( pImp
->m_xDocStorage
.is(), "The method must either return storage or throw an exception!" );
3109 SetupStorage( pImp
->m_xDocStorage
, SOFFICE_FILEFORMAT_CURRENT
, sal_False
, false );
3110 pImp
->m_bCreateTempStor
= sal_False
;
3111 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED
, GlobalEventConfig::GetEventName(STR_EVENT_STORAGECHANGED
), this ) );
3113 catch( uno::Exception
& )
3115 // TODO/LATER: error handling?
3116 DBG_UNHANDLED_EXCEPTION();
3120 OSL_ENSURE( pImp
->m_xDocStorage
.is(), "The document storage must be created!" );
3121 return pImp
->m_xDocStorage
;
3125 sal_Bool
SfxObjectShell::SaveChildren( sal_Bool bObjectsOnly
)
3127 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveChildren" );
3129 sal_Bool bResult
= sal_True
;
3130 if ( pImp
->mpObjectContainer
)
3132 sal_Bool bOasis
= ( SotStorage::GetVersion( GetStorage() ) > SOFFICE_FILEFORMAT_60
);
3133 GetEmbeddedObjectContainer().StoreChildren(bOasis
,bObjectsOnly
);
3139 sal_Bool
SfxObjectShell::SaveAsChildren( SfxMedium
& rMedium
)
3141 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveAsChildren" );
3143 sal_Bool bResult
= sal_True
;
3145 uno::Reference
< embed::XStorage
> xStorage
= rMedium
.GetStorage();
3146 if ( !xStorage
.is() )
3149 if ( xStorage
== GetStorage() )
3150 return SaveChildren();
3152 sal_Bool bOasis
= sal_True
;
3153 if ( pImp
->mpObjectContainer
)
3155 bOasis
= ( SotStorage::GetVersion( xStorage
) > SOFFICE_FILEFORMAT_60
);
3156 GetEmbeddedObjectContainer().StoreAsChildren(bOasis
,SFX_CREATE_MODE_EMBEDDED
== eCreateMode
,xStorage
);
3160 bResult
= CopyStoragesOfUnknownMediaType( GetStorage(), xStorage
);
3165 sal_Bool
SfxObjectShell::SaveCompletedChildren( sal_Bool bSuccess
)
3167 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveCompletedChildren" );
3169 sal_Bool bResult
= sal_True
;
3171 if ( pImp
->mpObjectContainer
)
3173 uno::Sequence
< OUString
> aNames
= GetEmbeddedObjectContainer().GetObjectNames();
3174 for ( sal_Int32 n
=0; n
<aNames
.getLength(); n
++ )
3176 uno::Reference
< embed::XEmbeddedObject
> xObj
= GetEmbeddedObjectContainer().GetEmbeddedObject( aNames
[n
] );
3177 OSL_ENSURE( xObj
.is(), "An empty entry in the embedded objects list!\n" );
3180 uno::Reference
< embed::XEmbedPersist
> xPersist( xObj
, uno::UNO_QUERY
);
3181 if ( xPersist
.is() )
3185 xPersist
->saveCompleted( bSuccess
);
3187 catch( uno::Exception
& )
3189 // TODO/LATER: error handling
3190 bResult
= sal_False
;
3201 sal_Bool
SfxObjectShell::SwitchChildrenPersistance( const uno::Reference
< embed::XStorage
>& xStorage
,
3202 sal_Bool bForceNonModified
)
3204 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SwitchChildrenPersistence" );
3206 if ( !xStorage
.is() )
3208 // TODO/LATER: error handling
3212 sal_Bool bResult
= sal_True
;
3214 if ( pImp
->mpObjectContainer
)
3215 pImp
->mpObjectContainer
->SetPersistentEntries(xStorage
,bForceNonModified
);
3220 // Never call this method directly, always use the DoSaveCompleted call
3221 sal_Bool
SfxObjectShell::SaveCompleted( const uno::Reference
< embed::XStorage
>& xStorage
)
3223 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SaveCompleted" );
3225 sal_Bool bResult
= sal_False
;
3226 sal_Bool bSendNotification
= sal_False
;
3227 uno::Reference
< embed::XStorage
> xOldStorageHolder
;
3230 // check for wrong creation of object container
3231 sal_Bool bHasContainer
= ( pImp
->mpObjectContainer
!= 0 );
3234 if ( !xStorage
.is() || xStorage
== GetStorage() )
3236 // no persistence change
3237 bResult
= SaveCompletedChildren( sal_False
);
3241 if ( pImp
->mpObjectContainer
)
3242 GetEmbeddedObjectContainer().SwitchPersistence( xStorage
);
3244 bResult
= SwitchChildrenPersistance( xStorage
, sal_True
);
3249 if ( xStorage
.is() && pImp
->m_xDocStorage
!= xStorage
)
3251 // make sure that until the storage is assigned the object
3252 // container is not created by accident!
3253 DBG_ASSERT( bHasContainer
== (pImp
->mpObjectContainer
!= 0), "Wrong storage in object container!" );
3254 xOldStorageHolder
= pImp
->m_xDocStorage
;
3255 pImp
->m_xDocStorage
= xStorage
;
3256 bSendNotification
= sal_True
;
3258 if ( IsEnableSetModified() )
3259 SetModified( sal_False
);
3264 if ( pImp
->mpObjectContainer
)
3265 GetEmbeddedObjectContainer().SwitchPersistence( pImp
->m_xDocStorage
);
3267 // let already successfully connected objects be switched back
3268 SwitchChildrenPersistance( pImp
->m_xDocStorage
, sal_True
);
3271 if ( bSendNotification
)
3273 SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_STORAGECHANGED
, GlobalEventConfig::GetEventName(STR_EVENT_STORAGECHANGED
), this ) );
3279 #if OSL_DEBUG_LEVEL > 0
3280 sal_Bool
StoragesOfUnknownMediaTypeAreCopied_Impl( const uno::Reference
< embed::XStorage
>& xSource
,
3281 const uno::Reference
< embed::XStorage
>& xTarget
)
3283 OSL_ENSURE( xSource
.is() && xTarget
.is(), "Source and/or target storages are not available!\n" );
3284 if ( !xSource
.is() || !xTarget
.is() || xSource
== xTarget
)
3289 uno::Sequence
< OUString
> aSubElements
= xSource
->getElementNames();
3290 for ( sal_Int32 nInd
= 0; nInd
< aSubElements
.getLength(); nInd
++ )
3292 if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3294 OUString aMediaType
;
3295 OUString
aMediaTypePropName( "MediaType" );
3296 sal_Bool bGotMediaType
= sal_False
;
3300 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xSource
, uno::UNO_QUERY_THROW
);
3302 ( xOptStorage
->getElementPropertyValue( aSubElements
[nInd
], aMediaTypePropName
) >>= aMediaType
);
3304 catch( uno::Exception
& )
3307 if ( !bGotMediaType
)
3309 uno::Reference
< embed::XStorage
> xSubStorage
;
3311 xSubStorage
= xSource
->openStorageElement( aSubElements
[nInd
], embed::ElementModes::READ
);
3312 } catch( uno::Exception
& )
3315 if ( !xSubStorage
.is() )
3317 xSubStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3318 xSource
->copyStorageElementLastCommitTo( aSubElements
[nInd
], xSubStorage
);
3321 uno::Reference
< beans::XPropertySet
> xProps( xSubStorage
, uno::UNO_QUERY_THROW
);
3322 bGotMediaType
= ( xProps
->getPropertyValue( aMediaTypePropName
) >>= aMediaType
);
3325 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3326 // probably it should be placed in the MimeType-ClassID table or in standalone table
3327 if ( !aMediaType
.isEmpty()
3328 && aMediaType
.compareToAscii( "application/vnd.sun.star.oleobject" ) != COMPARE_EQUAL
)
3330 ::com::sun::star::datatransfer::DataFlavor aDataFlavor
;
3331 aDataFlavor
.MimeType
= aMediaType
;
3332 sal_uInt32 nFormat
= SotExchange::GetFormat( aDataFlavor
);
3336 case SOT_FORMATSTR_ID_STARWRITER_60
:
3337 case SOT_FORMATSTR_ID_STARWRITERWEB_60
:
3338 case SOT_FORMATSTR_ID_STARWRITERGLOB_60
:
3339 case SOT_FORMATSTR_ID_STARDRAW_60
:
3340 case SOT_FORMATSTR_ID_STARIMPRESS_60
:
3341 case SOT_FORMATSTR_ID_STARCALC_60
:
3342 case SOT_FORMATSTR_ID_STARCHART_60
:
3343 case SOT_FORMATSTR_ID_STARMATH_60
:
3344 case SOT_FORMATSTR_ID_STARWRITER_8
:
3345 case SOT_FORMATSTR_ID_STARWRITERWEB_8
:
3346 case SOT_FORMATSTR_ID_STARWRITERGLOB_8
:
3347 case SOT_FORMATSTR_ID_STARDRAW_8
:
3348 case SOT_FORMATSTR_ID_STARIMPRESS_8
:
3349 case SOT_FORMATSTR_ID_STARCALC_8
:
3350 case SOT_FORMATSTR_ID_STARCHART_8
:
3351 case SOT_FORMATSTR_ID_STARMATH_8
:
3356 if ( !xTarget
->hasByName( aSubElements
[nInd
] ) )
3364 catch( uno::Exception
& )
3366 OSL_FAIL( "Cant check storage consistency!\n" );
3373 sal_Bool
SfxObjectShell::SwitchPersistance( const uno::Reference
< embed::XStorage
>& xStorage
)
3375 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::SwitchPersistance" );
3377 sal_Bool bResult
= sal_False
;
3379 // check for wrong creation of object container
3380 sal_Bool bHasContainer
= ( pImp
->mpObjectContainer
!= 0 );
3382 if ( xStorage
.is() )
3384 if ( pImp
->mpObjectContainer
)
3385 GetEmbeddedObjectContainer().SwitchPersistence( xStorage
);
3386 bResult
= SwitchChildrenPersistance( xStorage
);
3388 // TODO/LATER: substorages that have unknown mimetypes probably should be copied to the target storage here
3389 OSL_ENSURE( StoragesOfUnknownMediaTypeAreCopied_Impl( pImp
->m_xDocStorage
, xStorage
),
3390 "Some of substorages with unknown mimetypes is lost!" );
3395 // make sure that until the storage is assigned the object container is not created by accident!
3396 DBG_ASSERT( bHasContainer
== (pImp
->mpObjectContainer
!= 0), "Wrong storage in object container!" );
3397 if ( pImp
->m_xDocStorage
!= xStorage
)
3398 DoSaveCompleted( new SfxMedium( xStorage
, GetMedium()->GetBaseURL() ) );
3400 if ( IsEnableSetModified() )
3401 SetModified( sal_True
); // ???
3407 sal_Bool
SfxObjectShell::CopyStoragesOfUnknownMediaType( const uno::Reference
< embed::XStorage
>& xSource
,
3408 const uno::Reference
< embed::XStorage
>& xTarget
)
3410 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::CopyStoragesOfUnknownMediaType" );
3412 // This method does not commit the target storage and should not do it
3413 sal_Bool bResult
= sal_True
;
3417 uno::Sequence
< OUString
> aSubElements
= xSource
->getElementNames();
3418 for ( sal_Int32 nInd
= 0; nInd
< aSubElements
.getLength(); nInd
++ )
3420 if ( aSubElements
[nInd
] == "Configurations" )
3422 // The workaround for compatibility with SO7, "Configurations" substorage must be preserved
3423 if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3425 OSL_ENSURE( !xTarget
->hasByName( aSubElements
[nInd
] ),
3426 "The target storage is an output storage, the element should not exist in the target!\n" );
3428 xSource
->copyElementTo( aSubElements
[nInd
], xTarget
, aSubElements
[nInd
] );
3431 else if ( xSource
->isStorageElement( aSubElements
[nInd
] ) )
3433 OUString aMediaType
;
3434 OUString
aMediaTypePropName( "MediaType" );
3435 sal_Bool bGotMediaType
= sal_False
;
3439 uno::Reference
< embed::XOptimizedStorage
> xOptStorage( xSource
, uno::UNO_QUERY_THROW
);
3441 ( xOptStorage
->getElementPropertyValue( aSubElements
[nInd
], aMediaTypePropName
) >>= aMediaType
);
3443 catch( uno::Exception
& )
3446 if ( !bGotMediaType
)
3448 uno::Reference
< embed::XStorage
> xSubStorage
;
3450 xSubStorage
= xSource
->openStorageElement( aSubElements
[nInd
], embed::ElementModes::READ
);
3451 } catch( uno::Exception
& )
3454 if ( !xSubStorage
.is() )
3456 // TODO/LATER: as optimization in future a substorage of target storage could be used
3457 // instead of the temporary storage; this substorage should be removed later
3458 // if the MimeType is wrong
3459 xSubStorage
= ::comphelper::OStorageHelper::GetTemporaryStorage();
3460 xSource
->copyStorageElementLastCommitTo( aSubElements
[nInd
], xSubStorage
);
3463 uno::Reference
< beans::XPropertySet
> xProps( xSubStorage
, uno::UNO_QUERY_THROW
);
3464 bGotMediaType
= ( xProps
->getPropertyValue( aMediaTypePropName
) >>= aMediaType
);
3467 // TODO/LATER: there should be a way to detect whether an object with such a MediaType can exist
3468 // probably it should be placed in the MimeType-ClassID table or in standalone table
3469 if ( !aMediaType
.isEmpty()
3470 && aMediaType
.compareToAscii( "application/vnd.sun.star.oleobject" ) != COMPARE_EQUAL
)
3472 ::com::sun::star::datatransfer::DataFlavor aDataFlavor
;
3473 aDataFlavor
.MimeType
= aMediaType
;
3474 sal_uInt32 nFormat
= SotExchange::GetFormat( aDataFlavor
);
3478 case SOT_FORMATSTR_ID_STARWRITER_60
:
3479 case SOT_FORMATSTR_ID_STARWRITERWEB_60
:
3480 case SOT_FORMATSTR_ID_STARWRITERGLOB_60
:
3481 case SOT_FORMATSTR_ID_STARDRAW_60
:
3482 case SOT_FORMATSTR_ID_STARIMPRESS_60
:
3483 case SOT_FORMATSTR_ID_STARCALC_60
:
3484 case SOT_FORMATSTR_ID_STARCHART_60
:
3485 case SOT_FORMATSTR_ID_STARMATH_60
:
3486 case SOT_FORMATSTR_ID_STARWRITER_8
:
3487 case SOT_FORMATSTR_ID_STARWRITERWEB_8
:
3488 case SOT_FORMATSTR_ID_STARWRITERGLOB_8
:
3489 case SOT_FORMATSTR_ID_STARDRAW_8
:
3490 case SOT_FORMATSTR_ID_STARIMPRESS_8
:
3491 case SOT_FORMATSTR_ID_STARCALC_8
:
3492 case SOT_FORMATSTR_ID_STARCHART_8
:
3493 case SOT_FORMATSTR_ID_STARMATH_8
:
3498 OSL_ENSURE( aSubElements
[nInd
] == "Configurations2" || !xTarget
->hasByName( aSubElements
[nInd
] ),
3499 "The target storage is an output storage, the element should not exist in the target!\n" );
3501 if ( !xTarget
->hasByName( aSubElements
[nInd
] ) )
3503 xSource
->copyElementTo( aSubElements
[nInd
], xTarget
, aSubElements
[nInd
] );
3511 catch( uno::Exception
& )
3513 bResult
= sal_False
;
3514 // TODO/LATER: a specific error could be provided
3520 sal_Bool
SfxObjectShell::GenerateAndStoreThumbnail( sal_Bool bEncrypted
,
3522 sal_Bool bIsTemplate
,
3523 const uno::Reference
< embed::XStorage
>& xStor
)
3525 RTL_LOGFILE_CONTEXT( aLog
, "sfx2 (mv76033) SfxObjectShell::GenerateAndStoreThumbnail" );
3527 sal_Bool bResult
= sal_False
;
3530 uno::Reference
< embed::XStorage
> xThumbnailStor
=
3531 xStor
->openStorageElement( OUString("Thumbnails"),
3532 embed::ElementModes::READWRITE
);
3533 if ( xThumbnailStor
.is() )
3535 uno::Reference
< io::XStream
> xStream
= xThumbnailStor
->openStreamElement(
3536 OUString("thumbnail.png"),
3537 embed::ElementModes::READWRITE
);
3539 if ( xStream
.is() && WriteThumbnail( bEncrypted
, bSigned
, bIsTemplate
, xStream
) )
3541 uno::Reference
< embed::XTransactedObject
> xTransact( xThumbnailStor
, uno::UNO_QUERY_THROW
);
3542 xTransact
->commit();
3547 catch( uno::Exception
& )
3554 sal_Bool
SfxObjectShell::WriteThumbnail( sal_Bool bEncrypted
,
3556 sal_Bool bIsTemplate
,
3557 const uno::Reference
< io::XStream
>& xStream
)
3559 sal_Bool bResult
= sal_False
;
3564 uno::Reference
< io::XTruncate
> xTruncate( xStream
->getOutputStream(), uno::UNO_QUERY_THROW
);
3565 xTruncate
->truncate();
3567 uno::Reference
< beans::XPropertySet
> xSet( xStream
, uno::UNO_QUERY
);
3569 xSet
->setPropertyValue( OUString("MediaType"),
3570 uno::makeAny( OUString("image/png") ) );
3573 sal_uInt16 nResID
= GraphicHelper::getThumbnailReplacementIDByFactoryName_Impl(
3574 OUString::createFromAscii( GetFactory().GetShortName() ),
3580 bResult
= GraphicHelper::getThumbnailReplacement_Impl( nResID
, xStream
);
3584 // retrieve the bitmap and write a signature bitmap over it
3585 SfxResId
aResId( nResID
);
3586 BitmapEx
aThumbBitmap( aResId
);
3587 bResult
= GraphicHelper::getSignedThumbnailFormatFromBitmap_Impl( aThumbBitmap
, xStream
);
3593 ::boost::shared_ptr
<GDIMetaFile
> pMetaFile
=
3594 GetPreviewMetaFile( sal_False
);
3597 bResult
= GraphicHelper::getThumbnailFormatFromGDI_Impl(
3598 pMetaFile
.get(), bSigned
, xStream
);
3602 catch( uno::Exception
& )
3609 void SfxObjectShell::UpdateLinks()
3613 bool SfxObjectShell::LoadExternal( SfxMedium
& )
3615 // Not implemented. It's an error if the code path ever comes here.
3619 void SfxObjectShell::CheckConfigOptions()
3621 // not handled. Each app's shell needs to overwrite this method to add handler.
3622 SetConfigOptionsChecked(true);
3625 sal_Bool
SfxObjectShell::IsConfigOptionsChecked() const
3627 return pImp
->m_bConfigOptionsChecked
;
3630 void SfxObjectShell::SetConfigOptionsChecked( sal_Bool bChecked
)
3632 pImp
->m_bConfigOptionsChecked
= bChecked
;
3635 sal_Bool
SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference
< task::XInteractionHandler
>& xHandler
)
3637 #ifdef DISABLE_SCRIPTING
3643 if ( !pImp
->pBasicManager
->isValid() )
3645 uno::Sequence
< OUString
> sModules
;
3646 if ( xHandler
.is() )
3648 if( pImp
->pBasicManager
->LegacyPsswdBinaryLimitExceeded( sModules
) )
3650 ModuleSizeExceeded
* pReq
= new ModuleSizeExceeded( sModules
);
3651 uno::Reference
< task::XInteractionRequest
> xReq( pReq
);
3652 xHandler
->handle( xReq
);
3653 return pReq
->isApprove();
3657 // No interaction handler, default is to continue to save
3660 // -----------------------------------------------------------------------------
3661 uno::Reference
< task::XInteractionHandler
> SfxObjectShell::getInteractionHandler() const
3663 uno::Reference
< task::XInteractionHandler
> xRet
;
3665 xRet
= GetMedium()->GetInteractionHandler();
3669 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */