Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / unoobj / scdetect.cxx
blobf477cf91e00813ddfc5536e79d59ddd87f95b261
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 OUString aURL;
292 OUString sTemp;
293 OUString aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection)
294 OUString 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.isEmpty() && lDescriptor[nProperty].Name == "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 OUString aPrefix = "private:factory/";
378 if( aURL.startsWith( aPrefix ) )
380 OUString aPattern = aPrefix + "scalc";
381 if ( aURL.startsWith( aPattern ) )
382 pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL );
384 else
386 // container for Calc filters
387 SfxFilterMatcher aMatcher("scalc");
388 if ( !aPreselectedFilterName.isEmpty() )
389 pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName );
390 else if( !aTypeName.isEmpty() )
391 pFilter = aMatcher.GetFilter4EA( aTypeName );
393 // ctor of SfxMedium uses owner transition of ItemSet
394 SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, NULL, pSet );
395 aMedium.UseInteractionHandler( sal_True );
397 sal_Bool bIsStorage = aMedium.IsStorage();
398 if ( aMedium.GetErrorCode() == ERRCODE_NONE )
400 // remember input stream and content and put them into the descriptor later
401 // should be done here since later the medium can switch to a version
402 xStream.set(aMedium.GetInputStream());
403 xContent.set(aMedium.GetContent());
404 bReadOnly = aMedium.IsReadOnly();
406 // maybe that IsStorage() already created an error!
407 if ( bIsStorage )
409 uno::Reference < embed::XStorage > xStorage(aMedium.GetStorage( false ));
410 if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE )
412 // error during storage creation means _here_ that the medium
413 // is broken, but we can not handle it in medium since unpossibility
414 // to create a storage does not _always_ means that the medium is broken
415 aMedium.SetError(aMedium.GetLastStorageCreationState(), OUString(OSL_LOG_PREFIX));
416 if ( xInteraction.is() )
418 OUString empty;
421 InteractiveAppException xException( empty,
422 uno::Reference< XInterface >(),
423 InteractionClassification_ERROR,
424 aMedium.GetError() );
426 uno::Reference< XInteractionRequest > xRequest(
427 new ucbhelper::SimpleInteractionRequest( makeAny( xException ),
428 ucbhelper::CONTINUATION_APPROVE ) );
429 xInteraction->handle( xRequest );
431 catch ( Exception & ) {};
434 else if ( xStorage.is() )
438 OUString aFilterName;
439 if ( pFilter )
440 aFilterName = pFilter->GetName();
441 aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : false, &aFilterName );
443 catch( const lang::WrappedTargetException& aWrap )
445 if (!bDeepDetection)
446 // Bail out early unless it's a deep detection.
447 return OUString();
449 packages::zip::ZipIOException aZipException;
451 // repairing is done only if this type is requested from outside
452 if ( ( aWrap.TargetException >>= aZipException ) && !aTypeName.isEmpty() )
454 if ( xInteraction.is() )
456 // the package is broken one
457 aDocumentTitle = aMedium.GetURLObject().getName(
458 INetURLObject::LAST_SEGMENT,
459 true,
460 INetURLObject::DECODE_WITH_CHARSET );
462 if ( !bRepairPackage )
464 // ask the user whether he wants to try to repair
465 RequestPackageReparation aRequest( aDocumentTitle );
466 xInteraction->handle( aRequest.GetRequest() );
467 bRepairAllowed = aRequest.isApproved();
470 if ( !bRepairAllowed )
472 // repair either not allowed or not successful
473 NotifyBrokenPackage aNotifyRequest( aDocumentTitle );
474 xInteraction->handle( aNotifyRequest.GetRequest() );
478 if ( !bRepairAllowed )
479 aTypeName = "";
482 catch( uno::RuntimeException& )
484 throw;
486 catch( uno::Exception& )
488 aTypeName = "";
491 if ( !aTypeName.isEmpty() )
492 pFilter = SfxFilterMatcher("scalc").GetFilter4EA( aTypeName );
495 else
497 // Non-storage format.
499 if (aTypeName == "calc8_template" ||
500 aTypeName == "calc8" ||
501 aTypeName == "calc_StarOffice_XML_Calc" ||
502 aTypeName == "calc_StarOffice_XML_Calc_Template")
503 // These types require storage. Bail out.
504 return OUString();
506 SvStream* pStream = aMedium.GetInStream();
507 if (!pStream)
508 // No stream, no detection.
509 return OUString();
511 pFilter = NULL;
513 pStream->Seek( STREAM_SEEK_TO_END);
514 sal_Size nSize = pStream->Tell();
515 pStream->Seek( 0);
516 // Do not attempt to create an SotStorage on a
517 // 0-length stream as that would create the compound
518 // document header on the stream and effectively write to
519 // disk!
520 if (nSize > 0)
522 const char* pSearchFilterName = NULL;
523 if (aTypeName == "calc_Lotus")
525 if (!detectThisFormat(*pStream, pLotus) && !detectThisFormat(*pStream, pLotusNew) && !detectThisFormat(*pStream, pLotus2))
526 return OUString();
528 pSearchFilterName = pFilterLotus;
530 else if (aTypeName == "calc_QPro")
532 if (!detectThisFormat(*pStream, pQPro))
533 return OUString();
535 pSearchFilterName = pFilterQPro6;
537 else if (aTypeName == "calc_SYLK")
539 if (!detectThisFormat(*pStream, pSylk))
540 return OUString();
542 pSearchFilterName = pFilterSylk;
544 else if (aTypeName == "calc_DIF")
546 if (!detectThisFormat(*pStream, pDIF1) && !detectThisFormat(*pStream, pDIF2))
547 return OUString();
549 pSearchFilterName = pFilterDif;
551 else if (aTypeName == "calc_dBase")
553 if (!lcl_MayBeDBase(*pStream))
554 return OUString();
556 pSearchFilterName = pFilterDBase;
559 if (!pSearchFilterName)
560 return OUString();
562 pFilter = aMatcher.GetFilter4FilterName(OUString::createFromAscii(pSearchFilterName));
568 if ( nIndexOfInputStream == -1 && xStream.is() )
570 // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
571 lDescriptor.realloc( nPropertyCount + 1 );
572 lDescriptor[nPropertyCount].Name = "InputStream";
573 lDescriptor[nPropertyCount].Value <<= xStream;
574 nPropertyCount++;
577 if ( nIndexOfContent == -1 && xContent.is() )
579 // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice
580 lDescriptor.realloc( nPropertyCount + 1 );
581 lDescriptor[nPropertyCount].Name = "UCBContent";
582 lDescriptor[nPropertyCount].Value <<= xContent;
583 nPropertyCount++;
586 if ( bReadOnly != bWasReadOnly )
588 if ( nIndexOfReadOnlyFlag == -1 )
590 lDescriptor.realloc( nPropertyCount + 1 );
591 lDescriptor[nPropertyCount].Name = "ReadOnly";
592 lDescriptor[nPropertyCount].Value <<= bReadOnly;
593 nPropertyCount++;
595 else
596 lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly;
599 if ( !bRepairPackage && bRepairAllowed )
601 lDescriptor.realloc( nPropertyCount + 1 );
602 lDescriptor[nPropertyCount].Name = "RepairPackage";
603 lDescriptor[nPropertyCount].Value <<= bRepairAllowed;
604 nPropertyCount++;
606 bOpenAsTemplate = sal_True;
608 // TODO/LATER: set progress bar that should be used
611 if ( bOpenAsTemplate )
613 if ( nIndexOfTemplateFlag == -1 )
615 lDescriptor.realloc( nPropertyCount + 1 );
616 lDescriptor[nPropertyCount].Name = "AsTemplate";
617 lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate;
618 nPropertyCount++;
620 else
621 lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate;
624 if ( !aDocumentTitle.isEmpty() )
626 // the title was set here
627 if ( nIndexOfDocumentTitle == -1 )
629 lDescriptor.realloc( nPropertyCount + 1 );
630 lDescriptor[nPropertyCount].Name = "DocumentTitle";
631 lDescriptor[nPropertyCount].Value <<= aDocumentTitle;
632 nPropertyCount++;
634 else
635 lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle;
638 if (!pFilter)
639 return OUString();
641 if (nIndexOfFilterName == -1)
643 lDescriptor.realloc(nPropertyCount + 1);
644 lDescriptor[nPropertyCount].Name = "FilterName";
645 lDescriptor[nPropertyCount].Value <<= pFilter->GetName();
646 ++nPropertyCount;
648 else
649 lDescriptor[nIndexOfFilterName].Value <<= pFilter->GetName();
651 return aTypeName;
654 OUString SAL_CALL ScFilterDetect::getImplementationName() throw (uno::RuntimeException)
656 return impl_getStaticImplementationName();
659 sal_Bool ScFilterDetect::supportsService( const OUString& sServiceName )
660 throw (uno::RuntimeException)
662 uno::Sequence<OUString> seqServiceNames(getSupportedServiceNames());
663 const OUString* pArray = seqServiceNames.getConstArray();
664 for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ )
666 if ( pArray[nCounter] == sServiceName )
668 return sal_True ;
671 return false ;
674 com::sun::star::uno::Sequence<OUString> ScFilterDetect::getSupportedServiceNames()
675 throw (uno::RuntimeException)
677 return impl_getStaticSupportedServiceNames();
680 uno::Sequence<OUString> ScFilterDetect::impl_getStaticSupportedServiceNames()
682 uno::Sequence<OUString> seqServiceNames(1);
683 seqServiceNames.getArray()[0] = "com.sun.star.frame.ExtendedTypeDetection";
684 return seqServiceNames;
687 OUString ScFilterDetect::impl_getStaticImplementationName()
689 return OUString("com.sun.star.comp.calc.FormatDetector");
692 uno::Reference<uno::XInterface> ScFilterDetect::impl_createInstance(
693 const uno::Reference<uno::XComponentContext>& xContext ) throw (uno::Exception)
695 return static_cast<cppu::OWeakObject*>(new ScFilterDetect(xContext));
698 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */