blob: 1681fc1824c2cb6edc87149309fdc1a83949b1da [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#include <sfx2/docfile.hxx>
#include "sfx2/signaturestate.hxx"
#include <uno/mapping.hxx>
#include <com/sun/star/task/XInteractionHandler.hpp>
#include <com/sun/star/uno/Reference.h>
#include <com/sun/star/ucb/XContent.hpp>
#include <com/sun/star/document/XDocumentRevisionListPersistence.hpp>
#include <com/sun/star/document/LockedDocumentRequest.hpp>
#include <com/sun/star/document/OwnLockOnDocumentRequest.hpp>
#include <com/sun/star/document/LockedOnSavingRequest.hpp>
#include <com/sun/star/document/LockFileIgnoreRequest.hpp>
#include <com/sun/star/document/ChangedByOthersRequest.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/embed/XTransactedObject.hpp>
#include <com/sun/star/embed/ElementModes.hpp>
#include <com/sun/star/embed/UseBackupException.hpp>
#include <com/sun/star/embed/XOptimizedStorage.hpp>
#include <com/sun/star/ucb/InteractiveIOException.hpp>
#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/XCommandEnvironment.hpp>
#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
#include <com/sun/star/ucb/XContentProvider.hpp>
#include <com/sun/star/ucb/XProgressHandler.hpp>
#include <com/sun/star/ucb/XCommandInfo.hpp>
#include <com/sun/star/util/XArchiver.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XTruncate.hpp>
#include <com/sun/star/io/XStreamListener.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/ucb/InsertCommandArgument.hpp>
#include <com/sun/star/ucb/NameClash.hpp>
#include <com/sun/star/ucb/TransferInfo.hpp>
#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
#include <com/sun/star/ucb/OpenMode.hpp>
#include <com/sun/star/ucb/NameClashException.hpp>
#include <com/sun/star/logging/XSimpleLogRing.hpp>
#include <cppuhelper/implbase1.hxx>
#include <com/sun/star/beans/PropertyValue.hpp>
#ifndef _COM_SUN_STAR_SECURITY_DOCUMENTSIGNATURESINFORMATION_HPP_
#include <com/sun/star/security/DocumentSignatureInformation.hpp>
#endif
#include <com/sun/star/security/XDocumentDigitalSignatures.hpp>
#include <tools/zcodec.hxx>
#include <tools/cachestr.hxx>
#include <tools/urlobj.hxx>
#include <unotools/tempfile.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/componentcontext.hxx>
#include <comphelper/interaction.hxx>
#include <framework/interaction.hxx>
#include <unotools/streamhelper.hxx>
#include <unotools/localedatawrapper.hxx>
#ifndef _MSGBOX_HXX //autogen
#include <vcl/msgbox.hxx>
#endif
#include <svl/stritem.hxx>
#include <svl/eitem.hxx>
#include <svl/lckbitem.hxx>
#include <svtools/sfxecode.hxx>
#include <svl/itemset.hxx>
#include <svl/intitem.hxx>
#include <svtools/svparser.hxx> // SvKeyValue
#include <cppuhelper/weakref.hxx>
#include <cppuhelper/implbase1.hxx>
#define _SVSTDARR_ULONGS
#define _SVSTDARR_STRINGSDTOR
#include <svl/svstdarr.hxx>
#include <unotools/streamwrap.hxx>
#include <rtl/logfile.hxx>
#include <osl/file.hxx>
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::ucb;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::io;
#include <comphelper/storagehelper.hxx>
#include <comphelper/mediadescriptor.hxx>
#include <comphelper/configurationhelper.hxx>
#include <comphelper/docpasswordhelper.hxx>
#include <tools/urlobj.hxx>
#include <tools/inetmime.hxx>
#include <unotools/ucblockbytes.hxx>
#include <unotools/pathoptions.hxx>
#include <svtools/asynclink.hxx>
#include <svl/inettype.hxx>
#include <ucbhelper/contentbroker.hxx>
#include <ucbhelper/commandenvironment.hxx>
#include <unotools/localfilehelper.hxx>
#include <unotools/ucbstreamhelper.hxx>
#include <unotools/ucbhelper.hxx>
#include <unotools/progresshandlerwrap.hxx>
#include <ucbhelper/content.hxx>
#include <ucbhelper/interactionrequest.hxx>
#include <sot/stg.hxx>
#include <unotools/saveopt.hxx>
#include <svl/documentlockfile.hxx>
#include "helper.hxx"
#include <sfx2/request.hxx> // SFX_ITEMSET_SET
#include <sfx2/app.hxx> // GetFilterMatcher
#include <sfx2/frame.hxx> // LoadTargetFrame
#include "fltfnc.hxx" // SfxFilterMatcher
#include <sfx2/docfilt.hxx> // SfxFilter
#include <sfx2/objsh.hxx> // CheckOpenMode
#include <sfx2/docfac.hxx> // GetFilterContainer
#include "doc.hrc"
#include "openflag.hxx" // SFX_STREAM_READONLY etc.
#include "sfx2/sfxresid.hxx"
#include <sfx2/appuno.hxx>
//#include "xmlversion.hxx"
#define MAX_REDIRECT 5
sal_Bool IsReadonlyAccordingACL( const sal_Unicode* pFilePath );
//==========================================================
namespace {
static const sal_Int8 LOCK_UI_NOLOCK = 0;
static const sal_Int8 LOCK_UI_SUCCEEDED = 1;
static const sal_Int8 LOCK_UI_TRY = 2;
//----------------------------------------------------------------
sal_Bool IsSystemFileLockingUsed()
{
// check whether system file locking has been used, the default value is false
sal_Bool bUseSystemLock = sal_False;
try
{
uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
::comphelper::getProcessServiceFactory(),
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
::comphelper::ConfigurationHelper::E_STANDARD );
if ( !xCommonConfig.is() )
throw uno::RuntimeException();
::comphelper::ConfigurationHelper::readRelativeKey(
xCommonConfig,
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentSystemFileLocking" ) ) ) >>= bUseSystemLock;
}
catch( const uno::Exception& )
{
}
return bUseSystemLock;
}
//----------------------------------------------------------------
sal_Bool IsOOoLockFileUsed()
{
// check whether system file locking has been used, the default value is false
sal_Bool bOOoLockFileUsed = sal_False;
try
{
uno::Reference< uno::XInterface > xCommonConfig = ::comphelper::ConfigurationHelper::openConfig(
::comphelper::getProcessServiceFactory(),
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common" ) ),
::comphelper::ConfigurationHelper::E_STANDARD );
if ( !xCommonConfig.is() )
throw uno::RuntimeException();
::comphelper::ConfigurationHelper::readRelativeKey(
xCommonConfig,
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Misc/" ) ),
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseDocumentOOoLockFile" ) ) ) >>= bOOoLockFileUsed;
}
catch( const uno::Exception& )
{
}
return bOOoLockFileUsed;
}
} // anonymous namespace
//==========================================================
//----------------------------------------------------------------
class SfxMediumHandler_Impl : public ::cppu::WeakImplHelper1< com::sun::star::task::XInteractionHandler >
{
com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > m_xInter;
public:
virtual void SAL_CALL handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
throw( com::sun::star::uno::RuntimeException );
SfxMediumHandler_Impl( com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > xInteraction )
: m_xInter( xInteraction )
{}
~SfxMediumHandler_Impl();
};
//----------------------------------------------------------------
SfxMediumHandler_Impl::~SfxMediumHandler_Impl()
{
}
//----------------------------------------------------------------
void SAL_CALL SfxMediumHandler_Impl::handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& xRequest )
throw( com::sun::star::uno::RuntimeException )
{
if( !m_xInter.is() )
return;
com::sun::star::uno::Any aRequest = xRequest->getRequest();
com::sun::star::ucb::InteractiveIOException aIoException;
com::sun::star::ucb::UnsupportedDataSinkException aSinkException;
if ( (aRequest >>= aIoException) && ( aIoException.Code == IOErrorCode_ACCESS_DENIED || aIoException.Code == IOErrorCode_LOCKING_VIOLATION ) )
return;
else
if ( aRequest >>= aSinkException )
return;
else
m_xInter->handle( xRequest );
}
//----------------------------------------------------------------
class SfxMedium_Impl : public SvCompatWeakBase
{
public:
::ucbhelper::Content aContent;
sal_Bool bUpdatePickList : 1;
sal_Bool bIsTemp : 1;
sal_Bool bForceSynchron : 1;
sal_Bool bDownloadDone : 1;
sal_Bool bDontCallDoneLinkOnSharingError : 1;
sal_Bool bIsStorage: 1;
sal_Bool bUseInteractionHandler: 1;
sal_Bool bAllowDefaultIntHdl: 1;
sal_Bool bIsCharsetInitialized: 1;
sal_Bool bDisposeStorage: 1;
sal_Bool bStorageBasedOnInStream: 1;
sal_Bool m_bSalvageMode: 1;
sal_Bool m_bVersionsAlreadyLoaded: 1;
sal_Bool m_bLocked: 1;
sal_Bool m_bGotDateTime: 1;
uno::Reference < embed::XStorage > xStorage;
SfxMedium* pAntiImpl;
long nFileVersion;
const SfxFilter* pOrigFilter;
String aOrigURL;
String aPreRedirectionURL;
String aReferer;
DateTime aExpireTime;
SfxFrameWeak wLoadTargetFrame;
SvKeyValueIteratorRef xAttributes;
svtools::AsynchronLink aDoneLink;
svtools::AsynchronLink aAvailableLink;
uno::Sequence < util::RevisionTag > aVersions;
::utl::TempFile* pTempFile;
uno::Reference < embed::XStorage > m_xZipStorage;
Reference < XInputStream > xInputStream;
Reference < XStream > xStream;
uno::Reference< io::XStream > m_xLockingStream;
sal_uInt32 nLastStorageError;
::rtl::OUString aCharset;
::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xInteraction;
sal_Bool m_bRemoveBackup;
::rtl::OUString m_aBackupURL;
// the following member is changed and makes sence only during saving
// TODO/LATER: in future the signature state should be controlled by the medium not by the document
// in this case the member will hold this information
sal_uInt16 m_nSignatureState;
util::DateTime m_aDateTime;
uno::Reference< logging::XSimpleLogRing > m_xLogRing;
SfxMedium_Impl( SfxMedium* pAntiImplP );
~SfxMedium_Impl();
};
void SfxMedium::DataAvailable_Impl()
{
pImp->aAvailableLink.ClearPendingCall();
pImp->aAvailableLink.Call( NULL );
}
void SfxMedium::Cancel_Impl()
{
SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
//------------------------------------------------------------------
SfxMedium_Impl::SfxMedium_Impl( SfxMedium* pAntiImplP )
: SvCompatWeakBase( pAntiImplP ),
bUpdatePickList(sal_True),
bIsTemp( sal_False ),
bForceSynchron( sal_False ),
bDownloadDone( sal_True ),
bDontCallDoneLinkOnSharingError( sal_False ),
bIsStorage( sal_False ),
bUseInteractionHandler( sal_True ),
bAllowDefaultIntHdl( sal_False ),
bIsCharsetInitialized( sal_False ),
bStorageBasedOnInStream( sal_False ),
m_bSalvageMode( sal_False ),
m_bVersionsAlreadyLoaded( sal_False ),
m_bLocked( sal_False ),
m_bGotDateTime( sal_False ),
pAntiImpl( pAntiImplP ),
nFileVersion( 0 ),
pOrigFilter( 0 ),
aExpireTime( Date() + 10, Time() ),
pTempFile( NULL ),
nLastStorageError( 0 ),
m_bRemoveBackup( sal_False ),
m_nSignatureState( SIGNATURESTATE_NOSIGNATURES )
{
aDoneLink.CreateMutex();
}
//------------------------------------------------------------------
SfxMedium_Impl::~SfxMedium_Impl()
{
aDoneLink.ClearPendingCall();
aAvailableLink.ClearPendingCall();
if ( pTempFile )
delete pTempFile;
}
//================================================================
#define IMPL_CTOR(rootVal,URLVal) \
eError( SVSTREAM_OK ), \
\
bDirect( sal_False ), \
bRoot( rootVal ), \
bSetFilter( sal_False ), \
bTriedStorage( sal_False ), \
\
nStorOpenMode( SFX_STREAM_READWRITE ), \
pURLObj( URLVal ), \
pInStream(0), \
pOutStream( 0 )
//------------------------------------------------------------------
void SfxMedium::ResetError()
{
eError = SVSTREAM_OK;
if( pInStream )
pInStream->ResetError();
if( pOutStream )
pOutStream->ResetError();
}
//------------------------------------------------------------------
sal_uInt32 SfxMedium::GetLastStorageCreationState()
{
return pImp->nLastStorageError;
}
//------------------------------------------------------------------
void SfxMedium::AddLog( const ::rtl::OUString& aMessage )
{
if ( !pImp->m_xLogRing.is() )
{
try
{
::comphelper::ComponentContext aContext( ::comphelper::getProcessServiceFactory() );
if ( aContext.is() )
pImp->m_xLogRing.set( aContext.getSingleton( "com.sun.star.logging.DocumentIOLogRing" ), UNO_QUERY_THROW );
}
catch( uno::Exception& )
{}
}
if ( pImp->m_xLogRing.is() )
pImp->m_xLogRing->logString( aMessage );
}
//------------------------------------------------------------------
void SfxMedium::SetError( sal_uInt32 nError, const ::rtl::OUString& aLogMessage )
{
eError = nError;
if ( eError != ERRCODE_NONE && aLogMessage.getLength() )
AddLog( aLogMessage );
}
//------------------------------------------------------------------
sal_uInt32 SfxMedium::GetErrorCode() const
{
sal_uInt32 lError=eError;
if(!lError && pInStream)
lError=pInStream->GetErrorCode();
if(!lError && pOutStream)
lError=pOutStream->GetErrorCode();
return lError;
}
//------------------------------------------------------------------
void SfxMedium::CheckFileDate( const util::DateTime& aInitDate )
{
GetInitFileDate( sal_True );
if ( pImp->m_aDateTime.Seconds != aInitDate.Seconds
|| pImp->m_aDateTime.Minutes != aInitDate.Minutes
|| pImp->m_aDateTime.Hours != aInitDate.Hours
|| pImp->m_aDateTime.Day != aInitDate.Day
|| pImp->m_aDateTime.Month != aInitDate.Month
|| pImp->m_aDateTime.Year != aInitDate.Year )
{
uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
if ( xHandler.is() )
{
try
{
::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
document::ChangedByOthersRequest() ) );
uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
xInteractionRequestImpl->setContinuations( aContinuations );
xHandler->handle( xInteractionRequestImpl.get() );
::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
{
SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
catch ( uno::Exception& )
{}
}
}
}
//------------------------------------------------------------------
sal_Bool SfxMedium::DocNeedsFileDateCheck()
{
return ( !IsReadOnly() && ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
}
//------------------------------------------------------------------
util::DateTime SfxMedium::GetInitFileDate( sal_Bool bIgnoreOldValue )
{
if ( ( bIgnoreOldValue || !pImp->m_bGotDateTime ) && aLogicName.Len() )
{
try
{
uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
::ucbhelper::Content aContent( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv );
aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "DateModified" )) ) >>= pImp->m_aDateTime;
pImp->m_bGotDateTime = sal_True;
}
catch ( ::com::sun::star::uno::Exception& )
{
}
}
return pImp->m_aDateTime;
}
//------------------------------------------------------------------
Reference < XContent > SfxMedium::GetContent() const
{
if ( !pImp->aContent.get().is() )
{
Reference < ::com::sun::star::ucb::XContent > xContent;
Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
SFX_ITEMSET_ARG( pSet, pItem, SfxUnoAnyItem, SID_CONTENT, sal_False);
if ( pItem )
pItem->GetValue() >>= xContent;
if ( xContent.is() )
{
try
{
pImp->aContent = ::ucbhelper::Content( xContent, xEnv );
}
catch ( Exception& )
{
}
}
else
{
// TODO: DBG_ERROR("SfxMedium::GetContent()\nCreate Content? This code exists as fallback only. Please clarify, why its used.");
String aURL;
if ( aName.Len() )
::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL );
else if ( aLogicName.Len() )
aURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
if ( aURL.Len() )
::ucbhelper::Content::create( aURL, xEnv, pImp->aContent );
}
}
return pImp->aContent.get();
}
//------------------------------------------------------------------
::rtl::OUString SfxMedium::GetBaseURL( bool bForSaving )
{
::rtl::OUString aBaseURL;
const SfxStringItem* pBaseURLItem = static_cast<const SfxStringItem*>( GetItemSet()->GetItem(SID_DOC_BASEURL) );
if ( pBaseURLItem )
aBaseURL = pBaseURLItem->GetValue();
else if ( GetContent().is() )
{
try
{
Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("BaseURI" )) );
aAny >>= aBaseURL;
}
catch ( ::com::sun::star::uno::Exception& )
{
}
if ( !aBaseURL.getLength() )
aBaseURL = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
}
if ( bForSaving )
{
SvtSaveOptions aOpt;
sal_Bool bIsRemote = IsRemote();
if( (bIsRemote && !aOpt.IsSaveRelINet()) || (!bRemote && !aOpt.IsSaveRelFSys()) )
return ::rtl::OUString();
}
return aBaseURL;
}
//------------------------------------------------------------------
SvStream* SfxMedium::GetInStream()
{
if ( pInStream )
{
return pInStream;
}
if ( pImp->pTempFile )
{
pInStream = new SvFileStream( aName, nStorOpenMode );
eError = pInStream->GetError();
if( !eError && (nStorOpenMode & STREAM_WRITE)
&& ! pInStream->IsWritable() )
{
eError = ERRCODE_IO_ACCESSDENIED;
delete pInStream;
pInStream = NULL;
}
else
{
return pInStream;
}
}
GetMedium_Impl();
if ( GetError() )
{
return NULL;
}
return pInStream;
}
//------------------------------------------------------------------
void SfxMedium::CloseInStream()
{
CloseInStream_Impl();
}
void SfxMedium::CloseInStream_Impl()
{
// if there is a storage based on the InStream, we have to
// close the storage, too, because otherwise the storage
// would use an invalid ( deleted ) stream.
if ( pInStream && pImp->xStorage.is() )
{
if ( pImp->bStorageBasedOnInStream )
CloseStorage();
}
if ( pInStream && !GetContent().is() )
{
CreateTempFile( sal_True );
return;
}
DELETEZ( pInStream );
if ( pSet )
pSet->ClearItem( SID_INPUTSTREAM );
CloseZipStorage_Impl();
pImp->xInputStream = uno::Reference< io::XInputStream >();
if ( !pOutStream )
{
// output part of the stream is not used so the whole stream can be closed
// TODO/LATER: is it correct?
pImp->xStream = uno::Reference< io::XStream >();
if ( pSet )
pSet->ClearItem( SID_STREAM );
}
}
//------------------------------------------------------------------
SvStream* SfxMedium::GetOutStream()
{
if ( !pOutStream )
{
// Create a temp. file if there is none because we always
// need one.
CreateTempFile( sal_False );
if ( pImp->pTempFile )
{
pOutStream = new SvFileStream( aName, STREAM_STD_READWRITE );
CloseStorage();
}
}
return pOutStream;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::CloseOutStream()
{
CloseOutStream_Impl();
return sal_True;
}
sal_Bool SfxMedium::CloseOutStream_Impl()
{
if ( pOutStream )
{
// if there is a storage based on the OutStream, we have to
// close the storage, too, because otherwise the storage
// would use an invalid ( deleted ) stream.
//TODO/MBA: how to deal with this?!
//maybe we need a new flag when the storage was created from the outstream
if ( pImp->xStorage.is() )
{
//const SvStream *pStorage = aStorage->GetSvStream();
//if ( pStorage == pOutStream )
CloseStorage();
}
delete pOutStream;
pOutStream = NULL;
}
if ( !pInStream )
{
// input part of the stream is not used so the whole stream can be closed
// TODO/LATER: is it correct?
pImp->xStream = uno::Reference< io::XStream >();
if ( pSet )
pSet->ClearItem( SID_STREAM );
}
return sal_True;
}
//------------------------------------------------------------------
const String& SfxMedium::GetPhysicalName() const
{
if ( !aName.Len() && aLogicName.Len() )
(( SfxMedium*)this)->CreateFileStream();
// return the name then
return aName;
}
//------------------------------------------------------------------
void SfxMedium::CreateFileStream()
{
ForceSynchronStream_Impl( sal_True );
GetInStream();
if( pInStream )
{
CreateTempFile( sal_False );
pImp->bIsTemp = sal_True;
CloseInStream_Impl();
}
}
//------------------------------------------------------------------
sal_Bool SfxMedium::Commit()
{
if( pImp->xStorage.is() )
StorageCommit_Impl();
else if( pOutStream )
pOutStream->Flush();
else if( pInStream )
pInStream->Flush();
if ( GetError() == SVSTREAM_OK )
{
// does something only in case there is a temporary file ( means aName points to different location than aLogicName )
Transfer_Impl();
}
sal_Bool bResult = ( GetError() == SVSTREAM_OK );
if ( bResult && DocNeedsFileDateCheck() )
GetInitFileDate( sal_True );
// remove truncation mode from the flags
nStorOpenMode &= (~STREAM_TRUNC);
return bResult;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::IsStorage()
{
if ( pImp->xStorage.is() )
return sal_True;
if ( bTriedStorage )
return pImp->bIsStorage;
if ( pImp->pTempFile )
{
String aURL;
if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aURL ) )
{
DBG_ERROR("Physical name not convertable!");
}
pImp->bIsStorage = SotStorage::IsStorageFile( aURL ) && !SotStorage::IsOLEStorage( aURL);
if ( !pImp->bIsStorage )
bTriedStorage = sal_True;
}
else if ( GetInStream() )
{
pImp->bIsStorage = SotStorage::IsStorageFile( pInStream ) && !SotStorage::IsOLEStorage( pInStream );
if ( !pInStream->GetError() && !pImp->bIsStorage )
bTriedStorage = sal_True;
}
return pImp->bIsStorage;
}
//------------------------------------------------------------------
Link SfxMedium::GetDataAvailableLink() const
{
return pImp->aAvailableLink.GetLink();
}
//------------------------------------------------------------------
Link SfxMedium::GetDoneLink() const
{
return pImp->aDoneLink.GetLink();
}
//------------------------------------------------------------------
sal_Bool SfxMedium::IsPreview_Impl()
{
sal_Bool bPreview = sal_False;
SFX_ITEMSET_ARG( GetItemSet(), pPreview, SfxBoolItem, SID_PREVIEW, sal_False);
if ( pPreview )
bPreview = pPreview->GetValue();
else
{
SFX_ITEMSET_ARG( GetItemSet(), pFlags, SfxStringItem, SID_OPTIONS, sal_False);
if ( pFlags )
{
String aFileFlags = pFlags->GetValue();
aFileFlags.ToUpperAscii();
if ( STRING_NOTFOUND != aFileFlags.Search( 'B' ) )
bPreview = sal_True;
}
}
return bPreview;
}
//------------------------------------------------------------------
void SfxMedium::StorageBackup_Impl()
{
::ucbhelper::Content aOriginalContent;
Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
sal_Bool bBasedOnOriginalFile = ( !pImp->pTempFile && !( aLogicName.Len() && pImp->m_bSalvageMode )
&& GetURLObject().GetMainURL( INetURLObject::NO_DECODE ).getLength()
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
&& ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) );
if ( bBasedOnOriginalFile && !pImp->m_aBackupURL.getLength()
&& ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aOriginalContent ) )
{
DoInternalBackup_Impl( aOriginalContent );
if( !pImp->m_aBackupURL.getLength() )
SetError( ERRCODE_SFX_CANTCREATEBACKUP, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
//------------------------------------------------------------------
::rtl::OUString SfxMedium::GetBackup_Impl()
{
if ( !pImp->m_aBackupURL.getLength() )
StorageBackup_Impl();
return pImp->m_aBackupURL;
}
//------------------------------------------------------------------
uno::Reference < embed::XStorage > SfxMedium::GetOutputStorage()
{
if ( GetError() )
return uno::Reference< embed::XStorage >();
// if the medium was constructed with a Storage: use this one, not a temp. storage
// if a temporary storage already exists: use it
if ( pImp->xStorage.is() && ( !aLogicName.Len() || pImp->pTempFile ) )
return pImp->xStorage;
// if necessary close stream that was used for reading
if ( pInStream && !pInStream->IsWritable() )
CloseInStream();
DBG_ASSERT( !pOutStream, "OutStream in a readonly Medium?!" );
// TODO/LATER: The current solution is to store the document temporary and then copy it to the target location;
// in future it should be stored directly and then copied to the temporary location, since in this case no
// file attributes have to be preserved and system copying mechanics could be used instead of streaming.
CreateTempFileNoCopy();
return GetStorage();
}
//------------------------------------------------------------------
void SfxMedium::SetEncryptionDataToStorage_Impl()
{
// in case media-descriptor contains password it should be used on opening
if ( pImp->xStorage.is() && pSet )
{
uno::Sequence< beans::NamedValue > aEncryptionData;
if ( GetEncryptionData_Impl( pSet, aEncryptionData ) )
{
// replace the password with encryption data
pSet->ClearItem( SID_PASSWORD );
pSet->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
try
{
::comphelper::OStorageHelper::SetCommonStorageEncryptionData( pImp->xStorage, aEncryptionData );
}
catch( uno::Exception& )
{
OSL_ENSURE( sal_False, "It must be possible to set a common password for the storage" );
// TODO/LATER: set the error code in case of problem
// SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
}
}
//------------------------------------------------------------------
sal_Int8 SfxMedium::ShowLockedDocumentDialog( const uno::Sequence< ::rtl::OUString >& aData, sal_Bool bIsLoading, sal_Bool bOwnLock )
{
sal_Int8 nResult = LOCK_UI_NOLOCK;
// show the interaction regarding the document opening
uno::Reference< task::XInteractionHandler > xHandler = GetInteractionHandler();
if ( ::svt::DocumentLockFile::IsInteractionAllowed() && xHandler.is() && ( bIsLoading || bOwnLock ) )
{
::rtl::OUString aDocumentURL = GetURLObject().GetLastName();
::rtl::OUString aInfo;
::rtl::Reference< ::ucbhelper::InteractionRequest > xInteractionRequestImpl;
if ( bOwnLock )
{
if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
aInfo = aData[LOCKFILE_EDITTIME_ID];
xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
document::OwnLockOnDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo, !bIsLoading ) ) );
}
else
{
if ( aData.getLength() > LOCKFILE_EDITTIME_ID )
{
if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() )
aInfo = aData[LOCKFILE_OOOUSERNAME_ID];
else
aInfo = aData[LOCKFILE_SYSUSERNAME_ID];
if ( aInfo.getLength() && aData[LOCKFILE_EDITTIME_ID].getLength() )
{
aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " ( " ) );
aInfo += aData[LOCKFILE_EDITTIME_ID];
aInfo += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( " )" ) );
}
}
if ( bIsLoading )
{
xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
document::LockedDocumentRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
}
else
{
xInteractionRequestImpl = new ::ucbhelper::InteractionRequest( uno::makeAny(
document::LockedOnSavingRequest( ::rtl::OUString(), uno::Reference< uno::XInterface >(), aDocumentURL, aInfo ) ) );
}
}
uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( 3 );
aContinuations[0] = new ::ucbhelper::InteractionAbort( xInteractionRequestImpl.get() );
aContinuations[1] = new ::ucbhelper::InteractionApprove( xInteractionRequestImpl.get() );
aContinuations[2] = new ::ucbhelper::InteractionDisapprove( xInteractionRequestImpl.get() );
xInteractionRequestImpl->setContinuations( aContinuations );
xHandler->handle( xInteractionRequestImpl.get() );
::rtl::Reference< ::ucbhelper::InteractionContinuation > xSelected = xInteractionRequestImpl->getSelection();
if ( uno::Reference< task::XInteractionAbort >( xSelected.get(), uno::UNO_QUERY ).is() )
{
SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
else if ( uno::Reference< task::XInteractionDisapprove >( xSelected.get(), uno::UNO_QUERY ).is() )
{
// own lock on loading, user has selected to ignore the lock
// own lock on saving, user has selected to ignore the lock
// alien lock on loading, user has selected to edit a copy of document
// TODO/LATER: alien lock on saving, user has selected to do SaveAs to different location
if ( bIsLoading && !bOwnLock )
{
// means that a copy of the document should be opened
GetItemSet()->Put( SfxBoolItem( SID_TEMPLATE, sal_True ) );
}
else if ( bOwnLock )
nResult = LOCK_UI_SUCCEEDED;
}
else // if ( XSelected == aContinuations[1] )
{
// own lock on loading, user has selected to open readonly
// own lock on saving, user has selected to open readonly
// alien lock on loading, user has selected to retry saving
// TODO/LATER: alien lock on saving, user has selected to retry saving
if ( bIsLoading )
GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
else
nResult = LOCK_UI_TRY;
}
}
else
{
if ( bIsLoading )
{
// if no interaction handler is provided the default answer is open readonly
// that usually happens in case the document is loaded per API
// so the document must be opened readonly for backward compatibility
GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
}
else
SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
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
if ( pImp->m_bLocked && 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;
if ( !bResult )
{
// no read-write access is necessary on loading if the document is explicitly opened as copy
SFX_ITEMSET_ARG( GetItemSet(), pTemplateItem, SfxBoolItem, SID_TEMPLATE, sal_False);
bResult = ( bLoading && pTemplateItem && pTemplateItem->GetValue() );
}
if ( !bResult && !IsReadOnly() )
{
sal_Bool bContentReadonly = sal_False;
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
// and to let the writable stream stay open to hold the lock on the document
GetLockingStream_Impl();
}
// "IsReadOnly" property does not allow to detect whether the file is readonly always
// so we try always to open the file for editing
// the file is readonly only in case the read-write stream can not be opened
if ( bLoading && !pImp->m_xLockingStream.is() )
{
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 )
{}
if ( !bContentReadonly )
{
// the file is not readonly, check the ACL
String aPhysPath;
if ( ::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aPhysPath ) )
bContentReadonly = IsReadonlyAccordingACL( aPhysPath.GetBuffer() );
}
}
// do further checks only if the file not readonly in fs
if ( !bContentReadonly )
{
// the special file locking should be used only for file URLs
if ( ::utl::LocalFileHelper::IsLocalFile( aLogicName ) )
{
// in case of storing the document should request the output before locking
if ( bLoading )
{
// let the stream be opened to check the system file locking
GetMedium_Impl();
}
sal_Int8 bUIStatus = LOCK_UI_NOLOCK;
// check whether system file locking has been used, the default value is false
sal_Bool bUseSystemLock = IsSystemFileLockingUsed();
// TODO/LATER: This implementation does not allow to detect the system lock on saving here, actually this is no big problem
// if system lock is used the writeable stream should be available
sal_Bool bHandleSysLocked = ( bLoading && bUseSystemLock && !pImp->xStream.is() && !pOutStream );
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() )
{
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;
}
else
{
// this is no file URL, check whether the file is readonly
bResult = !bContentReadonly;
}
}
}
if ( !bResult && GetError() == ERRCODE_NONE )
{
// the error should be set in case it is storing process
// or the document has been opened for editing explicitly
SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
if ( !bLoading || (pReadOnlyItem && !pReadOnlyItem->GetValue()) )
SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
else
GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
}
// when the file is locked, get the current file date
if ( bResult && DocNeedsFileDateCheck() )
GetInitFileDate( sal_True );
return bResult;
}
//------------------------------------------------------------------
uno::Reference < embed::XStorage > SfxMedium::GetStorage( sal_Bool bCreateTempIfNo )
{
if ( pImp->xStorage.is() || bTriedStorage )
return pImp->xStorage;
uno::Sequence< uno::Any > aArgs( 2 );
// the medium should be retrieved before temporary file creation
// to let the MediaDescriptor be filled with the streams
GetMedium_Impl();
if ( bCreateTempIfNo )
CreateTempFile( sal_False );
GetMedium_Impl();
if ( GetError() )
return pImp->xStorage;
SFX_ITEMSET_ARG( GetItemSet(), pRepairItem, SfxBoolItem, SID_REPAIRPACKAGE, sal_False);
if ( pRepairItem && pRepairItem->GetValue() )
{
// the storage should be created for repairing mode
CreateTempFile( sal_False );
GetMedium_Impl();
Reference< ::com::sun::star::ucb::XProgressHandler > xProgressHandler;
Reference< ::com::sun::star::task::XStatusIndicator > xStatusIndicator;
SFX_ITEMSET_ARG( GetItemSet(), pxProgressItem, SfxUnoAnyItem, SID_PROGRESS_STATUSBAR_CONTROL, sal_False );
if( pxProgressItem && ( pxProgressItem->GetValue() >>= xStatusIndicator ) )
xProgressHandler = Reference< ::com::sun::star::ucb::XProgressHandler >(
new utl::ProgressHandlerWrap( xStatusIndicator ) );
uno::Sequence< beans::PropertyValue > aAddProps( 2 );
aAddProps[0].Name = ::rtl::OUString::createFromAscii( "RepairPackage" );
aAddProps[0].Value <<= (sal_Bool)sal_True;
aAddProps[1].Name = ::rtl::OUString::createFromAscii( "StatusIndicator" );
aAddProps[1].Value <<= xProgressHandler;
// the first arguments will be filled later
aArgs.realloc( 3 );
aArgs[2] <<= aAddProps;
}
if ( pImp->xStream.is() )
{
// since the storage is based on temporary stream we open it always read-write
aArgs[0] <<= pImp->xStream;
aArgs[1] <<= embed::ElementModes::READWRITE;
pImp->bStorageBasedOnInStream = sal_True;
}
else if ( pImp->xInputStream.is() )
{
// since the storage is based on temporary stream we open it always read-write
aArgs[0] <<= pImp->xInputStream;
aArgs[1] <<= embed::ElementModes::READ;
pImp->bStorageBasedOnInStream = sal_True;
}
else
{
CloseStreams_Impl();
aArgs[0] <<= ::rtl::OUString( aName );
aArgs[1] <<= embed::ElementModes::READ;
pImp->bStorageBasedOnInStream = sal_False;
}
try
{
pImp->xStorage = uno::Reference< embed::XStorage >(
::comphelper::OStorageHelper::GetStorageFactory()->createInstanceWithArguments( aArgs ),
uno::UNO_QUERY );
}
catch( uno::Exception& )
{
// impossibility to create the storage is no error
}
if( ( pImp->nLastStorageError = GetError() ) != SVSTREAM_OK )
{
pImp->xStorage = 0;
if ( pInStream )
pInStream->Seek(0);
return uno::Reference< embed::XStorage >();
}
bTriedStorage = sal_True;
// TODO/LATER: Get versionlist on demand
if ( pImp->xStorage.is() )
{
SetEncryptionDataToStorage_Impl();
GetVersionList();
}
SFX_ITEMSET_ARG( pSet, pVersion, SfxInt16Item, SID_VERSION, sal_False);
sal_Bool bResetStorage = sal_False;
if ( pVersion && pVersion->GetValue() )
{
// Alle verf"ugbaren Versionen einlesen
if ( pImp->aVersions.getLength() )
{
// Die zum Kommentar passende Version suchen
// Die Versionen sind von 1 an durchnumeriert, mit negativen
// Versionsnummern werden die Versionen von der aktuellen aus
// r"uckw"arts gez"ahlt
short nVersion = pVersion ? pVersion->GetValue() : 0;
if ( nVersion<0 )
nVersion = ( (short) pImp->aVersions.getLength() ) + nVersion;
else if ( nVersion )
nVersion--;
util::RevisionTag& rTag = pImp->aVersions[nVersion];
{
// SubStorage f"ur alle Versionen "offnen
uno::Reference < embed::XStorage > xSub = pImp->xStorage->openStorageElement( DEFINE_CONST_UNICODE( "Versions" ),
embed::ElementModes::READ );
DBG_ASSERT( xSub.is(), "Versionsliste, aber keine Versionen!" );
// Dort ist die Version als gepackter Stream gespeichert
uno::Reference < io::XStream > xStr = xSub->openStreamElement( rTag.Identifier, embed::ElementModes::READ );
SvStream* pStream = utl::UcbStreamHelper::CreateStream( xStr );
if ( pStream && pStream->GetError() == SVSTREAM_OK )
{
// Stream ins TempDir auspacken
::utl::TempFile aTempFile;
String aTmpName = aTempFile.GetURL();
SvFileStream aTmpStream( aTmpName, SFX_STREAM_READWRITE );
*pStream >> aTmpStream;
aTmpStream.Close();
// Datei als Storage "offnen
nStorOpenMode = SFX_STREAM_READONLY;
pImp->xStorage = comphelper::OStorageHelper::GetStorageFromURL( aTmpName, embed::ElementModes::READ );
pImp->bStorageBasedOnInStream = sal_False;
String aTemp;
::utl::LocalFileHelper::ConvertURLToPhysicalName( aTmpName, aTemp );
SetPhysicalName_Impl( aTemp );
pImp->bIsTemp = sal_True;
GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
// TODO/MBA
pImp->aVersions.realloc(0);
}
else
bResetStorage = sal_True;
}
}
else
bResetStorage = sal_True;
}
if ( bResetStorage )
{
pImp->xStorage = 0;
if ( pInStream )
pInStream->Seek( 0L );
}
pImp->bIsStorage = pImp->xStorage.is();
return pImp->xStorage;
}
//------------------------------------------------------------------
uno::Reference< embed::XStorage > SfxMedium::GetZipStorageToSign_Impl( sal_Bool bReadOnly )
{
if ( !GetError() && !pImp->m_xZipStorage.is() )
{
// very careful!!!
// if bReadOnly == sal_False and there is no temporary file the original file might be used
GetMedium_Impl();
try
{
// we can not sign document if there is no stream
// should it be possible at all?
if ( !bReadOnly && pImp->xStream.is() )
{
pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream, embed::ElementModes::READWRITE );
}
else if ( pImp->xInputStream.is() )
{
pImp->m_xZipStorage = ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream( ZIP_STORAGE_FORMAT_STRING, pImp->xInputStream );
}
}
catch( uno::Exception& )
{
OSL_ENSURE( sal_False, "No possibility to get readonly version of storage from medium!\n" );
}
if ( GetError() ) // do not remove warnings
ResetError();
}
return pImp->m_xZipStorage;
}
//------------------------------------------------------------------
void SfxMedium::CloseZipStorage_Impl()
{
if ( pImp->m_xZipStorage.is() )
{
try {
pImp->m_xZipStorage->dispose();
} catch( uno::Exception& )
{}
pImp->m_xZipStorage = uno::Reference< embed::XStorage >();
}
}
//------------------------------------------------------------------
void SfxMedium::CloseStorage()
{
if ( pImp->xStorage.is() )
{
uno::Reference < lang::XComponent > xComp( pImp->xStorage, uno::UNO_QUERY );
// in the salvage mode the medium does not own the storage
if ( pImp->bDisposeStorage && !pImp->m_bSalvageMode )
{
try {
xComp->dispose();
} catch( uno::Exception& )
{
OSL_ENSURE( sal_False, "Medium's storage is already disposed!\n" );
}
}
pImp->xStorage = 0;
pImp->bStorageBasedOnInStream = sal_False;
}
bTriedStorage = sal_False;
pImp->bIsStorage = sal_False;
}
void SfxMedium::CanDisposeStorage_Impl( sal_Bool bDisposeStorage )
{
pImp->bDisposeStorage = bDisposeStorage;
}
sal_Bool SfxMedium::WillDisposeStorageOnClose_Impl()
{
return pImp->bDisposeStorage;
}
//------------------------------------------------------------------
void SfxMedium::SetOpenMode( StreamMode nStorOpen,
sal_Bool bDirectP,
sal_Bool bDontClose )
{
if ( nStorOpenMode != nStorOpen )
{
nStorOpenMode = nStorOpen;
if( !bDontClose )
{
if ( pImp->xStorage.is() )
CloseStorage();
CloseStreams_Impl();
}
}
bDirect = bDirectP;
bSetFilter = sal_False;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::UseBackupToRestore_Impl( ::ucbhelper::Content& aOriginalContent,
const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
{
try
{
::ucbhelper::Content aTransactCont( pImp->m_aBackupURL, xComEnv );
Reference< XInputStream > aOrigInput = aTransactCont.openStream();
aOriginalContent.writeStream( aOrigInput, sal_True );
return sal_True;
}
catch( Exception& )
{
// in case of failure here the backup file should not be removed
// TODO/LATER: a message should be used to let user know about the backup
pImp->m_bRemoveBackup = sal_False;
// TODO/LATER: needs a specific error code
eError = ERRCODE_IO_GENERAL;
}
return sal_False;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::StorageCommit_Impl()
{
sal_Bool bResult = sal_False;
Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
::ucbhelper::Content aOriginalContent;
if ( pImp->xStorage.is() )
{
if ( !GetError() )
{
uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
if ( xTrans.is() )
{
try
{
xTrans->commit();
CloseZipStorage_Impl();
bResult = sal_True;
}
catch ( embed::UseBackupException& aBackupExc )
{
// since the temporary file is created always now, the scenario is close to be impossible
if ( !pImp->pTempFile )
{
OSL_ENSURE( pImp->m_aBackupURL.getLength(), "No backup on storage commit!\n" );
if ( pImp->m_aBackupURL.getLength()
&& ::ucbhelper::Content::create( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
xDummyEnv,
aOriginalContent ) )
{
// use backup to restore the file
// the storage has already disconnected from original location
CloseAndReleaseStreams_Impl();
if ( !UseBackupToRestore_Impl( aOriginalContent, xDummyEnv ) )
{
// connect the medium to the temporary file of the storage
pImp->aContent = ::ucbhelper::Content();
aName = aBackupExc.TemporaryFileURL;
OSL_ENSURE( aName.Len(), "The exception _must_ contain the temporary URL!\n" );
}
}
if ( !GetError() )
SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
catch ( uno::Exception& )
{
//TODO/LATER: improve error handling
SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
}
}
return bResult;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
const INetURLObject& aDest,
const Reference< ::com::sun::star::ucb::XCommandEnvironment >& xComEnv )
{
sal_Bool bResult = sal_False;
Reference< ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
Reference< XOutputStream > aDestStream;
::ucbhelper::Content aOriginalContent;
try
{
aOriginalContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
}
catch ( ::com::sun::star::ucb::CommandAbortedException& )
{
eError = ERRCODE_ABORT;
}
catch ( ::com::sun::star::ucb::CommandFailedException& )
{
eError = ERRCODE_ABORT;
}
catch (const ::com::sun::star::ucb::ContentCreationException& ex)
{
eError = ERRCODE_IO_GENERAL;
if (
(ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
(ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
)
{
eError = ERRCODE_IO_NOTEXISTSPATH;
}
}
catch (const ::com::sun::star::uno::Exception&)
{
eError = ERRCODE_IO_GENERAL;
}
if( !eError || (eError & ERRCODE_WARNING_MASK) )
{
if ( pImp->xStorage.is() )
CloseStorage();
CloseStreams_Impl();
::ucbhelper::Content aTempCont;
if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xDummyEnv, aTempCont ) )
{
sal_Bool bTransactStarted = sal_False;
SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
sal_Bool bRename = pRename ? pRename->GetValue() : sal_False;
sal_Bool bOverWrite = pOverWrite ? pOverWrite->GetValue() : !bRename;
try
{
if( bOverWrite && ::utl::UCBContentHelper::IsDocument( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) )
{
if( ! pImp->m_aBackupURL.getLength() )
DoInternalBackup_Impl( aOriginalContent );
if( pImp->m_aBackupURL.getLength() )
{
Reference< XInputStream > aTempInput = aTempCont.openStream();
bTransactStarted = sal_True;
aOriginalContent.setPropertyValue( ::rtl::OUString::createFromAscii( "Size" ),
uno::makeAny( (sal_Int64)0 ) );
aOriginalContent.writeStream( aTempInput, bOverWrite );
bResult = sal_True;
}
else
{
eError = ERRCODE_SFX_CANTCREATEBACKUP;
}
}
else
{
Reference< XInputStream > aTempInput = aTempCont.openStream();
aOriginalContent.writeStream( aTempInput, bOverWrite );
bResult = sal_True;
}
}
catch ( ::com::sun::star::ucb::CommandAbortedException& )
{
eError = ERRCODE_ABORT;
}
catch ( ::com::sun::star::ucb::CommandFailedException& )
{
eError = ERRCODE_ABORT;
}
catch ( ::com::sun::star::ucb::InteractiveIOException& r )
{
if ( r.Code == IOErrorCode_ACCESS_DENIED )
eError = ERRCODE_IO_ACCESSDENIED;
else if ( r.Code == IOErrorCode_NOT_EXISTING )
eError = ERRCODE_IO_NOTEXISTS;
else if ( r.Code == IOErrorCode_CANT_READ )
eError = ERRCODE_IO_CANTREAD;
else
eError = ERRCODE_IO_GENERAL;
}
catch ( ::com::sun::star::uno::Exception& )
{
eError = ERRCODE_IO_GENERAL;
}
if ( bResult )
{
if ( pImp->pTempFile )
{
pImp->pTempFile->EnableKillingFile( sal_True );
delete pImp->pTempFile;
pImp->pTempFile = NULL;
}
}
else if ( bTransactStarted )
{
UseBackupToRestore_Impl( aOriginalContent, xDummyEnv );
}
}
else
eError = ERRCODE_IO_CANTREAD;
}
return bResult;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::TryDirectTransfer( const ::rtl::OUString& aURL, SfxItemSet& aTargetSet )
{
if ( GetError() )
return sal_False;
// if the document had no password it should be stored without password
// if the document had password it should be stored with the same password
// otherwise the stream copying can not be done
SFX_ITEMSET_ARG( &aTargetSet, pNewPassItem, SfxStringItem, SID_PASSWORD, sal_False );
SFX_ITEMSET_ARG( GetItemSet(), pOldPassItem, SfxStringItem, SID_PASSWORD, sal_False );
if ( ( !pNewPassItem && !pOldPassItem )
|| ( pNewPassItem && pOldPassItem && pNewPassItem->GetValue().Equals( pOldPassItem->GetValue() ) ) )
{
// the filter must be the same
SFX_ITEMSET_ARG( &aTargetSet, pNewFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
SFX_ITEMSET_ARG( GetItemSet(), pOldFilterItem, SfxStringItem, SID_FILTER_NAME, sal_False );
if ( pNewFilterItem && pOldFilterItem && pNewFilterItem->GetValue().Equals( pOldFilterItem->GetValue() ) )
{
// get the input stream and copy it
// in case of success return true
uno::Reference< io::XInputStream > xInStream = GetInputStream();
ResetError();
if ( xInStream.is() )
{
try
{
uno::Reference< io::XSeekable > xSeek( xInStream, uno::UNO_QUERY );
sal_Int64 nPos = 0;
if ( xSeek.is() )
{
nPos = xSeek->getPosition();
xSeek->seek( 0 );
}
uno::Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
::ucbhelper::Content aTargetContent( aURL, xEnv );
InsertCommandArgument aInsertArg;
aInsertArg.Data = xInStream;
SFX_ITEMSET_ARG( &aTargetSet, pRename, SfxBoolItem, SID_RENAME, sal_False );
SFX_ITEMSET_ARG( &aTargetSet, pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
if ( (pOverWrite && !pOverWrite->GetValue()) // argument says: never overwrite
|| (pRename && pRename->GetValue()) ) // argument says: rename file
aInsertArg.ReplaceExisting = sal_False;
else
aInsertArg.ReplaceExisting = sal_True; // default is overwrite existing files
Any aCmdArg;
aCmdArg <<= aInsertArg;
aTargetContent.executeCommand( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
aCmdArg );
if ( xSeek.is() )
xSeek->seek( nPos );
return sal_True;
}
catch( uno::Exception& )
{}
}
}
}
return sal_False;
}
//------------------------------------------------------------------
void SfxMedium::Transfer_Impl()
{
// The transfer is required only in two cases: either if there is a temporary file or if there is a salvage item
String aNameURL;
if ( pImp->pTempFile )
aNameURL = pImp->pTempFile->GetURL();
else if ( aLogicName.Len() && pImp->m_bSalvageMode )
{
// makes sence only in case logic name is set
if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aNameURL ) )
OSL_ENSURE( sal_False, "The medium name is not convertable!\n" );
}
if ( aNameURL.Len() && ( !eError || (eError & ERRCODE_WARNING_MASK) ) )
{
RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::Transfer_Impl, copying to target" );
Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
Reference< XOutputStream > rOutStream;
// in case an output stream is provided from outside and the URL is correct
// commit to the stream
if( aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL )
{
// TODO/LATER: support storing to SID_STREAM
SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
if( pOutStreamItem && ( pOutStreamItem->GetValue() >>= rOutStream ) )
{
if ( pImp->xStorage.is() )
CloseStorage();
CloseStreams_Impl();
INetURLObject aSource( aNameURL );
::ucbhelper::Content aTempCont;
if( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aTempCont ) )
{
try
{
sal_Int32 nRead;
sal_Int32 nBufferSize = 32767;
Sequence < sal_Int8 > aSequence ( nBufferSize );
Reference< XInputStream > aTempInput = aTempCont.openStream();
do
{
nRead = aTempInput->readBytes ( aSequence, nBufferSize );
if ( nRead < nBufferSize )
{
Sequence < sal_Int8 > aTempBuf ( aSequence.getConstArray(), nRead );
rOutStream->writeBytes ( aTempBuf );
}
else
rOutStream->writeBytes ( aSequence );
}
while ( nRead == nBufferSize );
// remove temporary file
if ( pImp->pTempFile )
{
pImp->pTempFile->EnableKillingFile( sal_True );
delete pImp->pTempFile;
pImp->pTempFile = NULL;
}
}
catch( Exception& )
{}
}
}
else
{
DBG_ERROR( "Illegal Output stream parameter!\n" );
SetError( ERRCODE_IO_GENERAL, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
// free the reference
if ( pSet )
pSet->ClearItem( SID_OUTPUTSTREAM );
return;
}
GetContent();
if ( !pImp->aContent.get().is() )
{
eError = ERRCODE_IO_NOTEXISTS;
return;
}
SFX_ITEMSET_ARG( GetItemSet(), pSegmentSize, SfxInt32Item, SID_SEGMENTSIZE, sal_False);
if ( pSegmentSize )
{
// this file must be stored into a disk spanned package
try
{
uno::Reference < embed::XStorage > xStor = comphelper::OStorageHelper::GetStorageFromURL( GetName(),
embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE );
// set segment size property; package will automatically be divided in pieces fitting
// into this size
::com::sun::star::uno::Any aAny;
aAny <<= pSegmentSize->GetValue();
uno::Reference < beans::XPropertySet > xSet( pImp->xStorage, uno::UNO_QUERY );
xSet->setPropertyValue( String::CreateFromAscii("SegmentSize"), aAny );
// copy the temporary storage into the disk spanned package
GetStorage()->copyToStorage( xStor );
uno::Reference < embed::XTransactedObject > xTrans( pImp->xStorage, uno::UNO_QUERY );
if ( xTrans.is() )
xTrans->commit();
}
catch ( uno::Exception& )
{
//TODO/MBA: error handling
}
return;
}
INetURLObject aDest( GetURLObject() );
// source is the temp file written so far
INetURLObject aSource( aNameURL );
// a special case, an interaction handler should be used for
// authentication in case it is available
Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
if (xInteractionHandler.is())
xComEnv = new ::ucbhelper::CommandEnvironment( xInteractionHandler,
Reference< ::com::sun::star::ucb::XProgressHandler >() );
if ( ::utl::LocalFileHelper::IsLocalFile( aDest.GetMainURL( INetURLObject::NO_DECODE ) ) || !aDest.removeSegment() )
{
TransactedTransferForFS_Impl( aSource, aDest, xComEnv );
}
else
{
// create content for the parent folder and call transfer on that content with the source content
// and the destination file name as parameters
::ucbhelper::Content aSourceContent;
::ucbhelper::Content aTransferContent;
String aFileName = GetLongName();
if ( !aFileName.Len() )
aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
try
{
aTransferContent = ::ucbhelper::Content( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
}
catch (const ::com::sun::star::ucb::ContentCreationException& ex)
{
eError = ERRCODE_IO_GENERAL;
if (
(ex.eError == ::com::sun::star::ucb::ContentCreationError_NO_CONTENT_PROVIDER ) ||
(ex.eError == ::com::sun::star::ucb::ContentCreationError_CONTENT_CREATION_FAILED)
)
{
eError = ERRCODE_IO_NOTEXISTSPATH;
}
}
catch (const ::com::sun::star::uno::Exception&)
{
eError = ERRCODE_IO_GENERAL;
}
if ( !eError || (eError & ERRCODE_WARNING_MASK) )
{
// free resources, otherwise the transfer may fail
if ( pImp->xStorage.is() )
CloseStorage();
CloseStreams_Impl();
::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent );
// check for external parameters that may customize the handling of NameClash situations
SFX_ITEMSET_ARG( GetItemSet(), pRename, SfxBoolItem, SID_RENAME, sal_False );
SFX_ITEMSET_ARG( GetItemSet(), pOverWrite, SfxBoolItem, SID_OVERWRITE, sal_False );
sal_Int32 nNameClash;
if ( pOverWrite && !pOverWrite->GetValue() )
// argument says: never overwrite
nNameClash = NameClash::ERROR;
else if ( pRename && pRename->GetValue() )
// argument says: rename file
nNameClash = NameClash::RENAME;
else
// default is overwrite existing files
nNameClash = NameClash::OVERWRITE;
try
{
if (!aTransferContent.transferContent( aSourceContent, ::ucbhelper::InsertOperation_COPY, aFileName, nNameClash ))
eError = ERRCODE_IO_GENERAL;
}
catch ( ::com::sun::star::ucb::CommandAbortedException& )
{
eError = ERRCODE_ABORT;
}
catch ( ::com::sun::star::ucb::CommandFailedException& )
{
eError = ERRCODE_ABORT;
}
catch ( ::com::sun::star::ucb::InteractiveIOException& r )
{
if ( r.Code == IOErrorCode_ACCESS_DENIED )
eError = ERRCODE_IO_ACCESSDENIED;
else if ( r.Code == IOErrorCode_NOT_EXISTING )
eError = ERRCODE_IO_NOTEXISTS;
else if ( r.Code == IOErrorCode_CANT_READ )
eError = ERRCODE_IO_CANTREAD;
else
eError = ERRCODE_IO_GENERAL;
}
catch ( ::com::sun::star::uno::Exception& )
{
eError = ERRCODE_IO_GENERAL;
}
// do not switch from temporary file in case of nonfile protocol
}
}
if ( ( !eError || (eError & ERRCODE_WARNING_MASK) ) && !pImp->pTempFile )
{
// without a TempFile the physical and logical name should be the same after successful transfer
::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ),
aName );
pImp->m_bSalvageMode = sal_False;
}
}
}
//------------------------------------------------------------------
void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent,
const String& aPrefix,
const String& aExtension,
const String& aDestDir )
{
RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoInternalBackup_Impl( with destdir )" );
if ( pImp->m_aBackupURL.getLength() )
return; // the backup was done already
::utl::TempFile aTransactTemp( aPrefix, &aExtension, &aDestDir );
aTransactTemp.EnableKillingFile( sal_False );
INetURLObject aBackObj( aTransactTemp.GetURL() );
::rtl::OUString aBackupName = aBackObj.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
Reference < ::com::sun::star::ucb::XCommandEnvironment > xDummyEnv;
::ucbhelper::Content aBackupCont;
if( ::ucbhelper::Content::create( aDestDir, xDummyEnv, aBackupCont ) )
{
try
{
if( aBackupCont.transferContent( aOriginalContent,
::ucbhelper::InsertOperation_COPY,
aBackupName,
NameClash::OVERWRITE ) )
{
pImp->m_aBackupURL = aBackObj.GetMainURL( INetURLObject::NO_DECODE );
pImp->m_bRemoveBackup = sal_True;
}
}
catch( Exception& )
{}
}
if ( !pImp->m_aBackupURL.getLength() )
aTransactTemp.EnableKillingFile( sal_True );
}
//------------------------------------------------------------------
void SfxMedium::DoInternalBackup_Impl( const ::ucbhelper::Content& aOriginalContent )
{
if ( pImp->m_aBackupURL.getLength() )
return; // the backup was done already
::rtl::OUString aFileName = GetURLObject().getName( INetURLObject::LAST_SEGMENT,
true,
INetURLObject::NO_DECODE );
sal_Int32 nPrefixLen = aFileName.lastIndexOf( '.' );
String aPrefix = ( nPrefixLen == -1 ) ? aFileName : aFileName.copy( 0, nPrefixLen );
String aExtension = ( nPrefixLen == -1 ) ? String() : String(aFileName.copy( nPrefixLen ));
String aBakDir = SvtPathOptions().GetBackupPath();
DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aBakDir );
if ( !pImp->m_aBackupURL.getLength() )
{
// the copiing to the backup catalog failed ( for example because
// of using an encrypted partition as target catalog )
// since the user did not specify to make backup explicitly
// office should try to make backup in another place,
// target catalog does not look bad for this case ( and looks
// to be the only way for encrypted partitions )
INetURLObject aDest = GetURLObject();
if ( aDest.removeSegment() )
DoInternalBackup_Impl( aOriginalContent, aPrefix, aExtension, aDest.GetMainURL( INetURLObject::NO_DECODE ) );
}
}
//------------------------------------------------------------------
void SfxMedium::DoBackup_Impl()
{
RTL_LOGFILE_CONTEXT( aLog, "sfx2 (mv76033) SfxMedium::DoBackup_Impl" );
// source file name is the logical name of this medium
INetURLObject aSource( GetURLObject() );
// there is nothing to backup in case source file does not exist
if ( !::utl::UCBContentHelper::IsDocument( aSource.GetMainURL( INetURLObject::NO_DECODE ) ) )
return;
sal_Bool bSuccess = sal_False;
// get path for backups
String aBakDir = SvtPathOptions().GetBackupPath();
if( aBakDir.Len() )
{
// create content for the parent folder ( = backup folder )
::ucbhelper::Content aContent;
Reference < ::com::sun::star::ucb::XCommandEnvironment > xEnv;
if( ::ucbhelper::Content::create( aBakDir, xEnv, aContent ) )
{
// save as ".bak" file
INetURLObject aDest( aBakDir );
aDest.insertName( aSource.getName() );
aDest.setExtension( DEFINE_CONST_UNICODE( "bak" ) );
String aFileName = aDest.getName( INetURLObject::LAST_SEGMENT, true, INetURLObject::DECODE_WITH_CHARSET );
// create a content for the source file
::ucbhelper::Content aSourceContent;
if ( ::ucbhelper::Content::create( aSource.GetMainURL( INetURLObject::NO_DECODE ), xEnv, aSourceContent ) )
{
try
{
// do the transfer ( copy source file to backup dir )
bSuccess = aContent.transferContent( aSourceContent,
::ucbhelper::InsertOperation_COPY,
aFileName,
NameClash::OVERWRITE );
if( bSuccess )
{
pImp->m_aBackupURL = aDest.GetMainURL( INetURLObject::NO_DECODE );
pImp->m_bRemoveBackup = sal_False;
}
}
catch ( ::com::sun::star::uno::Exception& )
{
}
}
}
}
if ( !bSuccess )
{
eError = ERRCODE_SFX_CANTCREATEBACKUP;
}
}
//------------------------------------------------------------------
void SfxMedium::ClearBackup_Impl()
{
if( pImp->m_bRemoveBackup )
{
// currently a document is always stored in a new medium,
// thus if a backup can not be removed the backup URL should not be cleaned
if ( pImp->m_aBackupURL.getLength() )
{
if ( ::utl::UCBContentHelper::Kill( pImp->m_aBackupURL ) )
// || !::utl::UCBContentHelper::IsDocument( pImp->m_aBackupURL ) );
{
pImp->m_bRemoveBackup = sal_False;
pImp->m_aBackupURL = ::rtl::OUString();
}
else
{
DBG_ERROR("Couldn't remove backup file!");
}
}
}
else
pImp->m_aBackupURL = ::rtl::OUString();
}
//----------------------------------------------------------------
void SfxMedium::GetLockingStream_Impl()
{
if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
&& !pImp->m_xLockingStream.is() )
{
SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
if ( pWriteStreamItem )
pWriteStreamItem->GetValue() >>= pImp->m_xLockingStream;
if ( !pImp->m_xLockingStream.is() )
{
// open the original document
uno::Sequence< beans::PropertyValue > xProps;
TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
comphelper::MediaDescriptor aMedium( xProps );
aMedium.addInputStreamOwnLock();
uno::Reference< io::XInputStream > xInputStream;
aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->m_xLockingStream;
aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= xInputStream;
if ( !pImp->pTempFile && !aName.Len() )
{
// the medium is still based on the original file, it makes sence to initialize the streams
if ( pImp->m_xLockingStream.is() )
pImp->xStream = pImp->m_xLockingStream;
if ( xInputStream.is() )
pImp->xInputStream = xInputStream;
if ( !pImp->xInputStream.is() && pImp->xStream.is() )
pImp->xInputStream = pImp->xStream->getInputStream();
}
}
}
}
//----------------------------------------------------------------
void SfxMedium::GetMedium_Impl()
{
if ( !pInStream )
{
pImp->bDownloadDone = sal_False;
Reference< ::com::sun::star::task::XInteractionHandler > xInteractionHandler = GetInteractionHandler();
//TODO/MBA: need support for SID_STREAM
SFX_ITEMSET_ARG( pSet, pWriteStreamItem, SfxUnoAnyItem, SID_STREAM, sal_False);
SFX_ITEMSET_ARG( pSet, pInStreamItem, SfxUnoAnyItem, SID_INPUTSTREAM, sal_False);
if ( pWriteStreamItem )
{
pWriteStreamItem->GetValue() >>= pImp->xStream;
if ( pInStreamItem )
pInStreamItem->GetValue() >>= pImp->xInputStream;
if ( !pImp->xInputStream.is() && pImp->xStream.is() )
pImp->xInputStream = pImp->xStream->getInputStream();
}
else if ( pInStreamItem )
{
pInStreamItem->GetValue() >>= pImp->xInputStream;
}
else
{
uno::Sequence < beans::PropertyValue > xProps;
String aFileName;
if ( aName.Len() )
{
if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aFileName ) )
{
DBG_ERROR("Physical name not convertable!");
}
}
else
aFileName = GetName();
// in case the temporary file exists the streams should be initialized from it,
// but the original MediaDescriptor should not be changed
sal_Bool bFromTempFile = ( pImp->pTempFile != NULL );
if ( !bFromTempFile )
{
GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, aFileName ) );
if( !(nStorOpenMode & STREAM_WRITE ) )
GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
if (xInteractionHandler.is())
GetItemSet()->Put( SfxUnoAnyItem( SID_INTERACTIONHANDLER, makeAny(xInteractionHandler) ) );
}
if ( m_xInputStreamToLoadFrom.is() )
{
pImp->xInputStream = m_xInputStreamToLoadFrom;
pImp->xInputStream->skipBytes(0);
if(m_bIsReadOnly)
GetItemSet()->Put( SfxBoolItem( SID_DOC_READONLY, sal_True ) );
// m_xInputStreamToLoadFrom = 0;
}
else
{
TransformItems( SID_OPENDOC, *GetItemSet(), xProps );
comphelper::MediaDescriptor aMedium( xProps );
if ( pImp->m_xLockingStream.is() && !bFromTempFile )
{
// the medium is not based on the temporary file, so the original stream can be used
pImp->xStream = pImp->m_xLockingStream;
}
else
{
if ( bFromTempFile )
{
aMedium[comphelper::MediaDescriptor::PROP_URL()] <<= ::rtl::OUString( aFileName );
aMedium.erase( comphelper::MediaDescriptor::PROP_READONLY() );
aMedium.addInputStream();
}
else if ( ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
{
// use the special locking approach only for file URLs
aMedium.addInputStreamOwnLock();
}
else
aMedium.addInputStream();
// the ReadOnly property set in aMedium is ignored
// the check is done in LockOrigFileOnDemand() for file and non-file URLs
//TODO/MBA: what happens if property is not there?!
aMedium[comphelper::MediaDescriptor::PROP_STREAM()] >>= pImp->xStream;
aMedium[comphelper::MediaDescriptor::PROP_INPUTSTREAM()] >>= pImp->xInputStream;
}
GetContent();
if ( !pImp->xInputStream.is() && pImp->xStream.is() )
pImp->xInputStream = pImp->xStream->getInputStream();
}
if ( !bFromTempFile )
{
//TODO/MBA: need support for SID_STREAM
if ( pImp->xStream.is() )
GetItemSet()->Put( SfxUsrAnyItem( SID_STREAM, makeAny( pImp->xStream ) ) );
GetItemSet()->Put( SfxUsrAnyItem( SID_INPUTSTREAM, makeAny( pImp->xInputStream ) ) );
}
}
//TODO/MBA: ErrorHandling - how to transport error from MediaDescriptor
if ( !GetError() && !pImp->xStream.is() && !pImp->xInputStream.is() )
{
SetError( ERRCODE_IO_ACCESSDENIED, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
if ( !GetError() )
{
if ( pImp->xStream.is() )
{
pInStream = utl::UcbStreamHelper::CreateStream( pImp->xStream );
}
else if ( pImp->xInputStream.is() )
{
pInStream = utl::UcbStreamHelper::CreateStream( pImp->xInputStream );
}
}
pImp->bDownloadDone = sal_True;
pImp->aDoneLink.ClearPendingCall();
pImp->aDoneLink.Call( (void*) GetError() );
}
}
//----------------------------------------------------------------
sal_Bool SfxMedium::IsRemote()
{
return bRemote;
}
//------------------------------------------------------------------
void SfxMedium::SetUpdatePickList(sal_Bool bVal)
{
if(!pImp)
pImp = new SfxMedium_Impl( this );
pImp->bUpdatePickList = bVal;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::IsUpdatePickList() const
{
return pImp? pImp->bUpdatePickList: sal_True;
}
//----------------------------------------------------------------
void SfxMedium::SetDoneLink( const Link& rLink )
{
pImp->aDoneLink = rLink;
}
//----------------------------------------------------------------
void SfxMedium::SetDataAvailableLink( const Link& rLink )
{
pImp->aAvailableLink = rLink;
}
//----------------------------------------------------------------
void SfxMedium::StartDownload()
{
GetInStream();
}
void SfxMedium::DownLoad( const Link& aLink )
{
SetDoneLink( aLink );
GetInStream();
if ( pInStream && !aLink.IsSet() )
{
while( !pImp->bDownloadDone )
Application::Yield();
}
}
//------------------------------------------------------------------
void SfxMedium::Init_Impl()
/* [Beschreibung]
Setzt in den Logischen Namen eine gueltige ::com::sun::star::util::URL (Falls zuvor ein Filename
drin war) und setzt den physikalschen Namen auf den Filenamen, falls
vorhanden.
*/
{
Reference< XOutputStream > rOutStream;
// TODO/LATER: handle lifetime of storages
pImp->bDisposeStorage = sal_False;
SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False);
if ( pSalvageItem && !pSalvageItem->GetValue().Len() )
{
pSalvageItem = NULL;
pSet->ClearItem( SID_DOC_SALVAGE );
}
if( aLogicName.Len() )
{
INetURLObject aUrl( aLogicName );
INetProtocol eProt = aUrl.GetProtocol();
if ( eProt == INET_PROT_NOT_VALID )
{
DBG_ERROR ( "Unknown protocol!" );
}
else
{
if ( aUrl.HasMark() )
{
aLogicName = aUrl.GetURLNoMark( INetURLObject::NO_DECODE );
GetItemSet()->Put( SfxStringItem( SID_JUMPMARK, aUrl.GetMark() ) );
}
// try to convert the URL into a physical name - but never change a physical name
// physical name may be set if the logical name is changed after construction
if ( !aName.Len() )
::utl::LocalFileHelper::ConvertURLToPhysicalName( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ), aName );
else {
DBG_ASSERT( pSalvageItem, "Suspicious change of logical name!" );
}
}
}
if ( pSalvageItem && pSalvageItem->GetValue().Len() )
{
aLogicName = pSalvageItem->GetValue();
DELETEZ( pURLObj );
pImp->m_bSalvageMode = sal_True;
}
// in case output stream is by mistake here
// clear the reference
SFX_ITEMSET_ARG( pSet, pOutStreamItem, SfxUnoAnyItem, SID_OUTPUTSTREAM, sal_False);
if( pOutStreamItem
&& ( !( pOutStreamItem->GetValue() >>= rOutStream )
|| !aLogicName.CompareToAscii( "private:stream", 14 ) == COMPARE_EQUAL ) )
{
pSet->ClearItem( SID_OUTPUTSTREAM );
DBG_ERROR( "Unexpected Output stream parameter!\n" );
}
if ( aLogicName.Len() )
{
// if the logic name is set it should be set in MediaDescriptor as well
SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
if ( !pFileNameItem )
{
// let the ItemSet be created if necessary
GetItemSet()->Put( SfxStringItem( SID_FILE_NAME, INetURLObject( aLogicName ).GetMainURL( INetURLObject::NO_DECODE ) ) );
}
}
SetIsRemote_Impl();
}
//------------------------------------------------------------------
SfxMedium::SfxMedium()
: IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
pFilter(0),
pSet(0),
pImp(new SfxMedium_Impl( this ))
{
Init_Impl();
}
//------------------------------------------------------------------
SfxMedium::SfxMedium( const SfxMedium& rMedium, sal_Bool bTemporary )
: SvRefBase(),
IMPL_CTOR( sal_True, // bRoot, pURLObj
rMedium.pURLObj ? new INetURLObject(*rMedium.pURLObj) : 0 ),
pImp(new SfxMedium_Impl( this ))
{
bDirect = rMedium.IsDirect();
nStorOpenMode = rMedium.GetOpenMode();
if ( !bTemporary )
aName = rMedium.aName;
pImp->bIsTemp = bTemporary;
DBG_ASSERT( ! rMedium.pImp->bIsTemp, "Temporaeres Medium darf nicht kopiert werden" );
aLogicName = rMedium.aLogicName;
pSet = rMedium.GetItemSet() ? new SfxItemSet(*rMedium.GetItemSet()) : 0;
pFilter = rMedium.pFilter;
Init_Impl();
if( bTemporary )
CreateTempFile( sal_True );
}
//------------------------------------------------------------------
void SfxMedium::UseInteractionHandler( sal_Bool bUse )
{
pImp->bAllowDefaultIntHdl = bUse;
}
//------------------------------------------------------------------
::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >
SfxMedium::GetInteractionHandler()
{
// if interaction isnt allowed explicitly ... return empty reference!
if ( !pImp->bUseInteractionHandler )
return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
// search a possible existing handler inside cached item set
if ( pSet )
{
::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler > xHandler;
SFX_ITEMSET_ARG( pSet, pHandler, SfxUnoAnyItem, SID_INTERACTIONHANDLER, sal_False);
if ( pHandler && (pHandler->GetValue() >>= xHandler) && xHandler.is() )
return xHandler;
}
// if default interaction isnt allowed explicitly ... return empty reference!
if ( !pImp->bAllowDefaultIntHdl )
return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
// otherwhise return cached default handler ... if it exist.
if ( pImp->xInteraction.is() )
return pImp->xInteraction;
// create default handler and cache it!
::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory > xFactory = ::comphelper::getProcessServiceFactory();
if ( xFactory.is() )
{
pImp->xInteraction = ::com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler >( xFactory->createInstance( DEFINE_CONST_UNICODE("com.sun.star.task.InteractionHandler") ), ::com::sun::star::uno::UNO_QUERY );
return pImp->xInteraction;
}
return ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >();
}
//----------------------------------------------------------------
void SfxMedium::SetFilter( const SfxFilter* pFilterP, sal_Bool /*bResetOrig*/ )
{
pFilter = pFilterP;
pImp->nFileVersion = 0;
}
//----------------------------------------------------------------
const SfxFilter* SfxMedium::GetOrigFilter( sal_Bool bNotCurrent ) const
{
return ( pImp->pOrigFilter || bNotCurrent ) ? pImp->pOrigFilter : pFilter;
}
//----------------------------------------------------------------
void SfxMedium::SetOrigFilter_Impl( const SfxFilter* pOrigFilter )
{
pImp->pOrigFilter = pOrigFilter;
}
//------------------------------------------------------------------
sal_uInt32 SfxMedium::CreatePasswordToModifyHash( const ::rtl::OUString& aPasswd, sal_Bool bWriter )
{
sal_uInt32 nHash = 0;
if ( aPasswd.getLength() )
{
if ( bWriter )
{
nHash = ::comphelper::DocPasswordHelper::GetWordHashAsUINT32( aPasswd );
}
else
{
rtl_TextEncoding nEncoding = RTL_TEXTENCODING_UTF8;
// if the MS-filter should be used
// use the inconsistent algorithm to find the encoding specified by MS
nEncoding = osl_getThreadTextEncoding();
switch( nEncoding )
{
case RTL_TEXTENCODING_ISO_8859_15:
case RTL_TEXTENCODING_MS_874:
case RTL_TEXTENCODING_MS_1250:
case RTL_TEXTENCODING_MS_1251:
case RTL_TEXTENCODING_MS_1252:
case RTL_TEXTENCODING_MS_1253:
case RTL_TEXTENCODING_MS_1254:
case RTL_TEXTENCODING_MS_1255:
case RTL_TEXTENCODING_MS_1256:
case RTL_TEXTENCODING_MS_1257:
case RTL_TEXTENCODING_MS_1258:
case RTL_TEXTENCODING_SHIFT_JIS:
case RTL_TEXTENCODING_GB_2312:
case RTL_TEXTENCODING_BIG5:
// in case the system uses an encoding from the list above, it should be used
break;
default:
// in case other encoding is used, use one of the encodings from the list
nEncoding = RTL_TEXTENCODING_MS_1250;
break;
}
nHash = ::comphelper::DocPasswordHelper::GetXLHashAsUINT16( aPasswd, nEncoding );
}
}
return nHash;
}
//------------------------------------------------------------------
void SfxMedium::Close()
{
if ( pImp->xStorage.is() )
{
// don't close the streams if they belong to the
// storage
//TODO/MBA: how to?! Do we need the flag?!
/*
const SvStream *pStream = aStorage->GetSvStream();
if ( pStream && pStream == pInStream )
{
CloseZipStorage_Impl();
pInStream = NULL;
pImp->xInputStream = Reference < XInputStream >();
pImp->xLockBytes.Clear();
if ( pSet )
pSet->ClearItem( SID_INPUTSTREAM );
aStorage->SetDeleteStream( sal_True );
}
else if ( pStream && pStream == pOutStream )
{
pOutStream = NULL;
aStorage->SetDeleteStream( sal_True );
} */
CloseStorage();
}
CloseStreams_Impl();
UnlockFile( sal_False );
}
void SfxMedium::CloseAndRelease()
{
if ( pImp->xStorage.is() )
{
// don't close the streams if they belong to the
// storage
//TODO/MBA: how to?! Do we need the flag?!
/*
const SvStream *pStream = aStorage->GetSvStream();
if ( pStream && pStream == pInStream )
{
CloseZipStorage_Impl();
pInStream = NULL;
pImp->xInputStream = Reference < XInputStream >();
pImp->xLockBytes.Clear();
if ( pSet )
pSet->ClearItem( SID_INPUTSTREAM );
aStorage->SetDeleteStream( sal_True );
}
else if ( pStream && pStream == pOutStream )
{
pOutStream = NULL;
aStorage->SetDeleteStream( sal_True );
} */
CloseStorage();
}
CloseAndReleaseStreams_Impl();
UnlockFile( sal_True );
}
void SfxMedium::UnlockFile( sal_Bool bReleaseLockStream )
{
if ( pImp->m_xLockingStream.is() )
{
if ( bReleaseLockStream )
{
try
{
uno::Reference< io::XInputStream > xInStream = pImp->m_xLockingStream->getInputStream();
uno::Reference< io::XOutputStream > xOutStream = pImp->m_xLockingStream->getOutputStream();
if ( xInStream.is() )
xInStream->closeInput();
if ( xOutStream.is() )
xOutStream->closeOutput();
}
catch( uno::Exception& )
{}
}
pImp->m_xLockingStream = uno::Reference< io::XStream >();
}
if ( pImp->m_bLocked )
{
try
{
pImp->m_bLocked = sal_False;
::svt::DocumentLockFile aLockFile( aLogicName );
// TODO/LATER: A warning could be shown in case the file is not the own one
aLockFile.RemoveFile();
}
catch( uno::Exception& )
{}
}
}
void SfxMedium::CloseAndReleaseStreams_Impl()
{
CloseZipStorage_Impl();
uno::Reference< io::XInputStream > xInToClose = pImp->xInputStream;
uno::Reference< io::XOutputStream > xOutToClose;
if ( pImp->xStream.is() )
{
xOutToClose = pImp->xStream->getOutputStream();
// if the locking stream is closed here the related member should be cleaned
if ( pImp->xStream == pImp->m_xLockingStream )
pImp->m_xLockingStream = uno::Reference< io::XStream >();
}
// The probably exsisting SvStream wrappers should be closed first
CloseStreams_Impl();
// in case of salvage mode the storage is based on the streams
if ( !pImp->m_bSalvageMode )
{
try
{
if ( xInToClose.is() )
xInToClose->closeInput();
if ( xOutToClose.is() )
xOutToClose->closeOutput();
}
catch ( uno::Exception& )
{
}
}
}
//------------------------------------------------------------------
void SfxMedium::CloseStreams_Impl()
{
CloseInStream_Impl();
CloseOutStream_Impl();
if ( pSet )
pSet->ClearItem( SID_CONTENT );
pImp->aContent = ::ucbhelper::Content();
}
//------------------------------------------------------------------
void SfxMedium::RefreshName_Impl()
{
#if 0 //(dv)
if ( pImp->aContent.get().is() )
{
String aNameP = pImp->xAnchor->GetViewURL();
pImp->aOrigURL = aNameP;
aLogicName = aNameP;
DELETEZ( pURLObj );
if (aLogicName.Len())
aLogicName = GetURLObject().GetMainURL( INetURLObject::NO_DECODE );
SetIsRemote_Impl();
}
#endif //(dv)
}
void SfxMedium::SetIsRemote_Impl()
{
INetURLObject aObj( GetName() );
switch( aObj.GetProtocol() )
{
case INET_PROT_FTP:
case INET_PROT_HTTP:
case INET_PROT_HTTPS:
case INET_PROT_POP3:
case INET_PROT_NEWS:
case INET_PROT_IMAP:
// case INET_PROT_OUT:
case INET_PROT_VIM:
bRemote = sal_True; break;
default:
bRemote = ( GetName().CompareToAscii( "private:msgid", 13 ) == COMPARE_EQUAL );
break;
}
// Da Dateien, die Remote geschrieben werden zur Uebertragung auch
// gelesen werden koennen muessen
if( bRemote )
nStorOpenMode |= STREAM_READ;
}
void SfxMedium::SetName( const String& aNameP, sal_Bool bSetOrigURL )
{
if( !pImp->aOrigURL.Len() )
pImp->aOrigURL = aLogicName;
if( bSetOrigURL )
pImp->aOrigURL = aNameP;
aLogicName = aNameP;
DELETEZ( pURLObj );
pImp->aContent = ::ucbhelper::Content();
Init_Impl();
}
//----------------------------------------------------------------
const String& SfxMedium::GetOrigURL() const
{
return !pImp->aOrigURL.Len() ? (String &)aLogicName : pImp->aOrigURL;
}
//----------------------------------------------------------------
void SfxMedium::SetPhysicalName_Impl( const String& rNameP )
{
if ( rNameP != aName )
{
if( pImp->pTempFile )
{
delete pImp->pTempFile;
pImp->pTempFile = NULL;
}
if ( aName.Len() || rNameP.Len() )
pImp->aContent = ::ucbhelper::Content();
aName = rNameP;
bTriedStorage = sal_False;
pImp->bIsStorage = sal_False;
}
}
//------------------------------------------------------------------
void SfxMedium::SetTemporary( sal_Bool bTemp )
{
pImp->bIsTemp = bTemp;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::IsTemporary() const
{
return pImp->bIsTemp;
}
//------------------------------------------------------------------
sal_Bool SfxMedium::Exists( sal_Bool /*bForceSession*/ )
{
DBG_ERROR( "Not implemented!" );
return sal_True;
}
//------------------------------------------------------------------
void SfxMedium::ReOpen()
{
sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler;
pImp->bUseInteractionHandler = sal_False;
GetMedium_Impl();
pImp->bUseInteractionHandler = bUseInteractionHandler;
}
//------------------------------------------------------------------
void SfxMedium::CompleteReOpen()
{
// do not use temporary file for reopen and in case of success throw the temporary file away
sal_Bool bUseInteractionHandler = pImp->bUseInteractionHandler;
pImp->bUseInteractionHandler = sal_False;
::utl::TempFile* pTmpFile = NULL;
if ( pImp->pTempFile )
{
pTmpFile = pImp->pTempFile;
pImp->pTempFile = NULL;
aName = String();
}
GetMedium_Impl();
if ( GetError() )
{
if ( pImp->pTempFile )
{
pImp->pTempFile->EnableKillingFile( sal_True );
delete pImp->pTempFile;
}
pImp->pTempFile = pTmpFile;
if ( pImp->pTempFile )
aName = pImp->pTempFile->GetFileName();
}
else
{
pTmpFile->EnableKillingFile( sal_True );
delete pTmpFile;
}
pImp->bUseInteractionHandler = bUseInteractionHandler;
}
//------------------------------------------------------------------
SfxMedium::SfxMedium
(
const String &rName, StreamMode nOpenMode, sal_Bool bDirectP,
const SfxFilter *pFlt, SfxItemSet *pInSet
)
: IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
pFilter(pFlt),
pSet( pInSet ),
pImp(new SfxMedium_Impl( this ))
{
aLogicName = rName;
nStorOpenMode = nOpenMode;
bDirect = bDirectP;
Init_Impl();
}
SfxMedium::SfxMedium( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArgs )
: IMPL_CTOR( sal_False, 0 ), // bRoot, pURLObj
pFilter(0),
pSet(0),
pImp(new SfxMedium_Impl( this ))
{
SfxAllItemSet *pParams = new SfxAllItemSet( SFX_APP()->GetPool() );
pSet = pParams;
TransformParameters( SID_OPENDOC, aArgs, *pParams );
String aFilterName;
SFX_ITEMSET_ARG( pSet, pFilterNameItem, SfxStringItem, SID_FILTER_NAME, sal_False );
if( pFilterNameItem )
aFilterName = pFilterNameItem->GetValue();
pFilter = SFX_APP()->GetFilterMatcher().GetFilter4FilterName( aFilterName );
sal_Bool bSalvage = sal_False;
SFX_ITEMSET_ARG( pSet, pSalvageItem, SfxStringItem, SID_DOC_SALVAGE, sal_False );
if( pSalvageItem )
{
// QUESTION: there is some treatment of Salvage in Init_Impl; align!
bSalvage = sal_True;
if ( pSalvageItem->GetValue().Len() )
{
// if an URL is provided in SalvageItem that means that the FileName refers to a temporary file
// that must be copied here
SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
if (!pFileNameItem) throw uno::RuntimeException();
::rtl::OUString aNewTempFileURL = SfxMedium::CreateTempCopyWithExt( pFileNameItem->GetValue() );
if ( aNewTempFileURL.getLength() )
{
pSet->Put( SfxStringItem( SID_FILE_NAME, aNewTempFileURL ) );
pSet->ClearItem( SID_INPUTSTREAM );
pSet->ClearItem( SID_STREAM );
pSet->ClearItem( SID_CONTENT );
}
else
{
OSL_ENSURE( sal_False, "Can not create a new temporary file for crash recovery!\n" );
}
}
}
sal_Bool bReadOnly = sal_False;
SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
bReadOnly = sal_True;
SFX_ITEMSET_ARG( pSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False );
if (!pFileNameItem) throw uno::RuntimeException();
aLogicName = pFileNameItem->GetValue();
nStorOpenMode = bReadOnly ? SFX_STREAM_READONLY : SFX_STREAM_READWRITE;
bDirect = sal_False;
Init_Impl();
}
//------------------------------------------------------------------
SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const SfxItemSet* p, sal_Bool bRootP )
: IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj
pSet(0),
pImp( new SfxMedium_Impl( this ))
{
String aType = SfxFilter::GetTypeFromStorage( rStor );
pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( aType );
DBG_ASSERT( pFilter, "No Filter for storage found!" );
Init_Impl();
pImp->xStorage = rStor;
pImp->bDisposeStorage = sal_False;
// always take BaseURL first, could be overwritten by ItemSet
GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
if ( p )
GetItemSet()->Put( *p );
}
SfxMedium::SfxMedium( const uno::Reference < embed::XStorage >& rStor, const String& rBaseURL, const String& rTypeName, const SfxItemSet* p, sal_Bool bRootP )
: IMPL_CTOR( bRootP, 0 ), // bRoot, pURLObj
pSet(0),
pImp( new SfxMedium_Impl( this ))
{
pFilter = SFX_APP()->GetFilterMatcher().GetFilter4EA( rTypeName );
DBG_ASSERT( pFilter, "No Filter for storage found!" );
Init_Impl();
pImp->xStorage = rStor;
pImp->bDisposeStorage = sal_False;
// always take BaseURL first, could be overwritten by ItemSet
GetItemSet()->Put( SfxStringItem( SID_DOC_BASEURL, rBaseURL ) );
if ( p )
GetItemSet()->Put( *p );
}
//------------------------------------------------------------------
SfxMedium::~SfxMedium()
{
/* Attention
Don't enable CancelTransfers() till you know that the writer/web has changed his asynchronous load
behaviour. Otherwhise may StyleSheets inside a html file will be loaded at the right time.
=> further the help will be empty then ... #100490#
*/
//CancelTransfers();
// if there is a requirement to clean the backup this is the last possibility to do it
ClearBackup_Impl();
Close();
delete pSet;
if( pImp->bIsTemp && aName.Len() )
{
String aTemp;
if ( !::utl::LocalFileHelper::ConvertPhysicalNameToURL( aName, aTemp ))
{
DBG_ERROR("Physical name not convertable!");
}
if ( !::utl::UCBContentHelper::Kill( aTemp ) )
{
DBG_ERROR("Couldn't remove temporary file!");
}
}
pFilter = 0;
delete pURLObj;
delete pImp;
}
//------------------------------------------------------------------
void SfxMedium::SetItemSet(SfxItemSet *pNewSet)
{
delete pSet;
pSet = pNewSet;
}
//----------------------------------------------------------------
const INetURLObject& SfxMedium::GetURLObject() const
{
if( !pURLObj )
{
SfxMedium* pThis = const_cast < SfxMedium* > (this);
pThis->pURLObj = new INetURLObject( aLogicName );
if ( pThis->pURLObj->HasMark() )
(*pThis->pURLObj) = INetURLObject( aLogicName ).GetURLNoMark();
}
return *pURLObj;
}
//----------------------------------------------------------------
const String& SfxMedium::GetPreRedirectedURL() const
{
return pImp->aPreRedirectionURL;
}
//----------------------------------------------------------------
sal_uInt32 SfxMedium::GetMIMEAndRedirect( String& /*rName*/ )
{
/* dv !!!! not needed any longer ?
INetProtocol eProt = GetURLObject().GetProtocol();
if( eProt == INET_PROT_FTP && SvBinding::ShouldUseFtpProxy( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
{
Any aAny( UCB_Helper::GetProperty( GetContent(), WID_FLAG_IS_FOLDER ) );
sal_Bool bIsFolder = sal_False;
if ( ( aAny >>= bIsFolder ) && bIsFolder )
return ERRCODE_NONE;
}
GetMedium_Impl();
if( !eError && pImp->xBinding.Is() )
{
eError = pImp->xBinding->GetMimeType( rName );
// Wir koennen keine Parameter wie CharSets usw.
rName = rName.GetToken( 0, ';' );
if( !eError )
{
if( !pImp->aPreRedirectionURL.Len() )
pImp->aPreRedirectionURL = aLogicName;
SetName( pImp->xBinding->GetRedirectedURL() );
}
pImp->aExpireTime = pImp->xBinding->GetExpireDateTime();
}
return eError;
*/
return 0;
}
//----------------------------------------------------------------
void SfxMedium::SetReferer( const String& rRefer )
{
pImp->aReferer = rRefer;
}
//----------------------------------------------------------------
const String& SfxMedium::GetReferer( ) const
{
return pImp->aReferer;
}
//----------------------------------------------------------------
void SfxMedium::SetExpired_Impl( const DateTime& rDateTime )
{
pImp->aExpireTime = rDateTime;
}
//----------------------------------------------------------------
sal_Bool SfxMedium::IsExpired() const
{
return pImp->aExpireTime.IsValid() && pImp->aExpireTime < DateTime();
}
//----------------------------------------------------------------
void SfxMedium::ForceSynchronStream_Impl( sal_Bool bForce )
{
if( pInStream )
{
SvLockBytes* pBytes = pInStream->GetLockBytes();
if( pBytes )
pBytes->SetSynchronMode( bForce );
}
pImp->bForceSynchron = bForce;
}
//----------------------------------------------------------------
SfxFrame* SfxMedium::GetLoadTargetFrame() const
{
return pImp->wLoadTargetFrame;
}
//----------------------------------------------------------------
void SfxMedium::SetLoadTargetFrame(SfxFrame* pFrame )
{
pImp->wLoadTargetFrame = pFrame;
}
//----------------------------------------------------------------
void SfxMedium::SetStorage_Impl( const uno::Reference < embed::XStorage >& rStor )
{
pImp->xStorage = rStor;
}
//----------------------------------------------------------------
SfxItemSet* SfxMedium::GetItemSet() const
{
// this method *must* return an ItemSet, returning NULL can cause crashes
if( !pSet )
((SfxMedium*)this)->pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
return pSet;
}
//----------------------------------------------------------------
SvKeyValueIterator* SfxMedium::GetHeaderAttributes_Impl()
{
if( !pImp->xAttributes.Is() )
{
pImp->xAttributes = SvKeyValueIteratorRef( new SvKeyValueIterator );
if ( GetContent().is() )
{
pImp->bIsCharsetInitialized = sal_True;
try
{
Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
::rtl::OUString aContentType;
aAny >>= aContentType;
pImp->xAttributes->Append( SvKeyValue( ::rtl::OUString::createFromAscii( "content-type" ), aContentType ) );
}
catch ( ::com::sun::star::uno::Exception& )
{
}
}
}
return pImp->xAttributes;
}
//----------------------------------------------------------------
SvCompatWeakHdl* SfxMedium::GetHdl()
{
return pImp->GetHdl();
}
sal_Bool SfxMedium::IsDownloadDone_Impl()
{
return pImp->bDownloadDone;
}
::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SfxMedium::GetInputStream()
{
if ( !pImp->xInputStream.is() )
GetMedium_Impl();
return pImp->xInputStream;
}
const uno::Sequence < util::RevisionTag >& SfxMedium::GetVersionList( bool _bNoReload )
{
// if the medium has no name, then this medium should represent a new document and can have no version info
if ( ( !_bNoReload || !pImp->m_bVersionsAlreadyLoaded ) && !pImp->aVersions.getLength() &&
( aName.Len() || aLogicName.Len() ) && GetStorage().is() )
{
uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
if ( xReader.is() )
{
try
{
pImp->aVersions = xReader->load( GetStorage() );
}
catch ( uno::Exception& )
{
}
}
}
if ( !pImp->m_bVersionsAlreadyLoaded )
pImp->m_bVersionsAlreadyLoaded = sal_True;
return pImp->aVersions;
}
uno::Sequence < util::RevisionTag > SfxMedium::GetVersionList( const uno::Reference < embed::XStorage >& xStorage )
{
uno::Reference < document::XDocumentRevisionListPersistence > xReader( comphelper::getProcessServiceFactory()->createInstance(
::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
if ( xReader.is() )
{
try
{
return xReader->load( xStorage );
}
catch ( uno::Exception& )
{
}
}
return uno::Sequence < util::RevisionTag >();
}
sal_uInt16 SfxMedium::AddVersion_Impl( util::RevisionTag& rRevision )
{
if ( GetStorage().is() )
{
// Einen eindeutigen Namen f"ur den Stream ermitteln
SvULongs aLongs;
sal_Int32 nLength = pImp->aVersions.getLength();
for ( sal_Int32 m=0; m<nLength; m++ )
{
sal_uInt32 nVer = (sal_uInt32) String( pImp->aVersions[m].Identifier ).Copy(7).ToInt32();
sal_uInt16 n;
for ( n=0; n<aLongs.Count(); n++ )
if ( nVer<aLongs[n] )
break;
aLongs.Insert( nVer, n );
}
sal_uInt16 nKey;
for ( nKey=0; nKey<aLongs.Count(); nKey++ )
if ( aLongs[nKey] > ( sal_uIntPtr ) nKey+1 )
break;
String aRevName = DEFINE_CONST_UNICODE( "Version" );
aRevName += String::CreateFromInt32( nKey + 1 );
pImp->aVersions.realloc( nLength+1 );
rRevision.Identifier = aRevName;
pImp->aVersions[nLength] = rRevision;
return nKey;
}
return 0;
}
sal_Bool SfxMedium::RemoveVersion_Impl( const ::rtl::OUString& rName )
{
if ( !pImp->aVersions.getLength() )
return sal_False;
sal_Int32 nLength = pImp->aVersions.getLength();
for ( sal_Int32 n=0; n<nLength; n++ )
{
if ( pImp->aVersions[n].Identifier == rName )
{
for ( sal_Int32 m=n; m<nLength-1; m++ )
pImp->aVersions[m] = pImp->aVersions[m+1];
pImp->aVersions.realloc(nLength-1);
return sal_True;
}
}
return sal_False;
}
sal_Bool SfxMedium::TransferVersionList_Impl( SfxMedium& rMedium )
{
if ( rMedium.pImp->aVersions.getLength() )
{
pImp->aVersions = rMedium.pImp->aVersions;
return sal_True;
}
return sal_False;
}
sal_Bool SfxMedium::SaveVersionList_Impl( sal_Bool /*bUseXML*/ )
{
if ( GetStorage().is() )
{
if ( !pImp->aVersions.getLength() )
return sal_True;
uno::Reference < document::XDocumentRevisionListPersistence > xWriter( comphelper::getProcessServiceFactory()->createInstance(
::rtl::OUString::createFromAscii("com.sun.star.document.DocumentRevisionListPersistence") ), uno::UNO_QUERY );
if ( xWriter.is() )
{
try
{
xWriter->store( GetStorage(), pImp->aVersions );
return sal_True;
}
catch ( uno::Exception& )
{
}
}
}
return sal_False;
}
//----------------------------------------------------------------
sal_Bool SfxMedium::IsReadOnly()
{
sal_Bool bReadOnly = sal_False;
// a) ReadOnly filter cant produce read/write contents!
bReadOnly = (
(pFilter ) &&
((pFilter->GetFilterFlags() & SFX_FILTER_OPENREADONLY) == SFX_FILTER_OPENREADONLY)
);
// b) if filter allow read/write contents .. check open mode of the storage
if (!bReadOnly)
bReadOnly = !( GetOpenMode() & STREAM_WRITE );
// c) the API can force the readonly state!
if (!bReadOnly)
{
SFX_ITEMSET_ARG( GetItemSet(), pItem, SfxBoolItem, SID_DOC_READONLY, sal_False);
if (pItem)
bReadOnly = pItem->GetValue();
}
return bReadOnly;
}
//----------------------------------------------------------------
sal_Bool SfxMedium::SetWritableForUserOnly( const ::rtl::OUString& aURL )
{
// UCB does not allow to allow write access only for the user,
// use osl API
sal_Bool bResult = sal_False;
::osl::DirectoryItem aDirItem;
if ( ::osl::DirectoryItem::get( aURL, aDirItem ) == ::osl::FileBase::E_None )
{
::osl::FileStatus aFileStatus( FileStatusMask_Attributes );
if ( aDirItem.getFileStatus( aFileStatus ) == osl::FileBase::E_None
&& aFileStatus.isValid( FileStatusMask_Attributes ) )
{
sal_uInt64 nAttributes = aFileStatus.getAttributes();
nAttributes &= ~(Attribute_OwnWrite |
Attribute_GrpWrite |
Attribute_OthWrite |
Attribute_ReadOnly);
nAttributes |= Attribute_OwnWrite;
bResult = ( osl::File::setAttributes( aURL, nAttributes ) == ::osl::FileBase::E_None );
}
}
return bResult;
}
//----------------------------------------------------------------
void SfxMedium::CreateTempFile( sal_Bool bReplace )
{
if ( pImp->pTempFile )
{
if ( !bReplace )
return;
DELETEZ( pImp->pTempFile );
aName = String();
}
do
{
pImp->pTempFile = new ::utl::TempFile();
if ( GetName().Equals( pImp->pTempFile->GetURL() ) )
{
delete pImp->pTempFile;
pImp->pTempFile = NULL;
}
} while ( pImp->pTempFile == NULL );
pImp->pTempFile->EnableKillingFile( sal_True );
aName = pImp->pTempFile->GetFileName();
::rtl::OUString aTmpURL = pImp->pTempFile->GetURL();
if ( !aName.Len() || !aTmpURL.getLength() )
{
SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
return;
}
if ( !( nStorOpenMode & STREAM_TRUNC ) )
{
sal_Bool bTransferSuccess = sal_False;
if ( GetContent().is()
&& ::utl::LocalFileHelper::IsLocalFile( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) )
&& ::utl::UCBContentHelper::IsDocument( GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) ) )
{
// if there is already such a document, we should copy it
// if it is a file system use OS copy process
try
{
uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
INetURLObject aTmpURLObj( aTmpURL );
::rtl::OUString aFileName = aTmpURLObj.getName( INetURLObject::LAST_SEGMENT,
true,
INetURLObject::DECODE_WITH_CHARSET );
if ( aFileName.getLength() && aTmpURLObj.removeSegment() )
{
::ucbhelper::Content aTargetContent( aTmpURLObj.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
if ( aTargetContent.transferContent( pImp->aContent, ::ucbhelper::InsertOperation_COPY, aFileName, NameClash::OVERWRITE ) )
{
SetWritableForUserOnly( aTmpURL );
bTransferSuccess = sal_True;
}
}
}
catch( uno::Exception& )
{}
if ( bTransferSuccess )
{
CloseOutStream();
CloseInStream();
}
}
if ( !bTransferSuccess && pInStream )
{
// the case when there is no URL-access available or this is a remote protocoll
// but there is an input stream
GetOutStream();
if ( pOutStream )
{
char *pBuf = new char [8192];
sal_uInt32 nErr = ERRCODE_NONE;
pInStream->Seek(0);
pOutStream->Seek(0);
while( !pInStream->IsEof() && nErr == ERRCODE_NONE )
{
sal_uInt32 nRead = pInStream->Read( pBuf, 8192 );
nErr = pInStream->GetError();
pOutStream->Write( pBuf, nRead );
}
bTransferSuccess = sal_True;
delete[] pBuf;
CloseInStream();
}
CloseOutStream_Impl();
}
else
{
// Quite strange design, but currently it is expected that in this case no transfer happens
// TODO/LATER: get rid of this inconsistent part of the call design
bTransferSuccess = sal_True;
CloseInStream();
}
if ( !bTransferSuccess )
{
SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
return;
}
}
CloseStorage();
}
//----------------------------------------------------------------
void SfxMedium::CreateTempFileNoCopy()
{
// this call always replaces the existing temporary file
if ( pImp->pTempFile )
{
delete pImp->pTempFile;
pImp->pTempFile = NULL;
}
do
{
pImp->pTempFile = new ::utl::TempFile();
if ( GetName().Equals( pImp->pTempFile->GetURL() ) )
{
delete pImp->pTempFile;
pImp->pTempFile = NULL;
}
} while ( pImp->pTempFile == NULL );
pImp->pTempFile->EnableKillingFile( sal_True );
aName = pImp->pTempFile->GetFileName();
if ( !aName.Len() )
{
SetError( ERRCODE_IO_CANTWRITE, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
return;
}
CloseOutStream_Impl();
CloseStorage();
}
::rtl::OUString SfxMedium::GetCharset()
{
if( !pImp->bIsCharsetInitialized )
{
// Set an error in case there is no content?
if ( GetContent().is() )
{
pImp->bIsCharsetInitialized = sal_True;
try
{
Any aAny = pImp->aContent.getPropertyValue( ::rtl::OUString::createFromAscii( "MediaType" ) );
::rtl::OUString aField;
aAny >>= aField;
::rtl::OString sContent = ::rtl::OUStringToOString( aField, RTL_TEXTENCODING_ASCII_US );
ByteString sType, sSubType;
INetContentTypeParameterList aParameters;
if( INetContentTypes::parse( sContent, sType, sSubType, &aParameters ) )
{
const INetContentTypeParameter * pCharset = aParameters.find("charset");
if (pCharset != 0)
pImp->aCharset = pCharset->m_sValue;
}
}
catch ( ::com::sun::star::uno::Exception& )
{
}
}
}
return pImp->aCharset;
}
void SfxMedium::SetCharset( ::rtl::OUString aChs )
{
pImp->bIsCharsetInitialized = sal_True;
pImp->aCharset = aChs;
}
sal_Bool SfxMedium::SignContents_Impl( sal_Bool bScriptingContent, const ::rtl::OUString& aODFVersion, sal_Bool bHasValidDocumentSignature )
{
sal_Bool bChanges = sal_False;
// the medium should be closed to be able to sign, the caller is responsible to close it
if ( !IsOpen() && !GetError() )
{
// The component should know if there was a valid document signature, since
// it should show a warning in this case
uno::Sequence< uno::Any > aArgs( 2 );
aArgs[0] <<= aODFVersion;
aArgs[1] <<= bHasValidDocumentSignature;
::com::sun::star::uno::Reference< ::com::sun::star::security::XDocumentDigitalSignatures > xSigner(
comphelper::getProcessServiceFactory()->createInstanceWithArguments(
rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.security.DocumentDigitalSignatures" ) ),
aArgs ),
::com::sun::star::uno::UNO_QUERY );
if ( xSigner.is() )
{
uno::Reference< embed::XStorage > xWriteableZipStor;
if ( !IsReadOnly() )
{
// we can reuse the temporary file if there is one already
CreateTempFile( sal_False );
GetMedium_Impl();
try
{
if ( !pImp->xStream.is() )
throw uno::RuntimeException();
xWriteableZipStor = ::comphelper::OStorageHelper::GetStorageOfFormatFromStream( ZIP_STORAGE_FORMAT_STRING, pImp->xStream );
if ( !xWriteableZipStor.is() )
throw uno::RuntimeException();
uno::Reference< embed::XStorage > xMetaInf = xWriteableZipStor->openStorageElement(
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF" ) ),
embed::ElementModes::READWRITE );
if ( !xMetaInf.is() )
throw uno::RuntimeException();
if ( bScriptingContent )
{
// If the signature has already the document signature it will be removed
// after the scripting signature is inserted.
uno::Reference< io::XStream > xStream(
xMetaInf->openStreamElement( xSigner->getScriptingContentSignatureDefaultStreamName(),
embed::ElementModes::READWRITE ),
uno::UNO_SET_THROW );
if ( xSigner->signScriptingContent( GetZipStorageToSign_Impl(), xStream ) )
{
// remove the document signature if any
::rtl::OUString aDocSigName = xSigner->getDocumentContentSignatureDefaultStreamName();
if ( aDocSigName.getLength() && xMetaInf->hasByName( aDocSigName ) )
xMetaInf->removeElement( aDocSigName );
uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
xTransact->commit();
xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
xTransact->commit();
// the temporary file has been written, commit it to the original file
Commit();
bChanges = sal_True;
}
}
else
{
uno::Reference< io::XStream > xStream(
xMetaInf->openStreamElement( xSigner->getDocumentContentSignatureDefaultStreamName(),
embed::ElementModes::READWRITE ),
uno::UNO_SET_THROW );
if ( xSigner->signDocumentContent( GetZipStorageToSign_Impl(), xStream ) )
{
uno::Reference< embed::XTransactedObject > xTransact( xMetaInf, uno::UNO_QUERY_THROW );
xTransact->commit();
xTransact.set( xWriteableZipStor, uno::UNO_QUERY_THROW );
xTransact->commit();
// the temporary file has been written, commit it to the original file
Commit();
bChanges = sal_True;
}
}
}
catch ( uno::Exception& )
{
OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
}
CloseAndRelease();
}
else
{
try
{
if ( bScriptingContent )
xSigner->showScriptingContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
else
xSigner->showDocumentContentSignatures( GetZipStorageToSign_Impl(), uno::Reference< io::XInputStream >() );
}
catch( uno::Exception& )
{
OSL_ENSURE( sal_False, "Couldn't use signing functionality!\n" );
}
}
}
ResetError();
}
return bChanges;
}
//----------------------------------------------------------------
sal_uInt16 SfxMedium::GetCachedSignatureState_Impl()
{
return pImp->m_nSignatureState;
}
//----------------------------------------------------------------
void SfxMedium::SetCachedSignatureState_Impl( sal_uInt16 nState )
{
pImp->m_nSignatureState = nState;
}
sal_Bool SfxMedium::HasStorage_Impl() const
{
return pImp->xStorage.is();
}
sal_Bool SfxMedium::IsOpen() const
{
return pInStream || pOutStream || pImp->xStorage.is();
}
::rtl::OUString SfxMedium::CreateTempCopyWithExt( const ::rtl::OUString& aURL )
{
::rtl::OUString aResult;
if ( aURL.getLength() )
{
sal_Int32 nPrefixLen = aURL.lastIndexOf( '.' );
String aExt = ( nPrefixLen == -1 ) ? String() : String( aURL.copy( nPrefixLen ) );
::rtl::OUString aNewTempFileURL = ::utl::TempFile( String(), &aExt ).GetURL();
if ( aNewTempFileURL.getLength() )
{
INetURLObject aSource( aURL );
INetURLObject aDest( aNewTempFileURL );
::rtl::OUString aFileName = aDest.getName( INetURLObject::LAST_SEGMENT,
true,
INetURLObject::DECODE_WITH_CHARSET );
if ( aFileName.getLength() && aDest.removeSegment() )
{
try
{
uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > xComEnv;
::ucbhelper::Content aTargetContent( aDest.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
::ucbhelper::Content aSourceContent( aSource.GetMainURL( INetURLObject::NO_DECODE ), xComEnv );
if ( aTargetContent.transferContent( aSourceContent,
::ucbhelper::InsertOperation_COPY,
aFileName,
NameClash::OVERWRITE ) )
{
// Success
aResult = aNewTempFileURL;
}
}
catch( uno::Exception& )
{}
}
}
}
return aResult;
}
sal_Bool SfxMedium::CallApproveHandler( const uno::Reference< task::XInteractionHandler >& xHandler, uno::Any aRequest, sal_Bool bAllowAbort )
{
sal_Bool bResult = sal_False;
if ( xHandler.is() )
{
try
{
uno::Sequence< uno::Reference< task::XInteractionContinuation > > aContinuations( bAllowAbort ? 2 : 1 );
::rtl::Reference< ::comphelper::OInteractionApprove > pApprove( new ::comphelper::OInteractionApprove );
aContinuations[ 0 ] = pApprove.get();
if ( bAllowAbort )
{
::rtl::Reference< ::comphelper::OInteractionAbort > pAbort( new ::comphelper::OInteractionAbort );
aContinuations[ 1 ] = pAbort.get();
}
xHandler->handle(::framework::InteractionRequest::CreateRequest (aRequest,aContinuations));
bResult = pApprove->wasSelected();
}
catch( const Exception& )
{
}
}
return bResult;
}
::rtl::OUString SfxMedium::SwitchDocumentToTempFile()
{
// the method returns empty string in case of failure
::rtl::OUString aResult;
::rtl::OUString aOrigURL = aLogicName;
if ( aOrigURL.getLength() )
{
sal_Int32 nPrefixLen = aOrigURL.lastIndexOf( '.' );
String aExt = ( nPrefixLen == -1 ) ? String() : String( aOrigURL.copy( nPrefixLen ) );
::rtl::OUString aNewURL = ::utl::TempFile( String(), &aExt ).GetURL();
// TODO/LATER: In future the aLogicName should be set to shared folder URL
// and a temporary file should be created. Transport_Impl should be impossible then.
if ( aNewURL.getLength() )
{
uno::Reference< embed::XStorage > xStorage = GetStorage();
uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
if ( xOptStorage.is() )
{
// TODO/LATER: reuse the pImp->pTempFile if it already exists
CanDisposeStorage_Impl( sal_False );
Close();
SetPhysicalName_Impl( String() );
SetName( aNewURL );
// remove the readonly state
sal_Bool bWasReadonly = sal_False;
nStorOpenMode = SFX_STREAM_READWRITE;
SFX_ITEMSET_ARG( pSet, pReadOnlyItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
if ( pReadOnlyItem && pReadOnlyItem->GetValue() )
bWasReadonly = sal_True;
GetItemSet()->ClearItem( SID_DOC_READONLY );
GetMedium_Impl();
LockOrigFileOnDemand( sal_False, sal_False );
CreateTempFile( sal_True );
GetMedium_Impl();
if ( pImp->xStream.is() )
{
try
{
xOptStorage->writeAndAttachToStream( pImp->xStream );
pImp->xStorage = xStorage;
aResult = aNewURL;
}
catch( uno::Exception& )
{}
}
if ( !aResult.getLength() )
{
Close();
SetPhysicalName_Impl( String() );
SetName( aOrigURL );
if ( bWasReadonly )
{
// set the readonly state back
nStorOpenMode = SFX_STREAM_READONLY;
GetItemSet()->Put( SfxBoolItem(SID_DOC_READONLY, sal_True));
}
GetMedium_Impl();
pImp->xStorage = xStorage;
}
}
}
}
return aResult;
}
sal_Bool SfxMedium::SwitchDocumentToFile( ::rtl::OUString aURL )
{
// the method is only for storage based documents
sal_Bool bResult = sal_False;
::rtl::OUString aOrigURL = aLogicName;
if ( aURL.getLength() && aOrigURL.getLength() )
{
uno::Reference< embed::XStorage > xStorage = GetStorage();
uno::Reference< embed::XOptimizedStorage > xOptStorage( xStorage, uno::UNO_QUERY );
if ( xOptStorage.is() )
{
// TODO/LATER: reuse the pImp->pTempFile if it already exists
CanDisposeStorage_Impl( sal_False );
Close();
SetPhysicalName_Impl( String() );
SetName( aURL );
// open the temporary file based document
GetMedium_Impl();
LockOrigFileOnDemand( sal_False, sal_False );
CreateTempFile( sal_True );
GetMedium_Impl();
if ( pImp->xStream.is() )
{
try
{
uno::Reference< io::XTruncate > xTruncate( pImp->xStream, uno::UNO_QUERY_THROW );
if ( xTruncate.is() )
xTruncate->truncate();
xOptStorage->writeAndAttachToStream( pImp->xStream );
pImp->xStorage = xStorage;
bResult = sal_True;
}
catch( uno::Exception& )
{}
}
if ( !bResult )
{
Close();
SetPhysicalName_Impl( String() );
SetName( aOrigURL );
GetMedium_Impl();
pImp->xStorage = xStorage;
}
}
}
return bResult;
}