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

fix missing BaseURL when loading embedded objects

When the object is edited in the UI, the m_xClient is set to a
SfxInPlaceClient and the DocumentBaseURL is retrieved from it.  But if
the object is not edited, it will be loaded during export via the API
and without a m_xClient; in this case the DocumentBaseURL must have been
set previously to be available during import.

There appears to be no way to get the URL of the document via the API
while it is being imported; SfxBaseModel's m_sURL is unfortunately only
initialized from SfxObjectShell::FinishedLoading().

During ODF import, the SvXMLEmbeddedObjectHelper creates the
embedded object, so let's make it pass in the parent's BaseURL.

The "DefaultParentBaseURL" parameter already exists but was unused
previously.

Change-Id: I3d1ed29b3a2c0e77ec606a1d09f7bc07e7860733
(cherry picked from commit b0fc09da)
üst 88cd3f3f
...@@ -280,7 +280,9 @@ OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const css::uno::Referen ...@@ -280,7 +280,9 @@ OUString EmbeddedObjectContainer::GetEmbeddedObjectName( const css::uno::Referen
return OUString(); return OUString();
} }
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedObject( const OUString& rName ) uno::Reference< embed::XEmbeddedObject>
EmbeddedObjectContainer::GetEmbeddedObject(
const OUString& rName, OUString const*const pBaseURL)
{ {
SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Empty object name!"); SAL_WARN_IF( rName.isEmpty(), "comphelper.container", "Empty object name!");
...@@ -303,12 +305,15 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedOb ...@@ -303,12 +305,15 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::GetEmbeddedOb
if ( aIt != pImpl->maObjectContainer.end() ) if ( aIt != pImpl->maObjectContainer.end() )
xObj = (*aIt).second; xObj = (*aIt).second;
else else
xObj = Get_Impl( rName, uno::Reference < embed::XEmbeddedObject >() ); xObj = Get_Impl(rName, uno::Reference<embed::XEmbeddedObject>(), pBaseURL);
return xObj; return xObj;
} }
uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( const OUString& rName, const uno::Reference < embed::XEmbeddedObject >& xCopy ) uno::Reference<embed::XEmbeddedObject> EmbeddedObjectContainer::Get_Impl(
const OUString& rName,
const uno::Reference<embed::XEmbeddedObject>& xCopy,
rtl::OUString const*const pBaseURL)
{ {
uno::Reference < embed::XEmbeddedObject > xObj; uno::Reference < embed::XEmbeddedObject > xObj;
try try
...@@ -328,13 +333,20 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( con ...@@ -328,13 +333,20 @@ uno::Reference < embed::XEmbeddedObject > EmbeddedObjectContainer::Get_Impl( con
// object was not added until now - should happen only by calling this method from "inside" // object was not added until now - should happen only by calling this method from "inside"
//TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call) //TODO/LATER: it would be good to detect an error when an object should be created already, but isn't (not an "inside" call)
uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() ); uno::Reference < embed::XEmbeddedObjectCreator > xFactory = embed::EmbeddedObjectCreator::create( ::comphelper::getProcessComponentContext() );
uno::Sequence< beans::PropertyValue > aObjDescr( xCopy.is() ? 2 : 1 ); uno::Sequence< beans::PropertyValue > aObjDescr(1 + (xCopy.is() ? 1 : 0) + (pBaseURL ? 1 : 0));
aObjDescr[0].Name = "Parent"; aObjDescr[0].Name = "Parent";
aObjDescr[0].Value <<= pImpl->m_xModel.get(); aObjDescr[0].Value <<= pImpl->m_xModel.get();
sal_Int32 i = 1;
if (pBaseURL)
{
aObjDescr[i].Name = "DefaultParentBaseURL";
aObjDescr[i].Value <<= *pBaseURL;
++i;
}
if ( xCopy.is() ) if ( xCopy.is() )
{ {
aObjDescr[1].Name = "CloneFrom"; aObjDescr[i].Name = "CloneFrom";
aObjDescr[1].Value <<= xCopy; aObjDescr[i].Value <<= xCopy;
} }
uno::Sequence< beans::PropertyValue > aMediaDescr( 1 ); uno::Sequence< beans::PropertyValue > aMediaDescr( 1 );
......
...@@ -43,6 +43,7 @@ namespace comphelper ...@@ -43,6 +43,7 @@ namespace comphelper
virtual css::uno::Reference < css::embed::XStorage > getStorage() const = 0; virtual css::uno::Reference < css::embed::XStorage > getStorage() const = 0;
virtual css::uno::Reference< css::task::XInteractionHandler > getInteractionHandler() const = 0; virtual css::uno::Reference< css::task::XInteractionHandler > getInteractionHandler() const = 0;
virtual bool isEnableSetModified() const = 0; virtual bool isEnableSetModified() const = 0;
virtual OUString getDocumentBaseURL() const = 0;
protected: protected:
~IEmbeddedHelper() {} ~IEmbeddedHelper() {}
...@@ -54,7 +55,8 @@ class COMPHELPER_DLLPUBLIC EmbeddedObjectContainer ...@@ -54,7 +55,8 @@ class COMPHELPER_DLLPUBLIC EmbeddedObjectContainer
EmbedImpl* pImpl; EmbedImpl* pImpl;
css::uno::Reference < css::embed::XEmbeddedObject > Get_Impl( const OUString&, css::uno::Reference < css::embed::XEmbeddedObject > Get_Impl( const OUString&,
const css::uno::Reference < css::embed::XEmbeddedObject >& xCopy); const css::uno::Reference < css::embed::XEmbeddedObject >& xCopy,
OUString const* pBaseURL = nullptr);
public: public:
// add an embedded object to the container storage // add an embedded object to the container storage
...@@ -92,7 +94,7 @@ public: ...@@ -92,7 +94,7 @@ public:
OUString GetEmbeddedObjectName( const css::uno::Reference < css::embed::XEmbeddedObject >& ); OUString GetEmbeddedObjectName( const css::uno::Reference < css::embed::XEmbeddedObject >& );
// retrieve an embedded object by name that either has been added already or is available in the container storage // retrieve an embedded object by name that either has been added already or is available in the container storage
css::uno::Reference < css::embed::XEmbeddedObject > GetEmbeddedObject( const OUString& ); css::uno::Reference<css::embed::XEmbeddedObject> GetEmbeddedObject(const OUString&, OUString const* pBaseURL = nullptr);
// create an object from a ClassId // create an object from a ClassId
css::uno::Reference < css::embed::XEmbeddedObject > css::uno::Reference < css::embed::XEmbeddedObject >
......
...@@ -584,6 +584,8 @@ public: ...@@ -584,6 +584,8 @@ public:
{ {
return IsEnableSetModified(); return IsEnableSetModified();
} }
virtual OUString getDocumentBaseURL() const override;
comphelper::EmbeddedObjectContainer& GetEmbeddedObjectContainer() const; comphelper::EmbeddedObjectContainer& GetEmbeddedObjectContainer() const;
void ClearEmbeddedObjects(); void ClearEmbeddedObjects();
......
...@@ -392,6 +392,7 @@ namespace reportdesign ...@@ -392,6 +392,7 @@ namespace reportdesign
virtual ::comphelper::EmbeddedObjectContainer& getEmbeddedObjectContainer() const override; virtual ::comphelper::EmbeddedObjectContainer& getEmbeddedObjectContainer() const override;
virtual css::uno::Reference< css::task::XInteractionHandler > getInteractionHandler() const override; virtual css::uno::Reference< css::task::XInteractionHandler > getInteractionHandler() const override;
virtual bool isEnableSetModified() const override; virtual bool isEnableSetModified() const override;
virtual OUString getDocumentBaseURL() const override;
css::uno::Reference< css::ui::XUIConfigurationManager2 > getUIConfigurationManager2( ) throw (css::uno::RuntimeException); css::uno::Reference< css::ui::XUIConfigurationManager2 > getUIConfigurationManager2( ) throw (css::uno::RuntimeException);
}; };
......
...@@ -2512,6 +2512,11 @@ bool OReportDefinition::isEnableSetModified() const ...@@ -2512,6 +2512,11 @@ bool OReportDefinition::isEnableSetModified() const
return true; return true;
} }
OUString OReportDefinition::getDocumentBaseURL() const
{
return const_cast<OReportDefinition*>(this)->getURL();
}
uno::Reference< frame::XTitle > OReportDefinition::impl_getTitleHelper_throw() uno::Reference< frame::XTitle > OReportDefinition::impl_getTitleHelper_throw()
{ {
SolarMutexGuard aSolarGuard; SolarMutexGuard aSolarGuard;
......
...@@ -3618,6 +3618,7 @@ bool SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference< ta ...@@ -3618,6 +3618,7 @@ bool SfxObjectShell::QuerySaveSizeExceededModules_Impl( const uno::Reference< ta
return true; return true;
} }
// comphelper::IEmbeddedHelper
uno::Reference< task::XInteractionHandler > SfxObjectShell::getInteractionHandler() const uno::Reference< task::XInteractionHandler > SfxObjectShell::getInteractionHandler() const
{ {
uno::Reference< task::XInteractionHandler > xRet; uno::Reference< task::XInteractionHandler > xRet;
...@@ -3626,4 +3627,9 @@ uno::Reference< task::XInteractionHandler > SfxObjectShell::getInteractionHandle ...@@ -3626,4 +3627,9 @@ uno::Reference< task::XInteractionHandler > SfxObjectShell::getInteractionHandle
return xRet; return xRet;
} }
OUString SfxObjectShell::getDocumentBaseURL() const
{
return GetMedium()->GetBaseURL();
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
...@@ -445,7 +445,8 @@ bool SvXMLEmbeddedObjectHelper::ImplReadObject( ...@@ -445,7 +445,8 @@ bool SvXMLEmbeddedObjectHelper::ImplReadObject(
// server that was used to create the object. pClassId could be used to specify the server that should // server that was used to create the object. pClassId could be used to specify the server that should
// be used for the next opening, but this information seems to be out of the file format responsibility // be used for the next opening, but this information seems to be out of the file format responsibility
// area. // area.
rContainer.GetEmbeddedObject( aName ); OUString const baseURL(mpDocPersist->getDocumentBaseURL());
rContainer.GetEmbeddedObject(aName, &baseURL);
return true; return true;
} }
......
...@@ -475,10 +475,32 @@ DECLARE_OOXMLEXPORT_TEST(testTableBorders, "table-borders.docx") ...@@ -475,10 +475,32 @@ DECLARE_OOXMLEXPORT_TEST(testTableBorders, "table-borders.docx")
DECLARE_OOXMLEXPORT_TEST(testFdo51550, "fdo51550.odt") DECLARE_OOXMLEXPORT_TEST(testFdo51550, "fdo51550.odt")
{ {
// The problem was that we lacked the fallback to export the replacement graphic for OLE objects. // The problem was that we lacked the fallback to export the replacement
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); // graphic for OLE objects. But we can actually export the OLE itself now,
uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY); // so check that instead.
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xDraws->getCount()); uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xEmbeddedObjects(xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(1), xEmbeddedObjects->getCount());
xmlDocPtr pXmlDocCT = parseExport("[Content_Types].xml");
if (!pXmlDocCT)
return; // initial import
assertXPath(pXmlDocCT, "/ContentType:Types/ContentType:Override[@PartName='/word/embeddings/oleObject1.xlsx']", "ContentType", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
// check the rels too
xmlDocPtr pXmlDocRels = parseExport("word/_rels/document.xml.rels");
assertXPath(pXmlDocRels,
"/rels:Relationships/rels:Relationship[@Target='embeddings/oleObject1.xlsx']",
"Type",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/package");
// check the content too
xmlDocPtr pXmlDocContent = parseExport("word/document.xml");
assertXPath(pXmlDocContent,
"/w:document/w:body/w:p/w:r/w:object/o:OLEObject",
"ProgID",
"Excel.Sheet.12");
} }
/* /*
......
...@@ -828,13 +828,13 @@ DECLARE_OOXMLEXPORT_TEST(testContentTypeXLSM, "fdo76098.docx") ...@@ -828,13 +828,13 @@ DECLARE_OOXMLEXPORT_TEST(testContentTypeXLSM, "fdo76098.docx")
assertXPath(pXmlDoc, "/ContentType:Types/ContentType:Override[@PartName='/word/embeddings/Microsoft_Excel_Macro-Enabled_Worksheet1.xlsm']", "ContentType", "application/vnd.ms-excel.sheet.macroEnabled.12"); assertXPath(pXmlDoc, "/ContentType:Types/ContentType:Override[@PartName='/word/embeddings/Microsoft_Excel_Macro-Enabled_Worksheet1.xlsm']", "ContentType", "application/vnd.ms-excel.sheet.macroEnabled.12");
// check the rels too // check the rels too
xmlDocPtr pXmlDocRels = parseExport("word/charts/_rels/chart1.xml.rels"); xmlDocPtr pXmlDocRels = parseExport("word/charts/_rels/chart2.xml.rels");
assertXPath(pXmlDocRels, assertXPath(pXmlDocRels,
"/rels:Relationships/rels:Relationship[@Target='../embeddings/Microsoft_Excel_Macro-Enabled_Worksheet1.xlsm']", "/rels:Relationships/rels:Relationship[@Target='../embeddings/Microsoft_Excel_Macro-Enabled_Worksheet1.xlsm']",
"Type", "Type",
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/package"); "http://schemas.openxmlformats.org/officeDocument/2006/relationships/package");
// check the content too // check the content too
xmlDocPtr pXmlDocChart1 = parseExport("word/charts/chart1.xml"); xmlDocPtr pXmlDocChart1 = parseExport("word/charts/chart2.xml");
assertXPath(pXmlDocChart1, assertXPath(pXmlDocChart1,
"/c:chartSpace/c:externalData", "/c:chartSpace/c:externalData",
"id", "id",
......
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