LibreOffice Module writerfilter (master) 1
OLEHandler.cxx
Go to the documentation of this file.
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#include "OLEHandler.hxx"
20#include "DomainMapper.hxx"
21#include "GraphicHelpers.hxx"
22
24#include <ooxml/resourceids.hxx>
25#include <rtl/ustring.hxx>
26#include <sal/log.hxx>
27#include <osl/diagnose.h>
30#include <officecfg/Office/Common.hxx>
31#include <com/sun/star/container/XNameAccess.hpp>
32#include <com/sun/star/document/XEmbeddedObjectResolver.hpp>
33#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
34#include <com/sun/star/document/XFilter.hpp>
35#include <com/sun/star/document/XImporter.hpp>
36#include <com/sun/star/drawing/XShape.hpp>
37#include <com/sun/star/graphic/XGraphic.hpp>
38#include <com/sun/star/io/XOutputStream.hpp>
39#include <com/sun/star/lang/XComponent.hpp>
40#include <com/sun/star/lang/XMultiServiceFactory.hpp>
41#include <com/sun/star/lang/XServiceInfo.hpp>
42#include <com/sun/star/text/XTextDocument.hpp>
43#include <com/sun/star/text/WrapTextMode.hpp>
44#include <com/sun/star/uno/XComponentContext.hpp>
45
46namespace writerfilter::dmapper {
47
48using namespace ::com::sun::star;
49
50
52LoggedProperties("OLEHandler"),
53 m_nWrapMode(text::WrapTextMode_THROUGHT),
54 m_rDomainMapper(rDomainMapper)
55{
56}
57
58
60{
61}
62
63
65{
66 OUString sStringValue = rVal.getString();
67 switch( rName )
68 {
69 case NS_ooxml::LN_CT_OLEObject_Type:
70 break;
71 case NS_ooxml::LN_CT_OLEObject_ProgID:
72 m_sProgId = sStringValue;
73 break;
74 case NS_ooxml::LN_CT_OLEObject_ShapeID:
75 break;
76 case NS_ooxml::LN_CT_OLEObject_DrawAspect:
77 m_sDrawAspect = sStringValue;
78 break;
79 case NS_ooxml::LN_CT_OLEObject_ObjectID:
80 break;
81 case NS_ooxml::LN_CT_OLEObject_r_id:
82 break;
83 case NS_ooxml::LN_inputstream:
84 rVal.getAny() >>= m_xInputStream;
85 break;
86 case NS_ooxml::LN_CT_Object_dxaOrig:
87 m_sVisAreaWidth = sStringValue;
88 break;
89 case NS_ooxml::LN_CT_Object_dyaOrig:
90 m_sVisAreaHeight = sStringValue;
91 break;
92 case NS_ooxml::LN_shape:
93 {
95 rVal.getAny() >>= xTempShape;
96
97 // Control shape is handled on a different code path
98 uno::Reference< lang::XServiceInfo > xSInfo( xTempShape, uno::UNO_QUERY_THROW );
99 if(xSInfo->supportsService("com.sun.star.drawing.ControlShape"))
100 {
102 break;
103 }
104
105 if( xTempShape.is() )
106 {
107 m_xShape.set( xTempShape );
108
109 // No need to set the wrapping here as it's either set in oox or will be set later
110
111 // Shapes in the header or footer should be in the background, since the default is WrapTextMode_THROUGH.
113 {
114 try
115 {
116 uno::Reference<beans::XPropertySet> xShapeProps(m_xShape, uno::UNO_QUERY);
117 xShapeProps->setPropertyValue("Opaque", uno::Any(false));
118 }
119 catch( const uno::Exception& )
120 {
121 TOOLS_WARN_EXCEPTION("writerfilter", "Exception in OLE Handler");
122 }
123 }
124 }
125 }
126 break;
127 default:
128 OSL_FAIL( "unknown attribute");
129 }
130}
131
132css::awt::Size OLEHandler::getSize() const
133{
134 if (!m_xShape)
135 return css::awt::Size();
136 return m_xShape->getSize();
137}
138
139css::uno::Reference<css::graphic::XGraphic> OLEHandler::getReplacement() const
140{
141 if (!m_xShape)
142 return nullptr;
143 uno::Reference<beans::XPropertySet> xShapeProps(m_xShape, uno::UNO_QUERY);
144 css::uno::Reference<css::graphic::XGraphic> xReplacement;
145 xShapeProps->getPropertyValue(getPropertyName(PROP_BITMAP)) >>= xReplacement;
146 return xReplacement;
147}
148
150{
151 sal_uInt32 nSprmId = rSprm.getId();
152 switch( nSprmId )
153 {
154 case NS_ooxml::LN_OLEObject_OLEObject:
155 {
157 if( pProperties )
158 {
159 pProperties->resolve(*this);
160 }
161 }
162 break;
163 case NS_ooxml::LN_wrap_wrap:
164 {
166 if ( pProperties )
167 {
169 pProperties->resolve( *pHandler );
170
171 m_nWrapMode = pHandler->getWrapMode( );
172
173 try
174 {
175 uno::Reference< beans::XPropertySet > xShapeProps( m_xShape, uno::UNO_QUERY_THROW );
176
177 xShapeProps->setPropertyValue(
179 uno::Any( static_cast<sal_Int32>(m_nWrapMode) ) );
180
181 // Through shapes in the header or footer(that spill into the body) should be in the background.
182 // It is just assumed that all shapes will spill into the body.
184 xShapeProps->setPropertyValue("Opaque", uno::Any(m_nWrapMode != text::WrapTextMode_THROUGH));
185 }
186 catch( const uno::Exception& )
187 {
188 TOOLS_WARN_EXCEPTION("writerfilter", "Exception in OLE Handler");
189 }
190 }
191 }
192 break;
193 default:
194 {
195 OSL_FAIL( "unknown attribute");
196 }
197 }
198}
199
201{
202 OUString aFilterService;
203 if (m_sProgId == "Word.Document.12")
204 aFilterService = "com.sun.star.comp.Writer.WriterFilter";
205 else if (m_sProgId == "Excel.Sheet.12")
206 aFilterService = "com.sun.star.comp.oox.xls.ExcelFilter";
207 else if (m_sProgId == "Equation.3")
208 aFilterService = "com.sun.star.comp.Math.MathTypeFilter";
209 else
210 SAL_WARN("writerfilter", "OLEHandler::importStream: unhandled m_sProgId: " << m_sProgId);
211
212 if (!m_xInputStream.is() || aFilterService.isEmpty())
213 return;
214
215 // Create the filter service.
216 uno::Reference<uno::XInterface> xInterface = xComponentContext->getServiceManager()->createInstanceWithContext(aFilterService, xComponentContext);
217
218 // Set target document.
219 uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY);
220 uno::Reference<document::XEmbeddedObjectSupplier> xSupplier(xOLE, uno::UNO_QUERY);
221 uno::Reference<lang::XComponent> xEmbeddedObject = xSupplier->getEmbeddedObject();
222 if (!xEmbeddedObject.is())
223 return;
224 xImporter->setTargetDocument( xEmbeddedObject );
225
226 // Import the input stream.
227 utl::MediaDescriptor aMediaDescriptor;
228 aMediaDescriptor["InputStream"] <<= m_xInputStream;
229 uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY);
230 xFilter->filter(aMediaDescriptor.getAsConstPropertyValueList());
231
232 // Now that the data is imported, update the (typically) changed stream name.
233 uno::Reference<beans::XPropertySet> xPropertySet(xOLE, uno::UNO_QUERY);
234 ::oox::ole::SaveInteropProperties(xTextDocument,
235 xPropertySet->getPropertyValue("StreamName").get<OUString>(), &m_aURL,
236 m_sProgId);
237}
238
239OUString OLEHandler::getCLSID() const
240{
241 OUString aRet;
242
243 // See officecfg/registry/data/org/openoffice/Office/Embedding.xcu.
244 if (m_sProgId == "Word.Document.12")
245 {
246 if (officecfg::Office::Common::Filter::Microsoft::Import::WinWordToWriter::get())
247 aRet = "8BC6B165-B1B2-4EDD-aa47-dae2ee689dd6";
248 }
249 else if (m_sProgId == "Excel.Sheet.12")
250 {
251 if (officecfg::Office::Common::Filter::Microsoft::Import::ExcelToCalc::get())
252 aRet = "47BBB4CB-CE4C-4E80-A591-42D9AE74950F";
253 }
254 else if (m_sProgId == "Equation.3")
255 {
256 if (officecfg::Office::Common::Filter::Microsoft::Import::MathTypeToMath::get())
257 aRet = "078B7ABA-54FC-457F-8551-6147E776A997";
258 }
259 else
260 SAL_WARN("writerfilter", "OLEHandler::getCLSID: unhandled m_sProgId: " << m_sProgId);
261
262 return aRet;
263}
264
265OUString const & OLEHandler::GetDrawAspect() const
266{
267 return m_sDrawAspect;
268}
269
270OUString const & OLEHandler::GetVisAreaWidth() const
271{
272 return m_sVisAreaWidth;
273}
274
275OUString const & OLEHandler::GetVisAreaHeight() const
276{
277 return m_sVisAreaHeight;
278}
279
281 uno::Reference<text::XTextDocument> const& xTextDocument)
282{
283 OUString sRet;
284 if( !m_xInputStream.is( ) )
285 return sRet;
286 try
287 {
288 uno::Reference < lang::XMultiServiceFactory > xFactory(xTextDocument, uno::UNO_QUERY_THROW);
290 xFactory->createInstance("com.sun.star.document.ImportEmbeddedObjectResolver"), uno::UNO_QUERY_THROW );
291 //hack to work with the ImportEmbeddedObjectResolver
292 static sal_Int32 nObjectCount = 100;
293 uno::Reference< container::XNameAccess > xNA( xEmbeddedResolver, uno::UNO_QUERY_THROW );
294 OUString aURL = "Obj" + OUString::number( nObjectCount++ );
296 if( (xNA->getByName( aURL ) >>= xOLEStream) && xOLEStream.is() )
297 {
298 const sal_Int32 nReadRequest = 0x1000;
300
301 while( true )
302 {
303 sal_Int32 nRead = m_xInputStream->readBytes( aData, nReadRequest );
304 xOLEStream->writeBytes( aData );
305 if( nRead < nReadRequest )
306 {
307 xOLEStream->closeOutput();
308 break;
309 }
310 }
311
312 ::oox::ole::SaveInteropProperties(xTextDocument, aURL, nullptr, m_sProgId);
313
314 OUString aPersistName( xEmbeddedResolver->resolveEmbeddedObjectURL( aURL ) );
315 sRet = aPersistName.copy( strlen("vnd.sun.star.EmbeddedObject:") );
316
317 }
318 uno::Reference< lang::XComponent > xComp( xEmbeddedResolver, uno::UNO_QUERY_THROW );
319 xComp->dispose();
320 m_aURL = aURL;
321 }
322 catch( const uno::Exception& )
323 {
324 TOOLS_WARN_EXCEPTION( "writerfilter", "OLEHandler::createOLEObject");
325 }
326 return sRet;
327}
328
329} //namespace writerfilter::dmapper
330
331/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
An SPRM: Section, Paragraph and Run Modifier.
virtual sal_uInt32 getId() const =0
Returns id of the SPRM.
virtual writerfilter::Reference< Properties >::Pointer_t getProps()=0
Returns reference to properties contained in the SPRM.
virtual OUString getString() const =0
Returns string representation of the value.
virtual css::uno::Any getAny() const =0
Returns representation of the value as uno::Any.
virtual ~OLEHandler() override
Definition: OLEHandler.cxx:59
OUString const & GetDrawAspect() const
Definition: OLEHandler.cxx:265
virtual void lcl_sprm(Sprm &sprm) override
Definition: OLEHandler.cxx:149
virtual void lcl_attribute(Id Name, Value &val) override
Definition: OLEHandler.cxx:64
css::uno::Reference< css::io::XInputStream > m_xInputStream
Definition: OLEHandler.hxx:59
OUString getCLSID() const
Get the CLSID of the OLE object, in case we can find one based on m_sProgId.
Definition: OLEHandler.cxx:239
OUString m_aURL
The stream URL right after the import of the raw data.
Definition: OLEHandler.hxx:53
OLEHandler(DomainMapper &rDomainMapper)
Definition: OLEHandler.cxx:51
void importStream(const css::uno::Reference< css::uno::XComponentContext > &xComponentContext, const css::uno::Reference< css::text::XTextDocument > &xTextDocument, const css::uno::Reference< css::text::XTextContent > &xOLE)
In case of a valid CLSID, import the native data to the previously created empty OLE object.
Definition: OLEHandler.cxx:200
css::text::WrapTextMode m_nWrapMode
Definition: OLEHandler.hxx:55
css::uno::Reference< css::graphic::XGraphic > getReplacement() const
Definition: OLEHandler.cxx:139
OUString const & GetVisAreaWidth() const
Definition: OLEHandler.cxx:270
css::uno::Reference< css::drawing::XShape > m_xShape
Definition: OLEHandler.hxx:57
css::awt::Size getSize() const
Definition: OLEHandler.cxx:132
OUString const & GetVisAreaHeight() const
Definition: OLEHandler.cxx:275
OUString copyOLEOStream(css::uno::Reference< css::text::XTextDocument > const &xTextDocument)
Definition: OLEHandler.cxx:280
#define TOOLS_WARN_EXCEPTION(area, stream)
URL aURL
Reference< XSingleServiceFactory > xFactory
#define SAL_WARN(area, stream)
def text(shape, orig_st)
constexpr OUStringLiteral aData
OUString getPropertyName(PropertyIds eId)
sal_uInt32 Id