1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: msoleexp.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
33 #include <com/sun/star/uno/Reference.hxx>
34 #include <com/sun/star/uno/Sequence.hxx>
35 #include <com/sun/star/uno/Any.hxx>
36 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
37 #include <com/sun/star/container/XNameAccess.hpp>
38 #ifndef _COM_SUN_STAR_EMBED_XEmbedPersist_HPP_
39 #include <com/sun/star/embed/XEmbedPersist.hpp>
41 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
42 #include <com/sun/star/embed/EmbedStates.hpp>
43 #include <com/sun/star/frame/XStorable.hpp>
44 #include <com/sun/star/awt/Size.hpp>
45 #include <com/sun/star/embed/Aspects.hpp>
47 #ifndef _SO_CLSIDS_HXX
48 #include <sot/clsids.hxx>
50 #include <sfx2/objsh.hxx>
51 //#ifndef _SFX_INTERNO_HXX
52 //#include <sfx2/interno.hxx>
54 #include <sfx2/docfac.hxx>
55 #include <sfx2/docfilt.hxx>
56 #include <sfx2/docfile.hxx>
57 #include <sfx2/fcontnr.hxx>
58 #include <sot/formats.hxx>
59 #include <comphelper/processfactory.hxx>
61 #include <unotools/streamwrap.hxx>
62 #include <comphelper/storagehelper.hxx>
63 #include <svtools/embedhlp.hxx>
64 #include <svx/msdffimp.hxx> // extern sichtbare Header-Datei
66 #include "msoleexp.hxx"
68 #define CREATE_CONST_ASC(s) String::CreateFromAscii( \
69 RTL_CONSTASCII_STRINGPARAM(s))
71 using namespace ::com::sun::star
;
73 SvGlobalName
GetEmbeddedVersion( const SvGlobalName
& aAppName
)
75 if ( aAppName
== SvGlobalName( SO3_SM_CLASSID_60
) )
76 return SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8
);
77 else if ( aAppName
== SvGlobalName( SO3_SW_CLASSID_60
) )
78 return SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8
);
79 else if ( aAppName
== SvGlobalName( SO3_SC_CLASSID_60
) )
80 return SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8
);
81 else if ( aAppName
== SvGlobalName( SO3_SDRAW_CLASSID_60
) )
82 return SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8
);
83 else if ( aAppName
== SvGlobalName( SO3_SIMPRESS_CLASSID_60
) )
84 return SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8
);
85 else if ( aAppName
== SvGlobalName( SO3_SCH_CLASSID_60
) )
86 return SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8
);
88 return SvGlobalName();
91 String
GetStorageType( const SvGlobalName
& aEmbName
)
93 if ( aEmbName
== SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8
) )
94 return String::CreateFromAscii( "opendocument.MathDocument.1" );
95 else if ( aEmbName
== SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8
) )
96 return String::CreateFromAscii( "opendocument.WriterDocument.1" );
97 else if ( aEmbName
== SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8
) )
98 return String::CreateFromAscii( "opendocument.CalcDocument.1" );
99 else if ( aEmbName
== SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8
) )
100 return String::CreateFromAscii( "opendocument.DrawDocument.1" );
101 else if ( aEmbName
== SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8
) )
102 return String::CreateFromAscii( "opendocument.ImpressDocument.1" );
103 else if ( aEmbName
== SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8
) )
104 return String::CreateFromAscii( "opendocument.ChartDocument.1" );
109 sal_Bool
UseOldMSExport()
111 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= ::comphelper::getProcessServiceFactory();
115 uno::Reference
< lang::XMultiServiceFactory
> xProvider( xFactory
->createInstance(
116 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationProvider"))),
118 if ( xProvider
.is() )
121 uno::Sequence
< uno::Any
> aArg( 1 );
122 aArg
[0] <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/org.openoffice.Office.Common/InternalMSExport") );
123 uno::Reference
< container::XNameAccess
> xNameAccess(
124 xProvider
->createInstanceWithArguments(
125 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.configuration.ConfigurationUpdateAccess" ) ),
128 if ( xNameAccess
.is() )
130 uno::Any aResult
= xNameAccess
->getByName(
131 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UseOldExport" ) ) );
133 sal_Bool bResult
= sal_Bool();
134 if ( aResult
>>= bResult
)
138 catch( uno::Exception
& )
144 OSL_ENSURE( sal_False
, "Could not get access to configuration entry!\n" );
148 void SvxMSExportOLEObjects::ExportOLEObject( const com::sun::star::uno::Reference
< com::sun::star::embed::XEmbeddedObject
>& rObj
, SotStorage
& rDestStg
)
150 svt::EmbeddedObjectRef
aObj( rObj
, embed::Aspects::MSOLE_CONTENT
);
151 ExportOLEObject( aObj
, rDestStg
);
154 void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef
& rObj
, SvStorage
& rDestStg
)
156 SvGlobalName aOwnGlobalName
;
157 SvGlobalName
aObjName( rObj
->getClassID() );
158 const SfxFilter
* pExpFilter
= NULL
;
160 static struct _ObjExpType
{
162 const char* pFilterNm
;
164 struct _GlobalNameIds
{
167 BYTE b8
, b9
, b10
, b11
, b12
, b13
, b14
, b15
;
171 { OLE_STARMATH_2_MATHTYPE
, "MathType 3.x",
172 {{SO3_SM_CLASSID_60
}, {SO3_SM_CLASSID_50
},
173 {SO3_SM_CLASSID_40
}, {SO3_SM_CLASSID_30
}}},
174 { OLE_STARWRITER_2_WINWORD
, "MS Word 97",
175 {{SO3_SW_CLASSID_60
}, {SO3_SW_CLASSID_50
},
176 {SO3_SW_CLASSID_40
}, {SO3_SW_CLASSID_30
}}},
177 { OLE_STARCALC_2_EXCEL
, "MS Excel 97",
178 {{SO3_SC_CLASSID_60
}, {SO3_SC_CLASSID_50
},
179 {SO3_SC_CLASSID_40
}, {SO3_SC_CLASSID_30
}}},
180 { OLE_STARIMPRESS_2_POWERPOINT
, "MS PowerPoint 97",
181 {{SO3_SIMPRESS_CLASSID_60
}, {SO3_SIMPRESS_CLASSID_50
},
182 {SO3_SIMPRESS_CLASSID_40
}, {SO3_SIMPRESS_CLASSID_30
}}},
184 {{SO3_SCH_CLASSID_60
}, {SO3_SCH_CLASSID_50
},
185 {SO3_SCH_CLASSID_40
}, {SO3_SCH_CLASSID_30
}}},
187 {{SO3_SDRAW_CLASSID_60
}, {SO3_SDRAW_CLASSID_50
}, // SJ: !!!! SO3_SDRAW_CLASSID is only available up from
188 {SO3_SDRAW_CLASSID_60
}, {SO3_SDRAW_CLASSID_50
}}}, // ver 5.0, it is purpose to have double entrys here.
191 {{SO3_SDRAW_CLASSID_60
}, {SO3_SDRAW_CLASSID_50
},
192 {SO3_SDRAW_CLASSID_60
}, {SO3_SDRAW_CLASSID_50
}}}
195 for( const _ObjExpType
* pArr
= aArr
; !pExpFilter
&& ( pArr
->nFlag
!= 0xffff ); ++pArr
)
197 for ( int n
= 0; n
< 4; ++n
)
199 const _ObjExpType::_GlobalNameIds
& rId
= pArr
->aGlNmIds
[ n
];
200 SvGlobalName
aGlbNm( rId
.n1
, rId
.n2
, rId
.n3
,
201 rId
.b8
, rId
.b9
, rId
.b10
, rId
.b11
,
202 rId
.b12
, rId
.b13
, rId
.b14
, rId
.b15
);
203 if( aObjName
== aGlbNm
)
205 aOwnGlobalName
= aGlbNm
;
207 // flags for checking if conversion is wanted at all (SaveOptions?!)
208 if( GetFlags() & pArr
->nFlag
)
210 pExpFilter
= SfxFilterMatcher().GetFilter4FilterName(String::CreateFromAscii(pArr
->pFilterNm
));
218 if( pExpFilter
) // use this filter for the export
222 if ( rObj
->getCurrentState() == embed::EmbedStates::LOADED
)
223 rObj
->changeState( embed::EmbedStates::RUNNING
);
224 //TODO/LATER: is stream instead of outputstream a better choice?!
225 //TODO/LATER: a "StoreTo" method at embedded object would be nice
226 uno::Sequence
< beans::PropertyValue
> aSeq(2);
227 SvStream
* pStream
= new SvMemoryStream
;
228 aSeq
[0].Name
= ::rtl::OUString::createFromAscii( "OutputStream" );
229 ::uno::Reference
< io::XOutputStream
> xOut
= new ::utl::OOutputStreamWrapper( *pStream
);
230 aSeq
[0].Value
<<= xOut
;
231 aSeq
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "FilterName" ) );
232 aSeq
[1].Value
<<= ::rtl::OUString( pExpFilter
->GetName() );
233 uno::Reference
< frame::XStorable
> xStor( rObj
->getComponent(), uno::UNO_QUERY
);
236 xStor
->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq
);
238 catch( uno::Exception
& ) {} // #TODO really handle exceptions - interactionalhandler etc. ?
240 SotStorageRef xOLEStor
= new SotStorage( pStream
, TRUE
);
241 xOLEStor
->CopyTo( &rDestStg
);
244 catch( uno::Exception
& )
246 // TODO/LATER: Error handling
247 DBG_ERROR( "The object could not be exported!" );
250 else if( aOwnGlobalName
!= SvGlobalName() )
252 // own format, maybe SO6 format or lower
253 SvGlobalName aEmbName
= GetEmbeddedVersion( aOwnGlobalName
);
254 if ( aEmbName
!= SvGlobalName() && !UseOldMSExport() )
256 // this is a SO6 embedded object, save in old binary format
257 rDestStg
.SetVersion( SOFFICE_FILEFORMAT_31
);
258 rDestStg
.SetClass( aEmbName
,
259 SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE
,
260 GetStorageType( aEmbName
) );
261 SotStorageStreamRef xExtStm
= rDestStg
.OpenSotStream(
262 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "properties_stream" ) ),
263 STREAM_STD_READWRITE
);
265 sal_Bool bExtentSuccess
= sal_False
;
266 if( !xExtStm
->GetError() )
269 //TODO/MBA: check if writing a size is enough
270 if( rObj
.GetObject().is() )
272 // MSOLE objects don't need to be in running state for VisualArea access
276 // this is an own object, the content size must be stored in the
278 aSize
= rObj
->getVisualAreaSize( embed::Aspects::MSOLE_CONTENT
);
280 catch( embed::NoVisualAreaSizeException
& )
282 OSL_ENSURE( sal_False
, "Could not get visual area size!\n" );
286 catch( uno::Exception
& )
288 OSL_ENSURE( sal_False
, "Unexpected exception while getting visual area size!\n" );
293 //Rectangle aVisArea = xSfxIPObj->GetVisArea( ASPECT_CONTENT );
295 //pRect[0] = aVisArea.Left();
296 //pRect[1] = aVisArea.Right();
297 //pRect[2] = aVisArea.Top();
298 //pRect[3] = aVisArea.Bottom();
300 pRect
[1] = aSize
.Width
;
302 pRect
[3] = aSize
.Height
;
304 sal_Int8 aWriteSet
[16];
305 for ( int ind
= 0; ind
< 4; ind
++ )
307 sal_Int32 nVal
= pRect
[ind
];
308 for ( int nByte
= 0; nByte
< 4; nByte
++ )
310 aWriteSet
[ind
*4+nByte
] = (sal_Int8
) nVal
% 0x100;
315 bExtentSuccess
= ( xExtStm
->Write( aWriteSet
, 16 ) == 16 );
319 if ( bExtentSuccess
)
321 SotStorageStreamRef xEmbStm
= rDestStg
.OpenSotStream(
322 String::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "package_stream" ) ),
323 STREAM_STD_READWRITE
);
324 if( !xEmbStm
->GetError() )
328 if ( rObj
->getCurrentState() == embed::EmbedStates::LOADED
)
329 rObj
->changeState( embed::EmbedStates::RUNNING
);
330 //TODO/LATER: is stream instead of outputstream a better choice?!
331 //TODO/LATER: a "StoreTo" method at embedded object would be nice
332 uno::Sequence
< beans::PropertyValue
> aSeq(1);
333 aSeq
[0].Name
= ::rtl::OUString::createFromAscii( "OutputStream" );
334 ::uno::Reference
< io::XOutputStream
> xOut
= new ::utl::OOutputStreamWrapper( *xEmbStm
);
335 aSeq
[0].Value
<<= xOut
;
336 uno::Reference
< frame::XStorable
> xStor( rObj
->getComponent(), uno::UNO_QUERY
);
337 xStor
->storeToURL( ::rtl::OUString::createFromAscii( "private:stream" ), aSeq
);
339 catch( uno::Exception
& )
341 // TODO/LATER: Error handling
342 DBG_ERROR( "The object could not be exported!" );
349 DBG_ERROR("Own binary format inside own container document!");
355 //TODO/LATER: a "StoreTo" method at embedded object would be nice
356 rDestStg
.SetVersion( SOFFICE_FILEFORMAT_31
);
357 uno::Reference
< embed::XStorage
> xStor
= ::comphelper::OStorageHelper::GetTemporaryStorage();
358 uno::Reference
< embed::XEmbedPersist
> xPers( rObj
.GetObject(), uno::UNO_QUERY
);
361 uno::Sequence
< beans::PropertyValue
> aEmptySeq
;
362 ::rtl::OUString
aTempName(::rtl::OUString::createFromAscii("bla"));
365 xPers
->storeToEntry( xStor
, aTempName
, aEmptySeq
, aEmptySeq
);
367 catch ( uno::Exception
& )
370 SotStorageRef xOLEStor
= SotStorage::OpenOLEStorage( xStor
, aTempName
, STREAM_STD_READ
);
371 xOLEStor
->CopyTo( &rDestStg
);
376 //We never need this stream: See #99809# and #i2179#
377 rDestStg
.Remove(CREATE_CONST_ASC(SVEXT_PERSIST_STREAM
));