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