Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <sal/config.h>
21 :
22 : #include <boost/noncopyable.hpp>
23 : #include <com/sun/star/container/XNameAccess.hpp>
24 : #include <com/sun/star/drawing/XShape.hpp>
25 : #include <com/sun/star/frame/XModel.hpp>
26 : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
27 : #include <com/sun/star/task/XInteractionHandler.hpp>
28 : #include <com/sun/star/task/XStatusIndicator.hpp>
29 : #include <com/sun/star/uno/XComponentContext.hpp>
30 : #include <comphelper/docpasswordhelper.hxx>
31 : #include <cppuhelper/supportsservice.hxx>
32 : #include <unotools/mediadescriptor.hxx>
33 : #include <osl/mutex.hxx>
34 : #include <osl/diagnose.h>
35 : #include <rtl/instance.hxx>
36 : #include <rtl/uri.hxx>
37 : #include <memory>
38 : #include <set>
39 :
40 : #include "oox/core/filterbase.hxx"
41 : #include "oox/helper/binaryinputstream.hxx"
42 : #include "oox/helper/binaryoutputstream.hxx"
43 : #include "oox/helper/graphichelper.hxx"
44 : #include "oox/helper/modelobjecthelper.hxx"
45 : #include "oox/ole/oleobjecthelper.hxx"
46 : #include "oox/ole/vbaproject.hxx"
47 :
48 : namespace oox {
49 : namespace core {
50 :
51 : using namespace ::com::sun::star::beans;
52 : using namespace ::com::sun::star::frame;
53 : using namespace ::com::sun::star::graphic;
54 : using namespace ::com::sun::star::drawing;
55 : using namespace ::com::sun::star::io;
56 : using namespace ::com::sun::star::lang;
57 : using namespace ::com::sun::star::task;
58 : using namespace ::com::sun::star::uno;
59 :
60 : using ::com::sun::star::container::XNameAccess;
61 : using utl::MediaDescriptor;
62 : using ::comphelper::SequenceAsHashMap;
63 : using ::oox::ole::OleObjectHelper;
64 : using ::oox::ole::VbaProject;
65 :
66 : namespace {
67 :
68 48 : struct UrlPool
69 : {
70 : ::osl::Mutex maMutex;
71 : ::std::set< OUString > maUrls;
72 : };
73 :
74 : struct StaticUrlPool : public ::rtl::Static< UrlPool, StaticUrlPool > {};
75 :
76 : /** This guard prevents recursive loading/saving of the same document. */
77 : class DocumentOpenedGuard: private boost::noncopyable
78 : {
79 : public:
80 : explicit DocumentOpenedGuard( const OUString& rUrl );
81 : ~DocumentOpenedGuard();
82 :
83 2575 : inline bool isValid() const { return mbValid; }
84 :
85 : private:
86 : OUString maUrl;
87 : bool mbValid;
88 : };
89 :
90 2575 : DocumentOpenedGuard::DocumentOpenedGuard( const OUString& rUrl )
91 : {
92 2575 : UrlPool& rUrlPool = StaticUrlPool::get();
93 2575 : ::osl::MutexGuard aGuard( rUrlPool.maMutex );
94 2575 : mbValid = rUrl.isEmpty() || (rUrlPool.maUrls.count( rUrl ) == 0);
95 2575 : if( mbValid && !rUrl.isEmpty() )
96 : {
97 871 : rUrlPool.maUrls.insert( rUrl );
98 871 : maUrl = rUrl;
99 2575 : }
100 2575 : }
101 :
102 5150 : DocumentOpenedGuard::~DocumentOpenedGuard()
103 : {
104 2575 : UrlPool& rUrlPool = StaticUrlPool::get();
105 2575 : ::osl::MutexGuard aGuard( rUrlPool.maMutex );
106 2575 : if( !maUrl.isEmpty() )
107 871 : rUrlPool.maUrls.erase( maUrl );
108 2575 : }
109 :
110 : } // namespace
111 :
112 : /** Specifies whether this filter is an import or export filter. */
113 : enum FilterDirection
114 : {
115 : FILTERDIRECTION_UNKNOWN,
116 : FILTERDIRECTION_IMPORT,
117 : FILTERDIRECTION_EXPORT
118 : };
119 :
120 1675 : struct FilterBaseImpl
121 : {
122 : typedef std::shared_ptr< GraphicHelper > GraphicHelperRef;
123 : typedef std::shared_ptr< ModelObjectHelper > ModelObjHelperRef;
124 : typedef std::shared_ptr< OleObjectHelper > OleObjHelperRef;
125 : typedef std::shared_ptr< VbaProject > VbaProjectRef;
126 :
127 : FilterDirection meDirection;
128 : SequenceAsHashMap maArguments;
129 : SequenceAsHashMap maFilterData;
130 : MediaDescriptor maMediaDesc;
131 : OUString maFileUrl;
132 : StorageRef mxStorage;
133 : OoxmlVersion meVersion;
134 :
135 : GraphicHelperRef mxGraphicHelper; /// Graphic and graphic object handling.
136 : ModelObjHelperRef mxModelObjHelper; /// Tables to create new named drawing objects.
137 : OleObjHelperRef mxOleObjHelper; /// OLE object handling.
138 : VbaProjectRef mxVbaProject; /// VBA project manager.
139 :
140 : Reference< XComponentContext > mxComponentContext;
141 : Reference< XMultiComponentFactory > mxComponentFactory;
142 : Reference< XModel > mxModel;
143 : Reference< XMultiServiceFactory > mxModelFactory;
144 : Reference< XFrame > mxTargetFrame;
145 : Reference< XInputStream > mxInStream;
146 : Reference< XStream > mxOutStream;
147 : Reference< XStatusIndicator > mxStatusIndicator;
148 : Reference< XInteractionHandler > mxInteractionHandler;
149 : Reference< XShape > mxParentShape;
150 :
151 : explicit FilterBaseImpl( const Reference< XComponentContext >& rxContext ) throw( RuntimeException );
152 :
153 : void setDocumentModel( const Reference< XComponent >& rxComponent ) throw( IllegalArgumentException );
154 :
155 : void initializeFilter();
156 : };
157 :
158 1675 : FilterBaseImpl::FilterBaseImpl( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
159 : meDirection( FILTERDIRECTION_UNKNOWN ),
160 : meVersion( ECMA_DIALECT ),
161 : mxComponentContext( rxContext, UNO_SET_THROW ),
162 1675 : mxComponentFactory( rxContext->getServiceManager(), UNO_SET_THROW )
163 : {
164 1675 : }
165 :
166 2575 : void FilterBaseImpl::setDocumentModel( const Reference< XComponent >& rxComponent ) throw( IllegalArgumentException )
167 : {
168 : try
169 : {
170 2575 : mxModel.set( rxComponent, UNO_QUERY_THROW );
171 2575 : mxModelFactory.set( rxComponent, UNO_QUERY_THROW );
172 : }
173 0 : catch( Exception& )
174 : {
175 0 : throw IllegalArgumentException();
176 : }
177 2575 : }
178 :
179 2575 : void FilterBaseImpl::initializeFilter()
180 : {
181 : try
182 : {
183 : // lock the model controllers
184 2575 : mxModel->lockControllers();
185 : }
186 0 : catch( Exception& )
187 : {
188 : }
189 2575 : }
190 :
191 1675 : FilterBase::FilterBase( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
192 1675 : mxImpl( new FilterBaseImpl( rxContext ) )
193 : {
194 1675 : }
195 :
196 1675 : FilterBase::~FilterBase()
197 : {
198 1675 : }
199 :
200 849 : bool FilterBase::isImportFilter() const
201 : {
202 849 : return mxImpl->meDirection == FILTERDIRECTION_IMPORT;
203 : }
204 :
205 82 : bool FilterBase::isExportFilter() const
206 : {
207 82 : return mxImpl->meDirection == FILTERDIRECTION_EXPORT;
208 : }
209 :
210 15013 : OoxmlVersion FilterBase::getVersion() const
211 : {
212 15013 : return mxImpl->meVersion;
213 : }
214 :
215 12892 : const Reference< XComponentContext >& FilterBase::getComponentContext() const
216 : {
217 12892 : return mxImpl->mxComponentContext;
218 : }
219 :
220 5885 : const Reference< XModel >& FilterBase::getModel() const
221 : {
222 5885 : return mxImpl->mxModel;
223 : }
224 :
225 2558 : const Reference< XMultiServiceFactory >& FilterBase::getModelFactory() const
226 : {
227 2558 : return mxImpl->mxModelFactory;
228 : }
229 :
230 1027 : const Reference< XFrame >& FilterBase::getTargetFrame() const
231 : {
232 1027 : return mxImpl->mxTargetFrame;
233 : }
234 :
235 0 : const Reference< XShape >& FilterBase::getParentShape() const
236 : {
237 0 : return mxImpl->mxParentShape;
238 : }
239 :
240 309 : const Reference< XStatusIndicator >& FilterBase::getStatusIndicator() const
241 : {
242 309 : return mxImpl->mxStatusIndicator;
243 : }
244 :
245 936 : MediaDescriptor& FilterBase::getMediaDescriptor() const
246 : {
247 936 : return mxImpl->maMediaDesc;
248 : }
249 :
250 83 : SequenceAsHashMap& FilterBase::getFilterData() const
251 : {
252 83 : return mxImpl->maFilterData;
253 : }
254 :
255 26 : const OUString& FilterBase::getFileUrl() const
256 : {
257 26 : return mxImpl->maFileUrl;
258 : }
259 :
260 : namespace {
261 :
262 10 : inline bool lclIsDosDrive( const OUString& rUrl, sal_Int32 nPos = 0 )
263 : {
264 : return
265 20 : (rUrl.getLength() >= nPos + 3) &&
266 30 : ((('A' <= rUrl[ nPos ]) && (rUrl[ nPos ] <= 'Z')) || (('a' <= rUrl[ nPos ]) && (rUrl[ nPos ] <= 'z'))) &&
267 20 : (rUrl[ nPos + 1 ] == ':') &&
268 10 : (rUrl[ nPos + 2 ] == '/');
269 : }
270 :
271 : } // namespace
272 :
273 10 : OUString FilterBase::getAbsoluteUrl( const OUString& rUrl ) const
274 : {
275 : // handle some special cases before calling ::rtl::Uri::convertRelToAbs()
276 :
277 10 : const OUString aFileSchema = "file:";
278 20 : const OUString aFilePrefix = "file:///";
279 10 : const sal_Int32 nFilePrefixLen = aFilePrefix.getLength();
280 20 : const OUString aUncPrefix = "//";
281 :
282 : /* (1) convert all backslashes to slashes, and check that passed URL is
283 : not empty. */
284 20 : OUString aUrl = rUrl.replace( '\\', '/' );
285 10 : if( aUrl.isEmpty() )
286 0 : return aUrl;
287 :
288 : /* (2) add 'file:///' to absolute Windows paths, e.g. convert
289 : 'C:/path/file' to 'file:///c:/path/file'. */
290 10 : if( lclIsDosDrive( aUrl ) )
291 0 : return aFilePrefix + aUrl;
292 :
293 : /* (3) add 'file:' to UNC paths, e.g. convert '//server/path/file' to
294 : 'file://server/path/file'. */
295 10 : if( aUrl.match( aUncPrefix ) )
296 0 : return aFileSchema + aUrl;
297 :
298 : /* (4) remove additional slashes from UNC paths, e.g. convert
299 : 'file://///server/path/file' to 'file://server/path/file'. */
300 29 : if( (aUrl.getLength() >= nFilePrefixLen + 2) &&
301 14 : aUrl.match( aFilePrefix ) &&
302 4 : aUrl.match( aUncPrefix, nFilePrefixLen ) )
303 : {
304 0 : return aFileSchema + aUrl.copy( nFilePrefixLen );
305 : }
306 :
307 : /* (5) handle URLs relative to current drive, e.g. the URL '/path1/file1'
308 : relative to the base URL 'file:///C:/path2/file2' does not result in
309 : the expected 'file:///C:/path1/file1', but in 'file:///path1/file1'. */
310 20 : if( aUrl.startsWith("/") &&
311 10 : mxImpl->maFileUrl.match( aFilePrefix ) &&
312 0 : lclIsDosDrive( mxImpl->maFileUrl, nFilePrefixLen ) )
313 : {
314 0 : return mxImpl->maFileUrl.copy( 0, nFilePrefixLen + 3 ) + aUrl.copy( 1 );
315 : }
316 :
317 : try
318 : {
319 10 : return ::rtl::Uri::convertRelToAbs( mxImpl->maFileUrl, aUrl );
320 : }
321 0 : catch( ::rtl::MalformedUriException& )
322 : {
323 : }
324 10 : return aUrl;
325 : }
326 :
327 3189 : StorageRef FilterBase::getStorage() const
328 : {
329 3189 : return mxImpl->mxStorage;
330 : }
331 :
332 7099 : Reference< XInputStream > FilterBase::openInputStream( const OUString& rStreamName ) const
333 : {
334 7099 : return mxImpl->mxStorage->openInputStream( rStreamName );
335 : }
336 :
337 7393 : Reference< XOutputStream > FilterBase::openOutputStream( const OUString& rStreamName ) const
338 : {
339 7393 : return mxImpl->mxStorage->openOutputStream( rStreamName );
340 : }
341 :
342 563 : void FilterBase::commitStorage() const
343 : {
344 563 : mxImpl->mxStorage->commit();
345 563 : }
346 :
347 : // helpers
348 :
349 42234 : GraphicHelper& FilterBase::getGraphicHelper() const
350 : {
351 42234 : if( !mxImpl->mxGraphicHelper )
352 1027 : mxImpl->mxGraphicHelper.reset( implCreateGraphicHelper() );
353 42234 : return *mxImpl->mxGraphicHelper;
354 : }
355 :
356 4158 : ModelObjectHelper& FilterBase::getModelObjectHelper() const
357 : {
358 4158 : if( !mxImpl->mxModelObjHelper )
359 879 : mxImpl->mxModelObjHelper.reset( new ModelObjectHelper( mxImpl->mxModelFactory ) );
360 4158 : return *mxImpl->mxModelObjHelper;
361 : }
362 :
363 4 : OleObjectHelper& FilterBase::getOleObjectHelper() const
364 : {
365 4 : if( !mxImpl->mxOleObjHelper )
366 3 : mxImpl->mxOleObjHelper.reset( new OleObjectHelper( mxImpl->mxModelFactory ) );
367 4 : return *mxImpl->mxOleObjHelper;
368 : }
369 :
370 2 : VbaProject& FilterBase::getVbaProject() const
371 : {
372 2 : if( !mxImpl->mxVbaProject )
373 1 : mxImpl->mxVbaProject.reset( implCreateVbaProject() );
374 2 : return *mxImpl->mxVbaProject;
375 : }
376 :
377 101 : bool FilterBase::importBinaryData( StreamDataSequence& orDataSeq, const OUString& rStreamName )
378 : {
379 : OSL_ENSURE( !rStreamName.isEmpty(), "FilterBase::importBinaryData - empty stream name" );
380 101 : if( rStreamName.isEmpty() )
381 0 : return false;
382 :
383 : // try to open the stream (this may fail - do not assert)
384 101 : BinaryXInputStream aInStrm( openInputStream( rStreamName ), true );
385 101 : if( aInStrm.isEof() )
386 0 : return false;
387 :
388 : // copy the entire stream to the passed sequence
389 202 : SequenceOutputStream aOutStrm( orDataSeq );
390 101 : aInStrm.copyToStream( aOutStrm );
391 202 : return true;
392 : }
393 :
394 : // com.sun.star.lang.XServiceInfo interface
395 :
396 0 : sal_Bool SAL_CALL FilterBase::supportsService( const OUString& rServiceName ) throw( RuntimeException, std::exception )
397 : {
398 0 : return cppu::supportsService(this, rServiceName);
399 : }
400 :
401 2 : Sequence< OUString > SAL_CALL FilterBase::getSupportedServiceNames() throw( RuntimeException, std::exception )
402 : {
403 2 : Sequence< OUString > aServiceNames( 2 );
404 2 : aServiceNames[ 0 ] = "com.sun.star.document.ImportFilter";
405 2 : aServiceNames[ 1 ] = "com.sun.star.document.ExportFilter";
406 2 : return aServiceNames;
407 : }
408 :
409 : // com.sun.star.lang.XInitialization interface
410 :
411 310 : void SAL_CALL FilterBase::initialize( const Sequence< Any >& rArgs ) throw( Exception, RuntimeException, std::exception )
412 : {
413 310 : if( rArgs.getLength() >= 2 ) try
414 : {
415 0 : mxImpl->maArguments << rArgs[ 1 ];
416 : }
417 0 : catch( Exception& )
418 : {
419 : }
420 310 : }
421 :
422 : // com.sun.star.document.XImporter interface
423 :
424 1931 : void SAL_CALL FilterBase::setTargetDocument( const Reference< XComponent >& rxDocument ) throw( IllegalArgumentException, RuntimeException, std::exception )
425 : {
426 1931 : mxImpl->setDocumentModel( rxDocument );
427 1931 : mxImpl->meDirection = FILTERDIRECTION_IMPORT;
428 1931 : }
429 :
430 : // com.sun.star.document.XExporter interface
431 :
432 644 : void SAL_CALL FilterBase::setSourceDocument( const Reference< XComponent >& rxDocument ) throw( IllegalArgumentException, RuntimeException, std::exception )
433 : {
434 644 : mxImpl->setDocumentModel( rxDocument );
435 644 : mxImpl->meDirection = FILTERDIRECTION_EXPORT;
436 644 : }
437 :
438 : // com.sun.star.document.XFilter interface
439 :
440 2575 : sal_Bool SAL_CALL FilterBase::filter( const Sequence< PropertyValue >& rMediaDescSeq ) throw( RuntimeException, std::exception )
441 : {
442 2575 : if( !mxImpl->mxModel.is() || !mxImpl->mxModelFactory.is() || (mxImpl->meDirection == FILTERDIRECTION_UNKNOWN) )
443 0 : throw RuntimeException();
444 :
445 2575 : bool bRet = false;
446 2575 : setMediaDescriptor( rMediaDescSeq );
447 2575 : DocumentOpenedGuard aOpenedGuard( mxImpl->maFileUrl );
448 2575 : if( aOpenedGuard.isValid() || mxImpl->maFileUrl.isEmpty() )
449 : {
450 2575 : mxImpl->initializeFilter();
451 2575 : switch( mxImpl->meDirection )
452 : {
453 : case FILTERDIRECTION_UNKNOWN:
454 0 : break;
455 : case FILTERDIRECTION_IMPORT:
456 1931 : if( mxImpl->mxInStream.is() )
457 : {
458 1930 : mxImpl->mxStorage = implCreateStorage( mxImpl->mxInStream );
459 1930 : bRet = mxImpl->mxStorage.get() && importDocument();
460 : }
461 1931 : break;
462 : case FILTERDIRECTION_EXPORT:
463 644 : if( mxImpl->mxOutStream.is() )
464 : {
465 644 : mxImpl->mxStorage = implCreateStorage( mxImpl->mxOutStream );
466 644 : bRet = mxImpl->mxStorage.get() && exportDocument() && implFinalizeExport( getMediaDescriptor() );
467 : }
468 644 : break;
469 : }
470 2575 : mxImpl->mxModel->unlockControllers();
471 : }
472 2575 : return bRet;
473 : }
474 :
475 0 : void SAL_CALL FilterBase::cancel() throw( RuntimeException, std::exception )
476 : {
477 0 : }
478 :
479 : // protected
480 :
481 0 : Reference< XInputStream > FilterBase::implGetInputStream( MediaDescriptor& rMediaDesc ) const
482 : {
483 0 : return rMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INPUTSTREAM(), Reference< XInputStream >() );
484 : }
485 :
486 644 : Reference< XStream > FilterBase::implGetOutputStream( MediaDescriptor& rMediaDesc ) const
487 : {
488 644 : return rMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_STREAMFOROUTPUT(), Reference< XStream >() );
489 : }
490 :
491 0 : bool FilterBase::implFinalizeExport( MediaDescriptor& /*rMediaDescriptor*/ )
492 : {
493 0 : return true;
494 : }
495 :
496 0 : Reference< XStream > FilterBase::getMainDocumentStream( ) const
497 : {
498 0 : return mxImpl->mxOutStream;
499 : }
500 :
501 : // private
502 :
503 2575 : void FilterBase::setMediaDescriptor( const Sequence< PropertyValue >& rMediaDescSeq )
504 : {
505 2575 : mxImpl->maMediaDesc << rMediaDescSeq;
506 :
507 2575 : switch( mxImpl->meDirection )
508 : {
509 : case FILTERDIRECTION_UNKNOWN:
510 : OSL_FAIL( "FilterBase::setMediaDescriptor - invalid filter direction" );
511 0 : break;
512 : case FILTERDIRECTION_IMPORT:
513 1931 : mxImpl->maMediaDesc.addInputStream();
514 1931 : mxImpl->mxInStream = implGetInputStream( mxImpl->maMediaDesc );
515 : OSL_ENSURE( mxImpl->mxInStream.is(), "FilterBase::setMediaDescriptor - missing input stream" );
516 1931 : break;
517 : case FILTERDIRECTION_EXPORT:
518 644 : mxImpl->mxOutStream = implGetOutputStream( mxImpl->maMediaDesc );
519 : OSL_ENSURE( mxImpl->mxOutStream.is(), "FilterBase::setMediaDescriptor - missing output stream" );
520 644 : break;
521 : }
522 :
523 2575 : mxImpl->maFileUrl = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_URL(), OUString() );
524 2575 : mxImpl->mxTargetFrame = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_FRAME(), Reference< XFrame >() );
525 2575 : mxImpl->mxStatusIndicator = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_STATUSINDICATOR(), Reference< XStatusIndicator >() );
526 2575 : mxImpl->mxInteractionHandler = mxImpl->maMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INTERACTIONHANDLER(), Reference< XInteractionHandler >() );
527 2575 : mxImpl->mxParentShape = mxImpl->maMediaDesc.getUnpackedValueOrDefault( "ParentShape", mxImpl->mxParentShape );
528 2575 : mxImpl->maFilterData = mxImpl->maMediaDesc.getUnpackedValueOrDefault( "FilterData", Sequence< PropertyValue >() );
529 :
530 : // Check for ISO OOXML
531 2575 : OUString sFilterName = mxImpl->maMediaDesc.getUnpackedValueOrDefault( "FilterName", OUString() );
532 : try
533 : {
534 2575 : Reference<XMultiServiceFactory> xFactory(getComponentContext()->getServiceManager(), UNO_QUERY_THROW);
535 5150 : Reference<XNameAccess> xFilters(xFactory->createInstance("com.sun.star.document.FilterFactory" ), UNO_QUERY_THROW );
536 3446 : Any aValues = xFilters->getByName( sFilterName );
537 1742 : Sequence<PropertyValue > aPropSeq;
538 871 : aValues >>= aPropSeq;
539 1742 : SequenceAsHashMap aProps( aPropSeq );
540 :
541 871 : sal_Int32 nVersion = aProps.getUnpackedValueOrDefault( "FileFormatVersion", sal_Int32( 0 ) );
542 3446 : mxImpl->meVersion = OoxmlVersion( nVersion );
543 : }
544 1704 : catch ( const Exception& )
545 : {
546 : // Not ISO OOXML
547 2575 : }
548 2575 : }
549 :
550 0 : GraphicHelper* FilterBase::implCreateGraphicHelper() const
551 : {
552 : // default: return base implementation without any special behaviour
553 0 : return new GraphicHelper( mxImpl->mxComponentContext, mxImpl->mxTargetFrame, mxImpl->mxStorage );
554 : }
555 :
556 : } // namespace core
557 246 : } // namespace oox
558 :
559 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|