LCOV - code coverage report
Current view: top level - writerfilter/source/filter - WriterFilter.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 119 152 78.3 %
Date: 2015-06-13 12:38:46 Functions: 15 18 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #ifdef DEBUG_WRITERFILTER
      21             : #include <iostream>
      22             : #endif
      23             : 
      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/lang/WrappedTargetRuntimeException.hpp>
      30             : #include <com/sun/star/lang/XInitialization.hpp>
      31             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      32             : #include <com/sun/star/xml/sax/SAXParseException.hpp>
      33             : #include <cppuhelper/exc_hlp.hxx>
      34             : #include <cppuhelper/implbase.hxx>
      35             : #include <cppuhelper/supportsservice.hxx>
      36             : #include <dmapper/DomainMapperFactory.hxx>
      37             : #include <oox/core/filterdetect.hxx>
      38             : #include <oox/helper/graphichelper.hxx>
      39             : #include <oox/ole/olestorage.hxx>
      40             : #include <oox/ole/vbaproject.hxx>
      41             : #include <ooxml/OOXMLDocument.hxx>
      42             : #include <unotools/mediadescriptor.hxx>
      43             : 
      44             : using namespace ::com::sun::star;
      45             : 
      46             : static OUString lcl_GetExceptionMessageRec(xml::sax::SAXException const& e);
      47             : 
      48           0 : static OUString lcl_GetExceptionMessage(xml::sax::SAXException const& e)
      49             : {
      50           0 :     OUString const thisMessage("SAXParseException: \"" + e.Message + "\"");
      51           0 :     OUString const restMessage(lcl_GetExceptionMessageRec(e));
      52           0 :     return restMessage + "\n" + thisMessage;
      53             : }
      54           1 : static OUString lcl_GetExceptionMessage(xml::sax::SAXParseException const& e)
      55             : {
      56           2 :     OUString const thisMessage("SAXParseException: '" + e.Message + "', Stream '" + e.SystemId + "', Line " + OUString::number(e.LineNumber)
      57           3 :                                + ", Column " + OUString::number(e.ColumnNumber));
      58           2 :     OUString const restMessage(lcl_GetExceptionMessageRec(e));
      59           2 :     return restMessage + "\n" + thisMessage;
      60             : }
      61             : 
      62           1 : static OUString lcl_GetExceptionMessageRec(xml::sax::SAXException const& e)
      63             : {
      64           1 :     xml::sax::SAXParseException saxpe;
      65           1 :     if (e.WrappedException >>= saxpe)
      66             :     {
      67           0 :         return lcl_GetExceptionMessage(saxpe);
      68             :     }
      69           2 :     xml::sax::SAXException saxe;
      70           1 :     if (e.WrappedException >>= saxe)
      71             :     {
      72           0 :         return lcl_GetExceptionMessage(saxe);
      73             :     }
      74           2 :     uno::Exception ue;
      75           1 :     if (e.WrappedException >>= ue)
      76             :     {
      77           0 :         return ue.Message;
      78             :     }
      79           2 :     return OUString();
      80             : }
      81             : 
      82             : /// Common DOCX filter, calls DocxExportFilter via UNO or does the DOCX import.
      83             : class WriterFilter : public cppu::WeakImplHelper
      84             :     <
      85             :     document::XFilter,
      86             :     document::XImporter,
      87             :     document::XExporter,
      88             :     lang::XInitialization,
      89             :     lang::XServiceInfo
      90             :     >
      91             : {
      92             : 
      93             : protected:
      94             :     uno::Reference<uno::XComponentContext> m_xContext;
      95             :     uno::Reference<lang::XComponent> m_xSrcDoc, m_xDstDoc;
      96             : 
      97             : public:
      98        2007 :     explicit WriterFilter(const uno::Reference<uno::XComponentContext>& rxContext)
      99        2007 :         : m_xContext(rxContext)
     100        2007 :     {}
     101        4014 :     virtual ~WriterFilter() {}
     102             : 
     103             :     // XFilter
     104             :     virtual sal_Bool SAL_CALL filter(const uno::Sequence<beans::PropertyValue>& rDescriptor) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     105             :     virtual void SAL_CALL cancel() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     106             : 
     107             :     // XImporter
     108             :     virtual void SAL_CALL setTargetDocument(const uno::Reference<lang::XComponent>& xDoc) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
     109             : 
     110             :     // XExporter
     111             :     virtual void SAL_CALL setSourceDocument(const uno::Reference<lang::XComponent>& xDoc) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception) SAL_OVERRIDE;
     112             : 
     113             :     // XInitialization
     114             :     virtual void SAL_CALL initialize(const uno::Sequence<uno::Any>& rArguments) throw (uno::Exception, uno::RuntimeException, std::exception) SAL_OVERRIDE;
     115             : 
     116             :     // XServiceInfo
     117             :     virtual OUString SAL_CALL getImplementationName() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     118             :     virtual sal_Bool SAL_CALL supportsService(const OUString& rServiceName) throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     119             :     virtual uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE;
     120             : 
     121             : private:
     122             :     void putPropertiesToDocumentGrabBag(const comphelper::SequenceAsHashMap& rProperties);
     123             : 
     124             : };
     125             : 
     126        2006 : sal_Bool WriterFilter::filter(const uno::Sequence< beans::PropertyValue >& aDescriptor) throw (uno::RuntimeException, std::exception)
     127             : {
     128        2006 :     if (m_xSrcDoc.is())
     129             :     {
     130         482 :         uno::Reference< lang::XMultiServiceFactory > xMSF(m_xContext->getServiceManager(), uno::UNO_QUERY_THROW);
     131         964 :         uno::Reference< uno::XInterface > xIfc;
     132             :         try
     133             :         {
     134         482 :             xIfc.set(xMSF->createInstance("com.sun.star.comp.Writer.DocxExport"), uno::UNO_QUERY_THROW);
     135             :         }
     136           0 :         catch (uno::RuntimeException&)
     137             :         {
     138           0 :             throw;
     139             :         }
     140           0 :         catch (uno::Exception& e)
     141             :         {
     142           0 :             uno::Any a(cppu::getCaughtException());
     143           0 :             throw lang::WrappedTargetRuntimeException("wrapped " + a.getValueTypeName() + ": " + e.Message, uno::Reference<uno::XInterface>(), a);
     144             :         }
     145         964 :         uno::Reference< document::XExporter > xExprtr(xIfc, uno::UNO_QUERY_THROW);
     146         964 :         uno::Reference< document::XFilter > xFltr(xIfc, uno::UNO_QUERY_THROW);
     147         482 :         if (!xExprtr.is() || !xFltr.is())
     148           0 :             return sal_False;
     149         482 :         xExprtr->setSourceDocument(m_xSrcDoc);
     150         964 :         return xFltr->filter(aDescriptor);
     151             :     }
     152        1524 :     else if (m_xDstDoc.is())
     153             :     {
     154        1524 :         utl::MediaDescriptor aMediaDesc(aDescriptor);
     155        1524 :         bool bRepairStorage = aMediaDesc.getUnpackedValueOrDefault("RepairPackage", false);
     156        1524 :         bool bSkipImages = aMediaDesc.getUnpackedValueOrDefault("FilterOptions", OUString("")) == "SkipImages";
     157             : 
     158        3048 :         uno::Reference< io::XInputStream > xInputStream;
     159             :         try
     160             :         {
     161             :             // use the oox.core.FilterDetect implementation to extract the decrypted ZIP package
     162        1524 :             ::oox::core::FilterDetect aDetector(m_xContext);
     163        1524 :             xInputStream = aDetector.extractUnencryptedPackage(aMediaDesc);
     164             :         }
     165           0 :         catch (uno::Exception&)
     166             :         {
     167             :         }
     168             : 
     169        1524 :         if (!xInputStream.is())
     170           0 :             return sal_False;
     171             : 
     172        1524 :         writerfilter::dmapper::SourceDocumentType eType = writerfilter::dmapper::SourceDocumentType::OOXML;
     173             :         writerfilter::Stream::Pointer_t pStream(
     174        3048 :             writerfilter::dmapper::DomainMapperFactory::createMapper(m_xContext, xInputStream, m_xDstDoc, bRepairStorage, eType, uno::Reference<text::XTextRange>(), aMediaDesc));
     175             :         //create the tokenizer and domain mapper
     176        3048 :         writerfilter::ooxml::OOXMLStream::Pointer_t pDocStream = writerfilter::ooxml::OOXMLDocumentFactory::createStream(m_xContext, xInputStream, bRepairStorage);
     177        3048 :         uno::Reference<task::XStatusIndicator> xStatusIndicator = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_STATUSINDICATOR(), uno::Reference<task::XStatusIndicator>());
     178        3048 :         writerfilter::ooxml::OOXMLDocument::Pointer_t pDocument(writerfilter::ooxml::OOXMLDocumentFactory::createDocument(pDocStream, xStatusIndicator, bSkipImages));
     179             : 
     180        3048 :         uno::Reference<frame::XModel> xModel(m_xDstDoc, uno::UNO_QUERY_THROW);
     181        1524 :         pDocument->setModel(xModel);
     182             : 
     183             :         uno::Reference<drawing::XDrawPageSupplier> xDrawings
     184        3048 :         (m_xDstDoc, uno::UNO_QUERY_THROW);
     185             :         uno::Reference<drawing::XDrawPage> xDrawPage
     186        3048 :         (xDrawings->getDrawPage(), uno::UNO_SET_THROW);
     187        1524 :         pDocument->setDrawPage(xDrawPage);
     188             : 
     189             :         try
     190             :         {
     191        1524 :             pDocument->resolve(*pStream);
     192             :         }
     193           2 :         catch (xml::sax::SAXParseException const& e)
     194             :         {
     195             :             // note: SfxObjectShell checks for WrongFormatException
     196           1 :             io::WrongFormatException wfe(lcl_GetExceptionMessage(e));
     197             :             throw lang::WrappedTargetRuntimeException("",
     198           1 :                     static_cast<OWeakObject*>(this), uno::makeAny(wfe));
     199             :         }
     200           0 :         catch (xml::sax::SAXException const& e)
     201             :         {
     202             :             // note: SfxObjectShell checks for WrongFormatException
     203           0 :             io::WrongFormatException wfe(lcl_GetExceptionMessage(e));
     204             :             throw lang::WrappedTargetRuntimeException("",
     205           0 :                     static_cast<OWeakObject*>(this), uno::makeAny(wfe));
     206             :         }
     207           0 :         catch (uno::RuntimeException const&)
     208             :         {
     209           0 :             throw;
     210             :         }
     211           2 :         catch (uno::Exception const& e)
     212             :         {
     213             :             SAL_WARN("writerfilter", "WriterFilter::filter(): "
     214             :                      "failed with exception " << e.Message);
     215             :             throw lang::WrappedTargetRuntimeException("",
     216           1 :                     static_cast<OWeakObject*>(this), uno::makeAny(e));
     217             :         }
     218             : 
     219             :         // Adding some properties to the document's grab bag for interoperability purposes:
     220        3044 :         comphelper::SequenceAsHashMap aGrabBagProperties;
     221             : 
     222             :         // Adding the saved Theme DOM
     223        1522 :         aGrabBagProperties["OOXTheme"] = uno::makeAny(pDocument->getThemeDom());
     224             : 
     225             :         // Adding the saved custom xml DOM
     226        1522 :         aGrabBagProperties["OOXCustomXml"] = uno::makeAny(pDocument->getCustomXmlDomList());
     227        1522 :         aGrabBagProperties["OOXCustomXmlProps"] = uno::makeAny(pDocument->getCustomXmlDomPropsList());
     228             : 
     229             :         // Adding the saved ActiveX DOM
     230        1522 :         aGrabBagProperties["OOXActiveX"] = uno::makeAny(pDocument->getActiveXDomList());
     231        1522 :         aGrabBagProperties["OOXActiveXBin"] = uno::makeAny(pDocument->getActiveXBinList());
     232             : 
     233             :         // Adding the saved Glossary Documnet DOM to the document's grab bag
     234        1522 :         aGrabBagProperties["OOXGlossary"] = uno::makeAny(pDocument->getGlossaryDocDom());
     235        1522 :         aGrabBagProperties["OOXGlossaryDom"] = uno::makeAny(pDocument->getGlossaryDomList());
     236             : 
     237             :         // Adding the saved embedding document to document's grab bag
     238        1522 :         aGrabBagProperties["OOXEmbeddings"] = uno::makeAny(pDocument->getEmbeddingsList());
     239             : 
     240        1522 :         putPropertiesToDocumentGrabBag(aGrabBagProperties);
     241             : 
     242        3044 :         writerfilter::ooxml::OOXMLStream::Pointer_t  pVBAProjectStream(writerfilter::ooxml::OOXMLDocumentFactory::createStream(pDocStream, writerfilter::ooxml::OOXMLStream::VBAPROJECT));
     243        3044 :         oox::StorageRef xVbaPrjStrg(new ::oox::ole::OleStorage(m_xContext, pVBAProjectStream->getDocumentStream(), false));
     244        1522 :         if (xVbaPrjStrg.get() && xVbaPrjStrg->isStorage())
     245             :         {
     246           0 :             ::oox::ole::VbaProject aVbaProject(m_xContext, xModel, "Writer");
     247           0 :             uno::Reference< frame::XFrame > xFrame = aMediaDesc.getUnpackedValueOrDefault(utl::MediaDescriptor::PROP_FRAME(), uno::Reference< frame::XFrame > ());
     248             : 
     249             :             // if no XFrame try fallback to what we can glean from the Model
     250           0 :             if (!xFrame.is())
     251             :             {
     252           0 :                 uno::Reference< frame::XController > xController =  xModel->getCurrentController();
     253           0 :                 xFrame =  xController.is() ? xController->getFrame() : nullptr;
     254             :             }
     255             : 
     256           0 :             oox::GraphicHelper gHelper(m_xContext, xFrame, xVbaPrjStrg);
     257           0 :             aVbaProject.importVbaProject(*xVbaPrjStrg, gHelper);
     258             :         }
     259             : 
     260             :         // Document signature.
     261        3044 :         writerfilter::ooxml::OOXMLStream::Pointer_t pSignatureStream;
     262        1522 :         pSignatureStream = writerfilter::ooxml::OOXMLDocumentFactory::createStream(m_xContext, xInputStream, bRepairStorage, writerfilter::ooxml::OOXMLStream::SIGNATURE);
     263        1522 :         if (pSignatureStream->getDocumentStream().is())
     264             :         {
     265             :             // TODO found, handle it.
     266             :         }
     267             : 
     268        1522 :         pStream.reset();
     269             : 
     270        3046 :         return sal_True;
     271             :     }
     272           0 :     return sal_False;
     273             : }
     274             : 
     275             : 
     276           0 : void WriterFilter::cancel() throw (uno::RuntimeException, std::exception)
     277             : {
     278           0 : }
     279             : 
     280        1524 : void WriterFilter::setTargetDocument(const uno::Reference< lang::XComponent >& xDoc) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     281             : {
     282        1524 :     m_xDstDoc = xDoc;
     283             : 
     284             :     // Set some compatibility options that are valid for all the formats
     285        1524 :     uno::Reference< lang::XMultiServiceFactory > xFactory(xDoc, uno::UNO_QUERY);
     286        3048 :     uno::Reference< beans::XPropertySet > xSettings(xFactory->createInstance("com.sun.star.document.Settings"), uno::UNO_QUERY);
     287             : 
     288        1524 :     xSettings->setPropertyValue("AddFrameOffsets", uno::makeAny(sal_True));
     289        1524 :     xSettings->setPropertyValue("UseOldNumbering", uno::makeAny(sal_False));
     290        1524 :     xSettings->setPropertyValue("IgnoreFirstLineIndentInNumbering", uno::makeAny(sal_False));
     291        1524 :     xSettings->setPropertyValue("DoNotResetParaAttrsForNumFont", uno::makeAny(sal_False));
     292        1524 :     xSettings->setPropertyValue("UseFormerLineSpacing", uno::makeAny(sal_False));
     293        1524 :     xSettings->setPropertyValue("AddParaSpacingToTableCells", uno::makeAny(sal_True));
     294        1524 :     xSettings->setPropertyValue("UseFormerObjectPositioning", uno::makeAny(sal_False));
     295        1524 :     xSettings->setPropertyValue("ConsiderTextWrapOnObjPos", uno::makeAny(sal_True));
     296        1524 :     xSettings->setPropertyValue("UseFormerTextWrapping", uno::makeAny(sal_False));
     297        1524 :     xSettings->setPropertyValue("TableRowKeep", uno::makeAny(sal_True));
     298        1524 :     xSettings->setPropertyValue("IgnoreTabsAndBlanksForLineCalculation", uno::makeAny(sal_True));
     299        1524 :     xSettings->setPropertyValue("InvertBorderSpacing", uno::makeAny(sal_True));
     300        1524 :     xSettings->setPropertyValue("CollapseEmptyCellPara", uno::makeAny(sal_True));
     301        1524 :     xSettings->setPropertyValue("TabOverflow", uno::makeAny(sal_True));
     302        1524 :     xSettings->setPropertyValue("UnbreakableNumberings", uno::makeAny(sal_True));
     303             : 
     304        1524 :     xSettings->setPropertyValue("FloattableNomargins", uno::makeAny(sal_True));
     305        1524 :     xSettings->setPropertyValue("ClippedPictures", uno::makeAny(sal_True));
     306        1524 :     xSettings->setPropertyValue("BackgroundParaOverDrawings", uno::makeAny(sal_True));
     307        1524 :     xSettings->setPropertyValue("TabOverMargin", uno::makeAny(sal_True));
     308        3048 :     xSettings->setPropertyValue("PropLineSpacingShrinksFirstLine", uno::makeAny(sal_True));
     309        1524 : }
     310             : 
     311         482 : void WriterFilter::setSourceDocument(const uno::Reference< lang::XComponent >& xDoc) throw (lang::IllegalArgumentException, uno::RuntimeException, std::exception)
     312             : {
     313         482 :     m_xSrcDoc = xDoc;
     314         482 : }
     315             : 
     316        2001 : void WriterFilter::initialize(const uno::Sequence< uno::Any >& /*rArguments*/) throw (uno::Exception, uno::RuntimeException, std::exception)
     317             : {
     318        2001 : }
     319             : 
     320           1 : OUString WriterFilter::getImplementationName() throw (uno::RuntimeException, std::exception)
     321             : {
     322           1 :     return OUString("com.sun.star.comp.Writer.WriterFilter");
     323             : }
     324             : 
     325             : 
     326           0 : sal_Bool WriterFilter::supportsService(const OUString& rServiceName) throw (uno::RuntimeException, std::exception)
     327             : {
     328           0 :     return cppu::supportsService(this, rServiceName);
     329             : }
     330             : 
     331             : 
     332           1 : uno::Sequence<OUString> WriterFilter::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
     333             : {
     334             :     uno::Sequence<OUString> aRet =
     335             :     {
     336             :         OUString("com.sun.star.document.ImportFilter"),
     337             :         OUString("com.sun.star.document.ExportFilter")
     338           1 :     };
     339           1 :     return aRet;
     340             : }
     341             : 
     342        1522 : void WriterFilter::putPropertiesToDocumentGrabBag(const comphelper::SequenceAsHashMap& rProperties)
     343             : {
     344             :     try
     345             :     {
     346        1522 :         uno::Reference<beans::XPropertySet> xDocProps(m_xDstDoc, uno::UNO_QUERY);
     347        1522 :         if (xDocProps.is())
     348             :         {
     349        1522 :             uno::Reference<beans::XPropertySetInfo> xPropsInfo = xDocProps->getPropertySetInfo();
     350             : 
     351        3044 :             const OUString aGrabBagPropName = "InteropGrabBag";
     352        1522 :             if (xPropsInfo.is() && xPropsInfo->hasPropertyByName(aGrabBagPropName))
     353             :             {
     354             :                 // get existing grab bag
     355        1522 :                 comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
     356             : 
     357             :                 // put the new items
     358        1522 :                 aGrabBag.update(rProperties);
     359             : 
     360             :                 // put it back to the document
     361        1522 :                 xDocProps->setPropertyValue(aGrabBagPropName, uno::Any(aGrabBag.getAsConstPropertyValueList()));
     362        1522 :             }
     363        1522 :         }
     364             :     }
     365           0 :     catch (const uno::Exception&)
     366             :     {
     367             :         SAL_WARN("writerfilter","Failed to save documents grab bag");
     368             :     }
     369        1522 : }
     370             : 
     371        2007 : extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* SAL_CALL com_sun_star_comp_Writer_WriterFilter_get_implementation(uno::XComponentContext* component, uno::Sequence<uno::Any> const&)
     372             : {
     373        2007 :     return cppu::acquire(new WriterFilter(component));
     374          72 : }
     375             : 
     376             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11