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_chart2.hxx"
26 
27 #include "XMLFilter.hxx"
28 #include "macros.hxx"
29 #include "MediaDescriptorHelper.hxx"
30 #include "ContainerHelper.hxx"
31 #include <comphelper/mediadescriptor.hxx>
32 
33 // for ERRCODE_SFX_GENERAL etc.
34 // header contains only macros
35 #include <svtools/sfxecode.hxx>
36 // header for class SvtSaveOptions
37 #include <unotools/saveopt.hxx>
38 #include <comphelper/genericpropertyset.hxx>
39 // header for struct PropertyMapEntry
40 #include <comphelper/propertysetinfo.hxx>
41 #include <comphelper/documentconstants.hxx>
42 
43 // header for class SotStorage
44 #include <sot/storage.hxx>
45 #include <com/sun/star/beans/PropertyAttribute.hpp>
46 #include <com/sun/star/xml/sax/InputSource.hpp>
47 #include <com/sun/star/lang/XMultiComponentFactory.hpp>
48 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
49 #include <com/sun/star/embed/ElementModes.hpp>
50 #include <com/sun/star/embed/XStorage.hpp>
51 #include <com/sun/star/embed/XTransactedObject.hpp>
52 #include <com/sun/star/frame/XModel.hpp>
53 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
54 #include <com/sun/star/xml/sax/XParser.hpp>
55 #include <com/sun/star/xml/sax/SAXParseException.hpp>
56 #include <com/sun/star/packages/zip/ZipIOException.hpp>
57 #include <com/sun/star/document/XGraphicObjectResolver.hpp>
58 #include <com/sun/star/container/XNameAccess.hpp>
59 
60 using namespace ::com::sun::star;
61 
62 using ::com::sun::star::uno::Reference;
63 using ::com::sun::star::uno::Sequence;
64 using ::rtl::OUString;
65 using ::osl::MutexGuard;
66 
67 // ----------------------------------------
68 namespace
69 {
70 #define LOCAL_CONST_STR(i, x) sal_Char __READONLY_DATA i[sizeof(x)] = x
71 #define MAP_LEN(x) x, sizeof(x) - 1
72 
73 LOCAL_CONST_STR( sXML_metaStreamName,       "meta.xml");
74 LOCAL_CONST_STR( sXML_styleStreamName,      "styles.xml" );
75 LOCAL_CONST_STR( sXML_contentStreamName,    "content.xml" );
76 LOCAL_CONST_STR( sXML_oldContentStreamName, "Content.xml" );
77 
78 // soffice 6/7
79 // LOCAL_CONST_STR( sXML_export_chart_meta_service,            "com.sun.star.comp.Chart.XMLMetaExporter" );
80 LOCAL_CONST_STR( sXML_export_chart_styles_service,          "com.sun.star.comp.Chart.XMLStylesExporter" );
81 LOCAL_CONST_STR( sXML_export_chart_content_service,         "com.sun.star.comp.Chart.XMLContentExporter" );
82 
83 // LOCAL_CONST_STR( sXML_import_chart_meta_service,            "com.sun.star.comp.Chart.XMLMetaImporter" );
84 LOCAL_CONST_STR( sXML_import_chart_styles_service,          "com.sun.star.comp.Chart.XMLStylesImporter" );
85 LOCAL_CONST_STR( sXML_import_chart_content_service,         "com.sun.star.comp.Chart.XMLContentImporter" );
86 LOCAL_CONST_STR( sXML_import_chart_old_content_service,     "com.sun.star.office.sax.importer.Chart" );
87 
88 // Oasis
89 LOCAL_CONST_STR( sXML_export_chart_oasis_styles_service,    "com.sun.star.comp.Chart.XMLOasisStylesExporter" );
90 LOCAL_CONST_STR( sXML_export_chart_oasis_content_service,   "com.sun.star.comp.Chart.XMLOasisContentExporter" );
91 LOCAL_CONST_STR( sXML_export_chart_oasis_meta_service,      "com.sun.star.comp.Chart.XMLOasisMetaExporter" );
92 
93 LOCAL_CONST_STR( sXML_import_chart_oasis_styles_service,    "com.sun.star.comp.Chart.XMLOasisStylesImporter" );
94 LOCAL_CONST_STR( sXML_import_chart_oasis_content_service,   "com.sun.star.comp.Chart.XMLOasisContentImporter" );
95 LOCAL_CONST_STR( sXML_import_chart_oasis_meta_service,      "com.sun.star.comp.Chart.XMLOasisMetaImporter" );
96 
lcl_getWriteStorage(const Sequence<beans::PropertyValue> & rMediaDescriptor,const uno::Reference<uno::XComponentContext> & xContext,const::rtl::OUString & _sMediaType)97 uno::Reference< embed::XStorage > lcl_getWriteStorage(
98     const Sequence< beans::PropertyValue >& rMediaDescriptor,
99     const uno::Reference< uno::XComponentContext >& xContext,const ::rtl::OUString& _sMediaType)
100 {
101     uno::Reference< embed::XStorage > xStorage;
102     try
103     {
104         apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
105         if( aMDHelper.ISSET_Storage )
106         {
107             xStorage = aMDHelper.Storage;
108         }
109         else
110         {
111             Reference< lang::XSingleServiceFactory > xStorageFact(
112                 xContext->getServiceManager()->createInstanceWithContext(
113                     C2U("com.sun.star.embed.StorageFactory"),
114                     xContext ), uno::UNO_QUERY_THROW );
115 
116             ::std::vector< beans::PropertyValue > aPropertiesForStorage;
117 
118             for( sal_Int32 i=rMediaDescriptor.getLength(); i--; )
119             {
120                 // properties understood by storage factory
121                 // (see package/source/xstor/xfactory.cxx for details)
122                 if ( rMediaDescriptor[i].Name.equalsAsciiL(
123                         RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ))
124                     || rMediaDescriptor[i].Name.equalsAsciiL(
125                         RTL_CONSTASCII_STRINGPARAM( "Password" ))
126                     || rMediaDescriptor[i].Name.equalsAsciiL(
127                         RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ))
128     //                  || rMediaDescriptor[i].Name.equalsAsciiL(
129     //                      RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ))
130     //                  || rMediaDescriptor[i].Name.equalsAsciiL(
131     //                      RTL_CONSTASCII_STRINGPARAM( "Unpacked" ))
132                     )
133                 {
134                     aPropertiesForStorage.push_back( rMediaDescriptor[i] );
135                 }
136             }
137 
138             if( aMDHelper.ISSET_Storage )
139                 xStorage.set( aMDHelper.Storage );
140             else
141             {
142                 Sequence< uno::Any > aStorageArgs( 3 );
143                 if( aMDHelper.ISSET_OutputStream  )
144                     aStorageArgs[0] <<= aMDHelper.OutputStream;
145                 else
146                     aStorageArgs[0] <<= aMDHelper.URL;
147                 aStorageArgs[1] <<= (embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE);
148                 aStorageArgs[2] <<= ::chart::ContainerHelper::ContainerToSequence( aPropertiesForStorage );
149 
150                 xStorage.set(
151                     xStorageFact->createInstanceWithArguments( aStorageArgs ),
152                     uno::UNO_QUERY_THROW );
153             }
154         }
155 
156         // set correct media type at storage
157         uno::Reference<beans::XPropertySet> xProp(xStorage,uno::UNO_QUERY);
158         OUString aMediaType;
159         if ( ! xProp.is() ||
160              ! ( xProp->getPropertyValue( C2U("MediaType")) >>= aMediaType ) ||
161              aMediaType.isEmpty() )
162         {
163             xProp->setPropertyValue( C2U("MediaType"), uno::makeAny( _sMediaType ));
164         }
165     }
166     catch( uno::Exception & ex )
167     {
168         ASSERT_EXCEPTION( ex );
169     }
170     return xStorage;
171 }
172 
lcl_getReadStorage(const Sequence<beans::PropertyValue> & rMediaDescriptor,const uno::Reference<uno::XComponentContext> & xContext)173 uno::Reference< embed::XStorage > lcl_getReadStorage(
174     const Sequence< beans::PropertyValue >& rMediaDescriptor,
175     const uno::Reference< uno::XComponentContext >& xContext)
176 {
177     uno::Reference< embed::XStorage > xStorage;
178 
179     try
180     {
181         apphelper::MediaDescriptorHelper aMDHelper( rMediaDescriptor );
182         if( aMDHelper.ISSET_Storage )
183         {
184             xStorage = aMDHelper.Storage;
185         }
186         else
187         {
188             // get XStream from MediaDescriptor
189             uno::Reference< io::XInputStream > xStream;
190             ::std::vector< beans::PropertyValue > aPropertiesForStorage;
191             for( sal_Int32 i=rMediaDescriptor.getLength(); i--; )
192             {
193                 if( rMediaDescriptor[i].Name.equalsAsciiL(
194                         RTL_CONSTASCII_STRINGPARAM( "InputStream" )))
195                     xStream.set( rMediaDescriptor[i].Value, uno::UNO_QUERY );
196 
197                 // properties understood by storage factory
198                 // (see package/source/xstor/xfactory.cxx for details)
199                 if ( rMediaDescriptor[i].Name.equalsAsciiL(
200                          RTL_CONSTASCII_STRINGPARAM( "InteractionHandler" ))
201                      || rMediaDescriptor[i].Name.equalsAsciiL(
202                          RTL_CONSTASCII_STRINGPARAM( "Password" ))
203                      || rMediaDescriptor[i].Name.equalsAsciiL(
204                          RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ))
205 //                  || rMediaDescriptor[i].Name.equalsAsciiL(
206 //                      RTL_CONSTASCII_STRINGPARAM( "StatusIndicator" ))
207 //                  || rMediaDescriptor[i].Name.equalsAsciiL(
208 //                      RTL_CONSTASCII_STRINGPARAM( "Unpacked" ))
209                     )
210                 {
211                     aPropertiesForStorage.push_back( rMediaDescriptor[i] );
212                 }
213             }
214             OSL_ENSURE( xStream.is(), "No Stream" );
215             if( ! xStream.is())
216                 return xStorage;
217 
218             // convert XInputStream to XStorage via the storage factory
219             Reference< lang::XSingleServiceFactory > xStorageFact(
220                 xContext->getServiceManager()->createInstanceWithContext(
221                     C2U("com.sun.star.embed.StorageFactory"),
222                     xContext ),
223                 uno::UNO_QUERY_THROW );
224             Sequence< uno::Any > aStorageArgs( 3 );
225             aStorageArgs[0] <<= xStream;
226             aStorageArgs[1] <<= (embed::ElementModes::READ | embed::ElementModes::NOCREATE);
227             aStorageArgs[2] <<= ::chart::ContainerHelper::ContainerToSequence( aPropertiesForStorage );
228             xStorage.set(
229                 xStorageFact->createInstanceWithArguments( aStorageArgs ), uno::UNO_QUERY_THROW );
230         }
231 
232         OSL_ENSURE( xStorage.is(), "No Storage" );
233     }
234     catch( uno::Exception & ex )
235     {
236         ASSERT_EXCEPTION( ex );
237     }
238 
239     return xStorage;
240 }
241 
242 
243 } // anonymous namespace
244 
245 // ----------------------------------------
246 
247 namespace chart
248 {
249 
XMLFilter(Reference<uno::XComponentContext> const & xContext)250 XMLFilter::XMLFilter( Reference< uno::XComponentContext > const & xContext ) :
251         m_xContext( xContext ),
252         m_bCancelOperation( false )
253 {}
254 
~XMLFilter()255 XMLFilter::~XMLFilter()
256 {}
257 
258 // ____ XFilter ____
filter(const Sequence<beans::PropertyValue> & aDescriptor)259 sal_Bool SAL_CALL XMLFilter::filter(
260     const Sequence< beans::PropertyValue >& aDescriptor )
261     throw (uno::RuntimeException)
262 {
263     bool bResult = false;
264 
265     MutexGuard aGuard( m_aMutex );
266 
267     // ignore cancel flag at start of function
268     // note: is currently ignored during import/export
269     if( m_bCancelOperation )
270         m_bCancelOperation = false;
271 
272     if( m_xSourceDoc.is())
273     {
274         OSL_ENSURE( ! m_xTargetDoc.is(), "source doc is set -> target document should not be set" );
275         if( impl_Export( m_xSourceDoc,
276                          aDescriptor ) == 0 )
277         {
278             m_xSourceDoc = NULL;
279             bResult = true;
280         }
281     }
282     else if( m_xTargetDoc.is())
283     {
284         if( impl_Import( m_xTargetDoc,
285                          aDescriptor ) == 0 )
286         {
287             m_xTargetDoc = NULL;
288             bResult = true;
289         }
290     }
291     else
292     {
293         OSL_ENSURE( false, "filter() called with no document set" );
294     }
295 
296     return bResult;
297 }
298 
cancel()299 void SAL_CALL XMLFilter::cancel()
300     throw (uno::RuntimeException)
301 {
302     // if mutex is locked set "cancel state"
303     // note: is currently ignored in filter-method
304     if( ! m_aMutex.tryToAcquire())
305     {
306         m_bCancelOperation = true;
307     }
308 }
309 
310 // ____ XImporter ____
setTargetDocument(const Reference<lang::XComponent> & Document)311 void SAL_CALL XMLFilter::setTargetDocument(
312     const Reference< lang::XComponent >& Document )
313     throw (lang::IllegalArgumentException,
314            uno::RuntimeException)
315 {
316     MutexGuard aGuard( m_aMutex );
317     OSL_ENSURE( ! m_xSourceDoc.is(), "Setting target doc while source doc is set" );
318 
319     m_xTargetDoc = Document;
320 }
321 
322 
323 // ____ XExporter ____
setSourceDocument(const Reference<lang::XComponent> & Document)324 void SAL_CALL XMLFilter::setSourceDocument(
325     const Reference< lang::XComponent >& Document )
326     throw (lang::IllegalArgumentException,
327            uno::RuntimeException)
328 {
329     MutexGuard aGuard( m_aMutex );
330     OSL_ENSURE( ! m_xTargetDoc.is(), "Setting source doc while target doc is set" );
331 
332     m_xSourceDoc = Document;
333 }
334 
335 
impl_Import(const Reference<lang::XComponent> & xDocumentComp,const Sequence<beans::PropertyValue> & rMediaDescriptor)336 sal_Int32 XMLFilter::impl_Import(
337     const Reference< lang::XComponent > & xDocumentComp,
338     const Sequence< beans::PropertyValue > & rMediaDescriptor )
339 {
340     sal_Int32 nWarning = 0;
341 
342     OSL_ENSURE( xDocumentComp.is(), "Import: No Model" );
343     OSL_ENSURE( m_xContext.is(), "Import: No ComponentContext" );
344 
345     if( ! (xDocumentComp.is() &&
346            m_xContext.is()))
347         return nWarning;
348 
349     try
350     {
351         Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW );
352         if( ! xServInfo->supportsService( C2U( "com.sun.star.chart2.ChartDocument" )))
353         {
354             OSL_ENSURE( false, "Import: No ChartDocument" );
355             return ERRCODE_SFX_GENERAL;
356         }
357 
358         Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager());
359         OSL_ENSURE( xFactory.is(), "Import: No Factory" );
360         if( ! xFactory.is())
361             return ERRCODE_SFX_GENERAL;
362 
363         // create a sax parser
364         Reference< xml::sax::XParser > xSaxParser(
365             xFactory->createInstanceWithContext( C2U( "com.sun.star.xml.sax.Parser" ), m_xContext ),
366             uno::UNO_QUERY_THROW );
367 
368         bool bOasis = true;
369         isOasisFormat( rMediaDescriptor, bOasis );
370         Reference< embed::XStorage > xStorage( lcl_getReadStorage( rMediaDescriptor, m_xContext));
371         if( ! xStorage.is())
372             return ERRCODE_SFX_GENERAL;
373 
374 //         bool bOasis = (SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60);
375 
376         Reference< document::XGraphicObjectResolver > xGraphicObjectResolver;
377         uno::Reference< lang::XMultiServiceFactory > xServiceFactory( xFactory, uno::UNO_QUERY);
378         if( xServiceFactory.is())
379         {
380             uno::Sequence< uno::Any > aArgs(1);
381             aArgs[0] <<= xStorage;
382             xGraphicObjectResolver.set(
383                 xServiceFactory->createInstanceWithArguments(
384                     C2U("com.sun.star.comp.Svx.GraphicImportHelper"), aArgs ), uno::UNO_QUERY );
385         }
386 
387         // create XPropertySet with extra informatio for the filter
388 	    /** property map for import info set */
389         comphelper::PropertyMapEntry aImportInfoMap[] =
390 	    {
391 		    // #80365# necessary properties for XML progress bar at load time
392 		    { MAP_LEN( "ProgressRange" ),	0, &::getCppuType((const sal_Int32*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0},
393 		    { MAP_LEN( "ProgressMax" ),		0, &::getCppuType((const sal_Int32*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0},
394 		    { MAP_LEN( "ProgressCurrent" ),	0, &::getCppuType((const sal_Int32*)0), ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0},
395 		    { MAP_LEN( "PrivateData" ), 0,
396 			    &::getCppuType( (Reference<XInterface> *)0 ),
397 			    ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
398 		    { MAP_LEN( "BaseURI" ), 0,
399 			    &::getCppuType( (OUString *)0 ),
400 			    ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
401 		    { MAP_LEN( "StreamRelPath" ), 0,
402 			    &::getCppuType( (OUString *)0 ),
403 			    ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
404 		    { MAP_LEN( "StreamName" ), 0,
405 			    &::getCppuType( (OUString *)0 ),
406 			    ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
407             { MAP_LEN( "BuildId" ), 0,
408 			    &::getCppuType( (OUString *)0 ),
409 			    ::com::sun::star::beans::PropertyAttribute::MAYBEVOID, 0 },
410 		    { NULL, 0, 0, NULL, 0, 0 }
411 	    };
412 	    uno::Reference< beans::XPropertySet > xImportInfo(
413 				    comphelper::GenericPropertySet_CreateInstance(
414 							    new comphelper::PropertySetInfo( aImportInfoMap ) ) );
415 
416         // Set base URI and Hierarchical Name
417 	    OUString aHierarchName, aBaseUri;
418         uno::Reference< frame::XModel > xModel( m_xSourceDoc, uno::UNO_QUERY );
419 	    if( xModel.is() )
420 	    {
421 		    uno::Sequence< beans::PropertyValue > aModProps = xModel->getArgs();
422 		    for( sal_Int32 nInd = 0; nInd < aModProps.getLength(); nInd++ )
423             {
424                 if( aModProps[nInd].Name.equals( C2U( "HierarchicalDocumentName" ) ) )
425 			    {
426 				    // Actually this argument only has meaning for embedded documents
427 				    aModProps[nInd].Value >>= aHierarchName;
428 			    }
429                 else if( aModProps[nInd].Name.equals( C2U( "DocumentBaseURL" ) ) )
430                 {
431                     aModProps[nInd].Value >>= aBaseUri;
432                 }
433             }
434 	    }
435 
436         if( !aBaseUri.isEmpty() )
437             xImportInfo->setPropertyValue( C2U("BaseURI"), uno::makeAny( aBaseUri ) );
438 
439 	    if( !aHierarchName.isEmpty() )
440 		    xImportInfo->setPropertyValue( C2U("StreamRelPath"), uno::makeAny( aHierarchName ) );
441 
442         // import meta information
443         if( bOasis )
444             nWarning |= impl_ImportStream(
445                 C2U( sXML_metaStreamName ),
446                 C2U( sXML_import_chart_oasis_meta_service ),
447                 xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
448 
449         // import styles
450         nWarning |= impl_ImportStream(
451             C2U( sXML_styleStreamName ),
452             bOasis
453             ? C2U( sXML_import_chart_oasis_styles_service )
454             : C2U( sXML_import_chart_styles_service ),
455             xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
456 
457         // import content
458         sal_Int32 nContentWarning = impl_ImportStream(
459             C2U( sXML_contentStreamName ),
460             bOasis
461             ? C2U( sXML_import_chart_oasis_content_service )
462             : C2U( sXML_import_chart_content_service ),
463             xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
464         nWarning |= nContentWarning;
465 
466         // import of "content.xml" didn't work - try old "Content.xml" stream
467         if( nContentWarning != 0 )
468         {
469             nWarning = impl_ImportStream(
470                 C2U( sXML_oldContentStreamName ),
471                 C2U( sXML_import_chart_old_content_service ),
472                 xStorage, xSaxParser, xFactory, xGraphicObjectResolver, xImportInfo );
473         }
474     }
475     catch( uno::Exception & ex )
476     {
477         ASSERT_EXCEPTION( ex );
478 
479         // something went awry
480         nWarning = ERRCODE_SFX_GENERAL;
481     }
482 
483     return nWarning;
484 }
485 
impl_ImportStream(const OUString & rStreamName,const OUString & rServiceName,const Reference<embed::XStorage> & xStorage,const Reference<xml::sax::XParser> & xParser,const Reference<lang::XMultiComponentFactory> & xFactory,const Reference<document::XGraphicObjectResolver> & xGraphicObjectResolver,uno::Reference<beans::XPropertySet> & xImportInfo)486 sal_Int32 XMLFilter::impl_ImportStream(
487     const OUString & rStreamName,
488     const OUString & rServiceName,
489     const Reference< embed::XStorage > & xStorage,
490     const Reference< xml::sax::XParser > & xParser,
491     const Reference< lang::XMultiComponentFactory > & xFactory,
492     const Reference< document::XGraphicObjectResolver > & xGraphicObjectResolver,
493     uno::Reference< beans::XPropertySet >& xImportInfo )
494 {
495     sal_Int32 nWarning = ERRCODE_SFX_GENERAL;
496 
497     Reference< container::XNameAccess > xNameAcc( xStorage, uno::UNO_QUERY );
498     if( ! (xNameAcc.is() &&
499            xNameAcc->hasByName( rStreamName )))
500         return 0;
501 
502     if( xImportInfo.is() )
503 		xImportInfo->setPropertyValue( C2U("StreamName"), uno::makeAny( rStreamName ) );
504 
505     if( xStorage.is() &&
506         xStorage->isStreamElement( rStreamName ) )
507     {
508         try
509         {
510             xml::sax::InputSource aParserInput;
511             aParserInput.aInputStream.set(
512                 xStorage->openStreamElement(
513                     rStreamName,
514                     embed::ElementModes::READ | embed::ElementModes::NOCREATE ),
515                 uno::UNO_QUERY );
516 
517             // todo: encryption
518 
519             if( aParserInput.aInputStream.is())
520             {
521                 sal_Int32 nArgs = 0;
522                 //if( m_xStatusIndicator.is())
523 				//    nArgs++;
524 			    if( xGraphicObjectResolver.is())
525 				    nArgs++;
526 			    if( xImportInfo.is())
527 				    nArgs++;
528 
529 			    uno::Sequence< uno::Any > aFilterCompArgs( nArgs );
530 
531                 nArgs = 0;
532                 //if( m_xStatusIndicator.is())
533 				//    aFilterCompArgs[ nArgs++ ] <<= m_xStatusIndicator;
534                 if( xGraphicObjectResolver.is())
535                     aFilterCompArgs[nArgs++] <<= xGraphicObjectResolver;
536                 if( xImportInfo.is())
537 				    aFilterCompArgs[ nArgs++ ] <<= xImportInfo;
538 
539                 Reference< xml::sax::XDocumentHandler > xDocHandler(
540                     xFactory->createInstanceWithArgumentsAndContext( rServiceName, aFilterCompArgs, m_xContext ),
541                     uno::UNO_QUERY_THROW );
542 
543 
544                 Reference< document::XImporter > xImporter( xDocHandler, uno::UNO_QUERY_THROW );
545                 xImporter->setTargetDocument( Reference< lang::XComponent >( m_xTargetDoc, uno::UNO_QUERY_THROW ));
546 
547                 if ( !m_sDocumentHandler.isEmpty() )
548                 {
549                     try
550                     {
551                         uno::Sequence< uno::Any > aArgs(2);
552                         beans::NamedValue aValue;
553                         aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentHandler"));
554                         aValue.Value <<= xDocHandler;
555                         aArgs[0] <<= aValue;
556                         aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Model"));
557                         aValue.Value <<= m_xTargetDoc;
558                         aArgs[1] <<= aValue;
559 
560                         xDocHandler.set(xFactory->createInstanceWithArgumentsAndContext(m_sDocumentHandler,aArgs,m_xContext), uno::UNO_QUERY );
561                         xImporter.set(xDocHandler,uno::UNO_QUERY);
562                     }
563                     catch(uno::Exception&)
564                     {
565                         OSL_ENSURE(0,"Exception caught!");
566                     }
567                 }
568                 xParser->setDocumentHandler( xDocHandler );
569                 xParser->parseStream( aParserInput );
570             }
571 
572             // load was successful
573             nWarning = 0;
574         }
575         catch( xml::sax::SAXParseException )
576         {
577             // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD
578         }
579         catch( xml::sax::SAXException )
580         {
581             // todo: if encrypted: ERRCODE_SFX_WRONGPASSWORD
582         }
583         catch( packages::zip::ZipIOException )
584         {
585             nWarning = ERRCODE_IO_BROKENPACKAGE;
586         }
587         catch( io::IOException )
588         {
589         }
590         catch( uno::Exception& aEx )
591         {
592             ASSERT_EXCEPTION( aEx );
593         }
594     }
595 
596     return nWarning;
597 }
598 
impl_Export(const Reference<lang::XComponent> & xDocumentComp,const Sequence<beans::PropertyValue> & rMediaDescriptor)599 sal_Int32 XMLFilter::impl_Export(
600     const Reference< lang::XComponent > & xDocumentComp,
601     const Sequence< beans::PropertyValue > & rMediaDescriptor )
602 {
603     //save
604 
605     sal_Int32 nWarning = 0;
606 
607     OSL_ENSURE( xDocumentComp.is(), "Export: No Model" );
608     OSL_ENSURE( m_xContext.is(), "Export: No ComponentContext" );
609 
610     if( !xDocumentComp.is() || !m_xContext.is() )
611         return nWarning;
612 
613     try
614     {
615         Reference< lang::XServiceInfo > xServInfo( xDocumentComp, uno::UNO_QUERY_THROW );
616         if( ! xServInfo->supportsService( C2U( "com.sun.star.chart2.ChartDocument" )))
617         {
618             OSL_ENSURE( false, "Export: No ChartDocument" );
619             return ERRCODE_SFX_GENERAL;
620         }
621 
622         Reference< lang::XMultiComponentFactory > xFactory( m_xContext->getServiceManager());
623         OSL_ENSURE( xFactory.is(), "Export: No Factory" );
624         if( ! xFactory.is())
625             return ERRCODE_SFX_GENERAL;
626         uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_xContext->getServiceManager(), uno::UNO_QUERY);
627         if( ! xServiceFactory.is())
628             return ERRCODE_SFX_GENERAL;
629 
630         uno::Reference< io::XActiveDataSource > xSaxWriter( xServiceFactory->createInstance(
631                 C2U("com.sun.star.xml.sax.Writer")), uno::UNO_QUERY );
632         if ( !xSaxWriter.is() )
633 		    return ERRCODE_SFX_GENERAL;
634 
635         bool bOasis = true;
636         isOasisFormat( rMediaDescriptor, bOasis );
637 
638         uno::Reference< embed::XStorage > xStorage( lcl_getWriteStorage( rMediaDescriptor, m_xContext, getMediaType(bOasis) ) );
639         OSL_ENSURE( xStorage.is(), "No Storage" );
640         if( ! xStorage.is())
641             return ERRCODE_SFX_GENERAL;
642 
643         uno::Reference< xml::sax::XDocumentHandler> xDocHandler( xSaxWriter, uno::UNO_QUERY );
644 
645         if ( !m_sDocumentHandler.isEmpty() )
646         {
647             try
648             {
649                 uno::Sequence< uno::Any > aArgs(2);
650                 beans::NamedValue aValue;
651                 aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentHandler"));
652                 aValue.Value <<= xDocHandler;
653                 aArgs[0] <<= aValue;
654                 aValue.Name = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Model"));
655                 aValue.Value <<= xDocumentComp;
656                 aArgs[1] <<= aValue;
657 
658                 xDocHandler.set(xServiceFactory->createInstanceWithArguments(m_sDocumentHandler,aArgs), uno::UNO_QUERY );
659                 xSaxWriter.set(xDocHandler,uno::UNO_QUERY);
660             }
661             catch(uno::Exception&)
662             {
663                 OSL_ENSURE(0,"Exception caught!");
664             }
665         }
666 
667         uno::Sequence< uno::Any > aGraphicResolverArgs(1);
668         aGraphicResolverArgs[0] <<= xStorage;
669         Reference< document::XGraphicObjectResolver > xGraphicObjectResolver(
670             xServiceFactory->createInstanceWithArguments(
671                 C2U("com.sun.star.comp.Svx.GraphicExportHelper"), aGraphicResolverArgs ), uno::UNO_QUERY );
672 
673         uno::Reference< beans::XPropertySet > xInfoSet;
674         {
675             // property map for export info set
676             comphelper::PropertyMapEntry aExportInfoMap[] =
677 		    {
678 			    { MAP_LEN("UsePrettyPrinting"), 0, &::getBooleanCppuType(), beans::PropertyAttribute::MAYBEVOID, 0},
679 			    { MAP_LEN("BaseURI"), 0, &::getCppuType( (OUString *)0 ), beans::PropertyAttribute::MAYBEVOID, 0 },
680 			    { MAP_LEN("StreamRelPath"), 0, &::getCppuType( (OUString *)0 ), beans::PropertyAttribute::MAYBEVOID, 0 },
681 			    { MAP_LEN("StreamName"), 0, &::getCppuType( (OUString *)0 ), beans::PropertyAttribute::MAYBEVOID, 0 },
682                 { MAP_LEN("ExportTableNumberList"), 0, &::getBooleanCppuType(), beans::PropertyAttribute::MAYBEVOID, 0 },
683 			    { NULL, 0, 0, NULL, 0, 0 }
684 		    };
685 
686 		    xInfoSet = comphelper::GenericPropertySet_CreateInstance( new comphelper::PropertySetInfo( aExportInfoMap ) );
687 
688 		    SvtSaveOptions aSaveOpt;
689 		    OUString sUsePrettyPrinting(RTL_CONSTASCII_USTRINGPARAM("UsePrettyPrinting"));
690 		    sal_Bool bUsePrettyPrinting( aSaveOpt.IsPrettyPrinting() );
691 		    xInfoSet->setPropertyValue( sUsePrettyPrinting, uno::makeAny( bUsePrettyPrinting ) );
692             if( ! bOasis )
693                 xInfoSet->setPropertyValue( C2U("ExportTableNumberList"), uno::makeAny( true ));
694         }
695 
696         sal_Int32 nArgs = 2;
697 		if( xGraphicObjectResolver.is())
698 			nArgs++;
699 
700 		uno::Sequence< uno::Any > aFilterProperties( nArgs );
701         {
702 		    nArgs = 0;
703 		    aFilterProperties[ nArgs++ ] <<= xInfoSet;
704 		    aFilterProperties[ nArgs++ ] <<= xDocHandler;
705 		    if( xGraphicObjectResolver.is())
706 			    aFilterProperties[ nArgs++ ] <<= xGraphicObjectResolver;
707         }
708 
709 //         bool bOasis = (SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60);
710 
711         // export meta information
712         if( bOasis )
713             nWarning |= impl_ExportStream(
714                 C2U( sXML_metaStreamName ),
715                 C2U( sXML_export_chart_oasis_meta_service ),
716                 xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
717 
718         // export styles
719         nWarning |= impl_ExportStream(
720             C2U( sXML_styleStreamName ),
721             bOasis
722             ? C2U( sXML_export_chart_oasis_styles_service )
723             : C2U( sXML_export_chart_styles_service ),
724             xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
725 
726         // export content
727         sal_Int32 nContentWarning = impl_ExportStream(
728             C2U( sXML_contentStreamName ),
729             bOasis
730             ? C2U( sXML_export_chart_oasis_content_service )
731             : C2U( sXML_export_chart_content_service ),
732             xStorage, xSaxWriter, xServiceFactory, aFilterProperties );
733         nWarning |= nContentWarning;
734 
735         Reference< lang::XComponent > xComp( xGraphicObjectResolver, uno::UNO_QUERY );
736         if( xComp.is())
737             xComp->dispose();
738 
739         uno::Reference<embed::XTransactedObject> xTransact( xStorage ,uno::UNO_QUERY);
740 		if ( xTransact.is() )
741 			xTransact->commit();
742     }
743     catch( uno::Exception & ex )
744     {
745         ASSERT_EXCEPTION( ex );
746 
747         // something went awry
748         nWarning = ERRCODE_SFX_GENERAL;
749     }
750 
751     return nWarning;
752 }
753 
impl_ExportStream(const OUString & rStreamName,const OUString & rServiceName,const Reference<embed::XStorage> & xStorage,const uno::Reference<io::XActiveDataSource> & xActiveDataSource,const Reference<lang::XMultiServiceFactory> & xServiceFactory,const Sequence<uno::Any> & rFilterProperties)754 sal_Int32 XMLFilter::impl_ExportStream(
755     const OUString & rStreamName,
756     const OUString & rServiceName,
757     const Reference< embed::XStorage > & xStorage,
758     const uno::Reference< io::XActiveDataSource >& xActiveDataSource,
759     const Reference< lang::XMultiServiceFactory >& xServiceFactory,
760     const Sequence< uno::Any > & rFilterProperties )
761 {
762     sal_Int32 nWarning = 0;
763 
764     try
765     {
766         if( !xServiceFactory.is() )
767             return ERRCODE_SFX_GENERAL;
768         if( !xStorage.is() )
769             return ERRCODE_SFX_GENERAL;
770         if ( !xActiveDataSource.is() )
771 		    return ERRCODE_SFX_GENERAL;
772 
773         uno::Reference< io::XStream > xStream( xStorage->openStreamElement(
774             rStreamName, embed::ElementModes::READWRITE | embed::ElementModes::TRUNCATE ) );
775 	    if ( !xStream.is() )
776 		    return ERRCODE_SFX_GENERAL;
777         uno::Reference< io::XOutputStream > xOutputStream( xStream->getOutputStream() );
778         if ( !xOutputStream.is() )
779 		    return ERRCODE_SFX_GENERAL;
780 
781         uno::Reference< beans::XPropertySet > xStreamProp( xOutputStream, uno::UNO_QUERY );
782         if(xStreamProp.is()) try
783         {
784             xStreamProp->setPropertyValue( C2U("MediaType"), uno::makeAny( C2U("text/xml") ) );
785             xStreamProp->setPropertyValue( C2U("Compressed"), uno::makeAny( sal_True ) );//@todo?
786             xStreamProp->setPropertyValue( C2U("UseCommonStoragePasswordEncryption"), uno::makeAny( sal_True ) );
787         }
788         catch( uno::Exception& rEx )
789 	    {
790             ASSERT_EXCEPTION( rEx );
791         }
792 
793         xActiveDataSource->setOutputStream(xOutputStream);
794 
795         // set Base URL
796         {
797 		    uno::Reference< beans::XPropertySet > xInfoSet;
798 		    if( rFilterProperties.getLength() > 0 )
799 			    rFilterProperties.getConstArray()[0] >>= xInfoSet;
800 		    OSL_ENSURE( xInfoSet.is(), "missing infoset for export" );
801 		    if( xInfoSet.is() )
802 			    xInfoSet->setPropertyValue( C2U("StreamName"), uno::makeAny( rStreamName ) );
803         }
804 
805 	    Reference< XExporter > xExporter( xServiceFactory->createInstanceWithArguments(
806             rServiceName, rFilterProperties ), uno::UNO_QUERY);
807         if ( !xExporter.is() )
808 		    return ERRCODE_SFX_GENERAL;
809 
810         xExporter->setSourceDocument( m_xSourceDoc );
811 
812         uno::Reference< document::XFilter > xFilter( xExporter, uno::UNO_QUERY );
813         if ( !xFilter.is() )
814 		    return ERRCODE_SFX_GENERAL;
815 
816         uno::Sequence < beans::PropertyValue > aMediaDesc(0);
817         //@todo? filter properties? ... url? ...
818 	    xFilter->filter( aMediaDesc );
819     }
820     catch( uno::Exception& rEx )
821 	{
822         ASSERT_EXCEPTION( rEx );
823     }
824     return nWarning;
825 }
826 
827 // --------------------------------------------------------------------------------
828 
getSupportedServiceNames_Static()829 Sequence< OUString > XMLFilter::getSupportedServiceNames_Static()
830 {
831     Sequence< OUString > aServices( 2 );
832     aServices[ 0 ] = C2U( "com.sun.star.document.ImportFilter" );
833     aServices[ 1 ] = C2U( "com.sun.star.document.ExportFilter" );
834 
835     // todo: services are incomplete.  Missing:
836     // XInitialization, XNamed
837     return aServices;
838 }
839 // -----------------------------------------------------------------------------
840 
isOasisFormat(const Sequence<beans::PropertyValue> & _rMediaDescriptor,bool & rOutOASIS)841 void XMLFilter::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS )
842 {
843     apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor );
844     if( aMDHelper.ISSET_FilterName )
845         rOutOASIS = aMDHelper.FilterName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("chart8"));
846 }
847 // -----------------------------------------------------------------------------
getMediaType(bool _bOasis)848 ::rtl::OUString XMLFilter::getMediaType(bool _bOasis)
849 {
850     return _bOasis ? MIMETYPE_OASIS_OPENDOCUMENT_CHART : MIMETYPE_VND_SUN_XML_CHART;
851 }
852 // -----------------------------------------------------------------------------
853 
854 APPHELPER_XSERVICEINFO_IMPL( XMLFilter, C2U( "com.sun.star.comp.chart2.XMLFilter" ) );
855 // -----------------------------------------------------------------------------
856 
isOasisFormat(const Sequence<beans::PropertyValue> & _rMediaDescriptor,bool & rOutOASIS)857 void XMLReportFilterHelper::isOasisFormat(const Sequence< beans::PropertyValue >& _rMediaDescriptor, bool & rOutOASIS )
858 {
859     apphelper::MediaDescriptorHelper aMDHelper( _rMediaDescriptor );
860     if( aMDHelper.ISSET_FilterName )
861         rOutOASIS = aMDHelper.FilterName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("StarOffice XML (Base) Report Chart"));
862 }
863 // -----------------------------------------------------------------------------
getMediaType(bool)864 ::rtl::OUString XMLReportFilterHelper::getMediaType(bool )
865 {
866     return MIMETYPE_OASIS_OPENDOCUMENT_REPORT_CHART;
867 }
868 
869 } //  namespace chart
870