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 : #include <OLEHandler.hxx>
20 : #include <DomainMapper.hxx>
21 : #include <PropertyMap.hxx>
22 : #include "GraphicHelpers.hxx"
23 :
24 : #include <editeng/unoprnms.hxx>
25 : #include <ooxml/resourceids.hxx>
26 : #include <rtl/ustring.hxx>
27 : #include <osl/diagnose.h>
28 : #include <unotools/mediadescriptor.hxx>
29 : #include <officecfg/Office/Common.hxx>
30 : #include <com/sun/star/beans/PropertyValue.hpp>
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/document/XStorageBasedDocument.hpp>
37 : #include <com/sun/star/drawing/XShape.hpp>
38 : #include <com/sun/star/embed/XEmbeddedObject.hpp>
39 : #include <com/sun/star/embed/XEmbedObjectCreator.hpp>
40 : #include <com/sun/star/graphic/XGraphic.hpp>
41 : #include <com/sun/star/io/XStream.hpp>
42 : #include <com/sun/star/lang/XComponent.hpp>
43 : #include <com/sun/star/lang/XInitialization.hpp>
44 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 : #include <com/sun/star/text/XTextDocument.hpp>
46 : #include <com/sun/star/uno/XComponentContext.hpp>
47 :
48 : namespace writerfilter {
49 : namespace dmapper {
50 :
51 : using namespace ::com::sun::star;
52 :
53 :
54 299 : OLEHandler::OLEHandler(DomainMapper& rDomainMapper) :
55 : LoggedProperties("OLEHandler"),
56 : m_nDxaOrig(0),
57 : m_nDyaOrig(0),
58 : m_nWrapMode(1),
59 299 : m_rDomainMapper(rDomainMapper)
60 : {
61 299 : }
62 :
63 :
64 598 : OLEHandler::~OLEHandler()
65 : {
66 598 : }
67 :
68 :
69 794 : void OLEHandler::lcl_attribute(Id rName, Value & rVal)
70 : {
71 794 : OUString sStringValue = rVal.getString();
72 : (void)rName;
73 794 : switch( rName )
74 : {
75 : case NS_ooxml::LN_CT_OLEObject_Type:
76 54 : m_sObjectType = sStringValue;
77 54 : break;
78 : case NS_ooxml::LN_CT_OLEObject_ProgID:
79 57 : m_sProgId = sStringValue;
80 57 : break;
81 : case NS_ooxml::LN_CT_OLEObject_ShapeID:
82 54 : m_sShapeId = sStringValue;
83 54 : break;
84 : case NS_ooxml::LN_CT_OLEObject_DrawAspect:
85 54 : m_sDrawAspect = sStringValue;
86 54 : break;
87 : case NS_ooxml::LN_CT_OLEObject_ObjectID:
88 54 : m_sObjectId = sStringValue;
89 54 : break;
90 : case NS_ooxml::LN_CT_OLEObject_r_id:
91 54 : m_sr_id = sStringValue;
92 54 : break;
93 : case NS_ooxml::LN_inputstream:
94 57 : rVal.getAny() >>= m_xInputStream;
95 57 : break;
96 : case NS_ooxml::LN_CT_Object_dxaOrig:
97 58 : m_nDxaOrig = rVal.getInt();
98 58 : break;
99 : case NS_ooxml::LN_CT_Object_dyaOrig:
100 58 : m_nDyaOrig = rVal.getInt();
101 58 : break;
102 : case NS_ooxml::LN_shape:
103 : {
104 294 : uno::Reference< drawing::XShape > xTempShape;
105 294 : rVal.getAny() >>= xTempShape;
106 294 : if( xTempShape.is() )
107 : {
108 294 : m_xShape.set( xTempShape );
109 294 : uno::Reference< beans::XPropertySet > xShapeProps( xTempShape, uno::UNO_QUERY );
110 294 : PropertyNameSupplier& rNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
111 :
112 : try
113 : {
114 : // Shapes in the header or footer should be in the background.
115 294 : if (m_rDomainMapper.IsInHeaderFooter())
116 83 : xShapeProps->setPropertyValue("Opaque", uno::makeAny(false));
117 :
118 294 : m_aShapeSize = xTempShape->getSize();
119 294 : m_aShapePosition = xTempShape->getPosition();
120 :
121 219 : xShapeProps->getPropertyValue( rNameSupplier.GetName( PROP_BITMAP ) ) >>= m_xReplacement;
122 : }
123 75 : catch( const uno::Exception& e )
124 : {
125 : SAL_WARN("writerfilter", "Exception in OLE Handler: " << e.Message);
126 294 : }
127 : // No need to set the wrapping here as it's either set in oox or will be set later
128 294 : }
129 : }
130 294 : break;
131 : default:
132 : OSL_FAIL( "unknown attribute");
133 794 : }
134 794 : }
135 :
136 :
137 114 : void OLEHandler::lcl_sprm(Sprm & rSprm)
138 : {
139 114 : sal_uInt32 nSprmId = rSprm.getId();
140 114 : switch( nSprmId )
141 : {
142 : case NS_ooxml::LN_OLEObject_OLEObject:
143 : {
144 57 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
145 57 : if( pProperties.get())
146 : {
147 57 : pProperties->resolve(*this);
148 57 : }
149 : }
150 57 : break;
151 : case NS_ooxml::LN_wrap_wrap:
152 : {
153 37 : writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
154 37 : if ( pProperties.get( ) )
155 : {
156 37 : WrapHandlerPtr pHandler( new WrapHandler );
157 37 : pProperties->resolve( *pHandler );
158 :
159 37 : m_nWrapMode = pHandler->getWrapMode( );
160 :
161 : try
162 : {
163 37 : uno::Reference< beans::XPropertySet > xShapeProps( m_xShape, uno::UNO_QUERY_THROW );
164 37 : PropertyNameSupplier& rNameSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
165 :
166 37 : xShapeProps->setPropertyValue(
167 : rNameSupplier.GetName( PROP_SURROUND ),
168 37 : uno::makeAny( m_nWrapMode ) );
169 : }
170 0 : catch( const uno::Exception& e )
171 : {
172 : SAL_WARN("writerfilter", "Exception in OLE Handler: " << e.Message);
173 37 : }
174 37 : }
175 : }
176 37 : break;
177 : default:
178 : {
179 : OSL_FAIL( "unknown attribute");
180 : }
181 : }
182 114 : }
183 :
184 :
185 60 : void OLEHandler::saveInteropProperties(uno::Reference<text::XTextDocument> const& xTextDocument, const OUString& sObjectName, const OUString& sOldObjectName)
186 : {
187 : static const char sEmbeddingsPropName[] = "EmbeddedObjects";
188 :
189 : // get interop grab bag from document
190 60 : uno::Reference< beans::XPropertySet > xDocProps( xTextDocument, uno::UNO_QUERY );
191 120 : comphelper::SequenceAsHashMap aGrabBag(xDocProps->getPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG));
192 :
193 : // get EmbeddedObjects property inside grab bag
194 120 : comphelper::SequenceAsHashMap objectsList;
195 60 : if (aGrabBag.find(sEmbeddingsPropName) != aGrabBag.end())
196 13 : objectsList << aGrabBag[sEmbeddingsPropName];
197 :
198 120 : uno::Sequence< beans::PropertyValue > aGrabBagAttribute(2);
199 60 : aGrabBagAttribute[0].Name = "ProgID";
200 60 : aGrabBagAttribute[0].Value = uno::Any( m_sProgId );
201 60 : aGrabBagAttribute[1].Name = "DrawAspect";
202 60 : aGrabBagAttribute[1].Value = uno::Any( m_sDrawAspect );
203 :
204 : // If we got an "old name", erase that first.
205 60 : if (!sOldObjectName.isEmpty())
206 : {
207 5 : comphelper::SequenceAsHashMap::iterator it = objectsList.find(sOldObjectName);
208 5 : if (it != objectsList.end())
209 5 : objectsList.erase(it);
210 : }
211 :
212 60 : objectsList[sObjectName] = uno::Any( aGrabBagAttribute );
213 :
214 : // put objects list back into the grab bag
215 60 : aGrabBag[sEmbeddingsPropName] = uno::Any(objectsList.getAsConstPropertyValueList());
216 :
217 : // put grab bag back into the document
218 120 : xDocProps->setPropertyValue(UNO_NAME_MISC_OBJ_INTEROPGRABBAG, uno::Any(aGrabBag.getAsConstPropertyValueList()));
219 60 : }
220 :
221 5 : void OLEHandler::importStream(uno::Reference<uno::XComponentContext> xComponentContext, uno::Reference<text::XTextDocument> xTextDocument, uno::Reference<text::XTextContent> xOLE)
222 : {
223 5 : OUString aFilterService;
224 5 : if (m_sProgId == "Word.Document.12")
225 3 : aFilterService = "com.sun.star.comp.Writer.WriterFilter";
226 2 : else if (m_sProgId == "Equation.3")
227 2 : aFilterService = "com.sun.star.comp.Math.MathTypeFilter";
228 : else
229 : SAL_WARN("writerfilter", "OLEHandler::importStream: unhandled m_sProgId: " << m_sProgId);
230 :
231 5 : if (!m_xInputStream.is() || aFilterService.isEmpty())
232 5 : return;
233 :
234 : // Create the filter service.
235 10 : uno::Reference<uno::XInterface> xInterface = xComponentContext->getServiceManager()->createInstanceWithContext(aFilterService, xComponentContext);
236 :
237 : // Set target document.
238 10 : uno::Reference<document::XImporter> xImporter(xInterface, uno::UNO_QUERY);
239 10 : uno::Reference<document::XEmbeddedObjectSupplier> xSupplier(xOLE, uno::UNO_QUERY);
240 10 : uno::Reference<lang::XComponent> xEmbeddedObject(xSupplier->getEmbeddedObject(), uno::UNO_QUERY);
241 5 : xImporter->setTargetDocument( xEmbeddedObject );
242 :
243 : // Import the input stream.
244 10 : utl::MediaDescriptor aMediaDescriptor;
245 5 : aMediaDescriptor["InputStream"] <<= m_xInputStream;
246 10 : uno::Reference<document::XFilter> xFilter(xInterface, uno::UNO_QUERY);
247 5 : xFilter->filter(aMediaDescriptor.getAsConstPropertyValueList());
248 :
249 : // Now that the data is imported, update the (typically) changed stream name.
250 10 : uno::Reference<beans::XPropertySet> xPropertySet(xOLE, uno::UNO_QUERY);
251 10 : saveInteropProperties(xTextDocument, xPropertySet->getPropertyValue("StreamName").get<OUString>(), m_aURL);
252 : }
253 :
254 55 : OUString OLEHandler::getCLSID(uno::Reference<uno::XComponentContext> xComponentContext) const
255 : {
256 55 : OUString aRet;
257 :
258 : // See officecfg/registry/data/org/openoffice/Office/Embedding.xcu.
259 55 : if (m_sProgId == "Word.Document.12")
260 : {
261 3 : if (officecfg::Office::Common::Filter::Microsoft::Import::WinWordToWriter::get(xComponentContext))
262 3 : aRet = "8BC6B165-B1B2-4EDD-aa47-dae2ee689dd6";
263 : }
264 52 : else if (m_sProgId == "Equation.3")
265 : {
266 5 : if (officecfg::Office::Common::Filter::Microsoft::Import::MathTypeToMath::get(xComponentContext))
267 2 : aRet = "078B7ABA-54FC-457F-8551-6147E776A997";
268 : }
269 : else
270 : SAL_WARN("writerfilter", "OLEHandler::getCLSID: unhandled m_sProgId: " << m_sProgId);
271 :
272 55 : return aRet;
273 : }
274 :
275 57 : OUString OLEHandler::copyOLEOStream(
276 : uno::Reference<text::XTextDocument> const& xTextDocument)
277 : {
278 57 : OUString sRet;
279 57 : if( !m_xInputStream.is( ) )
280 0 : return sRet;
281 : try
282 : {
283 57 : uno::Reference < lang::XMultiServiceFactory > xFactory(xTextDocument, uno::UNO_QUERY_THROW);
284 : uno::Reference< document::XEmbeddedObjectResolver > xEmbeddedResolver(
285 110 : xFactory->createInstance("com.sun.star.document.ImportEmbeddedObjectResolver"), uno::UNO_QUERY_THROW );
286 : //hack to work with the ImportEmbeddedObjectResolver
287 : static sal_Int32 nObjectCount = 100;
288 110 : uno::Reference< container::XNameAccess > xNA( xEmbeddedResolver, uno::UNO_QUERY_THROW );
289 110 : OUString aURL("Obj");
290 55 : aURL += OUString::number( nObjectCount++ );
291 110 : uno::Reference < io::XOutputStream > xOLEStream;
292 55 : if( (xNA->getByName( aURL ) >>= xOLEStream) && xOLEStream.is() )
293 : {
294 55 : const sal_Int32 nReadRequest = 0x1000;
295 55 : uno::Sequence< sal_Int8 > aData;
296 :
297 : while( true )
298 : {
299 468 : sal_Int32 nRead = m_xInputStream->readBytes( aData, nReadRequest );
300 468 : xOLEStream->writeBytes( aData );
301 468 : if( nRead < nReadRequest )
302 : {
303 55 : xOLEStream->closeOutput();
304 55 : break;
305 : }
306 : }
307 :
308 55 : saveInteropProperties( xTextDocument, aURL );
309 :
310 : static const char sProtocol[] = "vnd.sun.star.EmbeddedObject:";
311 110 : OUString aPersistName( xEmbeddedResolver->resolveEmbeddedObjectURL( aURL ) );
312 110 : sRet = aPersistName.copy( strlen(sProtocol) );
313 :
314 : }
315 110 : uno::Reference< lang::XComponent > xComp( xEmbeddedResolver, uno::UNO_QUERY_THROW );
316 55 : xComp->dispose();
317 110 : m_aURL = aURL;
318 : }
319 2 : catch( const uno::Exception& )
320 : {
321 : OSL_FAIL("exception in OLEHandler::createOLEObject");
322 : }
323 57 : return sRet;
324 : }
325 :
326 : } //namespace dmapper
327 : } //namespace writerfilter
328 :
329 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|