LCOV - code coverage report
Current view: top level - sc/source/ui/unoobj - exceldetect.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 40 88 45.5 %
Date: 2014-11-03 Functions: 11 15 73.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  */
       9             : 
      10             : #include "exceldetect.hxx"
      11             : 
      12             : #include <com/sun/star/io/XInputStream.hpp>
      13             : #include <com/sun/star/ucb/XContent.hpp>
      14             : #include <cppuhelper/supportsservice.hxx>
      15             : 
      16             : #include <svl/itemset.hxx>
      17             : #include <svl/eitem.hxx>
      18             : #include <sfx2/app.hxx>
      19             : #include <sfx2/docfile.hxx>
      20             : #include <sfx2/sfxsids.hrc>
      21             : #include <unotools/mediadescriptor.hxx>
      22             : #include <sot/storage.hxx>
      23             : 
      24             : using namespace com::sun::star;
      25             : using utl::MediaDescriptor;
      26             : 
      27          52 : ScExcelBiffDetect::ScExcelBiffDetect( const uno::Reference<uno::XComponentContext>& /*xContext*/ ) {}
      28         104 : ScExcelBiffDetect::~ScExcelBiffDetect() {}
      29             : 
      30           0 : OUString ScExcelBiffDetect::getImplementationName() throw (uno::RuntimeException, std::exception)
      31             : {
      32           0 :     return impl_getStaticImplementationName();
      33             : }
      34             : 
      35           0 : sal_Bool ScExcelBiffDetect::supportsService( const OUString& aName ) throw (uno::RuntimeException, std::exception)
      36             : {
      37           0 :     return cppu::supportsService(this, aName);
      38             : }
      39             : 
      40           0 : uno::Sequence<OUString> ScExcelBiffDetect::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
      41             : {
      42           0 :     return impl_getStaticSupportedServiceNames();
      43             : }
      44             : 
      45             : namespace {
      46             : 
      47          52 : bool hasStream(const uno::Reference<io::XInputStream>& xInStream, const OUString& rName)
      48             : {
      49          52 :     SfxMedium aMedium;
      50          52 :     aMedium.UseInteractionHandler(false);
      51          52 :     aMedium.setStreamToLoadFrom(xInStream, true);
      52          52 :     SvStream* pStream = aMedium.GetInStream();
      53          52 :     if (!pStream)
      54           0 :         return false;
      55             : 
      56          52 :     pStream->Seek(STREAM_SEEK_TO_END);
      57          52 :     sal_Size nSize = pStream->Tell();
      58          52 :     pStream->Seek(0);
      59             : 
      60          52 :     if (!nSize)
      61             :     {
      62             :         // 0-size stream.  Failed.
      63           0 :         return false;
      64             :     }
      65             : 
      66             :     try
      67             :     {
      68          52 :         SotStorageRef xStorage = new SotStorage(pStream, false);
      69          52 :         if (!xStorage.Is() || xStorage->GetError())
      70           0 :             return false;
      71          52 :         return xStorage->IsStream(rName);
      72             :     }
      73           0 :     catch (const css::ucb::ContentCreationException &e)
      74             :     {
      75             :         SAL_WARN("sc", "hasStream caught " << e.Message);
      76             :     }
      77             : 
      78          52 :     return false;
      79             : }
      80             : 
      81             : /**
      82             :  * We detect BIFF 2, 3 and 4 file types together since the only thing that
      83             :  * set them apart is the BOF ID.
      84             :  */
      85           0 : bool isExcel40(const uno::Reference<io::XInputStream>& xInStream)
      86             : {
      87           0 :     SfxMedium aMedium;
      88           0 :     aMedium.UseInteractionHandler(false);
      89           0 :     aMedium.setStreamToLoadFrom(xInStream, true);
      90           0 :     SvStream* pStream = aMedium.GetInStream();
      91           0 :     if (!pStream)
      92           0 :         return false;
      93             : 
      94           0 :     pStream->Seek(STREAM_SEEK_TO_END);
      95           0 :     sal_Size nSize = pStream->Tell();
      96           0 :     pStream->Seek(0);
      97             : 
      98           0 :     if (nSize < 4)
      99           0 :         return false;
     100             : 
     101             :     sal_uInt16 nBofId, nBofSize;
     102           0 :     pStream->ReadUInt16( nBofId ).ReadUInt16( nBofSize );
     103             : 
     104           0 :     switch (nBofId)
     105             :     {
     106             :         case 0x0009: // Excel 2.1 worksheet (BIFF 2)
     107             :         case 0x0209: // Excel 3.0 worksheet (BIFF 3)
     108             :         case 0x0409: // Excel 4.0 worksheet (BIFF 4)
     109             :         case 0x0809: // Excel 5.0 worksheet (BIFF 5), some apps create such files (fdo#70100)
     110           0 :             break;
     111             :         default:
     112           0 :             return false;
     113             :     }
     114             : 
     115           0 :     if (nBofSize < 4 || 16 < nBofSize)
     116             :         // BOF record must be sized between 4 and 16 for BIFF 2, 3 and 4.
     117           0 :         return false;
     118             : 
     119           0 :     sal_Size nPos = pStream->Tell();
     120           0 :     if (nSize - nPos < nBofSize)
     121             :         // BOF record doesn't have required bytes.
     122           0 :         return false;
     123             : 
     124           0 :     return true;
     125             : }
     126             : 
     127          52 : bool isTemplate(const OUString& rType)
     128             : {
     129          52 :     return rType.indexOf("_VorlageTemplate") != -1;
     130             : }
     131             : 
     132             : }
     133             : 
     134          52 : OUString ScExcelBiffDetect::detect( uno::Sequence<beans::PropertyValue>& lDescriptor )
     135             :     throw (uno::RuntimeException, std::exception)
     136             : {
     137          52 :     MediaDescriptor aMediaDesc(lDescriptor);
     138         104 :     OUString aType;
     139          52 :     aMediaDesc[MediaDescriptor::PROP_TYPENAME()] >>= aType;
     140          52 :     if (aType.isEmpty())
     141             :         // Type is not given.  We can't proceed.
     142           0 :         return OUString();
     143             : 
     144          52 :     aMediaDesc.addInputStream();
     145         104 :     uno::Reference<io::XInputStream> xInStream(aMediaDesc[MediaDescriptor::PROP_INPUTSTREAM()], uno::UNO_QUERY);
     146          52 :     if (!xInStream.is())
     147             :         // No input stream.
     148           0 :         return OUString();
     149             : 
     150          52 :     if (aType == "calc_MS_Excel_97" || aType == "calc_MS_Excel_97_VorlageTemplate")
     151             :     {
     152             :         // See if this stream is a Excel 97/XP/2003 (BIFF8) stream.
     153          52 :         if (!hasStream(xInStream, "Workbook"))
     154             :             // BIFF8 is expected to contain a stream named "Workbook".
     155           0 :             return OUString();
     156             : 
     157          52 :         aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= isTemplate(aType) ? OUString("MS Excel 97 Vorlage/Template") : OUString("MS Excel 97");
     158             :     }
     159             : 
     160           0 :     else if (aType == "calc_MS_Excel_95" || aType == "calc_MS_Excel_95_VorlageTemplate")
     161             :     {
     162             :         // See if this stream is a Excel 95 (BIFF5) stream.
     163           0 :         if (!hasStream(xInStream, "Book"))
     164           0 :             return OUString();
     165             : 
     166           0 :         aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= isTemplate(aType) ? OUString("MS Excel 95 Vorlage/Template") : OUString("MS Excel 95");
     167             :     }
     168             : 
     169           0 :     else if (aType == "calc_MS_Excel_5095" || aType == "calc_MS_Excel_5095_VorlageTemplate")
     170             :     {
     171             :         // See if this stream is a Excel 5.0/95 stream.
     172           0 :         if (!hasStream(xInStream, "Book"))
     173           0 :             return OUString();
     174             : 
     175           0 :         aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= isTemplate(aType) ? OUString("MS Excel 5.0/95 Vorlage/Template") : OUString("MS Excel 5.0/95");
     176             :     }
     177             : 
     178           0 :     else if (aType == "calc_MS_Excel_40" || aType == "calc_MS_Excel_40_VorlageTemplate")
     179             :     {
     180             :         // See if this stream is a Excel 4.0 stream.
     181           0 :         if (!isExcel40(xInStream))
     182           0 :             return OUString();
     183             : 
     184           0 :         aMediaDesc[MediaDescriptor::PROP_FILTERNAME()] <<= isTemplate(aType) ? OUString("MS Excel 4.0 Vorlage/Template") : OUString("MS Excel 4.0");
     185             :     }
     186             : 
     187             :     else
     188             :         // Nothing to detect.
     189           0 :         return OUString();
     190             : 
     191          52 :     aMediaDesc >> lDescriptor;
     192         104 :     return aType;
     193             : }
     194             : 
     195           6 : uno::Sequence<OUString> ScExcelBiffDetect::impl_getStaticSupportedServiceNames()
     196             : {
     197           6 :     uno::Sequence<OUString> aNames(1);
     198           6 :     aNames[0] = "com.sun.star.frame.ExtendedTypeDetection";
     199           6 :     return aNames;
     200             : }
     201             : 
     202           6 : OUString ScExcelBiffDetect::impl_getStaticImplementationName()
     203             : {
     204           6 :     return OUString("com.sun.star.comp.calc.ExcelBiffFormatDetector");
     205             : }
     206             : 
     207          52 : uno::Reference<uno::XInterface> ScExcelBiffDetect::impl_createInstance(
     208             :     const uno::Reference<uno::XComponentContext>& xContext )
     209             :         throw (com::sun::star::uno::Exception)
     210             : {
     211          52 :     return static_cast<cppu::OWeakObject*>(new ScExcelBiffDetect(xContext));
     212          18 : }
     213             : 
     214             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10