bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / msfilter / msoleexp.cxx
blob11bbf0efba6c5073504643d569318eb13e3fc695
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/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/XEmbedPersist.hpp>
27 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
28 #include <com/sun/star/embed/EmbedStates.hpp>
29 #include <com/sun/star/frame/XStorable.hpp>
30 #include <com/sun/star/awt/Size.hpp>
31 #include <com/sun/star/embed/Aspects.hpp>
32 #include <comphelper/classids.hxx>
33 #include <sfx2/objsh.hxx>
34 #include <sfx2/docfac.hxx>
35 #include <sfx2/docfilt.hxx>
36 #include <sfx2/docfile.hxx>
37 #include <sfx2/fcontnr.hxx>
38 #include <sot/formats.hxx>
39 #include <comphelper/processfactory.hxx>
40 #include <unotools/streamwrap.hxx>
41 #include <comphelper/storagehelper.hxx>
42 #include <svtools/embedhlp.hxx>
43 #include <filter/msfilter/msdffimp.hxx> // extern sichtbare Header-Datei
45 #include "filter/msfilter/msoleexp.hxx"
47 using namespace ::com::sun::star;
49 SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName )
51 if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
52 return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 );
53 else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
54 return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 );
55 else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
56 return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 );
57 else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
58 return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 );
59 else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
60 return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 );
61 else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
62 return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 );
64 return SvGlobalName();
67 OUString GetStorageType( const SvGlobalName& aEmbName )
69 if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
70 return OUString( "LibreOffice.MathDocument.1" );
71 else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
72 return OUString( "LibreOffice.WriterDocument.1" );
73 else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
74 return OUString( "LibreOffice.CalcDocument.1" );
75 else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
76 return OUString( "LibreOffice.DrawDocument.1" );
77 else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
78 return OUString( "LibreOffice.ImpressDocument.1" );
79 else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
80 return OUString("LibreOffice.ChartDocument.1");
81 return OUString();
84 sal_Bool UseOldMSExport()
86 uno::Reference< lang::XMultiServiceFactory > xProvider(
87 configuration::theDefaultProvider::get(
88 comphelper::getProcessComponentContext()));
89 try {
90 uno::Sequence< uno::Any > aArg( 1 );
91 aArg[0] <<= OUString( "/org.openoffice.Office.Common/InternalMSExport" );
92 uno::Reference< container::XNameAccess > xNameAccess(
93 xProvider->createInstanceWithArguments(
94 "com.sun.star.configuration.ConfigurationUpdateAccess",
95 aArg ),
96 uno::UNO_QUERY );
97 if ( xNameAccess.is() )
99 uno::Any aResult = xNameAccess->getByName( "UseOldExport" );
101 sal_Bool bResult = sal_Bool();
102 if ( aResult >>= bResult )
103 return bResult;
106 catch( const uno::Exception& )
110 OSL_FAIL( "Could not get access to configuration entry!\n" );
111 return sal_False;
114 void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
116 svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
117 ExportOLEObject( aObj, rDestStg );
120 void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvStorage& rDestStg )
122 SvGlobalName aOwnGlobalName;
123 SvGlobalName aObjName( rObj->getClassID() );
124 const SfxFilter* pExpFilter = NULL;
126 static struct _ObjExpType {
127 sal_uInt32 nFlag;
128 const char* pFilterNm;
129 // GlobalNameId
130 struct _GlobalNameIds {
131 sal_uInt32 n1;
132 sal_uInt16 n2, n3;
133 sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
135 aGlNmIds[4];
136 } aArr[] = {
137 { OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
138 {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50},
139 {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}},
140 { OLE_STARWRITER_2_WINWORD, "MS Word 97",
141 {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50},
142 {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}},
143 { OLE_STARCALC_2_EXCEL, "MS Excel 97",
144 {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50},
145 {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}},
146 { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
147 {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50},
148 {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}},
149 { 0, "",
150 {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50},
151 {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}},
152 { 0, "",
153 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
154 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entrys here.
156 { 0xffff,0,
157 {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},
158 {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}}
161 for( const _ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
163 for ( int n = 0; n < 4; ++n )
165 const _ObjExpType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
166 SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
167 rId.b8, rId.b9, rId.b10, rId.b11,
168 rId.b12, rId.b13, rId.b14, rId.b15 );
169 if( aObjName == aGlbNm )
171 aOwnGlobalName = aGlbNm;
173 // flags for checking if conversion is wanted at all (SaveOptions?!)
174 if( GetFlags() & pArr->nFlag )
176 pExpFilter = SfxFilterMatcher().GetFilter4FilterName(OUString::createFromAscii(pArr->pFilterNm));
177 break;
184 if( pExpFilter ) // use this filter for the export
188 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
189 rObj->changeState( embed::EmbedStates::RUNNING );
190 //TODO/LATER: is stream instead of outputstream a better choice?!
191 //TODO/LATER: a "StoreTo" method at embedded object would be nice
192 uno::Sequence < beans::PropertyValue > aSeq(2);
193 SvStream* pStream = new SvMemoryStream;
194 aSeq[0].Name = OUString( "OutputStream" );
195 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
196 aSeq[0].Value <<= xOut;
197 aSeq[1].Name = OUString( "FilterName" );
198 aSeq[1].Value <<= OUString( pExpFilter->GetName() );
199 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
202 xStor->storeToURL( "private:stream", aSeq );
204 catch( const uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
206 SotStorageRef xOLEStor = new SotStorage( pStream, sal_True );
207 xOLEStor->CopyTo( &rDestStg );
208 rDestStg.Commit();
210 catch( const uno::Exception& )
212 // TODO/LATER: Error handling
213 OSL_FAIL( "The object could not be exported!" );
216 else if( aOwnGlobalName != SvGlobalName() )
218 // own format, maybe SO6 format or lower
219 SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
220 if ( aEmbName != SvGlobalName() && !UseOldMSExport() )
222 // this is a SO6 embedded object, save in old binary format
223 rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
224 rDestStg.SetClass( aEmbName,
225 SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE,
226 GetStorageType( aEmbName ) );
227 SotStorageStreamRef xExtStm = rDestStg.OpenSotStream(
228 OUString( "properties_stream" ),
229 STREAM_STD_READWRITE);
231 sal_Bool bExtentSuccess = sal_False;
232 if( !xExtStm->GetError() )
234 // write extent
235 //TODO/MBA: check if writing a size is enough
236 if( rObj.GetObject().is() )
238 // MSOLE objects don't need to be in running state for VisualArea access
239 awt::Size aSize;
242 // this is an own object, the content size must be stored in the
243 // extension stream
244 aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
246 catch( const embed::NoVisualAreaSizeException& )
248 OSL_FAIL( "Could not get visual area size!\n" );
249 aSize.Width = 5000;
250 aSize.Height = 5000;
252 catch( const uno::Exception& )
254 OSL_FAIL( "Unexpected exception while getting visual area size!\n" );
255 aSize.Width = 5000;
256 aSize.Height = 5000;
259 sal_Int32 pRect[4];
260 pRect[0] = 0;
261 pRect[1] = aSize.Width;
262 pRect[2] = 0;
263 pRect[3] = aSize.Height;
265 sal_Int8 aWriteSet[16];
266 for ( int ind = 0; ind < 4; ind++ )
268 sal_Int32 nVal = pRect[ind];
269 for ( int nByte = 0; nByte < 4; nByte++ )
271 aWriteSet[ind*4+nByte] = (sal_Int8) nVal % 0x100;
272 nVal /= 0x100;
276 bExtentSuccess = ( xExtStm->Write( aWriteSet, 16 ) == 16 );
280 if ( bExtentSuccess )
282 SotStorageStreamRef xEmbStm = rDestStg.OpenSotStream(
283 OUString( "package_stream" ),
284 STREAM_STD_READWRITE);
285 if( !xEmbStm->GetError() )
289 if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
290 rObj->changeState( embed::EmbedStates::RUNNING );
291 //TODO/LATER: is stream instead of outputstream a better choice?!
292 //TODO/LATER: a "StoreTo" method at embedded object would be nice
293 uno::Sequence < beans::PropertyValue > aSeq(1);
294 aSeq[0].Name = OUString( "OutputStream" );
295 ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
296 aSeq[0].Value <<= xOut;
297 uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
298 xStor->storeToURL( "private:stream", aSeq );
300 catch( const uno::Exception& )
302 // TODO/LATER: Error handling
303 OSL_FAIL( "The object could not be exported!" );
308 else
310 OSL_FAIL("Own binary format inside own container document!");
313 else
315 // alien objects
316 //TODO/LATER: a "StoreTo" method at embedded object would be nice
317 rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
318 uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
319 uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
320 if ( xPers.is() )
322 uno::Sequence < beans::PropertyValue > aEmptySeq;
323 OUString aTempName( "bla" );
326 xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
328 catch ( const uno::Exception& )
331 SotStorageRef xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, STREAM_STD_READ );
332 xOLEStor->CopyTo( &rDestStg );
333 rDestStg.Commit();
337 //We never need this stream: See #99809# and #i2179#
338 rDestStg.Remove( OUString(SVEXT_PERSIST_STREAM) );
343 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */