bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / ui / unoobj / scdetect.cxx
blobffdb7ea5bf0a2b28b8d84e3c1f0111f5dd79733f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "scdetect.hxx"
22 #include <sal/macros.h>
24 #include <framework/interaction.hxx>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/beans/PropertyValue.hpp>
27 #include <com/sun/star/frame/XFrame.hpp>
28 #include <com/sun/star/frame/XModel.hpp>
29 #include <com/sun/star/awt/XWindow.hpp>
30 #include <com/sun/star/lang/XUnoTunnel.hpp>
31 #include <comphelper/processfactory.hxx>
32 #include <comphelper/string.hxx>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/io/XInputStream.hpp>
35 #include <com/sun/star/task/XInteractionHandler.hpp>
36 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37 #include <com/sun/star/ucb/CommandAbortedException.hpp>
38 #include <com/sun/star/ucb/InteractiveAppException.hpp>
39 #include <com/sun/star/ucb/XContent.hpp>
40 #include <com/sun/star/packages/zip/ZipIOException.hpp>
42 #include <toolkit/helper/vclunohelper.hxx>
43 #include <ucbhelper/simpleinteractionrequest.hxx>
45 #include <svtools/parhtml.hxx>
46 #include <rtl/ustring.h>
47 #include <svl/itemset.hxx>
48 #include <vcl/window.hxx>
49 #include <svl/eitem.hxx>
50 #include <svl/stritem.hxx>
51 #include <tools/urlobj.hxx>
52 #include <osl/mutex.hxx>
53 #include <svtools/sfxecode.hxx>
54 #include <svtools/ehdl.hxx>
55 #include <sot/storinfo.hxx>
56 #include <vcl/svapp.hxx>
57 #include <sfx2/sfxsids.hrc>
58 #include <sfx2/request.hxx>
59 #include <sfx2/docfile.hxx>
60 #include <sfx2/docfilt.hxx>
61 #include <sfx2/fcontnr.hxx>
62 #include <sfx2/app.hxx>
63 #include <sfx2/brokenpackageint.hxx>
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::uno;
67 using namespace ::com::sun::star::io;
68 using namespace ::com::sun::star::frame;
69 using namespace ::com::sun::star::task;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::lang;
72 using namespace ::com::sun::star::ucb;
74 namespace {
76 const sal_Char pFilterLotus[] = "Lotus";
77 const sal_Char pFilterQPro6[] = "Quattro Pro 6.0";
78 const sal_Char pFilterDBase[] = "dBase";
79 const sal_Char pFilterDif[] = "DIF";
80 const sal_Char pFilterSylk[] = "SYLK";
82 // Tabelle mit Suchmustern
83 // Bedeutung der Sequenzen
84 // 0x00??: genau Byte 0x?? muss an dieser Stelle stehen
85 // 0x0100: ein Byte ueberlesen (don't care)
86 // 0x02nn: ein Byte aus 0xnn Alternativen folgt
87 // 0x8000: Erkennung abgeschlossen
90 #define M_DC 0x0100
91 #define M_ALT(ANZ) (0x0200+(ANZ))
92 #define M_ENDE 0x8000
94 const sal_uInt16 pLotus[] = // Lotus 1/1A/2
95 { 0x0000, 0x0000, 0x0002, 0x0000,
96 M_ALT(2), 0x0004, 0x0006,
97 0x0004, M_ENDE };
99 const sal_uInt16 pLotusNew[] = // Lotus >= 9.7
100 { 0x0000, 0x0000, M_DC, 0x0000, // Rec# + Len (0x1a)
101 M_ALT(3), 0x0003, 0x0004, 0x0005, // File Revision Code 97->ME
102 0x0010, 0x0004, 0x0000, 0x0000,
103 M_ENDE };
105 const sal_uInt16 pLotus2[] = // Lotus >3
106 { 0x0000, 0x0000, 0x001A, 0x0000, // Rec# + Len (26)
107 M_ALT(2), 0x0000, 0x0002, // File Revision Code
108 0x0010,
109 0x0004, 0x0000, // File Revision Subcode
110 M_ENDE };
112 const sal_uInt16 pQPro[] =
113 { 0x0000, 0x0000, 0x0002, 0x0000,
114 M_ALT(4), 0x0001, 0x0002, // WB1, WB2
115 0x0006, 0x0007, // QPro 6/7 (?)
116 0x0010,
117 M_ENDE };
119 const sal_uInt16 pDIF1[] = // DIF mit CR-LF
121 'T', 'A', 'B', 'L', 'E',
122 M_DC, M_DC,
123 '0', ',', '1',
124 M_DC, M_DC,
125 '\"',
126 M_ENDE };
128 const sal_uInt16 pDIF2[] = // DIF mit CR oder LF
130 'T', 'A', 'B', 'L', 'E',
131 M_DC,
132 '0', ',', '1',
133 M_DC,
134 '\"',
135 M_ENDE };
137 const sal_uInt16 pSylk[] = // Sylk
139 'I', 'D', ';',
140 M_ALT(3), 'P', 'N', 'E', // 'P' plus undocumented Excel extensions 'N' and 'E'
141 M_ENDE };
143 bool detectThisFormat(SvStream& rStr, const sal_uInt16* pSearch)
145 sal_uInt8 nByte;
146 rStr.Seek( 0 ); // am Anfang war alles Uebel...
147 rStr >> nByte;
148 bool bSync = true;
149 while( !rStr.IsEof() && bSync )
151 sal_uInt16 nMuster = *pSearch;
153 if( nMuster < 0x0100 )
154 { // direkter Byte-Vergleich
155 if( ( sal_uInt8 ) nMuster != nByte )
156 bSync = false;
158 else if( nMuster & M_DC )
159 { // don't care
161 else if( nMuster & M_ALT(0) )
162 { // alternative Bytes
163 sal_uInt8 nAnzAlt = ( sal_uInt8 ) nMuster;
164 bSync = false; // zunaechst unsynchron
165 while( nAnzAlt > 0 )
167 pSearch++;
168 if( ( sal_uInt8 ) *pSearch == nByte )
169 bSync = true; // jetzt erst Synchronisierung
170 nAnzAlt--;
173 else if( nMuster & M_ENDE )
174 { // Format detected
175 return true;
178 pSearch++;
179 rStr >> nByte;
182 return false;
187 ScFilterDetect::ScFilterDetect( const uno::Reference<uno::XComponentContext>& /*xContext*/ )
191 ScFilterDetect::~ScFilterDetect()
195 #if 0
196 // This method is no longer used, but I do want to keep this for now to see
197 // if we could transfer this check to the now centralized ascii detection
198 // code in the filter module.
199 static sal_Bool lcl_MayBeAscii( SvStream& rStream )
201 // ASCII/CSV is considered possible if there are no null bytes, or a Byte
202 // Order Mark is present, or if, for Unicode UCS2/UTF-16, all null bytes
203 // are on either even or uneven byte positions.
205 rStream.Seek(STREAM_SEEK_TO_BEGIN);
207 const size_t nBufSize = 2048;
208 sal_uInt16 aBuffer[ nBufSize ];
209 sal_uInt8* pByte = reinterpret_cast<sal_uInt8*>(aBuffer);
210 sal_uLong nBytesRead = rStream.Read( pByte, nBufSize*2);
212 if ( nBytesRead >= 2 && (aBuffer[0] == 0xfffe || aBuffer[0] == 0xfeff) )
214 // Unicode BOM file may contain null bytes.
215 return sal_True;
218 const sal_uInt16* p = aBuffer;
219 sal_uInt16 nMask = 0xffff;
220 nBytesRead /= 2;
221 while( nBytesRead-- && nMask )
223 sal_uInt16 nVal = *p++ & nMask;
224 if (!(nVal & 0x00ff))
225 nMask &= 0xff00;
226 if (!(nVal & 0xff00))
227 nMask &= 0x00ff;
230 return nMask != 0;
232 #endif
234 static sal_Bool lcl_MayBeDBase( SvStream& rStream )
236 // Look for dbf marker, see connectivity/source/inc/dbase/DTable.hxx
237 // DBFType for values.
238 const sal_uInt8 nValidMarks[] = {
239 0x03, 0x04, 0x05, 0x30, 0x43, 0xB3, 0x83, 0x8b, 0x8e, 0xf5 };
240 sal_uInt8 nMark;
241 rStream.Seek(STREAM_SEEK_TO_BEGIN);
242 rStream >> nMark;
243 bool bValidMark = false;
244 for (size_t i=0; i < sizeof(nValidMarks)/sizeof(nValidMarks[0]) && !bValidMark; ++i)
246 if (nValidMarks[i] == nMark)
247 bValidMark = true;
249 if ( !bValidMark )
250 return false;
252 const size_t nHeaderBlockSize = 32;
253 // Empty dbf is >= 32*2+1 bytes in size.
254 const size_t nEmptyDbf = nHeaderBlockSize * 2 + 1;
256 rStream.Seek(STREAM_SEEK_TO_END);
257 sal_uLong nSize = rStream.Tell();
258 if ( nSize < nEmptyDbf )
259 return false;
261 // length of header starts at 8
262 rStream.Seek(8);
263 sal_uInt16 nHeaderLen;
264 rStream >> nHeaderLen;
266 if ( nHeaderLen < nEmptyDbf || nSize < nHeaderLen )
267 return false;
269 // Last byte of header must be 0x0d, this is how it's specified.
270 // #i9581#,#i26407# but some applications don't follow the specification
271 // and pad the header with one byte 0x00 to reach an
272 // even boundary. Some (#i88577# ) even pad more or pad using a 0x1a ^Z
273 // control character (#i8857#). This results in:
274 // Last byte of header must be 0x0d on 32 bytes boundary.
275 sal_uInt16 nBlocks = (nHeaderLen - 1) / nHeaderBlockSize;
276 sal_uInt8 nEndFlag = 0;
277 while ( nBlocks > 1 && nEndFlag != 0x0d ) {
278 rStream.Seek( nBlocks-- * nHeaderBlockSize );
279 rStream >> nEndFlag;
282 return ( 0x0d == nEndFlag );
285 OUString SAL_CALL ScFilterDetect::detect( uno::Sequence<beans::PropertyValue>& lDescriptor )
286 throw( uno::RuntimeException )
288 uno::Reference< XInputStream > xStream;
289 uno::Reference< XContent > xContent;
290 uno::Reference< XInteractionHandler > xInteraction;
291 String aURL;
292 OUString sTemp;
293 String aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
294 String aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action)
296 OUString aDocumentTitle; // interesting only if set in this method
298 // opening as template is done when a parameter tells to do so and a template filter can be detected
299 // (otherwise no valid filter would be found) or if the detected filter is a template filter and
300 // there is no parameter that forbids to open as template
301 sal_Bool bOpenAsTemplate = false;
302 sal_Bool bWasReadOnly = false, bReadOnly = false;
304 sal_Bool bRepairPackage = false;
305 sal_Bool bRepairAllowed = false;
306 bool bDeepDetection = false;
308 // now some parameters that can already be in the array, but may be overwritten or new inserted here
309 // remember their indices in the case new values must be added to the array
310 sal_Int32 nPropertyCount = lDescriptor.getLength();
311 sal_Int32 nIndexOfFilterName = -1;
312 sal_Int32 nIndexOfInputStream = -1;
313 sal_Int32 nIndexOfContent = -1;
314 sal_Int32 nIndexOfReadOnlyFlag = -1;
315 sal_Int32 nIndexOfTemplateFlag = -1;
316 sal_Int32 nIndexOfDocumentTitle = -1;
318 for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty )
320 // extract properties
321 if ( lDescriptor[nProperty].Name == "URL" )
323 lDescriptor[nProperty].Value >>= sTemp;
324 aURL = sTemp;
326 else if( !aURL.Len() && lDescriptor[nProperty].Name.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("FileName")) )
328 lDescriptor[nProperty].Value >>= sTemp;
329 aURL = sTemp;
331 else if ( lDescriptor[nProperty].Name == "TypeName" )
333 lDescriptor[nProperty].Value >>= sTemp;
334 aTypeName = sTemp;
336 else if ( lDescriptor[nProperty].Name == "FilterName" )
338 lDescriptor[nProperty].Value >>= sTemp;
339 aPreselectedFilterName = sTemp;
341 // if the preselected filter name is not correct, it must be erased after detection
342 // remember index of property to get access to it later
343 nIndexOfFilterName = nProperty;
345 else if ( lDescriptor[nProperty].Name == "InputStream" )
346 nIndexOfInputStream = nProperty;
347 else if ( lDescriptor[nProperty].Name == "ReadOnly" )
348 nIndexOfReadOnlyFlag = nProperty;
349 else if ( lDescriptor[nProperty].Name == "UCBContent" )
350 nIndexOfContent = nProperty;
351 else if ( lDescriptor[nProperty].Name == "AsTemplate" )
353 lDescriptor[nProperty].Value >>= bOpenAsTemplate;
354 nIndexOfTemplateFlag = nProperty;
356 else if ( lDescriptor[nProperty].Name == "InteractionHandler" )
357 lDescriptor[nProperty].Value >>= xInteraction;
358 else if ( lDescriptor[nProperty].Name == "RepairPackage" )
359 lDescriptor[nProperty].Value >>= bRepairPackage;
360 else if ( lDescriptor[nProperty].Name == "DocumentTitle" )
361 nIndexOfDocumentTitle = nProperty;
362 else if (lDescriptor[nProperty].Name == "DeepDetection")
363 bDeepDetection = lDescriptor[nProperty].Value.get<sal_Bool>();
366 // can't check the type for external filters, so set the "dont" flag accordingly
367 SolarMutexGuard aGuard;
368 //SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED;
370 SfxAllItemSet *pSet = new SfxAllItemSet( SFX_APP()->GetPool() );
371 TransformParameters( SID_OPENDOC, lDescriptor, *pSet );
372 SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, false );
374 bWasReadOnly = pItem && pItem->GetValue();
376 const SfxFilter* pFilter = 0;
377 String aPrefix = OUString( "private:factory/" );
378 if( aURL.Match( aPrefix ) == aPrefix.Len() )
380 String aPattern( aPrefix );
381 aPattern += OUString("scalc");
382 if ( aURL.Match( aPattern ) >= aPattern.Len() )
383 pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
385 else
387 // container for Calc filters
388 SfxFilterMatcher aMatcher("scalc");
389 if ( aPreselectedFilterName.Len() )
390 pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
391 else if( aTypeName.Len() )
392 pFilter = aMatcher.GetFilter4EA( aTypeName );
394 // ctor of SfxMedium uses owner transition of ItemSet
395 SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
396 aMedium.UseInteractionHandler( sal_True );
398 sal_Bool bIsStorage = aMedium.IsStorage();
399 if ( aMedium.GetErrorCode() == ERRCODE_NONE )
401 // remember input stream and content and put them into the descriptor later
402 // should be done here since later the medium can switch to a version
403 xStream.set(aMedium.GetInputStream());
404 xContent.set(aMedium.GetContent());
405 bReadOnly = aMedium.IsReadOnly();
407 // maybe that IsStorage() already created an error!
408 if ( bIsStorage )
410 uno::Reference < embed::XStorage > xStorage(aMedium.GetStorage( false ));
411 if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
413 // error during storage creation means _here_ that the medium
414 // is broken, but we can not handle it in medium since unpossibility
415 // to create a storage does not _always_ means that the medium is broken
416 aMedium.SetError(aMedium.GetLastStorageCreationState(), OUString(OSL_LOG_PREFIX));
417 if ( xInteraction.is() )
419 OUString empty;
422 InteractiveAppException xException( empty,
423 uno::Reference< XInterface >(),
424 InteractionClassification_ERROR,
425 aMedium.GetError() );
427 uno::Reference< XInteractionRequest > xRequest(
428 new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
429 ucbhelper::CONTINUATION_APPROVE ) );
430 xInteraction->handle( xRequest );
432 catch ( Exception & ) {};
435 else if ( xStorage.is() )
439 OUString aFilterName;
440 if ( pFilter )
441 aFilterName = pFilter->GetName();
442 aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : false, &aFilterName );
444 catch( const lang::WrappedTargetException& aWrap )
446 if (!bDeepDetection)
447 // Bail out early unless it's a deep detection.
448 return OUString();
450 packages::zip::ZipIOException aZipException;
452 // repairing is done only if this type is requested from outside
453 if ( ( aWrap.TargetException >>= aZipException ) && aTypeName.Len() )
455 if ( xInteraction.is() )
457 // the package is broken one
458 aDocumentTitle = aMedium.GetURLObject().getName(
459 INetURLObject::LAST_SEGMENT,
460 true,
461 INetURLObject::DECODE_WITH_CHARSET );
463 if ( !bRepairPackage )
465 // ask the user whether he wants to try to repair
466 RequestPackageReparation aRequest( aDocumentTitle );
467 xInteraction->handle( aRequest.GetRequest() );
468 bRepairAllowed = aRequest.isApproved();
471 if ( !bRepairAllowed )
473 // repair either not allowed or not successful
474 NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
475 xInteraction->handle( aNotifyRequest.GetRequest() );
479 if ( !bRepairAllowed )
480 aTypeName.Erase();
483 catch( uno::RuntimeException& )
485 throw;
487 catch( uno::Exception& )
489 aTypeName.Erase();
492 if ( aTypeName.Len() )
493 pFilter = SfxFilterMatcher("scalc").GetFilter4EA( aTypeName );
496 else
498 // Non-storage format.
500 if (aTypeName == "calc8_template" ||
501 aTypeName == "calc8" ||
502 aTypeName == "calc_StarOffice_XML_Calc" ||
503 aTypeName == "calc_StarOffice_XML_Calc_Template")
504 // These types require storage. Bail out.
505 return OUString();
507 SvStream* pStream = aMedium.GetInStream();
508 if (!pStream)
509 // No stream, no detection.
510 return OUString();
512 pFilter = NULL;
514 pStream->Seek( STREAM_SEEK_TO_END);
515 sal_Size nSize = pStream->Tell();
516 pStream->Seek( 0);
517 // Do not attempt to create an SotStorage on a
518 // 0-length stream as that would create the compound
519 // document header on the stream and effectively write to
520 // disk!
521 if (nSize > 0)
523 const char* pSearchFilterName = NULL;
524 if (aTypeName == "calc_Lotus")
526 if (!detectThisFormat(*pStream, pLotus) && !detectThisFormat(*pStream, pLotusNew) && !detectThisFormat(*pStream, pLotus2))
527 return OUString();
529 pSearchFilterName = pFilterLotus;
531 else if (aTypeName == "calc_QPro")
533 if (!detectThisFormat(*pStream, pQPro))
534 return OUString();
536 pSearchFilterName = pFilterQPro6;
538 else if (aTypeName == "calc_SYLK")
540 if (!detectThisFormat(*pStream, pSylk))
541 return OUString();
543 pSearchFilterName = pFilterSylk;
545 else if (aTypeName == "calc_DIF")
547 if (!detectThisFormat(*pStream, pDIF1) && !detectThisFormat(*pStream, pDIF2))
548 return OUString();
550 pSearchFilterName = pFilterDif;
552 else if (aTypeName == "calc_dBase")
554 if (!lcl_MayBeDBase(*pStream))
555 return OUString();
557 pSearchFilterName = pFilterDBase;
560 if (!pSearchFilterName)
561 return OUString();
563 pFilter = aMatcher.GetFilter4FilterName(OUString::createFromAscii(pSearchFilterName));
569 if ( nIndexOfInputStream == -1 && xStream.is() )
571 // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
572 lDescriptor.realloc( nPropertyCount + 1 );
573 lDescriptor[nPropertyCount].Name = "InputStream";
574 lDescriptor[nPropertyCount].Value <<= xStream;
575 nPropertyCount++;
578 if ( nIndexOfContent == -1 && xContent.is() )
580 // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
581 lDescriptor.realloc( nPropertyCount + 1 );
582 lDescriptor[nPropertyCount].Name = "UCBContent";
583 lDescriptor[nPropertyCount].Value <<= xContent;
584 nPropertyCount++;
587 if ( bReadOnly != bWasReadOnly )
589 if ( nIndexOfReadOnlyFlag == -1 )
591 lDescriptor.realloc( nPropertyCount + 1 );
592 lDescriptor[nPropertyCount].Name = "ReadOnly";
593 lDescriptor[nPropertyCount].Value <<= bReadOnly;
594 nPropertyCount++;
596 else
597 lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
600 if ( !bRepairPackage && bRepairAllowed )
602 lDescriptor.realloc( nPropertyCount + 1 );
603 lDescriptor[nPropertyCount].Name = "RepairPackage";
604 lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
605 nPropertyCount++;
607 bOpenAsTemplate = sal_True;
609 // TODO/LATER: set progress bar that should be used
612 if ( bOpenAsTemplate )
614 if ( nIndexOfTemplateFlag == -1 )
616 lDescriptor.realloc( nPropertyCount + 1 );
617 lDescriptor[nPropertyCount].Name = "AsTemplate";
618 lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
619 nPropertyCount++;
621 else
622 lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
625 if ( !aDocumentTitle.isEmpty() )
627 // the title was set here
628 if ( nIndexOfDocumentTitle == -1 )
630 lDescriptor.realloc( nPropertyCount + 1 );
631 lDescriptor[nPropertyCount].Name = "DocumentTitle";
632 lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
633 nPropertyCount++;
635 else
636 lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
639 if (!pFilter)
640 return OUString();
642 if (nIndexOfFilterName == -1)
644 lDescriptor.realloc(nPropertyCount + 1);
645 lDescriptor[nPropertyCount].Name = "FilterName";
646 lDescriptor[nPropertyCount].Value <<= pFilter->GetName();
647 ++nPropertyCount;
649 else
650 lDescriptor[nIndexOfFilterName].Value <<= pFilter->GetName();
652 return aTypeName;
655 OUString SAL_CALL ScFilterDetect::getImplementationName() throw (uno::RuntimeException)
657 return impl_getStaticImplementationName();
660 sal_Bool ScFilterDetect::supportsService( const OUString& sServiceName )
661 throw (uno::RuntimeException)
663 uno::Sequence<OUString> seqServiceNames(getSupportedServiceNames());
664 const OUString* pArray = seqServiceNames.getConstArray();
665 for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ )
667 if ( pArray[nCounter] == sServiceName )
669 return sal_True ;
672 return false ;
675 com::sun::star::uno::Sequence<OUString> ScFilterDetect::getSupportedServiceNames()
676 throw (uno::RuntimeException)
678 return impl_getStaticSupportedServiceNames();
681 uno::Sequence<OUString> ScFilterDetect::impl_getStaticSupportedServiceNames()
683 uno::Sequence<OUString> seqServiceNames(1);
684 seqServiceNames.getArray()[0] = "com.sun.star.frame.ExtendedTypeDetection";
685 return seqServiceNames;
688 OUString ScFilterDetect::impl_getStaticImplementationName()
690 return OUString("com.sun.star.comp.calc.FormatDetector");
693 uno::Reference<uno::XInterface> ScFilterDetect::impl_createInstance(
694 const uno::Reference<uno::XComponentContext>& xContext ) throw (uno::Exception)
696 return static_cast<cppu::OWeakObject*>(new ScFilterDetect(xContext));
699 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */