From c5138cad87575283cdf0670355f2b2cddae93fc8 Mon Sep 17 00:00:00 2001 From: Michael Stahl Date: Thu, 5 Dec 2013 12:15:15 +0100 Subject: 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 --- include/sfx2/objsh.hxx | 10 ++++++- sd/source/ui/docshell/docshel4.cxx | 5 ++-- sd/source/ui/inc/DrawDocShell.hxx | 4 ++- sfx2/source/doc/objstor.cxx | 60 ++++++++++++++++++++++++++++---------- sw/inc/docsh.hxx | 3 ++ sw/source/ui/app/docsh.cxx | 17 +++++++++++ sw/source/ui/uiview/view2.cxx | 7 ++++- 7 files changed, 86 insertions(+), 20 deletions(-) diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index fac2625698cd..de041fbf3bc7 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -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 const& xInsertPosition); + virtual bool ImportFrom( SfxMedium &rMedium, + css::uno::Reference const& xInsertPosition); sal_Bool ExportTo( SfxMedium &rMedium ); // xmlsec05, check with SFX team diff --git a/sd/source/ui/docshell/docshel4.cxx b/sd/source/ui/docshell/docshel4.cxx index 04fcf2a1f321..eeae1004450b 100644 --- a/sd/source/ui/docshell/docshel4.cxx +++ b/sd/source/ui/docshell/docshel4.cxx @@ -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 const& xInsertPosition) { - const sal_Bool bRet=SfxObjectShell::ImportFrom(rMedium, bInsert); + const sal_Bool bRet = SfxObjectShell::ImportFrom(rMedium, xInsertPosition); SfxItemSet* pSet = rMedium.GetItemSet(); if( pSet ) diff --git a/sd/source/ui/inc/DrawDocShell.hxx b/sd/source/ui/inc/DrawDocShell.hxx index 5278fc6ec1ee..d4e46fc0aced 100644 --- a/sd/source/ui/inc/DrawDocShell.hxx +++ b/sd/source/ui/inc/DrawDocShell.hxx @@ -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 const& xInsertPosition) + SAL_OVERRIDE; virtual sal_Bool ConvertFrom( SfxMedium &rMedium ); virtual sal_Bool Save(); virtual sal_Bool SaveAsOwnFormat( SfxMedium& rMedium ); diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx index 125edca36a7f..df12f4f976a0 100644 --- a/sfx2/source/doc/objstor.cxx +++ b/sfx2/source/doc/objstor.cxx @@ -66,6 +66,7 @@ #include #include #include +#include #include #include @@ -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 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 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 const&) +{ + // Not implemented. It's an error if the code path ever comes here. + assert(false); return false; } diff --git a/sw/inc/docsh.hxx b/sw/inc/docsh.hxx index 267060338d7a..f8f60bf71684 100644 --- a/sw/inc/docsh.hxx +++ b/sw/inc/docsh.hxx @@ -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 const& xInsertPosition) + SAL_OVERRIDE; /// Make DocInfo known to the Doc. SW_DLLPRIVATE virtual SfxDocumentInfoDialog* CreateDocumentInfoDialog( diff --git a/sw/source/ui/app/docsh.cxx b/sw/source/ui/app/docsh.cxx index e4f95338416f..e96af964120e 100644 --- a/sw/source/ui/app/docsh.cxx +++ b/sw/source/ui/app/docsh.cxx @@ -106,6 +106,7 @@ #include #include +#include #include #include @@ -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 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, diff --git a/sw/source/ui/uiview/view2.cxx b/sw/source/ui/uiview/view2.cxx index ecfaa893e602..06ea67fa70d2 100644 --- a/sw/source/ui/uiview/view2.cxx +++ b/sw/source/ui/uiview/view2.cxx @@ -131,6 +131,7 @@ #include #include #include +#include #include #include @@ -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 const xInsertPosition( + SwXTextRange::CreateXTextRange(*pDoc, + *m_pWrtShell->GetCrsr()->GetPoint(), 0)); + nErrno = pDocSh->ImportFrom(*pMedium, xInsertPosition) + ? 0 : ERR_SWG_READ_ERROR; } } -- cgit v1.2.3