include/oox/core/xmlfilterbase.hxx          |    5 
 oox/source/core/xmlfilterbase.cxx           |  202 ++++++++++++++++++++++++++++
 writerfilter/source/filter/WriterFilter.cxx |   36 ----
 3 files changed, 209 insertions(+), 34 deletions(-)

New commits:
commit 335a2b80fa900848a8b60d8fd5db6656bc30a95a
Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk>
Date:   Tue Feb 6 17:49:23 2018 -0500

    oox: preserve custom oox fragments and packages
    
    Change-Id: Ic4c75d136601a9b7d772aab577c9fbebc7391eaf
    Reviewed-on: https://gerrit.libreoffice.org/49236
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Ashod Nakashian <ashnak...@gmail.com>

diff --git a/include/oox/core/xmlfilterbase.hxx 
b/include/oox/core/xmlfilterbase.hxx
index 7621a0081a53..51e6e496ea6a 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -259,6 +259,9 @@ private:
     virtual StorageRef  implCreateStorage(
                             const css::uno::Reference< css::io::XStream >& 
rxOutStream ) const override;
 
+    void importCustomFragments(css::uno::Reference<css::embed::XStorage>& 
xDocumentStorage);
+    void exportCustomFragments();
+
 private:
     ::std::unique_ptr< XmlFilterBaseImpl > mxImpl;
     sal_Int32 mnRelId;
diff --git a/oox/source/core/xmlfilterbase.cxx 
b/oox/source/core/xmlfilterbase.cxx
index 15f253c734c7..d97aeab59a89 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -29,6 +29,9 @@
 #include <com/sun/star/xml/sax/InputSource.hpp>
 #include <com/sun/star/xml/sax/XFastParser.hpp>
 #include <com/sun/star/xml/sax/XFastSAXSerializable.hpp>
+#include <com/sun/star/xml/dom/XDocument.hpp>
+#include <com/sun/star/xml/sax/XSAXSerializable.hpp>
+#include <com/sun/star/xml/sax/Writer.hpp>
 #include <com/sun/star/document/XDocumentProperties.hpp>
 #include <o3tl/any.hxx>
 #include <unotools/mediadescriptor.hxx>
@@ -48,6 +51,7 @@
 #include <oox/helper/zipstorage.hxx>
 #include <oox/ole/olestorage.hxx>
 #include <oox/token/namespaces.hxx>
+#include <oox/token/relationship.hxx>
 #include <oox/token/properties.hxx>
 #include <oox/token/tokens.hxx>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
@@ -57,6 +61,7 @@
 #include <comphelper/processfactory.hxx>
 #include <oox/core/filterdetect.hxx>
 #include <comphelper/storagehelper.hxx>
+#include <comphelper/sequence.hxx>
 
 #include <oox/crypto/DocumentEncryption.hxx>
 #include <tools/date.hxx>
@@ -64,6 +69,7 @@
 #include <com/sun/star/util/Duration.hpp>
 #include <sax/tools/converter.hxx>
 #include <oox/token/namespacemap.hxx>
+#include <editeng/unoprnms.hxx>
 
 using ::com::sun::star::xml::dom::DocumentBuilder;
 using ::com::sun::star::xml::dom::XDocument;
@@ -282,6 +288,8 @@ void XmlFilterBase::importDocumentProperties()
     Reference< XDocumentProperties > xDocProps = 
xPropSupplier->getDocumentProperties();
     xImporter->importProperties( xDocumentStorage, xDocProps );
     checkDocumentProperties(xDocProps);
+
+    importCustomFragments(xDocumentStorage);
 }
 
 FastParser* XmlFilterBase::createParser()
@@ -833,6 +841,8 @@ void XmlFilterBase::exportDocumentProperties( const 
Reference< XDocumentProperti
         writeAppProperties( *this, xProperties );
         writeCustomProperties( *this, xProperties );
     }
+
+    exportCustomFragments();
 }
 
 // protected ------------------------------------------------------------------
@@ -946,6 +956,168 @@ OUString XmlFilterBase::getNamespaceURL(sal_Int32 nNSID) 
const
     return itr->second;
 }
 
+void 
XmlFilterBase::importCustomFragments(css::uno::Reference<css::embed::XStorage>& 
xDocumentStorage)
+{
+    Reference<XRelationshipAccess> xRelations(xDocumentStorage, UNO_QUERY);
+    if (xRelations.is())
+    {
+        // These are all the custom types we recognize and can preserve.
+        static const std::set<OUString> sCustomTypes = {
+                            
"http://schemas.dell.com/ddp/2016/relationships/xenFile";,
+                            
"http://schemas.dell.com/ddp/2016/relationships/hmacFile";,
+                            
"http://schemas.dell.com/ddp/2016/relationships/metadataFile";
+                        };
+
+        uno::Sequence<uno::Sequence<beans::StringPair>> aSeqs = 
xRelations->getAllRelationships();
+
+        std::vector<StreamDataSequence> aCustomFragments;
+        std::vector<OUString> aCustomFragmentTypes;
+        std::vector<OUString> aCustomFragmentTargets;
+        for (sal_Int32 j = 0; j < aSeqs.getLength(); j++)
+        {
+            OUString sType;
+            OUString sTarget;
+            const uno::Sequence<beans::StringPair>& aSeq = aSeqs[j];
+            for (sal_Int32 i = 0; i < aSeq.getLength(); i++)
+            {
+                const beans::StringPair& aPair = aSeq[i];
+                if (aPair.First == "Target")
+                    sTarget = aPair.Second;
+                else if (aPair.First == "Type")
+                    sType = aPair.Second;
+            }
+
+            if (sCustomTypes.find(sType) != sCustomTypes.end())
+            {
+                StreamDataSequence aDataSeq;
+                if (importBinaryData(aDataSeq, sTarget))
+                {
+                    aCustomFragments.emplace_back(aDataSeq);
+                    aCustomFragmentTypes.emplace_back(sType);
+                    aCustomFragmentTargets.emplace_back(sTarget);
+                }
+            }
+        }
+
+        // Adding the saved custom xml DOM
+        comphelper::SequenceAsHashMap aGrabBagProperties;
+        aGrabBagProperties["OOXCustomFragments"] <<= 
comphelper::containerToSequence(aCustomFragments);
+        aGrabBagProperties["OOXCustomFragmentTypes"] <<= 
comphelper::containerToSequence(aCustomFragmentTypes);
+        aGrabBagProperties["OOXCustomFragmentTargets"] <<= 
comphelper::containerToSequence(aCustomFragmentTargets);
+
+        std::vector<uno::Reference<xml::dom::XDocument>> aCustomXmlDomList;
+        std::vector<uno::Reference<xml::dom::XDocument>> 
aCustomXmlDomPropsList;
+        //FIXME: Ideally, we should get these the relations, but it seems that 
is not consistently set.
+        // In some cases it's stored in the workbook relationships, which is 
unexpected. So we discover them directly.
+        for (int i = 1; i < 100; ++i)
+        {
+            Reference<XDocument> xCustDoc = importFragment("customXml/item" + 
OUString::number(i) + ".xml");
+            Reference<XDocument> xCustDocProps = 
importFragment("customXml/itemProps" + OUString::number(i) + ".xml");
+            if (xCustDoc && xCustDocProps)
+            {
+                aCustomXmlDomList.emplace_back(xCustDoc);
+                aCustomXmlDomPropsList.emplace_back(xCustDocProps);
+            }
+            else
+                break;
+        }
+
+        // Adding the saved custom xml DOM
+        aGrabBagProperties["OOXCustomXml"] <<= 
comphelper::containerToSequence(aCustomXmlDomList);
+        aGrabBagProperties["OOXCustomXmlProps"] <<= 
comphelper::containerToSequence(aCustomXmlDomPropsList);
+
+        Reference<XComponent> xModel(getModel(), UNO_QUERY);
+        oox::core::XmlFilterBase::putPropertiesToDocumentGrabBag(xModel, 
aGrabBagProperties);
+    }
+}
+
+void XmlFilterBase::exportCustomFragments()
+{
+    Reference<XComponent> xModel(getModel(), UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xPropSet(xModel, uno::UNO_QUERY_THROW);
+
+    uno::Reference<beans::XPropertySetInfo> xPropSetInfo = 
xPropSet->getPropertySetInfo();
+    static const OUString aName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG;
+    if (!xPropSetInfo->hasPropertyByName(aName))
+        return;
+
+    uno::Sequence<uno::Reference<xml::dom::XDocument>> customXmlDomlist;
+    uno::Sequence<uno::Reference<xml::dom::XDocument>> customXmlDomPropslist;
+    uno::Sequence<StreamDataSequence> customFragments;
+    uno::Sequence<OUString> customFragmentTypes;
+    uno::Sequence<OUString> customFragmentTargets;
+
+    uno::Sequence<beans::PropertyValue> propList;
+    xPropSet->getPropertyValue(aName) >>= propList;
+    for (sal_Int32 nProp = 0; nProp < propList.getLength(); ++nProp)
+    {
+        const OUString propName = propList[nProp].Name;
+        if (propName == "OOXCustomXml")
+        {
+            propList[nProp].Value >>= customXmlDomlist;
+        }
+        else if (propName == "OOXCustomXmlProps")
+        {
+            propList[nProp].Value >>= customXmlDomPropslist;
+        }
+        else if (propName == "OOXCustomFragments")
+        {
+            propList[nProp].Value >>= customFragments;
+        }
+        else if (propName == "OOXCustomFragmentTypes")
+        {
+            propList[nProp].Value >>= customFragmentTypes;
+        }
+        else if (propName == "OOXCustomFragmentTargets")
+        {
+            propList[nProp].Value >>= customFragmentTargets;
+        }
+    }
+
+    // Expect customXmlDomPropslist.getLength() == 
customXmlDomlist.getLength().
+    for (sal_Int32 j = 0; j < customXmlDomlist.getLength(); j++)
+    {
+        uno::Reference<xml::dom::XDocument> customXmlDom = customXmlDomlist[j];
+        uno::Reference<xml::dom::XDocument> customXmlDomProps = 
customXmlDomPropslist[j];
+        const OUString fragmentPath = "customXml/item" + 
OUString::number((j+1)) + ".xml";
+        if (customXmlDom.is())
+        {
+            addRelation(oox::getRelationship(Relationship::CUSTOMXML), "../" + 
fragmentPath);
+
+            uno::Reference<xml::sax::XSAXSerializable> 
serializer(customXmlDom, uno::UNO_QUERY);
+            uno::Reference<xml::sax::XWriter> writer = 
xml::sax::Writer::create(comphelper::getProcessComponentContext());
+            writer->setOutputStream(openFragmentStream(fragmentPath, 
"application/xml"));
+            
serializer->serialize(uno::Reference<xml::sax::XDocumentHandler>(writer, 
uno::UNO_QUERY_THROW),
+                                  uno::Sequence<beans::StringPair>());
+        }
+
+        if (customXmlDomProps.is())
+        {
+            uno::Reference<xml::sax::XSAXSerializable> 
serializer(customXmlDomProps, uno::UNO_QUERY);
+            uno::Reference<xml::sax::XWriter> writer = 
xml::sax::Writer::create(comphelper::getProcessComponentContext());
+            
writer->setOutputStream(openFragmentStream("customXml/itemProps"+OUString::number((j+1))+".xml",
+                                    
"application/vnd.openxmlformats-officedocument.customXmlProperties+xml"));
+            
serializer->serialize(uno::Reference<xml::sax::XDocumentHandler>(writer, 
uno::UNO_QUERY_THROW),
+                                  uno::Sequence<beans::StringPair>());
+
+            // Adding itemprops's relationship entry to item.xml.rels file
+            addRelation(openFragmentStream(fragmentPath, "application/xml"),
+                        oox::getRelationship(Relationship::CUSTOMXMLPROPS),
+                        "itemProps"+OUString::number((j+1))+".xml");
+        }
+    }
+
+    // Expect customFragments.getLength() == customFragmentTypes.getLength() 
== customFragmentTargets.getLength().
+    for (sal_Int32 j = 0; j < customFragments.getLength(); j++)
+    {
+        addRelation(customFragmentTypes[j], customFragmentTargets[j]);
+        Reference<XOutputStream> xOutStream = 
openOutputStream(customFragmentTargets[j]);
+        xOutStream->writeBytes(customFragments[j]);
+        // BinaryXInputStream 
aInStrm(openOutputStream(customFragmentTargets[j]), true);
+        // aInStrm.copyToStream(xOutputStream);
+    }
+}
+
 } // namespace core
 } // namespace oox
 
commit e26a95360e60e0c17e70e72f36fb988bb664ddb5
Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk>
Date:   Tue Feb 6 17:46:28 2018 -0500

    oox: move putPropertiesToDocumentGrabBag to XmlFilterBase
    
    Change-Id: Ic3cbabc420c7856682b889528043563622997c14
    Reviewed-on: https://gerrit.libreoffice.org/49235
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Ashod Nakashian <ashnak...@gmail.com>

diff --git a/include/oox/core/xmlfilterbase.hxx 
b/include/oox/core/xmlfilterbase.hxx
index 26948588e1dd..7621a0081a53 100644
--- a/include/oox/core/xmlfilterbase.hxx
+++ b/include/oox/core/xmlfilterbase.hxx
@@ -228,6 +228,8 @@ public:
     void exportDocumentProperties( const css::uno::Reference< 
css::document::XDocumentProperties >& xProperties );
 
     void importDocumentProperties();
+    static void putPropertiesToDocumentGrabBag(const 
css::uno::Reference<css::lang::XComponent>& xDstDoc,
+                                               const 
comphelper::SequenceAsHashMap& rProperties);
 
     static FastParser* createParser();
 
diff --git a/oox/source/core/xmlfilterbase.cxx 
b/oox/source/core/xmlfilterbase.cxx
index 7f20d13b8200..15f253c734c7 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -234,6 +234,36 @@ void XmlFilterBase::checkDocumentProperties(const 
Reference<XDocumentProperties>
     mbMSO2007 = true;
 }
 
+void XmlFilterBase::putPropertiesToDocumentGrabBag(const 
css::uno::Reference<css::lang::XComponent>& xDstDoc,
+                                                   const 
comphelper::SequenceAsHashMap& rProperties)
+{
+    try
+    {
+        uno::Reference<beans::XPropertySet> xDocProps(xDstDoc, uno::UNO_QUERY);
+        if (xDocProps.is())
+        {
+            uno::Reference<beans::XPropertySetInfo> xPropsInfo = 
xDocProps->getPropertySetInfo();
+
+            static const OUString aGrabBagPropName = "InteropGrabBag";
+            if (xPropsInfo.is() && 
xPropsInfo->hasPropertyByName(aGrabBagPropName))
+            {
+                // get existing grab bag
+                comphelper::SequenceAsHashMap 
aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
+
+                // put the new items
+                aGrabBag.update(rProperties);
+
+                // put it back to the document
+                xDocProps->setPropertyValue(aGrabBagPropName, 
uno::Any(aGrabBag.getAsConstPropertyValueList()));
+            }
+        }
+    }
+    catch (const uno::Exception&)
+    {
+        SAL_WARN("oox","Failed to save documents grab bag");
+    }
+}
+
 void XmlFilterBase::importDocumentProperties()
 {
     MediaDescriptor aMediaDesc( getMediaDescriptor() );
diff --git a/writerfilter/source/filter/WriterFilter.cxx 
b/writerfilter/source/filter/WriterFilter.cxx
index af348d9eb33b..2953c6cc3f17 100644
--- a/writerfilter/source/filter/WriterFilter.cxx
+++ b/writerfilter/source/filter/WriterFilter.cxx
@@ -35,6 +35,7 @@
 #include <cppuhelper/supportsservice.hxx>
 #include <dmapper/DomainMapperFactory.hxx>
 #include <oox/core/filterdetect.hxx>
+#include <oox/core/xmlfilterbase.hxx>
 #include <oox/helper/graphichelper.hxx>
 #include <oox/ole/olestorage.hxx>
 #include <oox/ole/vbaproject.hxx>
@@ -115,10 +116,6 @@ public:
     OUString SAL_CALL getImplementationName() override;
     sal_Bool SAL_CALL supportsService(const OUString& rServiceName) override;
     uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override;
-
-private:
-    void putPropertiesToDocumentGrabBag(const comphelper::SequenceAsHashMap& 
rProperties);
-
 };
 
 sal_Bool WriterFilter::filter(const uno::Sequence< beans::PropertyValue >& 
rDescriptor)
@@ -231,7 +228,7 @@ sal_Bool WriterFilter::filter(const uno::Sequence< 
beans::PropertyValue >& rDesc
         // Adding the saved embedding document to document's grab bag
         aGrabBagProperties["OOXEmbeddings"] <<= pDocument->getEmbeddingsList();
 
-        putPropertiesToDocumentGrabBag(aGrabBagProperties);
+        oox::core::XmlFilterBase::putPropertiesToDocumentGrabBag(m_xDstDoc, 
aGrabBagProperties);
 
         writerfilter::ooxml::OOXMLStream::Pointer_t  
pVBAProjectStream(writerfilter::ooxml::OOXMLDocumentFactory::createStream(pDocStream,
 writerfilter::ooxml::OOXMLStream::VBAPROJECT));
         oox::StorageRef xVbaPrjStrg(new ::oox::ole::OleStorage(m_xContext, 
pVBAProjectStream->getDocumentStream(), false));
@@ -336,35 +333,6 @@ uno::Sequence<OUString> 
WriterFilter::getSupportedServiceNames()
     return aRet;
 }
 
-void WriterFilter::putPropertiesToDocumentGrabBag(const 
comphelper::SequenceAsHashMap& rProperties)
-{
-    try
-    {
-        uno::Reference<beans::XPropertySet> xDocProps(m_xDstDoc, 
uno::UNO_QUERY);
-        if (xDocProps.is())
-        {
-            uno::Reference<beans::XPropertySetInfo> xPropsInfo = 
xDocProps->getPropertySetInfo();
-
-            const OUString aGrabBagPropName = "InteropGrabBag";
-            if (xPropsInfo.is() && 
xPropsInfo->hasPropertyByName(aGrabBagPropName))
-            {
-                // get existing grab bag
-                comphelper::SequenceAsHashMap 
aGrabBag(xDocProps->getPropertyValue(aGrabBagPropName));
-
-                // put the new items
-                aGrabBag.update(rProperties);
-
-                // put it back to the document
-                xDocProps->setPropertyValue(aGrabBagPropName, 
uno::Any(aGrabBag.getAsConstPropertyValueList()));
-            }
-        }
-    }
-    catch (const uno::Exception&)
-    {
-        SAL_WARN("writerfilter","Failed to save documents grab bag");
-    }
-}
-
 extern "C" SAL_DLLPUBLIC_EXPORT uno::XInterface* 
com_sun_star_comp_Writer_WriterFilter_get_implementation(uno::XComponentContext*
 component, uno::Sequence<uno::Any> const& /*rSequence*/)
 {
     return cppu::acquire(new WriterFilter(component));
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to