[Libreoffice-commits] .: Branch 'libreoffice-3-3' - patches/dev300
Tor Lillqvist
tml at kemper.freedesktop.org
Wed Feb 16 18:14:23 PST 2011
patches/dev300/apply | 26
patches/dev300/cws-mav58.diff | 2195 ++++++++
patches/dev300/sfx2-pre-and-postprocess-during-save-load-after-mav58.diff | 63
patches/dev300/webdav-locking-after-mav58.diff | 86
patches/dev300/webdav-locking.diff | 2615 ----------
5 files changed, 2355 insertions(+), 2630 deletions(-)
New commits:
commit 683a11216cc2885a2bd345b2d90de2a9cd97d7ab
Author: Tor Lillqvist <tlillqvist at novell.com>
Date: Thu Feb 10 20:12:30 2011 +0200
Work on WebDAV locking
The code already contains the ucb part (from OOo), and it mostly seems
to work fine.
But, the sfx2 part is missing. OOo is working on that in the CWS
mav58. Introduce the code from that in cws-mav58.diff, an extract of
that CWS, modified to apply.
The old webdav-locking.diff can thus finally be retired, good
riddance.
Re-insert the sfx2 pre and postprocessing code for saving into the
code as now modified by cws-mav58.diff.
The Apache server handling the Novell Innerweb Vibe OnPrem service
(formerly known as "Teaming") decreases the WebDAV timeout granted by
one second from what was requested each time a lock is granted or
refreshed.
As we start with a requested timeout of 180 seconds, and refresh the
lock always 30 seconds before it is about to expire, this means that
after about 150*180 seconds (7.5 hours) the timeout would reach zero
and locking would break. Which is likely to happen, as people might
well keep a document open in LibreOffice for the whole day.
Avoid this by not reducing the timeout requested next time even if the
server granted a slightly shorter timeout than what we asked for.
There are still problems. The most obvious one is that after saving a
document into WebDAV once, it no longer is locked... Somehow the code
seems to forget the authentication to use, but only for lock requests,
huh? Possibly it needlessly tears down the WebDAV session completely
after saving the document. Further debugging needed. Should
investigate why it can't just keep the same session live for the same
document.
Build neon with debugging printout capability, and ask for neon
debugging printout in the webdav UCP if built with debug=t.
diff --git a/patches/dev300/apply b/patches/dev300/apply
old mode 100755
new mode 100644
index c47179f..a563f0b
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -406,20 +406,6 @@ cws-webdavandgvfslocking1-tools.diff
cws-webdavandgvfslocking1-ucb.diff
cws-webdavandgvfslocking1-unotools.diff
-[ WebDAV ]
-SectionOwner => tml
-SectionIssue => i#29152
-
-# Rework of the webdav-locking-from-ooo-build-2-4-1.diff, combined
-# with webdav-locking-local-temp-file.diff. Even seems to work, just
-# that saving is quite slow (at least against Novell Teaming) with
-# lots of odd things going on (as can be seen if one builds the webdav
-# ucp with debug=true). But it was like that in 3.1.1, too. I
-# definitely don't think it makes sense to attempt to upstream this
-# any longer, as I don't really understand the code, and it probably
-# works by now just by accident.
-# FIXME dev300-m77 webdav-locking.diff, i#29152, bnc#440514, tml # FIXME check that we lost nothing
-
[ GnomeVFS ]
# gnome-vfs locking implementation
# it was not committed up-stream yet because up-stream uses so old gnome-vfs
@@ -1384,7 +1370,17 @@ vba-import-xlsm.diff
[ Features ]
# Pre- and postprocessing capabilities for loading and saving.
-sfx2-pre-and-postprocess-during-save-load.diff, i#71939, florian
+sfx2-pre-and-postprocess-during-save-load.diff, i#71939, flr
+
+
+[ WebDAV ]
+SectionOwner => tml
+SectionIssue => bnc#651977
+
+cws-mav58.diff, bnc#651977, tml
+webdav-locking-after-mav58.diff, tml
+sfx2-pre-and-postprocess-during-save-load-after-mav58.diff, i#71939, flr
+
[ msaccess ]
SectionOwner => strba
diff --git a/patches/dev300/cws-mav58.diff b/patches/dev300/cws-mav58.diff
new file mode 100644
index 0000000..8197aaf
--- /dev/null
+++ b/patches/dev300/cws-mav58.diff
@@ -0,0 +1,2195 @@
+--- sfx2/source/doc/makefile.mk
++++ sfx2/source/doc/makefile.mk
+@@ -200,6 +200,7 @@
+ $(SLO)$/doctdlg.obj \
+ $(SLO)$/sfxbasemodel.obj \
+ $(SLO)$/guisaveas.obj\
++ $(SLO)$/mediumstorholder.obj\
+ $(SLO)$/objembed.obj\
+ $(SLO)$/graphhelp.obj \
+ $(SLO)$/QuerySaveDocument.obj \
+--- sfx2/inc/sfx2/docfile.hxx
++++ sfx2/inc/sfx2/docfile.hxx
+@@ -211,6 +211,7 @@
+ sal_Bool IsStorage();
+
+ sal_Int8 ShowLockedDocumentDialog( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading, sal_Bool bOwnLock );
++ sal_Int8 LockIterationImpl( sal_Bool bHandleSysLocked, sal_Bool bUseSystemLock, sal_Bool bLoading, sal_Bool bNoUI );
+ sal_Bool LockOrigFileOnDemand( sal_Bool bLoading, sal_Bool bNoUI );
+ void UnlockFile( sal_Bool bReleaseLockStream );
+
+--- sfx2/inc/sfx2/objsh.hxx
++++ sfx2/inc/sfx2/objsh.hxx
+@@ -712,9 +712,8 @@
+
+ SAL_DLLPRIVATE ::boost::shared_ptr<GDIMetaFile> CreatePreviewMetaFile_Impl( sal_Bool bFullContent, sal_Bool bHighContrast ) const;
+
+- SAL_DLLPRIVATE sal_Bool IsOwnStorageFormat_Impl(const SfxMedium &) const;
+-
+- SAL_DLLPRIVATE sal_Bool IsPackageStorageFormat_Impl(const SfxMedium &) const;
++ SAL_DLLPRIVATE static sal_Bool IsOwnStorageFormat_Impl(const SfxMedium &);
++ SAL_DLLPRIVATE static sal_Bool IsPackageStorageFormat_Impl(const SfxMedium &);
+
+ SAL_DLLPRIVATE sal_Bool ConnectTmpStorage_Impl( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage, SfxMedium* pMedium );
+ SAL_DLLPRIVATE sal_Bool DisconnectStorage_Impl( SfxMedium& rSrcMedium, SfxMedium& rTargetMedium );
+@@ -770,13 +769,16 @@
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aMediaDescr );
+ SAL_DLLPRIVATE void PositionView_Impl();
+ SAL_DLLPRIVATE void UpdateFromTemplate_Impl();
+- SAL_DLLPRIVATE sal_Bool CanReload_Impl();
++ SAL_DLLPRIVATE bool ForbidReload_Impl( bool bForbid );
++ SAL_DLLPRIVATE bool CanReload_Impl();
+ SAL_DLLPRIVATE void SetNamedVisibility_Impl();
+ SAL_DLLPRIVATE sal_Bool DoSave_Impl( const SfxItemSet* pSet=0 );
+ SAL_DLLPRIVATE sal_Bool Save_Impl( const SfxItemSet* pSet=0 );
+ SAL_DLLPRIVATE sal_Bool PreDoSaveAs_Impl(const String &rFileName, const String &rFiltName, SfxItemSet *);
+ SAL_DLLPRIVATE sal_Bool APISaveAs_Impl ( const String& aFileName, SfxItemSet* aParams );
+ SAL_DLLPRIVATE sal_Bool CommonSaveAs_Impl ( const INetURLObject& aURL, const String& aFilterName, SfxItemSet* aParams );
++ SAL_DLLPRIVATE bool IsSaving_Impl();
++ SAL_DLLPRIVATE bool PreserveVersions_Impl();
+ SAL_DLLPRIVATE sal_Bool GeneralInit_Impl(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage,
+ sal_Bool bTypeMustBeSetAlready );
+--- sfx2/source/doc/docfile.cxx
++++ sfx2/source/doc/docfile.cxx
+@@ -49,6 +49,7 @@
+ #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
+ #include <com/sun/star/ucb/CommandFailedException.hpp>
+ #include <com/sun/star/ucb/CommandAbortedException.hpp>
++#include <com/sun/star/ucb/InteractiveLockingLockedException.hpp>
+ #include <com/sun/star/ucb/XCommandEnvironment.hpp>
+ #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
+ #include <com/sun/star/ucb/XContentProvider.hpp>
+@@ -278,7 +279,8 @@
+ sal_Bool bStorageBasedOnInStream: 1;
+ sal_Bool m_bSalvageMode: 1;
+ sal_Bool m_bVersionsAlreadyLoaded: 1;
+- sal_Bool m_bLocked: 1;
++ sal_Bool m_bOwnLockSet: 1;
++ sal_Bool m_bUCBLockSet: 1;
+ sal_Bool m_bGotDateTime: 1;
+
+ uno::Reference < embed::XStorage > xStorage;
+@@ -355,7 +357,8 @@
+ bStorageBasedOnInStream( sal_False ),
+ m_bSalvageMode( sal_False ),
+ m_bVersionsAlreadyLoaded( sal_False ),
+- m_bLocked( sal_False ),
++ m_bOwnLockSet( sal_False ),
++ m_bUCBLockSet( sal_False ),
+ m_bGotDateTime( sal_False ),
+ pAntiImpl( pAntiImplP ),
+ nFileVersion( 0 ),
+@@ -1018,23 +1021,142 @@
+ }
+
+ //------------------------------------------------------------------
++sal_Int8 SfxMedium::LockIterationImpl( sal_Bool bHandleSysLocked, sal_Bool bUseSystemLock, sal_Bool bLoading, sal_Bool bNoUI )
++{
++ sal_Int8 nResult = LOCK_UI_NOLOCK;
++ try
++ {
++ ::svt::DocumentLockFile aLockFile( aLogicName );
++ if ( !bHandleSysLocked )
++ {
++ try
++ {
++ if ( aLockFile.CreateOwnLockFile() )
++ nResult = LOCK_UI_SUCCEEDED;
++ }
++ catch ( ucb::InteractiveIOException& e )
++ {
++ // exception means that the lock file can not be successfuly accessed
++ // in this case it should be ignored if system file locking is anyway active
++ if ( bUseSystemLock || !IsOOoLockFileUsed() )
++ {
++ nResult = LOCK_UI_SUCCEEDED;
++ // take the ownership over the lock file
++ aLockFile.OverwriteOwnLockFile();
++ }
++ else if ( e.Code == IOErrorCode_INVALID_PARAMETER )
++ {
++ // system file locking is not active, ask user whether he wants to open the document without any locking
++ uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
++
++ if ( xHandler.is() )
++ {
++ ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
++ = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
++
++ uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
++ aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
++ aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
++ xIgnoreRequestImpl->setContinuations( aContinuations );
++
++ xHandler->handle( xIgnoreRequestImpl.get() );
++
++ ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
++ if ( uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is() )
++ nResult = LOCK_UI_SUCCEEDED;
++ }
++ }
++ }
++ catch ( uno::Exception& )
++ {
++ // exception means that the lock file can not be successfuly accessed
++ // in this case it should be ignored if system file locking is anyway active
++ if ( bUseSystemLock || !IsOOoLockFileUsed() )
++ {
++ nResult = LOCK_UI_SUCCEEDED;
++ // take the ownership over the lock file
++ aLockFile.OverwriteOwnLockFile();
++ }
++ }
++
++ // in case OOo locking is turned off the lock file is still written if possible
++ // but it is ignored while deciding whether the document should be opened for editing or not
++ if ( nResult != LOCK_UI_SUCCEEDED && !IsOOoLockFileUsed() )
++ {
++ nResult = LOCK_UI_SUCCEEDED;
++ // take the ownership over the lock file
++ aLockFile.OverwriteOwnLockFile();
++ }
++ }
++
++
++ if ( nResult != LOCK_UI_SUCCEEDED )
++ {
++ uno::Sequence< ::rtl::OUString > aData;
++ try
++ {
++ // impossibility to get data is no real problem
++ aData = aLockFile.GetLockData();
++ }
++ catch( uno::Exception ) {}
++
++ sal_Bool bOwnLock = sal_False;
++
++ if ( !bHandleSysLocked )
++ {
++ uno::Sequence< ::rtl::OUString > aOwnData = aLockFile.GenerateOwnEntry();
++ bOwnLock = ( aData.getLength() > LOCKFILE_USERURL_ID
++ && aOwnData.getLength() > LOCKFILE_USERURL_ID
++ && aOwnData[LOCKFILE_SYSUSERNAME_ID].equals( aData[LOCKFILE_SYSUSERNAME_ID] ) );
++
++ if ( bOwnLock
++ && aOwnData[LOCKFILE_LOCALHOST_ID].equals( aData[LOCKFILE_LOCALHOST_ID] )
++ && aOwnData[LOCKFILE_USERURL_ID].equals( aData[LOCKFILE_USERURL_ID] ) )
++ {
++ // this is own lock from the same installation, it could remain because of crash
++ nResult = LOCK_UI_SUCCEEDED;
++ }
++ }
++
++ if ( nResult != LOCK_UI_SUCCEEDED && !bNoUI )
++ {
++ sal_Int8 nUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock );
++ if ( nUIStatus == LOCK_UI_SUCCEEDED )
++ {
++ // take the ownership over the lock file
++ if ( aLockFile.OverwriteOwnLockFile() )
++ nResult = nUIStatus;
++ }
++ else
++ nResult = nUIStatus;
++ }
++ }
++ }
++ catch( uno::Exception& )
++ {
++ }
++
++ return nResult;
++}
++
++//------------------------------------------------------------------
+ sal_Bool SfxMedium::LockOrigFileOnDemand( sal_Bool bLoading, sal_Bool bNoUI )
+ {
+ // returns true if the document can be opened for editing ( even if it should be a copy )
+ // otherwise the document should be opened readonly
+ // if user cancel the loading the ERROR_ABORT is set
+ sal_Bool bResult = sal_False;
+
+ if ( !GetURLObject().HasError() ) try
+ {
+- if ( pImp->m_bLocked && bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
++ if ( pImp->m_bOwnLockSet && bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ // if the document is already locked the system locking might be temporarely off after storing
+ // check whether the system file locking should be taken again
+ GetLockingStream_Impl();
+ }
+
+- sal_Bool bResult = pImp->m_bLocked;
++ bResult = pImp->m_bOwnLockSet || pImp->m_bUCBLockSet;
+
+ if ( !bResult )
+ {
+@@ -1043,6 +1168,9 @@
+ if ( !bResult && !IsReadOnly() )
+ {
+ sal_Bool bContentReadonly = sal_False;
++ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
++ ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
++
+ if ( bLoading && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
+ {
+ // let the original document be opened to check the possibility to open it for editing
+@@ -1058,8 +1186,6 @@
+ try
+ {
+ // MediaDescriptor does this check also, the duplication should be avoided in future
+- Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
+- ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
+ aContent.getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ) ) >>= bContentReadonly;
+ }
+ catch( uno::Exception )
+@@ -1089,7 +1215,7 @@
+ GetMedium_Impl();
+ }
+
+- sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
++ sal_Int8 nUIStatus = LOCK_UI_NOLOCK;
+
+ // check whether system file locking has been used, the default value is false
+ sal_Bool bUseSystemLock = IsSystemFileLockingUsed();
+@@ -1100,122 +1226,40 @@
+
+ do
+ {
+- try
+- {
+- ::svt::DocumentLockFile aLockFile( aLogicName );
+- if ( !bHandleSysLocked )
+- {
+- try
+- {
+- bResult = aLockFile.CreateOwnLockFile();
+- }
+- catch ( ucb::InteractiveIOException& e )
+- {
+- // exception means that the lock file can not be successfuly accessed
+- // in this case it should be ignored if system file locking is anyway active
+- if ( bUseSystemLock || !IsOOoLockFileUsed() )
+- {
++ nUIStatus = LockIterationImpl( bHandleSysLocked, bUseSystemLock, bLoading, bNoUI );
++ bHandleSysLocked = sal_False;
++ } while( !bResult && nUIStatus == LOCK_UI_TRY );
++
++ if ( nUIStatus == LOCK_UI_SUCCEEDED )
+ bResult = sal_True;
+- // take the ownership over the lock file
+- aLockFile.OverwriteOwnLockFile();
+- }
+- else if ( e.Code == IOErrorCode_INVALID_PARAMETER )
+- {
+- // system file locking is not active, ask user whether he wants to open the document without any locking
+- uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
+-
+- if ( xHandler.is() )
+- {
+- ::rtl::Reference< ::ucbhelper::InteractionRequest > xIgnoreRequestImpl
+- = new ::ucbhelper::InteractionRequest( uno::makeAny( document::LockFileIgnoreRequest() ) );
+-
+- uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 2 );
+- aContinuations[0] = new ::ucbhelper::InteractionAbort( xIgnoreRequestImpl.get() );
+- aContinuations[1] = new ::ucbhelper::InteractionApprove( xIgnoreRequestImpl.get() );
+- xIgnoreRequestImpl->setContinuations( aContinuations );
+-
+- xHandler->handle( xIgnoreRequestImpl.get() );
+-
+- ::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xIgnoreRequestImpl->getSelection();
+- bResult = ( uno::Reference< task::XInteractionApprove >( xSelected.get(), uno::UNO_QUERY ).is() );
+- }
+- }
+- }
+- catch ( uno::Exception& )
+- {
+- // exception means that the lock file can not be successfuly accessed
+- // in this case it should be ignored if system file locking is anyway active
+- if ( bUseSystemLock || !IsOOoLockFileUsed() )
+- {
+- bResult = sal_True;
+- // take the ownership over the lock file
+- aLockFile.OverwriteOwnLockFile();
+- }
+- }
+-
+- // in case OOo locking is turned off the lock file is still written if possible
+- // but it is ignored while deciding whether the document should be opened for editing or not
+- if ( !bResult && !IsOOoLockFileUsed() )
+- {
+- bResult = sal_True;
+- // take the ownership over the lock file
+- aLockFile.OverwriteOwnLockFile();
+- }
+- }
+-
+-
+- if ( !bResult )
+- {
+- uno::Sequence< ::rtl::OUString > aData;
+- try
+- {
+- // impossibility to get data is no real problem
+- aData = aLockFile.GetLockData();
+- }
+- catch( uno::Exception ) {}
+-
+- sal_Bool bOwnLock = sal_False;
+-
+- if ( !bHandleSysLocked )
+- {
+- uno::Sequence< ::rtl::OUString > aOwnData = aLockFile.GenerateOwnEntry();
+- bOwnLock = ( aData.getLength() > LOCKFILE_USERURL_ID
+- && aOwnData.getLength() > LOCKFILE_USERURL_ID
+- && aOwnData[LOCKFILE_SYSUSERNAME_ID].equals( aData[LOCKFILE_SYSUSERNAME_ID] ) );
+-
+- if ( bOwnLock
+- && aOwnData[LOCKFILE_LOCALHOST_ID].equals( aData[LOCKFILE_LOCALHOST_ID] )
+- && aOwnData[LOCKFILE_USERURL_ID].equals( aData[LOCKFILE_USERURL_ID] ) )
+- {
+- // this is own lock from the same installation, it could remain because of crash
+- bResult = sal_True;
+- }
+- }
+-
+- if ( !bResult && !bNoUI )
+- {
+- bUIStatus = ShowLockedDocumentDialog( aData, bLoading, bOwnLock );
+- if ( bUIStatus == LOCK_UI_SUCCEEDED )
+- {
+- // take the ownership over the lock file
+- bResult = aLockFile.OverwriteOwnLockFile();
+- }
+- }
+-
+- bHandleSysLocked = sal_False;
+- }
+- }
+- catch( uno::Exception& )
+- {
+- }
+- } while( !bResult && bUIStatus == LOCK_UI_TRY );
+-
+- pImp->m_bLocked = bResult;
++
++ pImp->m_bOwnLockSet = bResult;
+ }
+ else
+ {
+ // this is no file URL, check whether the file is readonly
+ bResult = !bContentReadonly;
++ if ( bResult )
++ {
++ try
++ {
++ aContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "lock" ) ), uno::Any() );
++ pImp->m_bUCBLockSet = sal_True;
++ }
++ catch( ucb::InteractiveLockingLockedException& )
++ {
++ bResult = sal_False;
++ uno::Sequence< ::rtl::OUString > aData;
++
++ if ( !bNoUI )
++ {
++ sal_Int8 nUIStatus = ShowLockedDocumentDialog( aData, bLoading, sal_False );
++ bResult = ( nUIStatus == LOCK_UI_SUCCEEDED );
++ }
++ }
++ catch( uno::Exception& )
++ {}
++ }
+ }
+ }
+ }
+@@ -2720,11 +2769,11 @@
+ pImp->m_xLockingStream = uno::Reference< io::XStream >();
+ }
+
+- if ( pImp->m_bLocked )
++ if ( pImp->m_bOwnLockSet )
+ {
+ try
+ {
+- pImp->m_bLocked = sal_False;
++ pImp->m_bOwnLockSet = sal_False;
+ ::svt::DocumentLockFile aLockFile( aLogicName );
+ // TODO/LATER: A warning could be shown in case the file is not the own one
+ aLockFile.RemoveFile();
+@@ -2732,6 +2781,20 @@
+ catch( uno::Exception& )
+ {}
+ }
++
++ if ( pImp->m_bUCBLockSet )
++ {
++ pImp->m_bUCBLockSet = sal_False;
++
++ try
++ {
++ Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
++ ::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
++ aContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "unlock" ) ), uno::Any() );
++ }
++ catch( uno::Exception& )
++ {}
++ }
+ }
+
+ void SfxMedium::CloseAndReleaseStreams_Impl()
+--- /dev/null
++++ sfx2/source/doc/mediumstorholder.cxx
+@@ -0,0 +1,814 @@
++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2000, 2010 Oracle and/or its affiliates.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org. If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#include <com/sun/star/embed/XTransactedObject.hpp>
++#include <com/sun/star/beans/XPropertySetInfo.hpp>
++#include <com/sun/star/ucb/XCommandEnvironment.hpp>
++#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
++#include <com/sun/star/document/XDocumentProperties.hpp>
++
++#include <comphelper/documentconstants.hxx>
++#include <comphelper/storagehelper.hxx>
++#include <comphelper/processfactory.hxx>
++#include <comphelper/string.hxx>
++#include <tools/datetime.hxx>
++#include <unotools/saveopt.hxx>
++#include <unotools/useroptions.hxx>
++#include <unotools/ucbhelper.hxx>
++#include <sot/exchange.hxx>
++#include <svl/eitem.hxx>
++#include <svl/stritem.hxx>
++#include <sfx2/docfile.hxx>
++#include <sfx2/objsh.hxx>
++#include <sfx2/viewfrm.hxx>
++#include <sfx2/docfac.hxx>
++#include <sfx2/docfilt.hxx>
++#include <sfx2/fcontnr.hxx>
++#include <sfx2/signaturestate.hxx>
++#include <sfx2/dispatch.hxx>
++#include <sfx2/app.hxx>
++#include <sfx2/request.hxx>
++
++#include <mediumstorholder.hxx>
++
++using namespace ::com::sun::star;
++
++//-------------------------------------------------------------------------
++SfxMediumsStoringHolder::SfxMediumsStoringHolder( SfxObjectShell& rShell, SfxMedium& rSource, SfxMedium& rTarget, const SfxItemSet* pSet )
++: m_nStatus( HOLDER_CREATED )
++, m_rObjectShell( rShell )
++, m_rSourceMedium( rSource )
++, m_rTargetMedium( rTarget )
++, m_pSet( pSet )
++, m_bStorageBasedSource( SfxObjectShell::IsPackageStorageFormat_Impl( rSource ) )
++, m_bStorageBasedTarget( SfxObjectShell::IsPackageStorageFormat_Impl( rTarget ) )
++, m_bOwnSource( SfxObjectShell::IsOwnStorageFormat_Impl( rSource ) )
++, m_bOwnTarget( SfxObjectShell::IsOwnStorageFormat_Impl( rTarget ) )
++, m_bNeedsDisconnectionOnFail( false )
++, m_bStoreToSameLocation( false )
++, m_bTryToPreserveScriptingSignature( false )
++, m_bNoPreserveForOasis( false )
++, m_bCopyTo( false )
++, m_bUILocked( true )
++, m_bOldForbidReload( false )
++, m_bPasswordProvided( false )
++{
++ const SfxFilter *pFilter = rTarget.GetFilter();
++ if ( !pFilter )
++ {
++ // if no filter was set, use the default filter
++ // this should be changed in the feature, it should be an error!
++ DBG_ERROR("No filter set!");
++ pFilter = rShell.GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT | SFX_FILTER_EXPORT );
++ rTarget.SetFilter(pFilter);
++ }
++}
++
++// ==================================================
++// Private methods
++// ==================================================
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::CheckSignaturePreservingNecessity()
++{
++ sal_uInt16 nScriptingSignatureState = m_rObjectShell.GetScriptingSignatureState();
++ // decide whether the script signatures should be preserved
++ if ( m_bOwnSource && m_bOwnTarget
++ && ( nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_OK
++ || nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED
++ || nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_INVALID ) )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "MacroSignaturePreserving" ) ) );
++
++ // the checking of the library modified state iterates over the libraries, should be done only when required
++ // currently the check is commented out since it is broken, we have to check the signature every time we save
++ // TODO/LATER: let isAnyContainerModified() work!
++ m_bTryToPreserveScriptingSignature = true; // !pImp->pBasicManager->isAnyContainerModified();
++ if ( m_bTryToPreserveScriptingSignature )
++ {
++ // check that the storage format stays the same
++ SvtSaveOptions aSaveOpt;
++ SvtSaveOptions::ODFDefaultVersion nVersion = aSaveOpt.GetODFDefaultVersion();
++
++ ::rtl::OUString aODFVersion;
++ try
++ {
++ uno::Reference < beans::XPropertySet > xPropSet( m_rObjectShell.GetStorage(), uno::UNO_QUERY_THROW );
++ xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= aODFVersion;
++ }
++ catch( uno::Exception& )
++ {}
++
++ // preserve only if the same filter has been used
++ m_bTryToPreserveScriptingSignature = m_rSourceMedium.GetFilter() && m_rTargetMedium.GetFilter() && m_rSourceMedium.GetFilter()->GetFilterName() == m_rTargetMedium.GetFilter()->GetFilterName();
++
++ m_bNoPreserveForOasis = (
++ (aODFVersion.equals( ODFVER_012_TEXT ) && nVersion == SvtSaveOptions::ODFVER_011) ||
++ (!aODFVersion.getLength() && nVersion >= SvtSaveOptions::ODFVER_012)
++ );
++ }
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::CheckStoreSelfAndPrepare()
++{
++ // use UCB for case sensitive/insensitive file name comparison
++ if ( m_rSourceMedium.GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL
++ && m_rTargetMedium.GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL
++ && ::utl::UCBContentHelper::EqualURLs( m_rSourceMedium.GetName(), m_rTargetMedium.GetName() ) )
++ {
++ m_bStoreToSameLocation = true;
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save" ) ) );
++
++ if ( m_rSourceMedium.DocNeedsFileDateCheck() )
++ m_rTargetMedium.CheckFileDate( m_rSourceMedium.GetInitFileDate( sal_False ) );
++
++ if ( m_bCopyTo && m_rObjectShell.GetCreateMode() != SFX_CREATE_MODE_EMBEDDED )
++ {
++ // export to the same location is vorbidden
++ m_rObjectShell.SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ }
++ else
++ {
++ // before we overwrite the original file, we will make a backup if there is a demand for that
++ // if the backup is not created here it will be created internally and will be removed in case of successful saving
++ if ( SvtSaveOptions().IsBackup() )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "DoBackup" ) ) );
++ m_rTargetMedium.DoBackup_Impl();
++ if ( m_rTargetMedium.GetError() )
++ {
++ m_rObjectShell.SetError( m_rTargetMedium.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ m_rTargetMedium.ResetError();
++ }
++ }
++
++ if ( m_bStorageBasedSource && m_bStorageBasedTarget )
++ {
++ // The active storage must be switched. The simple saving is not enough.
++ // The problem is that the target medium contains target MediaDescriptor.
++
++ // In future the switch of the persistance could be done on stream level:
++ // a new wrapper service will be implemented that allows to exchange
++ // persistance on the fly. So the real persistance will be set
++ // to that stream only after successful commit of the storage.
++ // TODO/LATER:
++ // create wrapper stream based on the URL
++ // create a new storage based on this stream
++ // store to this new storage
++ // commit the new storage
++ // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
++ // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
++ // if the last step is failed the stream should stay to be transacted and should be commited on any flush
++ // so we can forget the stream in any way and the next storage commit will flush it
++
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Own to Own" ) ) );
++
++ m_bNeedsDisconnectionOnFail = m_rObjectShell.DisconnectStorage_Impl( m_rSourceMedium, m_rTargetMedium );
++ if ( m_bNeedsDisconnectionOnFail
++ || m_rObjectShell.ConnectTmpStorage_Impl( m_rSourceMedium.GetStorage(), &m_rSourceMedium ) )
++ {
++ m_rSourceMedium.CloseAndRelease();
++
++ // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
++ // in future those streams should not be copied in case a valid target url is provided,
++ // if the url is not provided ( means the document is based on a stream ) this code is not
++ // reachable.
++ m_rTargetMedium.CloseAndRelease();
++ m_rTargetMedium.GetOutputStorage();
++ }
++ }
++ else if ( !m_bStorageBasedSource && !m_bStorageBasedTarget )
++ {
++ // the source and the target formats are alien
++ // just disconnect the stream from the source format
++ // so that the target medium can use it
++
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Alien to Alien" ) ) );
++
++ m_rSourceMedium.CloseAndRelease();
++ m_rTargetMedium.CloseAndRelease();
++ m_rTargetMedium.CreateTempFileNoCopy();
++ m_rTargetMedium.GetOutStream();
++ }
++ else if ( !m_bStorageBasedSource && m_bStorageBasedTarget )
++ {
++ // the source format is an alien one but the target
++ // format is an own one so just disconnect the source
++ // medium
++
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Alien to Own" ) ) );
++
++ m_rSourceMedium.CloseAndRelease();
++ m_rTargetMedium.CloseAndRelease();
++ m_rTargetMedium.GetOutputStorage();
++ }
++ else // means if ( m_bStorageBasedSource && !m_bStorageBasedTarget )
++ {
++ // the source format is an own one but the target is
++ // an alien format, just connect the source to temporary
++ // storage
++
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Own to Alien" ) ) );
++
++ m_bNeedsDisconnectionOnFail = m_rObjectShell.DisconnectStorage_Impl( m_rSourceMedium, m_rTargetMedium );
++ if ( m_bNeedsDisconnectionOnFail
++ || m_rObjectShell.ConnectTmpStorage_Impl( m_rSourceMedium.GetStorage(), &m_rSourceMedium ) )
++ {
++ m_rSourceMedium.CloseAndRelease();
++ m_rTargetMedium.CloseAndRelease();
++ m_rTargetMedium.CreateTempFileNoCopy();
++ m_rTargetMedium.GetOutStream();
++ }
++ }
++ }
++ }
++ else
++ {
++ // This is SaveAs or export action, prepare the target medium
++ // the alien filters still might write directly to the file, that is of course a bug,
++ // but for now the framework has to be ready for it
++ // TODO/LATER: let the medium be prepared for alien formats as well
++
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "SaveAs/Export" ) ) );
++
++ m_rTargetMedium.CloseAndRelease();
++ if ( m_bStorageBasedTarget )
++ {
++ m_rTargetMedium.GetOutputStorage();
++ }
++
++ // if it is simple saving the locking will be transfered from medium to medium
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Locking" ) ) );
++ m_rTargetMedium.LockOrigFileOnDemand( sal_False, sal_False );
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::LockUI( bool bLock )
++{
++ if ( m_bUILocked != bLock )
++ {
++ SfxViewFrame *pFrame= SfxViewFrame::GetFirst( &m_rObjectShell );
++ while ( pFrame )
++ {
++ pFrame->GetDispatcher()->Lock( bLock );
++ pFrame->Enable( !bLock );
++ pFrame = SfxViewFrame::GetNext( *pFrame, &m_rObjectShell );
++ }
++
++ m_bOldForbidReload = m_rObjectShell.ForbidReload_Impl( bLock ? bLock : m_bOldForbidReload );
++
++ m_bUILocked = bLock;
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::PrepareStorageIfAny()
++{
++ if ( m_bStorageBasedTarget )
++ {
++ // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from
++ // a draw document ), the ClassId of the destination storage is different from the ClassId of this
++ // document. It can be retrieved from the default filter for the desired target format
++ long nFormat = m_rTargetMedium.GetFilter()->GetFormat();
++ SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher();
++ const SfxFilter *pFilt = rMatcher.GetFilter4ClipBoardId( nFormat );
++ if ( pFilt )
++ {
++ if ( pFilt->GetServiceName() != m_rTargetMedium.GetFilter()->GetServiceName() )
++ {
++ datatransfer::DataFlavor aDataFlavor;
++ SotExchange::GetFormatDataFlavor( nFormat, aDataFlavor );
++
++ try
++ {
++ uno::Reference< beans::XPropertySet > xProps( m_rTargetMedium.GetStorage(), uno::UNO_QUERY );
++ DBG_ASSERT( xProps.is(), "The storage implementation must implement XPropertySet!" );
++ if ( !xProps.is() )
++ throw uno::RuntimeException();
++
++ xProps->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ),
++ uno::makeAny( aDataFlavor.MimeType ) );
++ }
++ catch( uno::Exception& )
++ {
++ }
++ }
++ }
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ if( m_bOwnTarget && !( m_rTargetMedium.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) )
++ {
++ uno::Reference< embed::XStorage > xMedStorage = m_rTargetMedium.GetStorage();
++ if ( !xMedStorage.is() )
++ {
++ // no saving without storage
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ return;
++ }
++
++ // transfer password from the parameters to the storage
++ ::rtl::OUString aPasswd;
++ if ( GetPasswd_Impl( m_rTargetMedium.GetItemSet(), aPasswd ) )
++ {
++ m_bPasswordProvided = sal_True;
++ try {
++ ::comphelper::OStorageHelper::SetCommonStoragePassword( xMedStorage, aPasswd );
++ }
++ catch( uno::Exception& )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ }
++ }
++ }
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::OwnDocumentStoring()
++{
++ ::rtl::OUString aTmpVersionURL;
++
++ if ( m_rTargetMedium.GetStorage() == m_rObjectShell.GetStorage() )
++ {
++ // currently the case that the storage is the same should be impossible
++ OSL_ENSURE( sal_False, "This scenario is impossible currently!\n" );
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Should be impossible." ) ) );
++ // usual save procedure
++ if ( !m_rObjectShell.Save() )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Error in Save()" ) ) );
++ }
++ else
++ {
++ // save to target
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save as own format." ) ) );
++ if ( !m_rObjectShell.SaveAsOwnFormat( m_rTargetMedium ) )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Error in SaveAsOwnFormat()" ) ) );
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::CreateThumbnail()
++{
++ if ( m_rObjectShell.GetCreateMode() != SFX_CREATE_MODE_EMBEDDED && !m_bPasswordProvided )
++ {
++ // store the thumbnail representation image
++ // the thumbnail is not stored in case of encrypted document
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Thumbnail creation." ) ) );
++ if ( !m_rObjectShell.GenerateAndStoreThumbnail( m_bPasswordProvided,
++ sal_False,
++ m_rTargetMedium.GetFilter()->IsOwnTemplateFormat(),
++ m_rTargetMedium.GetStorage() ) )
++ {
++ // TODO/LATER: shouldn't we show warning?
++ OSL_ENSURE( sal_False, "Couldn't store thumbnail representation!" );
++ }
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::HandleVersions()
++{
++ ::rtl::OUString aTmpVersionURL;
++ SFX_ITEMSET_ARG( m_pSet, pVersionItem, SfxStringItem, SID_DOCINFO_COMMENTS, FALSE );
++ if ( pVersionItem )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "pVersionItem != NULL" ) ) );
++ aTmpVersionURL = m_rObjectShell.CreateTempCopyOfStorage_Impl( m_rTargetMedium.GetStorage() );
++ if ( !aTmpVersionURL.getLength() )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can not generate version file" ) ) );
++ }
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ // in case the versions should be preserved, copy them here
++ if ( m_rObjectShell.IsSaving_Impl() || m_rObjectShell.PreserveVersions_Impl() )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Preserve versions." ) ) );
++ try
++ {
++ uno::Sequence< util::RevisionTag > aVersions = m_rTargetMedium.GetVersionList();
++ if ( aVersions.getLength() )
++ {
++ // copy the version streams
++ ::rtl::OUString aVersionsName( RTL_CONSTASCII_USTRINGPARAM( "Versions" ) );
++ uno::Reference< embed::XStorage > xNewVerStor = m_rTargetMedium.GetStorage()->openStorageElement(
++ aVersionsName,
++ embed::ElementModes::READWRITE );
++ uno::Reference< embed::XStorage > xOldVerStor = m_rObjectShell.GetStorage()->openStorageElement(
++ aVersionsName,
++ embed::ElementModes::READ );
++ if ( !xNewVerStor.is() || !xOldVerStor.is() )
++ throw uno::RuntimeException();
++
++ for ( sal_Int32 n=0; n<aVersions.getLength(); n++ )
++ {
++ if ( xOldVerStor->hasByName( aVersions[n].Identifier ) )
++ xOldVerStor->copyElementTo( aVersions[n].Identifier, xNewVerStor, aVersions[n].Identifier );
++ }
++
++ uno::Reference< embed::XTransactedObject > xTransact( xNewVerStor, uno::UNO_QUERY );
++ if ( xTransact.is() )
++ xTransact->commit();
++ }
++ }
++ catch( uno::Exception& )
++ {
++ // TODO/LATER: a specific error could be set
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Preserving of versions has failed" ) ) );
++ }
++ }
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ // store a new version here if requested
++ if ( pVersionItem )
++ {
++ // store a version also
++ SFX_ITEMSET_ARG( m_pSet, pAuthorItem, SfxStringItem, SID_DOCINFO_AUTHOR, FALSE );
++
++ // version comment
++ util::RevisionTag aInfo;
++ aInfo.Comment = pVersionItem->GetValue();
++
++ // version author
++ String aAuthor;
++ if ( pAuthorItem )
++ aInfo.Author = pAuthorItem->GetValue();
++ else
++ // if not transferred as a parameter, get it from user settings
++ aInfo.Author = SvtUserOptions().GetFullName();
++
++ DateTime aTime;
++ aInfo.TimeStamp.Day = aTime.GetDay();
++ aInfo.TimeStamp.Month = aTime.GetMonth();
++ aInfo.TimeStamp.Year = aTime.GetYear();
++ aInfo.TimeStamp.Hours = aTime.GetHour();
++ aInfo.TimeStamp.Minutes = aTime.GetMin();
++ aInfo.TimeStamp.Seconds = aTime.GetSec();
++
++ // add new version information into the versionlist and save the versionlist
++ // the version list must have been transferred from the "old" medium before
++ m_rTargetMedium.AddVersion_Impl( aInfo );
++ m_rTargetMedium.SaveVersionList_Impl( sal_True );
++ if ( !m_rObjectShell.PutURLContentsToVersionStream_Impl( aTmpVersionURL, m_rTargetMedium.GetStorage(), aInfo.Identifier ) )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can not store version stream" ) ) );
++ }
++ else if ( m_rObjectShell.IsSaving_Impl() || m_rObjectShell.PreserveVersions_Impl() )
++ {
++ m_rTargetMedium.SaveVersionList_Impl( sal_True );
++ }
++
++ if ( aTmpVersionURL.getLength() )
++ ::utl::UCBContentHelper::Kill( aTmpVersionURL );
++}
++
++
++// ==================================================
++// Public methods
++// ==================================================
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::Init()
++{
++ if ( m_nStatus != HOLDER_CREATED )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Misuse of SfxMediumsStoringHolder" ) ) );
++ return;
++ }
++
++ // Examine target format to determine whether to query if any password
++ // protected libraries exceeds the size we can handle
++ if ( m_bOwnTarget && !m_rObjectShell.QuerySaveSizeExceededModules_Impl( m_rTargetMedium.GetInteractionHandler() ) )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ return;
++ }
++
++ CheckSignaturePreservingNecessity();
++
++ SFX_ITEMSET_ARG( m_rTargetMedium.GetItemSet(), pSaveToItem, SfxBoolItem, SID_SAVETO, sal_False );
++ m_bCopyTo = ( m_rObjectShell.GetCreateMode() == SFX_CREATE_MODE_EMBEDDED || ( pSaveToItem && pSaveToItem->GetValue() ) );
++
++ CheckStoreSelfAndPrepare();
++
++ // TODO/LATER: in future it would be more comfortable to use exception instead of such checks
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ PrepareStorageIfAny();
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ m_nStatus = HOLDER_INITIALIZED;
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::DoStoring()
++{
++ if ( m_nStatus != HOLDER_INITIALIZED )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Misuse of SfxMediumsStoringHolder" ) ) );
++ return;
++ }
++
++ // lock user interface while saving the document and forbid reloading
++ LockUI( true );
++
++ if( m_bOwnTarget && !( m_rTargetMedium.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing in own format." ) ) );
++
++ SFX_ITEMSET_ARG( m_pSet, pVersionItem, SfxStringItem, SID_DOCINFO_COMMENTS, FALSE );
++ uno::Reference< embed::XStorage > xMedStorage = m_rTargetMedium.GetStorage();
++
++ OwnDocumentStoring();
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ HandleVersions();
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ CreateThumbnail();
++ }
++ else
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing in alien format." ) ) );
++ // it's a "SaveAs" in an alien format
++ if ( m_rTargetMedium.GetFilter() && ( m_rTargetMedium.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) )
++ {
++ if ( !m_rObjectShell.ExportTo( m_rTargetMedium ) )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can not export" ) ) );
++ }
++ else
++ {
++ if ( !m_rObjectShell.ConvertTo( m_rTargetMedium ) )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Can not export" ) ) );
++ }
++
++ if ( m_rTargetMedium.GetErrorCode() || m_rSourceMedium.GetErrorCode() || m_rObjectShell.GetErrorCode() )
++ return;
++
++ // after saving the document, the temporary object storage must be updated
++ // if the old object storage was not a temporary one, it will be updated also, because it will be used
++ // as a source for copying the objects into the new temporary storage that will be created below
++ // updating means: all child objects must be stored into it
++ // ( same as on loading, where these objects are copied to the temporary storage )
++ // but don't commit these changes, because in the case when the old object storage is not a temporary one,
++ // all changes will be written into the original file !
++
++ // we also don't touch any graphical replacements here
++ if( !m_bCopyTo && m_rObjectShell.SaveChildren( TRUE ) )
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "SaveChildren has failed" ) ) );
++ }
++
++ m_nStatus = HOLDER_DOCUMENT_STORED;
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::PreserveScriptSignatureIfNecessary()
++{
++ if ( m_nStatus != HOLDER_DOCUMENT_STORED )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Misuse of SfxMediumsStoringHolder" ) ) );
++ return;
++ }
++
++
++ // if ODF version of oasis format changes on saving the signature should not be preserved
++ if ( m_bTryToPreserveScriptingSignature && m_bNoPreserveForOasis )
++ m_bTryToPreserveScriptingSignature = ( SotStorage::GetVersion( m_rTargetMedium.GetStorage() ) == SOFFICE_FILEFORMAT_60 );
++
++ uno::Reference< security::XDocumentDigitalSignatures > xDDSigns;
++ if ( m_bTryToPreserveScriptingSignature )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Copying scripting signature." ) ) );
++
++ // if the scripting code was not changed and it is signed the signature should be preserved
++ // unfortunately at this point we have only information whether the basic code has changed or not
++ // so the only way is to check the signature if the basic was not changed
++ try
++ {
++ // get the ODF version of the new medium
++ uno::Sequence< uno::Any > aArgs( 1 );
++ aArgs[0] <<= ::rtl::OUString();
++ try
++ {
++ uno::Reference < beans::XPropertySet > xPropSet( m_rTargetMedium.GetStorage(), uno::UNO_QUERY_THROW );
++ aArgs[0] = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) );
++ }
++ catch( uno::Exception& )
++ {
++ }
++
++ xDDSigns = uno::Reference< security::XDocumentDigitalSignatures >(
++ comphelper::getProcessServiceFactory()->createInstanceWithArguments(
++ rtl::OUString(
++ RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
++ aArgs ),
++ uno::UNO_QUERY_THROW );
++
++ ::rtl::OUString aScriptSignName = xDDSigns->getScriptingContentSignatureDefaultStreamName();
++
++ if ( aScriptSignName.getLength() )
++ {
++ m_rSourceMedium.Close();
++
++ // target medium is still not commited, it should not be closed
++ // commit the package storage and close it, but leave the streams open
++ m_rTargetMedium.StorageCommit_Impl();
++ m_rTargetMedium.CloseStorage();
++
++ uno::Reference< embed::XStorage > xReadOrig = m_rSourceMedium.GetZipStorageToSign_Impl();
++ if ( !xReadOrig.is() )
++ throw uno::RuntimeException();
++ uno::Reference< embed::XStorage > xMetaInf = xReadOrig->openStorageElement(
++ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
++ embed::ElementModes::READ );
++
++ uno::Reference< embed::XStorage > xTarget = m_rTargetMedium.GetZipStorageToSign_Impl( sal_False );
++ if ( !xTarget.is() )
++ throw uno::RuntimeException();
++ uno::Reference< embed::XStorage > xTargetMetaInf = xTarget->openStorageElement(
++ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
++ embed::ElementModes::READWRITE );
++
++ if ( xMetaInf.is() && xTargetMetaInf.is() )
++ {
++ xMetaInf->copyElementTo( aScriptSignName, xTargetMetaInf, aScriptSignName );
++
++ uno::Reference< embed::XTransactedObject > xTransact( xTargetMetaInf, uno::UNO_QUERY );
++ if ( xTransact.is() )
++ xTransact->commit();
++
++ xTargetMetaInf->dispose();
++
++ // now check the copied signature
++ uno::Sequence< security::DocumentSignatureInformation > aInfos =
++ xDDSigns->verifyScriptingContentSignatures( xTarget,
++ uno::Reference< io::XInputStream >() );
++ sal_uInt16 nState = m_rObjectShell.ImplCheckSignaturesInformation( aInfos );
++ if ( nState == SIGNATURESTATE_SIGNATURES_OK || nState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED
++ || nState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK)
++ {
++ m_rTargetMedium.SetCachedSignatureState_Impl( nState );
++
++ // commit the ZipStorage from target medium
++ xTransact.set( xTarget, uno::UNO_QUERY );
++ if ( xTransact.is() )
++ xTransact->commit();
++ }
++ else
++ {
++ // it should not happen, the copies signature is invalid!
++ // throw the changes away
++ OSL_ASSERT( "An invalid signature was copied!" );
++ }
++ }
++ }
++ }
++ catch( uno::Exception& )
++ {
++ }
++
++ m_rSourceMedium.Close();
++ m_rTargetMedium.CloseZipStorage_Impl();
++ }
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::CommitMedium()
++{
++ if ( m_nStatus != HOLDER_DOCUMENT_STORED )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Misuse of SfxMediumsStoringHolder" ) ) );
++ return;
++ }
++
++
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Medium commit." ) ) );
++
++ // transfer data to its destinated location
++ // the medium commits the storage or the stream it is based on
++ m_rObjectShell.RegisterTransfer( m_rTargetMedium );
++ if ( m_rTargetMedium.Commit() )
++ {
++ m_rObjectShell.AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing is successful." ) ) );
++
++ // if the target medium is an alien format and the "old" medium was an own format and the "old" medium
++ // has a name, the object storage must be exchanged, because now we need a new temporary storage
++ // as object storage
++ if ( !m_bCopyTo && m_bStorageBasedSource && !m_bStorageBasedTarget )
++ {
++ if ( m_bStoreToSameLocation )
++ {
++ // if the old medium already disconnected from document storage, the storage still must
++ // be switched if backup file is used
++ if ( m_bNeedsDisconnectionOnFail )
++ m_rObjectShell.ConnectTmpStorage_Impl( m_rObjectShell.GetStorage(), NULL );
++ }
++ else if ( m_rSourceMedium.GetName().Len()
++ || ( m_rSourceMedium.HasStorage_Impl() && m_rSourceMedium.WillDisposeStorageOnClose_Impl() ) )
++ {
++ OSL_ENSURE( m_rSourceMedium.GetName().Len(), "Fallback is used, the medium without name should not dispose the storage!\n" );
++ // copy storage of old medium to new temporary storage and take this over
++ if( !m_rObjectShell.ConnectTmpStorage_Impl( m_rSourceMedium.GetStorage(), &m_rSourceMedium ) )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ }
++ }
++ }
++ }
++ else
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Target medium commit has failed" ) ) );
++
++ // in case the document storage was connected to backup temporarely it must be disconnected now
++ if ( m_bNeedsDisconnectionOnFail )
++ m_rObjectShell.ConnectTmpStorage_Impl( m_rObjectShell.GetStorage(), NULL );
++ }
++
++ m_nStatus = HOLDER_MEDIUM_COMMITED;
++}
++
++//-------------------------------------------------------------------------
++void SfxMediumsStoringHolder::SetFileProperties()
++{
++ if ( m_nStatus != HOLDER_MEDIUM_COMMITED )
++ {
++ m_rObjectShell.SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Misuse of SfxMediumsStoringHolder" ) ) );
++ return;
++ }
++
++ try
++ {
++ ::ucbhelper::Content aContent( m_rTargetMedium.GetName(), com::sun::star::uno::Reference < ucb::XCommandEnvironment >() );
++ com::sun::star::uno::Reference < beans::XPropertySetInfo > xProps = aContent.getProperties();
++ if ( xProps.is() )
++ {
++ ::rtl::OUString aAuthor( RTL_CONSTASCII_USTRINGPARAM("Author") );
++ ::rtl::OUString aKeywords( RTL_CONSTASCII_USTRINGPARAM("Keywords") );
++ ::rtl::OUString aSubject( RTL_CONSTASCII_USTRINGPARAM("Subject") );
++ uno::Any aAny;
++
++ uno::Reference<document::XDocumentPropertiesSupplier> xDPS( m_rObjectShell.GetModel(), uno::UNO_QUERY_THROW );
++ uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
++
++ if ( xProps->hasPropertyByName( aAuthor ) )
++ {
++ aAny <<= xDocProps->getAuthor();
++ aContent.setPropertyValue( aAuthor, aAny );
++ }
++ if ( xProps->hasPropertyByName( aKeywords ) )
++ {
++ aAny <<= ::comphelper::string::convertCommaSeparated( xDocProps->getKeywords() );
++ aContent.setPropertyValue( aKeywords, aAny );
++ }
++ if ( xProps->hasPropertyByName( aSubject ) )
++ {
++ aAny <<= xDocProps->getSubject();
++ aContent.setPropertyValue( aSubject, aAny );
++ }
++ }
++ }
++ catch( uno::Exception& )
++ {
++ }
++}
++
++/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+--- sfx2/source/doc/objstor.cxx
++++ sfx2/source/doc/objstor.cxx
+@@ -131,6 +131,7 @@
+ #include "graphhelp.hxx"
+ #include "appbaslib.hxx"
+ #include "appdata.hxx"
++#include <mediumstorholder.hxx>
+
+ #ifdef OS2
+ #include <osl/file.hxx>
+@@ -979,18 +980,15 @@
+ }
+
+ //-------------------------------------------------------------------------
+-
+-sal_Bool SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium &rMedium) const
++// static
++sal_Bool SfxObjectShell::IsOwnStorageFormat_Impl(const SfxMedium &rMedium)
+ {
+- return !rMedium.GetFilter() || // Embedded
+- ( rMedium.GetFilter()->IsOwnFormat() &&
+- rMedium.GetFilter()->UsesStorage() &&
+- rMedium.GetFilter()->GetVersion() >= SOFFICE_FILEFORMAT_60 );
++ return IsPackageStorageFormat_Impl( rMedium ) && ( !rMedium.GetFilter() || rMedium.GetFilter()->IsOwnFormat() );
+ }
+
+ //-------------------------------------------------------------------------
+-
+-sal_Bool SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium &rMedium) const
++// static
++sal_Bool SfxObjectShell::IsPackageStorageFormat_Impl(const SfxMedium &rMedium)
+ {
+ return !rMedium.GetFilter() || // Embedded
+ ( rMedium.GetFilter()->UsesStorage() &&
+@@ -1081,21 +1079,7 @@
+ return bOk;
+ }
+
+-void Lock_Impl( SfxObjectShell* pDoc, BOOL bLock )
+-{
+- SfxViewFrame *pFrame= SfxViewFrame::GetFirst( pDoc );
+- while ( pFrame )
+- {
+- pFrame->GetDispatcher()->Lock( bLock );
+- pFrame->Enable( !bLock );
+- pFrame = SfxViewFrame::GetNext( *pFrame, pDoc );
+- }
+-
+-}
+-
+-
+ //-------------------------------------------------------------------------
+-
+ sal_Bool SfxObjectShell::SaveTo_Impl
+ (
+ SfxMedium &rMedium, // Medium, in das gespeichert werden soll
+@@ -1121,701 +1106,36 @@
+
+ AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Begin" ) ) );
+
+- ModifyBlocker_Impl aMod(this);
+-
+- const SfxFilter *pFilter = rMedium.GetFilter();
+- if ( !pFilter )
+- {
+- // if no filter was set, use the default filter
+- // this should be changed in the feature, it should be an error!
+- DBG_ERROR("No filter set!");
+- pFilter = GetFactory().GetFilterContainer()->GetAnyFilter( SFX_FILTER_IMPORT | SFX_FILTER_EXPORT );
+- rMedium.SetFilter(pFilter);
+- }
+-
+- sal_Bool bStorageBasedSource = IsPackageStorageFormat_Impl( *pMedium );
+- sal_Bool bStorageBasedTarget = IsPackageStorageFormat_Impl( rMedium );
+- sal_Bool bOwnSource = IsOwnStorageFormat_Impl( *pMedium );
+- sal_Bool bOwnTarget = IsOwnStorageFormat_Impl( rMedium );
+-
+- // Examine target format to determine whether to query if any password
+- // protected libraries exceed the size we can handler
+- if ( bOwnTarget && !QuerySaveSizeExceededModules_Impl( rMedium.GetInteractionHandler() ) )
+- {
+- SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
++ if ( !pMedium )
+ return sal_False;
+- }
+-
+- sal_Bool bNeedsDisconnectionOnFail = sal_False;
+-
+- sal_Bool bStoreToSameLocation = sal_False;
+-
+- // the detection whether the script is changed should be done before saving
+- sal_Bool bTryToPreserveScriptSignature = sal_False;
+- // no way to detect whether a filter is oasis format, have to wait for saving process
+- sal_Bool bNoPreserveForOasis = sal_False;
+- if ( bOwnSource && bOwnTarget
+- && ( pImp->nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_OK
+- || pImp->nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED
+- || pImp->nScriptingSignatureState == SIGNATURESTATE_SIGNATURES_INVALID ) )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "MacroSignaturePreserving" ) ) );
+-
+- // the checking of the library modified state iterates over the libraries, should be done only when required
+- // currently the check is commented out since it is broken, we have to check the signature every time we save
+- // TODO/LATER: let isAnyContainerModified() work!
+- bTryToPreserveScriptSignature = sal_True; // !pImp->pBasicManager->isAnyContainerModified();
+- if ( bTryToPreserveScriptSignature )
+- {
+- // check that the storage format stays the same
+- SvtSaveOptions aSaveOpt;
+- SvtSaveOptions::ODFDefaultVersion nVersion = aSaveOpt.GetODFDefaultVersion();
+-
+- ::rtl::OUString aODFVersion;
+- try
+- {
+- uno::Reference < beans::XPropertySet > xPropSet( GetStorage(), uno::UNO_QUERY_THROW );
+- xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) ) >>= aODFVersion;
+- }
+- catch( uno::Exception& )
+- {}
+-
+- // preserve only if the same filter has been used
+- bTryToPreserveScriptSignature = pMedium->GetFilter() && pFilter && pMedium->GetFilter()->GetFilterName() == pFilter->GetFilterName();
+-
+- bNoPreserveForOasis = (
+- (aODFVersion.equals( ODFVER_012_TEXT ) && nVersion == SvtSaveOptions::ODFVER_011) ||
+- (!aODFVersion.getLength() && nVersion >= SvtSaveOptions::ODFVER_012)
+- );
+- }
+- }
+-
+- sal_Bool bCopyTo = sal_False;
+- SfxItemSet *pMedSet = rMedium.GetItemSet();
+- if( pMedSet )
+- {
+- SFX_ITEMSET_ARG( pMedSet, pSaveToItem, SfxBoolItem, SID_SAVETO, sal_False );
+- bCopyTo = GetCreateMode() == SFX_CREATE_MODE_EMBEDDED ||
+- (pSaveToItem && pSaveToItem->GetValue());
+- }
+-
+- // use UCB for case sensitive/insensitive file name comparison
+- if ( pMedium
+- && pMedium->GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL
+- && rMedium.GetName().CompareIgnoreCaseToAscii( "private:stream", 14 ) != COMPARE_EQUAL
+- && ::utl::UCBContentHelper::EqualURLs( pMedium->GetName(), rMedium.GetName() ) )
+- {
+- bStoreToSameLocation = sal_True;
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save" ) ) );
+-
+- if ( pMedium->DocNeedsFileDateCheck() )
+- rMedium.CheckFileDate( pMedium->GetInitFileDate( sal_False ) );
+-
+- if ( bCopyTo && GetCreateMode() != SFX_CREATE_MODE_EMBEDDED )
+- {
+- // export to the same location is vorbidden
+- SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+- }
+- else
+- {
+- // before we overwrite the original file, we will make a backup if there is a demand for that
+- // if the backup is not created here it will be created internally and will be removed in case of successful saving
+- const sal_Bool bDoBackup = SvtSaveOptions().IsBackup();
+- if ( bDoBackup )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "DoBackup" ) ) );
+- rMedium.DoBackup_Impl();
+- if ( rMedium.GetError() )
+- {
+- SetError( rMedium.GetErrorCode(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+- rMedium.ResetError();
+- }
+- }
+-
+- if ( bStorageBasedSource && bStorageBasedTarget )
+- {
+- // The active storage must be switched. The simple saving is not enough.
+- // The problem is that the target medium contains target MediaDescriptor.
+-
+- // In future the switch of the persistance could be done on stream level:
+- // a new wrapper service will be implemented that allows to exchange
+- // persistance on the fly. So the real persistance will be set
+- // to that stream only after successful commit of the storage.
+- // TODO/LATER:
+- // create wrapper stream based on the URL
+- // create a new storage based on this stream
+- // store to this new storage
+- // commit the new storage
+- // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
+- // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
+- // if the last step is failed the stream should stay to be transacted and should be commited on any flush
+- // so we can forget the stream in any way and the next storage commit will flush it
+-
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Own to Own" ) ) );
+-
+- bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
+- *pMedium, rMedium );
+- if ( bNeedsDisconnectionOnFail
+- || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
+- {
+- pMedium->CloseAndRelease();
+-
+- // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
+- // in future those streams should not be copied in case a valid target url is provided,
+- // if the url is not provided ( means the document is based on a stream ) this code is not
+- // reachable.
+- rMedium.CloseAndRelease();
+- rMedium.GetOutputStorage();
+- }
+- }
+- else if ( !bStorageBasedSource && !bStorageBasedTarget )
+- {
+- // the source and the target formats are alien
+- // just disconnect the stream from the source format
+- // so that the target medium can use it
+-
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Alien to Alien" ) ) );
+-
+- pMedium->CloseAndRelease();
+- rMedium.CloseAndRelease();
+- rMedium.CreateTempFileNoCopy();
+- rMedium.GetOutStream();
+- }
+- else if ( !bStorageBasedSource && bStorageBasedTarget )
+- {
+- // the source format is an alien one but the target
+- // format is an own one so just disconnect the source
+- // medium
+-
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Alien to Own" ) ) );
+-
+- pMedium->CloseAndRelease();
+- rMedium.CloseAndRelease();
+- rMedium.GetOutputStorage();
+- }
+- else // means if ( bStorageBasedSource && !bStorageBasedTarget )
+- {
+- // the source format is an own one but the target is
+- // an alien format, just connect the source to temporary
+- // storage
+-
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save: Own to Alien" ) ) );
+-
+- bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
+- *pMedium, rMedium );
+- if ( bNeedsDisconnectionOnFail
+- || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
+- {
+- pMedium->CloseAndRelease();
+- rMedium.CloseAndRelease();
+- rMedium.CreateTempFileNoCopy();
+- rMedium.GetOutStream();
+- }
+- }
+- }
+- }
+- else
+- {
+- // This is SaveAs or export action, prepare the target medium
+- // the alien filters still might write directly to the file, that is of course a bug,
+- // but for now the framework has to be ready for it
+- // TODO/LATER: let the medium be prepared for alien formats as well
+-
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "SaveAs/Export" ) ) );
+-
+- rMedium.CloseAndRelease();
+- if ( bStorageBasedTarget )
+- {
+- rMedium.GetOutputStorage();
+- }
+- }
++
++ ModifyBlocker_Impl aMod( this );
++
++ // the object controls storing of the document
++ SfxMediumsStoringHolder aStorer( *this, *pMedium, rMedium, pSet );
++
++ aStorer.Init();
+
+ // TODO/LATER: error handling
+ if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() )
+ return sal_False;
+
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Locking" ) ) );
+-
+- rMedium.LockOrigFileOnDemand( sal_False, sal_False );
+-
+- if ( bStorageBasedTarget )
+- {
+- if ( rMedium.GetErrorCode() )
+- return sal_False;
+-
+- // If the filter is a "cross export" filter ( f.e. a filter for exporting an impress document from
+- // a draw document ), the ClassId of the destination storage is different from the ClassId of this
+- // document. It can be retrieved from the default filter for the desired target format
+- long nFormat = rMedium.GetFilter()->GetFormat();
+- SfxFilterMatcher& rMatcher = SFX_APP()->GetFilterMatcher();
+- const SfxFilter *pFilt = rMatcher.GetFilter4ClipBoardId( nFormat );
+- if ( pFilt )
+- {
+- if ( pFilt->GetServiceName() != rMedium.GetFilter()->GetServiceName() )
+- {
+- datatransfer::DataFlavor aDataFlavor;
+- SotExchange::GetFormatDataFlavor( nFormat, aDataFlavor );
+-
+- try
+- {
+- uno::Reference< beans::XPropertySet > xProps( rMedium.GetStorage(), uno::UNO_QUERY );
+- DBG_ASSERT( xProps.is(), "The storage implementation must implement XPropertySet!" );
+- if ( !xProps.is() )
+- throw uno::RuntimeException();
+-
+- xProps->setPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ),
+- uno::makeAny( aDataFlavor.MimeType ) );
+- }
+- catch( uno::Exception& )
+- {
+- }
+- }
+- }
+- }
+-
+- // TODO/LATER: error handling
++ aStorer.DoStoring();
++
+ if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() )
+ return sal_False;
+
+- sal_Bool bOldStat = pImp->bForbidReload;
+- pImp->bForbidReload = sal_True;
+-
+- // lock user interface while saving the document
+- Lock_Impl( this, sal_True );
+-
+- sal_Bool bOk = sal_False;
+- // TODO/LATER: get rid of bOk
+-
+- if( bOwnTarget && !( pFilter->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing in own format." ) ) );
+- uno::Reference< embed::XStorage > xMedStorage = rMedium.GetStorage();
+- if ( !xMedStorage.is() )
+- {
+- // no saving without storage, unlock UI and return
+- Lock_Impl( this, sal_False );
+- pImp->bForbidReload = bOldStat;
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing failed, still no error set." ) ) );
++ aStorer.PreserveScriptSignatureIfNecessary();
++
++ if( rMedium.GetErrorCode() || pMedium->GetErrorCode() || GetErrorCode() )
+ return sal_False;
+- }
+-
+- // transfer password from the parameters to the storage
+- ::rtl::OUString aPasswd;
+- sal_Bool bPasswdProvided = sal_False;
+- if ( GetPasswd_Impl( rMedium.GetItemSet(), aPasswd ) )
+- {
+- bPasswdProvided = sal_True;
+- try {
+- ::comphelper::OStorageHelper::SetCommonStoragePassword( xMedStorage, aPasswd );
+- bOk = sal_True;
+- }
+- catch( uno::Exception& )
+- {
+- DBG_ERROR( "Setting of common encryption key failed!" );
+- SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
+- }
+- }
+- else
+- bOk = sal_True;
+-
+- pFilter = rMedium.GetFilter();
+-
+- const SfxStringItem *pVersionItem = pSet ? (const SfxStringItem*)
+- SfxRequest::GetItem( pSet, SID_DOCINFO_COMMENTS, sal_False, TYPE(SfxStringItem) ) : NULL;
+- ::rtl::OUString aTmpVersionURL;
+-
+- if ( bOk )
+- {
+- bOk = sal_False;
+- // currently the case that the storage is the same should be impossible
+- if ( xMedStorage == GetStorage() )
+- {
+- OSL_ENSURE( !pVersionItem, "This scenario is impossible currently!\n" );
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Should be impossible." ) ) );
+- // usual save procedure
+- bOk = Save();
+- }
+- else
+- {
+- // save to target
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Save as own format." ) ) );
+- bOk = SaveAsOwnFormat( rMedium );
+- if ( bOk && pVersionItem )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "pVersionItem != NULL" ) ) );
+- aTmpVersionURL = CreateTempCopyOfStorage_Impl( xMedStorage );
+- bOk = ( aTmpVersionURL.getLength() > 0 );
+- }
+- }
+- }
+-
+-
+- if ( bOk && GetCreateMode() != SFX_CREATE_MODE_EMBEDDED && !bPasswdProvided )
+- {
+- // store the thumbnail representation image
+- // the thumbnail is not stored in case of encrypted document
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Thumbnail creation." ) ) );
+- if ( !GenerateAndStoreThumbnail( bPasswdProvided,
+- sal_False,
+- pFilter->IsOwnTemplateFormat(),
+- xMedStorage ) )
+- {
+- // TODO: error handling
+- OSL_ENSURE( sal_False, "Couldn't store thumbnail representation!" );
+- }
+- }
+-
+- if ( bOk )
+- {
+- if ( pImp->bIsSaving || pImp->bPreserveVersions )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Preserve versions." ) ) );
+- try
+- {
+- Sequence < util::RevisionTag > aVersions = rMedium.GetVersionList();
+- if ( aVersions.getLength() )
+- {
+- // copy the version streams
+- ::rtl::OUString aVersionsName( RTL_CONSTASCII_USTRINGPARAM( "Versions" ) );
+- uno::Reference< embed::XStorage > xNewVerStor = xMedStorage->openStorageElement(
+- aVersionsName,
+- embed::ElementModes::READWRITE );
+- uno::Reference< embed::XStorage > xOldVerStor = GetStorage()->openStorageElement(
+- aVersionsName,
+- embed::ElementModes::READ );
+- if ( !xNewVerStor.is() || !xOldVerStor.is() )
+- throw uno::RuntimeException();
+-
+- for ( sal_Int32 n=0; n<aVersions.getLength(); n++ )
+- {
+- if ( xOldVerStor->hasByName( aVersions[n].Identifier ) )
+- xOldVerStor->copyElementTo( aVersions[n].Identifier, xNewVerStor, aVersions[n].Identifier );
+- }
+-
+- uno::Reference< embed::XTransactedObject > xTransact( xNewVerStor, uno::UNO_QUERY );
+- if ( xTransact.is() )
+- xTransact->commit();
+- }
+- }
+- catch( uno::Exception& )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Preserve versions has failed." ) ) );
+- DBG_ERROR( "Couldn't copy versions!\n" );
+- bOk = sal_False;
+- // TODO/LATER: a specific error could be set
+- }
+- }
+-
+- if ( bOk && pVersionItem )
+- {
+- // store a version also
+- const SfxStringItem *pAuthorItem = pSet ? (const SfxStringItem*)
+- SfxRequest::GetItem( pSet, SID_DOCINFO_AUTHOR, sal_False, TYPE(SfxStringItem) ) : NULL;
+-
+- // version comment
+- util::RevisionTag aInfo;
+- aInfo.Comment = pVersionItem->GetValue();
+-
+- // version author
+- String aAuthor;
+- if ( pAuthorItem )
+- aInfo.Author = pAuthorItem->GetValue();
+- else
+- // if not transferred as a parameter, get it from user settings
+- aInfo.Author = SvtUserOptions().GetFullName();
+-
+- DateTime aTime;
+- aInfo.TimeStamp.Day = aTime.GetDay();
+- aInfo.TimeStamp.Month = aTime.GetMonth();
+- aInfo.TimeStamp.Year = aTime.GetYear();
+- aInfo.TimeStamp.Hours = aTime.GetHour();
+- aInfo.TimeStamp.Minutes = aTime.GetMin();
+- aInfo.TimeStamp.Seconds = aTime.GetSec();
+-
+- if ( bOk )
+- {
+- // add new version information into the versionlist and save the versionlist
+- // the version list must have been transferred from the "old" medium before
+- rMedium.AddVersion_Impl( aInfo );
+- rMedium.SaveVersionList_Impl( sal_True );
+- bOk = PutURLContentsToVersionStream_Impl( aTmpVersionURL, xMedStorage, aInfo.Identifier );
+- }
+- }
+- else if ( bOk && ( pImp->bIsSaving || pImp->bPreserveVersions ) )
+- {
+- rMedium.SaveVersionList_Impl( sal_True );
+- }
+- }
+-
+- if ( aTmpVersionURL.getLength() )
+- ::utl::UCBContentHelper::Kill( aTmpVersionURL );
+- }
+- else
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing in alien format." ) ) );
+- // it's a "SaveAs" in an alien format
+- if ( rMedium.GetFilter() && ( rMedium.GetFilter()->GetFilterFlags() & SFX_FILTER_STARONEFILTER ) )
+- bOk = ExportTo( rMedium );
+- else
+- bOk = ConvertTo( rMedium );
+-
+- // after saving the document, the temporary object storage must be updated
+- // if the old object storage was not a temporary one, it will be updated also, because it will be used
+- // as a source for copying the objects into the new temporary storage that will be created below
+- // updating means: all child objects must be stored into it
+- // ( same as on loading, where these objects are copied to the temporary storage )
+- // but don't commit these changes, because in the case when the old object storage is not a temporary one,
+- // all changes will be written into the original file !
+-
+- if( bOk && !bCopyTo )
+- // we also don't touch any graphical replacements here
+- bOk = SaveChildren( TRUE );
+- }
+-
+- if (bOk) { // commit *before* we do the conversion!
+- bOk = rMedium.Commit();
+- }
+-
+- uno::Reference< embed::XStorage > xNewTmpStorage;
+- if (bOk) {
+- String aUserData=pFilter->GetUserData();
+- // check whether a postprocessing step is requested in the configuration
+- static const char POSTPROCESS_CONST[]="Postprocess=<";
+- int pos=aUserData.Search(::rtl::OUString::createFromAscii(POSTPROCESS_CONST).getStr(), 0);
+- int end=aUserData.Search( '>', pos+strlen(POSTPROCESS_CONST));
+- if (pos!=STRING_NOTFOUND && end!=STRING_NOTFOUND) {
+- String aAppName(aUserData, pos+strlen(POSTPROCESS_CONST), end-(pos+strlen(POSTPROCESS_CONST)));
+-
+- // setup status bar
+- SfxItemSet *pSet2 = rMedium.GetItemSet();
+- const SfxUnoAnyItem *pItem=NULL;
+- SfxItemState ret=pSet2->GetItemState( SID_PROGRESS_STATUSBAR_CONTROL, TRUE, (const SfxPoolItem**)&pItem);
+- uno::Reference< ::com::sun::star::task::XStatusIndicator > xStatusIndicator;
+- if (ret==SFX_ITEM_SET && pItem!=NULL)
+- {
+- pItem->GetValue() >>= xStatusIndicator;
+- }
+-
+- // create copy
+- ::rtl::OUString aTmpVersionURL = CreateTempCopyOfStorage_Impl( rMedium.GetStorage() );
+- rMedium.CloseAndRelease();
+-
+- rtl::OUString aSourceFile;
+- osl::FileBase::getSystemPathFromFileURL(aTmpVersionURL, aSourceFile);
+- String aTargetFile(rMedium.GetPhysicalName());
+-
+- // remove the current target file after it was copied
+- // the postprocess might crash and the unprocessed file would confuse users
+- String aTargetFileURL;
+- ::utl::LocalFileHelper::ConvertPhysicalNameToURL( aTargetFile, aTargetFileURL );
+- osl_removeFile(::rtl::OUString(aTargetFileURL).pData);
+-
+- bOk=invokeExternalApp(aAppName, aSourceFile, aTargetFile, xStatusIndicator);
+-
+- if (bOk) {
+- // create a new tmp storage
+- xNewTmpStorage=::comphelper::OStorageHelper::GetStorageFromURL( aTmpVersionURL, embed::ElementModes::READWRITE );
+- // it does not make sense to reopen the file if it was not saved correctly
+- rMedium.ReOpen();
+- }
+- }
+- }
+-
+- if (bOk && xNewTmpStorage.is()) {
+- rMedium.SetStorage_Impl(xNewTmpStorage);
+- }
+-
+- if ( bOk )
+- {
+- // if ODF version of oasis format changes on saving the signature should not be preserved
+- if ( bOk && bTryToPreserveScriptSignature && bNoPreserveForOasis )
+- bTryToPreserveScriptSignature = ( SotStorage::GetVersion( rMedium.GetStorage() ) == SOFFICE_FILEFORMAT_60 );
+-
+- uno::Reference< security::XDocumentDigitalSignatures > xDDSigns;
+- if ( bOk && bTryToPreserveScriptSignature )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Copying scripting signature." ) ) );
+-
+- // if the scripting code was not changed and it is signed the signature should be preserved
+- // unfortunately at this point we have only information whether the basic code has changed or not
+- // so the only way is to check the signature if the basic was not changed
+- try
+- {
+- // get the ODF version of the new medium
+- uno::Sequence< uno::Any > aArgs( 1 );
+- aArgs[0] <<= ::rtl::OUString();
+- try
+- {
+- uno::Reference < beans::XPropertySet > xPropSet( rMedium.GetStorage(), uno::UNO_QUERY_THROW );
+- aArgs[0] = xPropSet->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Version" ) ) );
+- }
+- catch( uno::Exception& )
+- {
+- }
+-
+- xDDSigns = uno::Reference< security::XDocumentDigitalSignatures >(
+- comphelper::getProcessServiceFactory()->createInstanceWithArguments(
+- rtl::OUString(
+- RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
+- aArgs ),
+- uno::UNO_QUERY_THROW );
+-
+- ::rtl::OUString aScriptSignName = xDDSigns->getScriptingContentSignatureDefaultStreamName();
+-
+- if ( aScriptSignName.getLength() )
+- {
+- pMedium->Close();
+-
+- // target medium is still not commited, it should not be closed
+- // commit the package storage and close it, but leave the streams open
+- rMedium.StorageCommit_Impl();
+- rMedium.CloseStorage();
+-
+- uno::Reference< embed::XStorage > xReadOrig = pMedium->GetZipStorageToSign_Impl();
+- if ( !xReadOrig.is() )
+- throw uno::RuntimeException();
+- uno::Reference< embed::XStorage > xMetaInf = xReadOrig->openStorageElement(
+- ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
+- embed::ElementModes::READ );
+-
+- uno::Reference< embed::XStorage > xTarget = rMedium.GetZipStorageToSign_Impl( sal_False );
+- if ( !xTarget.is() )
+- throw uno::RuntimeException();
+- uno::Reference< embed::XStorage > xTargetMetaInf = xTarget->openStorageElement(
+- ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
+- embed::ElementModes::READWRITE );
+-
+- if ( xMetaInf.is() && xTargetMetaInf.is() )
+- {
+- xMetaInf->copyElementTo( aScriptSignName, xTargetMetaInf, aScriptSignName );
+-
+- uno::Reference< embed::XTransactedObject > xTransact( xTargetMetaInf, uno::UNO_QUERY );
+- if ( xTransact.is() )
+- xTransact->commit();
+-
+- xTargetMetaInf->dispose();
+-
+- // now check the copied signature
+- uno::Sequence< security::DocumentSignatureInformation > aInfos =
+- xDDSigns->verifyScriptingContentSignatures( xTarget,
+- uno::Reference< io::XInputStream >() );
+- sal_uInt16 nState = ImplCheckSignaturesInformation( aInfos );
+- if ( nState == SIGNATURESTATE_SIGNATURES_OK || nState == SIGNATURESTATE_SIGNATURES_NOTVALIDATED
+- || nState == SIGNATURESTATE_SIGNATURES_PARTIAL_OK)
+- {
+- rMedium.SetCachedSignatureState_Impl( nState );
+-
+- // commit the ZipStorage from target medium
+- xTransact.set( xTarget, uno::UNO_QUERY );
+- if ( xTransact.is() )
+- xTransact->commit();
+- }
+- else
+- {
+- // it should not happen, the copies signature is invalid!
+- // throw the changes away
+- OSL_ASSERT( "An invalid signature was copied!" );
+- }
+- }
+- }
+- }
+- catch( uno::Exception& )
+- {
+- }
+-
+- pMedium->Close();
+- rMedium.CloseZipStorage_Impl();
+- }
+-
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Medium commit." ) ) );
+-
+- // transfer data to its destinated location
+- // the medium commits the storage or the stream it is based on
+- RegisterTransfer( rMedium );
+-
+- if ( bOk )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing is successful." ) ) );
+- bOk = rMedium.Commit();
+-
+- // if the target medium is an alien format and the "old" medium was an own format and the "old" medium
+- // has a name, the object storage must be exchanged, because now we need a new temporary storage
+- // as object storage
+- if ( !bCopyTo && bStorageBasedSource && !bStorageBasedTarget )
+- {
+- if ( bStoreToSameLocation )
+- {
+- // if the old medium already disconnected from document storage, the storage still must
+- // be switched if backup file is used
+- if ( bNeedsDisconnectionOnFail )
+- ConnectTmpStorage_Impl( pImp->m_xDocStorage, NULL );
+- }
+- else if ( pMedium->GetName().Len()
+- || ( pMedium->HasStorage_Impl() && pMedium->WillDisposeStorageOnClose_Impl() ) )
+- {
+- OSL_ENSURE( pMedium->GetName().Len(), "Fallback is used, the medium without name should not dispose the storage!\n" );
+- // copy storage of old medium to new temporary storage and take this over
+- if( !ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Process after storing has failed." ) ) );
+- bOk = sal_False;
+- }
+- }
+- }
+- }
+- else
+- {
+- AddLog( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Storing has failed." ) ) );
+-
+- // in case the document storage was connected to backup temporarely it must be disconnected now
+- if ( bNeedsDisconnectionOnFail )
+- ConnectTmpStorage_Impl( pImp->m_xDocStorage, NULL );
+- }
+- }
+-
+- // unlock user interface
+- Lock_Impl( this, sal_False );
+- pImp->bForbidReload = bOldStat;
+-
+- if ( bOk )
+- {
+- try
+- {
+- ::ucbhelper::Content aContent( rMedium.GetName(), com::sun::star::uno::Reference < XCommandEnvironment >() );
+- com::sun::star::uno::Reference < XPropertySetInfo > xProps = aContent.getProperties();
+- if ( xProps.is() )
+- {
+- ::rtl::OUString aAuthor( RTL_CONSTASCII_USTRINGPARAM("Author") );
+- ::rtl::OUString aKeywords( RTL_CONSTASCII_USTRINGPARAM("Keywords") );
+- ::rtl::OUString aSubject( RTL_CONSTASCII_USTRINGPARAM("Subject") );
... etc. - the rest is truncated
More information about the Libreoffice-commits
mailing list