LibreOffice Module filter (master) 1
msoleexp.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
20#include <com/sun/star/uno/Reference.hxx>
21#include <com/sun/star/uno/Sequence.hxx>
22#include <com/sun/star/uno/Any.hxx>
23#include <com/sun/star/lang/XMultiServiceFactory.hpp>
24#include <com/sun/star/configuration/theDefaultProvider.hpp>
25#include <com/sun/star/container/XNameAccess.hpp>
26#include <com/sun/star/embed/XEmbeddedObject.hpp>
27#include <com/sun/star/embed/XEmbedPersist.hpp>
28#include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
29#include <com/sun/star/embed/EmbedStates.hpp>
30#include <com/sun/star/frame/XStorable.hpp>
31#include <com/sun/star/awt/Size.hpp>
32#include <com/sun/star/embed/Aspects.hpp>
34#include <sfx2/docfilt.hxx>
35#include <sfx2/fcontnr.hxx>
36#include <sot/formats.hxx>
37#include <sot/storage.hxx>
44#include <svtools/embedhlp.hxx>
46
48
49using namespace ::com::sun::star;
50
52{
53 if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
55 else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
57 else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
59 else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
61 else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
63 else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
65
66 return SvGlobalName();
67}
68
69static OUString GetStorageType( const SvGlobalName& aEmbName )
70{
71 if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
72 return "LibreOffice.MathDocument.1";
73 else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
74 return "LibreOffice.WriterDocument.1";
75 else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
76 return "LibreOffice.CalcDocument.1";
77 else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
78 return "LibreOffice.DrawDocument.1";
79 else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
80 return "LibreOffice.ImpressDocument.1";
81 else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
82 return "LibreOffice.ChartDocument.1";
83 return OUString();
84}
85
86static bool UseOldMSExport()
87{
88 uno::Reference< lang::XMultiServiceFactory > xProvider(
89 configuration::theDefaultProvider::get(
91 try {
92 uno::Sequence< uno::Any > aArg{ uno::Any(
93 OUString( "/org.openoffice.Office.Common/InternalMSExport" )) };
94 uno::Reference< container::XNameAccess > xNameAccess(
95 xProvider->createInstanceWithArguments(
96 "com.sun.star.configuration.ConfigurationUpdateAccess",
97 aArg ),
98 uno::UNO_QUERY );
99 if ( xNameAccess.is() )
100 {
101 uno::Any aResult = xNameAccess->getByName( "UseOldExport" );
102
103 bool bResult;
104 if ( aResult >>= bResult )
105 return bResult;
106 }
107 }
108 catch( const uno::Exception& )
109 {
110 }
111
112 OSL_FAIL( "Could not get access to configuration entry!" );
113 return false;
114}
115
116void SvxMSExportOLEObjects::ExportOLEObject( const css::uno::Reference < css::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
117{
118 svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
119 ExportOLEObject( aObj, rDestStg );
120}
121
123{
124 SvGlobalName aOwnGlobalName;
125 SvGlobalName aObjName( rObj->getClassID() );
126 std::shared_ptr<const SfxFilter> pExpFilter;
127 {
128 static struct ObjExpType {
129 sal_uInt32 nFlag;
130 const char* pFilterNm;
131 // GlobalNameId
132 struct GlobalNameIds {
133 sal_uInt32 n1;
134 sal_uInt16 n2, n3;
135 sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
136 }
137 aGlNmIds[4];
138 } const aArr[] = {
139 { OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
142 { OLE_STARWRITER_2_WINWORD, "MS Word 97",
145 { OLE_STARCALC_2_EXCEL, "MS Excel 97",
148 { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
151 { 0, "",
154 { 0, "",
155 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
156 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entries here.
157
158 { 0xffff,nullptr,
161 };
162
163 for( const ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
164 {
165 for (const ObjExpType::GlobalNameIds& rId : pArr->aGlNmIds)
166 {
167 SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
168 rId.b8, rId.b9, rId.b10, rId.b11,
169 rId.b12, rId.b13, rId.b14, rId.b15 );
170 if( aObjName == aGlbNm )
171 {
172 aOwnGlobalName = aGlbNm;
173
174 // flags for checking if conversion is wanted at all (SaveOptions?!)
175 if( nConvertFlags & pArr->nFlag )
176 {
177 pExpFilter = SfxFilterMatcher().GetFilter4FilterName(OUString::createFromAscii(pArr->pFilterNm));
178 break;
179 }
180 }
181 }
182 }
183 }
184
185 if( pExpFilter ) // use this filter for the export
186 {
187 try
188 {
189 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
190 rObj->changeState( embed::EmbedStates::RUNNING );
191 //TODO/LATER: is stream instead of outputstream a better choice?!
192 //TODO/LATER: a "StoreTo" method at embedded object would be nice
193 SvStream* pStream = new SvMemoryStream;
194 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
195 uno::Sequence < beans::PropertyValue > aSeq{
196 comphelper::makePropertyValue("OutputStream", xOut),
197 comphelper::makePropertyValue("FilterName", pExpFilter->GetName())
198 };
199 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
200 try
201 {
202 xStor->storeToURL( "private:stream", aSeq );
203 }
204 catch( const uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
205
206 tools::SvRef<SotStorage> xOLEStor = new SotStorage( pStream, true );
207 xOLEStor->CopyTo( &rDestStg );
208 rDestStg.Commit();
209 }
210 catch( const uno::Exception& )
211 {
212 // TODO/LATER: Error handling
213 OSL_FAIL( "The object could not be exported!" );
214 }
215 }
216 else if( aOwnGlobalName != SvGlobalName() )
217 {
218 // own format, maybe SO6 format or lower
219 SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
220 if ( aEmbName != SvGlobalName() && !UseOldMSExport() )
221 {
222 // this is a SO6 embedded object, save in old binary format
224 rDestStg.SetClass( aEmbName,
225 SotClipboardFormatId::EMBEDDED_OBJ_OLE,
226 GetStorageType( aEmbName ) );
228 "properties_stream");
229
230 bool bExtentSuccess = false;
231 if( !xExtStm->GetError() )
232 {
233 // write extent
234 //TODO/MBA: check if writing a size is enough
235 if( rObj.GetObject().is() )
236 {
237 // MSOLE objects don't need to be in running state for VisualArea access
238 awt::Size aSize;
239 try
240 {
241 // this is an own object, the content size must be stored in the
242 // extension stream
243 aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
244 }
245 catch( const embed::NoVisualAreaSizeException& )
246 {
247 OSL_FAIL( "Could not get visual area size!" );
248 aSize.Width = 5000;
249 aSize.Height = 5000;
250 }
251 catch( const uno::Exception& )
252 {
254 "filter.ms", "Unexpected exception while getting visual area size!");
255 aSize.Width = 5000;
256 aSize.Height = 5000;
257 }
258
259 sal_Int32 pRect[4];
260 pRect[0] = 0;
261 pRect[1] = aSize.Width;
262 pRect[2] = 0;
263 pRect[3] = aSize.Height;
264
265 sal_Int8 aWriteSet[16];
266 for ( int ind = 0; ind < 4; ind++ )
267 {
268 sal_Int32 nVal = pRect[ind];
269 for ( int nByte = 0; nByte < 4; nByte++ )
270 {
271 aWriteSet[ind*4+nByte] = static_cast<sal_Int8>(nVal) % 0x100;
272 nVal /= 0x100;
273 }
274 }
275
276 bExtentSuccess = (xExtStm->WriteBytes(aWriteSet, 16) == 16);
277 }
278 }
279
280 if ( bExtentSuccess )
281 {
283 "package_stream");
284 if( !xEmbStm->GetError() )
285 {
286 try
287 {
288 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
289 rObj->changeState( embed::EmbedStates::RUNNING );
290 //TODO/LATER: is stream instead of outputstream a better choice?!
291 //TODO/LATER: a "StoreTo" method at embedded object would be nice
292 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
293 uno::Sequence < beans::PropertyValue > aSeq{ comphelper::makePropertyValue(
294 "OutputStream", xOut) };
295 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
296 xStor->storeToURL( "private:stream", aSeq );
297 }
298 catch( const uno::Exception& )
299 {
300 // TODO/LATER: Error handling
301 OSL_FAIL( "The object could not be exported!" );
302 }
303 }
304 }
305 }
306 else
307 {
308 OSL_FAIL("Own binary format inside own container document!");
309 }
310 }
311 else
312 {
313 // alien objects
314 //TODO/LATER: a "StoreTo" method at embedded object would be nice
316 uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
317 uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
318 if ( xPers.is() )
319 {
320 uno::Sequence < beans::PropertyValue > aEmptySeq;
321 OUString aTempName( "bla" );
322 try
323 {
324 xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
325 }
326 catch ( const uno::Exception& )
327 {}
328
329 tools::SvRef<SotStorage> xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, StreamMode::STD_READ );
330 xOLEStor->CopyTo( &rDestStg );
331 rDestStg.Commit();
332 }
333 }
334
335 //We never need this stream: See #99809# and #i2179#
336 rDestStg.Remove( SVEXT_PERSIST_STREAM );
337}
338
339
340/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::shared_ptr< const SfxFilter > GetFilter4FilterName(const OUString &rName, SfxFilterFlags nMust=SfxFilterFlags::NONE, SfxFilterFlags nDont=SFX_FILTER_NOTINSTALLED) const
bool Remove(const OUString &rEleName)
void SetVersion(sal_Int32 nVersion)
tools::SvRef< SotStorageStream > OpenSotStream(const OUString &rEleName, StreamMode=StreamMode::STD_READWRITE)
bool Commit()
void SetClass(const SvGlobalName &rClass, SotClipboardFormatId bOriginalClipFormat, const OUString &rUserTypeName)
static SotStorage * OpenOLEStorage(css::uno::Reference< css::embed::XStorage > const &xStorage, OUString const &rEleName, StreamMode=StreamMode::STD_READWRITE)
void ExportOLEObject(svt::EmbeddedObjectRef const &rObj, SotStorage &rDestStg)
Definition: msoleexp.cxx:122
sal_uInt32 nConvertFlags
Definition: msoleexp.hxx:45
static css::uno::Reference< css::embed::XStorage > GetTemporaryStorage(const css::uno::Reference< css::uno::XComponentContext > &rxContext=css::uno::Reference< css::uno::XComponentContext >())
#define SO3_SW_CLASSID_40
#define SO3_SDRAW_CLASSID_50
#define SO3_SCH_CLASSID_40
#define SO3_SC_CLASSID_30
#define SO3_SDRAW_CLASSID_60
#define SO3_SIMPRESS_CLASSID_50
#define SO3_SW_CLASSID_50
#define SO3_SM_CLASSID_50
#define SO3_SC_CLASSID_60
#define SO3_SIMPRESS_CLASSID_30
#define SO3_SM_CLASSID_60
#define SO3_SW_OLE_EMBED_CLASSID_8
#define SO3_SCH_CLASSID_30
#define SO3_SCH_CLASSID_50
#define SO3_SW_CLASSID_30
#define SO3_SW_CLASSID_60
#define SO3_SC_CLASSID_40
#define SO3_SCH_CLASSID_60
#define SO3_SIMPRESS_CLASSID_40
#define SO3_SM_CLASSID_30
#define SO3_SM_CLASSID_40
#define SO3_SIMPRESS_CLASSID_60
#define SO3_SM_OLE_EMBED_CLASSID_8
#define SO3_SDRAW_OLE_EMBED_CLASSID_8
#define SO3_SC_CLASSID_50
#define SO3_SCH_OLE_EMBED_CLASSID_8
#define SO3_SC_OLE_EMBED_CLASSID_8
#define SO3_SIMPRESS_OLE_EMBED_CLASSID_8
const css::uno::Reference< css::embed::XEmbeddedObject > & GetObject() const
#define TOOLS_WARN_EXCEPTION(area, stream)
#define SOFFICE_FILEFORMAT_31
Sequence< sal_Int8 > aSeq
int n2
int n1
constexpr OUStringLiteral SVEXT_PERSIST_STREAM
Definition: msdffimp.hxx:123
static SvGlobalName GetEmbeddedVersion(const SvGlobalName &aAppName)
Definition: msoleexp.cxx:51
static OUString GetStorageType(const SvGlobalName &aEmbName)
Definition: msoleexp.cxx:69
static bool UseOldMSExport()
Definition: msoleexp.cxx:86
#define OLE_STARIMPRESS_2_POWERPOINT
Definition: msoleexp.hxx:41
#define OLE_STARWRITER_2_WINWORD
Definition: msoleexp.hxx:39
#define OLE_STARCALC_2_EXCEL
Definition: msoleexp.hxx:40
#define OLE_STARMATH_2_MATHTYPE
Definition: msoleexp.hxx:38
sal_uInt32 n3
Shape IDs per cluster in DGG atom.
Reference< XComponentContext > getProcessComponentContext()
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
const SvxPageUsage aArr[]
unsigned char sal_uInt8
signed char sal_Int8