1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/document/XExporter.hpp>
26 #include <com/sun/star/document/XFilter.hpp>
27 #include <com/sun/star/document/XImporter.hpp>
28 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
29 #include <com/sun/star/io/WrongFormatException.hpp>
30 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
31 #include <com/sun/star/lang/XInitialization.hpp>
32 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 #include <com/sun/star/xml/sax/SAXParseException.hpp>
34 #include <cppuhelper/exc_hlp.hxx>
35 #include <cppuhelper/supportsservice.hxx>
36 #include <dmapper/DomainMapperFactory.hxx>
37 #include <oox/core/filterdetect.hxx>
38 #include <oox/core/xmlfilterbase.hxx>
39 #include <oox/helper/graphichelper.hxx>
40 #include <oox/ole/olestorage.hxx>
41 #include <oox/ole/vbaproject.hxx>
42 #include <ooxml/OOXMLDocument.hxx>
43 #include <unotools/mediadescriptor.hxx>
44 #include <rtl/ref.hxx>
45 #include <sal/log.hxx>
46 #include <tools/diagnose_ex.h>
48 using namespace ::com::sun::star
;
50 static OUString
lcl_GetExceptionMessageRec(xml::sax::SAXException
const& e
);
52 static OUString
lcl_GetExceptionMessage(xml::sax::SAXException
const& e
)
54 OUString
const thisMessage("SAXParseException: \"" + e
.Message
+ "\"");
55 OUString
const restMessage(lcl_GetExceptionMessageRec(e
));
56 return restMessage
+ "\n" + thisMessage
;
58 static OUString
lcl_GetExceptionMessage(xml::sax::SAXParseException
const& e
)
60 OUString
const thisMessage("SAXParseException: '" + e
.Message
+ "', Stream '" + e
.SystemId
+ "', Line " + OUString::number(e
.LineNumber
)
61 + ", Column " + OUString::number(e
.ColumnNumber
));
62 OUString
const restMessage(lcl_GetExceptionMessageRec(e
));
63 return restMessage
+ "\n" + thisMessage
;
66 static OUString
lcl_GetExceptionMessageRec(xml::sax::SAXException
const& e
)
68 xml::sax::SAXParseException saxpe
;
69 if (e
.WrappedException
>>= saxpe
)
71 return lcl_GetExceptionMessage(saxpe
);
73 xml::sax::SAXException saxe
;
74 if (e
.WrappedException
>>= saxe
)
76 return lcl_GetExceptionMessage(saxe
);
79 if (e
.WrappedException
>>= ue
)
86 /// Common DOCX filter, calls DocxExportFilter via UNO or does the DOCX import.
87 class WriterFilter
: public cppu::WeakImplHelper
92 lang::XInitialization
,
96 uno::Reference
<uno::XComponentContext
> m_xContext
;
97 uno::Reference
<lang::XComponent
> m_xSrcDoc
, m_xDstDoc
;
98 uno::Sequence
<uno::Any
> m_xInitializationArguments
;
101 explicit WriterFilter(uno::Reference
<uno::XComponentContext
> xContext
)
102 : m_xContext(std::move(xContext
))
106 sal_Bool SAL_CALL
filter(const uno::Sequence
<beans::PropertyValue
>& rDescriptor
) override
;
107 void SAL_CALL
cancel() override
;
110 void SAL_CALL
setTargetDocument(const uno::Reference
<lang::XComponent
>& xDoc
) override
;
113 void SAL_CALL
setSourceDocument(const uno::Reference
<lang::XComponent
>& xDoc
) override
;
116 void SAL_CALL
initialize(const uno::Sequence
<uno::Any
>& rArguments
) override
;
119 OUString SAL_CALL
getImplementationName() override
;
120 sal_Bool SAL_CALL
supportsService(const OUString
& rServiceName
) override
;
121 uno::Sequence
<OUString
> SAL_CALL
getSupportedServiceNames() override
;
124 sal_Bool
WriterFilter::filter(const uno::Sequence
< beans::PropertyValue
>& rDescriptor
)
128 uno::Reference
< lang::XMultiServiceFactory
> xMSF(m_xContext
->getServiceManager(), uno::UNO_QUERY_THROW
);
129 uno::Reference
< uno::XInterface
> xIfc
;
132 xIfc
.set(xMSF
->createInstance("com.sun.star.comp.Writer.DocxExport"), uno::UNO_SET_THROW
);
134 catch (uno::RuntimeException
&)
138 catch (uno::Exception
& e
)
140 uno::Any
a(cppu::getCaughtException());
141 throw lang::WrappedTargetRuntimeException("wrapped " + a
.getValueTypeName() + ": " + e
.Message
, uno::Reference
<uno::XInterface
>(), a
);
144 uno::Reference
<lang::XInitialization
> xInit(xIfc
, uno::UNO_QUERY_THROW
);
145 xInit
->initialize(m_xInitializationArguments
);
147 uno::Reference
<document::XExporter
> xExprtr(xIfc
, uno::UNO_QUERY_THROW
);
148 uno::Reference
< document::XFilter
> xFltr(xIfc
, uno::UNO_QUERY_THROW
);
149 xExprtr
->setSourceDocument(m_xSrcDoc
);
150 return xFltr
->filter(rDescriptor
);
154 utl::MediaDescriptor
aMediaDesc(rDescriptor
);
155 bool bRepairStorage
= aMediaDesc
.getUnpackedValueOrDefault("RepairPackage", false);
156 bool bSkipImages
= aMediaDesc
.getUnpackedValueOrDefault("FilterOptions", OUString()) == "SkipImages";
158 uno::Reference
< io::XInputStream
> xInputStream
;
161 // use the oox.core.FilterDetect implementation to extract the decrypted ZIP package
162 rtl::Reference
<::oox::core::FilterDetect
> xDetector(new ::oox::core::FilterDetect(m_xContext
));
163 xInputStream
= xDetector
->extractUnencryptedPackage(aMediaDesc
);
165 catch (uno::Exception
&)
169 if (!xInputStream
.is())
172 writerfilter::Stream::Pointer_t
pStream(
173 writerfilter::dmapper::DomainMapperFactory::createMapper(
174 m_xContext
, xInputStream
, m_xDstDoc
, bRepairStorage
,
175 writerfilter::dmapper::SourceDocumentType::OOXML
, aMediaDesc
));
176 //create the tokenizer and domain mapper
177 writerfilter::ooxml::OOXMLStream::Pointer_t pDocStream
= writerfilter::ooxml::OOXMLDocumentFactory::createStream(m_xContext
, xInputStream
, bRepairStorage
);
178 uno::Reference
<task::XStatusIndicator
> xStatusIndicator
= aMediaDesc
.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_STATUSINDICATOR(), uno::Reference
<task::XStatusIndicator
>());
179 writerfilter::ooxml::OOXMLDocument::Pointer_t
pDocument(writerfilter::ooxml::OOXMLDocumentFactory::createDocument(pDocStream
, xStatusIndicator
, bSkipImages
, rDescriptor
));
181 uno::Reference
<frame::XModel
> xModel(m_xDstDoc
, uno::UNO_QUERY_THROW
);
182 pDocument
->setModel(xModel
);
184 uno::Reference
<drawing::XDrawPageSupplier
> xDrawings
185 (m_xDstDoc
, uno::UNO_QUERY_THROW
);
186 uno::Reference
<drawing::XDrawPage
> xDrawPage
187 (xDrawings
->getDrawPage(), uno::UNO_SET_THROW
);
188 pDocument
->setDrawPage(xDrawPage
);
192 pDocument
->resolve(*pStream
);
194 catch (xml::sax::SAXParseException
const& e
)
196 // note: SfxObjectShell checks for WrongFormatException
197 io::WrongFormatException
wfe(lcl_GetExceptionMessage(e
));
198 throw lang::WrappedTargetRuntimeException("",
199 static_cast<OWeakObject
*>(this), uno::makeAny(wfe
));
201 catch (xml::sax::SAXException
const& e
)
203 // note: SfxObjectShell checks for WrongFormatException
204 io::WrongFormatException
wfe(lcl_GetExceptionMessage(e
));
205 throw lang::WrappedTargetRuntimeException("",
206 static_cast<OWeakObject
*>(this), uno::makeAny(wfe
));
208 catch (uno::RuntimeException
const&)
212 catch (uno::Exception
const&)
214 css::uno::Any anyEx
= cppu::getCaughtException();
215 SAL_WARN("writerfilter", "WriterFilter::filter(): failed with " << exceptionToString(anyEx
));
216 throw lang::WrappedTargetRuntimeException("",
217 static_cast<OWeakObject
*>(this), anyEx
);
220 // Adding some properties to the document's grab bag for interoperability purposes:
221 comphelper::SequenceAsHashMap aGrabBagProperties
;
223 // Adding the saved Theme DOM
224 aGrabBagProperties
["OOXTheme"] <<= pDocument
->getThemeDom();
226 // Adding the saved custom xml DOM
227 aGrabBagProperties
["OOXCustomXml"] <<= pDocument
->getCustomXmlDomList();
228 aGrabBagProperties
["OOXCustomXmlProps"] <<= pDocument
->getCustomXmlDomPropsList();
230 // Adding the saved Glossary Document DOM to the document's grab bag
231 aGrabBagProperties
["OOXGlossary"] <<= pDocument
->getGlossaryDocDom();
232 aGrabBagProperties
["OOXGlossaryDom"] <<= pDocument
->getGlossaryDomList();
234 // Adding the saved embedding document to document's grab bag
235 aGrabBagProperties
["OOXEmbeddings"] <<= pDocument
->getEmbeddingsList();
237 oox::core::XmlFilterBase::putPropertiesToDocumentGrabBag(m_xDstDoc
, aGrabBagProperties
);
239 writerfilter::ooxml::OOXMLStream::Pointer_t
pVBAProjectStream(writerfilter::ooxml::OOXMLDocumentFactory::createStream(pDocStream
, writerfilter::ooxml::OOXMLStream::VBAPROJECT
));
240 oox::StorageRef
xVbaPrjStrg(new ::oox::ole::OleStorage(m_xContext
, pVBAProjectStream
->getDocumentStream(), false));
241 if (xVbaPrjStrg
.get() && xVbaPrjStrg
->isStorage())
243 ::oox::ole::VbaProject
aVbaProject(m_xContext
, xModel
, "Writer");
244 uno::Reference
< frame::XFrame
> xFrame
= aMediaDesc
.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FRAME(), uno::Reference
< frame::XFrame
> ());
246 // if no XFrame try fallback to what we can glean from the Model
249 uno::Reference
< frame::XController
> xController
= xModel
->getCurrentController();
250 xFrame
= xController
.is() ? xController
->getFrame() : nullptr;
253 oox::GraphicHelper
gHelper(m_xContext
, xFrame
, xVbaPrjStrg
);
254 aVbaProject
.importVbaProject(*xVbaPrjStrg
, gHelper
);
256 writerfilter::ooxml::OOXMLStream::Pointer_t
pVBADataStream(writerfilter::ooxml::OOXMLDocumentFactory::createStream(pDocStream
, writerfilter::ooxml::OOXMLStream::VBADATA
));
259 uno::Reference
<io::XInputStream
> xDataStream
= pVBADataStream
->getDocumentStream();
260 if (xDataStream
.is())
261 aVbaProject
.importVbaData(xDataStream
);
272 void WriterFilter::cancel()
276 void WriterFilter::setTargetDocument(const uno::Reference
< lang::XComponent
>& xDoc
)
280 // Set some compatibility options that are valid for all the formats
281 uno::Reference
< lang::XMultiServiceFactory
> xFactory(xDoc
, uno::UNO_QUERY
);
282 uno::Reference
< beans::XPropertySet
> xSettings(xFactory
->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY
);
284 xSettings
->setPropertyValue("AddFrameOffsets", uno::makeAny(true));
285 xSettings
->setPropertyValue("AddVerticalFrameOffsets", uno::makeAny(true));
286 xSettings
->setPropertyValue("UseOldNumbering", uno::makeAny(false));
287 xSettings
->setPropertyValue("IgnoreFirstLineIndentInNumbering", uno::makeAny(false));
288 xSettings
->setPropertyValue("DoNotResetParaAttrsForNumFont", uno::makeAny(false));
289 xSettings
->setPropertyValue("UseFormerLineSpacing", uno::makeAny(false));
290 xSettings
->setPropertyValue("AddParaSpacingToTableCells", uno::makeAny(true));
291 xSettings
->setPropertyValue("UseFormerObjectPositioning", uno::makeAny(false));
292 xSettings
->setPropertyValue("ConsiderTextWrapOnObjPos", uno::makeAny(true));
293 xSettings
->setPropertyValue("UseFormerTextWrapping", uno::makeAny(false));
294 xSettings
->setPropertyValue("TableRowKeep", uno::makeAny(true));
295 xSettings
->setPropertyValue("IgnoreTabsAndBlanksForLineCalculation", uno::makeAny(true));
296 xSettings
->setPropertyValue("InvertBorderSpacing", uno::makeAny(true));
297 xSettings
->setPropertyValue("CollapseEmptyCellPara", uno::makeAny(true));
298 xSettings
->setPropertyValue("TabOverflow", uno::makeAny(true));
299 xSettings
->setPropertyValue("UnbreakableNumberings", uno::makeAny(true));
301 xSettings
->setPropertyValue("FloattableNomargins", uno::makeAny(true));
302 xSettings
->setPropertyValue("ClippedPictures", uno::makeAny(true));
303 xSettings
->setPropertyValue("BackgroundParaOverDrawings", uno::makeAny(true));
304 xSettings
->setPropertyValue("TabOverMargin", uno::makeAny(true));
305 xSettings
->setPropertyValue("TreatSingleColumnBreakAsPageBreak", uno::makeAny(true));
306 xSettings
->setPropertyValue("PropLineSpacingShrinksFirstLine", uno::makeAny(true));
307 xSettings
->setPropertyValue("DoNotCaptureDrawObjsOnPage", uno::makeAny(true));
308 xSettings
->setPropertyValue("DisableOffPagePositioning", uno::makeAny(true));
311 void WriterFilter::setSourceDocument(const uno::Reference
< lang::XComponent
>& xDoc
)
316 void WriterFilter::initialize(const uno::Sequence
< uno::Any
>& rArguments
)
318 m_xInitializationArguments
= rArguments
;
321 OUString
WriterFilter::getImplementationName()
323 return "com.sun.star.comp.Writer.WriterFilter";
327 sal_Bool
WriterFilter::supportsService(const OUString
& rServiceName
)
329 return cppu::supportsService(this, rServiceName
);
333 uno::Sequence
<OUString
> WriterFilter::getSupportedServiceNames()
335 uno::Sequence
<OUString
> aRet
=
337 OUString("com.sun.star.document.ImportFilter"),
338 OUString("com.sun.star.document.ExportFilter")
343 extern "C" SAL_DLLPUBLIC_EXPORT
uno::XInterface
* com_sun_star_comp_Writer_WriterFilter_get_implementation(uno::XComponentContext
* component
, uno::Sequence
<uno::Any
> const& /*rSequence*/)
345 return cppu::acquire(new WriterFilter(component
));
348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */