diff options
-rw-r--r-- | sw/qa/extras/ooxmlexport/data/activex.docx | bin | 0 -> 363044 bytes | |||
-rw-r--r-- | sw/qa/extras/ooxmlexport/ooxmlexport.cxx | 28 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.cxx | 44 | ||||
-rw-r--r-- | sw/source/filter/ww8/docxexport.hxx | 3 | ||||
-rw-r--r-- | writerfilter/inc/ooxml/OOXMLDocument.hxx | 3 | ||||
-rw-r--r-- | writerfilter/source/filter/ImportFilter.cxx | 30 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLDocumentImpl.cxx | 56 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLDocumentImpl.hxx | 3 | ||||
-rw-r--r-- | writerfilter/source/ooxml/OOXMLStreamImpl.cxx | 6 |
9 files changed, 171 insertions, 2 deletions
diff --git a/sw/qa/extras/ooxmlexport/data/activex.docx b/sw/qa/extras/ooxmlexport/data/activex.docx Binary files differnew file mode 100644 index 000000000000..e7c15e81cfb7 --- /dev/null +++ b/sw/qa/extras/ooxmlexport/data/activex.docx diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx index b622cb2934ef..ce9a0a965aec 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport.cxx @@ -1587,6 +1587,34 @@ DECLARE_OOXML_TEST(testCustomXmlGrabBag, "customxml.docx") CPPUNIT_ASSERT(CustomXml); // Grab Bag has all the expected elements } +DECLARE_OOXML_TEST(testActiveXGrabBag, "activex.docx") +{ + // The problem was that activeX.xml files were missing from docx file after saving file. + // This test case tests whether activex files grabbagged properly in correct object. + + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xTextDocumentPropertySet(xTextDocument, uno::UNO_QUERY); + uno::Sequence<beans::PropertyValue> aGrabBag(0); + xTextDocumentPropertySet->getPropertyValue(OUString("InteropGrabBag")) >>= aGrabBag; + CPPUNIT_ASSERT(aGrabBag.hasElements()); // Grab Bag not empty + bool bActiveX = sal_False; + for(int i = 0; i < aGrabBag.getLength(); ++i) + { + if (aGrabBag[i].Name == "OOXActiveX") + { + bActiveX = sal_True; + uno::Reference<xml::dom::XDocument> aActiveXDom; + uno::Sequence<uno::Reference<xml::dom::XDocument> > aActiveXDomList; + CPPUNIT_ASSERT(aGrabBag[i].Value >>= aActiveXDomList); // PropertyValue of proper type + sal_Int32 length = aActiveXDomList.getLength(); + CPPUNIT_ASSERT_EQUAL(sal_Int32(5), length); + aActiveXDom = aActiveXDomList[0]; + CPPUNIT_ASSERT(aActiveXDom.get()); // Reference not empty + } + } + CPPUNIT_ASSERT(bActiveX); // Grab Bag has all the expected elements +} + DECLARE_OOXML_TEST(testFdo69644, "fdo69644.docx") { // The problem was that the exporter exported the table definition diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx index 2df1a600d538..9053d6b5719c 100644 --- a/sw/source/filter/ww8/docxexport.cxx +++ b/sw/source/filter/ww8/docxexport.cxx @@ -353,6 +353,8 @@ void DocxExport::ExportDocument_Impl() WriteCustomXml(); + WriteActiveX(); + delete pStyles, pStyles = NULL; delete m_pSections, m_pSections = NULL; } @@ -855,6 +857,48 @@ void DocxExport::WriteCustomXml() } } +void DocxExport::WriteActiveX() +{ + uno::Reference< beans::XPropertySet > xPropSet( pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW ); + + uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); + OUString pName = UNO_NAME_MISC_OBJ_INTEROPGRABBAG; + if ( !xPropSetInfo->hasPropertyByName( pName ) ) + return; + + uno::Sequence<uno::Reference<xml::dom::XDocument> > activeXDomlist; + uno::Sequence< beans::PropertyValue > propList; + xPropSet->getPropertyValue( pName ) >>= propList; + for ( sal_Int32 nProp=0; nProp < propList.getLength(); ++nProp ) + { + OUString propName = propList[nProp].Name; + if ( propName == "OOXActiveX" ) + { + propList[nProp].Value >>= activeXDomlist; + break; + } + } + + for (sal_Int32 j = 0; j < activeXDomlist.getLength(); j++) + { + uno::Reference<xml::dom::XDocument> activeXDom = activeXDomlist[j]; + + if ( activeXDom.is() ) + { + m_pFilter->addRelation( m_pDocumentFS->getOutputStream(), + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/control", + "activeX/activeX"+OUString::number((j+1))+".xml" ); + + uno::Reference< xml::sax::XSAXSerializable > serializer( activeXDom, uno::UNO_QUERY ); + uno::Reference< xml::sax::XWriter > writer = xml::sax::Writer::create( comphelper::getProcessComponentContext() ); + writer->setOutputStream( GetFilter().openFragmentStream( "word/activeX/activeX"+OUString::number((j+1))+".xml", + "application/vnd.ms-office.activeX+xml" ) ); + serializer->serialize( uno::Reference< xml::sax::XDocumentHandler >( writer, uno::UNO_QUERY_THROW ), + uno::Sequence< beans::StringPair >() ); + } + } +} + VMLExport& DocxExport::VMLExporter() { return *m_pVMLExport; diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx index 8c2f958e36b5..38154595a8ff 100644 --- a/sw/source/filter/ww8/docxexport.hxx +++ b/sw/source/filter/ww8/docxexport.hxx @@ -210,6 +210,9 @@ private: /// Write customXml/item[n].xml and customXml/itemProps[n].xml void WriteCustomXml(); + /// Write word/activeX/activeX[n].xml + void WriteActiveX(); + /// All xml namespaces to be used at the top of any text .xml file (main doc, headers, footers,...) sax_fastparser::XFastAttributeListRef MainXmlNamespaces( sax_fastparser::FSHelperPtr serializer ); diff --git a/writerfilter/inc/ooxml/OOXMLDocument.hxx b/writerfilter/inc/ooxml/OOXMLDocument.hxx index 91d9adce87fe..e75cf629510a 100644 --- a/writerfilter/inc/ooxml/OOXMLDocument.hxx +++ b/writerfilter/inc/ooxml/OOXMLDocument.hxx @@ -76,7 +76,7 @@ class WRITERFILTER_OOXML_DLLPUBLIC OOXMLStream { public: enum StreamType_t { UNKNOWN, DOCUMENT, STYLES, FONTTABLE, NUMBERING, - FOOTNOTES, ENDNOTES, COMMENTS, THEME, CUSTOMXML, CUSTOMXMLPROPS, SETTINGS, VBAPROJECT }; + FOOTNOTES, ENDNOTES, COMMENTS, THEME, CUSTOMXML, CUSTOMXMLPROPS, ACTIVEX, SETTINGS, VBAPROJECT }; typedef boost::shared_ptr<OOXMLStream> Pointer_t; virtual ~OOXMLStream() {} @@ -244,6 +244,7 @@ public: virtual void setThemeDom( uno::Reference<xml::dom::XDocument> xThemeDom ) = 0; virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getCustomXmlDomList( ) = 0; virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getCustomXmlDomPropsList( ) = 0; + virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getActiveXDomList( ) = 0; }; diff --git a/writerfilter/source/filter/ImportFilter.cxx b/writerfilter/source/filter/ImportFilter.cxx index b7bcfb956f2e..f29e7ecac39a 100644 --- a/writerfilter/source/filter/ImportFilter.cxx +++ b/writerfilter/source/filter/ImportFilter.cxx @@ -187,6 +187,36 @@ sal_Bool WriterFilter::filter( const uno::Sequence< beans::PropertyValue >& aDes SAL_WARN("writerfilter","Failed to save custom xml dom to documents grab bag"); } + // Adding the saved ActiveX DOM to the document's grab bag + 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 ) ) + { + uno::Sequence<beans::PropertyValue> aGrabBag; + + // We want to keep the previous items + xDocProps->getPropertyValue( aGrabBagPropName ) >>= aGrabBag; + sal_Int32 length = aGrabBag.getLength(); + aGrabBag.realloc(length+1); + + beans::PropertyValue* pValue = aGrabBag.getArray(); + pValue[length].Name = "OOXActiveX"; + pValue[length].Value = uno::makeAny( pDocument->getActiveXDomList() ); + xDocProps->setPropertyValue( aGrabBagPropName, uno::Any( aGrabBag ) ); + } + } + } + catch(const uno::Exception&) + { + SAL_WARN("writerfilter","Failed to save ActiveX dom to documents grab bag"); + } + 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 ) ); if( xVbaPrjStrg.get() && xVbaPrjStrg->isStorage() ) diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx index c29ac5d18617..d71c339bf274 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.cxx @@ -431,6 +431,8 @@ void OOXMLDocumentImpl::resolve(Stream & rStream) // Custom xml's are handled as part of grab bag. resolveCustomXmlStream(rStream); + resolveActiveXStream(rStream); + resolveFastSubStream(rStream, OOXMLStream::FONTTABLE); resolveFastSubStream(rStream, OOXMLStream::STYLES); resolveFastSubStream(rStream, OOXMLStream::NUMBERING); @@ -511,6 +513,55 @@ void OOXMLDocumentImpl::resolveCustomXmlStream(Stream & rStream) } } +void OOXMLDocumentImpl::resolveActiveXStream(Stream & rStream) +{ + // Resolving all ActiveX[n].xml files from ActiveX folder. + uno::Reference<embed::XRelationshipAccess> mxRelationshipAccess; + mxRelationshipAccess.set((*dynamic_cast<OOXMLStreamImpl *>(mpStream.get())).accessDocumentStream(), uno::UNO_QUERY_THROW); + if (mxRelationshipAccess.is()) + { + OUString sCustomType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/control"); + OUString sTarget("Target"); + bool bFound = false; + sal_Int32 counter = 0; + uno::Sequence< uno::Sequence< beans::StringPair > >aSeqs = + mxRelationshipAccess->getAllRelationships(); + uno::Sequence<uno::Reference<xml::dom::XDocument> > mxActiveXDomListTemp(aSeqs.getLength()); + for (sal_Int32 j = 0; j < aSeqs.getLength(); j++) + { + uno::Sequence< beans::StringPair > aSeq = aSeqs[j]; + for (sal_Int32 i = 0; i < aSeq.getLength(); i++) + { + beans::StringPair aPair = aSeq[i]; + // Need to resolve only ActiveX files from document relationships. + // Skipping other files. + if (aPair.Second.compareTo(sCustomType) == 0) + bFound = true; + else if(aPair.First.compareTo(sTarget) == 0 && bFound) + { + // Adding value to extern variable customTarget. It will be used in ooxmlstreamimpl + // to ensure ActiveX.xml target is visited in lcl_getTarget. + customTarget = aPair.Second; + } + } + if(bFound) + { + uno::Reference<xml::dom::XDocument> activeXTemp = importSubStream(OOXMLStream::ACTIVEX); + // This will add all ActiveX[n].xml to grabbag list. + if(activeXTemp.is()) + { + mxActiveXDomListTemp[counter] = activeXTemp; + counter++; + resolveFastSubStream(rStream, OOXMLStream::ACTIVEX); + } + bFound = false; + } + } + mxActiveXDomListTemp.realloc(counter); + mxActiveXDomList = mxActiveXDomListTemp; + } +} + uno::Reference<io::XInputStream> OOXMLDocumentImpl::getInputStreamForId(const OUString & rId) { OOXMLStream::Pointer_t pStream(OOXMLDocumentFactory::createStream(mpStream, rId)); @@ -583,6 +634,11 @@ uno::Sequence<uno::Reference<xml::dom::XDocument> > OOXMLDocumentImpl::getCustom return mxCustomXmlDomPropsList; } +uno::Sequence<uno::Reference<xml::dom::XDocument> > OOXMLDocumentImpl::getActiveXDomList( ) +{ + return mxActiveXDomList; +} + OOXMLDocument * OOXMLDocumentFactory::createDocument (OOXMLStream::Pointer_t pStream) diff --git a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx index 07511331e8fe..74c1006425eb 100644 --- a/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx +++ b/writerfilter/source/ooxml/OOXMLDocumentImpl.hxx @@ -45,6 +45,7 @@ class OOXMLDocumentImpl : public OOXMLDocument uno::Sequence<uno::Reference<xml::dom::XDocument> > mxCustomXmlDomList; uno::Sequence<uno::Reference<xml::dom::XDocument> > mxCustomXmlDomPropsList; uno::Reference<xml::dom::XDocument> mxCustomXmlProsDom; + uno::Sequence<uno::Reference<xml::dom::XDocument> > mxActiveXDomList; bool mbIsSubstream; protected: @@ -69,6 +70,7 @@ protected: void setIsSubstream( bool bSubstream ) { mbIsSubstream = bSubstream; }; void resolveCustomXmlStream(Stream & rStream); + void resolveActiveXStream(Stream & rStream); public: OOXMLDocumentImpl(OOXMLStream::Pointer_t pStream); @@ -117,6 +119,7 @@ public: virtual uno::Reference<xml::dom::XDocument> getThemeDom(); virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getCustomXmlDomList(); virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getCustomXmlDomPropsList(); + virtual uno::Sequence<uno::Reference<xml::dom::XDocument> > getActiveXDomList(); }; }} #endif // OOXML_DOCUMENT_IMPL_HXX diff --git a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx index 333df28b2242..8b658c51faeb 100644 --- a/writerfilter/source/ooxml/OOXMLStreamImpl.cxx +++ b/writerfilter/source/ooxml/OOXMLStreamImpl.cxx @@ -112,6 +112,7 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess> static OUString sThemeType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme"); static OUString sCustomType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml"); static OUString sCustomPropsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXmlProps"); + static OUString sActiveXType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/control"); static OUString sSettingsType("http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings"); static OUString sTarget("Target"); static OUString sTargetMode("TargetMode"); @@ -155,6 +156,9 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess> case CUSTOMXMLPROPS: sStreamType = sCustomPropsType; break; + case ACTIVEX: + sStreamType = sActiveXType; + break; case SETTINGS: sStreamType = sSettingsType; break; @@ -186,7 +190,7 @@ bool OOXMLStreamImpl::lcl_getTarget(uno::Reference<embed::XRelationshipAccess> else if (aPair.First.compareTo(sTarget) == 0) { // checking item[n].xml is not visited already. - if(customTarget != aPair.Second && sStreamType == sCustomType) + if(customTarget != aPair.Second && (sStreamType == sCustomType || sStreamType == sActiveXType)) { bFound = false; } |