LCOV - code coverage report
Current view: top level - oox/source/core - filterdetect.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 118 306 38.6 %
Date: 2012-08-25 Functions: 25 43 58.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 127 608 20.9 %

           Branch data     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                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      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 .
      18                 :            :  */
      19                 :            : 
      20                 :            : #include "oox/core/filterdetect.hxx"
      21                 :            : 
      22                 :            : #include <com/sun/star/io/XStream.hpp>
      23                 :            : #include <comphelper/docpasswordhelper.hxx>
      24                 :            : #include <comphelper/mediadescriptor.hxx>
      25                 :            : #include <openssl/evp.h>
      26                 :            : #include <rtl/digest.h>
      27                 :            : #include "oox/core/fastparser.hxx"
      28                 :            : #include "oox/helper/attributelist.hxx"
      29                 :            : #include "oox/helper/binaryinputstream.hxx"
      30                 :            : #include "oox/helper/binaryoutputstream.hxx"
      31                 :            : #include "oox/helper/zipstorage.hxx"
      32                 :            : #include "oox/ole/olestorage.hxx"
      33                 :            : #include <com/sun/star/uri/UriReferenceFactory.hpp>
      34                 :            : 
      35                 :            : namespace oox {
      36                 :            : namespace core {
      37                 :            : 
      38                 :            : // ============================================================================
      39                 :            : 
      40                 :            : using namespace ::com::sun::star::beans;
      41                 :            : using namespace ::com::sun::star::io;
      42                 :            : using namespace ::com::sun::star::lang;
      43                 :            : using namespace ::com::sun::star::uno;
      44                 :            : using namespace ::com::sun::star::xml::sax;
      45                 :            : 
      46                 :            : using ::comphelper::MediaDescriptor;
      47                 :            : using ::comphelper::SequenceAsHashMap;
      48                 :            : using ::rtl::OUString;
      49                 :            : 
      50                 :            : // ============================================================================
      51                 :            : 
      52                 :        210 : FilterDetectDocHandler::FilterDetectDocHandler( const  Reference< XComponentContext >& rxContext, OUString& rFilterName ) :
      53         [ +  - ]:        210 :     mrFilterName( rFilterName ), mxContext( rxContext )
      54                 :            : {
      55         [ +  - ]:        210 :     maContextStack.reserve( 2 );
      56                 :        210 : }
      57                 :            : 
      58                 :        210 : FilterDetectDocHandler::~FilterDetectDocHandler()
      59                 :            : {
      60         [ -  + ]:        420 : }
      61                 :            : 
      62                 :        382 : void SAL_CALL FilterDetectDocHandler::startDocument()
      63                 :            :     throw (SAXException, RuntimeException)
      64                 :            : {
      65                 :        382 : }
      66                 :            : 
      67                 :        382 : void SAL_CALL FilterDetectDocHandler::endDocument()
      68                 :            :     throw (SAXException, RuntimeException)
      69                 :            : {
      70                 :        382 : }
      71                 :            : 
      72                 :        382 : void SAL_CALL FilterDetectDocHandler::setDocumentLocator( const Reference<XLocator>& /*xLocator*/ )
      73                 :            :     throw (SAXException, RuntimeException)
      74                 :            : {
      75                 :        382 : }
      76                 :            : 
      77                 :       2754 : void SAL_CALL FilterDetectDocHandler::startFastElement(
      78                 :            :         sal_Int32 nElement, const Reference< XFastAttributeList >& rAttribs )
      79                 :            :     throw (SAXException,RuntimeException)
      80                 :            : {
      81         [ +  - ]:       2754 :     AttributeList aAttribs( rAttribs );
      82   [ +  +  +  +  :       2754 :     switch ( nElement )
                   +  - ]
      83                 :            :     {
      84                 :            :         // cases for _rels/.rels
      85                 :            :         case PR_TOKEN( Relationships ):
      86                 :        191 :         break;
      87                 :            :         case PR_TOKEN( Relationship ):
      88 [ +  - ][ +  - ]:        579 :             if( !maContextStack.empty() && (maContextStack.back() == PR_TOKEN( Relationships )) )
         [ +  - ][ +  - ]
      89         [ +  - ]:        579 :                 parseRelationship( aAttribs );
      90                 :        579 :         break;
      91                 :            : 
      92                 :            :         // cases for [Content_Types].xml
      93                 :            :         case PC_TOKEN( Types ):
      94                 :        191 :         break;
      95                 :            :         case PC_TOKEN( Default ):
      96 [ +  - ][ +  - ]:        178 :             if( !maContextStack.empty() && (maContextStack.back() == PC_TOKEN( Types )) )
         [ +  - ][ +  - ]
      97         [ +  - ]:        178 :                 parseContentTypesDefault( aAttribs );
      98                 :        178 :         break;
      99                 :            :         case PC_TOKEN( Override ):
     100 [ +  - ][ +  - ]:       1615 :             if( !maContextStack.empty() && (maContextStack.back() == PC_TOKEN( Types )) )
         [ +  - ][ +  - ]
     101         [ +  - ]:       1615 :                 parseContentTypesOverride( aAttribs );
     102                 :       1615 :         break;
     103                 :            :     }
     104 [ +  - ][ +  - ]:       2754 :     maContextStack.push_back( nElement );
     105                 :       2754 : }
     106                 :            : 
     107                 :          0 : void SAL_CALL FilterDetectDocHandler::startUnknownElement(
     108                 :            :     const OUString& /*Namespace*/, const OUString& /*Name*/, const Reference<XFastAttributeList>& /*Attribs*/ )
     109                 :            :     throw (SAXException, RuntimeException)
     110                 :            : {
     111                 :          0 : }
     112                 :            : 
     113                 :       2754 : void SAL_CALL FilterDetectDocHandler::endFastElement( sal_Int32 /*nElement*/ )
     114                 :            :     throw (SAXException, RuntimeException)
     115                 :            : {
     116                 :       2754 :     maContextStack.pop_back();
     117                 :       2754 : }
     118                 :            : 
     119                 :          0 : void SAL_CALL FilterDetectDocHandler::endUnknownElement(
     120                 :            :     const OUString& /*Namespace*/, const OUString& /*Name*/ ) throw (SAXException, RuntimeException)
     121                 :            : {
     122                 :          0 : }
     123                 :            : 
     124                 :       2754 : Reference<XFastContextHandler> SAL_CALL FilterDetectDocHandler::createFastChildContext(
     125                 :            :     sal_Int32 /*Element*/, const Reference<XFastAttributeList>& /*Attribs*/ )
     126                 :            :     throw (SAXException, RuntimeException)
     127                 :            : {
     128                 :       2754 :     return this;
     129                 :            : }
     130                 :            : 
     131                 :          0 : Reference<XFastContextHandler> SAL_CALL FilterDetectDocHandler::createUnknownChildContext(
     132                 :            :     const OUString& /*Namespace*/, const OUString& /*Name*/, const Reference<XFastAttributeList>& /*Attribs*/)
     133                 :            :     throw (SAXException, RuntimeException)
     134                 :            : {
     135                 :          0 :     return this;
     136                 :            : }
     137                 :            : 
     138                 :        216 : void SAL_CALL FilterDetectDocHandler::characters( const OUString& /*aChars*/ )
     139                 :            :     throw (SAXException, RuntimeException)
     140                 :            : {
     141                 :        216 : }
     142                 :            : 
     143                 :          0 : void SAL_CALL FilterDetectDocHandler::ignorableWhitespace( const OUString& /*aWhitespaces*/ )
     144                 :            :     throw (SAXException, RuntimeException)
     145                 :            : {
     146                 :          0 : }
     147                 :            : 
     148                 :          0 : void SAL_CALL FilterDetectDocHandler::processingInstruction(
     149                 :            :     const OUString& /*aTarget*/, const OUString& /*aData*/ )
     150                 :            :     throw (SAXException, RuntimeException)
     151                 :            : {
     152                 :          0 : }
     153                 :            : 
     154                 :        579 : void FilterDetectDocHandler::parseRelationship( const AttributeList& rAttribs )
     155                 :            : {
     156         [ +  - ]:        579 :     OUString aType = rAttribs.getString( XML_Type, OUString() );
     157         [ +  + ]:        579 :     if ( aType == "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" )
     158                 :            :     {
     159         [ +  - ]:        191 :         Reference< com::sun::star::uri::XUriReferenceFactory > xFac =  com::sun::star::uri::UriReferenceFactory::create( mxContext );
     160                 :            :         try
     161                 :            :         {
     162                 :            :              // use '/' to representent the root of the zip package ( and provide a 'file' scheme to
     163                 :            :              // keep the XUriReference implementation happy )
     164 [ +  - ][ +  - ]:        191 :              Reference< com::sun::star::uri::XUriReference > xBase = xFac->parse( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("file:///" ) ) );
                 [ +  - ]
     165                 :            : 
     166 [ +  - ][ +  - ]:        191 :              Reference< com::sun::star::uri::XUriReference > xPart = xFac->parse(  rAttribs.getString( XML_Target, OUString() ) );
                 [ +  - ]
     167 [ +  - ][ +  - ]:        191 :              Reference< com::sun::star::uri::XUriReference > xAbs = xFac->makeAbsolute(  xBase, xPart, sal_True, com::sun::star::uri::RelativeUriExcessParentSegments_RETAIN );
     168                 :            : 
     169         [ +  - ]:        191 :              if ( xAbs.is() )
     170 [ +  - ][ +  - ]:        191 :                  maTargetPath = xAbs->getPath();
                 [ #  # ]
     171                 :            :         }
     172         [ #  # ]:          0 :         catch( const Exception& )
     173                 :            :         {
     174                 :        191 :         }
     175                 :        579 :     }
     176                 :        579 : }
     177                 :            : 
     178                 :        274 : OUString FilterDetectDocHandler::getFilterNameFromContentType( const OUString& rContentType ) const
     179                 :            : {
     180   [ +  +  -  + ]:        357 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ) ) ||
                 [ +  + ]
     181                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-word.document.macroEnabled.main+xml" ) ) )
     182                 :        191 :         return CREATE_OUSTRING( "writer_MS_Word_2007" );
     183                 :            : 
     184   [ +  -  -  + ]:        166 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.wordprocessingml.template.main+xml" ) ) ||
                 [ -  + ]
     185                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-word.template.macroEnabledTemplate.main+xml" ) ) )
     186                 :          0 :         return CREATE_OUSTRING( "writer_MS_Word_2007_Template" );
     187                 :            : 
     188   [ +  -  -  + ]:        166 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" ) ) ||
                 [ -  + ]
     189                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-excel.sheet.macroEnabled.main+xml" ) ) )
     190                 :          0 :         return CREATE_OUSTRING( "MS Excel 2007 XML" );
     191                 :            : 
     192   [ +  -  -  + ]:        166 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.spreadsheetml.template.main+xml" ) ) ||
                 [ -  + ]
     193                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-excel.template.macroEnabled.main+xml" ) ) )
     194                 :          0 :         return CREATE_OUSTRING( "MS Excel 2007 XML Template" );
     195                 :            : 
     196         [ -  + ]:         83 :     if ( rContentType == "application/vnd.ms-excel.sheet.binary.macroEnabled.main" )
     197                 :          0 :         return CREATE_OUSTRING( "MS Excel 2007 Binary" );
     198                 :            : 
     199   [ +  -  -  + ]:        166 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.presentationml.presentation.main+xml" ) ) ||
                 [ -  + ]
     200                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-powerpoint.presentation.macroEnabled.main+xml" ) ) )
     201                 :          0 :         return CREATE_OUSTRING( "MS PowerPoint 2007 XML" );
     202                 :            : 
     203   [ +  -  -  + ]:        166 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.presentationml.slideshow.main+xml" ) ) ||
                 [ -  + ]
     204                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-powerpoint.slideshow.macroEnabled.main+xml" ) ) )
     205                 :          0 :         return CREATE_OUSTRING( "MS PowerPoint 2007 XML AutoPlay" );
     206                 :            : 
     207   [ +  -  -  + ]:        166 :     if( rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.openxmlformats-officedocument.presentationml.template.main+xml" ) ) ||
                 [ -  + ]
     208                 :         83 :         rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "application/vnd.ms-powerpoint.template.macroEnabled.main+xml" ) ) )
     209                 :          0 :         return CREATE_OUSTRING( "MS PowerPoint 2007 XML Template" );
     210                 :            : 
     211                 :        274 :     return OUString();
     212                 :            : }
     213                 :            : 
     214                 :        178 : void FilterDetectDocHandler::parseContentTypesDefault( const AttributeList& rAttribs )
     215                 :            : {
     216                 :            :     // only if no overridden part name found
     217         [ +  - ]:        178 :     if( mrFilterName.isEmpty() )
     218                 :            :     {
     219                 :            :         // check if target path ends with extension
     220         [ +  - ]:        178 :         OUString aExtension = rAttribs.getString( XML_Extension, OUString() );
     221                 :        178 :         sal_Int32 nExtPos = maTargetPath.getLength() - aExtension.getLength();
     222 [ +  + ][ +  + ]:        178 :         if( (nExtPos > 0) && (maTargetPath[ nExtPos - 1 ] == '.') && maTargetPath.match( aExtension, nExtPos ) )
         [ +  + ][ +  - ]
     223 [ +  - ][ +  - ]:        178 :             mrFilterName = getFilterNameFromContentType( rAttribs.getString( XML_ContentType, OUString() ) );
     224                 :            :     }
     225                 :        178 : }
     226                 :            : 
     227                 :       1615 : void FilterDetectDocHandler::parseContentTypesOverride( const AttributeList& rAttribs )
     228                 :            : {
     229 [ +  - ][ +  + ]:       1615 :     if( rAttribs.getString( XML_PartName, OUString() ).equals( maTargetPath ) )
     230 [ +  - ][ +  - ]:        191 :         mrFilterName = getFilterNameFromContentType( rAttribs.getString( XML_ContentType, OUString() ) );
     231                 :       1615 : }
     232                 :            : 
     233                 :            : // ============================================================================
     234                 :            : 
     235                 :            : /* Helper for XServiceInfo */
     236                 :         17 : Sequence< OUString > FilterDetect_getSupportedServiceNames()
     237                 :            : {
     238                 :         17 :     Sequence< OUString > aServiceNames( 1 );
     239 [ +  - ][ +  - ]:         17 :     aServiceNames[ 0 ] = CREATE_OUSTRING( "com.sun.star.frame.ExtendedTypeDetection" );
     240                 :         17 :     return aServiceNames;
     241                 :            : }
     242                 :            : 
     243                 :            : /* Helper for XServiceInfo */
     244                 :         43 : OUString FilterDetect_getImplementationName()
     245                 :            : {
     246                 :         43 :     return CREATE_OUSTRING( "com.sun.star.comp.oox.FormatDetector" );
     247                 :            : }
     248                 :            : 
     249                 :            : /* Helper for registry */
     250                 :        210 : Reference< XInterface > SAL_CALL FilterDetect_createInstance( const Reference< XComponentContext >& rxContext ) throw( Exception )
     251                 :            : {
     252         [ +  - ]:        210 :     return static_cast< ::cppu::OWeakObject* >( new FilterDetect( rxContext ) );
     253                 :            : }
     254                 :            : 
     255                 :            : // ----------------------------------------------------------------------------
     256                 :            : 
     257                 :        515 : FilterDetect::FilterDetect( const Reference< XComponentContext >& rxContext ) throw( RuntimeException ) :
     258         [ +  - ]:        515 :     mxContext( rxContext, UNO_SET_THROW )
     259                 :            : {
     260                 :        515 : }
     261                 :            : 
     262                 :        515 : FilterDetect::~FilterDetect()
     263                 :            : {
     264         [ -  + ]:        725 : }
     265                 :            : 
     266                 :            : /* =========================================================================== */
     267                 :            : /*  Kudos to Caolan McNamara who provided the core decryption implementations. */
     268                 :            : /* =========================================================================== */
     269                 :            : 
     270                 :            : namespace {
     271                 :            : 
     272                 :            : const sal_uInt32 ENCRYPTINFO_CRYPTOAPI      = 0x00000004;
     273                 :            : const sal_uInt32 ENCRYPTINFO_DOCPROPS       = 0x00000008;
     274                 :            : const sal_uInt32 ENCRYPTINFO_EXTERNAL       = 0x00000010;
     275                 :            : const sal_uInt32 ENCRYPTINFO_AES            = 0x00000020;
     276                 :            : 
     277                 :            : const sal_uInt32 ENCRYPT_ALGO_AES128        = 0x0000660E;
     278                 :            : const sal_uInt32 ENCRYPT_ALGO_AES192        = 0x0000660F;
     279                 :            : const sal_uInt32 ENCRYPT_ALGO_AES256        = 0x00006610;
     280                 :            : const sal_uInt32 ENCRYPT_ALGO_RC4           = 0x00006801;
     281                 :            : 
     282                 :            : const sal_uInt32 ENCRYPT_HASH_SHA1          = 0x00008004;
     283                 :            : 
     284                 :            : // ----------------------------------------------------------------------------
     285                 :            : 
     286                 :        515 : bool lclIsZipPackage( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm )
     287                 :            : {
     288         [ +  - ]:        515 :     ZipStorage aZipStorage( rxContext, rxInStrm );
     289 [ +  - ][ +  - ]:        515 :     return aZipStorage.isStorage();
     290                 :            : }
     291                 :            : 
     292                 :            : // ----------------------------------------------------------------------------
     293                 :            : 
     294                 :            : struct PackageEncryptionInfo
     295                 :            : {
     296                 :            :     sal_uInt8           mpnSalt[ 16 ];
     297                 :            :     sal_uInt8           mpnEncrVerifier[ 16 ];
     298                 :            :     sal_uInt8           mpnEncrVerifierHash[ 32 ];
     299                 :            :     sal_uInt32          mnFlags;
     300                 :            :     sal_uInt32          mnAlgorithmId;
     301                 :            :     sal_uInt32          mnAlgorithmIdHash;
     302                 :            :     sal_uInt32          mnKeySize;
     303                 :            :     sal_uInt32          mnSaltSize;
     304                 :            :     sal_uInt32          mnVerifierHashSize;
     305                 :            : };
     306                 :            : 
     307                 :          0 : bool lclReadEncryptionInfo( PackageEncryptionInfo& rEncrInfo, BinaryInputStream& rStrm )
     308                 :            : {
     309         [ #  # ]:          0 :     rStrm.skip( 4 );
     310         [ #  # ]:          0 :     rStrm >> rEncrInfo.mnFlags;
     311         [ #  # ]:          0 :     if( getFlag( rEncrInfo.mnFlags, ENCRYPTINFO_EXTERNAL ) )
     312                 :          0 :         return false;
     313                 :            : 
     314                 :            :     sal_uInt32 nHeaderSize, nRepeatedFlags;
     315 [ #  # ][ #  # ]:          0 :     rStrm >> nHeaderSize >> nRepeatedFlags;
     316 [ #  # ][ #  # ]:          0 :     if( (nHeaderSize < 20) || (nRepeatedFlags != rEncrInfo.mnFlags) )
     317                 :          0 :         return false;
     318                 :            : 
     319         [ #  # ]:          0 :     rStrm.skip( 4 );
     320 [ #  # ][ #  # ]:          0 :     rStrm >> rEncrInfo.mnAlgorithmId >> rEncrInfo.mnAlgorithmIdHash >> rEncrInfo.mnKeySize;
                 [ #  # ]
     321         [ #  # ]:          0 :     rStrm.skip( nHeaderSize - 20 );
     322         [ #  # ]:          0 :     rStrm >> rEncrInfo.mnSaltSize;
     323         [ #  # ]:          0 :     if( rEncrInfo.mnSaltSize != 16 )
     324                 :          0 :         return false;
     325                 :            : 
     326         [ #  # ]:          0 :     rStrm.readMemory( rEncrInfo.mpnSalt, 16 );
     327         [ #  # ]:          0 :     rStrm.readMemory( rEncrInfo.mpnEncrVerifier, 16 );
     328         [ #  # ]:          0 :     rStrm >> rEncrInfo.mnVerifierHashSize;
     329         [ #  # ]:          0 :     rStrm.readMemory( rEncrInfo.mpnEncrVerifierHash, 32 );
     330                 :          0 :     return !rStrm.isEof();
     331                 :            : }
     332                 :            : 
     333                 :            : // ----------------------------------------------------------------------------
     334                 :            : 
     335                 :          0 : void lclDeriveKey( const sal_uInt8* pnHash, sal_uInt32 nHashLen, sal_uInt8* pnKeyDerived, sal_uInt32 nRequiredKeyLen )
     336                 :            : {
     337                 :            :     sal_uInt8 pnBuffer[ 64 ];
     338                 :          0 :     memset( pnBuffer, 0x36, sizeof( pnBuffer ) );
     339         [ #  # ]:          0 :     for( sal_uInt32 i = 0; i < nHashLen; ++i )
     340                 :          0 :         pnBuffer[ i ] ^= pnHash[ i ];
     341                 :            : 
     342                 :          0 :     rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
     343                 :          0 :     rtl_digest_update( aDigest, pnBuffer, sizeof( pnBuffer ) );
     344                 :            :     sal_uInt8 pnX1[ RTL_DIGEST_LENGTH_SHA1 ];
     345                 :          0 :     rtl_digest_get( aDigest, pnX1, RTL_DIGEST_LENGTH_SHA1 );
     346                 :          0 :     rtl_digest_destroy( aDigest );
     347                 :            : 
     348                 :          0 :     memset( pnBuffer, 0x5C, sizeof( pnBuffer ) );
     349         [ #  # ]:          0 :     for( sal_uInt32 i = 0; i < nHashLen; ++i )
     350                 :          0 :         pnBuffer[ i ] ^= pnHash[ i ];
     351                 :            : 
     352                 :          0 :     aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
     353                 :          0 :     rtl_digest_update( aDigest, pnBuffer, sizeof( pnBuffer ) );
     354                 :            :     sal_uInt8 pnX2[ RTL_DIGEST_LENGTH_SHA1 ];
     355                 :          0 :     rtl_digest_get( aDigest, pnX2, RTL_DIGEST_LENGTH_SHA1 );
     356                 :          0 :     rtl_digest_destroy( aDigest );
     357                 :            : 
     358         [ #  # ]:          0 :     if( nRequiredKeyLen > RTL_DIGEST_LENGTH_SHA1 )
     359                 :            :     {
     360                 :          0 :         memcpy( pnKeyDerived + RTL_DIGEST_LENGTH_SHA1, pnX2, nRequiredKeyLen - RTL_DIGEST_LENGTH_SHA1 );
     361                 :          0 :         nRequiredKeyLen = RTL_DIGEST_LENGTH_SHA1;
     362                 :            :     }
     363                 :          0 :     memcpy( pnKeyDerived, pnX1, nRequiredKeyLen );
     364                 :          0 : }
     365                 :            : 
     366                 :            : // ----------------------------------------------------------------------------
     367                 :            : 
     368                 :          0 : bool lclCheckEncryptionData( const sal_uInt8* pnKey, sal_uInt32 nKeySize, const sal_uInt8* pnVerifier, sal_uInt32 nVerifierSize, const sal_uInt8* pnVerifierHash, sal_uInt32 nVerifierHashSize )
     369                 :            : {
     370                 :          0 :     bool bResult = false;
     371                 :            : 
     372                 :            :     // the only currently supported algorithm needs key size 128
     373 [ #  # ][ #  # ]:          0 :     if ( nKeySize == 16 && nVerifierSize == 16 && nVerifierHashSize == 32 )
                 [ #  # ]
     374                 :            :     {
     375                 :            :         // check password
     376                 :            :         EVP_CIPHER_CTX aes_ctx;
     377         [ #  # ]:          0 :         EVP_CIPHER_CTX_init( &aes_ctx );
     378 [ #  # ][ #  # ]:          0 :         EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
     379         [ #  # ]:          0 :         EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
     380                 :          0 :         int nOutLen = 0;
     381                 :            :         sal_uInt8 pnTmpVerifier[ 16 ];
     382                 :          0 :         (void) memset( pnTmpVerifier, 0, sizeof(pnTmpVerifier) );
     383                 :            : 
     384         [ #  # ]:          0 :         /*int*/ EVP_DecryptUpdate( &aes_ctx, pnTmpVerifier, &nOutLen, pnVerifier, nVerifierSize );
     385         [ #  # ]:          0 :         EVP_CIPHER_CTX_cleanup( &aes_ctx );
     386                 :            : 
     387         [ #  # ]:          0 :         EVP_CIPHER_CTX_init( &aes_ctx );
     388 [ #  # ][ #  # ]:          0 :         EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, pnKey, 0 );
     389         [ #  # ]:          0 :         EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
     390                 :            :         sal_uInt8 pnTmpVerifierHash[ 32 ];
     391                 :          0 :         (void) memset( pnTmpVerifierHash, 0, sizeof(pnTmpVerifierHash) );
     392                 :            : 
     393         [ #  # ]:          0 :         /*int*/ EVP_DecryptUpdate( &aes_ctx, pnTmpVerifierHash, &nOutLen, pnVerifierHash, nVerifierHashSize );
     394         [ #  # ]:          0 :         EVP_CIPHER_CTX_cleanup( &aes_ctx );
     395                 :            : 
     396                 :          0 :         rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
     397                 :          0 :         rtl_digest_update( aDigest, pnTmpVerifier, sizeof( pnTmpVerifier ) );
     398                 :            :         sal_uInt8 pnSha1Hash[ RTL_DIGEST_LENGTH_SHA1 ];
     399                 :          0 :         rtl_digest_get( aDigest, pnSha1Hash, RTL_DIGEST_LENGTH_SHA1 );
     400                 :          0 :         rtl_digest_destroy( aDigest );
     401                 :            : 
     402                 :          0 :         bResult = ( memcmp( pnSha1Hash, pnTmpVerifierHash, RTL_DIGEST_LENGTH_SHA1 ) == 0 );
     403                 :            :     }
     404                 :            : 
     405                 :          0 :     return bResult;
     406                 :            : }
     407                 :            : 
     408                 :            : // ----------------------------------------------------------------------------
     409                 :            : 
     410                 :          0 : Sequence< NamedValue > lclGenerateEncryptionKey( const PackageEncryptionInfo& rEncrInfo, const OUString& rPassword, sal_uInt8* pnKey, sal_uInt32 nRequiredKeyLen )
     411                 :            : {
     412                 :          0 :     size_t nBufferSize = rEncrInfo.mnSaltSize + 2 * rPassword.getLength();
     413                 :          0 :     sal_uInt8* pnBuffer = new sal_uInt8[ nBufferSize ];
     414                 :          0 :     memcpy( pnBuffer, rEncrInfo.mpnSalt, rEncrInfo.mnSaltSize );
     415                 :            : 
     416                 :          0 :     sal_uInt8* pnPasswordLoc = pnBuffer + rEncrInfo.mnSaltSize;
     417                 :          0 :     const sal_Unicode* pStr = rPassword.getStr();
     418         [ #  # ]:          0 :     for( sal_Int32 i = 0, nLen = rPassword.getLength(); i < nLen; ++i, ++pStr, pnPasswordLoc += 2 )
     419                 :          0 :         ByteOrderConverter::writeLittleEndian( pnPasswordLoc, static_cast< sal_uInt16 >( *pStr ) );
     420                 :            : 
     421                 :          0 :     rtlDigest aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
     422                 :          0 :     rtl_digest_update( aDigest, pnBuffer, nBufferSize );
     423         [ #  # ]:          0 :     delete[] pnBuffer;
     424                 :            : 
     425                 :          0 :     size_t nHashSize = RTL_DIGEST_LENGTH_SHA1 + 4;
     426                 :          0 :     sal_uInt8* pnHash = new sal_uInt8[ nHashSize ];
     427                 :          0 :     rtl_digest_get( aDigest, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
     428                 :          0 :     rtl_digest_destroy( aDigest );
     429                 :            : 
     430         [ #  # ]:          0 :     for( sal_uInt32 i = 0; i < 50000; ++i )
     431                 :            :     {
     432                 :          0 :         ByteOrderConverter::writeLittleEndian( pnHash, i );
     433                 :          0 :         aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
     434                 :          0 :         rtl_digest_update( aDigest, pnHash, nHashSize );
     435                 :          0 :         rtl_digest_get( aDigest, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
     436                 :          0 :         rtl_digest_destroy( aDigest );
     437                 :            :     }
     438                 :            : 
     439                 :          0 :     memmove( pnHash, pnHash + 4, RTL_DIGEST_LENGTH_SHA1 );
     440                 :          0 :     memset( pnHash + RTL_DIGEST_LENGTH_SHA1, 0, 4 );
     441                 :          0 :     aDigest = rtl_digest_create( rtl_Digest_AlgorithmSHA1 );
     442                 :          0 :     rtl_digest_update( aDigest, pnHash, nHashSize );
     443                 :          0 :     rtl_digest_get( aDigest, pnHash, RTL_DIGEST_LENGTH_SHA1 );
     444                 :          0 :     rtl_digest_destroy( aDigest );
     445                 :            : 
     446                 :          0 :     lclDeriveKey( pnHash, RTL_DIGEST_LENGTH_SHA1, pnKey, nRequiredKeyLen );
     447         [ #  # ]:          0 :     delete[] pnHash;
     448                 :            : 
     449                 :          0 :     Sequence< NamedValue > aResult;
     450 [ #  # ][ #  # ]:          0 :     if( lclCheckEncryptionData( pnKey, nRequiredKeyLen, rEncrInfo.mpnEncrVerifier, sizeof( rEncrInfo.mpnEncrVerifier ), rEncrInfo.mpnEncrVerifierHash, sizeof( rEncrInfo.mpnEncrVerifierHash ) ) )
     451                 :            :     {
     452         [ #  # ]:          0 :         SequenceAsHashMap aEncryptionData;
     453 [ #  # ][ #  # ]:          0 :         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionKey" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( pnKey ), nRequiredKeyLen );
         [ #  # ][ #  # ]
                 [ #  # ]
     454 [ #  # ][ #  # ]:          0 :         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionSalt" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( rEncrInfo.mpnSalt ), rEncrInfo.mnSaltSize );
         [ #  # ][ #  # ]
                 [ #  # ]
     455 [ #  # ][ #  # ]:          0 :         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionVerifier" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( rEncrInfo.mpnEncrVerifier ), sizeof( rEncrInfo.mpnEncrVerifier ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     456 [ #  # ][ #  # ]:          0 :         aEncryptionData[ CREATE_OUSTRING( "AES128EncryptionVerifierHash" ) ] <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( rEncrInfo.mpnEncrVerifierHash ), sizeof( rEncrInfo.mpnEncrVerifierHash ) );
         [ #  # ][ #  # ]
                 [ #  # ]
     457 [ #  # ][ #  # ]:          0 :         aResult = aEncryptionData.getAsConstNamedValueList();
         [ #  # ][ #  # ]
     458                 :            :     }
     459                 :            : 
     460                 :          0 :     return aResult;
     461                 :            : }
     462                 :            : 
     463                 :            : // the password verifier ------------------------------------------------------
     464                 :            : 
     465         [ #  # ]:          0 : class PasswordVerifier : public ::comphelper::IDocPasswordVerifier
     466                 :            : {
     467                 :            : public:
     468                 :            :     explicit            PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo );
     469                 :            : 
     470                 :            :     virtual ::comphelper::DocPasswordVerifierResult
     471                 :            :                         verifyPassword( const OUString& rPassword, Sequence< NamedValue >& o_rEncryptionData );
     472                 :            :     virtual ::comphelper::DocPasswordVerifierResult
     473                 :            :                         verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData );
     474                 :            : 
     475                 :          0 :     inline const sal_uInt8* getKey() const { return &maKey.front(); }
     476                 :            : 
     477                 :            : private:
     478                 :            :     const PackageEncryptionInfo& mrEncryptInfo;
     479                 :            :     ::std::vector< sal_uInt8 > maKey;
     480                 :            : };
     481                 :            : 
     482                 :          0 : PasswordVerifier::PasswordVerifier( const PackageEncryptionInfo& rEncryptInfo ) :
     483                 :            :     mrEncryptInfo( rEncryptInfo ),
     484         [ #  # ]:          0 :     maKey( static_cast< size_t >( rEncryptInfo.mnKeySize / 8 ), 0 )
     485                 :            : {
     486                 :          0 : }
     487                 :            : 
     488                 :          0 : ::comphelper::DocPasswordVerifierResult PasswordVerifier::verifyPassword( const OUString& rPassword, Sequence< NamedValue >& o_rEncryptionData )
     489                 :            : {
     490                 :            :     // verifies the password and writes the related decryption key into maKey
     491         [ #  # ]:          0 :     o_rEncryptionData = lclGenerateEncryptionKey( mrEncryptInfo, rPassword, &maKey.front(), maKey.size() );
     492                 :          0 :     return o_rEncryptionData.hasElements() ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
     493                 :            : }
     494                 :            : 
     495                 :          0 : ::comphelper::DocPasswordVerifierResult PasswordVerifier::verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData )
     496                 :            : {
     497         [ #  # ]:          0 :     SequenceAsHashMap aHashData( rEncryptionData );
     498 [ #  # ][ #  # ]:          0 :     Sequence< sal_Int8 > aKey = aHashData.getUnpackedValueOrDefault( CREATE_OUSTRING( "AES128EncryptionKey" ), Sequence< sal_Int8 >() );
         [ #  # ][ #  # ]
     499 [ #  # ][ #  # ]:          0 :     Sequence< sal_Int8 > aVerifier = aHashData.getUnpackedValueOrDefault( CREATE_OUSTRING( "AES128EncryptionVerifier" ), Sequence< sal_Int8 >() );
         [ #  # ][ #  # ]
     500 [ #  # ][ #  # ]:          0 :     Sequence< sal_Int8 > aVerifierHash = aHashData.getUnpackedValueOrDefault( CREATE_OUSTRING( "AES128EncryptionVerifierHash" ), Sequence< sal_Int8 >() );
         [ #  # ][ #  # ]
     501                 :            : 
     502                 :            :     bool bResult = lclCheckEncryptionData(
     503                 :          0 :         reinterpret_cast< const sal_uInt8* >( aKey.getConstArray() ), aKey.getLength(),
     504                 :          0 :         reinterpret_cast< const sal_uInt8* >( aVerifier.getConstArray() ), aVerifier.getLength(),
     505         [ #  # ]:          0 :         reinterpret_cast< const sal_uInt8* >( aVerifierHash.getConstArray() ), aVerifierHash.getLength() );
     506                 :            : 
     507 [ #  # ][ #  # ]:          0 :     return bResult ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
         [ #  # ][ #  # ]
                 [ #  # ]
     508                 :            : }
     509                 :            : 
     510                 :            : } // namespace
     511                 :            : 
     512                 :            : // ----------------------------------------------------------------------------
     513                 :            : 
     514                 :        515 : Reference< XInputStream > FilterDetect::extractUnencryptedPackage( MediaDescriptor& rMediaDesc ) const
     515                 :            : {
     516                 :            :     // try the plain input stream
     517 [ +  - ][ +  - ]:        515 :     Reference< XInputStream > xInStrm( rMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ], UNO_QUERY );
                 [ +  - ]
     518 [ +  - ][ +  - ]:        515 :     if( !xInStrm.is() || lclIsZipPackage( mxContext, xInStrm ) )
         [ +  - ][ +  - ]
     519                 :        515 :         return xInStrm;
     520                 :            : 
     521                 :            :     // check if a temporary file is passed in the 'ComponentData' property
     522 [ #  # ][ #  # ]:          0 :     Reference< XStream > xDecrypted( rMediaDesc.getComponentDataEntry( CREATE_OUSTRING( "DecryptedPackage" ) ), UNO_QUERY );
                 [ #  # ]
     523         [ #  # ]:          0 :     if( xDecrypted.is() )
     524                 :            :     {
     525 [ #  # ][ #  # ]:          0 :         Reference< XInputStream > xDecrInStrm = xDecrypted->getInputStream();
     526 [ #  # ][ #  # ]:          0 :         if( lclIsZipPackage( mxContext, xDecrInStrm ) )
     527         [ #  # ]:          0 :             return xDecrInStrm;
     528                 :            :     }
     529                 :            : 
     530                 :            :     // try to decrypt an encrypted OLE package
     531         [ #  # ]:          0 :     ::oox::ole::OleStorage aOleStorage( mxContext, xInStrm, false );
     532 [ #  # ][ #  # ]:          0 :     if( aOleStorage.isStorage() ) try
     533                 :            :     {
     534                 :            :         // open the required input streams in the encrypted package
     535 [ #  # ][ #  # ]:          0 :         Reference< XInputStream > xEncryptionInfo( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptionInfo" ) ), UNO_SET_THROW );
                 [ #  # ]
     536 [ #  # ][ #  # ]:          0 :         Reference< XInputStream > xEncryptedPackage( aOleStorage.openInputStream( CREATE_OUSTRING( "EncryptedPackage" ) ), UNO_SET_THROW );
                 [ #  # ]
     537                 :            : 
     538                 :            :         // read the encryption info stream
     539                 :            :         PackageEncryptionInfo aEncryptInfo;
     540         [ #  # ]:          0 :         BinaryXInputStream aInfoStrm( xEncryptionInfo, true );
     541         [ #  # ]:          0 :         bool bValidInfo = lclReadEncryptionInfo( aEncryptInfo, aInfoStrm );
     542                 :            : 
     543                 :            :         // check flags and algorithm IDs, required are AES128 and SHA-1
     544                 :            :         bool bImplemented = bValidInfo &&
     545                 :          0 :             getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_CRYPTOAPI ) &&
     546                 :          0 :             getFlag( aEncryptInfo.mnFlags, ENCRYPTINFO_AES ) &&
     547                 :            :             // algorithm ID 0 defaults to AES128 too, if ENCRYPTINFO_AES flag is set
     548                 :            :             ((aEncryptInfo.mnAlgorithmId == 0) || (aEncryptInfo.mnAlgorithmId == ENCRYPT_ALGO_AES128)) &&
     549                 :            :             // hash algorithm ID 0 defaults to SHA-1 too
     550                 :            :             ((aEncryptInfo.mnAlgorithmIdHash == 0) || (aEncryptInfo.mnAlgorithmIdHash == ENCRYPT_HASH_SHA1)) &&
     551   [ #  #  #  #  :          0 :             (aEncryptInfo.mnVerifierHashSize == 20);
           #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     552                 :            : 
     553         [ #  # ]:          0 :         if( bImplemented )
     554                 :            :         {
     555                 :            :             /*  "VelvetSweatshop" is the built-in default encryption
     556                 :            :                 password used by MS Excel for the "workbook protection"
     557                 :            :                 feature with password. Try this first before prompting the
     558                 :            :                 user for a password. */
     559         [ #  # ]:          0 :             ::std::vector< OUString > aDefaultPasswords;
     560 [ #  # ][ #  # ]:          0 :             aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) );
     561                 :            : 
     562                 :            :             /*  Use the comphelper password helper to request a password.
     563                 :            :                 This helper returns either with the correct password
     564                 :            :                 (according to the verifier), or with an empty string if
     565                 :            :                 user has cancelled the password input dialog. */
     566         [ #  # ]:          0 :             PasswordVerifier aVerifier( aEncryptInfo );
     567                 :            :             Sequence< NamedValue > aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword(
     568         [ #  # ]:          0 :                 aVerifier, rMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords );
     569                 :            : 
     570         [ #  # ]:          0 :             if( aEncryptionData.getLength() == 0 )
     571                 :            :             {
     572 [ #  # ][ #  # ]:          0 :                 rMediaDesc[ MediaDescriptor::PROP_ABORTED() ] <<= true;
                 [ #  # ]
     573                 :            :             }
     574                 :            :             else
     575                 :            :             {
     576                 :            :                 // create temporary file for unencrypted package
     577 [ #  # ][ #  # ]:          0 :                 Reference< XMultiServiceFactory > xFactory( mxContext->getServiceManager(), UNO_QUERY_THROW );
                 [ #  # ]
     578 [ #  # ][ #  # ]:          0 :                 Reference< XStream > xTempFile( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TempFile" ) ), UNO_QUERY_THROW );
         [ #  # ][ #  # ]
     579 [ #  # ][ #  # ]:          0 :                 Reference< XOutputStream > xDecryptedPackage( xTempFile->getOutputStream(), UNO_SET_THROW );
                 [ #  # ]
     580         [ #  # ]:          0 :                 BinaryXOutputStream aDecryptedPackage( xDecryptedPackage, true );
     581         [ #  # ]:          0 :                 BinaryXInputStream aEncryptedPackage( xEncryptedPackage, true );
     582                 :            : 
     583                 :            :                 EVP_CIPHER_CTX aes_ctx;
     584         [ #  # ]:          0 :                 EVP_CIPHER_CTX_init( &aes_ctx );
     585 [ #  # ][ #  # ]:          0 :                 EVP_DecryptInit_ex( &aes_ctx, EVP_aes_128_ecb(), 0, aVerifier.getKey(), 0 );
                 [ #  # ]
     586         [ #  # ]:          0 :                 EVP_CIPHER_CTX_set_padding( &aes_ctx, 0 );
     587                 :            : 
     588                 :            :                 sal_uInt8 pnInBuffer[ 1024 ];
     589                 :            :                 sal_uInt8 pnOutBuffer[ 1024 ];
     590                 :            :                 sal_Int32 nInLen;
     591                 :            :                 int nOutLen;
     592         [ #  # ]:          0 :                 aEncryptedPackage.skip( 8 ); // decrypted size
     593 [ #  # ][ #  # ]:          0 :                 while( (nInLen = aEncryptedPackage.readMemory( pnInBuffer, sizeof( pnInBuffer ) )) > 0 )
     594                 :            :                 {
     595         [ #  # ]:          0 :                     EVP_DecryptUpdate( &aes_ctx, pnOutBuffer, &nOutLen, pnInBuffer, nInLen );
     596         [ #  # ]:          0 :                     aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
     597                 :            :                 }
     598         [ #  # ]:          0 :                 EVP_DecryptFinal_ex( &aes_ctx, pnOutBuffer, &nOutLen );
     599         [ #  # ]:          0 :                 aDecryptedPackage.writeMemory( pnOutBuffer, nOutLen );
     600                 :            : 
     601         [ #  # ]:          0 :                 EVP_CIPHER_CTX_cleanup( &aes_ctx );
     602 [ #  # ][ #  # ]:          0 :                 xDecryptedPackage->flush();
     603         [ #  # ]:          0 :                 aDecryptedPackage.seekToStart();
     604                 :            : 
     605                 :            :                 // store temp file in media descriptor to keep it alive
     606 [ #  # ][ #  # ]:          0 :                 rMediaDesc.setComponentDataEntry( CREATE_OUSTRING( "DecryptedPackage" ), Any( xTempFile ) );
                 [ #  # ]
     607                 :            : 
     608 [ #  # ][ #  # ]:          0 :                 Reference< XInputStream > xDecrInStrm = xTempFile->getInputStream();
     609 [ #  # ][ #  # ]:          0 :                 if( lclIsZipPackage( mxContext, xDecrInStrm ) )
     610 [ #  # ][ #  # ]:          0 :                     return xDecrInStrm;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     611 [ #  # ][ #  # ]:          0 :             }
         [ #  # ][ #  # ]
                 [ #  # ]
     612 [ #  # ][ #  # ]:          0 :         }
         [ #  # ][ #  # ]
                 [ #  # ]
     613                 :            :     }
     614         [ #  # ]:          0 :     catch( const Exception& )
     615                 :            :     {
     616                 :            :     }
     617                 :            : 
     618         [ #  # ]:        515 :     return Reference< XInputStream >();
     619                 :            : }
     620                 :            : 
     621                 :            : // com.sun.star.lang.XServiceInfo interface -----------------------------------
     622                 :            : 
     623                 :          0 : OUString SAL_CALL FilterDetect::getImplementationName() throw( RuntimeException )
     624                 :            : {
     625                 :          0 :     return FilterDetect_getImplementationName();
     626                 :            : }
     627                 :            : 
     628                 :          0 : sal_Bool SAL_CALL FilterDetect::supportsService( const OUString& rServiceName ) throw( RuntimeException )
     629                 :            : {
     630         [ #  # ]:          0 :     const Sequence< OUString > aServices = FilterDetect_getSupportedServiceNames();
     631                 :          0 :     const OUString* pArray = aServices.getConstArray();
     632                 :          0 :     const OUString* pArrayEnd = pArray + aServices.getLength();
     633 [ #  # ][ #  # ]:          0 :     return ::std::find( pArray, pArrayEnd, rServiceName ) != pArrayEnd;
     634                 :            : }
     635                 :            : 
     636                 :          0 : Sequence< OUString > SAL_CALL FilterDetect::getSupportedServiceNames() throw( RuntimeException )
     637                 :            : {
     638                 :          0 :     return FilterDetect_getSupportedServiceNames();
     639                 :            : }
     640                 :            : 
     641                 :            : // com.sun.star.document.XExtendedFilterDetection interface -------------------
     642                 :            : 
     643                 :        210 : OUString SAL_CALL FilterDetect::detect( Sequence< PropertyValue >& rMediaDescSeq ) throw( RuntimeException )
     644                 :            : {
     645                 :        210 :     OUString aFilterName;
     646         [ +  - ]:        210 :     MediaDescriptor aMediaDesc( rMediaDescSeq );
     647                 :            : 
     648                 :            :     /*  Check that the user has not choosen to abort detection, e.g. by hitting
     649                 :            :         'Cancel' in the password input dialog. This may happen because this
     650                 :            :         filter detection is used by different filters. */
     651 [ +  - ][ +  - ]:        210 :     bool bAborted = aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_ABORTED(), false );
     652         [ +  - ]:        210 :     if( !bAborted ) try
     653                 :            :     {
     654         [ +  - ]:        210 :         aMediaDesc.addInputStream();
     655                 :            : 
     656                 :            :         /*  Get the unencrypted input stream. This may include creation of a
     657                 :            :             temporary file that contains the decrypted package. This temporary
     658                 :            :             file will be stored in the 'ComponentData' property of the media
     659                 :            :             descriptor. */
     660 [ +  - ][ +  - ]:        210 :         Reference< XInputStream > xInStrm( extractUnencryptedPackage( aMediaDesc ), UNO_SET_THROW );
     661                 :            : 
     662                 :            :         // stream must be a ZIP package
     663         [ +  - ]:        210 :         ZipStorage aZipStorage( mxContext, xInStrm );
     664 [ +  - ][ +  - ]:        210 :         if( aZipStorage.isStorage() )
     665                 :            :         {
     666                 :            :             // create the fast parser, register the XML namespaces, set document handler
     667         [ +  - ]:        210 :             FastParser aParser( mxContext );
     668         [ +  - ]:        210 :             aParser.registerNamespace( NMSP_packageRel );
     669         [ +  - ]:        210 :             aParser.registerNamespace( NMSP_officeRel );
     670         [ +  - ]:        210 :             aParser.registerNamespace( NMSP_packageContentTypes );
     671 [ +  - ][ +  - ]:        210 :             aParser.setDocumentHandler( new FilterDetectDocHandler( mxContext, aFilterName ) );
         [ +  - ][ +  - ]
     672                 :            : 
     673                 :            :             /*  Parse '_rels/.rels' to get the target path and '[Content_Types].xml'
     674                 :            :                 to determine the content type of the part at the target path. */
     675 [ +  + ][ +  - ]:        210 :             aParser.parseStream( aZipStorage, CREATE_OUSTRING( "_rels/.rels" ) );
     676 [ +  - ][ +  - ]:        210 :             aParser.parseStream( aZipStorage, CREATE_OUSTRING( "[Content_Types].xml" ) );
                 [ +  - ]
     677 [ +  - ][ -  + ]:        210 :         }
     678                 :            :     }
     679         [ +  - ]:         19 :     catch( const Exception& )
     680                 :            :     {
     681                 :            :     }
     682                 :            : 
     683                 :            :     // write back changed media descriptor members
     684         [ +  - ]:        210 :     aMediaDesc >> rMediaDescSeq;
     685         [ +  - ]:        210 :     return aFilterName;
     686                 :            : }
     687                 :            : 
     688                 :            : // ============================================================================
     689                 :            : 
     690                 :            : } // namespace core
     691 [ +  - ][ +  - ]:        285 : } // namespace oox
     692                 :            : 
     693                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10