xref: /aoo41x/main/sd/source/ui/unoidl/sddetect.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sd.hxx"
30 
31 #include "sddetect.hxx"
32 
33 #include <framework/interaction.hxx>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/beans/PropertyValue.hpp>
36 #include <com/sun/star/frame/XFrame.hpp>
37 #include <com/sun/star/frame/XModel.hpp>
38 #include <com/sun/star/awt/XWindow.hpp>
39 #include <com/sun/star/lang/XUnoTunnel.hpp>
40 #include <comphelper/processfactory.hxx>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/io/XInputStream.hpp>
44 #include <com/sun/star/task/XInteractionHandler.hpp>
45 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
46 #include <com/sun/star/ucb/CommandAbortedException.hpp>
47 #include <com/sun/star/ucb/InteractiveAppException.hpp>
48 #include <com/sun/star/ucb/XContent.hpp>
49 #include <com/sun/star/packages/zip/ZipIOException.hpp>
50 #include <framework/interaction.hxx>
51 #include <toolkit/helper/vclunohelper.hxx>
52 #include <ucbhelper/simpleinteractionrequest.hxx>
53 #include <svtools/filter.hxx>
54 #include <rtl/ustring.h>
55 #include <rtl/logfile.hxx>
56 #include <svl/itemset.hxx>
57 #include <vcl/window.hxx>
58 #include <svl/eitem.hxx>
59 #include <svl/stritem.hxx>
60 #include <tools/urlobj.hxx>
61 #include <vos/mutex.hxx>
62 #include <svtools/sfxecode.hxx>
63 #include <svtools/ehdl.hxx>
64 #include <sot/storinfo.hxx>
65 #include <vcl/svapp.hxx>
66 #include <sfx2/app.hxx>
67 #include <sfx2/sfxsids.hrc>
68 #include <sfx2/request.hxx>
69 #include <sfx2/docfile.hxx>
70 #include <sfx2/docfilt.hxx>
71 #include <sfx2/fcontnr.hxx>
72 #include <sfx2/brokenpackageint.hxx>
73 #include <svtools/FilterConfigItem.hxx>
74 #include <sot/storage.hxx>
75 #include <unotools/moduleoptions.hxx>
76 #include <com/sun/star/util/XArchiver.hpp>
77 #include <comphelper/processfactory.hxx>
78 
79 #include "strmname.h"
80 
81 using namespace ::com::sun::star;
82 using namespace ::com::sun::star::uno;
83 using namespace ::com::sun::star::io;
84 using namespace ::com::sun::star::frame;
85 using namespace ::com::sun::star::task;
86 using namespace ::com::sun::star::beans;
87 using namespace ::com::sun::star::lang;
88 using namespace ::com::sun::star::ucb;
89 using namespace ::rtl;
90 
91 SdFilterDetect::SdFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >&  )
92 {
93 }
94 
95 SdFilterDetect::~SdFilterDetect()
96 {
97 }
98 
99 ::rtl::OUString SAL_CALL SdFilterDetect::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( ::com::sun::star::uno::RuntimeException )
100 {
101     REFERENCE< XInputStream > xStream;
102     REFERENCE< XContent > xContent;
103     REFERENCE< XInteractionHandler > xInteraction;
104     String aURL;
105 	::rtl::OUString sTemp;
106     String aTypeName;            // a name describing the type (from MediaDescriptor, usually from flat detection)
107     String aPreselectedFilterName;      // a name describing the filter to use (from MediaDescriptor, usually from UI action)
108 
109 	::rtl::OUString aDocumentTitle; // interesting only if set in this method
110 
111 	// opening as template is done when a parameter tells to do so and a template filter can be detected
112     // (otherwise no valid filter would be found) or if the detected filter is a template filter and
113 	// there is no parameter that forbids to open as template
114 	sal_Bool bOpenAsTemplate = sal_False;
115     sal_Bool bWasReadOnly = sal_False, bReadOnly = sal_False;
116 
117 	sal_Bool bRepairPackage = sal_False;
118 	sal_Bool bRepairAllowed = sal_False;
119 
120 	// now some parameters that can already be in the array, but may be overwritten or new inserted here
121 	// remember their indices in the case new values must be added to the array
122 	sal_Int32 nPropertyCount = lDescriptor.getLength();
123     sal_Int32 nIndexOfFilterName = -1;
124     sal_Int32 nIndexOfInputStream = -1;
125     sal_Int32 nIndexOfContent = -1;
126     sal_Int32 nIndexOfReadOnlyFlag = -1;
127     sal_Int32 nIndexOfTemplateFlag = -1;
128     sal_Int32 nIndexOfDocumentTitle = -1;
129 
130     for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
131 	{
132         // extract properties
133         if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("URL")) )
134 		{
135 			lDescriptor[nProperty].Value >>= sTemp;
136 			aURL = sTemp;
137 		}
138         else if( !aURL.Len() && lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")) )
139 		{
140 			lDescriptor[nProperty].Value >>= sTemp;
141 			aURL = sTemp;
142 		}
143         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")) )
144 		{
145 			lDescriptor[nProperty].Value >>= sTemp;
146             aTypeName = sTemp;
147 		}
148         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName")) )
149 		{
150 			lDescriptor[nProperty].Value >>= sTemp;
151             aPreselectedFilterName = sTemp;
152 
153             // if the preselected filter name is not correct, it must be erased after detection
154             // remember index of property to get access to it later
155             nIndexOfFilterName = nProperty;
156 		}
157         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream")) )
158             nIndexOfInputStream = nProperty;
159         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")) )
160             nIndexOfReadOnlyFlag = nProperty;
161         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("UCBContent")) )
162             nIndexOfContent = nProperty;
163         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("AsTemplate")) )
164 		{
165 			lDescriptor[nProperty].Value >>= bOpenAsTemplate;
166             nIndexOfTemplateFlag = nProperty;
167 		}
168         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler")) )
169             lDescriptor[nProperty].Value >>= xInteraction;
170         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("RepairPackage")) )
171             lDescriptor[nProperty].Value >>= bRepairPackage;
172         else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle")) )
173             nIndexOfDocumentTitle = nProperty;
174 	}
175 
176     // can't check the type for external filters, so set the "dont" flag accordingly
177     ::vos::OGuard aGuard( Application::GetSolarMutex() );
178     //SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED;
179 
180     SfxApplication* pApp = SFX_APP();
181     SfxAllItemSet *pSet = new SfxAllItemSet( pApp->GetPool() );
182     TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
183     SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, sal_False );
184 
185     bWasReadOnly = pItem && pItem->GetValue();
186 
187 	const SfxFilter* pFilter = 0;
188 	String aFilterName;
189 	String aPrefix = String::CreateFromAscii( "private:factory/" );
190 	if( aURL.Match( aPrefix ) == aPrefix.Len() )
191 	{
192 		if( SvtModuleOptions().IsImpress() )
193 		{
194 			String aPattern( aPrefix );
195 			aPattern += String::CreateFromAscii("simpress");
196 			if ( aURL.Match( aPattern ) >= aPattern.Len() )
197 				pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
198 		}
199 
200 		if( !pFilter && SvtModuleOptions().IsDraw() )
201 		{
202 			String aPattern( aPrefix );
203 			aPattern += String::CreateFromAscii("sdraw");
204 			if ( aURL.Match( aPattern ) >= aPattern.Len() )
205 				pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
206 		}
207 	}
208 	else
209 	{
210 	    // ctor of SfxMedium uses owner transition of ItemSet
211 	    SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, sal_False, NULL, pSet );
212 	    aMedium.UseInteractionHandler( sal_True );
213 		if ( aPreselectedFilterName.Len() )
214 			pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
215 		else if( aTypeName.Len() )
216 		{
217 			SfxFilterMatcher aMatch;
218 			pFilter = aMatch.GetFilter4EA( aTypeName );
219 		}
220 
221 	    if ( aMedium.GetErrorCode() == ERRCODE_NONE )
222 	    {
223 	        // remember input stream and content and put them into the descriptor later
224 			// should be done here since later the medium can switch to a version
225 	        xStream = aMedium.GetInputStream();
226 			xContent = aMedium.GetContent();
227             bReadOnly = aMedium.IsReadOnly();
228             sal_Bool bIsStorage = aMedium.IsStorage();
229 
230             if (aMedium.GetError() == SVSTREAM_OK)
231 			{
232 				if ( bIsStorage )
233 				{
234 					// PowerPoint needs to be detected via StreamName, all other storage based formats are our own and can
235 					// be detected by the ClipboardId, so except for the PPT filter all filters must have a ClipboardId set
236                     uno::Reference < embed::XStorage > xStorage = aMedium.GetStorage( sal_False );
237 
238                     //TODO/LATER: move error handling to central place! (maybe even complete own filters)
239                     if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
240 					{
241 						// error during storage creation means _here_ that the medium
242 						// is broken, but we can not handle it in medium since unpossibility
243 						// to create a storage does not _always_ means that the medium is broken
244 						aMedium.SetError( aMedium.GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
245 						if ( xInteraction.is() )
246 						{
247 							OUString empty;
248 							try
249 							{
250 								InteractiveAppException xException( empty,
251 																REFERENCE< XInterface >(),
252 																InteractionClassification_ERROR,
253 																aMedium.GetError() );
254 
255                                 REFERENCE< XInteractionRequest > xRequest(
256 									new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
257 																	 	 ucbhelper::CONTINUATION_APPROVE ) );
258 								xInteraction->handle( xRequest );
259 							}
260 							catch ( Exception & ) {};
261 						}
262 					}
263 					else
264 					{
265                         if ( pFilter && !pFilter->GetFormat() )
266                             // preselected Filter has no ClipboardId -> doesn't match (see comment above)
267                             pFilter = 0;
268 
269                         // the storage must be checked even if filter is already found, since it is deep type detection
270 						// the storage can be corrupted and it will be detected here
271 						try
272 						{
273                             String sFilterName;
274                             if ( pFilter )
275                                 sFilterName = pFilter->GetName();
276                             aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : sal_False, &sFilterName );
277 						}
278 						catch( lang::WrappedTargetException& aWrap )
279 						{
280 							packages::zip::ZipIOException aZipException;
281 							if ( ( aWrap.TargetException >>= aZipException ) && aTypeName.Len() )
282 							{
283 								if ( xInteraction.is() )
284 								{
285 									// the package is broken one
286        								aDocumentTitle = aMedium.GetURLObject().getName(
287 																INetURLObject::LAST_SEGMENT,
288 																true,
289 																INetURLObject::DECODE_WITH_CHARSET );
290 
291 									if ( !bRepairPackage )
292 									{
293 										// ask the user whether he wants to try to repair
294                                         RequestPackageReparation aRequest( aDocumentTitle );
295                                         xInteraction->handle( aRequest.GetRequest() );
296                                         bRepairAllowed = aRequest.isApproved();
297 									}
298 
299 									if ( !bRepairAllowed )
300 									{
301                                         // repair either not allowed or not successful
302                                         NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
303                                         xInteraction->handle( aNotifyRequest.GetRequest() );
304 									}
305 								}
306 
307 								if ( !bRepairAllowed )
308 								{
309 									aTypeName.Erase();
310 									pFilter = 0;
311 								}
312 							}
313 						}
314 						catch( uno::RuntimeException& )
315 						{
316 							throw;
317 						}
318 						catch( uno::Exception& )
319 						{
320 							aTypeName.Erase();
321 							pFilter = 0;
322 						}
323 
324                         if ( !pFilter && aTypeName.Len() )
325                         {
326                             //TODO/LATER: using this method impress is always preferred if no flat detecion has been made
327                             // this should been discussed!
328                             if ( SvtModuleOptions().IsImpress() )
329                                 pFilter = SfxFilterMatcher( String::CreateFromAscii("simpress") ).GetFilter4EA( aTypeName );
330                             else if ( SvtModuleOptions().IsDraw() )
331                                 pFilter = SfxFilterMatcher( String::CreateFromAscii("sdraw") ).GetFilter4EA( aTypeName );
332                         }
333 					}
334 				}
335 				else
336 				{
337 					SvStream* pStm = aMedium.GetInStream();
338                     if ( !pStm )
339                     {
340                         pFilter = 0;
341                     }
342                     else
343                     {
344                         SotStorageRef aStorage = new SotStorage ( pStm, sal_False );
345                         if ( !aStorage->GetError() )
346                         {
347                             String aStreamName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "PowerPoint Document" ) );
348                             if ( aStorage->IsStream( aStreamName ) && SvtModuleOptions().IsImpress() )
349                             {
350                                 String aFileName(aMedium.GetName());
351                                 aFileName.ToUpperAscii();
352 
353                                 if( aFileName.SearchAscii( ".POT" ) == STRING_NOTFOUND )
354                                     pFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97);
355                                 else
356                                     pFilter = SfxFilter::GetFilterByName( pFilterPowerPoint97Template );
357                             }
358                         }
359                         else
360                         {
361                             // Vektorgraphik?
362                             pStm->Seek( STREAM_SEEK_TO_BEGIN );
363 
364                             const String        aFileName( aMedium.GetURLObject().GetMainURL( INetURLObject::NO_DECODE ) );
365                             GraphicDescriptor   aDesc( *pStm, &aFileName );
366                             GraphicFilter*      pGrfFilter = GraphicFilter::GetGraphicFilter();
367                             if( !aDesc.Detect( sal_False ) )
368                             {
369                                 pFilter = 0;
370                                 if( SvtModuleOptions().IsImpress() )
371                                 {
372                                     INetURLObject aCheckURL( aFileName );
373                                     if( aCheckURL.getExtension().equalsIgnoreAsciiCaseAscii( "cgm" ) )
374                                     {
375                                         sal_uInt8 n8;
376                                         pStm->Seek( STREAM_SEEK_TO_BEGIN );
377                                         *pStm >> n8;
378                                         if ( ( n8 & 0xf0 ) == 0 )       // we are supporting binary cgm format only, so
379                                         {                               // this is a small test to exclude cgm text
380                                             const String aName = UniString::CreateFromAscii( RTL_CONSTASCII_STRINGPARAM( "CGM - Computer Graphics Metafile" ) );
381                                             SfxFilterMatcher aMatch( String::CreateFromAscii("simpress") );
382                                             pFilter = aMatch.GetFilter4FilterName( aName );
383                                         }
384                                     }
385                                 }
386                             }
387                             else
388                             {
389                                 String aShortName( aDesc.GetImportFormatShortName( aDesc.GetFileFormat() ) );
390                                 const String aName( pGrfFilter->GetImportFormatTypeName( pGrfFilter->GetImportFormatNumberForShortName( aShortName ) ) );
391 
392                                 if ( pFilter && aShortName.EqualsIgnoreCaseAscii( "PCD" ) )    // there is a multiple pcd selection possible
393                                 {
394                                     sal_Int32 nBase = 2;    // default Base0
395                                     String aFilterTypeName( pFilter->GetRealTypeName() );
396                                     if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base4" ) == COMPARE_EQUAL )
397                                         nBase = 1;
398                                     else if ( aFilterTypeName.CompareToAscii( "pcd_Photo_CD_Base16" ) == COMPARE_EQUAL )
399                                         nBase = 0;
400                                     String aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Import/PCD" ) );
401                                     FilterConfigItem aFilterConfigItem( aFilterConfigPath );
402                                     aFilterConfigItem.WriteInt32( String( RTL_CONSTASCII_USTRINGPARAM( "Resolution" ) ), nBase );
403                                 }
404 
405                                 SfxFilterMatcher aMatch( String::CreateFromAscii("sdraw") );
406                                 pFilter = aMatch.GetFilter4FilterName( aName );
407                             }
408                         }
409                     }
410 				}
411 			}
412 		}
413 	}
414 
415     if ( nIndexOfInputStream == -1 && xStream.is() )
416     {
417         // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
418         lDescriptor.realloc( nPropertyCount + 1 );
419         lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("InputStream");
420         lDescriptor[nPropertyCount].Value <<= xStream;
421         nPropertyCount++;
422     }
423 
424     if ( nIndexOfContent == -1 && xContent.is() )
425     {
426         // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
427         lDescriptor.realloc( nPropertyCount + 1 );
428         lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("UCBContent");
429         lDescriptor[nPropertyCount].Value <<= xContent;
430         nPropertyCount++;
431     }
432 
433     if ( bReadOnly != bWasReadOnly )
434     {
435         if ( nIndexOfReadOnlyFlag == -1 )
436         {
437             lDescriptor.realloc( nPropertyCount + 1 );
438             lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("ReadOnly");
439             lDescriptor[nPropertyCount].Value <<= bReadOnly;
440             nPropertyCount++;
441         }
442         else
443             lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
444     }
445 
446 	if ( !bRepairPackage && bRepairAllowed )
447 	{
448         lDescriptor.realloc( nPropertyCount + 1 );
449         lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("RepairPackage");
450         lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
451         nPropertyCount++;
452 
453 		bOpenAsTemplate = sal_True;
454 
455 		// TODO/LATER: set progress bar that should be used
456 	}
457 
458 	if ( bOpenAsTemplate )
459 	{
460 		if ( nIndexOfTemplateFlag == -1 )
461 		{
462         	lDescriptor.realloc( nPropertyCount + 1 );
463         	lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("AsTemplate");
464         	lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
465         	nPropertyCount++;
466 		}
467 		else
468         	lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
469 	}
470 
471 	if ( aDocumentTitle.getLength() )
472 	{
473 		// the title was set here
474 		if ( nIndexOfDocumentTitle == -1 )
475 		{
476         	lDescriptor.realloc( nPropertyCount + 1 );
477         	lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("DocumentTitle");
478         	lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
479         	nPropertyCount++;
480 		}
481 		else
482         	lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
483 	}
484 
485     if ( pFilter )
486         aTypeName = pFilter->GetTypeName();
487     else
488         aTypeName.Erase();
489 
490     return aTypeName;
491 }
492 
493 SFX_IMPL_SINGLEFACTORY( SdFilterDetect )
494 
495 /* XServiceInfo */
496 UNOOUSTRING SAL_CALL SdFilterDetect::getImplementationName() throw( UNORUNTIMEEXCEPTION )
497 {
498     return impl_getStaticImplementationName();
499 }
500                                                                                                                                 \
501 /* XServiceInfo */
502 sal_Bool SAL_CALL SdFilterDetect::supportsService( const UNOOUSTRING& sServiceName ) throw( UNORUNTIMEEXCEPTION )
503 {
504     UNOSEQUENCE< UNOOUSTRING >  seqServiceNames =   getSupportedServiceNames();
505     const UNOOUSTRING*          pArray          =   seqServiceNames.getConstArray();
506     for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ )
507     {
508         if ( pArray[nCounter] == sServiceName )
509         {
510             return sal_True ;
511         }
512     }
513     return sal_False ;
514 }
515 
516 /* XServiceInfo */
517 UNOSEQUENCE< UNOOUSTRING > SAL_CALL SdFilterDetect::getSupportedServiceNames() throw( UNORUNTIMEEXCEPTION )
518 {
519     return impl_getStaticSupportedServiceNames();
520 }
521 
522 /* Helper for XServiceInfo */
523 UNOSEQUENCE< UNOOUSTRING > SdFilterDetect::impl_getStaticSupportedServiceNames()
524 {
525     UNOMUTEXGUARD aGuard( UNOMUTEX::getGlobalMutex() );
526     UNOSEQUENCE< UNOOUSTRING > seqServiceNames( 1 );
527     seqServiceNames.getArray() [0] = UNOOUSTRING::createFromAscii( "com.sun.star.frame.ExtendedTypeDetection"  );
528     return seqServiceNames ;
529 }
530 
531 /* Helper for XServiceInfo */
532 UNOOUSTRING SdFilterDetect::impl_getStaticImplementationName()
533 {
534     return UNOOUSTRING::createFromAscii( "com.sun.star.comp.draw.FormatDetector" );
535 }
536 
537 /* Helper for registry */
538 UNOREFERENCE< UNOXINTERFACE > SAL_CALL SdFilterDetect::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION )
539 {
540     return UNOREFERENCE< UNOXINTERFACE >( *new SdFilterDetect( xServiceManager ) );
541 }
542 
543