Kaydet (Commit) 6083a8f1 authored tarafından Miklos Vajna's avatar Miklos Vajna

Related: tdf#59699 DOCX import: fix linked graphics with relative URLs

Because the writerfilter::ooxml::OOXMLFastContextHandlerShape
constructor only sent the input stream (and not the full media
descriptor) to oox::shape::ShapeContextHandler, it's startFastElement()
tried to reconstruct a media descriptor from just the input stream. As a
result, the base URL of the document got lost at the time the
oox::drawingml::BlipContext constructor tried to call getAbsoluteUrl(),
to convert the relative URL to an absolute one.

Fix the problem by sending not only the input stream, but the full media
descriptor to the shape importer. As a bonus that makes code simpler,
too.

Change-Id: I1f06c04d0745aa7e2e06d4848cf454790d5073ca
üst ec935c9b
......@@ -40,11 +40,11 @@ interface XFastShapeContextHandler: com::sun::star::xml::sax::XFastContextHandle
[attribute, readonly] com::sun::star::drawing::XShape Shape;
[attribute] com::sun::star::drawing::XDrawPage DrawPage;
[attribute] com::sun::star::frame::XModel Model;
[attribute] com::sun::star::io::XInputStream InputStream;
[attribute] string RelationFragmentPath;
[attribute] long StartToken;
[attribute] com::sun::star::awt::Point Position;
[attribute] com::sun::star::document::XDocumentProperties DocumentProperties;
[attribute] sequence< com::sun::star::beans::PropertyValue > MediaDescriptor;
};
......
......@@ -272,13 +272,7 @@ void SAL_CALL ShapeContextHandler::startFastElement
const uno::Reference< xml::sax::XFastAttributeList > & Attribs)
throw (uno::RuntimeException, xml::sax::SAXException, std::exception)
{
static const OUString sInputStream
("InputStream");
uno::Sequence<beans::PropertyValue> aSeq(1);
aSeq[0].Name = sInputStream;
aSeq[0].Value <<= mxInputStream;
mxFilterBase->filter(aSeq);
mxFilterBase->filter(maMediaDescriptor);
mpThemePtr.reset(new Theme());
......@@ -573,19 +567,6 @@ void SAL_CALL ShapeContextHandler::setModel
mxFilterBase->setTargetDocument(xComp);
}
uno::Reference< io::XInputStream > SAL_CALL
ShapeContextHandler::getInputStream() throw (uno::RuntimeException, std::exception)
{
return mxInputStream;
}
void SAL_CALL ShapeContextHandler::setInputStream
(const uno::Reference< io::XInputStream > & the_value)
throw (uno::RuntimeException, std::exception)
{
mxInputStream = the_value;
}
OUString SAL_CALL ShapeContextHandler::getRelationFragmentPath()
throw (uno::RuntimeException, std::exception)
{
......@@ -631,6 +612,18 @@ uno::Reference<document::XDocumentProperties> SAL_CALL ShapeContextHandler::getD
return mxDocumentProperties;
}
uno::Sequence<beans::PropertyValue> SAL_CALL ShapeContextHandler::getMediaDescriptor()
throw (uno::RuntimeException, std::exception)
{
return maMediaDescriptor;
}
void SAL_CALL ShapeContextHandler::setMediaDescriptor(const uno::Sequence<beans::PropertyValue>& rMediaDescriptor)
throw (uno::RuntimeException, std::exception)
{
maMediaDescriptor = rMediaDescriptor;
}
OUString ShapeContextHandler::getImplementationName()
throw (css::uno::RuntimeException, std::exception)
{
......
......@@ -120,13 +120,6 @@ public:
(const css::uno::Reference< css::frame::XModel > & the_value)
throw (css::uno::RuntimeException, std::exception) override;
virtual css::uno::Reference< css::io::XInputStream > SAL_CALL
getInputStream() throw (css::uno::RuntimeException, std::exception) override;
virtual void SAL_CALL setInputStream
(const css::uno::Reference< css::io::XInputStream > & the_value)
throw (css::uno::RuntimeException, std::exception) override;
virtual OUString SAL_CALL getRelationFragmentPath()
throw (css::uno::RuntimeException, std::exception) override;
virtual void SAL_CALL setRelationFragmentPath
......@@ -143,6 +136,10 @@ public:
throw (css::uno::RuntimeException, std::exception) override;
virtual css::uno::Reference<css::document::XDocumentProperties> SAL_CALL getDocumentProperties()
throw (css::uno::RuntimeException, std::exception) override;
virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL getMediaDescriptor()
throw (css::uno::RuntimeException, std::exception) override;
virtual void SAL_CALL setMediaDescriptor(const css::uno::Sequence<css::beans::PropertyValue>& rMediaDescriptor)
throw (css::uno::RuntimeException, std::exception) override;
private:
ShapeContextHandler(ShapeContextHandler &) = delete;
......@@ -165,11 +162,11 @@ private:
css::uno::Reference<XFastContextHandler> mxWpgContext;
css::uno::Reference<XFastContextHandler> mxChartShapeContext;
css::uno::Reference<css::document::XDocumentProperties> mxDocumentProperties;
css::uno::Sequence<css::beans::PropertyValue> maMediaDescriptor;
::rtl::Reference< core::XmlFilterBase > mxFilterBase;
drawingml::ThemePtr mpThemePtr;
css::uno::Reference<css::drawing::XDrawPage> mxDrawPage;
css::uno::Reference<css::io::XInputStream> mxInputStream;
OUString msRelationFragmentPath;
css::uno::Reference<XFastContextHandler> getGraphicShapeContext(::sal_Int32 Element);
......
......@@ -782,6 +782,14 @@ DECLARE_OOXMLIMPORT_TEST(testN777345, "n777345.docx")
#endif
}
DECLARE_OOXMLIMPORT_TEST(testTdf59699, "tdf59699.docx")
{
uno::Reference<beans::XPropertySet> xImage(getShape(1), uno::UNO_QUERY);
auto xGraphic = getProperty<uno::Reference<graphic::XGraphic> >(xImage, "Graphic");
// This was false: the referenced graphic data wasn't imported.
CPPUNIT_ASSERT(xGraphic.is());
}
DECLARE_OOXMLIMPORT_TEST(testN777337, "n777337.docx")
{
/*
......
......@@ -254,7 +254,7 @@ public:
static OOXMLDocument *
createDocument(OOXMLStream::Pointer_t pStream,
const css::uno::Reference<css::task::XStatusIndicator>& xStatusIndicator,
bool bSkipImage, OUString const& rBaseURL);
bool bSkipImage, const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor);
};
......
......@@ -153,7 +153,6 @@ sal_Bool WriterFilter::filter(const uno::Sequence< beans::PropertyValue >& aDesc
utl::MediaDescriptor aMediaDesc(aDescriptor);
bool bRepairStorage = aMediaDesc.getUnpackedValueOrDefault("RepairPackage", false);
bool bSkipImages = aMediaDesc.getUnpackedValueOrDefault("FilterOptions", OUString("")) == "SkipImages";
OUString const baseURI = aMediaDesc.getUnpackedValueOrDefault("DocumentBaseURL", OUString(""));
uno::Reference< io::XInputStream > xInputStream;
try
......@@ -174,7 +173,7 @@ sal_Bool WriterFilter::filter(const uno::Sequence< beans::PropertyValue >& aDesc
//create the tokenizer and domain mapper
writerfilter::ooxml::OOXMLStream::Pointer_t pDocStream = writerfilter::ooxml::OOXMLDocumentFactory::createStream(m_xContext, xInputStream, bRepairStorage);
uno::Reference<task::XStatusIndicator> xStatusIndicator = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_STATUSINDICATOR(), uno::Reference<task::XStatusIndicator>());
writerfilter::ooxml::OOXMLDocument::Pointer_t pDocument(writerfilter::ooxml::OOXMLDocumentFactory::createDocument(pDocStream, xStatusIndicator, bSkipImages, baseURI));
writerfilter::ooxml::OOXMLDocument::Pointer_t pDocument(writerfilter::ooxml::OOXMLDocumentFactory::createDocument(pDocStream, xStatusIndicator, bSkipImages, aDescriptor));
uno::Reference<frame::XModel> xModel(m_xDstDoc, uno::UNO_QUERY_THROW);
pDocument->setModel(xModel);
......
......@@ -38,6 +38,7 @@
#include <vcl/settings.hxx>
#include <svx/dialogs.hrc>
#include <comphelper/sequence.hxx>
#include <unotools/mediadescriptor.hxx>
#include <iostream>
......@@ -49,7 +50,7 @@ namespace writerfilter {
namespace ooxml
{
OOXMLDocumentImpl::OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream, const uno::Reference<task::XStatusIndicator>& xStatusIndicator, bool bSkipImages, OUString const& rBaseURL)
OOXMLDocumentImpl::OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream, const uno::Reference<task::XStatusIndicator>& xStatusIndicator, bool bSkipImages, const uno::Sequence<beans::PropertyValue>& rDescriptor)
: mpStream(pStream)
, mxStatusIndicator(xStatusIndicator)
, mnXNoteId(0)
......@@ -61,7 +62,8 @@ OOXMLDocumentImpl::OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream, const uno::
, mnProgressLastPos(0)
, mnProgressCurrentPos(0)
, mnProgressEndPos(0)
, m_rBaseURL(rBaseURL)
, m_rBaseURL(utl::MediaDescriptor(rDescriptor).getUnpackedValueOrDefault("DocumentBaseURL", OUString()))
, maMediaDescriptor(rDescriptor)
{
}
......@@ -266,7 +268,7 @@ OOXMLDocumentImpl::getSubStream(const OUString & rId)
OOXMLDocumentImpl * pTemp;
// Do not pass status indicator to sub-streams: they are typically marginal in size, so we just track the main document for now.
writerfilter::Reference<Stream>::Pointer_t pRet( pTemp = new OOXMLDocumentImpl(pStream, uno::Reference<task::XStatusIndicator>(), mbSkipImages, m_rBaseURL));
writerfilter::Reference<Stream>::Pointer_t pRet( pTemp = new OOXMLDocumentImpl(pStream, uno::Reference<task::XStatusIndicator>(), mbSkipImages, maMediaDescriptor));
pTemp->setModel(mxModel);
pTemp->setDrawPage(mxDrawPage);
pTemp->setIsSubstream( true );
......@@ -280,7 +282,7 @@ OOXMLDocumentImpl::getXNoteStream(OOXMLStream::StreamType_t nType, const Id & rT
OOXMLStream::Pointer_t pStream =
(OOXMLDocumentFactory::createStream(mpStream, nType));
// See above, no status indicator for the note stream, either.
OOXMLDocumentImpl * pDocument = new OOXMLDocumentImpl(pStream, uno::Reference<task::XStatusIndicator>(), mbSkipImages, m_rBaseURL);
OOXMLDocumentImpl * pDocument = new OOXMLDocumentImpl(pStream, uno::Reference<task::XStatusIndicator>(), mbSkipImages, maMediaDescriptor);
pDocument->setXNoteId(nId);
pDocument->setXNoteType(rType);
pDocument->setModel(getModel());
......@@ -886,6 +888,11 @@ uno::Reference<io::XInputStream> OOXMLDocumentImpl::getStorageStream()
return mpStream->getStorageStream();
}
const uno::Sequence<beans::PropertyValue>& OOXMLDocumentImpl::getMediaDescriptor()
{
return maMediaDescriptor;
}
void OOXMLDocumentImpl::setShapeContext( uno::Reference<xml::sax::XFastShapeContextHandler> xContext )
{
mxShapeContext = xContext;
......@@ -930,9 +937,9 @@ OOXMLDocument *
OOXMLDocumentFactory::createDocument
(OOXMLStream::Pointer_t pStream,
const uno::Reference<task::XStatusIndicator>& xStatusIndicator,
bool mbSkipImages, OUString const& rBaseURL)
bool mbSkipImages, const uno::Sequence<beans::PropertyValue>& rDescriptor)
{
return new OOXMLDocumentImpl(pStream, xStatusIndicator, mbSkipImages, rBaseURL);
return new OOXMLDocumentImpl(pStream, xStatusIndicator, mbSkipImages, rDescriptor);
}
}}
......
......@@ -64,7 +64,8 @@ class OOXMLDocumentImpl : public OOXMLDocument
/// End position, i.e. the estimated number of paragraphs.
sal_Int32 mnProgressEndPos;
/// DocumentBaseURL
OUString const m_rBaseURL;
OUString m_rBaseURL;
css::uno::Sequence<css::beans::PropertyValue> maMediaDescriptor;
protected:
void resolveFastSubStream(Stream & rStream,
......@@ -92,7 +93,7 @@ protected:
void resolveGlossaryStream(Stream & rStream);
void resolveEmbeddingsStream(OOXMLStream::Pointer_t pStream);
public:
OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream, const css::uno::Reference<css::task::XStatusIndicator>& xStatusIndicator, bool bSkipImages, OUString const& rBaseURL);
OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream, const css::uno::Reference<css::task::XStatusIndicator>& xStatusIndicator, bool bSkipImages, const css::uno::Sequence<css::beans::PropertyValue>& rDescriptor);
virtual ~OOXMLDocumentImpl();
virtual void resolve(Stream & rStream) override;
......@@ -141,6 +142,7 @@ public:
void incrementProgress();
bool IsSkipImages() { return mbSkipImages; };
OUString const& GetDocumentBaseURL() { return m_rBaseURL; };
const css::uno::Sequence<css::beans::PropertyValue>& getMediaDescriptor();
};
}}
#endif // OOXML_DOCUMENT_IMPL_HXX
......
......@@ -1511,7 +1511,7 @@ OOXMLFastContextHandlerShape::OOXMLFastContextHandlerShape
uno::Reference<document::XDocumentPropertiesSupplier> xDocSupplier(getDocument()->getModel(), uno::UNO_QUERY_THROW);
mrShapeContext->setDocumentProperties(xDocSupplier->getDocumentProperties());
mrShapeContext->setDrawPage(getDocument()->getDrawPage());
mrShapeContext->setInputStream(getDocument()->getStorageStream());
mrShapeContext->setMediaDescriptor(getDocument()->getMediaDescriptor());
mrShapeContext->setRelationFragmentPath
(mpParserState->getTarget());
......
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