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