diff options
Diffstat (limited to 'writerfilter/source/ooxml/OOXMLDocumentImpl.cxx')
-rw-r--r-- | writerfilter/source/ooxml/OOXMLDocumentImpl.cxx | 898 |
1 files changed, 898 insertions, 0 deletions
diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx new file mode 100644 index 000000000..0abd516a4 --- /dev/null +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx @@ -0,0 +1,898 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <comphelper/sequenceashashmap.hxx> + +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/xml/sax/SAXException.hpp> +#include <com/sun/star/xml/dom/DocumentBuilder.hpp> +#include <com/sun/star/graphic/GraphicMapper.hpp> +#include <ooxml/resourceids.hxx> +#include <oox/shape/ShapeFilterBase.hxx> +#include "OOXMLStreamImpl.hxx" +#include "OOXMLDocumentImpl.hxx" +#include "OOXMLBinaryObjectReference.hxx" +#include "OOXMLFastDocumentHandler.hxx" +#include "OOXMLPropertySet.hxx" + +#include <sal/log.hxx> +#include <tools/diagnose_ex.h> +#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> + +#include <iostream> +#include <sfx2/objsh.hxx> + +// this extern variable is declared in OOXMLStreamImpl.hxx +OUString customTarget; +OUString embeddingsTarget; +using namespace ::com::sun::star; +namespace writerfilter::ooxml +{ + +OOXMLDocumentImpl::OOXMLDocumentImpl(OOXMLStream::Pointer_t const & pStream, const uno::Reference<task::XStatusIndicator>& xStatusIndicator, bool bSkipImages, const uno::Sequence<beans::PropertyValue>& rDescriptor) + : mpStream(pStream) + , mxStatusIndicator(xStatusIndicator) + , mnXNoteId(0) + , mbIsSubstream(false) + , mbSkipImages(bSkipImages) + , mnPercentSize(0) + , mnProgressLastPos(0) + , mnProgressCurrentPos(0) + , mnProgressEndPos(0) + , m_rBaseURL(utl::MediaDescriptor(rDescriptor).getUnpackedValueOrDefault("DocumentBaseURL", OUString())) + , maMediaDescriptor(rDescriptor) + , mxGraphicMapper(graphic::GraphicMapper::create(mpStream->getContext())) +{ + pushShapeContext(); +} + +OOXMLDocumentImpl::~OOXMLDocumentImpl() +{ +} + +void OOXMLDocumentImpl::resolveFastSubStream(Stream & rStreamHandler, + OOXMLStream::StreamType_t nType) +{ + OOXMLStream::Pointer_t pStream; + try + { + pStream = OOXMLDocumentFactory::createStream(mpStream, nType); + } + catch (uno::Exception const&) + { + TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "resolveFastSubStream: exception while " + "resolving stream " << nType); + return; + } + OOXMLStream::Pointer_t savedStream = mpStream; + mpStream = pStream; + + uno::Reference<xml::sax::XFastParser> xParser(mpStream->getFastParser()); + + if (xParser.is()) + { + uno::Reference<uno::XComponentContext> xContext(mpStream->getContext()); + rtl::Reference<OOXMLFastDocumentHandler> pDocHandler = + new OOXMLFastDocumentHandler(xContext, &rStreamHandler, this, mnXNoteId); + + uno::Reference<xml::sax::XFastTokenHandler> xTokenHandler(mpStream->getFastTokenHandler()); + + xParser->setFastDocumentHandler(pDocHandler); + xParser->setTokenHandler(xTokenHandler); + + uno::Reference<io::XInputStream> xInputStream = mpStream->getDocumentStream(); + + if (xInputStream.is()) + { + struct xml::sax::InputSource oInputSource; + oInputSource.aInputStream = xInputStream; + xParser->parseStream(oInputSource); + + xInputStream->closeInput(); + } + } + + mpStream = savedStream; +} + +void OOXMLDocumentImpl::resolveFastSubStreamWithId(Stream & rStream, + const writerfilter::Reference<Stream>::Pointer_t& pStream, + sal_uInt32 nId) +{ + rStream.substream(nId, pStream); +} + +uno::Reference<xml::dom::XDocument> OOXMLDocumentImpl::importSubStream(OOXMLStream::StreamType_t nType) +{ + uno::Reference<xml::dom::XDocument> xRet; + + OOXMLStream::Pointer_t pStream; + try + { + pStream = OOXMLDocumentFactory::createStream(mpStream, nType); + } + catch (uno::Exception const&) + { + TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "importSubStream: exception while " + "importing stream " << nType); + return xRet; + } + + uno::Reference<io::XInputStream> xInputStream = pStream->getDocumentStream(); + if (xInputStream.is()) + { + try + { + uno::Reference<uno::XComponentContext> xContext(mpStream->getContext()); + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(xml::dom::DocumentBuilder::create(xContext)); + xRet = xDomBuilder->parse(xInputStream); + } + catch (uno::Exception const&) + { + TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "importSubStream: exception while " + "parsing stream " << nType); + return xRet; + } + } + + if (OOXMLStream::CUSTOMXML == nType) + { + importSubStreamRelations(pStream, OOXMLStream::CUSTOMXMLPROPS); + } + else if (OOXMLStream::CHARTS == nType) + { + importSubStreamRelations(pStream, OOXMLStream::EMBEDDINGS); + } + + return xRet; +} + + +void OOXMLDocumentImpl::importSubStreamRelations(const OOXMLStream::Pointer_t& pStream, OOXMLStream::StreamType_t nType) +{ + uno::Reference<xml::dom::XDocument> xRelation; + OOXMLStream::Pointer_t cStream; + try + { + cStream = OOXMLDocumentFactory::createStream(pStream, nType); + } + catch (uno::Exception const&) + { + TOOLS_WARN_EXCEPTION("writerfilter.ooxml", "importSubStreamRelations: exception while " + "importing stream " << nType); + return; + } + + uno::Reference<io::XInputStream> xcpInputStream = cStream->getDocumentStream(); + + if (!xcpInputStream.is()) + return; + + // importing itemprops files for item.xml from customXml. + if (OOXMLStream::CUSTOMXMLPROPS == nType) + { + try + { + uno::Reference<uno::XComponentContext> xcpContext(pStream->getContext()); + uno::Reference<xml::dom::XDocumentBuilder> xDomBuilder(xml::dom::DocumentBuilder::create(xcpContext)); + xRelation = xDomBuilder->parse(xcpInputStream); + } + catch (uno::Exception const&) + { + TOOLS_WARN_EXCEPTION("writerfilter.ooxml", "importSubStream: exception while " + "parsing stream " << nType); + mxCustomXmlProsDom = xRelation; + } + + if(xRelation.is()) + { + mxCustomXmlProsDom = xRelation; + } + } + else if(OOXMLStream::EMBEDDINGS == nType) + { + mxEmbeddings = xcpInputStream; + } + else if(OOXMLStream::CHARTS == nType) + { + importSubStreamRelations(cStream, OOXMLStream::EMBEDDINGS); + } + + +} + +void OOXMLDocumentImpl::setXNoteId(const sal_Int32 nId) +{ + mnXNoteId = nId; +} + +sal_Int32 OOXMLDocumentImpl::getXNoteId() const +{ + return mnXNoteId; +} + +const OUString & OOXMLDocumentImpl::getTarget() const +{ + return mpStream->getTarget(); +} + +writerfilter::Reference<Stream>::Pointer_t +OOXMLDocumentImpl::getSubStream(const OUString & rId) +{ + OOXMLStream::Pointer_t pStream + (OOXMLDocumentFactory::createStream(mpStream, 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, maMediaDescriptor)); + pTemp->setModel(mxModel); + pTemp->setDrawPage(mxDrawPage); + pTemp->mbIsSubstream = true; + return pRet; +} + +writerfilter::Reference<Stream>::Pointer_t +OOXMLDocumentImpl::getXNoteStream(OOXMLStream::StreamType_t nType, const sal_Int32 nId) +{ + 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, maMediaDescriptor); + pDocument->setXNoteId(nId); + pDocument->setModel(getModel()); + pDocument->setDrawPage(getDrawPage()); + + return writerfilter::Reference<Stream>::Pointer_t(pDocument); +} + +void OOXMLDocumentImpl::resolveFootnote(Stream & rStream, + Id aType, + const sal_Int32 nNoteId) +{ + if (!mpXFootnoteStream) + mpXFootnoteStream = getXNoteStream(OOXMLStream::FOOTNOTES, nNoteId); + + Id nId; + switch (aType) + { + case NS_ooxml::LN_Value_doc_ST_FtnEdn_separator: + case NS_ooxml::LN_Value_doc_ST_FtnEdn_continuationSeparator: + nId = aType; + break; + default: + nId = NS_ooxml::LN_footnote; + break; + } + + resolveFastSubStreamWithId(rStream, mpXFootnoteStream, nId); +} + +void OOXMLDocumentImpl::resolveEndnote(Stream & rStream, + Id aType, + const sal_Int32 nNoteId) +{ + if (!mpXEndnoteStream) + mpXEndnoteStream = getXNoteStream(OOXMLStream::ENDNOTES, nNoteId); + + Id nId; + switch (aType) + { + case NS_ooxml::LN_Value_doc_ST_FtnEdn_separator: + case NS_ooxml::LN_Value_doc_ST_FtnEdn_continuationSeparator: + nId = aType; + break; + default: + nId = NS_ooxml::LN_endnote; + break; + } + + resolveFastSubStreamWithId(rStream, mpXEndnoteStream, nId); +} + +void OOXMLDocumentImpl::resolveCommentsExtendedStream(Stream& rStream) +{ + resolveFastSubStream(rStream, OOXMLStream::COMMENTS_EXTENDED); +} + +void OOXMLDocumentImpl::resolveComment(Stream & rStream, + const sal_Int32 nId) +{ + if (!mbCommentsExtendedResolved) + { + resolveCommentsExtendedStream(rStream); + mbCommentsExtendedResolved = true; + } + + writerfilter::Reference<Stream>::Pointer_t pStream = + getXNoteStream(OOXMLStream::COMMENTS, nId); + + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_annotation); +} + +OOXMLPropertySet * OOXMLDocumentImpl::getPicturePropSet +(const OUString & rId) +{ + OOXMLStream::Pointer_t pStream + (OOXMLDocumentFactory::createStream(mpStream, rId)); + + writerfilter::Reference<BinaryObj>::Pointer_t pPicture + (new OOXMLBinaryObjectReference(pStream)); + + OOXMLValue::Pointer_t pPayloadValue(new OOXMLBinaryValue(pPicture)); + + OOXMLPropertySet::Pointer_t pBlipSet(new OOXMLPropertySet); + + pBlipSet->add(NS_ooxml::LN_payload, pPayloadValue, OOXMLProperty::ATTRIBUTE); + + OOXMLValue::Pointer_t pBlipValue(new OOXMLPropertySetValue(pBlipSet)); + + OOXMLPropertySet * pProps = new OOXMLPropertySet; + + pProps->add(NS_ooxml::LN_blip, pBlipValue, OOXMLProperty::ATTRIBUTE); + + return pProps; +} + +void OOXMLDocumentImpl::resolvePicture(Stream & rStream, + const OUString & rId) +{ + OOXMLPropertySet::Pointer_t pProps(getPicturePropSet(rId)); + + rStream.props(pProps.get()); +} + +OUString OOXMLDocumentImpl::getTargetForId(const OUString & rId) +{ + return mpStream->getTargetForId(rId); +} + +void OOXMLDocumentImpl::resolveHeader(Stream & rStream, + const sal_Int32 type, + const OUString & rId) +{ + writerfilter::Reference<Stream>::Pointer_t pStream = + getSubStream(rId); + switch (type) + { + case NS_ooxml::LN_Value_ST_HdrFtr_even: + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_headerl); + break; + case NS_ooxml::LN_Value_ST_HdrFtr_default: // here we assume that default is right, but not necessarily true :-( + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_headerr); + break; + case NS_ooxml::LN_Value_ST_HdrFtr_first: + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_headerf); + break; + default: + break; + } +} + +void OOXMLDocumentImpl::resolveFooter(Stream & rStream, + const sal_Int32 type, + const OUString & rId) +{ + writerfilter::Reference<Stream>::Pointer_t pStream = + getSubStream(rId); + + switch (type) + { + case NS_ooxml::LN_Value_ST_HdrFtr_even: + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_footerl); + break; + case NS_ooxml::LN_Value_ST_HdrFtr_default: // here we assume that default is right, but not necessarily true :-( + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_footerr); + break; + case NS_ooxml::LN_Value_ST_HdrFtr_first: + resolveFastSubStreamWithId(rStream, pStream, NS_ooxml::LN_footerf); + break; + default: + break; + } +} + +namespace { +// Ensures that the indicator is reset after exiting OOXMLDocumentImpl::resolve +class StatusIndicatorGuard{ +public: + explicit StatusIndicatorGuard(css::uno::Reference<css::task::XStatusIndicator> const & xStatusIndicator) + :mxStatusIndicator(xStatusIndicator) + { + } + + ~StatusIndicatorGuard() + { + if (mxStatusIndicator.is()) + mxStatusIndicator->end(); + } + +private: + css::uno::Reference<css::task::XStatusIndicator> mxStatusIndicator; +}; +} + +void OOXMLDocumentImpl::resolve(Stream & rStream) +{ + StatusIndicatorGuard aStatusIndicatorGuard(mxStatusIndicator); + + if (utl::MediaDescriptor(maMediaDescriptor).getUnpackedValueOrDefault("ReadGlossaries", false)) + { + resolveFastSubStream(rStream, OOXMLStream::GLOSSARY); + return; + } + + uno::Reference<xml::sax::XFastParser> xParser(mpStream->getFastParser()); + + if (mxModel.is()) + { + uno::Reference<document::XDocumentPropertiesSupplier> xDocumentPropertiesSupplier(mxModel, uno::UNO_QUERY); + uno::Reference<document::XDocumentProperties> xDocumentProperties = xDocumentPropertiesSupplier->getDocumentProperties(); + comphelper::SequenceAsHashMap aMap(xDocumentProperties->getDocumentStatistics()); + if (aMap.find("ParagraphCount") != aMap.end()) + { + sal_Int32 nValue; + if (aMap["ParagraphCount"] >>= nValue) + { + if (mxStatusIndicator.is()) + { + // We want to care about the progress if we know the estimated paragraph count and we have given a status indicator as well. + // Set the end position only here, so later it's enough to check if that is non-zero in incrementProgress(). + mnProgressEndPos = nValue; + OUString aDocLoad(SvxResId(RID_SVXSTR_DOC_LOAD)); + mxStatusIndicator->start(aDocLoad, mnProgressEndPos); + mnPercentSize = mnProgressEndPos / 100; + } + } + } + } + + if (!xParser.is()) + return; + + uno::Reference<uno::XComponentContext> xContext(mpStream->getContext()); + + rStream.setDocumentReference(this); + + rtl::Reference<OOXMLFastDocumentHandler> pDocHandler = + new OOXMLFastDocumentHandler(xContext, &rStream, this, mnXNoteId); + pDocHandler->setIsSubstream( mbIsSubstream ); + uno::Reference < xml::sax::XFastTokenHandler > xTokenHandler(mpStream->getFastTokenHandler()); + + resolveFastSubStream(rStream, OOXMLStream::SETTINGS); + mxThemeDom = importSubStream(OOXMLStream::THEME); + resolveFastSubStream(rStream, OOXMLStream::THEME); + mxGlossaryDocDom = importSubStream(OOXMLStream::GLOSSARY); + if (mxGlossaryDocDom.is()) + resolveGlossaryStream(rStream); + + resolveEmbeddingsStream(mpStream); + + // Custom xml's are handled as part of grab bag. + resolveCustomXmlStream(rStream); + + resolveFastSubStream(rStream, OOXMLStream::FONTTABLE); + resolveFastSubStream(rStream, OOXMLStream::STYLES); + resolveFastSubStream(rStream, OOXMLStream::NUMBERING); + + xParser->setFastDocumentHandler( pDocHandler ); + xParser->setTokenHandler( xTokenHandler ); + + xml::sax::InputSource aParserInput; + aParserInput.sSystemId = mpStream->getTarget(); + aParserInput.aInputStream = mpStream->getDocumentStream(); + try + { + xParser->parseStream(aParserInput); + } + catch (xml::sax::SAXException const& rErr) + { + // don't silently swallow these - handlers may not have been executed, + // and the domain mapper is likely in an inconsistent state + // In case user chooses to try to continue loading, don't ask again for this file + SfxObjectShell* rShell = SfxObjectShell::GetShellFromComponent(mxModel); + if (!rShell + || !rShell->IsContinueImportOnFilterExceptions( + OUStringConcatenation("SAXException: " + rErr.Message))) + throw; + } + catch (uno::RuntimeException const&) + { + throw; + } + // note: cannot throw anything other than SAXException out of here? + catch (uno::Exception const&) + { + css::uno::Any anyEx = cppu::getCaughtException(); + SAL_WARN("writerfilter.ooxml", "OOXMLDocumentImpl::resolve(): " << exceptionToString(anyEx)); + throw lang::WrappedTargetRuntimeException("", nullptr, anyEx); + } + catch (...) + { + SAL_WARN("writerfilter.ooxml", + "OOXMLDocumentImpl::resolve(): non-UNO exception"); + } +} + +void OOXMLDocumentImpl::incrementProgress() +{ + mnProgressCurrentPos++; + // 1) If we know the end + // 2) We progressed enough that updating makes sense + // 3) We did not reach the end yet (possible in case the doc stat is misleading) + if (mnProgressEndPos && mnProgressCurrentPos > (mnProgressLastPos + mnPercentSize) && mnProgressLastPos < mnProgressEndPos) + { + mnProgressLastPos = mnProgressCurrentPos; + if (mxStatusIndicator.is()) + mxStatusIndicator->setValue(mnProgressLastPos); + } +} + +void OOXMLDocumentImpl::resolveCustomXmlStream(Stream & rStream) +{ + // Resolving all item[n].xml files from CustomXml folder. + uno::Reference<embed::XRelationshipAccess> xRelationshipAccess; + xRelationshipAccess.set(dynamic_cast<OOXMLStreamImpl&>(*mpStream).accessDocumentStream(), uno::UNO_QUERY); + if (!xRelationshipAccess.is()) + return; + + static const char sCustomType[] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"; + static const char sCustomTypeStrict[] = "http://purl.oclc.org/ooxml/officeDocument/relationships/customXml"; + bool bFound = false; + const uno::Sequence<uno::Sequence< beans::StringPair>> aSeqs = xRelationshipAccess->getAllRelationships(); + std::vector<uno::Reference<xml::dom::XDocument>> aCustomXmlDomList; + std::vector<uno::Reference<xml::dom::XDocument>> aCustomXmlDomPropsList; + for (const uno::Sequence<beans::StringPair>& aSeq : aSeqs) + { + for (const beans::StringPair& aPair : aSeq) + { + // Need to resolve only customxml files from document relationships. + // Skipping other files. + if (aPair.Second == sCustomType || + aPair.Second == sCustomTypeStrict) + bFound = true; + else if (aPair.First == "Target" && bFound) + { + // Adding value to extern variable customTarget. It will be used in ooxmlstreamimpl + // to ensure customxml target is visited in lcl_getTarget. + customTarget = aPair.Second; + } + } + + if (bFound) + { + uno::Reference<xml::dom::XDocument> customXmlTemp = importSubStream(OOXMLStream::CUSTOMXML); + // This will add all item[n].xml with its relationship file i.e itemprops.xml to + // grabbag list. + if (mxCustomXmlProsDom.is() && customXmlTemp.is()) + { + aCustomXmlDomList.push_back(customXmlTemp); + aCustomXmlDomPropsList.push_back(mxCustomXmlProsDom); + resolveFastSubStream(rStream, OOXMLStream::CUSTOMXML); + } + + bFound = false; + } + } + + mxCustomXmlDomList = comphelper::containerToSequence(aCustomXmlDomList); + mxCustomXmlDomPropsList = comphelper::containerToSequence(aCustomXmlDomPropsList); +} + +namespace +{ +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 + { + pStream = OOXMLDocumentFactory::createStream(mpStream, OOXMLStream::GLOSSARY); + } + catch (uno::Exception const&) + { + TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "resolveGlossaryStream: exception while " + "createStream for glossary" << OOXMLStream::GLOSSARY); + return; + } + uno::Reference<embed::XRelationshipAccess> xRelationshipAccess; + xRelationshipAccess.set(dynamic_cast<OOXMLStreamImpl&>(*pStream).accessDocumentStream(), uno::UNO_QUERY); + if (!xRelationshipAccess.is()) + return; + + + const uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs = xRelationshipAccess->getAllRelationships(); + std::vector< uno::Sequence<beans::NamedValue> > aGlossaryDomList; + for (const uno::Sequence< beans::StringPair >& aSeq : aSeqs) + { + 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); +} + +void OOXMLDocumentImpl::resolveEmbeddingsStream(const OOXMLStream::Pointer_t& pStream) +{ + uno::Reference<embed::XRelationshipAccess> xRelationshipAccess; + xRelationshipAccess.set(dynamic_cast<OOXMLStreamImpl&>(*pStream).accessDocumentStream(), uno::UNO_QUERY); + if (xRelationshipAccess.is()) + { + OUString const sChartType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart"); + OUString const sChartTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/chart"); + OUString const sFootersType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer"); + OUString const sFootersTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/footer"); + OUString const sHeaderType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/header"); + OUString const sHeaderTypeStrict("http://purl.oclc.org/ooxml/officeDocument/relationships/header"); + + bool bFound = false; + bool bHeaderFooterFound = false; + OOXMLStream::StreamType_t streamType = OOXMLStream::UNKNOWN; + const uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs = xRelationshipAccess->getAllRelationships(); + for (const uno::Sequence< beans::StringPair >& aSeq : aSeqs) + { + for (const beans::StringPair& aPair : aSeq) + { + if (aPair.Second == sChartType || + aPair.Second == sChartTypeStrict) + { + bFound = true; + } + else if(aPair.Second == sFootersType || + aPair.Second == sFootersTypeStrict) + { + bHeaderFooterFound = true; + streamType = OOXMLStream::FOOTER; + } + else if(aPair.Second == sHeaderType || + aPair.Second == sHeaderTypeStrict) + { + bHeaderFooterFound = true; + streamType = OOXMLStream::HEADER; + } + else if(aPair.First == "Target" && ( bFound || bHeaderFooterFound )) + { + // Adding value to extern variable customTarget. It will be used in ooxmlstreamimpl + // to ensure chart.xml target is visited in lcl_getTarget. + customTarget = aPair.Second; + } + } + if( bFound || bHeaderFooterFound) + { + if(bFound) + { + importSubStreamRelations(pStream, OOXMLStream::CHARTS); + } + if(bHeaderFooterFound) + { + try + { + OOXMLStream::Pointer_t Stream = OOXMLDocumentFactory::createStream(pStream, streamType); + if (Stream) + resolveEmbeddingsStream(Stream); + } + catch (uno::Exception const&) + { + TOOLS_INFO_EXCEPTION("writerfilter.ooxml", "resolveEmbeddingsStream: can't find header/footer whilst " + "resolving stream " << streamType); + return; + } + } + + beans::PropertyValue embeddingsTemp; + // This will add all .xlsx and .bin to grabbag list. + if(bFound && mxEmbeddings.is()) + { + embeddingsTemp.Name = embeddingsTarget; + embeddingsTemp.Value <<= mxEmbeddings; + aEmbeddings.push_back(embeddingsTemp); + mxEmbeddings.clear(); + } + bFound = false; + bHeaderFooterFound = false; + } + } + } + if (!aEmbeddings.empty()) + mxEmbeddingsList = comphelper::containerToSequence(aEmbeddings); +} + +uno::Reference<xml::dom::XDocument> OOXMLDocumentImpl::getGlossaryDocDom( ) +{ + return mxGlossaryDocDom; +} + +uno::Sequence<uno::Sequence< beans::NamedValue> > OOXMLDocumentImpl::getGlossaryDomList() +{ + return mxGlossaryDomList; +} + +uno::Reference<io::XInputStream> OOXMLDocumentImpl::getInputStreamForId(const OUString & rId) +{ + OOXMLStream::Pointer_t pStream(OOXMLDocumentFactory::createStream(mpStream, rId)); + + return pStream->getDocumentStream(); +} + +void OOXMLDocumentImpl::setModel(uno::Reference<frame::XModel> xModel) +{ + mxModel.set(xModel); +} + +uno::Reference<frame::XModel> OOXMLDocumentImpl::getModel() +{ + return mxModel; +} + +void OOXMLDocumentImpl::setDrawPage(uno::Reference<drawing::XDrawPage> xDrawPage) +{ + mxDrawPage.set(xDrawPage); +} + +uno::Reference<drawing::XDrawPage> OOXMLDocumentImpl::getDrawPage() +{ + return mxDrawPage; +} + +const uno::Sequence<beans::PropertyValue>& OOXMLDocumentImpl::getMediaDescriptor() const +{ + return maMediaDescriptor; +} + +void OOXMLDocumentImpl::setShapeContext( rtl::Reference<oox::shape::ShapeContextHandler> xContext ) +{ + if (!maShapeContexts.empty()) + maShapeContexts.top() = xContext; +} + +rtl::Reference<oox::shape::ShapeContextHandler> OOXMLDocumentImpl::getShapeContext( ) +{ + if (!maShapeContexts.empty()) + return maShapeContexts.top(); + else + return {}; +} + +void OOXMLDocumentImpl::pushShapeContext() +{ + maShapeContexts.push({}); +} + +void OOXMLDocumentImpl::popShapeContext() +{ + if (!maShapeContexts.empty()) + maShapeContexts.pop(); +} + +uno::Reference<xml::dom::XDocument> OOXMLDocumentImpl::getThemeDom( ) +{ + return mxThemeDom; +} + +uno::Sequence<uno::Reference<xml::dom::XDocument> > OOXMLDocumentImpl::getCustomXmlDomList( ) +{ + return mxCustomXmlDomList; +} + +uno::Sequence<uno::Reference<xml::dom::XDocument> > OOXMLDocumentImpl::getCustomXmlDomPropsList( ) +{ + return mxCustomXmlDomPropsList; +} + +uno::Sequence<beans::PropertyValue > OOXMLDocumentImpl::getEmbeddingsList( ) +{ + return mxEmbeddingsList; +} + +const rtl::Reference<oox::shape::ShapeFilterBase>& OOXMLDocumentImpl::getShapeFilterBase() +{ + if (!mxShapeFilterBase) + mxShapeFilterBase = new oox::shape::ShapeFilterBase(mpStream->getContext()); + return mxShapeFilterBase; +} + +OOXMLDocument * +OOXMLDocumentFactory::createDocument +(const OOXMLStream::Pointer_t& pStream, + const uno::Reference<task::XStatusIndicator>& xStatusIndicator, + bool mbSkipImages, const uno::Sequence<beans::PropertyValue>& rDescriptor) +{ + return new OOXMLDocumentImpl(pStream, xStatusIndicator, mbSkipImages, rDescriptor); +} + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |