summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sw/qa/extras/ooxmlexport/data/activex.docxbin0 -> 363044 bytes
-rw-r--r--sw/qa/extras/ooxmlexport/ooxmlexport.cxx28
-rw-r--r--sw/source/filter/ww8/docxexport.cxx44
-rw-r--r--sw/source/filter/ww8/docxexport.hxx3
-rw-r--r--writerfilter/inc/ooxml/OOXMLDocument.hxx3
-rw-r--r--writerfilter/source/filter/ImportFilter.cxx30
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.cxx56
-rw-r--r--writerfilter/source/ooxml/OOXMLDocumentImpl.hxx3
-rw-r--r--writerfilter/source/ooxml/OOXMLStreamImpl.cxx6
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
new file mode 100644
index 000000000000..e7c15e81cfb7
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/activex.docx
Binary files differ
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;
}