Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <com/sun/star/uno/Reference.hxx>
30 : : #include <com/sun/star/uno/Sequence.hxx>
31 : : #include <com/sun/star/uno/Any.hxx>
32 : : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
33 : : #include <com/sun/star/configuration/theDefaultProvider.hpp>
34 : : #include <com/sun/star/container/XNameAccess.hpp>
35 : : #include <com/sun/star/embed/XEmbedPersist.hpp>
36 : : #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
37 : : #include <com/sun/star/embed/EmbedStates.hpp>
38 : : #include <com/sun/star/frame/XStorable.hpp>
39 : : #include <com/sun/star/awt/Size.hpp>
40 : : #include <com/sun/star/embed/Aspects.hpp>
41 : : #include <sot/clsids.hxx>
42 : : #include <sfx2/objsh.hxx>
43 : : #include <sfx2/docfac.hxx>
44 : : #include <sfx2/docfilt.hxx>
45 : : #include <sfx2/docfile.hxx>
46 : : #include <sfx2/fcontnr.hxx>
47 : : #include <sot/formats.hxx>
48 : : #include <comphelper/processfactory.hxx>
49 : : #include <unotools/streamwrap.hxx>
50 : : #include <comphelper/storagehelper.hxx>
51 : : #include <svtools/embedhlp.hxx>
52 : : #include <filter/msfilter/msdffimp.hxx> // extern sichtbare Header-Datei
53 : :
54 : : #include "filter/msfilter/msoleexp.hxx"
55 : :
56 : : using namespace ::com::sun::star;
57 : :
58 : 0 : SvGlobalName GetEmbeddedVersion( const SvGlobalName& aAppName )
59 : : {
60 [ # # ][ # # ]: 0 : if ( aAppName == SvGlobalName( SO3_SM_CLASSID_60 ) )
61 : 0 : return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 );
62 [ # # ][ # # ]: 0 : else if ( aAppName == SvGlobalName( SO3_SW_CLASSID_60 ) )
63 : 0 : return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 );
64 [ # # ][ # # ]: 0 : else if ( aAppName == SvGlobalName( SO3_SC_CLASSID_60 ) )
65 : 0 : return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 );
66 [ # # ][ # # ]: 0 : else if ( aAppName == SvGlobalName( SO3_SDRAW_CLASSID_60 ) )
67 : 0 : return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 );
68 [ # # ][ # # ]: 0 : else if ( aAppName == SvGlobalName( SO3_SIMPRESS_CLASSID_60 ) )
69 : 0 : return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 );
70 [ # # ][ # # ]: 0 : else if ( aAppName == SvGlobalName( SO3_SCH_CLASSID_60 ) )
71 : 0 : return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 );
72 : :
73 : 0 : return SvGlobalName();
74 : : }
75 : :
76 : 0 : String GetStorageType( const SvGlobalName& aEmbName )
77 : : {
78 [ # # ][ # # ]: 0 : if ( aEmbName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
79 [ # # ]: 0 : return rtl::OUString("LibreOffice.MathDocument.1");
80 [ # # ][ # # ]: 0 : else if ( aEmbName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
81 [ # # ]: 0 : return rtl::OUString("LibreOffice.WriterDocument.1");
82 [ # # ][ # # ]: 0 : else if ( aEmbName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
83 [ # # ]: 0 : return rtl::OUString("LibreOffice.CalcDocument.1");
84 [ # # ][ # # ]: 0 : else if ( aEmbName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
85 [ # # ]: 0 : return rtl::OUString("LibreOffice.DrawDocument.1");
86 [ # # ][ # # ]: 0 : else if ( aEmbName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
87 [ # # ]: 0 : return rtl::OUString("LibreOffice.ImpressDocument.1");
88 [ # # ][ # # ]: 0 : else if ( aEmbName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
89 [ # # ]: 0 : return rtl::OUString("LibreOffice.ChartDocument.1");
90 [ # # ]: 0 : return rtl::OUString();
91 : : }
92 : :
93 : 0 : sal_Bool UseOldMSExport()
94 : : {
95 : : uno::Reference< lang::XMultiServiceFactory > xProvider(
96 : : configuration::theDefaultProvider::get(
97 [ # # ][ # # ]: 0 : comphelper::getProcessComponentContext()));
98 : : try {
99 [ # # ]: 0 : uno::Sequence< uno::Any > aArg( 1 );
100 [ # # ][ # # ]: 0 : aArg[0] <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/InternalMSExport") );
[ # # ]
101 : : uno::Reference< container::XNameAccess > xNameAccess(
102 [ # # ]: 0 : xProvider->createInstanceWithArguments(
103 : : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
104 : 0 : aArg ),
105 [ # # ][ # # ]: 0 : uno::UNO_QUERY );
[ # # ]
106 [ # # ]: 0 : if ( xNameAccess.is() )
107 : : {
108 [ # # ]: 0 : uno::Any aResult = xNameAccess->getByName(
109 [ # # ][ # # ]: 0 : rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseOldExport" ) ) );
110 : :
111 : 0 : sal_Bool bResult = sal_Bool();
112 [ # # ]: 0 : if ( aResult >>= bResult )
113 [ # # ]: 0 : return bResult;
114 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
115 : : }
116 [ # # ]: 0 : catch( const uno::Exception& )
117 : : {
118 : : }
119 : :
120 : : OSL_FAIL( "Could not get access to configuration entry!\n" );
121 : 0 : return sal_False;
122 : : }
123 : :
124 : 0 : void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject>& rObj, SotStorage& rDestStg )
125 : : {
126 [ # # ]: 0 : svt::EmbeddedObjectRef aObj( rObj, embed::Aspects::MSOLE_CONTENT );
127 [ # # ][ # # ]: 0 : ExportOLEObject( aObj, rDestStg );
128 : 0 : }
129 : :
130 : 0 : void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef& rObj, SvStorage& rDestStg )
131 : : {
132 [ # # ]: 0 : SvGlobalName aOwnGlobalName;
133 [ # # ][ # # ]: 0 : SvGlobalName aObjName( rObj->getClassID() );
[ # # ][ # # ]
134 : 0 : const SfxFilter* pExpFilter = NULL;
135 : : {
136 : : static struct _ObjExpType {
137 : : sal_uInt32 nFlag;
138 : : const char* pFilterNm;
139 : : // GlobalNameId
140 : : struct _GlobalNameIds {
141 : : sal_uInt32 n1;
142 : : sal_uInt16 n2, n3;
143 : : sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
144 : : }
145 : : aGlNmIds[4];
146 : : } aArr[] = {
147 : : { OLE_STARMATH_2_MATHTYPE, "MathType 3.x",
148 : : {{SO3_SM_CLASSID_60}, {SO3_SM_CLASSID_50},
149 : : {SO3_SM_CLASSID_40}, {SO3_SM_CLASSID_30 }}},
150 : : { OLE_STARWRITER_2_WINWORD, "MS Word 97",
151 : : {{SO3_SW_CLASSID_60}, {SO3_SW_CLASSID_50},
152 : : {SO3_SW_CLASSID_40}, {SO3_SW_CLASSID_30 }}},
153 : : { OLE_STARCALC_2_EXCEL, "MS Excel 97",
154 : : {{SO3_SC_CLASSID_60}, {SO3_SC_CLASSID_50},
155 : : {SO3_SC_CLASSID_40}, {SO3_SC_CLASSID_30 }}},
156 : : { OLE_STARIMPRESS_2_POWERPOINT, "MS PowerPoint 97",
157 : : {{SO3_SIMPRESS_CLASSID_60}, {SO3_SIMPRESS_CLASSID_50},
158 : : {SO3_SIMPRESS_CLASSID_40}, {SO3_SIMPRESS_CLASSID_30 }}},
159 : : { 0, "",
160 : : {{SO3_SCH_CLASSID_60}, {SO3_SCH_CLASSID_50},
161 : : {SO3_SCH_CLASSID_40}, {SO3_SCH_CLASSID_30 }}},
162 : : { 0, "",
163 : : {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
164 : : {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50 }}}, // ver 5.0, it is purpose to have double entrys here.
165 : :
166 : : { 0xffff,0,
167 : : {{SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50},
168 : : {SO3_SDRAW_CLASSID_60}, {SO3_SDRAW_CLASSID_50}}}
169 : : };
170 : :
171 [ # # ][ # # ]: 0 : for( const _ObjExpType* pArr = aArr; !pExpFilter && ( pArr->nFlag != 0xffff ); ++pArr )
[ # # ]
172 : : {
173 [ # # ]: 0 : for ( int n = 0; n < 4; ++n )
174 : : {
175 : 0 : const _ObjExpType::_GlobalNameIds& rId = pArr->aGlNmIds[ n ];
176 : : SvGlobalName aGlbNm( rId.n1, rId.n2, rId.n3,
177 : : rId.b8, rId.b9, rId.b10, rId.b11,
178 [ # # ]: 0 : rId.b12, rId.b13, rId.b14, rId.b15 );
179 [ # # ][ # # ]: 0 : if( aObjName == aGlbNm )
180 : : {
181 [ # # ]: 0 : aOwnGlobalName = aGlbNm;
182 : :
183 : : // flags for checking if conversion is wanted at all (SaveOptions?!)
184 [ # # ]: 0 : if( GetFlags() & pArr->nFlag )
185 : : {
186 [ # # ][ # # ]: 0 : pExpFilter = SfxFilterMatcher().GetFilter4FilterName(rtl::OUString::createFromAscii(pArr->pFilterNm));
[ # # ][ # # ]
[ # # ]
187 : : break;
188 : : }
189 : : }
190 [ # # ][ # # ]: 0 : }
191 : : }
192 : : }
193 : :
194 [ # # ]: 0 : if( pExpFilter ) // use this filter for the export
195 : : {
196 : : try
197 : : {
198 [ # # ][ # # ]: 0 : if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
[ # # ]
199 [ # # ][ # # ]: 0 : rObj->changeState( embed::EmbedStates::RUNNING );
200 : : //TODO/LATER: is stream instead of outputstream a better choice?!
201 : : //TODO/LATER: a "StoreTo" method at embedded object would be nice
202 [ # # ]: 0 : uno::Sequence < beans::PropertyValue > aSeq(2);
203 [ # # ][ # # ]: 0 : SvStream* pStream = new SvMemoryStream;
204 [ # # ][ # # ]: 0 : aSeq[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OutputStream" ));
205 [ # # ][ # # ]: 0 : ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *pStream );
[ # # ]
206 [ # # ][ # # ]: 0 : aSeq[0].Value <<= xOut;
207 [ # # ][ # # ]: 0 : aSeq[1].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
208 [ # # ][ # # ]: 0 : aSeq[1].Value <<= ::rtl::OUString( pExpFilter->GetName() );
[ # # ]
209 [ # # ][ # # ]: 0 : uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
[ # # ]
210 : : try
211 : : {
212 [ # # ][ # # ]: 0 : xStor->storeToURL( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" )), aSeq );
[ # # ][ # # ]
213 : : }
214 [ # # ]: 0 : catch( const uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
215 : :
216 [ # # ][ # # ]: 0 : SotStorageRef xOLEStor = new SotStorage( pStream, sal_True );
217 [ # # ]: 0 : xOLEStor->CopyTo( &rDestStg );
218 [ # # ][ # # ]: 0 : rDestStg.Commit();
[ # # ][ # # ]
219 : : }
220 [ # # ]: 0 : catch( const uno::Exception& )
221 : : {
222 : : // TODO/LATER: Error handling
223 : : OSL_FAIL( "The object could not be exported!" );
224 : : }
225 : : }
226 [ # # ][ # # ]: 0 : else if( aOwnGlobalName != SvGlobalName() )
[ # # ][ # # ]
227 : : {
228 : : // own format, maybe SO6 format or lower
229 [ # # ]: 0 : SvGlobalName aEmbName = GetEmbeddedVersion( aOwnGlobalName );
230 [ # # ][ # # ]: 0 : if ( aEmbName != SvGlobalName() && !UseOldMSExport() )
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
[ # # # # ]
231 : : {
232 : : // this is a SO6 embedded object, save in old binary format
233 : 0 : rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
234 : : rDestStg.SetClass( aEmbName,
235 : : SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE,
236 [ # # ][ # # ]: 0 : GetStorageType( aEmbName ) );
[ # # ]
237 : : SotStorageStreamRef xExtStm = rDestStg.OpenSotStream(
238 : : rtl::OUString("properties_stream"),
239 [ # # ][ # # ]: 0 : STREAM_STD_READWRITE);
[ # # ]
[ # # # ]
240 : :
241 : 0 : sal_Bool bExtentSuccess = sal_False;
242 [ # # ]: 0 : if( !xExtStm->GetError() )
243 : : {
244 : : // write extent
245 : : //TODO/MBA: check if writing a size is enough
246 [ # # ]: 0 : if( rObj.GetObject().is() )
247 : : {
248 : : // MSOLE objects don't need to be in running state for VisualArea access
249 : 0 : awt::Size aSize;
250 : : try
251 : : {
252 : : // this is an own object, the content size must be stored in the
253 : : // extension stream
254 [ # # ][ # # ]: 0 : aSize = rObj->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT );
255 : : }
256 [ # # ]: 0 : catch( const embed::NoVisualAreaSizeException& )
257 : : {
258 : : OSL_FAIL( "Could not get visual area size!\n" );
259 : 0 : aSize.Width = 5000;
260 : 0 : aSize.Height = 5000;
261 : : }
262 [ # # ]: 0 : catch( const uno::Exception& )
263 : : {
264 : : OSL_FAIL( "Unexpected exception while getting visual area size!\n" );
265 : 0 : aSize.Width = 5000;
266 : 0 : aSize.Height = 5000;
267 : : }
268 : :
269 : : sal_Int32 pRect[4];
270 : 0 : pRect[0] = 0;
271 : 0 : pRect[1] = aSize.Width;
272 : 0 : pRect[2] = 0;
273 : 0 : pRect[3] = aSize.Height;
274 : :
275 : : sal_Int8 aWriteSet[16];
276 [ # # ]: 0 : for ( int ind = 0; ind < 4; ind++ )
277 : : {
278 : 0 : sal_Int32 nVal = pRect[ind];
279 [ # # ]: 0 : for ( int nByte = 0; nByte < 4; nByte++ )
280 : : {
281 : 0 : aWriteSet[ind*4+nByte] = (sal_Int8) nVal % 0x100;
282 : 0 : nVal /= 0x100;
283 : : }
284 : : }
285 : :
286 [ # # ]: 0 : bExtentSuccess = ( xExtStm->Write( aWriteSet, 16 ) == 16 );
287 : : }
288 : : }
289 : :
290 [ # # ]: 0 : if ( bExtentSuccess )
291 : : {
292 : : SotStorageStreamRef xEmbStm = rDestStg.OpenSotStream(
293 : : rtl::OUString("package_stream"),
294 [ # # ][ # # ]: 0 : STREAM_STD_READWRITE);
[ # # ]
295 [ # # ]: 0 : if( !xEmbStm->GetError() )
296 : : {
297 : : try
298 : : {
299 [ # # ][ # # ]: 0 : if ( rObj->getCurrentState() == embed::EmbedStates::LOADED )
[ # # ]
300 [ # # ][ # # ]: 0 : rObj->changeState( embed::EmbedStates::RUNNING );
301 : : //TODO/LATER: is stream instead of outputstream a better choice?!
302 : : //TODO/LATER: a "StoreTo" method at embedded object would be nice
303 [ # # ]: 0 : uno::Sequence < beans::PropertyValue > aSeq(1);
304 [ # # ][ # # ]: 0 : aSeq[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OutputStream" ));
305 [ # # ][ # # ]: 0 : ::uno::Reference < io::XOutputStream > xOut = new ::utl::OOutputStreamWrapper( *xEmbStm );
[ # # ]
306 [ # # ][ # # ]: 0 : aSeq[0].Value <<= xOut;
307 [ # # ][ # # ]: 0 : uno::Reference < frame::XStorable > xStor( rObj->getComponent(), uno::UNO_QUERY );
[ # # ]
308 [ # # ][ # # ]: 0 : xStor->storeToURL( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "private:stream" )), aSeq );
[ # # ][ # # ]
[ # # ]
309 : : }
310 [ # # ]: 0 : catch( const uno::Exception& )
311 : : {
312 : : // TODO/LATER: Error handling
313 : : OSL_FAIL( "The object could not be exported!" );
314 : : }
315 [ # # ]: 0 : }
316 [ # # ]: 0 : }
317 : : }
318 : : else
319 : : {
320 : : OSL_FAIL("Own binary format inside own container document!");
321 [ # # ]: 0 : }
322 : : }
323 : : else
324 : : {
325 : : // alien objects
326 : : //TODO/LATER: a "StoreTo" method at embedded object would be nice
327 : 0 : rDestStg.SetVersion( SOFFICE_FILEFORMAT_31 );
328 [ # # ][ # # ]: 0 : uno::Reference < embed::XStorage > xStor = ::comphelper::OStorageHelper::GetTemporaryStorage();
329 [ # # ]: 0 : uno::Reference < embed::XEmbedPersist > xPers( rObj.GetObject(), uno::UNO_QUERY );
330 [ # # ]: 0 : if ( xPers.is() )
331 : : {
332 [ # # ]: 0 : uno::Sequence < beans::PropertyValue > aEmptySeq;
333 [ # # ]: 0 : ::rtl::OUString aTempName( RTL_CONSTASCII_USTRINGPARAM( "bla" ));
334 : : try
335 : : {
336 [ # # ][ # # ]: 0 : xPers->storeToEntry( xStor, aTempName, aEmptySeq, aEmptySeq );
337 : : }
338 [ # # ]: 0 : catch ( const uno::Exception& )
339 : : {}
340 : :
341 [ # # ][ # # ]: 0 : SotStorageRef xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, STREAM_STD_READ );
[ # # ]
342 [ # # ]: 0 : xOLEStor->CopyTo( &rDestStg );
343 [ # # ][ # # ]: 0 : rDestStg.Commit();
[ # # ]
344 : 0 : }
345 : : }
346 : :
347 : : //We never need this stream: See #99809# and #i2179#
348 [ # # ][ # # ]: 0 : rDestStg.Remove(rtl::OUString(SVEXT_PERSIST_STREAM));
[ # # ][ # # ]
[ # # ]
349 : 0 : }
350 : :
351 : :
352 : :
353 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|