Resolves: rhbz#1673198 cannot overwrite open file with export

this reverts

commit 3c4cfa209f446fc433c8d3925cbbe628c2f536e8
Date:   Mon Nov 26 12:51:05 2007 +0000

    INTEGRATION: CWS fwk72 (1.195.14); FILE MERGED
    2007/09/10 14:55:01 mav 1.195.14.1: #i81437# do not allow to export to the file the document is based on

Change-Id: I8bf1524a8cc2d6d1911bdd228f33f1b7723e1d6e
Reviewed-on: https://gerrit.libreoffice.org/67491
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index 06b9ff7d..44364d2 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -1166,15 +1166,6 @@ bool SfxObjectShell::SaveTo_Impl
        }
    }

    bool bCopyTo = false;
    SfxItemSet *pMedSet = rMedium.GetItemSet();
    if( pMedSet )
    {
        const SfxBoolItem* pSaveToItem = SfxItemSet::GetItem<SfxBoolItem>(pMedSet, SID_SAVETO, false);
        bCopyTo =   GetCreateMode() == SfxObjectCreateMode::EMBEDDED ||
                    (pSaveToItem && pSaveToItem->GetValue());
    }

    // use UCB for case sensitive/insensitive file name comparison
    if ( !pMedium->GetName().equalsIgnoreAsciiCase("private:stream")
      && !rMedium.GetName().equalsIgnoreAsciiCase("private:stream")
@@ -1185,100 +1176,92 @@ bool SfxObjectShell::SaveTo_Impl
        if ( pMedium->DocNeedsFileDateCheck() )
            rMedium.CheckFileDate( pMedium->GetInitFileDate( false ) );

        if ( bCopyTo && GetCreateMode() != SfxObjectCreateMode::EMBEDDED )
        // before we overwrite the original file, we will make a backup if there is a demand for that
        // if the backup is not created here it will be created internally and will be removed in case of successful saving
        const bool bDoBackup = SvtSaveOptions().IsBackup();
        if ( bDoBackup )
        {
            // export to the same location is forbidden
            SetError(ERRCODE_IO_CANTWRITE);
            rMedium.DoBackup_Impl();
            if ( rMedium.GetError() )
            {
                SetError(rMedium.GetErrorCode());
                rMedium.ResetError();
            }
        }
        else

        if ( bStorageBasedSource && bStorageBasedTarget )
        {
            // before we overwrite the original file, we will make a backup if there is a demand for that
            // if the backup is not created here it will be created internally and will be removed in case of successful saving
            const bool bDoBackup = SvtSaveOptions().IsBackup();
            if ( bDoBackup )
            // The active storage must be switched. The simple saving is not enough.
            // The problem is that the target medium contains target MediaDescriptor.

                // In future the switch of the persistence could be done on stream level:
                // a new wrapper service will be implemented that allows to exchange
                // persistence on the fly. So the real persistence will be set
                // to that stream only after successful commit of the storage.
                // TODO/LATER:
                // create wrapper stream based on the URL
                // create a new storage based on this stream
                // store to this new storage
                // commit the new storage
                // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
                // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
                // if the last step is failed the stream should stay to be transacted and should be committed on any flush
                // so we can forget the stream in any way and the next storage commit will flush it

            bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
                *pMedium, rMedium );
            if ( bNeedsDisconnectionOnFail
              || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
            {
                rMedium.DoBackup_Impl();
                if ( rMedium.GetError() )
                {
                    SetError(rMedium.GetErrorCode());
                    rMedium.ResetError();
                }
                pMedium->CloseAndRelease();

                // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
                //             in future those streams should not be copied in case a valid target url is provided,
                //             if the url is not provided ( means the document is based on a stream ) this code is not
                //             reachable.
                rMedium.CloseAndRelease();
                rMedium.SetHasEmbeddedObjects(GetEmbeddedObjectContainer().HasEmbeddedObjects());
                rMedium.GetOutputStorage();
                rMedium.SetHasEmbeddedObjects(false);
            }
        }
        else if ( !bStorageBasedSource && !bStorageBasedTarget )
        {
            // the source and the target formats are alien
            // just disconnect the stream from the source format
            // so that the target medium can use it

            if ( bStorageBasedSource && bStorageBasedTarget )
            pMedium->CloseAndRelease();
            rMedium.CloseAndRelease();
            rMedium.CreateTempFileNoCopy();
            rMedium.GetOutStream();
        }
        else if ( !bStorageBasedSource && bStorageBasedTarget )
        {
            // the source format is an alien one but the target
            // format is an own one so just disconnect the source
            // medium

            pMedium->CloseAndRelease();
            rMedium.CloseAndRelease();
            rMedium.GetOutputStorage();
        }
        else // means if ( bStorageBasedSource && !bStorageBasedTarget )
        {
            // the source format is an own one but the target is
            // an alien format, just connect the source to temporary
            // storage

            bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
                *pMedium, rMedium );
            if ( bNeedsDisconnectionOnFail
              || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
            {
                // The active storage must be switched. The simple saving is not enough.
                // The problem is that the target medium contains target MediaDescriptor.

                    // In future the switch of the persistence could be done on stream level:
                    // a new wrapper service will be implemented that allows to exchange
                    // persistence on the fly. So the real persistence will be set
                    // to that stream only after successful commit of the storage.
                    // TODO/LATER:
                    // create wrapper stream based on the URL
                    // create a new storage based on this stream
                    // store to this new storage
                    // commit the new storage
                    // call saveCompleted based with this new storage ( get rid of old storage and "frees" URL )
                    // commit the wrapper stream ( the stream will connect the URL only on commit, after that it will hold it )
                    // if the last step is failed the stream should stay to be transacted and should be committed on any flush
                    // so we can forget the stream in any way and the next storage commit will flush it

                bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
                    *pMedium, rMedium );
                if ( bNeedsDisconnectionOnFail
                  || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
                {
                    pMedium->CloseAndRelease();

                    // TODO/LATER: for now the medium must be closed since it can already contain streams from old medium
                    //             in future those streams should not be copied in case a valid target url is provided,
                    //             if the url is not provided ( means the document is based on a stream ) this code is not
                    //             reachable.
                    rMedium.CloseAndRelease();
                    rMedium.SetHasEmbeddedObjects(GetEmbeddedObjectContainer().HasEmbeddedObjects());
                    rMedium.GetOutputStorage();
                    rMedium.SetHasEmbeddedObjects(false);
                }
            }
            else if ( !bStorageBasedSource && !bStorageBasedTarget )
            {
                // the source and the target formats are alien
                // just disconnect the stream from the source format
                // so that the target medium can use it

                pMedium->CloseAndRelease();
                rMedium.CloseAndRelease();
                rMedium.CreateTempFileNoCopy();
                rMedium.GetOutStream();
            }
            else if ( !bStorageBasedSource && bStorageBasedTarget )
            {
                // the source format is an alien one but the target
                // format is an own one so just disconnect the source
                // medium

                pMedium->CloseAndRelease();
                rMedium.CloseAndRelease();
                rMedium.GetOutputStorage();
            }
            else // means if ( bStorageBasedSource && !bStorageBasedTarget )
            {
                // the source format is an own one but the target is
                // an alien format, just connect the source to temporary
                // storage

                bNeedsDisconnectionOnFail = DisconnectStorage_Impl(
                    *pMedium, rMedium );
                if ( bNeedsDisconnectionOnFail
                  || ConnectTmpStorage_Impl( pMedium->GetStorage(), pMedium ) )
                {
                    pMedium->CloseAndRelease();
                    rMedium.CloseAndRelease();
                    rMedium.CreateTempFileNoCopy();
                    rMedium.GetOutStream();
                }
            }
        }
    }
    else
@@ -1347,6 +1330,15 @@ bool SfxObjectShell::SaveTo_Impl
    // lock user interface while saving the document
    LockUIGuard aLockUIGuard(this);

    bool bCopyTo = false;
    SfxItemSet *pMedSet = rMedium.GetItemSet();
    if( pMedSet )
    {
        const SfxBoolItem* pSaveToItem = SfxItemSet::GetItem<SfxBoolItem>(pMedSet, SID_SAVETO, false);
        bCopyTo =   GetCreateMode() == SfxObjectCreateMode::EMBEDDED ||
                    (pSaveToItem && pSaveToItem->GetValue());
    }

    bool bOk = false;
    // TODO/LATER: get rid of bOk
    if (bOwnTarget && pFilter && !(pFilter->GetFilterFlags() & SfxFilterFlags::STARONEFILTER))