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