Kaydet (Commit) c5138cad authored tarafından Michael Stahl's avatar Michael Stahl

fdo#68724: sw: fix crash on Insert->File with Hybrid PDF

This is an unfortunate combination of 2 special cases:
- the Hybrid PDF has its own XFilter implementation to extract the
  embedded ODF document
- Writer needs to create a SwReader with SwPaM for Insert

Since the PDF XFilter uses a special service in sfx2 to implement
the import, handling this requires a new method in SfxObjectShell
that calls back into Writer to create the properly setup SwReader.

Change-Id: Ie85f3bfa322bfe883c479e1cb198a8bf0cbbac23
üst de45a492
......@@ -116,6 +116,9 @@ namespace com { namespace sun { namespace star {
namespace lang {
class XComponent;
}
namespace text {
class XTextRange;
}
} } }
typedef sal_uInt32 SfxObjectShellFlags;
......@@ -348,7 +351,12 @@ public:
sal_Bool bForceNonModified = sal_False );
sal_Bool SaveCompletedChildren( sal_Bool bSuccess );
virtual sal_Bool ImportFrom( SfxMedium &rMedium, bool bInsert );
/** a very special case to insert at a position in Writer from UNO,
via OwnSubFilterService */
virtual bool InsertGeneratedStream(SfxMedium& rMedium,
css::uno::Reference<css::text::XTextRange> const& xInsertPosition);
virtual bool ImportFrom( SfxMedium &rMedium,
css::uno::Reference<css::text::XTextRange> const& xInsertPosition);
sal_Bool ExportTo( SfxMedium &rMedium );
// xmlsec05, check with SFX team
......
......@@ -375,9 +375,10 @@ sal_Bool DrawDocShell::LoadFrom( SfxMedium& rMedium )
/**
* load from 3rd party format
*/
sal_Bool DrawDocShell::ImportFrom( SfxMedium &rMedium, bool bInsert )
bool DrawDocShell::ImportFrom(SfxMedium &rMedium,
uno::Reference<text::XTextRange> const& xInsertPosition)
{
const sal_Bool bRet=SfxObjectShell::ImportFrom(rMedium, bInsert);
const sal_Bool bRet = SfxObjectShell::ImportFrom(rMedium, xInsertPosition);
SfxItemSet* pSet = rMedium.GetItemSet();
if( pSet )
......
......@@ -76,7 +76,9 @@ public:
virtual void Activate( sal_Bool bMDI );
virtual void Deactivate( sal_Bool bMDI );
virtual sal_Bool InitNew( const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStorage );
virtual sal_Bool ImportFrom( SfxMedium &rMedium, bool bInsert=false );
virtual bool ImportFrom(SfxMedium &rMedium,
css::uno::Reference<css::text::XTextRange> const& xInsertPosition)
SAL_OVERRIDE;
virtual sal_Bool ConvertFrom( SfxMedium &rMedium );
virtual sal_Bool Save();
virtual sal_Bool SaveAsOwnFormat( SfxMedium& rMedium );
......
......@@ -66,6 +66,7 @@
#include <com/sun/star/io/XTruncate.hpp>
#include <com/sun/star/util/XModifiable.hpp>
#include <com/sun/star/security/DocumentDigitalSignatures.hpp>
#include <com/sun/star/text/XTextRange.hpp>
#include <com/sun/star/xml/crypto/CipherID.hpp>
#include <com/sun/star/xml/crypto/DigestID.hpp>
......@@ -548,7 +549,7 @@ sal_Bool SfxObjectShell::DoInitNew( SfxMedium* pMed )
sal_Bool SfxObjectShell::ImportFromGeneratedStream_Impl(
const uno::Reference< io::XStream >& xStream,
const uno::Sequence< beans::PropertyValue >& aMediaDescr )
const uno::Sequence< beans::PropertyValue >& rMediaDescr )
{
if ( !xStream.is() )
return sal_False;
......@@ -572,22 +573,38 @@ sal_Bool SfxObjectShell::ImportFromGeneratedStream_Impl(
pMedium->SetStorage_Impl( xStorage );
SfxAllItemSet aSet( SFX_APP()->GetPool() );
TransformParameters( SID_OPENDOC, aMediaDescr, aSet );
TransformParameters( SID_OPENDOC, rMediaDescr, aSet );
pMedium->GetItemSet()->Put( aSet );
pMedium->CanDisposeStorage_Impl( sal_False );
uno::Reference<text::XTextRange> xInsertTextRange;
for (sal_Int32 i = 0; i < rMediaDescr.getLength(); ++i)
{
if (rMediaDescr[i].Name == "TextInsertModeRange")
{
rMediaDescr[i].Value >>= xInsertTextRange;
}
}
// allow the subfilter to reinit the model
if ( pImp->m_bIsInit )
pImp->m_bIsInit = sal_False;
if ( LoadOwnFormat( *pMedium ) )
if (xInsertTextRange.is())
{
bResult = InsertGeneratedStream(*pMedium, xInsertTextRange);
}
else
{
bHasName = sal_True;
if ( !IsReadOnly() && IsLoadReadonly() )
SetReadOnlyUI();
bResult = sal_True;
OSL_ENSURE( pImp->m_xDocStorage == xStorage, "Wrong storage is used!\n" );
// allow the subfilter to reinit the model
if ( pImp->m_bIsInit )
pImp->m_bIsInit = sal_False;
if ( LoadOwnFormat( *pMedium ) )
{
bHasName = sal_True;
if ( !IsReadOnly() && IsLoadReadonly() )
SetReadOnlyUI();
bResult = sal_True;
OSL_ENSURE( pImp->m_xDocStorage == xStorage, "Wrong storage is used!\n" );
}
}
// now the medium can be disconnected from the storage
......@@ -748,7 +765,7 @@ sal_Bool SfxObjectShell::DoLoad( SfxMedium *pMed )
{
bSetProperty = false;
}
bOk = ImportFrom( *pMedium, false );
bOk = ImportFrom(*pMedium, 0);
if(bSetProperty)
{
try
......@@ -2160,7 +2177,8 @@ sal_Bool SfxObjectShell::ConvertFrom
return sal_False;
}
sal_Bool SfxObjectShell::ImportFrom( SfxMedium& rMedium, bool bInsert )
bool SfxObjectShell::ImportFrom(SfxMedium& rMedium,
css::uno::Reference<css::text::XTextRange> const& xInsertPosition)
{
OUString aFilterName( rMedium.GetFilter()->GetFilterName() );
......@@ -2242,10 +2260,13 @@ sal_Bool SfxObjectShell::ImportFrom( SfxMedium& rMedium, bool bInsert )
aArgs[nEnd-1].Value <<= rMedium.GetBaseURL();
}
if ( bInsert ) {
if (xInsertPosition.is()) {
aArgs.realloc( ++nEnd );
aArgs[nEnd-1].Name = "InsertMode";
aArgs[nEnd-1].Value <<= (sal_Bool) sal_True;
aArgs.realloc( ++nEnd );
aArgs[nEnd-1].Name = "TextInsertModeRange";
aArgs[nEnd-1].Value <<= xInsertPosition;
}
// #i119492# During loading, some OLE objects like chart will be set
......@@ -3603,6 +3624,15 @@ void SfxObjectShell::UpdateLinks()
bool SfxObjectShell::LoadExternal( SfxMedium& )
{
// Not implemented. It's an error if the code path ever comes here.
assert(false);
return false;
}
bool SfxObjectShell::InsertGeneratedStream(SfxMedium&,
uno::Reference<text::XTextRange> const&)
{
// Not implemented. It's an error if the code path ever comes here.
assert(false);
return false;
}
......
......@@ -93,6 +93,9 @@ class SW_DLLPUBLIC SwDocShell: public SfxObjectShell, public SfxListener
SW_DLLPRIVATE virtual sal_uInt16 PrepareClose( sal_Bool bUI = sal_True, sal_Bool bForBrowsing = sal_False );
SW_DLLPRIVATE virtual bool InsertGeneratedStream(SfxMedium& rMedium,
css::uno::Reference<css::text::XTextRange> const& xInsertPosition)
SAL_OVERRIDE;
/// Make DocInfo known to the Doc.
SW_DLLPRIVATE virtual SfxDocumentInfoDialog* CreateDocumentInfoDialog(
......
......@@ -106,6 +106,7 @@
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <unomid.h>
#include <unotextrange.hxx>
#include <sfx2/Metadatable.hxx>
#include <switerator.hxx>
......@@ -124,6 +125,22 @@ TYPEINIT2(SwDocShell, SfxObjectShell, SfxListener);
SFX_IMPL_OBJECTFACTORY(SwDocShell, SvGlobalName(SO3_SW_CLASSID), SFXOBJECTSHELL_STD_NORMAL|SFXOBJECTSHELL_HASMENU, "swriter" )
bool SwDocShell::InsertGeneratedStream(SfxMedium & rMedium,
uno::Reference<text::XTextRange> const& xInsertPosition)
{
SwUnoInternalPaM aPam(*GetDoc()); // must have doc since called from SwView
if (!::sw::XTextRangeToSwPaM(aPam, xInsertPosition))
return false;
// similar to SwView::InsertMedium
SwReader *pReader(0);
Reader *const pRead = StartConvertFrom(rMedium, &pReader, 0, &aPam);
if (!pRead)
return false;
sal_uLong const nError = pReader->Read(*pRead);
delete pReader;
return 0 == nError;
}
// Prepare loading
Reader* SwDocShell::StartConvertFrom(SfxMedium& rMedium, SwReader** ppRdr,
SwCrsrShell *pCrsrShell,
......
......@@ -131,6 +131,7 @@
#include <fmthdft.hxx>
#include <svx/ofaitem.hxx>
#include <unomid.h>
#include <unotextrange.hxx>
#include <docstat.hxx>
#include <wordcountdialog.hxx>
......@@ -2150,7 +2151,11 @@ long SwView::InsertMedium( sal_uInt16 nSlotId, SfxMedium* pMedium, sal_Int16 nVe
else
{
::sw::UndoGuard const ug(pDoc->GetIDocumentUndoRedo());
nErrno = pDocSh->ImportFrom( *pMedium, true ) ? 0 : ERR_SWG_READ_ERROR;
uno::Reference<text::XTextRange> const xInsertPosition(
SwXTextRange::CreateXTextRange(*pDoc,
*m_pWrtShell->GetCrsr()->GetPoint(), 0));
nErrno = pDocSh->ImportFrom(*pMedium, xInsertPosition)
? 0 : ERR_SWG_READ_ERROR;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment