summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/com/sun/star/uno/Any.h1
-rw-r--r--include/com/sun/star/uno/Any.hxx2
-rw-r--r--sw/qa/extras/ooxmlexport/data/glossaryWithEmail.docxbin0 -> 19290 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport3.cxx11
-rw-r--r--sw/source/filter/ww8/docxexport.cxx42
-rw-r--r--writerfilter/inc/ooxml/OOXMLDocument.hxx3
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.cxx163
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.hxx4
8 files changed, 132 insertions, 94 deletions
diff --git a/include/com/sun/star/uno/Any.h b/include/com/sun/star/uno/Any.h
index 123952142517..f232ccd90fe9 100644
--- a/include/com/sun/star/uno/Any.h
+++ b/include/com/sun/star/uno/Any.h
@@ -88,6 +88,7 @@ public:
explicit Any(rtl::OUStringConcat<T1, T2> const &) = delete;
template<typename T> explicit inline Any(rtl::OUStringNumber<T> && value);
template<typename T> explicit Any(rtl::OUStringNumber<T> const &) = delete;
+ template <std::size_t N> explicit inline Any(const rtl::OUStringLiteral<N>& value);
#endif
/** Copy constructor: Sets value of the given any.
diff --git a/include/com/sun/star/uno/Any.hxx b/include/com/sun/star/uno/Any.hxx
index fbceffa5e241..d73b2a586d61 100644
--- a/include/com/sun/star/uno/Any.hxx
+++ b/include/com/sun/star/uno/Any.hxx
@@ -86,6 +86,8 @@ Any::Any(rtl::OUStringConcat<T1, T2> && value):
{}
template<typename T>
Any::Any(rtl::OUStringNumber<T> && value): Any(rtl::OUString(std::move(value))) {}
+template <std::size_t N>
+Any::Any(const rtl::OUStringLiteral<N>& value): Any(rtl::OUString(value)) {}
#endif
inline Any::Any( const Any & rAny )
diff --git a/sw/qa/extras/ooxmlexport/data/glossaryWithEmail.docx b/sw/qa/extras/ooxmlexport/data/glossaryWithEmail.docx
new file mode 100644
index 000000000000..5ec375adf3ac
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/glossaryWithEmail.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx
index fe1aa44d75e7..9930fa27b768 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport3.cxx
@@ -991,6 +991,17 @@ CPPUNIT_TEST_FIXTURE(Test, testGlossary)
assertXPath(pXmlDoc, "/w:glossaryDocument", "Ignorable", "w14 wp14");
}
+CPPUNIT_TEST_FIXTURE(Test, testGlossaryWithEmail)
+{
+ // tdf#152289
+ loadAndSave("glossaryWithEmail.docx");
+ xmlDocUniquePtr pXmlDoc = parseExport("word/glossary/_rels/document.xml.rels");
+ assertXPath(pXmlDoc, "/rels:Relationships/rels:Relationship[@Id='rId4' "
+ "and @Type='http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink' "
+ "and @Target='mailto:emailgoeshere@example.com' "
+ "and @TargetMode='External']");
+}
+
DECLARE_OOXMLEXPORT_TEST(testFdo71785, "fdo71785.docx")
{
// crashtest
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
index 97875b28817d..ea59775eda15 100644
--- a/sw/source/filter/ww8/docxexport.cxx
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -1484,6 +1484,7 @@ void DocxExport::WriteTheme()
uno::Sequence< beans::StringPair >() );
}
+// See OOXMLDocumentImpl::resolveGlossaryStream
void DocxExport::WriteGlossary()
{
uno::Reference< beans::XPropertySet > xPropSet( m_rDoc.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW );
@@ -1494,7 +1495,7 @@ void DocxExport::WriteGlossary()
return;
uno::Reference<xml::dom::XDocument> glossaryDocDom;
- uno::Sequence< uno::Sequence< uno::Any> > glossaryDomList;
+ uno::Sequence< uno::Sequence<beans::NamedValue> > glossaryDomList;
uno::Sequence< beans::PropertyValue > propList;
xPropSet->getPropertyValue( aName ) >>= propList;
sal_Int32 collectedProperties = 0;
@@ -1532,20 +1533,43 @@ void DocxExport::WriteGlossary()
serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
uno::Sequence< beans::StringPair >() );
- for ( const uno::Sequence< uno::Any>& glossaryElement : std::as_const(glossaryDomList))
+ for (const uno::Sequence<beans::NamedValue>& glossaryElement : glossaryDomList)
{
- OUString gTarget, gType, gId, contentType;
+ OUString gTarget, gType, gId, contentType, targetMode;
uno::Reference<xml::dom::XDocument> xDom;
- glossaryElement[0] >>= xDom;
- glossaryElement[1] >>= gId;
- glossaryElement[2] >>= gType;
- glossaryElement[3] >>= gTarget;
- glossaryElement[4] >>= contentType;
+ for (const auto& [name, value] : glossaryElement)
+ {
+ if (name == "Id")
+ value >>= gId;
+ else if (name == "Type")
+ value >>= gType;
+ else if (name == "Target")
+ value >>= gTarget;
+ else if (name == "TargetMode")
+ value >>= targetMode;
+ else if (name == "_contentType")
+ value >>= contentType;
+ else if (name == "_relDom")
+ value >>= xDom;
+ }
+ if (gId.isEmpty() || gType.isEmpty() || gTarget.isEmpty())
+ continue;
+ const bool bExternal = targetMode == "External";
+ if (!bExternal && !xDom)
+ {
+ // Some internal relation, but we didn't create a DOM for it
+ // in OOXMLDocumentImpl::resolveGlossaryStream?
+ SAL_WARN("sw.ww8", "Glossary internal relation without DOM: Id=\"" + gId
+ + "\" Type=\"" + gType + "\" Target=\"" + gTarget + "\"");
+ continue;
+ }
gId = gId.copy(3); //"rId" only save the numeric value
PropertySet aProps(xOutputStream);
aProps.setAnyProperty( PROP_RelId, uno::Any( gId.toInt32() ));
- m_rFilter.addRelation( xOutputStream, gType, gTarget);
+ m_rFilter.addRelation(xOutputStream, gType, gTarget, bExternal);
+ if (!xDom)
+ continue; // External relation, no stream to write
uno::Reference< xml::sax::XSAXSerializable > gserializer( xDom, uno::UNO_QUERY );
writer->setOutputStream(GetFilter().openFragmentStream( "word/glossary/" + gTarget, contentType ) );
gserializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ),
diff --git a/writerfilter/inc/ooxml/OOXMLDocument.hxx b/writerfilter/inc/ooxml/OOXMLDocument.hxx
index 8bf1502848ec..1179be43c8ac 100644
--- a/writerfilter/inc/ooxml/OOXMLDocument.hxx
+++ b/writerfilter/inc/ooxml/OOXMLDocument.hxx
@@ -19,6 +19,7 @@
#pragma once
#include <sal/types.h>
+#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
@@ -219,7 +220,7 @@ public:
virtual void popShapeContext() = 0;
virtual css::uno::Reference<css::xml::dom::XDocument> getThemeDom( ) = 0;
virtual css::uno::Reference<css::xml::dom::XDocument> getGlossaryDocDom( ) = 0;
- virtual css::uno::Sequence<css::uno::Sequence< css::uno::Any> > getGlossaryDomList() = 0;
+ virtual css::uno::Sequence<css::uno::Sequence< css::beans::NamedValue> > getGlossaryDomList() = 0;
virtual css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > getCustomXmlDomList( ) = 0;
virtual css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > getCustomXmlDomPropsList( ) = 0;
virtual css::uno::Sequence<css::beans::PropertyValue > getEmbeddingsList() = 0;
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
index 174549ed5e4b..fdfc1f1ed0ab 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx
@@ -37,6 +37,7 @@
#include <svx/dialmgr.hxx>
#include <svx/strings.hrc>
#include <comphelper/sequence.hxx>
+#include <comphelper/namedvaluecollection.hxx>
#include <cppuhelper/exc_hlp.hxx>
#include <unotools/mediadescriptor.hxx>
@@ -600,17 +601,32 @@ void OOXMLDocumentImpl::resolveCustomXmlStream(Stream & rStream)
mxCustomXmlDomPropsList = comphelper::containerToSequence(aCustomXmlDomPropsList);
}
-void OOXMLDocumentImpl::resolveGlossaryStream(Stream & /*rStream*/)
+namespace
{
- static const char sSettingsType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
- static const char sStylesType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
- static const char sFonttableType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
- static const char sWebSettings[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings";
- static const char sSettingsTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/settings";
- static const char sStylesTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/styles";
- static const char sFonttableTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/fontTable";
- static const char sWebSettingsStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/webSettings";
+const char sSettingsType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
+const char sStylesType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
+const char sFonttableType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
+const char sWebSettings[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings";
+const char sSettingsTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/settings";
+const char sStylesTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/styles";
+const char sFonttableTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/fontTable";
+const char sWebSettingsStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/webSettings";
+
+constexpr OUStringLiteral sId = u"Id";
+constexpr OUStringLiteral sType = u"Type";
+constexpr OUStringLiteral sTarget = u"Target";
+constexpr OUStringLiteral sTargetMode = u"TargetMode";
+constexpr OUStringLiteral sContentType = u"_contentType";
+constexpr OUStringLiteral sRelDom = u"_relDom";
+constexpr OUStringLiteral sSettingsContentType = u"application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml";
+constexpr OUStringLiteral sStylesContentType = u"application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml";
+constexpr OUStringLiteral sWebsettingsContentType = u"application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml";
+constexpr OUStringLiteral sFonttableContentType = u"application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml";
+}
+// See DocxExport::WriteGlossary
+void OOXMLDocumentImpl::resolveGlossaryStream(Stream & /*rStream*/)
+{
OOXMLStream::Pointer_t pStream;
try
{
@@ -629,80 +645,63 @@ void OOXMLDocumentImpl::resolveGlossaryStream(Stream & /*rStream*/)
const uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs = xRelationshipAccess->getAllRelationships();
- std::vector< uno::Sequence<uno::Any> > aGlossaryDomList;
+ std::vector< uno::Sequence<beans::NamedValue> > aGlossaryDomList;
for (const uno::Sequence< beans::StringPair >& aSeq : aSeqs)
{
- OOXMLStream::Pointer_t gStream;
- //Follows following aSeq[0] is Id, aSeq[1] is Type, aSeq[2] is Target
- if (aSeq.getLength() < 3)
- {
- SAL_WARN("writerfilter.ooxml", "too short sequence");
- continue;
- }
-
- OUString gId(aSeq[0].Second);
- OUString gType(aSeq[1].Second);
- OUString gTarget(aSeq[2].Second);
- OUString contentType;
-
- OOXMLStream::StreamType_t nType(OOXMLStream::UNKNOWN);
- bool bFound = true;
- if(gType == sSettingsType ||
- gType == sSettingsTypeStrict)
- {
- nType = OOXMLStream::SETTINGS;
- contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml";
- }
- else if(gType == sStylesType ||
- gType == sStylesTypeStrict)
- {
- nType = OOXMLStream::STYLES;
- contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml";
- }
- else if(gType == sWebSettings ||
- gType == sWebSettingsStrict)
- {
- nType = OOXMLStream::WEBSETTINGS;
- contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.webSettings+xml";
- }
- else if(gType == sFonttableType ||
- gType == sFonttableTypeStrict)
- {
- nType = OOXMLStream::FONTTABLE;
- contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml";
- }
- else
- {
- bFound = false;
- //"Unhandled content-type while grab bagging Glossary Folder");
- }
-
- if (bFound)
- {
- uno::Reference<xml::dom::XDocument> xDom;
- try
- {
- gStream = OOXMLDocumentFactory::createStream(pStream, nType);
- uno::Reference<io::XInputStream> xInputStream = gStream->getDocumentStream();
- uno::Reference<uno::XComponentContext> xContext(pStream->getContext());
- uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(xml::dom::DocumentBuilder::create(xContext));
- xDom = xDomBuilder->parse(xInputStream);
- }
- catch (uno::Exception const&)
- {
- TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "importSubStream: exception while "
- "parsing stream of Type" << nType);
- return;
- }
-
- if (xDom.is())
- {
- uno::Sequence< uno::Any > glossaryTuple{ uno::Any(xDom), uno::Any(gId),
- uno::Any(gType), uno::Any(gTarget),
- uno::Any(contentType) };
- aGlossaryDomList.push_back(glossaryTuple);
- }
- }
+ comphelper::NamedValueCollection aRelDefinition;
+ for (const auto& [name, value] : aSeq)
+ aRelDefinition.put(name, value);
+
+ const OUString gType = aRelDefinition.getOrDefault(sType, OUString{});
+ OOXMLStream::StreamType_t nType(OOXMLStream::UNKNOWN);
+ if (gType == sSettingsType || gType == sSettingsTypeStrict)
+ {
+ nType = OOXMLStream::SETTINGS;
+ aRelDefinition.put(sContentType, sSettingsContentType);
+ }
+ else if (gType == sStylesType || gType == sStylesTypeStrict)
+ {
+ nType = OOXMLStream::STYLES;
+ aRelDefinition.put(sContentType, sStylesContentType);
+ }
+ else if (gType == sWebSettings || gType == sWebSettingsStrict)
+ {
+ nType = OOXMLStream::WEBSETTINGS;
+ aRelDefinition.put(sContentType, sWebsettingsContentType);
+ }
+ else if (gType == sFonttableType || gType == sFonttableTypeStrict)
+ {
+ nType = OOXMLStream::FONTTABLE;
+ aRelDefinition.put(sContentType, sFonttableContentType);
+ }
+ else if (aRelDefinition.getOrDefault(sTargetMode, OUString{}) != "External")
+ {
+ // Some internal relation, but we don't create a DOM for it here yet?
+ SAL_WARN("writerfilter.ooxml", "Unknown type of glossary internal relation: "
+ "Id=\"" + aRelDefinition.getOrDefault<OUString>(sId, {}) + "\" "
+ "Type=\"" + gType + "\" "
+ "Target=\"" + aRelDefinition.getOrDefault<OUString>(sTarget, {}) + "\"");
+ continue;
+ }
+
+ if (nType != OOXMLStream::UNKNOWN)
+ {
+ try
+ {
+ auto gStream = OOXMLDocumentFactory::createStream(pStream, nType);
+ uno::Reference xInputStream = gStream->getDocumentStream();
+ uno::Reference xContext(pStream->getContext());
+ uno::Reference xDomBuilder(xml::dom::DocumentBuilder::create(xContext));
+ uno::Reference xDom = xDomBuilder->parse(xInputStream);
+ aRelDefinition.put(sRelDom, xDom);
+ }
+ catch (uno::Exception const&)
+ {
+ TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "importSubStream: exception while "
+ "parsing stream of Type" << nType);
+ }
+ }
+ aGlossaryDomList.push_back(aRelDefinition.getNamedValues());
}
mxGlossaryDomList = comphelper::containerToSequence(aGlossaryDomList);
}
@@ -797,7 +796,7 @@ uno::Reference<xml::dom::XDocument> OOXMLDocumentImpl::getGlossaryDocDom( )
return mxGlossaryDocDom;
}
-uno::Sequence<uno::Sequence< uno::Any> > OOXMLDocumentImpl::getGlossaryDomList()
+uno::Sequence<uno::Sequence< beans::NamedValue> > OOXMLDocumentImpl::getGlossaryDomList()
{
return mxGlossaryDomList;
}
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
index d7a8a00bd58c..c896d7bf4901 100644
--- a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
+++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx
@@ -44,7 +44,7 @@ class OOXMLDocumentImpl : public OOXMLDocument
css::uno::Reference<css::frame::XModel> mxModel;
css::uno::Reference<css::drawing::XDrawPage> mxDrawPage;
css::uno::Reference<css::xml::dom::XDocument> mxGlossaryDocDom;
- css::uno::Sequence < css::uno::Sequence< css::uno::Any > > mxGlossaryDomList;
+ css::uno::Sequence < css::uno::Sequence< css::beans::NamedValue > > mxGlossaryDomList;
/// Stack of shape contexts, 1 element for VML, 1 element / nesting level for drawingML.
std::stack< rtl::Reference<oox::shape::ShapeContextHandler> > maShapeContexts;
css::uno::Reference<css::xml::dom::XDocument> mxThemeDom;
@@ -141,7 +141,7 @@ public:
virtual css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > getCustomXmlDomList() override;
virtual css::uno::Sequence<css::uno::Reference<css::xml::dom::XDocument> > getCustomXmlDomPropsList() override;
virtual css::uno::Reference<css::xml::dom::XDocument> getGlossaryDocDom() override;
- virtual css::uno::Sequence<css::uno::Sequence< css::uno::Any> > getGlossaryDomList() override;
+ virtual css::uno::Sequence<css::uno::Sequence< css::beans::NamedValue> > getGlossaryDomList() override;
virtual css::uno::Sequence<css::beans::PropertyValue > getEmbeddingsList() override;
void incrementProgress();