related tdf#162786: Add cacert.pem
[LibreOffice.git] / filter / source / msfilter / msoleexp.cxx
blob90f04e6ad575356f8c7d6d819cdbe698cd35710f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <com/sun/star/uno/Reference.hxx>
21 #include <com/sun/star/uno/Sequence.hxx>
22 #include <com/sun/star/embed/XEmbeddedObject.hpp>
23 #include <com/sun/star/embed/XEmbedPersist.hpp>
24 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
25 #include <com/sun/star/embed/EmbedStates.hpp>
26 #include <com/sun/star/frame/XStorable.hpp>
27 #include <com/sun/star/awt/Size.hpp>
28 #include <com/sun/star/embed/Aspects.hpp>
29 #include <comphelper/classids.hxx>
30 #include <sfx2/docfilt.hxx>
31 #include <sfx2/fcontnr.hxx>
32 #include <sot/formats.hxx>
33 #include <sot/storage.hxx>
34 #include <comphelper/diagnose_ex.hxx>
35 #include <comphelper/fileformat.h>
36 #include <comphelper/propertyvalue.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <comphelper/storagehelper.hxx>
39 #include <svtools/embedhlp.hxx>
40 #include <filter/msfilter/msdffimp.hxx>
42 #include <filter/msfilter/msoleexp.hxx>
44 using namespace ::com::sun::star;
46 static SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName )
48 if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
49 return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 );
50 else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
51 return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 );
52 else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
53 return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 );
54 else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
55 return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 );
56 else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
57 return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 );
58 else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
59 return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 );
61 return SvGlobalName();
64 static OUString GetStorageType( const SvGlobalName& aEmbName )
66 if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
67 return u"LibreOffice.MathDocument.1"_ustr;
68 else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
69 return u"LibreOffice.WriterDocument.1"_ustr;
70 else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
71 return u"LibreOffice.CalcDocument.1"_ustr;
72 else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
73 return u"LibreOffice.DrawDocument.1"_ustr;
74 else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
75 return u"LibreOffice.ImpressDocument.1"_ustr;
76 else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
77 return u"LibreOffice.ChartDocument.1"_ustr;
78 return OUString();
81 void SvxMSExportOLEObjects::ExportOLEObject( const css::uno::Reference < css::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
83 svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
84 ExportOLEObject( aObj, rDestStg );
87 void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef const & rObj, SotStorage& rDestStg )
89 SvGlobalName aOwnGlobalName;
90 SvGlobalName aObjName( rObj->getClassID() );
91 std::shared_ptr<const SfxFilter> pExpFilter;
93 static struct ObjExpType {
94 sal_uInt32 nFlag;
95 const char* pFilterNm;
96 // GlobalNameId
97 struct GlobalNameIds {
98 sal_uInt32 n1;
99 sal_uInt16 n2, n3;
100 sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
102 aGlNmIds[4];
103 } const aArr[] = {
104 { OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
105 {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50},
106 {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}},
107 { OLE_STARWRITER_2_WINWORD, "MS Word 97",
108 {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50},
109 {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}},
110 { OLE_STARCALC_2_EXCEL, "MS Excel 97",
111 {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50},
112 {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}},
113 { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
114 {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50},
115 {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}},
116 { 0, "",
117 {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50},
118 {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}},
119 { 0, "",
120 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
121 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entries here.
123 { 0xffff,nullptr,
124 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},
125 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}}
128 for( const ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
130 for (const ObjExpType::GlobalNameIds& rId : pArr->aGlNmIds)
132 SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
133 rId.b8, rId.b9, rId.b10, rId.b11,
134 rId.b12, rId.b13, rId.b14, rId.b15 );
135 if( aObjName == aGlbNm )
137 aOwnGlobalName = aGlbNm;
139 // flags for checking if conversion is wanted at all (SaveOptions?!)
140 if( nConvertFlags & pArr->nFlag )
142 pExpFilter = SfxFilterMatcher().GetFilter4FilterName(OUString::createFromAscii(pArr->pFilterNm));
143 break;
150 if( pExpFilter ) // use this filter for the export
154 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
155 rObj->changeState( embed::EmbedStates::RUNNING );
156 //TODO/LATER: is stream instead of outputstream a better choice?!
157 //TODO/LATER: a "StoreTo" method at embedded object would be nice
158 SvStream* pStream = new SvMemoryStream;
159 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
160 uno::Sequence < beans::PropertyValue > aSeq{
161 comphelper::makePropertyValue(u"OutputStream"_ustr, xOut),
162 comphelper::makePropertyValue(u"FilterName"_ustr, pExpFilter->GetName())
164 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
167 xStor->storeToURL( u"private:stream"_ustr, aSeq );
169 catch( const uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
171 rtl::Reference<SotStorage> xOLEStor = new SotStorage( pStream, true );
172 xOLEStor->CopyTo( &rDestStg );
173 rDestStg.Commit();
175 catch( const uno::Exception& )
177 // TODO/LATER: Error handling
178 OSL_FAIL( "The object could not be exported!" );
181 else if( aOwnGlobalName != SvGlobalName() )
183 // own format, maybe SO6 format or lower
184 SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
185 if ( aEmbName != SvGlobalName() )
187 // this is a SO6 embedded object, save in old binary format
188 rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
189 rDestStg.SetClass( aEmbName,
190 SotClipboardFormatId::EMBEDDED_OBJ_OLE,
191 GetStorageType( aEmbName ) );
192 rtl::Reference<SotStorageStream> xExtStm = rDestStg.OpenSotStream(
193 u"properties_stream"_ustr);
195 bool bExtentSuccess = false;
196 if( !xExtStm->GetError() )
198 // write extent
199 //TODO/MBA: check if writing a size is enough
200 if( rObj.GetObject().is() )
202 // MSOLE objects don't need to be in running state for VisualArea access
203 awt::Size aSize;
206 // this is an own object, the content size must be stored in the
207 // extension stream
208 aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
210 catch( const embed::NoVisualAreaSizeException& )
212 OSL_FAIL( "Could not get visual area size!" );
213 aSize.Width = 5000;
214 aSize.Height = 5000;
216 catch( const uno::Exception& )
218 TOOLS_WARN_EXCEPTION(
219 "filter.ms", "Unexpected exception while getting visual area size!");
220 aSize.Width = 5000;
221 aSize.Height = 5000;
224 sal_Int32 pRect[4];
225 pRect[0] = 0;
226 pRect[1] = aSize.Width;
227 pRect[2] = 0;
228 pRect[3] = aSize.Height;
230 sal_Int8 aWriteSet[16];
231 for ( int ind = 0; ind < 4; ind++ )
233 sal_Int32 nVal = pRect[ind];
234 for ( int nByte = 0; nByte < 4; nByte++ )
236 aWriteSet[ind*4+nByte] = static_cast<sal_Int8>(nVal) % 0x100;
237 nVal /= 0x100;
241 bExtentSuccess = (xExtStm->WriteBytes(aWriteSet, 16) == 16);
245 if ( bExtentSuccess )
247 rtl::Reference<SotStorageStream> xEmbStm = rDestStg.OpenSotStream(
248 u"package_stream"_ustr);
249 if( !xEmbStm->GetError() )
253 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
254 rObj->changeState( embed::EmbedStates::RUNNING );
255 //TODO/LATER: is stream instead of outputstream a better choice?!
256 //TODO/LATER: a "StoreTo" method at embedded object would be nice
257 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
258 uno::Sequence < beans::PropertyValue > aSeq{ comphelper::makePropertyValue(
259 u"OutputStream"_ustr, xOut) };
260 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
261 xStor->storeToURL( u"private:stream"_ustr, aSeq );
263 catch( const uno::Exception& )
265 // TODO/LATER: Error handling
266 OSL_FAIL( "The object could not be exported!" );
271 else
273 OSL_FAIL("Own binary format inside own container document!");
276 else
278 // alien objects
279 //TODO/LATER: a "StoreTo" method at embedded object would be nice
280 rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
281 uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
282 uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
283 if ( xPers.is() )
285 uno::Sequence < beans::PropertyValue > aEmptySeq;
286 OUString aTempName( u"bla"_ustr );
289 xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
291 catch ( const uno::Exception& )
294 rtl::Reference<SotStorage> xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, StreamMode::STD_READ );
295 xOLEStor->CopyTo( &rDestStg );
296 rDestStg.Commit();
300 //We never need this stream: See #99809# and #i2179#
301 rDestStg.Remove( SVEXT_PERSIST_STREAM );
305 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */